Re: [PATCH v6 3/5] USB: ohci: da8xx: Allow a regulator to handle VBUS

2016-11-22 Thread David Lechner

On 11/22/2016 02:46 PM, Axel Haslam wrote:

On Tue, Nov 22, 2016 at 9:37 PM, David Lechner  wrote:

On 11/21/2016 10:30 AM, Axel Haslam wrote:


Using a regulator to handle VBUS will eliminate the need for
platform data and callbacks, and make the driver more generic
allowing different types of regulators to handle VBUS.

The regulator equivalents to the platform callbacks are:
set_power   ->  regulator_enable/regulator_disable
get_power   ->  regulator_is_enabled
get_oci ->  regulator_get_error_flags
ocic_notify ->  regulator event notification

Signed-off-by: Axel Haslam 
---
 drivers/usb/host/ohci-da8xx.c | 97
+--
 1 file changed, 94 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index 90763ad..d0eb754 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -36,8 +37,12 @@ static int (*orig_ohci_hub_control)(struct usb_hcd
*hcd, u16 typeReq,
 static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf);

 struct da8xx_ohci_hcd {
+   struct usb_hcd *hcd;
struct clk *usb11_clk;
struct phy *usb11_phy;
+   struct regulator *vbus_reg;
+   struct notifier_block nb;
+   unsigned int reg_enabled;
 };

 #define to_da8xx_ohci(hcd) (struct da8xx_ohci_hcd
*)(hcd_to_ohci(hcd)->priv)
@@ -83,56 +88,103 @@ static void ohci_da8xx_disable(struct usb_hcd *hcd)

 static int ohci_da8xx_set_power(struct usb_hcd *hcd, int on)
 {
+   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
struct device *dev  = hcd->self.controller;
struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
+   int ret;

if (hub && hub->set_power)
return hub->set_power(1, on);

+   if (!da8xx_ohci->vbus_reg)
+   return 0;
+
+   if (on && !da8xx_ohci->reg_enabled) {
+   ret = regulator_enable(da8xx_ohci->vbus_reg);
+   if (ret) {
+   dev_err(dev, "Failed to enable regulator: %d\n",
ret);
+   return ret;
+   }
+   da8xx_ohci->reg_enabled = 1;
+
+   } else if (!on && da8xx_ohci->reg_enabled) {
+   ret = regulator_disable(da8xx_ohci->vbus_reg);
+   if (ret) {
+   dev_err(dev, "Failed  to disable regulator: %d\n",
ret);
+   return ret;
+   }
+   da8xx_ohci->reg_enabled = 0;
+   }
+
return 0;
 }

 static int ohci_da8xx_get_power(struct usb_hcd *hcd)
 {
+   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
struct device *dev  = hcd->self.controller;
struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);

if (hub && hub->get_power)
return hub->get_power(1);

+   if (da8xx_ohci->vbus_reg)
+   return regulator_is_enabled(da8xx_ohci->vbus_reg);
+
return 1;
 }

 static int ohci_da8xx_get_oci(struct usb_hcd *hcd)
 {
+   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
struct device *dev  = hcd->self.controller;
struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
+   unsigned int flags;
+   int ret;

if (hub && hub->get_oci)
return hub->get_oci(1);

+   if (!da8xx_ohci->vbus_reg)
+   return 0;
+
+   ret = regulator_get_error_flags(da8xx_ohci->vbus_reg, &flags);
+   if (ret)
+   return ret;
+
+   if (flags & REGULATOR_ERROR_OVER_CURRENT)
+   return 1;
+
return 0;
 }

 static int ohci_da8xx_has_set_power(struct usb_hcd *hcd)
 {
+   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
struct device *dev  = hcd->self.controller;
struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);

if (hub && hub->set_power)
return 1;

+   if (da8xx_ohci->vbus_reg)
+   return 1;
+
return 0;
 }

 static int ohci_da8xx_has_oci(struct usb_hcd *hcd)
 {
+   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
struct device *dev  = hcd->self.controller;
struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);

if (hub && hub->get_oci)
return 1;

+   if (da8xx_ohci->vbus_reg)
+   return 1;
+
return 0;
 }

@@ -160,15 +212,41 @@ static void ohci_da8xx_ocic_handler(struct
da8xx_ohci_root_hub *hub,
hub->set_power(port, 0);
 }

+static int ohci_da8xx_regulator_event(struct notifier_block *nb,
+   unsigned long event, void *data)
+{
+   struct da8xx_ohci_hcd *da8xx_ohci =
+   container_of(nb, struct da8xx_ohci_hcd,
nb);
+   struct device *dev = da8xx_ohci->hcd->self.controller;
+
+  

Re: [PATCH v6 3/5] USB: ohci: da8xx: Allow a regulator to handle VBUS

2016-11-22 Thread Axel Haslam
On Tue, Nov 22, 2016 at 9:37 PM, David Lechner  wrote:
> On 11/21/2016 10:30 AM, Axel Haslam wrote:
>>
>> Using a regulator to handle VBUS will eliminate the need for
>> platform data and callbacks, and make the driver more generic
>> allowing different types of regulators to handle VBUS.
>>
>> The regulator equivalents to the platform callbacks are:
>> set_power   ->  regulator_enable/regulator_disable
>> get_power   ->  regulator_is_enabled
>> get_oci ->  regulator_get_error_flags
>> ocic_notify ->  regulator event notification
>>
>> Signed-off-by: Axel Haslam 
>> ---
>>  drivers/usb/host/ohci-da8xx.c | 97
>> +--
>>  1 file changed, 94 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
>> index 90763ad..d0eb754 100644
>> --- a/drivers/usb/host/ohci-da8xx.c
>> +++ b/drivers/usb/host/ohci-da8xx.c
>> @@ -20,6 +20,7 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>>  #include 
>>  #include 
>>  #include 
>> @@ -36,8 +37,12 @@ static int (*orig_ohci_hub_control)(struct usb_hcd
>> *hcd, u16 typeReq,
>>  static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf);
>>
>>  struct da8xx_ohci_hcd {
>> +   struct usb_hcd *hcd;
>> struct clk *usb11_clk;
>> struct phy *usb11_phy;
>> +   struct regulator *vbus_reg;
>> +   struct notifier_block nb;
>> +   unsigned int reg_enabled;
>>  };
>>
>>  #define to_da8xx_ohci(hcd) (struct da8xx_ohci_hcd
>> *)(hcd_to_ohci(hcd)->priv)
>> @@ -83,56 +88,103 @@ static void ohci_da8xx_disable(struct usb_hcd *hcd)
>>
>>  static int ohci_da8xx_set_power(struct usb_hcd *hcd, int on)
>>  {
>> +   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
>> struct device *dev  = hcd->self.controller;
>> struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
>> +   int ret;
>>
>> if (hub && hub->set_power)
>> return hub->set_power(1, on);
>>
>> +   if (!da8xx_ohci->vbus_reg)
>> +   return 0;
>> +
>> +   if (on && !da8xx_ohci->reg_enabled) {
>> +   ret = regulator_enable(da8xx_ohci->vbus_reg);
>> +   if (ret) {
>> +   dev_err(dev, "Failed to enable regulator: %d\n",
>> ret);
>> +   return ret;
>> +   }
>> +   da8xx_ohci->reg_enabled = 1;
>> +
>> +   } else if (!on && da8xx_ohci->reg_enabled) {
>> +   ret = regulator_disable(da8xx_ohci->vbus_reg);
>> +   if (ret) {
>> +   dev_err(dev, "Failed  to disable regulator: %d\n",
>> ret);
>> +   return ret;
>> +   }
>> +   da8xx_ohci->reg_enabled = 0;
>> +   }
>> +
>> return 0;
>>  }
>>
>>  static int ohci_da8xx_get_power(struct usb_hcd *hcd)
>>  {
>> +   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
>> struct device *dev  = hcd->self.controller;
>> struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
>>
>> if (hub && hub->get_power)
>> return hub->get_power(1);
>>
>> +   if (da8xx_ohci->vbus_reg)
>> +   return regulator_is_enabled(da8xx_ohci->vbus_reg);
>> +
>> return 1;
>>  }
>>
>>  static int ohci_da8xx_get_oci(struct usb_hcd *hcd)
>>  {
>> +   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
>> struct device *dev  = hcd->self.controller;
>> struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
>> +   unsigned int flags;
>> +   int ret;
>>
>> if (hub && hub->get_oci)
>> return hub->get_oci(1);
>>
>> +   if (!da8xx_ohci->vbus_reg)
>> +   return 0;
>> +
>> +   ret = regulator_get_error_flags(da8xx_ohci->vbus_reg, &flags);
>> +   if (ret)
>> +   return ret;
>> +
>> +   if (flags & REGULATOR_ERROR_OVER_CURRENT)
>> +   return 1;
>> +
>> return 0;
>>  }
>>
>>  static int ohci_da8xx_has_set_power(struct usb_hcd *hcd)
>>  {
>> +   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
>> struct device *dev  = hcd->self.controller;
>> struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
>>
>> if (hub && hub->set_power)
>> return 1;
>>
>> +   if (da8xx_ohci->vbus_reg)
>> +   return 1;
>> +
>> return 0;
>>  }
>>
>>  static int ohci_da8xx_has_oci(struct usb_hcd *hcd)
>>  {
>> +   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
>> struct device *dev  = hcd->self.controller;
>> struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
>>
>> if (hub && hub->get_oci)
>> return 1;
>>
>> +   if (da8xx_ohci->vbus_reg)
>> +   return 1;
>> +
>> return 0;
>>  }
>>
>> @@ -160,15 +212,41 @@ static void ohci_da8xx_ocic_handler(struct
>> da8xx

Re: [PATCH v6 3/5] USB: ohci: da8xx: Allow a regulator to handle VBUS

2016-11-22 Thread David Lechner

On 11/21/2016 10:30 AM, Axel Haslam wrote:

Using a regulator to handle VBUS will eliminate the need for
platform data and callbacks, and make the driver more generic
allowing different types of regulators to handle VBUS.

The regulator equivalents to the platform callbacks are:
set_power   ->  regulator_enable/regulator_disable
get_power   ->  regulator_is_enabled
get_oci ->  regulator_get_error_flags
ocic_notify ->  regulator event notification

Signed-off-by: Axel Haslam 
---
 drivers/usb/host/ohci-da8xx.c | 97 +--
 1 file changed, 94 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index 90763ad..d0eb754 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -36,8 +37,12 @@ static int (*orig_ohci_hub_control)(struct usb_hcd  *hcd, 
u16 typeReq,
 static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf);

 struct da8xx_ohci_hcd {
+   struct usb_hcd *hcd;
struct clk *usb11_clk;
struct phy *usb11_phy;
+   struct regulator *vbus_reg;
+   struct notifier_block nb;
+   unsigned int reg_enabled;
 };

 #define to_da8xx_ohci(hcd) (struct da8xx_ohci_hcd *)(hcd_to_ohci(hcd)->priv)
@@ -83,56 +88,103 @@ static void ohci_da8xx_disable(struct usb_hcd *hcd)

 static int ohci_da8xx_set_power(struct usb_hcd *hcd, int on)
 {
+   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
struct device *dev  = hcd->self.controller;
struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
+   int ret;

if (hub && hub->set_power)
return hub->set_power(1, on);

+   if (!da8xx_ohci->vbus_reg)
+   return 0;
+
+   if (on && !da8xx_ohci->reg_enabled) {
+   ret = regulator_enable(da8xx_ohci->vbus_reg);
+   if (ret) {
+   dev_err(dev, "Failed to enable regulator: %d\n", ret);
+   return ret;
+   }
+   da8xx_ohci->reg_enabled = 1;
+
+   } else if (!on && da8xx_ohci->reg_enabled) {
+   ret = regulator_disable(da8xx_ohci->vbus_reg);
+   if (ret) {
+   dev_err(dev, "Failed  to disable regulator: %d\n", ret);
+   return ret;
+   }
+   da8xx_ohci->reg_enabled = 0;
+   }
+
return 0;
 }

 static int ohci_da8xx_get_power(struct usb_hcd *hcd)
 {
+   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
struct device *dev  = hcd->self.controller;
struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);

if (hub && hub->get_power)
return hub->get_power(1);

+   if (da8xx_ohci->vbus_reg)
+   return regulator_is_enabled(da8xx_ohci->vbus_reg);
+
return 1;
 }

 static int ohci_da8xx_get_oci(struct usb_hcd *hcd)
 {
+   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
struct device *dev  = hcd->self.controller;
struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
+   unsigned int flags;
+   int ret;

if (hub && hub->get_oci)
return hub->get_oci(1);

+   if (!da8xx_ohci->vbus_reg)
+   return 0;
+
+   ret = regulator_get_error_flags(da8xx_ohci->vbus_reg, &flags);
+   if (ret)
+   return ret;
+
+   if (flags & REGULATOR_ERROR_OVER_CURRENT)
+   return 1;
+
return 0;
 }

 static int ohci_da8xx_has_set_power(struct usb_hcd *hcd)
 {
+   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
struct device *dev  = hcd->self.controller;
struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);

if (hub && hub->set_power)
return 1;

+   if (da8xx_ohci->vbus_reg)
+   return 1;
+
return 0;
 }

 static int ohci_da8xx_has_oci(struct usb_hcd *hcd)
 {
+   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
struct device *dev  = hcd->self.controller;
struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);

if (hub && hub->get_oci)
return 1;

+   if (da8xx_ohci->vbus_reg)
+   return 1;
+
return 0;
 }

@@ -160,15 +212,41 @@ static void ohci_da8xx_ocic_handler(struct 
da8xx_ohci_root_hub *hub,
hub->set_power(port, 0);
 }

+static int ohci_da8xx_regulator_event(struct notifier_block *nb,
+   unsigned long event, void *data)
+{
+   struct da8xx_ohci_hcd *da8xx_ohci =
+   container_of(nb, struct da8xx_ohci_hcd, nb);
+   struct device *dev = da8xx_ohci->hcd->self.controller;
+
+   if (event & REGULATOR_EVENT_OVER_CURRENT) {
+   dev_warn(dev, "over current event

[PATCH v6 3/5] USB: ohci: da8xx: Allow a regulator to handle VBUS

2016-11-21 Thread Axel Haslam
Using a regulator to handle VBUS will eliminate the need for
platform data and callbacks, and make the driver more generic
allowing different types of regulators to handle VBUS.

The regulator equivalents to the platform callbacks are:
set_power   ->  regulator_enable/regulator_disable
get_power   ->  regulator_is_enabled
get_oci ->  regulator_get_error_flags
ocic_notify ->  regulator event notification

Signed-off-by: Axel Haslam 
---
 drivers/usb/host/ohci-da8xx.c | 97 +--
 1 file changed, 94 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index 90763ad..d0eb754 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -36,8 +37,12 @@ static int (*orig_ohci_hub_control)(struct usb_hcd  *hcd, 
u16 typeReq,
 static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf);
 
 struct da8xx_ohci_hcd {
+   struct usb_hcd *hcd;
struct clk *usb11_clk;
struct phy *usb11_phy;
+   struct regulator *vbus_reg;
+   struct notifier_block nb;
+   unsigned int reg_enabled;
 };
 
 #define to_da8xx_ohci(hcd) (struct da8xx_ohci_hcd *)(hcd_to_ohci(hcd)->priv)
@@ -83,56 +88,103 @@ static void ohci_da8xx_disable(struct usb_hcd *hcd)
 
 static int ohci_da8xx_set_power(struct usb_hcd *hcd, int on)
 {
+   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
struct device *dev  = hcd->self.controller;
struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
+   int ret;
 
if (hub && hub->set_power)
return hub->set_power(1, on);
 
+   if (!da8xx_ohci->vbus_reg)
+   return 0;
+
+   if (on && !da8xx_ohci->reg_enabled) {
+   ret = regulator_enable(da8xx_ohci->vbus_reg);
+   if (ret) {
+   dev_err(dev, "Failed to enable regulator: %d\n", ret);
+   return ret;
+   }
+   da8xx_ohci->reg_enabled = 1;
+
+   } else if (!on && da8xx_ohci->reg_enabled) {
+   ret = regulator_disable(da8xx_ohci->vbus_reg);
+   if (ret) {
+   dev_err(dev, "Failed  to disable regulator: %d\n", ret);
+   return ret;
+   }
+   da8xx_ohci->reg_enabled = 0;
+   }
+
return 0;
 }
 
 static int ohci_da8xx_get_power(struct usb_hcd *hcd)
 {
+   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
struct device *dev  = hcd->self.controller;
struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
 
if (hub && hub->get_power)
return hub->get_power(1);
 
+   if (da8xx_ohci->vbus_reg)
+   return regulator_is_enabled(da8xx_ohci->vbus_reg);
+
return 1;
 }
 
 static int ohci_da8xx_get_oci(struct usb_hcd *hcd)
 {
+   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
struct device *dev  = hcd->self.controller;
struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
+   unsigned int flags;
+   int ret;
 
if (hub && hub->get_oci)
return hub->get_oci(1);
 
+   if (!da8xx_ohci->vbus_reg)
+   return 0;
+
+   ret = regulator_get_error_flags(da8xx_ohci->vbus_reg, &flags);
+   if (ret)
+   return ret;
+
+   if (flags & REGULATOR_ERROR_OVER_CURRENT)
+   return 1;
+
return 0;
 }
 
 static int ohci_da8xx_has_set_power(struct usb_hcd *hcd)
 {
+   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
struct device *dev  = hcd->self.controller;
struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
 
if (hub && hub->set_power)
return 1;
 
+   if (da8xx_ohci->vbus_reg)
+   return 1;
+
return 0;
 }
 
 static int ohci_da8xx_has_oci(struct usb_hcd *hcd)
 {
+   struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
struct device *dev  = hcd->self.controller;
struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
 
if (hub && hub->get_oci)
return 1;
 
+   if (da8xx_ohci->vbus_reg)
+   return 1;
+
return 0;
 }
 
@@ -160,15 +212,41 @@ static void ohci_da8xx_ocic_handler(struct 
da8xx_ohci_root_hub *hub,
hub->set_power(port, 0);
 }
 
+static int ohci_da8xx_regulator_event(struct notifier_block *nb,
+   unsigned long event, void *data)
+{
+   struct da8xx_ohci_hcd *da8xx_ohci =
+   container_of(nb, struct da8xx_ohci_hcd, nb);
+   struct device *dev = da8xx_ohci->hcd->self.controller;
+
+   if (event & REGULATOR_EVENT_OVER_CURRENT) {
+   dev_warn(dev, "over current event\n");
+   ocic