aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/phy/phy-generic.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-02-04 14:03:20 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-02-04 14:03:20 -0500
commit4d4bac4499e9955521af80198063ef9c2f2bd634 (patch)
treeb02fb1f3d343d3a4a9864be18eec04e10f43d410 /drivers/usb/phy/phy-generic.c
parent7fa40910e0bf5ef32eca49595d950cb24f6402bf (diff)
parent9298b4aad37e8c6962edcdbd0b62620adb207d03 (diff)
Merge tag 'usb-for-v3.20' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
Felipe writes: usb: patches for v3.20 merge window Here's the big pull request for Gadgets and PHYs. It's a total of 217 non-merge commits with pretty much everything being touched. The most important bits are a ton of new documentation for almost all usb gadget functions, a new isp1760 UDC driver, several improvements to the old net2280 UDC driver, and some minor tracepoint improvements to dwc3. Other than that, a big list of minor cleanups, smaller bugfixes and new features all over the place. Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/phy/phy-generic.c')
-rw-r--r--drivers/usb/phy/phy-generic.c150
1 files changed, 110 insertions, 40 deletions
diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
index f1b719b45a53..70be50b734b2 100644
--- a/drivers/usb/phy/phy-generic.c
+++ b/drivers/usb/phy/phy-generic.c
@@ -27,6 +27,7 @@
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/platform_device.h> 28#include <linux/platform_device.h>
29#include <linux/dma-mapping.h> 29#include <linux/dma-mapping.h>
30#include <linux/usb/gadget.h>
30#include <linux/usb/otg.h> 31#include <linux/usb/otg.h>
31#include <linux/usb/usb_phy_generic.h> 32#include <linux/usb/usb_phy_generic.h>
32#include <linux/slab.h> 33#include <linux/slab.h>
@@ -39,6 +40,10 @@
39 40
40#include "phy-generic.h" 41#include "phy-generic.h"
41 42
43#define VBUS_IRQ_FLAGS \
44 (IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | \
45 IRQF_ONESHOT)
46
42struct platform_device *usb_phy_generic_register(void) 47struct platform_device *usb_phy_generic_register(void)
43{ 48{
44 return platform_device_register_simple("usb_phy_generic", 49 return platform_device_register_simple("usb_phy_generic",
@@ -59,19 +64,79 @@ static int nop_set_suspend(struct usb_phy *x, int suspend)
59 64
60static void nop_reset_set(struct usb_phy_generic *nop, int asserted) 65static void nop_reset_set(struct usb_phy_generic *nop, int asserted)
61{ 66{
62 int value; 67 if (!nop->gpiod_reset)
68 return;
69
70 gpiod_direction_output(nop->gpiod_reset, !asserted);
71 usleep_range(10000, 20000);
72 gpiod_set_value(nop->gpiod_reset, asserted);
73}
74
75/* interface to regulator framework */
76static void nop_set_vbus_draw(struct usb_phy_generic *nop, unsigned mA)
77{
78 struct regulator *vbus_draw = nop->vbus_draw;
79 int enabled;
80 int ret;
63 81
64 if (!gpio_is_valid(nop->gpio_reset)) 82 if (!vbus_draw)
65 return; 83 return;
66 84
67 value = asserted; 85 enabled = nop->vbus_draw_enabled;
68 if (nop->reset_active_low) 86 if (mA) {
69 value = !value; 87 regulator_set_current_limit(vbus_draw, 0, 1000 * mA);
88 if (!enabled) {
89 ret = regulator_enable(vbus_draw);
90 if (ret < 0)
91 return;
92 nop->vbus_draw_enabled = 1;
93 }
94 } else {
95 if (enabled) {
96 ret = regulator_disable(vbus_draw);
97 if (ret < 0)
98 return;
99 nop->vbus_draw_enabled = 0;
100 }
101 }
102 nop->mA = mA;
103}
104
105
106static irqreturn_t nop_gpio_vbus_thread(int irq, void *data)
107{
108 struct usb_phy_generic *nop = data;
109 struct usb_otg *otg = nop->phy.otg;
110 int vbus, status;
111
112 vbus = gpiod_get_value(nop->gpiod_vbus);
113 if ((vbus ^ nop->vbus) == 0)
114 return IRQ_HANDLED;
115 nop->vbus = vbus;
116
117 if (vbus) {
118 status = USB_EVENT_VBUS;
119 otg->state = OTG_STATE_B_PERIPHERAL;
120 nop->phy.last_event = status;
121 usb_gadget_vbus_connect(otg->gadget);
122
123 /* drawing a "unit load" is *always* OK, except for OTG */
124 nop_set_vbus_draw(nop, 100);
125
126 atomic_notifier_call_chain(&nop->phy.notifier, status,
127 otg->gadget);
128 } else {
129 nop_set_vbus_draw(nop, 0);
70 130
71 gpio_set_value_cansleep(nop->gpio_reset, value); 131 usb_gadget_vbus_disconnect(otg->gadget);
132 status = USB_EVENT_NONE;
133 otg->state = OTG_STATE_B_IDLE;
134 nop->phy.last_event = status;
72 135
73 if (!asserted) 136 atomic_notifier_call_chain(&nop->phy.notifier, status,
74 usleep_range(10000, 20000); 137 otg->gadget);
138 }
139 return IRQ_HANDLED;
75} 140}
76 141
77int usb_gen_phy_init(struct usb_phy *phy) 142int usb_gen_phy_init(struct usb_phy *phy)
@@ -143,36 +208,47 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop,
143 struct usb_phy_generic_platform_data *pdata) 208 struct usb_phy_generic_platform_data *pdata)
144{ 209{
145 enum usb_phy_type type = USB_PHY_TYPE_USB2; 210 enum usb_phy_type type = USB_PHY_TYPE_USB2;
146 int err; 211 int err = 0;
147 212
148 u32 clk_rate = 0; 213 u32 clk_rate = 0;
149 bool needs_vcc = false; 214 bool needs_vcc = false;
150 215
151 nop->reset_active_low = true; /* default behaviour */
152
153 if (dev->of_node) { 216 if (dev->of_node) {
154 struct device_node *node = dev->of_node; 217 struct device_node *node = dev->of_node;
155 enum of_gpio_flags flags = 0;
156 218
157 if (of_property_read_u32(node, "clock-frequency", &clk_rate)) 219 if (of_property_read_u32(node, "clock-frequency", &clk_rate))
158 clk_rate = 0; 220 clk_rate = 0;
159 221
160 needs_vcc = of_property_read_bool(node, "vcc-supply"); 222 needs_vcc = of_property_read_bool(node, "vcc-supply");
161 nop->gpio_reset = of_get_named_gpio_flags(node, "reset-gpios", 223 nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset");
162 0, &flags); 224 err = PTR_ERR_OR_ZERO(nop->gpiod_reset);
163 if (nop->gpio_reset == -EPROBE_DEFER) 225 if (!err) {
164 return -EPROBE_DEFER; 226 nop->gpiod_vbus = devm_gpiod_get_optional(dev,
165 227 "vbus-detect");
166 nop->reset_active_low = flags & OF_GPIO_ACTIVE_LOW; 228 err = PTR_ERR_OR_ZERO(nop->gpiod_vbus);
167 229 }
168 } else if (pdata) { 230 } else if (pdata) {
169 type = pdata->type; 231 type = pdata->type;
170 clk_rate = pdata->clk_rate; 232 clk_rate = pdata->clk_rate;
171 needs_vcc = pdata->needs_vcc; 233 needs_vcc = pdata->needs_vcc;
172 nop->gpio_reset = pdata->gpio_reset; 234 if (gpio_is_valid(pdata->gpio_reset)) {
173 } else { 235 err = devm_gpio_request_one(dev, pdata->gpio_reset, 0,
174 nop->gpio_reset = -1; 236 dev_name(dev));
237 if (!err)
238 nop->gpiod_reset =
239 gpio_to_desc(pdata->gpio_reset);
240 }
241 nop->gpiod_vbus = pdata->gpiod_vbus;
242 }
243
244 if (err == -EPROBE_DEFER)
245 return -EPROBE_DEFER;
246 if (err) {
247 dev_err(dev, "Error requesting RESET or VBUS GPIO\n");
248 return err;
175 } 249 }
250 if (nop->gpiod_reset)
251 gpiod_direction_output(nop->gpiod_reset, 1);
176 252
177 nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg), 253 nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg),
178 GFP_KERNEL); 254 GFP_KERNEL);
@@ -201,24 +277,6 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop,
201 return -EPROBE_DEFER; 277 return -EPROBE_DEFER;
202 } 278 }
203 279
204 if (gpio_is_valid(nop->gpio_reset)) {
205 unsigned long gpio_flags;
206
207 /* Assert RESET */
208 if (nop->reset_active_low)
209 gpio_flags = GPIOF_OUT_INIT_LOW;
210 else
211 gpio_flags = GPIOF_OUT_INIT_HIGH;
212
213 err = devm_gpio_request_one(dev, nop->gpio_reset,
214 gpio_flags, dev_name(dev));
215 if (err) {
216 dev_err(dev, "Error requesting RESET GPIO %d\n",
217 nop->gpio_reset);
218 return err;
219 }
220 }
221
222 nop->dev = dev; 280 nop->dev = dev;
223 nop->phy.dev = nop->dev; 281 nop->phy.dev = nop->dev;
224 nop->phy.label = "nop-xceiv"; 282 nop->phy.label = "nop-xceiv";
@@ -247,6 +305,18 @@ static int usb_phy_generic_probe(struct platform_device *pdev)
247 err = usb_phy_gen_create_phy(dev, nop, dev_get_platdata(&pdev->dev)); 305 err = usb_phy_gen_create_phy(dev, nop, dev_get_platdata(&pdev->dev));
248 if (err) 306 if (err)
249 return err; 307 return err;
308 if (nop->gpiod_vbus) {
309 err = devm_request_threaded_irq(&pdev->dev,
310 gpiod_to_irq(nop->gpiod_vbus),
311 NULL, nop_gpio_vbus_thread,
312 VBUS_IRQ_FLAGS, "vbus_detect",
313 nop);
314 if (err) {
315 dev_err(&pdev->dev, "can't request irq %i, err: %d\n",
316 gpiod_to_irq(nop->gpiod_vbus), err);
317 return err;
318 }
319 }
250 320
251 nop->phy.init = usb_gen_phy_init; 321 nop->phy.init = usb_gen_phy_init;
252 nop->phy.shutdown = usb_gen_phy_shutdown; 322 nop->phy.shutdown = usb_gen_phy_shutdown;