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.masah...@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

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to