clk: at91: Improve the clock implementation
For the peripheral clock, provide the clock ops for the clock
provider, such as spi0_clk. The .of_xlate is to get the clk->id,
the .enable is to enable the spi0 peripheral clock, the .get_rate
is to get the clock frequency.
The driver for periph32ck node is responsible for recursively
binding its children as clk devices, not provide the clock ops.
So do the generated clock and system clock.
Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
Acked-by: Stephen Warren <swarren@nvidia.com>
diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 76ff387..76ba91a 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -25,6 +25,8 @@
.of_match = at91_pmc_match,
};
+/*---------------------------------------------------------*/
+
int at91_pmc_core_probe(struct udevice *dev)
{
struct pmc_platdata *plat = dev_get_platdata(dev);
@@ -36,21 +38,41 @@
return 0;
}
-int at91_pmc_clk_node_bind(struct udevice *dev)
+/**
+ * at91_clk_sub_device_bind() - for the at91 clock driver
+ * Recursively bind its children as clk devices.
+ *
+ * @return: 0 on success, or negative error code on failure
+ */
+int at91_clk_sub_device_bind(struct udevice *dev, const char *drv_name)
{
const void *fdt = gd->fdt_blob;
int offset = dev->of_offset;
+ bool pre_reloc_only = !(gd->flags & GD_FLG_RELOC);
const char *name;
int ret;
for (offset = fdt_first_subnode(fdt, offset);
offset > 0;
offset = fdt_next_subnode(fdt, offset)) {
+ if (pre_reloc_only &&
+ !fdt_getprop(fdt, offset, "u-boot,dm-pre-reloc", NULL))
+ continue;
+ /*
+ * If this node has "compatible" property, this is not
+ * a clock sub-node, but a normal device. skip.
+ */
+ fdt_get_property(fdt, offset, "compatible", &ret);
+ if (ret >= 0)
+ continue;
+
+ if (ret != -FDT_ERR_NOTFOUND)
+ return ret;
+
name = fdt_get_name(fdt, offset, NULL);
if (!name)
return -EINVAL;
-
- ret = device_bind_driver_to_node(dev, "clk", name,
+ ret = device_bind_driver_to_node(dev, drv_name, name,
offset, NULL);
if (ret)
return ret;
@@ -59,7 +81,33 @@
return 0;
}
-U_BOOT_DRIVER(clk_generic) = {
- .id = UCLASS_CLK,
- .name = "clk",
-};
+int at91_clk_of_xlate(struct clk *clk, struct fdtdec_phandle_args *args)
+{
+ int periph;
+
+ if (args->args_count) {
+ debug("Invalid args_count: %d\n", args->args_count);
+ return -EINVAL;
+ }
+
+ periph = fdtdec_get_uint(gd->fdt_blob, clk->dev->of_offset, "reg", -1);
+ if (periph < 0)
+ return -EINVAL;
+
+ clk->id = periph;
+
+ return 0;
+}
+
+int at91_clk_probe(struct udevice *dev)
+{
+ struct udevice *dev_periph_container, *dev_pmc;
+ struct pmc_platdata *plat = dev_get_platdata(dev);
+
+ dev_periph_container = dev_get_parent(dev);
+ dev_pmc = dev_get_parent(dev_periph_container);
+
+ plat->reg_base = (struct at91_pmc *)dev_get_addr_ptr(dev_pmc);
+
+ return 0;
+}