On Sat, Dec 06, 2014 at 10:05:15PM +0100, Robert Jarzmik wrote: > Add support for vbus detection and power supply. This code is more or > less stolen from phy-gpio-vbus-usb.c, and aims at providing a detection > mechanism for VBus (ie. usb cable plug) based on a GPIO line, and a > power supply activation which draws current from the VBus. > > Signed-off-by: Robert Jarzmik <robert.jarzmik@xxxxxxx> > --- > Since v1: changed vbus-gpios to vbus-detect-gpio > --- > drivers/usb/phy/phy-generic.c | 91 ++++++++++++++++++++++++++++++++++++- > drivers/usb/phy/phy-generic.h | 6 +++ > include/linux/usb/usb_phy_generic.h | 2 + > 3 files changed, 98 insertions(+), 1 deletion(-) > > diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c > index 71e061d..f56a47b 100644 > --- a/drivers/usb/phy/phy-generic.c > +++ b/drivers/usb/phy/phy-generic.c > @@ -29,6 +29,7 @@ > #include <linux/module.h> > #include <linux/platform_device.h> > #include <linux/dma-mapping.h> > +#include <linux/usb/gadget.h> > #include <linux/usb/otg.h> > #include <linux/usb/usb_phy_generic.h> > #include <linux/slab.h> > @@ -41,6 +42,9 @@ > > #include "phy-generic.h" > > +#define VBUS_IRQ_FLAGS \ > + (IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING) > + > struct platform_device *usb_phy_generic_register(void) > { > return platform_device_register_simple("usb_phy_generic", > @@ -68,6 +72,73 @@ static void nop_reset_set(struct usb_phy_generic *nop, int asserted) > usleep_range(10000, 20000); > } > > +/* interface to regulator framework */ > +static void nop_set_vbus_draw(struct usb_phy_generic *nop, unsigned mA) > +{ > + struct regulator *vbus_draw = nop->vbus_draw; > + int enabled; > + int ret; > + > + if (!vbus_draw) > + return; > + > + enabled = nop->vbus_draw_enabled; > + if (mA) { > + regulator_set_current_limit(vbus_draw, 0, 1000 * mA); > + if (!enabled) { > + ret = regulator_enable(vbus_draw); > + if (ret < 0) > + return; > + nop->vbus_draw_enabled = 1; > + } > + } else { > + if (enabled) { > + ret = regulator_disable(vbus_draw); > + if (ret < 0) > + return; > + nop->vbus_draw_enabled = 0; > + } > + } > + nop->mA = mA; > +} > + > + > +static irqreturn_t nop_gpio_vbus_thread(int irq, void *data) > +{ > + struct usb_phy_generic *nop = data; > + struct usb_otg *otg = nop->phy.otg; > + int vbus, status; > + > + vbus = gpiod_get_value(nop->gpiod_vbus); > + if ((vbus ^ nop->vbus) == 0) > + return IRQ_HANDLED; > + nop->vbus = vbus; > + > + if (vbus) { > + status = USB_EVENT_VBUS; > + nop->phy.state = OTG_STATE_B_PERIPHERAL; > + nop->phy.last_event = status; > + usb_gadget_vbus_connect(otg->gadget); > + > + /* drawing a "unit load" is *always* OK, except for OTG */ > + nop_set_vbus_draw(nop, 100); > + > + atomic_notifier_call_chain(&nop->phy.notifier, status, > + otg->gadget); > + } else { > + nop_set_vbus_draw(nop, 0); > + > + usb_gadget_vbus_disconnect(otg->gadget); > + status = USB_EVENT_NONE; > + nop->phy.state = OTG_STATE_B_IDLE; broke build :-( I'll see if I can fix it myself this time as this was probably caused by something that went in during the merge window. cheers -- balbi
Attachment:
signature.asc
Description: Digital signature