aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/otg
diff options
context:
space:
mode:
authorRobert Jarzmik <robert.jarzmik@free.fr>2009-01-25 02:54:31 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-03-24 19:20:26 -0400
commitc2344f13b59e007d782a3e591ebc551bc583a8b7 (patch)
tree17eda364b35d5c064c47e45b50487912844a0fa3 /drivers/usb/otg
parentdd44be6b17ac52238aa6c7f46b906d9fb76e7052 (diff)
USB: gpio_vbus: add delayed vbus_session calls
Call usb_gadget_vbus_connect() and ...disconnect() from a workqueue rather than from an irq handler, allowing msleep() calls in vbus_session. Update kerneldoc to match. [ dbrownell@users.sourceforge.net: more kerneldoc updates ] Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr> Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/otg')
-rw-r--r--drivers/usb/otg/gpio_vbus.c42
1 files changed, 31 insertions, 11 deletions
diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c
index 63a6036f04be..1c26c94513e9 100644
--- a/drivers/usb/otg/gpio_vbus.c
+++ b/drivers/usb/otg/gpio_vbus.c
@@ -13,6 +13,7 @@
13#include <linux/gpio.h> 13#include <linux/gpio.h>
14#include <linux/interrupt.h> 14#include <linux/interrupt.h>
15#include <linux/usb.h> 15#include <linux/usb.h>
16#include <linux/workqueue.h>
16 17
17#include <linux/regulator/consumer.h> 18#include <linux/regulator/consumer.h>
18 19
@@ -34,6 +35,7 @@ struct gpio_vbus_data {
34 struct regulator *vbus_draw; 35 struct regulator *vbus_draw;
35 int vbus_draw_enabled; 36 int vbus_draw_enabled;
36 unsigned mA; 37 unsigned mA;
38 struct work_struct work;
37}; 39};
38 40
39 41
@@ -76,24 +78,26 @@ static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA)
76 gpio_vbus->mA = mA; 78 gpio_vbus->mA = mA;
77} 79}
78 80
79/* VBUS change IRQ handler */ 81static int is_vbus_powered(struct gpio_vbus_mach_info *pdata)
80static irqreturn_t gpio_vbus_irq(int irq, void *data)
81{ 82{
82 struct platform_device *pdev = data; 83 int vbus;
83 struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
84 struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
85 int gpio, vbus;
86 84
87 vbus = gpio_get_value(pdata->gpio_vbus); 85 vbus = gpio_get_value(pdata->gpio_vbus);
88 if (pdata->gpio_vbus_inverted) 86 if (pdata->gpio_vbus_inverted)
89 vbus = !vbus; 87 vbus = !vbus;
90 88
91 dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n", 89 return vbus;
92 vbus ? "supplied" : "inactive", 90}
93 gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none"); 91
92static void gpio_vbus_work(struct work_struct *work)
93{
94 struct gpio_vbus_data *gpio_vbus =
95 container_of(work, struct gpio_vbus_data, work);
96 struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data;
97 int gpio;
94 98
95 if (!gpio_vbus->otg.gadget) 99 if (!gpio_vbus->otg.gadget)
96 return IRQ_HANDLED; 100 return;
97 101
98 /* Peripheral controllers which manage the pullup themselves won't have 102 /* Peripheral controllers which manage the pullup themselves won't have
99 * gpio_pullup configured here. If it's configured here, we'll do what 103 * gpio_pullup configured here. If it's configured here, we'll do what
@@ -101,7 +105,7 @@ static irqreturn_t gpio_vbus_irq(int irq, void *data)
101 * that may complicate usb_gadget_{,dis}connect() support. 105 * that may complicate usb_gadget_{,dis}connect() support.
102 */ 106 */
103 gpio = pdata->gpio_pullup; 107 gpio = pdata->gpio_pullup;
104 if (vbus) { 108 if (is_vbus_powered(pdata)) {
105 gpio_vbus->otg.state = OTG_STATE_B_PERIPHERAL; 109 gpio_vbus->otg.state = OTG_STATE_B_PERIPHERAL;
106 usb_gadget_vbus_connect(gpio_vbus->otg.gadget); 110 usb_gadget_vbus_connect(gpio_vbus->otg.gadget);
107 111
@@ -121,6 +125,21 @@ static irqreturn_t gpio_vbus_irq(int irq, void *data)
121 usb_gadget_vbus_disconnect(gpio_vbus->otg.gadget); 125 usb_gadget_vbus_disconnect(gpio_vbus->otg.gadget);
122 gpio_vbus->otg.state = OTG_STATE_B_IDLE; 126 gpio_vbus->otg.state = OTG_STATE_B_IDLE;
123 } 127 }
128}
129
130/* VBUS change IRQ handler */
131static irqreturn_t gpio_vbus_irq(int irq, void *data)
132{
133 struct platform_device *pdev = data;
134 struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
135 struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
136
137 dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n",
138 is_vbus_powered(pdata) ? "supplied" : "inactive",
139 gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none");
140
141 if (gpio_vbus->otg.gadget)
142 schedule_work(&gpio_vbus->work);
124 143
125 return IRQ_HANDLED; 144 return IRQ_HANDLED;
126} 145}
@@ -257,6 +276,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev)
257 irq, err); 276 irq, err);
258 goto err_irq; 277 goto err_irq;
259 } 278 }
279 INIT_WORK(&gpio_vbus->work, gpio_vbus_work);
260 280
261 /* only active when a gadget is registered */ 281 /* only active when a gadget is registered */
262 err = otg_set_transceiver(&gpio_vbus->otg); 282 err = otg_set_transceiver(&gpio_vbus->otg);