• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/usb/otg/
1/*
2 * gpio-vbus.c - simple GPIO VBUS sensing driver for B peripheral devices
3 *
4 * Copyright (c) 2008 Philipp Zabel <philipp.zabel@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/kernel.h>
12#include <linux/platform_device.h>
13#include <linux/gpio.h>
14#include <linux/slab.h>
15#include <linux/interrupt.h>
16#include <linux/usb.h>
17#include <linux/workqueue.h>
18
19#include <linux/regulator/consumer.h>
20
21#include <linux/usb/gadget.h>
22#include <linux/usb/gpio_vbus.h>
23#include <linux/usb/otg.h>
24
25
26/*
27 * A simple GPIO VBUS sensing driver for B peripheral only devices
28 * with internal transceivers. It can control a D+ pullup GPIO and
29 * a regulator to limit the current drawn from VBUS.
30 *
31 * Needs to be loaded before the UDC driver that will use it.
32 */
33struct gpio_vbus_data {
34	struct otg_transceiver otg;
35	struct device          *dev;
36	struct regulator       *vbus_draw;
37	int			vbus_draw_enabled;
38	unsigned		mA;
39	struct work_struct	work;
40};
41
42
43/*
44 * This driver relies on "both edges" triggering.  VBUS has 100 msec to
45 * stabilize, so the peripheral controller driver may need to cope with
46 * some bouncing due to current surges (e.g. charging local capacitance)
47 * and contact chatter.
48 *
49 * REVISIT in desperate straits, toggling between rising and falling
50 * edges might be workable.
51 */
52#define VBUS_IRQ_FLAGS \
53	( IRQF_SAMPLE_RANDOM | IRQF_SHARED \
54	| IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING )
55
56
57/* interface to regulator framework */
58static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA)
59{
60	struct regulator *vbus_draw = gpio_vbus->vbus_draw;
61	int enabled;
62
63	if (!vbus_draw)
64		return;
65
66	enabled = gpio_vbus->vbus_draw_enabled;
67	if (mA) {
68		regulator_set_current_limit(vbus_draw, 0, 1000 * mA);
69		if (!enabled) {
70			regulator_enable(vbus_draw);
71			gpio_vbus->vbus_draw_enabled = 1;
72		}
73	} else {
74		if (enabled) {
75			regulator_disable(vbus_draw);
76			gpio_vbus->vbus_draw_enabled = 0;
77		}
78	}
79	gpio_vbus->mA = mA;
80}
81
82static int is_vbus_powered(struct gpio_vbus_mach_info *pdata)
83{
84	int vbus;
85
86	vbus = gpio_get_value(pdata->gpio_vbus);
87	if (pdata->gpio_vbus_inverted)
88		vbus = !vbus;
89
90	return vbus;
91}
92
93static void gpio_vbus_work(struct work_struct *work)
94{
95	struct gpio_vbus_data *gpio_vbus =
96		container_of(work, struct gpio_vbus_data, work);
97	struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data;
98	int gpio;
99
100	if (!gpio_vbus->otg.gadget)
101		return;
102
103	/* Peripheral controllers which manage the pullup themselves won't have
104	 * gpio_pullup configured here.  If it's configured here, we'll do what
105	 * isp1301_omap::b_peripheral() does and enable the pullup here... although
106	 * that may complicate usb_gadget_{,dis}connect() support.
107	 */
108	gpio = pdata->gpio_pullup;
109	if (is_vbus_powered(pdata)) {
110		gpio_vbus->otg.state = OTG_STATE_B_PERIPHERAL;
111		usb_gadget_vbus_connect(gpio_vbus->otg.gadget);
112
113		/* drawing a "unit load" is *always* OK, except for OTG */
114		set_vbus_draw(gpio_vbus, 100);
115
116		/* optionally enable D+ pullup */
117		if (gpio_is_valid(gpio))
118			gpio_set_value(gpio, !pdata->gpio_pullup_inverted);
119	} else {
120		/* optionally disable D+ pullup */
121		if (gpio_is_valid(gpio))
122			gpio_set_value(gpio, pdata->gpio_pullup_inverted);
123
124		set_vbus_draw(gpio_vbus, 0);
125
126		usb_gadget_vbus_disconnect(gpio_vbus->otg.gadget);
127		gpio_vbus->otg.state = OTG_STATE_B_IDLE;
128	}
129}
130
131/* VBUS change IRQ handler */
132static irqreturn_t gpio_vbus_irq(int irq, void *data)
133{
134	struct platform_device *pdev = data;
135	struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
136	struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
137
138	dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n",
139		is_vbus_powered(pdata) ? "supplied" : "inactive",
140		gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none");
141
142	if (gpio_vbus->otg.gadget)
143		schedule_work(&gpio_vbus->work);
144
145	return IRQ_HANDLED;
146}
147
148/* OTG transceiver interface */
149
150/* bind/unbind the peripheral controller */
151static int gpio_vbus_set_peripheral(struct otg_transceiver *otg,
152				struct usb_gadget *gadget)
153{
154	struct gpio_vbus_data *gpio_vbus;
155	struct gpio_vbus_mach_info *pdata;
156	struct platform_device *pdev;
157	int gpio, irq;
158
159	gpio_vbus = container_of(otg, struct gpio_vbus_data, otg);
160	pdev = to_platform_device(gpio_vbus->dev);
161	pdata = gpio_vbus->dev->platform_data;
162	irq = gpio_to_irq(pdata->gpio_vbus);
163	gpio = pdata->gpio_pullup;
164
165	if (!gadget) {
166		dev_dbg(&pdev->dev, "unregistering gadget '%s'\n",
167			otg->gadget->name);
168
169		/* optionally disable D+ pullup */
170		if (gpio_is_valid(gpio))
171			gpio_set_value(gpio, pdata->gpio_pullup_inverted);
172
173		set_vbus_draw(gpio_vbus, 0);
174
175		usb_gadget_vbus_disconnect(otg->gadget);
176		otg->state = OTG_STATE_UNDEFINED;
177
178		otg->gadget = NULL;
179		return 0;
180	}
181
182	otg->gadget = gadget;
183	dev_dbg(&pdev->dev, "registered gadget '%s'\n", gadget->name);
184
185	/* initialize connection state */
186	gpio_vbus_irq(irq, pdev);
187	return 0;
188}
189
190/* effective for B devices, ignored for A-peripheral */
191static int gpio_vbus_set_power(struct otg_transceiver *otg, unsigned mA)
192{
193	struct gpio_vbus_data *gpio_vbus;
194
195	gpio_vbus = container_of(otg, struct gpio_vbus_data, otg);
196
197	if (otg->state == OTG_STATE_B_PERIPHERAL)
198		set_vbus_draw(gpio_vbus, mA);
199	return 0;
200}
201
202/* for non-OTG B devices: set/clear transceiver suspend mode */
203static int gpio_vbus_set_suspend(struct otg_transceiver *otg, int suspend)
204{
205	struct gpio_vbus_data *gpio_vbus;
206
207	gpio_vbus = container_of(otg, struct gpio_vbus_data, otg);
208
209	/* draw max 0 mA from vbus in suspend mode; or the previously
210	 * recorded amount of current if not suspended
211	 *
212	 * NOTE: high powered configs (mA > 100) may draw up to 2.5 mA
213	 * if they're wake-enabled ... we don't handle that yet.
214	 */
215	return gpio_vbus_set_power(otg, suspend ? 0 : gpio_vbus->mA);
216}
217
218/* platform driver interface */
219
220static int __init gpio_vbus_probe(struct platform_device *pdev)
221{
222	struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
223	struct gpio_vbus_data *gpio_vbus;
224	struct resource *res;
225	int err, gpio, irq;
226
227	if (!pdata || !gpio_is_valid(pdata->gpio_vbus))
228		return -EINVAL;
229	gpio = pdata->gpio_vbus;
230
231	gpio_vbus = kzalloc(sizeof(struct gpio_vbus_data), GFP_KERNEL);
232	if (!gpio_vbus)
233		return -ENOMEM;
234
235	platform_set_drvdata(pdev, gpio_vbus);
236	gpio_vbus->dev = &pdev->dev;
237	gpio_vbus->otg.label = "gpio-vbus";
238	gpio_vbus->otg.state = OTG_STATE_UNDEFINED;
239	gpio_vbus->otg.set_peripheral = gpio_vbus_set_peripheral;
240	gpio_vbus->otg.set_power = gpio_vbus_set_power;
241	gpio_vbus->otg.set_suspend = gpio_vbus_set_suspend;
242
243	err = gpio_request(gpio, "vbus_detect");
244	if (err) {
245		dev_err(&pdev->dev, "can't request vbus gpio %d, err: %d\n",
246			gpio, err);
247		goto err_gpio;
248	}
249	gpio_direction_input(gpio);
250
251	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
252	if (res) {
253		irq = res->start;
254		res->flags &= IRQF_TRIGGER_MASK;
255		res->flags |= IRQF_SAMPLE_RANDOM | IRQF_SHARED;
256	} else
257		irq = gpio_to_irq(gpio);
258
259	/* if data line pullup is in use, initialize it to "not pulling up" */
260	gpio = pdata->gpio_pullup;
261	if (gpio_is_valid(gpio)) {
262		err = gpio_request(gpio, "udc_pullup");
263		if (err) {
264			dev_err(&pdev->dev,
265				"can't request pullup gpio %d, err: %d\n",
266				gpio, err);
267			gpio_free(pdata->gpio_vbus);
268			goto err_gpio;
269		}
270		gpio_direction_output(gpio, pdata->gpio_pullup_inverted);
271	}
272
273	err = request_irq(irq, gpio_vbus_irq, VBUS_IRQ_FLAGS,
274		"vbus_detect", pdev);
275	if (err) {
276		dev_err(&pdev->dev, "can't request irq %i, err: %d\n",
277			irq, err);
278		goto err_irq;
279	}
280	INIT_WORK(&gpio_vbus->work, gpio_vbus_work);
281
282	/* only active when a gadget is registered */
283	err = otg_set_transceiver(&gpio_vbus->otg);
284	if (err) {
285		dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
286			err);
287		goto err_otg;
288	}
289
290	gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw");
291	if (IS_ERR(gpio_vbus->vbus_draw)) {
292		dev_dbg(&pdev->dev, "can't get vbus_draw regulator, err: %ld\n",
293			PTR_ERR(gpio_vbus->vbus_draw));
294		gpio_vbus->vbus_draw = NULL;
295	}
296
297	return 0;
298err_otg:
299	free_irq(irq, &pdev->dev);
300err_irq:
301	if (gpio_is_valid(pdata->gpio_pullup))
302		gpio_free(pdata->gpio_pullup);
303	gpio_free(pdata->gpio_vbus);
304err_gpio:
305	platform_set_drvdata(pdev, NULL);
306	kfree(gpio_vbus);
307	return err;
308}
309
310static int __exit gpio_vbus_remove(struct platform_device *pdev)
311{
312	struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
313	struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
314	int gpio = pdata->gpio_vbus;
315
316	regulator_put(gpio_vbus->vbus_draw);
317
318	otg_set_transceiver(NULL);
319
320	free_irq(gpio_to_irq(gpio), &pdev->dev);
321	if (gpio_is_valid(pdata->gpio_pullup))
322		gpio_free(pdata->gpio_pullup);
323	gpio_free(gpio);
324	platform_set_drvdata(pdev, NULL);
325	kfree(gpio_vbus);
326
327	return 0;
328}
329
330/* NOTE:  the gpio-vbus device may *NOT* be hotplugged */
331
332MODULE_ALIAS("platform:gpio-vbus");
333
334static struct platform_driver gpio_vbus_driver = {
335	.driver = {
336		.name  = "gpio-vbus",
337		.owner = THIS_MODULE,
338	},
339	.remove  = __exit_p(gpio_vbus_remove),
340};
341
342static int __init gpio_vbus_init(void)
343{
344	return platform_driver_probe(&gpio_vbus_driver, gpio_vbus_probe);
345}
346module_init(gpio_vbus_init);
347
348static void __exit gpio_vbus_exit(void)
349{
350	platform_driver_unregister(&gpio_vbus_driver);
351}
352module_exit(gpio_vbus_exit);
353
354MODULE_DESCRIPTION("simple GPIO controlled OTG transceiver driver");
355MODULE_AUTHOR("Philipp Zabel");
356MODULE_LICENSE("GPL");
357