diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-26 08:14:13 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-26 08:14:13 -0700 |
| commit | 9703fc8caf36ac65dca1538b23dd137de0b53233 (patch) | |
| tree | 4e92539741cdce08f3c0095fefe76232a686f576 /drivers/usb/dwc2/hcd.c | |
| parent | da19a102ce87bf3e0a7fe277a659d1fc35330d6d (diff) | |
| parent | b8d9ee24493d862fbfeb3d209c032647f6073d5d (diff) | |
| download | linux-next-9703fc8caf36ac65dca1538b23dd137de0b53233.tar.gz linux-next-9703fc8caf36ac65dca1538b23dd137de0b53233.zip | |
Merge tag 'usb-4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB/PHY updates from Greg KH:
"Here is the big USB/PHY driver patches for 4.20-rc1
Lots of USB changes in here, primarily in these areas:
- typec updates and new drivers
- new PHY drivers
- dwc2 driver updates and additions (this old core keeps getting
added to new devices.)
- usbtmc major update based on the industry group coming together and
working to add new features and performance to the driver.
- USB gadget additions for new features
- USB gadget configfs updates
- chipidea driver updates
- other USB gadget updates
- USB serial driver updates
- renesas driver updates
- xhci driver updates
- other tiny USB driver updates
All of these have been in linux-next for a while with no reported
issues"
* tag 'usb-4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (229 commits)
usb: phy: ab8500: silence some uninitialized variable warnings
usb: xhci: tegra: Add genpd support
usb: xhci: tegra: Power-off power-domains on removal
usbip:vudc: BUG kmalloc-2048 (Not tainted): Poison overwritten
usbip: tools: fix atoi() on non-null terminated string
USB: misc: appledisplay: fix backlight update_status return code
phy: phy-pxa-usb: add a new driver
usb: host: add DT bindings for faraday fotg2
usb: host: ohci-at91: fix request of irq for optional gpio
usb/early: remove set but not used variable 'remain_length'
usb: typec: Fix copy/paste on typec_set_vconn_role() kerneldoc
usb: typec: tcpm: Report back negotiated PPS voltage and current
USB: core: remove set but not used variable 'udev'
usb: core: fix memory leak on port_dev_path allocation
USB: net2280: Remove ->disconnect() callback from net2280_pullup()
usb: dwc2: disable power_down on rockchip devices
usb: gadget: udc: renesas_usb3: add support for r8a77990
dt-bindings: usb: renesas_usb3: add bindings for r8a77990
usb: gadget: udc: renesas_usb3: Add r8a774a1 support
USB: serial: cypress_m8: remove set but not used variable 'iflag'
...
Diffstat (limited to 'drivers/usb/dwc2/hcd.c')
| -rw-r--r-- | drivers/usb/dwc2/hcd.c | 48 |
1 files changed, 34 insertions, 14 deletions
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 2bd6e6bfc241..dd82fa516f3f 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -358,16 +358,10 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg) static int dwc2_vbus_supply_init(struct dwc2_hsotg *hsotg) { - int ret; - - hsotg->vbus_supply = devm_regulator_get_optional(hsotg->dev, "vbus"); - if (IS_ERR(hsotg->vbus_supply)) { - ret = PTR_ERR(hsotg->vbus_supply); - hsotg->vbus_supply = NULL; - return ret == -ENODEV ? 0 : ret; - } + if (hsotg->vbus_supply) + return regulator_enable(hsotg->vbus_supply); - return regulator_enable(hsotg->vbus_supply); + return 0; } static int dwc2_vbus_supply_exit(struct dwc2_hsotg *hsotg) @@ -1328,14 +1322,11 @@ static void dwc2_hc_write_packet(struct dwc2_hsotg *hsotg, u32 remaining_count; u32 byte_count; u32 dword_count; - u32 __iomem *data_fifo; u32 *data_buf = (u32 *)chan->xfer_buf; if (dbg_hc(chan)) dev_vdbg(hsotg->dev, "%s()\n", __func__); - data_fifo = (u32 __iomem *)(hsotg->regs + HCFIFO(chan->hc_num)); - remaining_count = chan->xfer_len - chan->xfer_count; if (remaining_count > chan->max_packet) byte_count = chan->max_packet; @@ -3564,6 +3555,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, u32 port_status; u32 speed; u32 pcgctl; + u32 pwr; switch (typereq) { case ClearHubFeature: @@ -3612,8 +3604,11 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, dev_dbg(hsotg->dev, "ClearPortFeature USB_PORT_FEAT_POWER\n"); hprt0 = dwc2_read_hprt0(hsotg); + pwr = hprt0 & HPRT0_PWR; hprt0 &= ~HPRT0_PWR; dwc2_writel(hsotg, hprt0, HPRT0); + if (pwr) + dwc2_vbus_supply_exit(hsotg); break; case USB_PORT_FEAT_INDICATOR: @@ -3823,8 +3818,11 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, dev_dbg(hsotg->dev, "SetPortFeature - USB_PORT_FEAT_POWER\n"); hprt0 = dwc2_read_hprt0(hsotg); + pwr = hprt0 & HPRT0_PWR; hprt0 |= HPRT0_PWR; dwc2_writel(hsotg, hprt0, HPRT0); + if (!pwr) + dwc2_vbus_supply_init(hsotg); break; case USB_PORT_FEAT_RESET: @@ -3841,6 +3839,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, dwc2_writel(hsotg, 0, PCGCTL); hprt0 = dwc2_read_hprt0(hsotg); + pwr = hprt0 & HPRT0_PWR; /* Clear suspend bit if resetting from suspend state */ hprt0 &= ~HPRT0_SUSP; @@ -3854,6 +3853,8 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, dev_dbg(hsotg->dev, "In host mode, hprt0=%08x\n", hprt0); dwc2_writel(hsotg, hprt0, HPRT0); + if (!pwr) + dwc2_vbus_supply_init(hsotg); } /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */ @@ -4393,6 +4394,8 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd) struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); struct usb_bus *bus = hcd_to_bus(hcd); unsigned long flags; + u32 hprt0; + int ret; dev_dbg(hsotg->dev, "DWC OTG HCD START\n"); @@ -4408,6 +4411,17 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd) dwc2_hcd_reinit(hsotg); + hprt0 = dwc2_read_hprt0(hsotg); + /* Has vbus power been turned on in dwc2_core_host_init ? */ + if (hprt0 & HPRT0_PWR) { + /* Enable external vbus supply before resuming root hub */ + spin_unlock_irqrestore(&hsotg->lock, flags); + ret = dwc2_vbus_supply_init(hsotg); + if (ret) + return ret; + spin_lock_irqsave(&hsotg->lock, flags); + } + /* Initialize and connect root hub if one is not already attached */ if (bus->root_hub) { dev_dbg(hsotg->dev, "DWC OTG HCD Has Root Hub\n"); @@ -4417,7 +4431,7 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd) spin_unlock_irqrestore(&hsotg->lock, flags); - return dwc2_vbus_supply_init(hsotg); + return 0; } /* @@ -4428,6 +4442,7 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd) { struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); unsigned long flags; + u32 hprt0; /* Turn off all host-specific interrupts */ dwc2_disable_host_interrupts(hsotg); @@ -4436,6 +4451,7 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd) synchronize_irq(hcd->irq); spin_lock_irqsave(&hsotg->lock, flags); + hprt0 = dwc2_read_hprt0(hsotg); /* Ensure hcd is disconnected */ dwc2_hcd_disconnect(hsotg, true); dwc2_hcd_stop(hsotg); @@ -4444,7 +4460,9 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd) clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); spin_unlock_irqrestore(&hsotg->lock, flags); - dwc2_vbus_supply_exit(hsotg); + /* keep balanced supply init/exit by checking HPRT0_PWR */ + if (hprt0 & HPRT0_PWR) + dwc2_vbus_supply_exit(hsotg); usleep_range(1000, 3000); } @@ -4482,7 +4500,9 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd) hprt0 |= HPRT0_SUSP; hprt0 &= ~HPRT0_PWR; dwc2_writel(hsotg, hprt0, HPRT0); + spin_unlock_irqrestore(&hsotg->lock, flags); dwc2_vbus_supply_exit(hsotg); + spin_lock_irqsave(&hsotg->lock, flags); } /* Enter partial_power_down */ |
