Commit 56289880 authored by Sean Anderson's avatar Sean Anderson Committed by Greg Kroah-Hartman
Browse files

usb: phy: generic: Implement otg->set_vbus



Some USB controller drivers call otg_set_vbus when entering host or
device mode. Implement this callback so that VBUS can be turned on and
off automatically. This is especially useful when there is no property
for a VBUS supply in the controller's binding.

This results in a change in semantics of the vbus_draw regulator.
Whereas before it represented the VBUS supplied by an A-Device when we
acted as a B-Device, now it represents an internal VBUS source.
Accordingly, we no longer set the current limit or enable/disable the
bus from nop_gpio_vbus_thread. Because this supply was never initialized
before the previous commit, there should be no change in behavior.

Signed-off-by: default avatarSean Anderson <sean.anderson@seco.com>
Link: https://lore.kernel.org/r/20240123225111.1629405-4-sean.anderson@seco.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 75fd6485
Loading
Loading
Loading
Loading
+17 −28
Original line number Diff line number Diff line
@@ -74,33 +74,26 @@ static void nop_reset(struct usb_phy_generic *nop)
}

/* interface to regulator framework */
static void nop_set_vbus_draw(struct usb_phy_generic *nop, unsigned mA)
static int nop_set_vbus(struct usb_otg *otg, bool enable)
{
	struct regulator *vbus_draw = nop->vbus_draw;
	int enabled;
	int ret;
	int ret = 0;
	struct usb_phy_generic *nop = dev_get_drvdata(otg->usb_phy->dev);

	if (!vbus_draw)
		return;
	if (!nop->vbus_draw)
		return 0;

	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;
		}
	if (enable && !nop->vbus_draw_enabled) {
		ret = regulator_enable(nop->vbus_draw);
		if (ret)
			nop->vbus_draw_enabled = false;
		else
			nop->vbus_draw_enabled = true;

	} else if (!enable && nop->vbus_draw_enabled) {
		ret = regulator_disable(nop->vbus_draw);
		nop->vbus_draw_enabled = false;
	}
	nop->mA = mA;
	return ret;
}


@@ -120,14 +113,9 @@ static irqreturn_t nop_gpio_vbus_thread(int irq, void *data)
		otg->state = OTG_STATE_B_PERIPHERAL;
		nop->phy.last_event = status;

		/* 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);

		status = USB_EVENT_NONE;
		otg->state = OTG_STATE_B_IDLE;
		nop->phy.last_event = status;
@@ -291,6 +279,7 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop)
	nop->phy.otg->usb_phy		= &nop->phy;
	nop->phy.otg->set_host		= nop_set_host;
	nop->phy.otg->set_peripheral	= nop_set_peripheral;
	nop->phy.otg->set_vbus          = nop_set_vbus;

	return 0;
}