Commit e44694e8 authored by Shinya Kuribayashi's avatar Shinya Kuribayashi Committed by Greg Kroah-Hartman

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: default avatarShinya Kuribayashi <shinya.kuribayashi.px@renesas.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent a6dc9cf7
...@@ -38,6 +38,7 @@ struct gpio_vbus_data { ...@@ -38,6 +38,7 @@ struct gpio_vbus_data {
int vbus_draw_enabled; int vbus_draw_enabled;
unsigned mA; unsigned mA;
struct delayed_work work; struct delayed_work work;
int vbus;
}; };
...@@ -96,18 +97,24 @@ static void gpio_vbus_work(struct work_struct *work) ...@@ -96,18 +97,24 @@ static void gpio_vbus_work(struct work_struct *work)
struct gpio_vbus_data *gpio_vbus = struct gpio_vbus_data *gpio_vbus =
container_of(work, struct gpio_vbus_data, work.work); container_of(work, struct gpio_vbus_data, work.work);
struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data; struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data;
int gpio, status; int gpio, status, vbus;
if (!gpio_vbus->phy.otg->gadget) if (!gpio_vbus->phy.otg->gadget)
return; 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 /* Peripheral controllers which manage the pullup themselves won't have
* gpio_pullup configured here. If it's configured here, we'll do what * gpio_pullup configured here. If it's configured here, we'll do what
* isp1301_omap::b_peripheral() does and enable the pullup here... although * isp1301_omap::b_peripheral() does and enable the pullup here... although
* that may complicate usb_gadget_{,dis}connect() support. * that may complicate usb_gadget_{,dis}connect() support.
*/ */
gpio = pdata->gpio_pullup; gpio = pdata->gpio_pullup;
if (is_vbus_powered(pdata)) {
if (vbus) {
status = USB_EVENT_VBUS; status = USB_EVENT_VBUS;
gpio_vbus->phy.state = OTG_STATE_B_PERIPHERAL; gpio_vbus->phy.state = OTG_STATE_B_PERIPHERAL;
gpio_vbus->phy.last_event = status; gpio_vbus->phy.last_event = status;
...@@ -195,6 +202,7 @@ static int gpio_vbus_set_peripheral(struct usb_otg *otg, ...@@ -195,6 +202,7 @@ static int gpio_vbus_set_peripheral(struct usb_otg *otg,
dev_dbg(&pdev->dev, "registered gadget '%s'\n", gadget->name); dev_dbg(&pdev->dev, "registered gadget '%s'\n", gadget->name);
/* initialize connection state */ /* initialize connection state */
gpio_vbus->vbus = 0; /* start with disconnected */
gpio_vbus_irq(irq, pdev); gpio_vbus_irq(irq, pdev);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment