diff options
author | Shinya Kuribayashi <shinya.kuribayashi.px@renesas.com> | 2012-05-10 06:02:38 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-05-14 18:02:23 +0200 |
commit | e44694e858ed000ef11ee37861c7f7c86d8ddbda (patch) | |
tree | 76c8b6f7f5e9bff4413729e0cfe08c9ae00dcf25 /drivers/usb/otg | |
parent | USB: gpio_vbus: put a missing regulator_put() on error (diff) | |
download | linux-e44694e858ed000ef11ee37861c7f7c86d8ddbda.tar.xz linux-e44694e858ed000ef11ee37861c7f7c86d8ddbda.zip |
USB: gpio_vbus: avoid consecutive vbus_session calls with the same "is_active"
Basically, ->vbus_session() calls should be served when VBUS session
starts and ends (it's not whenever transciever drivers detect VBUS
_changes_). Otherwise, if UDC gadget drivers don't want for some
reason ->vbus_session() calls with the same "is_active" value, either
OTG or UDC drivers need to have some protection handlings.
Also, on platforms using this 'gpio_vbus' driver, the driver is only
allowed to check whether VBUS is applied. There is no kernel-standard
way prepared for UDC gadget drivers to do that.
With this in mind, gpio_vbus should try to prevent unnecessary
consecutive vbus_session calls being served with the same "in_active"
value.
Signed-off-by: Shinya Kuribayashi <shinya.kuribayashi.px@renesas.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/otg')
-rw-r--r-- | drivers/usb/otg/gpio_vbus.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c index ac962acfbb18..bd6e755dd3d8 100644 --- a/drivers/usb/otg/gpio_vbus.c +++ b/drivers/usb/otg/gpio_vbus.c @@ -38,6 +38,7 @@ struct gpio_vbus_data { int vbus_draw_enabled; unsigned mA; struct delayed_work work; + int vbus; }; @@ -96,18 +97,24 @@ static void gpio_vbus_work(struct work_struct *work) struct gpio_vbus_data *gpio_vbus = container_of(work, struct gpio_vbus_data, work.work); struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data; - int gpio, status; + int gpio, status, vbus; if (!gpio_vbus->phy.otg->gadget) return; + vbus = is_vbus_powered(pdata); + if ((vbus ^ gpio_vbus->vbus) == 0) + return; + gpio_vbus->vbus = vbus; + /* Peripheral controllers which manage the pullup themselves won't have * gpio_pullup configured here. If it's configured here, we'll do what * isp1301_omap::b_peripheral() does and enable the pullup here... although * that may complicate usb_gadget_{,dis}connect() support. */ gpio = pdata->gpio_pullup; - if (is_vbus_powered(pdata)) { + + if (vbus) { status = USB_EVENT_VBUS; gpio_vbus->phy.state = OTG_STATE_B_PERIPHERAL; gpio_vbus->phy.last_event = status; @@ -195,6 +202,7 @@ static int gpio_vbus_set_peripheral(struct usb_otg *otg, dev_dbg(&pdev->dev, "registered gadget '%s'\n", gadget->name); /* initialize connection state */ + gpio_vbus->vbus = 0; /* start with disconnected */ gpio_vbus_irq(irq, pdev); return 0; } |