diff mbox

[U-Boot,01/50] dm: clk: Add support for decoding clocks from the device tree

Message ID 1452727540-3249-2-git-send-email-sjg@chromium.org
State Superseded
Delegated to: Simon Glass
Headers show

Commit Message

Simon Glass Jan. 13, 2016, 11:24 p.m. UTC
Add a method which can locate a clock for a device, given its index. This
uses the normal device tree bindings to return the clock device and the
first argument which is normally used as a peripheral ID in U-Boot.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/clk/clk-uclass.c | 28 ++++++++++++++++++++++++++++
 include/clk.h            | 15 +++++++++++++++
 2 files changed, 43 insertions(+)

Comments

Masahiro Yamada Jan. 14, 2016, 10:11 a.m. UTC | #1
Hi Simon,



> @@ -12,6 +12,8 @@
>  #include <dm/lists.h>
>  #include <dm/root.h>
>
> +DECLARE_GLOBAL_DATA_PTR;
> +
>  ulong clk_get_rate(struct udevice *dev)
>  {
>         struct clk_ops *ops = clk_get_ops(dev);
> @@ -62,6 +64,32 @@ int clk_get_id(struct udevice *dev, int args_count, uint32_t *args)
>         return ops->get_id(dev, args_count, args);
>  }
>
> +int clk_get_by_index(struct udevice *dev, int index, struct udevice **clk_devp,
> +                    int *periphp)


This function causes NULL pointer access
if called with clk_devp == NULL.


You can decrease the number of arguments
if this function returns periph ID.


> +{
> +       struct fdtdec_phandle_args args;
> +       int ret;
> +
> +       ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
> +                                            "clocks", "#clock-cells", 0, index,
> +                                            &args);
> +       if (ret) {
> +               debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
> +                     __func__, ret);
> +               return ret;
> +       }
> +
> +       ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, clk_devp);
> +       if (ret) {
> +               debug("%s: uclass_get_device_by_of_offset failed: err=%d\n",
> +                     __func__, ret);
> +               return ret;
> +       }
> +       *periphp = args.args_count > 0 ? args.args[0] : -1;


Do you want to let this function fail against #clock-cells == 0?



This code should be compiled only when OF_CONTROL is on.
Simon Glass Jan. 15, 2016, 1:21 p.m. UTC | #2
Hi Masahiro,

On 14 January 2016 at 03:11, Masahiro Yamada
<yamada.masahiro@socionext.com> wrote:
> Hi Simon,
>
>
>
>> @@ -12,6 +12,8 @@
>>  #include <dm/lists.h>
>>  #include <dm/root.h>
>>
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>>  ulong clk_get_rate(struct udevice *dev)
>>  {
>>         struct clk_ops *ops = clk_get_ops(dev);
>> @@ -62,6 +64,32 @@ int clk_get_id(struct udevice *dev, int args_count, uint32_t *args)
>>         return ops->get_id(dev, args_count, args);
>>  }
>>
>> +int clk_get_by_index(struct udevice *dev, int index, struct udevice **clk_devp,
>> +                    int *periphp)
>
>
> This function causes NULL pointer access
> if called with clk_devp == NULL.

Yes, don't do that. Do you think the function comment is unclear?

>
>
> You can decrease the number of arguments
> if this function returns periph ID.

Right, but how to handle 0?

>
>
>> +{
>> +       struct fdtdec_phandle_args args;
>> +       int ret;
>> +
>> +       ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
>> +                                            "clocks", "#clock-cells", 0, index,
>> +                                            &args);
>> +       if (ret) {
>> +               debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
>> +                     __func__, ret);
>> +               return ret;
>> +       }
>> +
>> +       ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, clk_devp);
>> +       if (ret) {
>> +               debug("%s: uclass_get_device_by_of_offset failed: err=%d\n",
>> +                     __func__, ret);
>> +               return ret;
>> +       }
>> +       *periphp = args.args_count > 0 ? args.args[0] : -1;
>
>
> Do you want to let this function fail against #clock-cells == 0?

At present it doesn't. That's why I didn't have it return the
peripheral ID. What could we return to signify that the function
succeeded but there was no peripheral ID?

>
>
>
> This code should be compiled only when OF_CONTROL is on.

OK, I'll update it once we sort out the above.

Regards,
Simon
Masahiro Yamada Jan. 19, 2016, 2:01 a.m. UTC | #3
Hi Simon,


2016-01-15 22:21 GMT+09:00 Simon Glass <sjg@chromium.org>:
> Hi Masahiro,
>
> On 14 January 2016 at 03:11, Masahiro Yamada
> <yamada.masahiro@socionext.com> wrote:
>> Hi Simon,
>>
>>
>>
>>> @@ -12,6 +12,8 @@
>>>  #include <dm/lists.h>
>>>  #include <dm/root.h>
>>>
>>> +DECLARE_GLOBAL_DATA_PTR;
>>> +
>>>  ulong clk_get_rate(struct udevice *dev)
>>>  {
>>>         struct clk_ops *ops = clk_get_ops(dev);
>>> @@ -62,6 +64,32 @@ int clk_get_id(struct udevice *dev, int args_count, uint32_t *args)
>>>         return ops->get_id(dev, args_count, args);
>>>  }
>>>
>>> +int clk_get_by_index(struct udevice *dev, int index, struct udevice **clk_devp,
>>> +                    int *periphp)
>>
>>
>> This function causes NULL pointer access
>> if called with clk_devp == NULL.
>
> Yes, don't do that. Do you think the function comment is unclear?


This would not be a problem in this case,
but I thought NULL-pointer checking is a boilterplate
when we return a pointer filled into a function argument.



>>
>>
>> You can decrease the number of arguments
>> if this function returns periph ID.
>
> Right, but how to handle 0?


>= 0  means peripheral ID.

< 0 means error code.


>>
>>
>>> +{
>>> +       struct fdtdec_phandle_args args;
>>> +       int ret;
>>> +
>>> +       ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
>>> +                                            "clocks", "#clock-cells", 0, index,
>>> +                                            &args);
>>> +       if (ret) {
>>> +               debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
>>> +                     __func__, ret);
>>> +               return ret;
>>> +       }
>>> +
>>> +       ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, clk_devp);
>>> +       if (ret) {
>>> +               debug("%s: uclass_get_device_by_of_offset failed: err=%d\n",
>>> +                     __func__, ret);
>>> +               return ret;
>>> +       }
>>> +       *periphp = args.args_count > 0 ? args.args[0] : -1;
>>
>>
>> Do you want to let this function fail against #clock-cells == 0?
>
> At present it doesn't. That's why I didn't have it return the
> peripheral ID. What could we return to signify that the function
> succeeded but there was no peripheral ID?


I think any clock provider should have at least one ID.

If "clock-cells == 0", this clock has ID 0.

Please correct me if I am misunderstanding.
Simon Glass Jan. 19, 2016, 2:53 a.m. UTC | #4
Hi Masahiro,

On 18 January 2016 at 19:01, Masahiro Yamada
<yamada.masahiro@socionext.com> wrote:
> Hi Simon,
>
>
> 2016-01-15 22:21 GMT+09:00 Simon Glass <sjg@chromium.org>:
>> Hi Masahiro,
>>
>> On 14 January 2016 at 03:11, Masahiro Yamada
>> <yamada.masahiro@socionext.com> wrote:
>>> Hi Simon,
>>>
>>>
>>>
>>>> @@ -12,6 +12,8 @@
>>>>  #include <dm/lists.h>
>>>>  #include <dm/root.h>
>>>>
>>>> +DECLARE_GLOBAL_DATA_PTR;
>>>> +
>>>>  ulong clk_get_rate(struct udevice *dev)
>>>>  {
>>>>         struct clk_ops *ops = clk_get_ops(dev);
>>>> @@ -62,6 +64,32 @@ int clk_get_id(struct udevice *dev, int args_count, uint32_t *args)
>>>>         return ops->get_id(dev, args_count, args);
>>>>  }
>>>>
>>>> +int clk_get_by_index(struct udevice *dev, int index, struct udevice **clk_devp,
>>>> +                    int *periphp)
>>>
>>>
>>> This function causes NULL pointer access
>>> if called with clk_devp == NULL.
>>
>> Yes, don't do that. Do you think the function comment is unclear?
>
>
> This would not be a problem in this case,
> but I thought NULL-pointer checking is a boilterplate
> when we return a pointer filled into a function argument.
>
>
>
>>>
>>>
>>> You can decrease the number of arguments
>>> if this function returns periph ID.
>>
>> Right, but how to handle 0?
>
>
>>= 0  means peripheral ID.
>
> < 0 means error code.
>
>
>>>
>>>
>>>> +{
>>>> +       struct fdtdec_phandle_args args;
>>>> +       int ret;
>>>> +
>>>> +       ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
>>>> +                                            "clocks", "#clock-cells", 0, index,
>>>> +                                            &args);
>>>> +       if (ret) {
>>>> +               debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
>>>> +                     __func__, ret);
>>>> +               return ret;
>>>> +       }
>>>> +
>>>> +       ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, clk_devp);
>>>> +       if (ret) {
>>>> +               debug("%s: uclass_get_device_by_of_offset failed: err=%d\n",
>>>> +                     __func__, ret);
>>>> +               return ret;
>>>> +       }
>>>> +       *periphp = args.args_count > 0 ? args.args[0] : -1;
>>>
>>>
>>> Do you want to let this function fail against #clock-cells == 0?
>>
>> At present it doesn't. That's why I didn't have it return the
>> peripheral ID. What could we return to signify that the function
>> succeeded but there was no peripheral ID?
>
>
> I think any clock provider should have at least one ID.
>
> If "clock-cells == 0", this clock has ID 0.
>
> Please correct me if I am misunderstanding.

That sounds fine to me. I've sent an update to that one patch.

Regards,
Simon
diff mbox

Patch

diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 8078b0f..a205b26 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -12,6 +12,8 @@ 
 #include <dm/lists.h>
 #include <dm/root.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 ulong clk_get_rate(struct udevice *dev)
 {
 	struct clk_ops *ops = clk_get_ops(dev);
@@ -62,6 +64,32 @@  int clk_get_id(struct udevice *dev, int args_count, uint32_t *args)
 	return ops->get_id(dev, args_count, args);
 }
 
+int clk_get_by_index(struct udevice *dev, int index, struct udevice **clk_devp,
+		     int *periphp)
+{
+	struct fdtdec_phandle_args args;
+	int ret;
+
+	ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev->of_offset,
+					     "clocks", "#clock-cells", 0, index,
+					     &args);
+	if (ret) {
+		debug("%s: fdtdec_parse_phandle_with_args failed: err=%d\n",
+		      __func__, ret);
+		return ret;
+	}
+
+	ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, clk_devp);
+	if (ret) {
+		debug("%s: uclass_get_device_by_of_offset failed: err=%d\n",
+		      __func__, ret);
+		return ret;
+	}
+	*periphp = args.args_count > 0 ? args.args[0] : -1;
+
+	return 0;
+}
+
 UCLASS_DRIVER(clk) = {
 	.id		= UCLASS_CLK,
 	.name		= "clk",
diff --git a/include/clk.h b/include/clk.h
index ce2db41..b77c788 100644
--- a/include/clk.h
+++ b/include/clk.h
@@ -150,4 +150,19 @@  static inline int fdt_clk_get(const void *fdt, int nodeoffset, int index,
 }
 #endif
 
+/**
+ * clk_get_by_index() - look up a clock referenced by a device
+ *
+ * Parse a device's 'clocks' list, returning information on the indexed clock,
+ * ensuring that it is activated.
+ *
+ * @dev:	Device containing the clock reference
+ * @index:	Clock index to return (0 = first)
+ * @clk_devp:	Returns clock device
+ * @periphp:	Returns peripheral ID for the device to control. This is the
+ *		first argument after the clock node phandle.
+ * @return 0 if OK, or -ve error code
+ */
+int clk_get_by_index(struct udevice *dev, int index, struct udevice **clk_devp,
+		     int *periphp);
 #endif /* _CLK_H_ */