[U-Boot] [PATCH v2 6/6] clk: add device tree support for clock framework
Masahiro Yamada
yamada.masahiro at socionext.com
Wed Jan 13 05:16:13 CET 2016
Add device tree binding support for the clock uclass. This allows
clock consumers to get the peripheral ID based on the "clocks"
property in the device tree.
Usage:
Assume the following device tree:
clk: myclock {
compatible = "myclocktype";
#clock-cells = <1>;
};
uart {
compatible = "myuart";
clocks = <&clk 3>;
};
i2c {
compatible = "myi2c";
clocks = <&clk 5>;
};
In this example, the UART, I2C driver can get the peripheral ID 3, 5,
respectively by calling fdt_clk_get().
By default, fdt_clk_get() returns the value of the first cell, or
zero if #clock-cells == <0>. This should work for most of the cases,
but you can still override this behavior by implementing .fdt_xlate
callback in your driver.
Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
---
Changes in v2:
- Change the arguments of fdt_clk_get() as Simon mentioned
- rename .get_id() to .fdt_xlate(), which seems a more suitable name
drivers/clk/clk-uclass.c | 33 +++++++++++++++++++++++++++++++++
include/clk.h | 29 +++++++++++++++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index ac3909d..81ef526 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -62,6 +62,39 @@ long clk_set_periph_rate(struct udevice *dev, int periph, ulong rate)
return ops->set_periph_rate(dev, periph, rate);
}
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+int fdt_clk_get(struct udevice *dev, int index, struct udevice **clkdevp)
+{
+ DECLARE_GLOBAL_DATA_PTR;
+ struct fdtdec_phandle_args clkspec;
+ struct clk_ops *ops;
+ struct udevice *clkdev;
+ int rc;
+
+ rc = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
+ "clocks", "#clock-cells", 0, index,
+ &clkspec);
+ if (rc)
+ return rc;
+
+ rc = uclass_get_device_by_of_offset(UCLASS_CLK, clkspec.node, &clkdev);
+ if (rc)
+ return rc;
+
+ ops = clk_get_ops(clkdev);
+
+ if (ops->fdt_xlate)
+ rc = ops->fdt_xlate(clkdev, &clkspec);
+ else
+ rc = clkspec.args_count > 0 ? clkspec.args[0] : 0;
+
+ if (clkdevp)
+ *clkdevp = clkdev;
+
+ return rc;
+}
+#endif
+
UCLASS_DRIVER(clk) = {
.id = UCLASS_CLK,
.name = "clk",
diff --git a/include/clk.h b/include/clk.h
index de15999..3f95395 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -10,6 +10,7 @@
#include <linux/types.h>
+struct fdtdec_phandle_args;
struct udevice;
int soc_clk_dump(void);
@@ -58,6 +59,16 @@ struct clk_ops {
* @return new clock rate in Hz, or -ve error code
*/
long (*set_periph_rate)(struct udevice *dev, int periph, ulong rate);
+
+ /**
+ * fdt_xlate() - translate DT arguments into peripheral ID
+ *
+ * @dev: clock provider
+ * @clkspec: arguments taken from the device tree
+ * @return peripheral ID, or -ve error code
+ */
+ int (*fdt_xlate)(struct udevice *dev,
+ struct fdtdec_phandle_args *clkspec);
};
#define clk_get_ops(dev) ((struct clk_ops *)(dev)->driver->ops)
@@ -105,4 +116,22 @@ long clk_get_periph_rate(struct udevice *dev, int periph);
*/
long clk_set_periph_rate(struct udevice *dev, int periph, ulong rate);
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+/**
+ * fdt_clk_get() - Get peripheral ID from device tree
+ *
+ * @dev: Peripheral device
+ * @index: index of a phandle to parse out in "clocks" property
+ * @clkdevp: if not NULL, filled with pointer of clock provider
+ * @return peripheral ID, or -ve error code
+ */
+int fdt_clk_get(struct udevice *dev, int index, struct udevice **clkdevp);
+#else
+static inline int fdt_clk_get(struct udevice *dev, int index,
+ struct udevice **clkdevp);
+{
+ return -ENOSYS;
+}
+#endif
+
#endif /* _CLK_H_ */
--
1.9.1
More information about the U-Boot
mailing list