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>
This commit is contained in:
parent
a6dc9cf76b
commit
e44694e858
@ -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)
|
|||||||
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,
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user