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 = dev_get_platdata(gpio_vbus->dev);
	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 (vbus) {
		status = USB_EVENT_VBUS;
		gpio_vbus->phy.otg->state = OTG_STATE_B_PERIPHERAL;
		gpio_vbus->phy.last_event = status;
		usb_gadget_vbus_connect(gpio_vbus->phy.otg->gadget);

		/* drawing a "unit load" is *always* OK, except for OTG */
		set_vbus_draw(gpio_vbus, 100);

		/* optionally enable D+ pullup */
		if (gpio_is_valid(gpio))
			gpio_set_value(gpio, !pdata->gpio_pullup_inverted);

		atomic_notifier_call_chain(&gpio_vbus->phy.notifier,
					   status, gpio_vbus->phy.otg->gadget);
	} else {
		/* optionally disable D+ pullup */
		if (gpio_is_valid(gpio))
			gpio_set_value(gpio, pdata->gpio_pullup_inverted);

		set_vbus_draw(gpio_vbus, 0);

		usb_gadget_vbus_disconnect(gpio_vbus->phy.otg->gadget);
		status = USB_EVENT_NONE;
		gpio_vbus->phy.otg->state = OTG_STATE_B_IDLE;
		gpio_vbus->phy.last_event = status;

		atomic_notifier_call_chain(&gpio_vbus->phy.notifier,
					   status, gpio_vbus->phy.otg->gadget);
	}
}
/* VBUS change IRQ handler */
static irqreturn_t gpio_vbus_irq(int irq, void *data)
{
	struct platform_device *pdev = data;
	struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data;
	struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev);
	int gpio, vbus;

	vbus = gpio_get_value(pdata->gpio_vbus);
	if (pdata->gpio_vbus_inverted)
		vbus = !vbus;

	dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n",
		vbus ? "supplied" : "inactive",
		gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none");

	if (!gpio_vbus->otg.gadget)
		return IRQ_HANDLED;

	/* 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 (vbus) {
		gpio_vbus->otg.state = OTG_STATE_B_PERIPHERAL;
		usb_gadget_vbus_connect(gpio_vbus->otg.gadget);

		/* drawing a "unit load" is *always* OK, except for OTG */
		set_vbus_draw(gpio_vbus, 100);

		/* optionally enable D+ pullup */
		if (gpio_is_valid(gpio))
			gpio_set_value(gpio, !pdata->gpio_pullup_inverted);
	} else {
		/* optionally disable D+ pullup */
		if (gpio_is_valid(gpio))
			gpio_set_value(gpio, pdata->gpio_pullup_inverted);

		set_vbus_draw(gpio_vbus, 0);

		usb_gadget_vbus_disconnect(gpio_vbus->otg.gadget);
		gpio_vbus->otg.state = OTG_STATE_B_IDLE;
	}

	return IRQ_HANDLED;
}
Exemple #3
0
/* effective for B devices, ignored for A-peripheral */
static int gpio_vbus_set_power(struct otg_transceiver *otg, unsigned mA)
{
	struct gpio_vbus_data *gpio_vbus;

	gpio_vbus = container_of(otg, struct gpio_vbus_data, otg);

	if (otg->state == OTG_STATE_B_PERIPHERAL)
		set_vbus_draw(gpio_vbus, mA);
	return 0;
}
Exemple #4
0
/* effective for B devices, ignored for A-peripheral */
static int gpio_vbus_set_power(struct usb_phy *phy, unsigned mA)
{
	struct gpio_vbus_data *gpio_vbus;

	gpio_vbus = container_of(phy, struct gpio_vbus_data, phy);

	if (phy->state == OTG_STATE_B_PERIPHERAL)
		set_vbus_draw(gpio_vbus, mA);
	return 0;
}
Exemple #5
0
static void gpio_vbus_work(struct work_struct *work)
{
	struct gpio_vbus_data *gpio_vbus =
		container_of(work, struct gpio_vbus_data, work);
	struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data;
	int gpio;

	if (!gpio_vbus->otg.gadget)
		return;

	/* 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)) {
		gpio_vbus->otg.state = OTG_STATE_B_PERIPHERAL;
		usb_gadget_vbus_connect(gpio_vbus->otg.gadget);

		/* drawing a "unit load" is *always* OK, except for OTG */
		set_vbus_draw(gpio_vbus, 100);

		/* optionally enable D+ pullup */
		if (gpio_is_valid(gpio))
			gpio_set_value(gpio, !pdata->gpio_pullup_inverted);
	} else {
		/* optionally disable D+ pullup */
		if (gpio_is_valid(gpio))
			gpio_set_value(gpio, pdata->gpio_pullup_inverted);

		set_vbus_draw(gpio_vbus, 0);

		usb_gadget_vbus_disconnect(gpio_vbus->otg.gadget);
		gpio_vbus->otg.state = OTG_STATE_B_IDLE;
	}
}
Exemple #6
0
/* bind/unbind the peripheral controller */
static int gpio_vbus_set_peripheral(struct otg_transceiver *otg,
				struct usb_gadget *gadget)
{
	struct gpio_vbus_data *gpio_vbus;
	struct gpio_vbus_mach_info *pdata;
	struct platform_device *pdev;
	int gpio, irq;

	gpio_vbus = container_of(otg, struct gpio_vbus_data, otg);
	pdev = to_platform_device(gpio_vbus->dev);
	pdata = gpio_vbus->dev->platform_data;
	irq = gpio_to_irq(pdata->gpio_vbus);
	gpio = pdata->gpio_pullup;

	if (!gadget) {
		dev_dbg(&pdev->dev, "unregistering gadget '%s'\n",
			otg->gadget->name);

		/* optionally disable D+ pullup */
		if (gpio_is_valid(gpio))
			gpio_set_value(gpio, pdata->gpio_pullup_inverted);

		set_vbus_draw(gpio_vbus, 0);

		usb_gadget_vbus_disconnect(otg->gadget);
		otg->state = OTG_STATE_UNDEFINED;

		otg->gadget = NULL;
		return 0;
	}

	otg->gadget = gadget;
	dev_dbg(&pdev->dev, "registered gadget '%s'\n", gadget->name);

	/* initialize connection state */
	gpio_vbus_irq(irq, pdev);
	return 0;
}