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>
This commit is contained in:
parent
75fd6485cc
commit
562898808c
@ -74,33 +74,26 @@ static void nop_reset(struct usb_phy_generic *nop)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* interface to regulator framework */
|
/* 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 ret = 0;
|
||||||
int enabled;
|
struct usb_phy_generic *nop = dev_get_drvdata(otg->usb_phy->dev);
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (!vbus_draw)
|
if (!nop->vbus_draw)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
enabled = nop->vbus_draw_enabled;
|
if (enable && !nop->vbus_draw_enabled) {
|
||||||
if (mA) {
|
ret = regulator_enable(nop->vbus_draw);
|
||||||
regulator_set_current_limit(vbus_draw, 0, 1000 * mA);
|
if (ret)
|
||||||
if (!enabled) {
|
nop->vbus_draw_enabled = false;
|
||||||
ret = regulator_enable(vbus_draw);
|
else
|
||||||
if (ret < 0)
|
nop->vbus_draw_enabled = true;
|
||||||
return;
|
|
||||||
nop->vbus_draw_enabled = 1;
|
} else if (!enable && nop->vbus_draw_enabled) {
|
||||||
}
|
ret = regulator_disable(nop->vbus_draw);
|
||||||
} else {
|
nop->vbus_draw_enabled = false;
|
||||||
if (enabled) {
|
|
||||||
ret = regulator_disable(vbus_draw);
|
|
||||||
if (ret < 0)
|
|
||||||
return;
|
|
||||||
nop->vbus_draw_enabled = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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;
|
otg->state = OTG_STATE_B_PERIPHERAL;
|
||||||
nop->phy.last_event = status;
|
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,
|
atomic_notifier_call_chain(&nop->phy.notifier, status,
|
||||||
otg->gadget);
|
otg->gadget);
|
||||||
} else {
|
} else {
|
||||||
nop_set_vbus_draw(nop, 0);
|
|
||||||
|
|
||||||
status = USB_EVENT_NONE;
|
status = USB_EVENT_NONE;
|
||||||
otg->state = OTG_STATE_B_IDLE;
|
otg->state = OTG_STATE_B_IDLE;
|
||||||
nop->phy.last_event = status;
|
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->usb_phy = &nop->phy;
|
||||||
nop->phy.otg->set_host = nop_set_host;
|
nop->phy.otg->set_host = nop_set_host;
|
||||||
nop->phy.otg->set_peripheral = nop_set_peripheral;
|
nop->phy.otg->set_peripheral = nop_set_peripheral;
|
||||||
|
nop->phy.otg->set_vbus = nop_set_vbus;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user