aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAxel Haslam <ahaslam@baylibre.com>2016-11-23 13:06:47 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-11-29 11:31:35 -0500
commitc844ff74b04fe83245c908a8c92f0a7620b25c4c (patch)
treed690d68ad535aea91c8cb233f41f7ff492f7e876
parentf3c56fb39658a3f81ffe878628109075a023c935 (diff)
USB: ohci: da8xx: Allow a regulator to handle VBUS
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 <ahaslam@baylibre.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/host/ohci-da8xx.c96
1 files changed, 93 insertions, 3 deletions
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index 90763ad5c4eb..2b9cb2e67de3 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -20,6 +20,7 @@
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/phy/phy.h> 21#include <linux/phy/phy.h>
22#include <linux/platform_data/usb-davinci.h> 22#include <linux/platform_data/usb-davinci.h>
23#include <linux/regulator/consumer.h>
23#include <linux/usb.h> 24#include <linux/usb.h>
24#include <linux/usb/hcd.h> 25#include <linux/usb/hcd.h>
25#include <asm/unaligned.h> 26#include <asm/unaligned.h>
@@ -36,8 +37,12 @@ static int (*orig_ohci_hub_control)(struct usb_hcd *hcd, u16 typeReq,
36static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf); 37static int (*orig_ohci_hub_status_data)(struct usb_hcd *hcd, char *buf);
37 38
38struct da8xx_ohci_hcd { 39struct da8xx_ohci_hcd {
40 struct usb_hcd *hcd;
39 struct clk *usb11_clk; 41 struct clk *usb11_clk;
40 struct phy *usb11_phy; 42 struct phy *usb11_phy;
43 struct regulator *vbus_reg;
44 struct notifier_block nb;
45 unsigned int reg_enabled;
41}; 46};
42 47
43#define to_da8xx_ohci(hcd) (struct da8xx_ohci_hcd *)(hcd_to_ohci(hcd)->priv) 48#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)
83 88
84static int ohci_da8xx_set_power(struct usb_hcd *hcd, int on) 89static int ohci_da8xx_set_power(struct usb_hcd *hcd, int on)
85{ 90{
91 struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
86 struct device *dev = hcd->self.controller; 92 struct device *dev = hcd->self.controller;
87 struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); 93 struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
94 int ret;
88 95
89 if (hub && hub->set_power) 96 if (hub && hub->set_power)
90 return hub->set_power(1, on); 97 return hub->set_power(1, on);
91 98
99 if (!da8xx_ohci->vbus_reg)
100 return 0;
101
102 if (on && !da8xx_ohci->reg_enabled) {
103 ret = regulator_enable(da8xx_ohci->vbus_reg);
104 if (ret) {
105 dev_err(dev, "Failed to enable regulator: %d\n", ret);
106 return ret;
107 }
108 da8xx_ohci->reg_enabled = 1;
109
110 } else if (!on && da8xx_ohci->reg_enabled) {
111 ret = regulator_disable(da8xx_ohci->vbus_reg);
112 if (ret) {
113 dev_err(dev, "Failed to disable regulator: %d\n", ret);
114 return ret;
115 }
116 da8xx_ohci->reg_enabled = 0;
117 }
118
92 return 0; 119 return 0;
93} 120}
94 121
95static int ohci_da8xx_get_power(struct usb_hcd *hcd) 122static int ohci_da8xx_get_power(struct usb_hcd *hcd)
96{ 123{
124 struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
97 struct device *dev = hcd->self.controller; 125 struct device *dev = hcd->self.controller;
98 struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); 126 struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
99 127
100 if (hub && hub->get_power) 128 if (hub && hub->get_power)
101 return hub->get_power(1); 129 return hub->get_power(1);
102 130
131 if (da8xx_ohci->vbus_reg)
132 return regulator_is_enabled(da8xx_ohci->vbus_reg);
133
103 return 1; 134 return 1;
104} 135}
105 136
106static int ohci_da8xx_get_oci(struct usb_hcd *hcd) 137static int ohci_da8xx_get_oci(struct usb_hcd *hcd)
107{ 138{
139 struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
108 struct device *dev = hcd->self.controller; 140 struct device *dev = hcd->self.controller;
109 struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); 141 struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
142 unsigned int flags;
143 int ret;
110 144
111 if (hub && hub->get_oci) 145 if (hub && hub->get_oci)
112 return hub->get_oci(1); 146 return hub->get_oci(1);
113 147
148 if (!da8xx_ohci->vbus_reg)
149 return 0;
150
151 ret = regulator_get_error_flags(da8xx_ohci->vbus_reg, &flags);
152 if (ret)
153 return ret;
154
155 if (flags & REGULATOR_ERROR_OVER_CURRENT)
156 return 1;
157
114 return 0; 158 return 0;
115} 159}
116 160
117static int ohci_da8xx_has_set_power(struct usb_hcd *hcd) 161static int ohci_da8xx_has_set_power(struct usb_hcd *hcd)
118{ 162{
163 struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
119 struct device *dev = hcd->self.controller; 164 struct device *dev = hcd->self.controller;
120 struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); 165 struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
121 166
122 if (hub && hub->set_power) 167 if (hub && hub->set_power)
123 return 1; 168 return 1;
124 169
170 if (da8xx_ohci->vbus_reg)
171 return 1;
172
125 return 0; 173 return 0;
126} 174}
127 175
128static int ohci_da8xx_has_oci(struct usb_hcd *hcd) 176static int ohci_da8xx_has_oci(struct usb_hcd *hcd)
129{ 177{
178 struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
130 struct device *dev = hcd->self.controller; 179 struct device *dev = hcd->self.controller;
131 struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); 180 struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
132 181
133 if (hub && hub->get_oci) 182 if (hub && hub->get_oci)
134 return 1; 183 return 1;
135 184
185 if (da8xx_ohci->vbus_reg)
186 return 1;
187
136 return 0; 188 return 0;
137} 189}
138 190
@@ -160,15 +212,39 @@ static void ohci_da8xx_ocic_handler(struct da8xx_ohci_root_hub *hub,
160 hub->set_power(port, 0); 212 hub->set_power(port, 0);
161} 213}
162 214
215static int ohci_da8xx_regulator_event(struct notifier_block *nb,
216 unsigned long event, void *data)
217{
218 struct da8xx_ohci_hcd *da8xx_ohci =
219 container_of(nb, struct da8xx_ohci_hcd, nb);
220
221 if (event & REGULATOR_EVENT_OVER_CURRENT) {
222 ocic_mask |= 1 << 1;
223 ohci_da8xx_set_power(da8xx_ohci->hcd, 0);
224 }
225
226 return 0;
227}
228
163static int ohci_da8xx_register_notify(struct usb_hcd *hcd) 229static int ohci_da8xx_register_notify(struct usb_hcd *hcd)
164{ 230{
231 struct da8xx_ohci_hcd *da8xx_ohci = to_da8xx_ohci(hcd);
165 struct device *dev = hcd->self.controller; 232 struct device *dev = hcd->self.controller;
166 struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev); 233 struct da8xx_ohci_root_hub *hub = dev_get_platdata(dev);
234 int ret = 0;
235
236 if (hub && hub->ocic_notify) {
237 ret = hub->ocic_notify(ohci_da8xx_ocic_handler);
238 } else if (da8xx_ohci->vbus_reg) {
239 da8xx_ohci->nb.notifier_call = ohci_da8xx_regulator_event;
240 ret = devm_regulator_register_notifier(da8xx_ohci->vbus_reg,
241 &da8xx_ohci->nb);
242 }
167 243
168 if (hub && hub->ocic_notify) 244 if (ret)
169 return hub->ocic_notify(ohci_da8xx_ocic_handler); 245 dev_err(dev, "Failed to register notifier: %d\n", ret);
170 246
171 return 0; 247 return ret;
172} 248}
173 249
174static void ohci_da8xx_unregister_notify(struct usb_hcd *hcd) 250static void ohci_da8xx_unregister_notify(struct usb_hcd *hcd)
@@ -331,6 +407,7 @@ static int ohci_da8xx_probe(struct platform_device *pdev)
331 return -ENOMEM; 407 return -ENOMEM;
332 408
333 da8xx_ohci = to_da8xx_ohci(hcd); 409 da8xx_ohci = to_da8xx_ohci(hcd);
410 da8xx_ohci->hcd = hcd;
334 411
335 da8xx_ohci->usb11_clk = devm_clk_get(&pdev->dev, "usb11"); 412 da8xx_ohci->usb11_clk = devm_clk_get(&pdev->dev, "usb11");
336 if (IS_ERR(da8xx_ohci->usb11_clk)) { 413 if (IS_ERR(da8xx_ohci->usb11_clk)) {
@@ -348,6 +425,19 @@ static int ohci_da8xx_probe(struct platform_device *pdev)
348 goto err; 425 goto err;
349 } 426 }
350 427
428 da8xx_ohci->vbus_reg = devm_regulator_get_optional(&pdev->dev, "vbus");
429 if (IS_ERR(da8xx_ohci->vbus_reg)) {
430 error = PTR_ERR(da8xx_ohci->vbus_reg);
431 if (error == -ENODEV) {
432 da8xx_ohci->vbus_reg = NULL;
433 } else if (error == -EPROBE_DEFER) {
434 goto err;
435 } else {
436 dev_err(&pdev->dev, "Failed to get regulator\n");
437 goto err;
438 }
439 }
440
351 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 441 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
352 hcd->regs = devm_ioremap_resource(&pdev->dev, mem); 442 hcd->regs = devm_ioremap_resource(&pdev->dev, mem);
353 if (IS_ERR(hcd->regs)) { 443 if (IS_ERR(hcd->regs)) {