Re: [U-Boot] [PATCH v3 5/7] usb: host: ohci-generic: add CLOCK support

2017-05-20 Thread Marek Vasut
On 05/19/2017 02:16 PM, Patrice CHOTARD wrote:
> On 05/19/2017 01:51 PM, Marek Vasut wrote:
>> On 05/19/2017 01:27 PM, Patrice CHOTARD wrote:
>>> Hi Marek
>>>
>>> On 05/18/2017 11:29 AM, Marek Vasut wrote:
 On 05/17/2017 03:34 PM, patrice.chot...@st.com wrote:
> From: Patrice Chotard 
>
> use list to save reference to enabled clocks in order to
> disabled them in case of error during probe() or
> during driver removal.
>
> Signed-off-by: Patrice Chotard 
> ---
>
> v3:   _ extract in this patch the CLOCK support add-on from previous 
> patch 5
>   _ keep enabled clocks reference in list in order to
> disable clocks in error path or in .remove callback
>
> v2:   _ add error path management
>   _ add .remove callback
>
>drivers/usb/host/ohci-generic.c | 81 
> -
>1 file changed, 80 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/host/ohci-generic.c 
> b/drivers/usb/host/ohci-generic.c
> index f3307f4..a6d89a8 100644
> --- a/drivers/usb/host/ohci-generic.c
> +++ b/drivers/usb/host/ohci-generic.c
> @@ -5,6 +5,7 @@
> */
>
>#include 
> +#include 
>#include 
>#include "ohci.h"
>
> @@ -12,20 +13,98 @@
># error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW"
>#endif
>
> +struct ohci_clock {
> + struct clk *clk;
> + struct list_head list;
> +};
> +
>struct generic_ohci {
>   ohci_t ohci;
> + struct list_head clks;
>};
>
> +static int ohci_release_clocks(struct generic_ohci *priv)
> +{
> + struct ohci_clock *ohci_clock, *tmp;
> + struct clk *clk;
> + int ret;
> +
> + list_for_each_entry_safe(ohci_clock, tmp, >clks, list) {
> + clk = ohci_clock->clk;
> +
> + clk_request(clk->dev, clk);
> + if (ret)
> + return ret;
> +
> + clk_disable(clk);
> +
> + ret = clk_free(clk);
> + if (ret)
> + return ret;
> +
> + list_del(_clock->list);
> + }
> + return 0;
> +}
> +
>static int ohci_usb_probe(struct udevice *dev)
>{
>   struct ohci_regs *regs = (struct ohci_regs *)dev_get_addr(dev);
> + struct generic_ohci *priv = dev_get_priv(dev);
> + int i, ret;
> +
> + INIT_LIST_HEAD(>clks);
> +
> + for (i = 0; ; i++) {
> + struct ohci_clock *ohci_clock;
> + struct clk *clk;
> +
> + clk = devm_kmalloc(dev, sizeof(*clk), GFP_KERNEL);

 Since you know how many entries the clock phandle has, you can allocate
 an array and drop this while list handling and this per-element kmalloc,
 which fragments the allocator pool.
>>>
>>> I disagree, at this point we don't know how many entries the clock
>>> phandle has.
>>
>> I know you can do it in less then 2 mallocs,  in fact in exactly 1 ,
>> which is already better.
> 
> Can you elaborate ?
> 
>>
>>> But, following your idea to avoid allocator pool fragmentation, in order
>>> to get the phandle number for array allocation, i can, for example add a
>>> new fdt API :
>>>
>>> int fdtdec_get_phandle_nb(const void *blob, int src_node,
>>>const char *list_name,
>>>const char *cells_name,
>>>int cell_count,
>>>int phandle_nb);
>>
>> Uh, why ?
>>
>>> Then, with phandle_nb,, we 'll be able to allocate the right array size
>>> for clocks and resets before populating them.
>>
>> Just query the number of elements up front and then allocate the array ?
> 
> Can you indicate me with which API please ?

fdt.*count() or somesuch .

-- 
Best regards,
Marek Vasut
___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v3 5/7] usb: host: ohci-generic: add CLOCK support

2017-05-19 Thread Patrice CHOTARD
On 05/19/2017 01:51 PM, Marek Vasut wrote:
> On 05/19/2017 01:27 PM, Patrice CHOTARD wrote:
>> Hi Marek
>>
>> On 05/18/2017 11:29 AM, Marek Vasut wrote:
>>> On 05/17/2017 03:34 PM, patrice.chot...@st.com wrote:
 From: Patrice Chotard 

 use list to save reference to enabled clocks in order to
 disabled them in case of error during probe() or
 during driver removal.

 Signed-off-by: Patrice Chotard 
 ---

 v3:_ extract in this patch the CLOCK support add-on from previous 
 patch 5
_ keep enabled clocks reference in list in order to
  disable clocks in error path or in .remove callback

 v2:_ add error path management
_ add .remove callback

drivers/usb/host/ohci-generic.c | 81 
 -
1 file changed, 80 insertions(+), 1 deletion(-)

 diff --git a/drivers/usb/host/ohci-generic.c 
 b/drivers/usb/host/ohci-generic.c
 index f3307f4..a6d89a8 100644
 --- a/drivers/usb/host/ohci-generic.c
 +++ b/drivers/usb/host/ohci-generic.c
 @@ -5,6 +5,7 @@
 */

#include 
 +#include 
#include 
#include "ohci.h"

 @@ -12,20 +13,98 @@
# error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW"
#endif

 +struct ohci_clock {
 +  struct clk *clk;
 +  struct list_head list;
 +};
 +
struct generic_ohci {
ohci_t ohci;
 +  struct list_head clks;
};

 +static int ohci_release_clocks(struct generic_ohci *priv)
 +{
 +  struct ohci_clock *ohci_clock, *tmp;
 +  struct clk *clk;
 +  int ret;
 +
 +  list_for_each_entry_safe(ohci_clock, tmp, >clks, list) {
 +  clk = ohci_clock->clk;
 +
 +  clk_request(clk->dev, clk);
 +  if (ret)
 +  return ret;
 +
 +  clk_disable(clk);
 +
 +  ret = clk_free(clk);
 +  if (ret)
 +  return ret;
 +
 +  list_del(_clock->list);
 +  }
 +  return 0;
 +}
 +
static int ohci_usb_probe(struct udevice *dev)
{
struct ohci_regs *regs = (struct ohci_regs *)dev_get_addr(dev);
 +  struct generic_ohci *priv = dev_get_priv(dev);
 +  int i, ret;
 +
 +  INIT_LIST_HEAD(>clks);
 +
 +  for (i = 0; ; i++) {
 +  struct ohci_clock *ohci_clock;
 +  struct clk *clk;
 +
 +  clk = devm_kmalloc(dev, sizeof(*clk), GFP_KERNEL);
>>>
>>> Since you know how many entries the clock phandle has, you can allocate
>>> an array and drop this while list handling and this per-element kmalloc,
>>> which fragments the allocator pool.
>>
>> I disagree, at this point we don't know how many entries the clock
>> phandle has.
> 
> I know you can do it in less then 2 mallocs,  in fact in exactly 1 ,
> which is already better.

Can you elaborate ?

> 
>> But, following your idea to avoid allocator pool fragmentation, in order
>> to get the phandle number for array allocation, i can, for example add a
>> new fdt API :
>>
>> int fdtdec_get_phandle_nb(const void *blob, int src_node,
>> const char *list_name,
>> const char *cells_name,
>> int cell_count,
>> int phandle_nb);
> 
> Uh, why ?
> 
>> Then, with phandle_nb,, we 'll be able to allocate the right array size
>> for clocks and resets before populating them.
> 
> Just query the number of elements up front and then allocate the array ?

Can you indicate me with which API please ?

> 
>> Thanks
>>
>> Patrice
>>
>>>
 +  if (!clk) {
 +  error("Can't allocate resource\n");
 +  goto clk_err;
 +  }
 +
 +  ret = clk_get_by_index(dev, i, clk);
 +  if (ret < 0)
 +  break;
 +
 +  if (clk_enable(clk)) {
 +  error("failed to enable ohci_clock %d\n", i);
 +  clk_free(clk);
 +  goto clk_err;
 +  }
 +  clk_free(clk);
 +
 +  /*
 +   * add enabled clocks into clks list in order to be disabled
 +   * later on ohci_usb_remove() call or in error path if needed
 +   */
 +  ohci_clock = devm_kmalloc(dev, sizeof(*ohci_clock), GFP_KERNEL);
>>>
>>> Can't you just embed one structure into the other ?
>>>
 +  if (!ohci_clock) {
 +  error("Can't allocate resource\n");
 +  goto clk_err;
 +  }
 +  ohci_clock->clk = clk;
 +  list_add(_clock->list, >clks);
 +  }

return ohci_register(dev, regs);

Re: [U-Boot] [PATCH v3 5/7] usb: host: ohci-generic: add CLOCK support

2017-05-19 Thread Marek Vasut
On 05/19/2017 01:27 PM, Patrice CHOTARD wrote:
> Hi Marek
> 
> On 05/18/2017 11:29 AM, Marek Vasut wrote:
>> On 05/17/2017 03:34 PM, patrice.chot...@st.com wrote:
>>> From: Patrice Chotard 
>>>
>>> use list to save reference to enabled clocks in order to
>>> disabled them in case of error during probe() or
>>> during driver removal.
>>>
>>> Signed-off-by: Patrice Chotard 
>>> ---
>>>
>>> v3: _ extract in this patch the CLOCK support add-on from previous patch 5
>>> _ keep enabled clocks reference in list in order to
>>>   disable clocks in error path or in .remove callback
>>>
>>> v2: _ add error path management
>>> _ add .remove callback
>>>
>>>   drivers/usb/host/ohci-generic.c | 81 
>>> -
>>>   1 file changed, 80 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/usb/host/ohci-generic.c 
>>> b/drivers/usb/host/ohci-generic.c
>>> index f3307f4..a6d89a8 100644
>>> --- a/drivers/usb/host/ohci-generic.c
>>> +++ b/drivers/usb/host/ohci-generic.c
>>> @@ -5,6 +5,7 @@
>>>*/
>>>   
>>>   #include 
>>> +#include 
>>>   #include 
>>>   #include "ohci.h"
>>>   
>>> @@ -12,20 +13,98 @@
>>>   # error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW"
>>>   #endif
>>>   
>>> +struct ohci_clock {
>>> +   struct clk *clk;
>>> +   struct list_head list;
>>> +};
>>> +
>>>   struct generic_ohci {
>>> ohci_t ohci;
>>> +   struct list_head clks;
>>>   };
>>>   
>>> +static int ohci_release_clocks(struct generic_ohci *priv)
>>> +{
>>> +   struct ohci_clock *ohci_clock, *tmp;
>>> +   struct clk *clk;
>>> +   int ret;
>>> +
>>> +   list_for_each_entry_safe(ohci_clock, tmp, >clks, list) {
>>> +   clk = ohci_clock->clk;
>>> +
>>> +   clk_request(clk->dev, clk);
>>> +   if (ret)
>>> +   return ret;
>>> +
>>> +   clk_disable(clk);
>>> +
>>> +   ret = clk_free(clk);
>>> +   if (ret)
>>> +   return ret;
>>> +
>>> +   list_del(_clock->list);
>>> +   }
>>> +   return 0;
>>> +}
>>> +
>>>   static int ohci_usb_probe(struct udevice *dev)
>>>   {
>>> struct ohci_regs *regs = (struct ohci_regs *)dev_get_addr(dev);
>>> +   struct generic_ohci *priv = dev_get_priv(dev);
>>> +   int i, ret;
>>> +
>>> +   INIT_LIST_HEAD(>clks);
>>> +
>>> +   for (i = 0; ; i++) {
>>> +   struct ohci_clock *ohci_clock;
>>> +   struct clk *clk;
>>> +
>>> +   clk = devm_kmalloc(dev, sizeof(*clk), GFP_KERNEL);
>>
>> Since you know how many entries the clock phandle has, you can allocate
>> an array and drop this while list handling and this per-element kmalloc,
>> which fragments the allocator pool.
> 
> I disagree, at this point we don't know how many entries the clock 
> phandle has.

I know you can do it in less then 2 mallocs,  in fact in exactly 1 ,
which is already better.

> But, following your idea to avoid allocator pool fragmentation, in order 
> to get the phandle number for array allocation, i can, for example add a 
> new fdt API :
> 
> int fdtdec_get_phandle_nb(const void *blob, int src_node,
>  const char *list_name,
>  const char *cells_name,
>  int cell_count,
>  int phandle_nb);

Uh, why ?

> Then, with phandle_nb,, we 'll be able to allocate the right array size 
> for clocks and resets before populating them.

Just query the number of elements up front and then allocate the array ?

> Thanks
> 
> Patrice
> 
>>
>>> +   if (!clk) {
>>> +   error("Can't allocate resource\n");
>>> +   goto clk_err;
>>> +   }
>>> +
>>> +   ret = clk_get_by_index(dev, i, clk);
>>> +   if (ret < 0)
>>> +   break;
>>> +
>>> +   if (clk_enable(clk)) {
>>> +   error("failed to enable ohci_clock %d\n", i);
>>> +   clk_free(clk);
>>> +   goto clk_err;
>>> +   }
>>> +   clk_free(clk);
>>> +
>>> +   /*
>>> +* add enabled clocks into clks list in order to be disabled
>>> +* later on ohci_usb_remove() call or in error path if needed
>>> +*/
>>> +   ohci_clock = devm_kmalloc(dev, sizeof(*ohci_clock), GFP_KERNEL);
>>
>> Can't you just embed one structure into the other ?
>>
>>> +   if (!ohci_clock) {
>>> +   error("Can't allocate resource\n");
>>> +   goto clk_err;
>>> +   }
>>> +   ohci_clock->clk = clk;
>>> +   list_add(_clock->list, >clks);
>>> +   }
>>>   
>>> return ohci_register(dev, regs);
>>> +
>>> +clk_err:
>>> +   return ohci_release_clocks(priv);
>>>   }
>>>   
>>>   static int ohci_usb_remove(struct udevice *dev)
>>>   {
>>> -   return ohci_deregister(dev);
>>> +   struct generic_ohci *priv = dev_get_priv(dev);
>>> +   int ret;
>>> +
>>> +   ret = 

Re: [U-Boot] [PATCH v3 5/7] usb: host: ohci-generic: add CLOCK support

2017-05-19 Thread Patrice CHOTARD
Hi Marek

On 05/18/2017 11:29 AM, Marek Vasut wrote:
> On 05/17/2017 03:34 PM, patrice.chot...@st.com wrote:
>> From: Patrice Chotard 
>>
>> use list to save reference to enabled clocks in order to
>> disabled them in case of error during probe() or
>> during driver removal.
>>
>> Signed-off-by: Patrice Chotard 
>> ---
>>
>> v3:  _ extract in this patch the CLOCK support add-on from previous patch 5
>>  _ keep enabled clocks reference in list in order to
>>disable clocks in error path or in .remove callback
>>
>> v2:  _ add error path management
>>  _ add .remove callback
>>
>>   drivers/usb/host/ohci-generic.c | 81 
>> -
>>   1 file changed, 80 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/usb/host/ohci-generic.c 
>> b/drivers/usb/host/ohci-generic.c
>> index f3307f4..a6d89a8 100644
>> --- a/drivers/usb/host/ohci-generic.c
>> +++ b/drivers/usb/host/ohci-generic.c
>> @@ -5,6 +5,7 @@
>>*/
>>   
>>   #include 
>> +#include 
>>   #include 
>>   #include "ohci.h"
>>   
>> @@ -12,20 +13,98 @@
>>   # error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW"
>>   #endif
>>   
>> +struct ohci_clock {
>> +struct clk *clk;
>> +struct list_head list;
>> +};
>> +
>>   struct generic_ohci {
>>  ohci_t ohci;
>> +struct list_head clks;
>>   };
>>   
>> +static int ohci_release_clocks(struct generic_ohci *priv)
>> +{
>> +struct ohci_clock *ohci_clock, *tmp;
>> +struct clk *clk;
>> +int ret;
>> +
>> +list_for_each_entry_safe(ohci_clock, tmp, >clks, list) {
>> +clk = ohci_clock->clk;
>> +
>> +clk_request(clk->dev, clk);
>> +if (ret)
>> +return ret;
>> +
>> +clk_disable(clk);
>> +
>> +ret = clk_free(clk);
>> +if (ret)
>> +return ret;
>> +
>> +list_del(_clock->list);
>> +}
>> +return 0;
>> +}
>> +
>>   static int ohci_usb_probe(struct udevice *dev)
>>   {
>>  struct ohci_regs *regs = (struct ohci_regs *)dev_get_addr(dev);
>> +struct generic_ohci *priv = dev_get_priv(dev);
>> +int i, ret;
>> +
>> +INIT_LIST_HEAD(>clks);
>> +
>> +for (i = 0; ; i++) {
>> +struct ohci_clock *ohci_clock;
>> +struct clk *clk;
>> +
>> +clk = devm_kmalloc(dev, sizeof(*clk), GFP_KERNEL);
> 
> Since you know how many entries the clock phandle has, you can allocate
> an array and drop this while list handling and this per-element kmalloc,
> which fragments the allocator pool.

I disagree, at this point we don't know how many entries the clock 
phandle has.

But, following your idea to avoid allocator pool fragmentation, in order 
to get the phandle number for array allocation, i can, for example add a 
new fdt API :

int fdtdec_get_phandle_nb(const void *blob, int src_node,
   const char *list_name,
   const char *cells_name,
   int cell_count,
   int phandle_nb);

Then, with phandle_nb,, we 'll be able to allocate the right array size 
for clocks and resets before populating them.

Thanks

Patrice

> 
>> +if (!clk) {
>> +error("Can't allocate resource\n");
>> +goto clk_err;
>> +}
>> +
>> +ret = clk_get_by_index(dev, i, clk);
>> +if (ret < 0)
>> +break;
>> +
>> +if (clk_enable(clk)) {
>> +error("failed to enable ohci_clock %d\n", i);
>> +clk_free(clk);
>> +goto clk_err;
>> +}
>> +clk_free(clk);
>> +
>> +/*
>> + * add enabled clocks into clks list in order to be disabled
>> + * later on ohci_usb_remove() call or in error path if needed
>> + */
>> +ohci_clock = devm_kmalloc(dev, sizeof(*ohci_clock), GFP_KERNEL);
> 
> Can't you just embed one structure into the other ?
> 
>> +if (!ohci_clock) {
>> +error("Can't allocate resource\n");
>> +goto clk_err;
>> +}
>> +ohci_clock->clk = clk;
>> +list_add(_clock->list, >clks);
>> +}
>>   
>>  return ohci_register(dev, regs);
>> +
>> +clk_err:
>> +return ohci_release_clocks(priv);
>>   }
>>   
>>   static int ohci_usb_remove(struct udevice *dev)
>>   {
>> -return ohci_deregister(dev);
>> +struct generic_ohci *priv = dev_get_priv(dev);
>> +int ret;
>> +
>> +ret = ohci_deregister(dev);
>> +if (ret)
>> +return ret;
>> +
>> +return ohci_release_clocks(priv);
>>   }
>>   
>>   static const struct udevice_id ohci_usb_ids[] = {
>>
> 
> 
___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


Re: [U-Boot] [PATCH v3 5/7] usb: host: ohci-generic: add CLOCK support

2017-05-18 Thread Marek Vasut
On 05/17/2017 03:34 PM, patrice.chot...@st.com wrote:
> From: Patrice Chotard 
> 
> use list to save reference to enabled clocks in order to
> disabled them in case of error during probe() or
> during driver removal.
> 
> Signed-off-by: Patrice Chotard 
> ---
> 
> v3:   _ extract in this patch the CLOCK support add-on from previous patch 5
>   _ keep enabled clocks reference in list in order to 
> disable clocks in error path or in .remove callback
> 
> v2:   _ add error path management
>   _ add .remove callback
> 
>  drivers/usb/host/ohci-generic.c | 81 
> -
>  1 file changed, 80 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c
> index f3307f4..a6d89a8 100644
> --- a/drivers/usb/host/ohci-generic.c
> +++ b/drivers/usb/host/ohci-generic.c
> @@ -5,6 +5,7 @@
>   */
>  
>  #include 
> +#include 
>  #include 
>  #include "ohci.h"
>  
> @@ -12,20 +13,98 @@
>  # error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW"
>  #endif
>  
> +struct ohci_clock {
> + struct clk *clk;
> + struct list_head list;
> +};
> +
>  struct generic_ohci {
>   ohci_t ohci;
> + struct list_head clks;
>  };
>  
> +static int ohci_release_clocks(struct generic_ohci *priv)
> +{
> + struct ohci_clock *ohci_clock, *tmp;
> + struct clk *clk;
> + int ret;
> +
> + list_for_each_entry_safe(ohci_clock, tmp, >clks, list) {
> + clk = ohci_clock->clk;
> +
> + clk_request(clk->dev, clk);
> + if (ret)
> + return ret;
> +
> + clk_disable(clk);
> +
> + ret = clk_free(clk);
> + if (ret)
> + return ret;
> +
> + list_del(_clock->list);
> + }
> + return 0;
> +}
> +
>  static int ohci_usb_probe(struct udevice *dev)
>  {
>   struct ohci_regs *regs = (struct ohci_regs *)dev_get_addr(dev);
> + struct generic_ohci *priv = dev_get_priv(dev);
> + int i, ret;
> +
> + INIT_LIST_HEAD(>clks);
> +
> + for (i = 0; ; i++) {
> + struct ohci_clock *ohci_clock;
> + struct clk *clk;
> +
> + clk = devm_kmalloc(dev, sizeof(*clk), GFP_KERNEL);

Since you know how many entries the clock phandle has, you can allocate
an array and drop this while list handling and this per-element kmalloc,
which fragments the allocator pool.

> + if (!clk) {
> + error("Can't allocate resource\n");
> + goto clk_err;
> + }
> +
> + ret = clk_get_by_index(dev, i, clk);
> + if (ret < 0)
> + break;
> +
> + if (clk_enable(clk)) {
> + error("failed to enable ohci_clock %d\n", i);
> + clk_free(clk);
> + goto clk_err;
> + }
> + clk_free(clk);
> +
> + /*
> +  * add enabled clocks into clks list in order to be disabled
> +  * later on ohci_usb_remove() call or in error path if needed
> +  */
> + ohci_clock = devm_kmalloc(dev, sizeof(*ohci_clock), GFP_KERNEL);

Can't you just embed one structure into the other ?

> + if (!ohci_clock) {
> + error("Can't allocate resource\n");
> + goto clk_err;
> + }
> + ohci_clock->clk = clk;
> + list_add(_clock->list, >clks);
> + }
>  
>   return ohci_register(dev, regs);
> +
> +clk_err:
> + return ohci_release_clocks(priv);
>  }
>  
>  static int ohci_usb_remove(struct udevice *dev)
>  {
> - return ohci_deregister(dev);
> + struct generic_ohci *priv = dev_get_priv(dev);
> + int ret;
> +
> + ret = ohci_deregister(dev);
> + if (ret)
> + return ret;
> +
> + return ohci_release_clocks(priv);
>  }
>  
>  static const struct udevice_id ohci_usb_ids[] = {
> 


-- 
Best regards,
Marek Vasut
___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot


[U-Boot] [PATCH v3 5/7] usb: host: ohci-generic: add CLOCK support

2017-05-17 Thread patrice.chotard
From: Patrice Chotard 

use list to save reference to enabled clocks in order to
disabled them in case of error during probe() or
during driver removal.

Signed-off-by: Patrice Chotard 
---

v3: _ extract in this patch the CLOCK support add-on from previous patch 5
_ keep enabled clocks reference in list in order to 
  disable clocks in error path or in .remove callback

v2: _ add error path management
_ add .remove callback

 drivers/usb/host/ohci-generic.c | 81 -
 1 file changed, 80 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/ohci-generic.c b/drivers/usb/host/ohci-generic.c
index f3307f4..a6d89a8 100644
--- a/drivers/usb/host/ohci-generic.c
+++ b/drivers/usb/host/ohci-generic.c
@@ -5,6 +5,7 @@
  */
 
 #include 
+#include 
 #include 
 #include "ohci.h"
 
@@ -12,20 +13,98 @@
 # error "Generic OHCI driver requires CONFIG_USB_OHCI_NEW"
 #endif
 
+struct ohci_clock {
+   struct clk *clk;
+   struct list_head list;
+};
+
 struct generic_ohci {
ohci_t ohci;
+   struct list_head clks;
 };
 
+static int ohci_release_clocks(struct generic_ohci *priv)
+{
+   struct ohci_clock *ohci_clock, *tmp;
+   struct clk *clk;
+   int ret;
+
+   list_for_each_entry_safe(ohci_clock, tmp, >clks, list) {
+   clk = ohci_clock->clk;
+
+   clk_request(clk->dev, clk);
+   if (ret)
+   return ret;
+
+   clk_disable(clk);
+
+   ret = clk_free(clk);
+   if (ret)
+   return ret;
+
+   list_del(_clock->list);
+   }
+   return 0;
+}
+
 static int ohci_usb_probe(struct udevice *dev)
 {
struct ohci_regs *regs = (struct ohci_regs *)dev_get_addr(dev);
+   struct generic_ohci *priv = dev_get_priv(dev);
+   int i, ret;
+
+   INIT_LIST_HEAD(>clks);
+
+   for (i = 0; ; i++) {
+   struct ohci_clock *ohci_clock;
+   struct clk *clk;
+
+   clk = devm_kmalloc(dev, sizeof(*clk), GFP_KERNEL);
+   if (!clk) {
+   error("Can't allocate resource\n");
+   goto clk_err;
+   }
+
+   ret = clk_get_by_index(dev, i, clk);
+   if (ret < 0)
+   break;
+
+   if (clk_enable(clk)) {
+   error("failed to enable ohci_clock %d\n", i);
+   clk_free(clk);
+   goto clk_err;
+   }
+   clk_free(clk);
+
+   /*
+* add enabled clocks into clks list in order to be disabled
+* later on ohci_usb_remove() call or in error path if needed
+*/
+   ohci_clock = devm_kmalloc(dev, sizeof(*ohci_clock), GFP_KERNEL);
+   if (!ohci_clock) {
+   error("Can't allocate resource\n");
+   goto clk_err;
+   }
+   ohci_clock->clk = clk;
+   list_add(_clock->list, >clks);
+   }
 
return ohci_register(dev, regs);
+
+clk_err:
+   return ohci_release_clocks(priv);
 }
 
 static int ohci_usb_remove(struct udevice *dev)
 {
-   return ohci_deregister(dev);
+   struct generic_ohci *priv = dev_get_priv(dev);
+   int ret;
+
+   ret = ohci_deregister(dev);
+   if (ret)
+   return ret;
+
+   return ohci_release_clocks(priv);
 }
 
 static const struct udevice_id ohci_usb_ids[] = {
-- 
1.9.1

___
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot