diff options
author | Sean Anderson <sean.anderson@seco.com> | 2024-01-23 17:51:10 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2024-01-27 17:37:22 -0800 |
commit | 562898808cb17fdea92953e6a69c193b783d7b3f (patch) | |
tree | b82a9482056c57023cda7e3bd57ffb5bbb4358df /drivers/usb/phy | |
parent | 75fd6485cccef269ac9eb3b71cf56753341195ef (diff) |
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: Sean Anderson <sean.anderson@seco.com>
Link: https://lore.kernel.org/r/20240123225111.1629405-4-sean.anderson@seco.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/phy')
-rw-r--r-- | drivers/usb/phy/phy-generic.c | 45 |
1 files changed, 17 insertions, 28 deletions
diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c index 16494030209e..f7db24b5ed5c 100644 --- a/drivers/usb/phy/phy-generic.c +++ b/drivers/usb/phy/phy-generic.c @@ -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; } |