123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- From 531ef5ebea96394ddb7f554d4d88e017dde30a59 Mon Sep 17 00:00:00 2001
- From: Amelie Delaunay <amelie.delaunay@st.com>
- Date: Tue, 13 Feb 2018 09:28:12 +0100
- Subject: [PATCH] usb: dwc2: add support for host mode external vbus supply
- This patch adds a way to enable an external vbus supply in host mode,
- when dwc2 drvvbus signal is not used.
- This patch is very similar to the one done in U-Boot dwc2 driver [1]. It
- also adds dynamic vbus supply management depending on the role and state
- of the core.
- [1] https://lists.denx.de/pipermail/u-boot/2017-March/283434.html
- Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
- Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
- ---
- drivers/usb/dwc2/core.h | 2 ++
- drivers/usb/dwc2/hcd.c | 26 ++++++++++++++++++++++++++
- 2 files changed, 28 insertions(+)
- --- a/drivers/usb/dwc2/core.h
- +++ b/drivers/usb/dwc2/core.h
- @@ -779,6 +779,7 @@ struct dwc2_hregs_backup {
- * @plat: The platform specific configuration data. This can be
- * removed once all SoCs support usb transceiver.
- * @supplies: Definition of USB power supplies
- + * @vbus_supply: Regulator supplying vbus.
- * @phyif: PHY interface width
- * @lock: Spinlock that protects all the driver data structures
- * @priv: Stores a pointer to the struct usb_hcd
- @@ -916,6 +917,7 @@ struct dwc2_hsotg {
- struct usb_phy *uphy;
- struct dwc2_hsotg_plat *plat;
- struct regulator_bulk_data supplies[DWC2_NUM_SUPPLIES];
- + struct regulator *vbus_supply;
- u32 phyif;
-
- spinlock_t lock;
- --- a/drivers/usb/dwc2/hcd.c
- +++ b/drivers/usb/dwc2/hcd.c
- @@ -359,6 +359,23 @@ static void dwc2_gusbcfg_init(struct dwc
- dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
- }
-
- +static int dwc2_vbus_supply_init(struct dwc2_hsotg *hsotg)
- +{
- + hsotg->vbus_supply = devm_regulator_get_optional(hsotg->dev, "vbus");
- + if (IS_ERR(hsotg->vbus_supply))
- + return 0;
- +
- + return regulator_enable(hsotg->vbus_supply);
- +}
- +
- +static int dwc2_vbus_supply_exit(struct dwc2_hsotg *hsotg)
- +{
- + if (hsotg->vbus_supply)
- + return regulator_disable(hsotg->vbus_supply);
- +
- + return 0;
- +}
- +
- /**
- * dwc2_enable_host_interrupts() - Enables the Host mode interrupts
- *
- @@ -3347,6 +3364,7 @@ static void dwc2_conn_id_status_change(s
-
- /* B-Device connector (Device Mode) */
- if (gotgctl & GOTGCTL_CONID_B) {
- + dwc2_vbus_supply_exit(hsotg);
- /* Wait for switch to device mode */
- dev_dbg(hsotg->dev, "connId B\n");
- if (hsotg->bus_suspended) {
- @@ -4456,6 +4474,9 @@ static int _dwc2_hcd_start(struct usb_hc
- }
-
- spin_unlock_irqrestore(&hsotg->lock, flags);
- +
- + dwc2_vbus_supply_init(hsotg);
- +
- return 0;
- }
-
- @@ -4483,6 +4504,8 @@ static void _dwc2_hcd_stop(struct usb_hc
- clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
- spin_unlock_irqrestore(&hsotg->lock, flags);
-
- + dwc2_vbus_supply_exit(hsotg);
- +
- usleep_range(1000, 3000);
- }
-
- @@ -4519,6 +4542,7 @@ static int _dwc2_hcd_suspend(struct usb_
- hprt0 |= HPRT0_SUSP;
- hprt0 &= ~HPRT0_PWR;
- dwc2_writel(hprt0, hsotg->regs + HPRT0);
- + dwc2_vbus_supply_exit(hsotg);
- }
-
- /* Enter hibernation */
- @@ -4599,6 +4623,8 @@ static int _dwc2_hcd_resume(struct usb_h
- spin_unlock_irqrestore(&hsotg->lock, flags);
- dwc2_port_resume(hsotg);
- } else {
- + dwc2_vbus_supply_init(hsotg);
- +
- /* Wait for controller to correctly update D+/D- level */
- usleep_range(3000, 5000);
-
|