15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2cbdc0f54SMauro Carvalho Chehab /* 372246da4SFelipe Balbi * core.c - DesignWare USB3 DRD Controller Core file 472246da4SFelipe Balbi * 510623b87SAlexander A. Klimov * Copyright (C) 2010-2011 Texas Instruments Incorporated - https://www.ti.com 672246da4SFelipe Balbi * 772246da4SFelipe Balbi * Authors: Felipe Balbi <balbi@ti.com>, 872246da4SFelipe Balbi * Sebastian Andrzej Siewior <bigeasy@linutronix.de> 972246da4SFelipe Balbi */ 1072246da4SFelipe Balbi 11fe8abf33SMasahiro Yamada #include <linux/clk.h> 12fa0ea13eSFelipe Balbi #include <linux/version.h> 13a72e658bSFelipe Balbi #include <linux/module.h> 1472246da4SFelipe Balbi #include <linux/kernel.h> 1572246da4SFelipe Balbi #include <linux/slab.h> 1672246da4SFelipe Balbi #include <linux/spinlock.h> 1772246da4SFelipe Balbi #include <linux/platform_device.h> 1872246da4SFelipe Balbi #include <linux/pm_runtime.h> 1972246da4SFelipe Balbi #include <linux/interrupt.h> 2072246da4SFelipe Balbi #include <linux/ioport.h> 2172246da4SFelipe Balbi #include <linux/io.h> 2272246da4SFelipe Balbi #include <linux/list.h> 2372246da4SFelipe Balbi #include <linux/delay.h> 2472246da4SFelipe Balbi #include <linux/dma-mapping.h> 25457e84b6SFelipe Balbi #include <linux/of.h> 26404905a6SHeikki Krogerus #include <linux/acpi.h> 276344475fSSekhar Nori #include <linux/pinctrl/consumer.h> 28fe8abf33SMasahiro Yamada #include <linux/reset.h> 2972246da4SFelipe Balbi 3072246da4SFelipe Balbi #include <linux/usb/ch9.h> 3172246da4SFelipe Balbi #include <linux/usb/gadget.h> 32f7e846f0SFelipe Balbi #include <linux/usb/of.h> 33a45c82b8SRuchika Kharwar #include <linux/usb/otg.h> 3472246da4SFelipe Balbi 3572246da4SFelipe Balbi #include "core.h" 3672246da4SFelipe Balbi #include "gadget.h" 3772246da4SFelipe Balbi #include "io.h" 3872246da4SFelipe Balbi 3972246da4SFelipe Balbi #include "debug.h" 4072246da4SFelipe Balbi 41fc8bb91bSFelipe Balbi #define DWC3_DEFAULT_AUTOSUSPEND_DELAY 5000 /* ms */ 428300dd23SFelipe Balbi 439d6173e1SThinh Nguyen /** 449d6173e1SThinh Nguyen * dwc3_get_dr_mode - Validates and sets dr_mode 459d6173e1SThinh Nguyen * @dwc: pointer to our context structure 469d6173e1SThinh Nguyen */ 479d6173e1SThinh Nguyen static int dwc3_get_dr_mode(struct dwc3 *dwc) 489d6173e1SThinh Nguyen { 499d6173e1SThinh Nguyen enum usb_dr_mode mode; 509d6173e1SThinh Nguyen struct device *dev = dwc->dev; 519d6173e1SThinh Nguyen unsigned int hw_mode; 529d6173e1SThinh Nguyen 539d6173e1SThinh Nguyen if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) 549d6173e1SThinh Nguyen dwc->dr_mode = USB_DR_MODE_OTG; 559d6173e1SThinh Nguyen 569d6173e1SThinh Nguyen mode = dwc->dr_mode; 579d6173e1SThinh Nguyen hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0); 589d6173e1SThinh Nguyen 599d6173e1SThinh Nguyen switch (hw_mode) { 609d6173e1SThinh Nguyen case DWC3_GHWPARAMS0_MODE_GADGET: 619d6173e1SThinh Nguyen if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) { 629d6173e1SThinh Nguyen dev_err(dev, 639d6173e1SThinh Nguyen "Controller does not support host mode.\n"); 649d6173e1SThinh Nguyen return -EINVAL; 659d6173e1SThinh Nguyen } 669d6173e1SThinh Nguyen mode = USB_DR_MODE_PERIPHERAL; 679d6173e1SThinh Nguyen break; 689d6173e1SThinh Nguyen case DWC3_GHWPARAMS0_MODE_HOST: 699d6173e1SThinh Nguyen if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) { 709d6173e1SThinh Nguyen dev_err(dev, 719d6173e1SThinh Nguyen "Controller does not support device mode.\n"); 729d6173e1SThinh Nguyen return -EINVAL; 739d6173e1SThinh Nguyen } 749d6173e1SThinh Nguyen mode = USB_DR_MODE_HOST; 759d6173e1SThinh Nguyen break; 769d6173e1SThinh Nguyen default: 779d6173e1SThinh Nguyen if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) 789d6173e1SThinh Nguyen mode = USB_DR_MODE_HOST; 799d6173e1SThinh Nguyen else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) 809d6173e1SThinh Nguyen mode = USB_DR_MODE_PERIPHERAL; 81a7700468SThinh Nguyen 82a7700468SThinh Nguyen /* 8389a9cc47SThinh Nguyen * DWC_usb31 and DWC_usb3 v3.30a and higher do not support OTG 8489a9cc47SThinh Nguyen * mode. If the controller supports DRD but the dr_mode is not 8589a9cc47SThinh Nguyen * specified or set to OTG, then set the mode to peripheral. 86a7700468SThinh Nguyen */ 8789a9cc47SThinh Nguyen if (mode == USB_DR_MODE_OTG && 888bb14308SThinh Nguyen (!IS_ENABLED(CONFIG_USB_ROLE_SWITCH) || 898bb14308SThinh Nguyen !device_property_read_bool(dwc->dev, "usb-role-switch")) && 909af21dd6SThinh Nguyen !DWC3_VER_IS_PRIOR(DWC3, 330A)) 91a7700468SThinh Nguyen mode = USB_DR_MODE_PERIPHERAL; 929d6173e1SThinh Nguyen } 939d6173e1SThinh Nguyen 949d6173e1SThinh Nguyen if (mode != dwc->dr_mode) { 959d6173e1SThinh Nguyen dev_warn(dev, 969d6173e1SThinh Nguyen "Configuration mismatch. dr_mode forced to %s\n", 979d6173e1SThinh Nguyen mode == USB_DR_MODE_HOST ? "host" : "gadget"); 989d6173e1SThinh Nguyen 999d6173e1SThinh Nguyen dwc->dr_mode = mode; 1009d6173e1SThinh Nguyen } 1019d6173e1SThinh Nguyen 1029d6173e1SThinh Nguyen return 0; 1039d6173e1SThinh Nguyen } 1049d6173e1SThinh Nguyen 105f09cc79bSRoger Quadros void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode) 1063140e8cbSSebastian Andrzej Siewior { 1073140e8cbSSebastian Andrzej Siewior u32 reg; 1083140e8cbSSebastian Andrzej Siewior 1093140e8cbSSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 1103140e8cbSSebastian Andrzej Siewior reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); 1113140e8cbSSebastian Andrzej Siewior reg |= DWC3_GCTL_PRTCAPDIR(mode); 1123140e8cbSSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 113c4a5153eSManu Gautam 114c4a5153eSManu Gautam dwc->current_dr_role = mode; 11541ce1456SRoger Quadros } 1166b3261a2SRoger Quadros 117f88359e1SYu Chen static int dwc3_core_soft_reset(struct dwc3 *dwc); 118f88359e1SYu Chen 11941ce1456SRoger Quadros static void __dwc3_set_mode(struct work_struct *work) 12041ce1456SRoger Quadros { 12141ce1456SRoger Quadros struct dwc3 *dwc = work_to_dwc(work); 12241ce1456SRoger Quadros unsigned long flags; 12341ce1456SRoger Quadros int ret; 124f580170fSYu Chen u32 reg; 12541ce1456SRoger Quadros 126f88359e1SYu Chen mutex_lock(&dwc->mutex); 127f88359e1SYu Chen 128c2cd3452SMartin Kepplinger pm_runtime_get_sync(dwc->dev); 129c2cd3452SMartin Kepplinger 130f09cc79bSRoger Quadros if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_OTG) 131f09cc79bSRoger Quadros dwc3_otg_update(dwc, 0); 132f09cc79bSRoger Quadros 13341ce1456SRoger Quadros if (!dwc->desired_dr_role) 134c2cd3452SMartin Kepplinger goto out; 13541ce1456SRoger Quadros 13641ce1456SRoger Quadros if (dwc->desired_dr_role == dwc->current_dr_role) 137c2cd3452SMartin Kepplinger goto out; 13841ce1456SRoger Quadros 139f09cc79bSRoger Quadros if (dwc->desired_dr_role == DWC3_GCTL_PRTCAP_OTG && dwc->edev) 140c2cd3452SMartin Kepplinger goto out; 14141ce1456SRoger Quadros 14241ce1456SRoger Quadros switch (dwc->current_dr_role) { 14341ce1456SRoger Quadros case DWC3_GCTL_PRTCAP_HOST: 14441ce1456SRoger Quadros dwc3_host_exit(dwc); 14541ce1456SRoger Quadros break; 14641ce1456SRoger Quadros case DWC3_GCTL_PRTCAP_DEVICE: 14741ce1456SRoger Quadros dwc3_gadget_exit(dwc); 14841ce1456SRoger Quadros dwc3_event_buffers_cleanup(dwc); 14941ce1456SRoger Quadros break; 150f09cc79bSRoger Quadros case DWC3_GCTL_PRTCAP_OTG: 151f09cc79bSRoger Quadros dwc3_otg_exit(dwc); 152f09cc79bSRoger Quadros spin_lock_irqsave(&dwc->lock, flags); 153f09cc79bSRoger Quadros dwc->desired_otg_role = DWC3_OTG_ROLE_IDLE; 154f09cc79bSRoger Quadros spin_unlock_irqrestore(&dwc->lock, flags); 155f09cc79bSRoger Quadros dwc3_otg_update(dwc, 1); 156f09cc79bSRoger Quadros break; 15741ce1456SRoger Quadros default: 15841ce1456SRoger Quadros break; 15941ce1456SRoger Quadros } 16041ce1456SRoger Quadros 161f88359e1SYu Chen /* For DRD host or device mode only */ 162f88359e1SYu Chen if (dwc->desired_dr_role != DWC3_GCTL_PRTCAP_OTG) { 163f88359e1SYu Chen reg = dwc3_readl(dwc->regs, DWC3_GCTL); 164f88359e1SYu Chen reg |= DWC3_GCTL_CORESOFTRESET; 165f88359e1SYu Chen dwc3_writel(dwc->regs, DWC3_GCTL, reg); 166f88359e1SYu Chen 167f88359e1SYu Chen /* 168f88359e1SYu Chen * Wait for internal clocks to synchronized. DWC_usb31 and 169f88359e1SYu Chen * DWC_usb32 may need at least 50ms (less for DWC_usb3). To 170f88359e1SYu Chen * keep it consistent across different IPs, let's wait up to 171f88359e1SYu Chen * 100ms before clearing GCTL.CORESOFTRESET. 172f88359e1SYu Chen */ 173f88359e1SYu Chen msleep(100); 174f88359e1SYu Chen 175f88359e1SYu Chen reg = dwc3_readl(dwc->regs, DWC3_GCTL); 176f88359e1SYu Chen reg &= ~DWC3_GCTL_CORESOFTRESET; 177f88359e1SYu Chen dwc3_writel(dwc->regs, DWC3_GCTL, reg); 178f88359e1SYu Chen } 179f88359e1SYu Chen 18041ce1456SRoger Quadros spin_lock_irqsave(&dwc->lock, flags); 18141ce1456SRoger Quadros 18241ce1456SRoger Quadros dwc3_set_prtcap(dwc, dwc->desired_dr_role); 18341ce1456SRoger Quadros 18441ce1456SRoger Quadros spin_unlock_irqrestore(&dwc->lock, flags); 18541ce1456SRoger Quadros 18641ce1456SRoger Quadros switch (dwc->desired_dr_role) { 18741ce1456SRoger Quadros case DWC3_GCTL_PRTCAP_HOST: 18841ce1456SRoger Quadros ret = dwc3_host_init(dwc); 189958d1a4cSFelipe Balbi if (ret) { 19041ce1456SRoger Quadros dev_err(dwc->dev, "failed to initialize host\n"); 191958d1a4cSFelipe Balbi } else { 192958d1a4cSFelipe Balbi if (dwc->usb2_phy) 193958d1a4cSFelipe Balbi otg_set_vbus(dwc->usb2_phy->otg, true); 194958d1a4cSFelipe Balbi phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); 195644cbbc3SManu Gautam phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST); 196f580170fSYu Chen if (dwc->dis_split_quirk) { 197f580170fSYu Chen reg = dwc3_readl(dwc->regs, DWC3_GUCTL3); 198f580170fSYu Chen reg |= DWC3_GUCTL3_SPLITDISABLE; 199f580170fSYu Chen dwc3_writel(dwc->regs, DWC3_GUCTL3, reg); 200f580170fSYu Chen } 201958d1a4cSFelipe Balbi } 20241ce1456SRoger Quadros break; 20341ce1456SRoger Quadros case DWC3_GCTL_PRTCAP_DEVICE: 204f88359e1SYu Chen dwc3_core_soft_reset(dwc); 205f88359e1SYu Chen 20641ce1456SRoger Quadros dwc3_event_buffers_setup(dwc); 207958d1a4cSFelipe Balbi 208958d1a4cSFelipe Balbi if (dwc->usb2_phy) 209958d1a4cSFelipe Balbi otg_set_vbus(dwc->usb2_phy->otg, false); 210958d1a4cSFelipe Balbi phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE); 211644cbbc3SManu Gautam phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE); 212958d1a4cSFelipe Balbi 21341ce1456SRoger Quadros ret = dwc3_gadget_init(dwc); 21441ce1456SRoger Quadros if (ret) 21541ce1456SRoger Quadros dev_err(dwc->dev, "failed to initialize peripheral\n"); 21641ce1456SRoger Quadros break; 217f09cc79bSRoger Quadros case DWC3_GCTL_PRTCAP_OTG: 218f09cc79bSRoger Quadros dwc3_otg_init(dwc); 219f09cc79bSRoger Quadros dwc3_otg_update(dwc, 0); 220f09cc79bSRoger Quadros break; 22141ce1456SRoger Quadros default: 22241ce1456SRoger Quadros break; 22341ce1456SRoger Quadros } 224f09cc79bSRoger Quadros 225c2cd3452SMartin Kepplinger out: 226c2cd3452SMartin Kepplinger pm_runtime_mark_last_busy(dwc->dev); 227c2cd3452SMartin Kepplinger pm_runtime_put_autosuspend(dwc->dev); 228f88359e1SYu Chen mutex_unlock(&dwc->mutex); 22941ce1456SRoger Quadros } 23041ce1456SRoger Quadros 23141ce1456SRoger Quadros void dwc3_set_mode(struct dwc3 *dwc, u32 mode) 23241ce1456SRoger Quadros { 23341ce1456SRoger Quadros unsigned long flags; 23441ce1456SRoger Quadros 235dc336b19SLi Jun if (dwc->dr_mode != USB_DR_MODE_OTG) 236dc336b19SLi Jun return; 237dc336b19SLi Jun 23841ce1456SRoger Quadros spin_lock_irqsave(&dwc->lock, flags); 23941ce1456SRoger Quadros dwc->desired_dr_role = mode; 24041ce1456SRoger Quadros spin_unlock_irqrestore(&dwc->lock, flags); 24141ce1456SRoger Quadros 242084a804eSRoger Quadros queue_work(system_freezable_wq, &dwc->drd_work); 2433140e8cbSSebastian Andrzej Siewior } 2448300dd23SFelipe Balbi 245cf6d867dSFelipe Balbi u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type) 246cf6d867dSFelipe Balbi { 247cf6d867dSFelipe Balbi struct dwc3 *dwc = dep->dwc; 248cf6d867dSFelipe Balbi u32 reg; 249cf6d867dSFelipe Balbi 250cf6d867dSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GDBGFIFOSPACE, 251cf6d867dSFelipe Balbi DWC3_GDBGFIFOSPACE_NUM(dep->number) | 252cf6d867dSFelipe Balbi DWC3_GDBGFIFOSPACE_TYPE(type)); 253cf6d867dSFelipe Balbi 254cf6d867dSFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GDBGFIFOSPACE); 255cf6d867dSFelipe Balbi 256cf6d867dSFelipe Balbi return DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(reg); 257cf6d867dSFelipe Balbi } 258cf6d867dSFelipe Balbi 25972246da4SFelipe Balbi /** 26072246da4SFelipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 26172246da4SFelipe Balbi * @dwc: pointer to our context structure 26272246da4SFelipe Balbi */ 26357303488SKishon Vijay Abraham I static int dwc3_core_soft_reset(struct dwc3 *dwc) 26472246da4SFelipe Balbi { 26572246da4SFelipe Balbi u32 reg; 266f59dcab1SFelipe Balbi int retries = 1000; 26757303488SKishon Vijay Abraham I int ret; 26872246da4SFelipe Balbi 26951e1e7bcSFelipe Balbi usb_phy_init(dwc->usb2_phy); 27051e1e7bcSFelipe Balbi usb_phy_init(dwc->usb3_phy); 27157303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 27257303488SKishon Vijay Abraham I if (ret < 0) 27357303488SKishon Vijay Abraham I return ret; 27457303488SKishon Vijay Abraham I 27557303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 27657303488SKishon Vijay Abraham I if (ret < 0) { 27757303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 27857303488SKishon Vijay Abraham I return ret; 27957303488SKishon Vijay Abraham I } 28072246da4SFelipe Balbi 281f59dcab1SFelipe Balbi /* 282f59dcab1SFelipe Balbi * We're resetting only the device side because, if we're in host mode, 283f59dcab1SFelipe Balbi * XHCI driver will reset the host block. If dwc3 was configured for 284f59dcab1SFelipe Balbi * host-only mode, then we can return early. 285f59dcab1SFelipe Balbi */ 286c4a5153eSManu Gautam if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) 28757303488SKishon Vijay Abraham I return 0; 288f59dcab1SFelipe Balbi 289f59dcab1SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 290f59dcab1SFelipe Balbi reg |= DWC3_DCTL_CSFTRST; 291f59dcab1SFelipe Balbi dwc3_writel(dwc->regs, DWC3_DCTL, reg); 292f59dcab1SFelipe Balbi 2934749e0e6SThinh Nguyen /* 2944749e0e6SThinh Nguyen * For DWC_usb31 controller 1.90a and later, the DCTL.CSFRST bit 2954749e0e6SThinh Nguyen * is cleared only after all the clocks are synchronized. This can 2964749e0e6SThinh Nguyen * take a little more than 50ms. Set the polling rate at 20ms 2974749e0e6SThinh Nguyen * for 10 times instead. 2984749e0e6SThinh Nguyen */ 2999af21dd6SThinh Nguyen if (DWC3_VER_IS_WITHIN(DWC31, 190A, ANY) || DWC3_IP_IS(DWC32)) 3004749e0e6SThinh Nguyen retries = 10; 3014749e0e6SThinh Nguyen 302f59dcab1SFelipe Balbi do { 303f59dcab1SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 304f59dcab1SFelipe Balbi if (!(reg & DWC3_DCTL_CSFTRST)) 305fab38333SThinh Nguyen goto done; 306f59dcab1SFelipe Balbi 3079af21dd6SThinh Nguyen if (DWC3_VER_IS_WITHIN(DWC31, 190A, ANY) || DWC3_IP_IS(DWC32)) 3084749e0e6SThinh Nguyen msleep(20); 3094749e0e6SThinh Nguyen else 310f59dcab1SFelipe Balbi udelay(1); 311f59dcab1SFelipe Balbi } while (--retries); 312f59dcab1SFelipe Balbi 31300b42170SBrian Norris phy_exit(dwc->usb3_generic_phy); 31400b42170SBrian Norris phy_exit(dwc->usb2_generic_phy); 31500b42170SBrian Norris 316f59dcab1SFelipe Balbi return -ETIMEDOUT; 317fab38333SThinh Nguyen 318fab38333SThinh Nguyen done: 319fab38333SThinh Nguyen /* 3204749e0e6SThinh Nguyen * For DWC_usb31 controller 1.80a and prior, once DCTL.CSFRST bit 3214749e0e6SThinh Nguyen * is cleared, we must wait at least 50ms before accessing the PHY 3224749e0e6SThinh Nguyen * domain (synchronization delay). 323fab38333SThinh Nguyen */ 3249af21dd6SThinh Nguyen if (DWC3_VER_IS_WITHIN(DWC31, ANY, 180A)) 325fab38333SThinh Nguyen msleep(50); 326fab38333SThinh Nguyen 327fab38333SThinh Nguyen return 0; 32872246da4SFelipe Balbi } 32972246da4SFelipe Balbi 330db2be4e9SNikhil Badola /* 331db2be4e9SNikhil Badola * dwc3_frame_length_adjustment - Adjusts frame length if required 332db2be4e9SNikhil Badola * @dwc3: Pointer to our controller context structure 333db2be4e9SNikhil Badola */ 334bcdb3272SFelipe Balbi static void dwc3_frame_length_adjustment(struct dwc3 *dwc) 335db2be4e9SNikhil Badola { 336db2be4e9SNikhil Badola u32 reg; 337db2be4e9SNikhil Badola u32 dft; 338db2be4e9SNikhil Badola 3399af21dd6SThinh Nguyen if (DWC3_VER_IS_PRIOR(DWC3, 250A)) 340db2be4e9SNikhil Badola return; 341db2be4e9SNikhil Badola 342bcdb3272SFelipe Balbi if (dwc->fladj == 0) 343db2be4e9SNikhil Badola return; 344db2be4e9SNikhil Badola 345db2be4e9SNikhil Badola reg = dwc3_readl(dwc->regs, DWC3_GFLADJ); 346db2be4e9SNikhil Badola dft = reg & DWC3_GFLADJ_30MHZ_MASK; 347a7d9874cSYinbo Zhu if (dft != dwc->fladj) { 348db2be4e9SNikhil Badola reg &= ~DWC3_GFLADJ_30MHZ_MASK; 349bcdb3272SFelipe Balbi reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj; 350db2be4e9SNikhil Badola dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); 351db2be4e9SNikhil Badola } 352db2be4e9SNikhil Badola } 353db2be4e9SNikhil Badola 354c5cc74e8SHeikki Krogerus /** 35572246da4SFelipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 35672246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 35772246da4SFelipe Balbi * @evt: Pointer to event buffer to be freed 35872246da4SFelipe Balbi */ 35972246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc, 36072246da4SFelipe Balbi struct dwc3_event_buffer *evt) 36172246da4SFelipe Balbi { 362d64ff406SArnd Bergmann dma_free_coherent(dwc->sysdev, evt->length, evt->buf, evt->dma); 36372246da4SFelipe Balbi } 36472246da4SFelipe Balbi 36572246da4SFelipe Balbi /** 3661d046793SPaul Zimmerman * dwc3_alloc_one_event_buffer - Allocates one event buffer structure 36772246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 36872246da4SFelipe Balbi * @length: size of the event buffer 36972246da4SFelipe Balbi * 3701d046793SPaul Zimmerman * Returns a pointer to the allocated event buffer structure on success 37172246da4SFelipe Balbi * otherwise ERR_PTR(errno). 37272246da4SFelipe Balbi */ 37367d0b500SFelipe Balbi static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, 37467d0b500SFelipe Balbi unsigned length) 37572246da4SFelipe Balbi { 37672246da4SFelipe Balbi struct dwc3_event_buffer *evt; 37772246da4SFelipe Balbi 378380f0d28SFelipe Balbi evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL); 37972246da4SFelipe Balbi if (!evt) 38072246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 38172246da4SFelipe Balbi 38272246da4SFelipe Balbi evt->dwc = dwc; 38372246da4SFelipe Balbi evt->length = length; 384d9fa4c63SJohn Youn evt->cache = devm_kzalloc(dwc->dev, length, GFP_KERNEL); 385d9fa4c63SJohn Youn if (!evt->cache) 386d9fa4c63SJohn Youn return ERR_PTR(-ENOMEM); 387d9fa4c63SJohn Youn 388d64ff406SArnd Bergmann evt->buf = dma_alloc_coherent(dwc->sysdev, length, 38972246da4SFelipe Balbi &evt->dma, GFP_KERNEL); 390e32672f0SFelipe Balbi if (!evt->buf) 39172246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 39272246da4SFelipe Balbi 39372246da4SFelipe Balbi return evt; 39472246da4SFelipe Balbi } 39572246da4SFelipe Balbi 39672246da4SFelipe Balbi /** 39772246da4SFelipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 39872246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 39972246da4SFelipe Balbi */ 40072246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc) 40172246da4SFelipe Balbi { 40272246da4SFelipe Balbi struct dwc3_event_buffer *evt; 40372246da4SFelipe Balbi 404696c8b12SFelipe Balbi evt = dwc->ev_buf; 40564b6c8a7SAnton Tikhomirov if (evt) 40672246da4SFelipe Balbi dwc3_free_one_event_buffer(dwc, evt); 40772246da4SFelipe Balbi } 40872246da4SFelipe Balbi 40972246da4SFelipe Balbi /** 41072246da4SFelipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 4111d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 41272246da4SFelipe Balbi * @length: size of event buffer 41372246da4SFelipe Balbi * 4141d046793SPaul Zimmerman * Returns 0 on success otherwise negative errno. In the error case, dwc 41572246da4SFelipe Balbi * may contain some buffers allocated but not all which were requested. 41672246da4SFelipe Balbi */ 41741ac7b3aSBill Pemberton static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) 41872246da4SFelipe Balbi { 41972246da4SFelipe Balbi struct dwc3_event_buffer *evt; 42072246da4SFelipe Balbi 42172246da4SFelipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 42272246da4SFelipe Balbi if (IS_ERR(evt)) { 42372246da4SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 42472246da4SFelipe Balbi return PTR_ERR(evt); 42572246da4SFelipe Balbi } 426696c8b12SFelipe Balbi dwc->ev_buf = evt; 42772246da4SFelipe Balbi 42872246da4SFelipe Balbi return 0; 42972246da4SFelipe Balbi } 43072246da4SFelipe Balbi 43172246da4SFelipe Balbi /** 43272246da4SFelipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 4331d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 43472246da4SFelipe Balbi * 43572246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 43672246da4SFelipe Balbi */ 437f09cc79bSRoger Quadros int dwc3_event_buffers_setup(struct dwc3 *dwc) 43872246da4SFelipe Balbi { 43972246da4SFelipe Balbi struct dwc3_event_buffer *evt; 44072246da4SFelipe Balbi 441696c8b12SFelipe Balbi evt = dwc->ev_buf; 4427acd85e0SPaul Zimmerman evt->lpos = 0; 443660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 44472246da4SFelipe Balbi lower_32_bits(evt->dma)); 445660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 44672246da4SFelipe Balbi upper_32_bits(evt->dma)); 447660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), 44868d6a01bSFelipe Balbi DWC3_GEVNTSIZ_SIZE(evt->length)); 449660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 45072246da4SFelipe Balbi 45172246da4SFelipe Balbi return 0; 45272246da4SFelipe Balbi } 45372246da4SFelipe Balbi 454f09cc79bSRoger Quadros void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 45572246da4SFelipe Balbi { 45672246da4SFelipe Balbi struct dwc3_event_buffer *evt; 45772246da4SFelipe Balbi 458696c8b12SFelipe Balbi evt = dwc->ev_buf; 4597acd85e0SPaul Zimmerman 4607acd85e0SPaul Zimmerman evt->lpos = 0; 4617acd85e0SPaul Zimmerman 462660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 0); 463660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 0); 464660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK 46568d6a01bSFelipe Balbi | DWC3_GEVNTSIZ_SIZE(0)); 466660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 46772246da4SFelipe Balbi } 46872246da4SFelipe Balbi 4690ffcaf37SFelipe Balbi static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) 4700ffcaf37SFelipe Balbi { 4710ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 4720ffcaf37SFelipe Balbi return 0; 4730ffcaf37SFelipe Balbi 4740ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 4750ffcaf37SFelipe Balbi return 0; 4760ffcaf37SFelipe Balbi 4770ffcaf37SFelipe Balbi dwc->scratchbuf = kmalloc_array(dwc->nr_scratch, 4780ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, GFP_KERNEL); 4790ffcaf37SFelipe Balbi if (!dwc->scratchbuf) 4800ffcaf37SFelipe Balbi return -ENOMEM; 4810ffcaf37SFelipe Balbi 4820ffcaf37SFelipe Balbi return 0; 4830ffcaf37SFelipe Balbi } 4840ffcaf37SFelipe Balbi 4850ffcaf37SFelipe Balbi static int dwc3_setup_scratch_buffers(struct dwc3 *dwc) 4860ffcaf37SFelipe Balbi { 4870ffcaf37SFelipe Balbi dma_addr_t scratch_addr; 4880ffcaf37SFelipe Balbi u32 param; 4890ffcaf37SFelipe Balbi int ret; 4900ffcaf37SFelipe Balbi 4910ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 4920ffcaf37SFelipe Balbi return 0; 4930ffcaf37SFelipe Balbi 4940ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 4950ffcaf37SFelipe Balbi return 0; 4960ffcaf37SFelipe Balbi 4970ffcaf37SFelipe Balbi /* should never fall here */ 4980ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 4990ffcaf37SFelipe Balbi return 0; 5000ffcaf37SFelipe Balbi 501d64ff406SArnd Bergmann scratch_addr = dma_map_single(dwc->sysdev, dwc->scratchbuf, 5020ffcaf37SFelipe Balbi dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, 5030ffcaf37SFelipe Balbi DMA_BIDIRECTIONAL); 504d64ff406SArnd Bergmann if (dma_mapping_error(dwc->sysdev, scratch_addr)) { 505d64ff406SArnd Bergmann dev_err(dwc->sysdev, "failed to map scratch buffer\n"); 5060ffcaf37SFelipe Balbi ret = -EFAULT; 5070ffcaf37SFelipe Balbi goto err0; 5080ffcaf37SFelipe Balbi } 5090ffcaf37SFelipe Balbi 5100ffcaf37SFelipe Balbi dwc->scratch_addr = scratch_addr; 5110ffcaf37SFelipe Balbi 5120ffcaf37SFelipe Balbi param = lower_32_bits(scratch_addr); 5130ffcaf37SFelipe Balbi 5140ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 5150ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param); 5160ffcaf37SFelipe Balbi if (ret < 0) 5170ffcaf37SFelipe Balbi goto err1; 5180ffcaf37SFelipe Balbi 5190ffcaf37SFelipe Balbi param = upper_32_bits(scratch_addr); 5200ffcaf37SFelipe Balbi 5210ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 5220ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param); 5230ffcaf37SFelipe Balbi if (ret < 0) 5240ffcaf37SFelipe Balbi goto err1; 5250ffcaf37SFelipe Balbi 5260ffcaf37SFelipe Balbi return 0; 5270ffcaf37SFelipe Balbi 5280ffcaf37SFelipe Balbi err1: 529d64ff406SArnd Bergmann dma_unmap_single(dwc->sysdev, dwc->scratch_addr, dwc->nr_scratch * 5300ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 5310ffcaf37SFelipe Balbi 5320ffcaf37SFelipe Balbi err0: 5330ffcaf37SFelipe Balbi return ret; 5340ffcaf37SFelipe Balbi } 5350ffcaf37SFelipe Balbi 5360ffcaf37SFelipe Balbi static void dwc3_free_scratch_buffers(struct dwc3 *dwc) 5370ffcaf37SFelipe Balbi { 5380ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 5390ffcaf37SFelipe Balbi return; 5400ffcaf37SFelipe Balbi 5410ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 5420ffcaf37SFelipe Balbi return; 5430ffcaf37SFelipe Balbi 5440ffcaf37SFelipe Balbi /* should never fall here */ 5450ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 5460ffcaf37SFelipe Balbi return; 5470ffcaf37SFelipe Balbi 548d64ff406SArnd Bergmann dma_unmap_single(dwc->sysdev, dwc->scratch_addr, dwc->nr_scratch * 5490ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 5500ffcaf37SFelipe Balbi kfree(dwc->scratchbuf); 5510ffcaf37SFelipe Balbi } 5520ffcaf37SFelipe Balbi 553789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc) 554789451f6SFelipe Balbi { 555789451f6SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 556789451f6SFelipe Balbi 55747d3946eSBryan O'Donoghue dwc->num_eps = DWC3_NUM_EPS(parms); 558789451f6SFelipe Balbi } 559789451f6SFelipe Balbi 56041ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc) 56126ceca97SFelipe Balbi { 56226ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 56326ceca97SFelipe Balbi 56426ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 56526ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 56626ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 56726ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 56826ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 56926ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 57026ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 57126ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 57226ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 57316710380SThinh Nguyen 57416710380SThinh Nguyen if (DWC3_IP_IS(DWC32)) 57516710380SThinh Nguyen parms->hwparams9 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS9); 57626ceca97SFelipe Balbi } 57726ceca97SFelipe Balbi 57898112041SRoger Quadros static int dwc3_core_ulpi_init(struct dwc3 *dwc) 57998112041SRoger Quadros { 58098112041SRoger Quadros int intf; 58198112041SRoger Quadros int ret = 0; 58298112041SRoger Quadros 58398112041SRoger Quadros intf = DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3); 58498112041SRoger Quadros 58598112041SRoger Quadros if (intf == DWC3_GHWPARAMS3_HSPHY_IFC_ULPI || 58698112041SRoger Quadros (intf == DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI && 58798112041SRoger Quadros dwc->hsphy_interface && 58898112041SRoger Quadros !strncmp(dwc->hsphy_interface, "ulpi", 4))) 58998112041SRoger Quadros ret = dwc3_ulpi_init(dwc); 59098112041SRoger Quadros 59198112041SRoger Quadros return ret; 59298112041SRoger Quadros } 59398112041SRoger Quadros 59472246da4SFelipe Balbi /** 595b5a65c40SHuang Rui * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core 596b5a65c40SHuang Rui * @dwc: Pointer to our controller context structure 59788bc9d19SHeikki Krogerus * 59888bc9d19SHeikki Krogerus * Returns 0 on success. The USB PHY interfaces are configured but not 59988bc9d19SHeikki Krogerus * initialized. The PHY interfaces and the PHYs get initialized together with 60088bc9d19SHeikki Krogerus * the core in dwc3_core_init. 601b5a65c40SHuang Rui */ 60288bc9d19SHeikki Krogerus static int dwc3_phy_setup(struct dwc3 *dwc) 603b5a65c40SHuang Rui { 6049ba3aca8SThinh Nguyen unsigned int hw_mode; 605b5a65c40SHuang Rui u32 reg; 606b5a65c40SHuang Rui 6079ba3aca8SThinh Nguyen hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0); 6089ba3aca8SThinh Nguyen 609b5a65c40SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 610b5a65c40SHuang Rui 6112164a476SHuang Rui /* 6121966b865SFelipe Balbi * Make sure UX_EXIT_PX is cleared as that causes issues with some 6131966b865SFelipe Balbi * PHYs. Also, this bit is not supposed to be used in normal operation. 6141966b865SFelipe Balbi */ 6151966b865SFelipe Balbi reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX; 6161966b865SFelipe Balbi 6171966b865SFelipe Balbi /* 6182164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY 6192164a476SHuang Rui * to '0' during coreConsultant configuration. So default value 6202164a476SHuang Rui * will be '0' when the core is reset. Application needs to set it 6212164a476SHuang Rui * to '1' after the core initialization is completed. 6222164a476SHuang Rui */ 6239af21dd6SThinh Nguyen if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) 6242164a476SHuang Rui reg |= DWC3_GUSB3PIPECTL_SUSPHY; 6252164a476SHuang Rui 6269ba3aca8SThinh Nguyen /* 6279ba3aca8SThinh Nguyen * For DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be cleared after 6289ba3aca8SThinh Nguyen * power-on reset, and it can be set after core initialization, which is 6299ba3aca8SThinh Nguyen * after device soft-reset during initialization. 6309ba3aca8SThinh Nguyen */ 6319ba3aca8SThinh Nguyen if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD) 6329ba3aca8SThinh Nguyen reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 6339ba3aca8SThinh Nguyen 634b5a65c40SHuang Rui if (dwc->u2ss_inp3_quirk) 635b5a65c40SHuang Rui reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; 636b5a65c40SHuang Rui 637e58dd357SRajesh Bhagat if (dwc->dis_rxdet_inp3_quirk) 638e58dd357SRajesh Bhagat reg |= DWC3_GUSB3PIPECTL_DISRXDETINP3; 639e58dd357SRajesh Bhagat 640df31f5b3SHuang Rui if (dwc->req_p1p2p3_quirk) 641df31f5b3SHuang Rui reg |= DWC3_GUSB3PIPECTL_REQP1P2P3; 642df31f5b3SHuang Rui 643a2a1d0f5SHuang Rui if (dwc->del_p1p2p3_quirk) 644a2a1d0f5SHuang Rui reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN; 645a2a1d0f5SHuang Rui 64641c06ffdSHuang Rui if (dwc->del_phy_power_chg_quirk) 64741c06ffdSHuang Rui reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE; 64841c06ffdSHuang Rui 649fb67afcaSHuang Rui if (dwc->lfps_filter_quirk) 650fb67afcaSHuang Rui reg |= DWC3_GUSB3PIPECTL_LFPSFILT; 651fb67afcaSHuang Rui 65214f4ac53SHuang Rui if (dwc->rx_detect_poll_quirk) 65314f4ac53SHuang Rui reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL; 65414f4ac53SHuang Rui 6556b6a0c9aSHuang Rui if (dwc->tx_de_emphasis_quirk) 6566b6a0c9aSHuang Rui reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); 6576b6a0c9aSHuang Rui 658cd72f890SFelipe Balbi if (dwc->dis_u3_susphy_quirk) 65959acfa20SHuang Rui reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 66059acfa20SHuang Rui 66100fe081dSWilliam Wu if (dwc->dis_del_phy_power_chg_quirk) 66200fe081dSWilliam Wu reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE; 66300fe081dSWilliam Wu 664b5a65c40SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 665b5a65c40SHuang Rui 6662164a476SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 6672164a476SHuang Rui 6683e10a2ceSHeikki Krogerus /* Select the HS PHY interface */ 6693e10a2ceSHeikki Krogerus switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) { 6703e10a2ceSHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI: 67143cacb03SFelipe Balbi if (dwc->hsphy_interface && 67243cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "utmi", 4)) { 6733e10a2ceSHeikki Krogerus reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI; 67488bc9d19SHeikki Krogerus break; 67543cacb03SFelipe Balbi } else if (dwc->hsphy_interface && 67643cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "ulpi", 4)) { 6773e10a2ceSHeikki Krogerus reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI; 67888bc9d19SHeikki Krogerus dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 6793e10a2ceSHeikki Krogerus } else { 68088bc9d19SHeikki Krogerus /* Relying on default value. */ 68188bc9d19SHeikki Krogerus if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) 6823e10a2ceSHeikki Krogerus break; 6833e10a2ceSHeikki Krogerus } 684df561f66SGustavo A. R. Silva fallthrough; 68588bc9d19SHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: 6863e10a2ceSHeikki Krogerus default: 6873e10a2ceSHeikki Krogerus break; 6883e10a2ceSHeikki Krogerus } 6893e10a2ceSHeikki Krogerus 69032f2ed86SWilliam Wu switch (dwc->hsphy_mode) { 69132f2ed86SWilliam Wu case USBPHY_INTERFACE_MODE_UTMI: 69232f2ed86SWilliam Wu reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | 69332f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); 69432f2ed86SWilliam Wu reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) | 69532f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT); 69632f2ed86SWilliam Wu break; 69732f2ed86SWilliam Wu case USBPHY_INTERFACE_MODE_UTMIW: 69832f2ed86SWilliam Wu reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | 69932f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); 70032f2ed86SWilliam Wu reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) | 70132f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT); 70232f2ed86SWilliam Wu break; 70332f2ed86SWilliam Wu default: 70432f2ed86SWilliam Wu break; 70532f2ed86SWilliam Wu } 70632f2ed86SWilliam Wu 7072164a476SHuang Rui /* 7082164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to 7092164a476SHuang Rui * '0' during coreConsultant configuration. So default value will 7102164a476SHuang Rui * be '0' when the core is reset. Application needs to set it to 7112164a476SHuang Rui * '1' after the core initialization is completed. 7122164a476SHuang Rui */ 7139af21dd6SThinh Nguyen if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) 7142164a476SHuang Rui reg |= DWC3_GUSB2PHYCFG_SUSPHY; 7152164a476SHuang Rui 7169ba3aca8SThinh Nguyen /* 7179ba3aca8SThinh Nguyen * For DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared after 7189ba3aca8SThinh Nguyen * power-on reset, and it can be set after core initialization, which is 7199ba3aca8SThinh Nguyen * after device soft-reset during initialization. 7209ba3aca8SThinh Nguyen */ 7219ba3aca8SThinh Nguyen if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD) 7229ba3aca8SThinh Nguyen reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 7239ba3aca8SThinh Nguyen 724cd72f890SFelipe Balbi if (dwc->dis_u2_susphy_quirk) 7250effe0a3SHuang Rui reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 7260effe0a3SHuang Rui 727ec791d14SJohn Youn if (dwc->dis_enblslpm_quirk) 728ec791d14SJohn Youn reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; 729eafeacf1SThinh Nguyen else 730eafeacf1SThinh Nguyen reg |= DWC3_GUSB2PHYCFG_ENBLSLPM; 731ec791d14SJohn Youn 73216199f33SWilliam Wu if (dwc->dis_u2_freeclk_exists_quirk) 73316199f33SWilliam Wu reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS; 73416199f33SWilliam Wu 7352164a476SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 73688bc9d19SHeikki Krogerus 73788bc9d19SHeikki Krogerus return 0; 738b5a65c40SHuang Rui } 739b5a65c40SHuang Rui 740c499ff71SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 741c499ff71SFelipe Balbi { 742c499ff71SFelipe Balbi dwc3_event_buffers_cleanup(dwc); 743c499ff71SFelipe Balbi 744c499ff71SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 745c499ff71SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 746c499ff71SFelipe Balbi phy_exit(dwc->usb2_generic_phy); 747c499ff71SFelipe Balbi phy_exit(dwc->usb3_generic_phy); 748c499ff71SFelipe Balbi 749c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 1); 750c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 1); 751c499ff71SFelipe Balbi phy_power_off(dwc->usb2_generic_phy); 752c499ff71SFelipe Balbi phy_power_off(dwc->usb3_generic_phy); 753240b65dcSAndrey Smirnov clk_bulk_disable_unprepare(dwc->num_clks, dwc->clks); 754fe8abf33SMasahiro Yamada reset_control_assert(dwc->reset); 755c499ff71SFelipe Balbi } 756c499ff71SFelipe Balbi 7570759956fSFelipe Balbi static bool dwc3_core_is_valid(struct dwc3 *dwc) 75872246da4SFelipe Balbi { 75972246da4SFelipe Balbi u32 reg; 76072246da4SFelipe Balbi 7617650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 7629af21dd6SThinh Nguyen dwc->ip = DWC3_GSNPS_ID(reg); 7630759956fSFelipe Balbi 7647650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 7659af21dd6SThinh Nguyen if (DWC3_IP_IS(DWC3)) { 766690fb371SJohn Youn dwc->revision = reg; 7679af21dd6SThinh Nguyen } else if (DWC3_IP_IS(DWC31) || DWC3_IP_IS(DWC32)) { 768690fb371SJohn Youn dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); 769475d8e01SThinh Nguyen dwc->version_type = dwc3_readl(dwc->regs, DWC3_VER_TYPE); 770690fb371SJohn Youn } else { 7710759956fSFelipe Balbi return false; 7727650bd74SSebastian Andrzej Siewior } 7737650bd74SSebastian Andrzej Siewior 7740759956fSFelipe Balbi return true; 7750e1e5c47SPaul Zimmerman } 7760e1e5c47SPaul Zimmerman 777941f918eSFelipe Balbi static void dwc3_core_setup_global_control(struct dwc3 *dwc) 77872246da4SFelipe Balbi { 77972246da4SFelipe Balbi u32 hwparams4 = dwc->hwparams.hwparams4; 78072246da4SFelipe Balbi u32 reg; 781c499ff71SFelipe Balbi 7824878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 7833e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 7844878a028SSebastian Andrzej Siewior 785164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 7864878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 78732a4a135SFelipe Balbi /** 78832a4a135SFelipe Balbi * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an 78932a4a135SFelipe Balbi * issue which would cause xHCI compliance tests to fail. 79032a4a135SFelipe Balbi * 79132a4a135SFelipe Balbi * Because of that we cannot enable clock gating on such 79232a4a135SFelipe Balbi * configurations. 79332a4a135SFelipe Balbi * 79432a4a135SFelipe Balbi * Refers to: 79532a4a135SFelipe Balbi * 79632a4a135SFelipe Balbi * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based 79732a4a135SFelipe Balbi * SOF/ITP Mode Used 79832a4a135SFelipe Balbi */ 79932a4a135SFelipe Balbi if ((dwc->dr_mode == USB_DR_MODE_HOST || 80032a4a135SFelipe Balbi dwc->dr_mode == USB_DR_MODE_OTG) && 8019af21dd6SThinh Nguyen DWC3_VER_IS_WITHIN(DWC3, 210A, 250A)) 80232a4a135SFelipe Balbi reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; 80332a4a135SFelipe Balbi else 8044878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 8054878a028SSebastian Andrzej Siewior break; 8060ffcaf37SFelipe Balbi case DWC3_GHWPARAMS1_EN_PWROPT_HIB: 8070ffcaf37SFelipe Balbi /* enable hibernation here */ 8080ffcaf37SFelipe Balbi dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); 8092eac3992SHuang Rui 8102eac3992SHuang Rui /* 8112eac3992SHuang Rui * REVISIT Enabling this bit so that host-mode hibernation 8122eac3992SHuang Rui * will work. Device-mode hibernation is not yet implemented. 8132eac3992SHuang Rui */ 8142eac3992SHuang Rui reg |= DWC3_GCTL_GBLHIBERNATIONEN; 8150ffcaf37SFelipe Balbi break; 8164878a028SSebastian Andrzej Siewior default: 8175eb30cedSFelipe Balbi /* nothing */ 8185eb30cedSFelipe Balbi break; 8194878a028SSebastian Andrzej Siewior } 8204878a028SSebastian Andrzej Siewior 821946bd579SHuang Rui /* check if current dwc3 is on simulation board */ 822946bd579SHuang Rui if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { 8236af19fd1SFaisal Mehmood dev_info(dwc->dev, "Running with FPGA optimizations\n"); 824946bd579SHuang Rui dwc->is_fpga = true; 825946bd579SHuang Rui } 826946bd579SHuang Rui 8273b81221aSHuang Rui WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga, 8283b81221aSHuang Rui "disable_scramble cannot be used on non-FPGA builds\n"); 8293b81221aSHuang Rui 8303b81221aSHuang Rui if (dwc->disable_scramble_quirk && dwc->is_fpga) 8313b81221aSHuang Rui reg |= DWC3_GCTL_DISSCRAMBLE; 8323b81221aSHuang Rui else 8333b81221aSHuang Rui reg &= ~DWC3_GCTL_DISSCRAMBLE; 8343b81221aSHuang Rui 8359a5b2f31SHuang Rui if (dwc->u2exit_lfps_quirk) 8369a5b2f31SHuang Rui reg |= DWC3_GCTL_U2EXIT_LFPS; 8379a5b2f31SHuang Rui 8384878a028SSebastian Andrzej Siewior /* 8394878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 8401d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 8414878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 8421d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 8434878a028SSebastian Andrzej Siewior */ 8449af21dd6SThinh Nguyen if (DWC3_VER_IS_PRIOR(DWC3, 190A)) 8454878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 8464878a028SSebastian Andrzej Siewior 8474878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 848941f918eSFelipe Balbi } 8494878a028SSebastian Andrzej Siewior 850f54edb53SFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc); 85198112041SRoger Quadros static int dwc3_core_ulpi_init(struct dwc3 *dwc); 852f54edb53SFelipe Balbi 853d9612c2fSPengbo Mu /* set global incr burst type configuration registers */ 854d9612c2fSPengbo Mu static void dwc3_set_incr_burst_type(struct dwc3 *dwc) 855d9612c2fSPengbo Mu { 856d9612c2fSPengbo Mu struct device *dev = dwc->dev; 857d9612c2fSPengbo Mu /* incrx_mode : for INCR burst type. */ 858d9612c2fSPengbo Mu bool incrx_mode; 859d9612c2fSPengbo Mu /* incrx_size : for size of INCRX burst. */ 860d9612c2fSPengbo Mu u32 incrx_size; 861d9612c2fSPengbo Mu u32 *vals; 862d9612c2fSPengbo Mu u32 cfg; 863d9612c2fSPengbo Mu int ntype; 864d9612c2fSPengbo Mu int ret; 865d9612c2fSPengbo Mu int i; 866d9612c2fSPengbo Mu 867d9612c2fSPengbo Mu cfg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0); 868d9612c2fSPengbo Mu 869d9612c2fSPengbo Mu /* 870d9612c2fSPengbo Mu * Handle property "snps,incr-burst-type-adjustment". 871d9612c2fSPengbo Mu * Get the number of value from this property: 872d9612c2fSPengbo Mu * result <= 0, means this property is not supported. 873d9612c2fSPengbo Mu * result = 1, means INCRx burst mode supported. 874d9612c2fSPengbo Mu * result > 1, means undefined length burst mode supported. 875d9612c2fSPengbo Mu */ 876a6e5e679SAndy Shevchenko ntype = device_property_count_u32(dev, "snps,incr-burst-type-adjustment"); 877d9612c2fSPengbo Mu if (ntype <= 0) 878d9612c2fSPengbo Mu return; 879d9612c2fSPengbo Mu 880d9612c2fSPengbo Mu vals = kcalloc(ntype, sizeof(u32), GFP_KERNEL); 881d9612c2fSPengbo Mu if (!vals) { 882d9612c2fSPengbo Mu dev_err(dev, "Error to get memory\n"); 883d9612c2fSPengbo Mu return; 884d9612c2fSPengbo Mu } 885d9612c2fSPengbo Mu 886d9612c2fSPengbo Mu /* Get INCR burst type, and parse it */ 887d9612c2fSPengbo Mu ret = device_property_read_u32_array(dev, 888d9612c2fSPengbo Mu "snps,incr-burst-type-adjustment", vals, ntype); 889d9612c2fSPengbo Mu if (ret) { 89075ecb9ddSAndy Shevchenko kfree(vals); 891d9612c2fSPengbo Mu dev_err(dev, "Error to get property\n"); 892d9612c2fSPengbo Mu return; 893d9612c2fSPengbo Mu } 894d9612c2fSPengbo Mu 895d9612c2fSPengbo Mu incrx_size = *vals; 896d9612c2fSPengbo Mu 897d9612c2fSPengbo Mu if (ntype > 1) { 898d9612c2fSPengbo Mu /* INCRX (undefined length) burst mode */ 899d9612c2fSPengbo Mu incrx_mode = INCRX_UNDEF_LENGTH_BURST_MODE; 900d9612c2fSPengbo Mu for (i = 1; i < ntype; i++) { 901d9612c2fSPengbo Mu if (vals[i] > incrx_size) 902d9612c2fSPengbo Mu incrx_size = vals[i]; 903d9612c2fSPengbo Mu } 904d9612c2fSPengbo Mu } else { 905d9612c2fSPengbo Mu /* INCRX burst mode */ 906d9612c2fSPengbo Mu incrx_mode = INCRX_BURST_MODE; 907d9612c2fSPengbo Mu } 908d9612c2fSPengbo Mu 90975ecb9ddSAndy Shevchenko kfree(vals); 91075ecb9ddSAndy Shevchenko 911d9612c2fSPengbo Mu /* Enable Undefined Length INCR Burst and Enable INCRx Burst */ 912d9612c2fSPengbo Mu cfg &= ~DWC3_GSBUSCFG0_INCRBRST_MASK; 913d9612c2fSPengbo Mu if (incrx_mode) 914d9612c2fSPengbo Mu cfg |= DWC3_GSBUSCFG0_INCRBRSTENA; 915d9612c2fSPengbo Mu switch (incrx_size) { 916d9612c2fSPengbo Mu case 256: 917d9612c2fSPengbo Mu cfg |= DWC3_GSBUSCFG0_INCR256BRSTENA; 918d9612c2fSPengbo Mu break; 919d9612c2fSPengbo Mu case 128: 920d9612c2fSPengbo Mu cfg |= DWC3_GSBUSCFG0_INCR128BRSTENA; 921d9612c2fSPengbo Mu break; 922d9612c2fSPengbo Mu case 64: 923d9612c2fSPengbo Mu cfg |= DWC3_GSBUSCFG0_INCR64BRSTENA; 924d9612c2fSPengbo Mu break; 925d9612c2fSPengbo Mu case 32: 926d9612c2fSPengbo Mu cfg |= DWC3_GSBUSCFG0_INCR32BRSTENA; 927d9612c2fSPengbo Mu break; 928d9612c2fSPengbo Mu case 16: 929d9612c2fSPengbo Mu cfg |= DWC3_GSBUSCFG0_INCR16BRSTENA; 930d9612c2fSPengbo Mu break; 931d9612c2fSPengbo Mu case 8: 932d9612c2fSPengbo Mu cfg |= DWC3_GSBUSCFG0_INCR8BRSTENA; 933d9612c2fSPengbo Mu break; 934d9612c2fSPengbo Mu case 4: 935d9612c2fSPengbo Mu cfg |= DWC3_GSBUSCFG0_INCR4BRSTENA; 936d9612c2fSPengbo Mu break; 937d9612c2fSPengbo Mu case 1: 938d9612c2fSPengbo Mu break; 939d9612c2fSPengbo Mu default: 940d9612c2fSPengbo Mu dev_err(dev, "Invalid property\n"); 941d9612c2fSPengbo Mu break; 942d9612c2fSPengbo Mu } 943d9612c2fSPengbo Mu 944d9612c2fSPengbo Mu dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, cfg); 945d9612c2fSPengbo Mu } 946d9612c2fSPengbo Mu 947941f918eSFelipe Balbi /** 948941f918eSFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 949941f918eSFelipe Balbi * @dwc: Pointer to our controller context structure 950941f918eSFelipe Balbi * 951941f918eSFelipe Balbi * Returns 0 on success otherwise negative errno. 952941f918eSFelipe Balbi */ 953941f918eSFelipe Balbi static int dwc3_core_init(struct dwc3 *dwc) 954941f918eSFelipe Balbi { 9559ba3aca8SThinh Nguyen unsigned int hw_mode; 956941f918eSFelipe Balbi u32 reg; 957941f918eSFelipe Balbi int ret; 958941f918eSFelipe Balbi 9599ba3aca8SThinh Nguyen hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0); 9609ba3aca8SThinh Nguyen 961941f918eSFelipe Balbi /* 962941f918eSFelipe Balbi * Write Linux Version Code to our GUID register so it's easy to figure 963941f918eSFelipe Balbi * out which kernel version a bug was found. 964941f918eSFelipe Balbi */ 965941f918eSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); 966941f918eSFelipe Balbi 967941f918eSFelipe Balbi ret = dwc3_phy_setup(dwc); 968941f918eSFelipe Balbi if (ret) 969941f918eSFelipe Balbi goto err0; 970941f918eSFelipe Balbi 97198112041SRoger Quadros if (!dwc->ulpi_ready) { 97298112041SRoger Quadros ret = dwc3_core_ulpi_init(dwc); 97398112041SRoger Quadros if (ret) 97498112041SRoger Quadros goto err0; 97598112041SRoger Quadros dwc->ulpi_ready = true; 97698112041SRoger Quadros } 97798112041SRoger Quadros 97898112041SRoger Quadros if (!dwc->phys_ready) { 97998112041SRoger Quadros ret = dwc3_core_get_phy(dwc); 98098112041SRoger Quadros if (ret) 98198112041SRoger Quadros goto err0a; 98298112041SRoger Quadros dwc->phys_ready = true; 98398112041SRoger Quadros } 98498112041SRoger Quadros 98598112041SRoger Quadros ret = dwc3_core_soft_reset(dwc); 98698112041SRoger Quadros if (ret) 98798112041SRoger Quadros goto err0a; 98898112041SRoger Quadros 9899ba3aca8SThinh Nguyen if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD && 9909af21dd6SThinh Nguyen !DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) { 9919ba3aca8SThinh Nguyen if (!dwc->dis_u3_susphy_quirk) { 9929ba3aca8SThinh Nguyen reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 9939ba3aca8SThinh Nguyen reg |= DWC3_GUSB3PIPECTL_SUSPHY; 9949ba3aca8SThinh Nguyen dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 9959ba3aca8SThinh Nguyen } 9969ba3aca8SThinh Nguyen 9979ba3aca8SThinh Nguyen if (!dwc->dis_u2_susphy_quirk) { 9989ba3aca8SThinh Nguyen reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 9999ba3aca8SThinh Nguyen reg |= DWC3_GUSB2PHYCFG_SUSPHY; 10009ba3aca8SThinh Nguyen dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 10019ba3aca8SThinh Nguyen } 10029ba3aca8SThinh Nguyen } 10039ba3aca8SThinh Nguyen 1004941f918eSFelipe Balbi dwc3_core_setup_global_control(dwc); 1005c499ff71SFelipe Balbi dwc3_core_num_eps(dwc); 10060ffcaf37SFelipe Balbi 10070ffcaf37SFelipe Balbi ret = dwc3_setup_scratch_buffers(dwc); 10080ffcaf37SFelipe Balbi if (ret) 1009c499ff71SFelipe Balbi goto err1; 1010c499ff71SFelipe Balbi 1011c499ff71SFelipe Balbi /* Adjust Frame Length */ 1012c499ff71SFelipe Balbi dwc3_frame_length_adjustment(dwc); 1013c499ff71SFelipe Balbi 1014d9612c2fSPengbo Mu dwc3_set_incr_burst_type(dwc); 1015d9612c2fSPengbo Mu 1016c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 0); 1017c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 0); 1018c499ff71SFelipe Balbi ret = phy_power_on(dwc->usb2_generic_phy); 1019c499ff71SFelipe Balbi if (ret < 0) 10200ffcaf37SFelipe Balbi goto err2; 10210ffcaf37SFelipe Balbi 1022c499ff71SFelipe Balbi ret = phy_power_on(dwc->usb3_generic_phy); 1023c499ff71SFelipe Balbi if (ret < 0) 1024c499ff71SFelipe Balbi goto err3; 1025c499ff71SFelipe Balbi 1026c499ff71SFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 1027c499ff71SFelipe Balbi if (ret) { 1028c499ff71SFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 1029c499ff71SFelipe Balbi goto err4; 1030c499ff71SFelipe Balbi } 1031c499ff71SFelipe Balbi 103206281d46SJohn Youn /* 103306281d46SJohn Youn * ENDXFER polling is available on version 3.10a and later of 103406281d46SJohn Youn * the DWC_usb3 controller. It is NOT available in the 103506281d46SJohn Youn * DWC_usb31 controller. 103606281d46SJohn Youn */ 10379af21dd6SThinh Nguyen if (DWC3_VER_IS_WITHIN(DWC3, 310A, ANY)) { 103806281d46SJohn Youn reg = dwc3_readl(dwc->regs, DWC3_GUCTL2); 103906281d46SJohn Youn reg |= DWC3_GUCTL2_RST_ACTBITLATER; 104006281d46SJohn Youn dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); 104106281d46SJohn Youn } 104206281d46SJohn Youn 10439af21dd6SThinh Nguyen if (!DWC3_VER_IS_PRIOR(DWC3, 250A)) { 10440bb39ca1SJohn Youn reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); 104565db7a0cSWilliam Wu 104665db7a0cSWilliam Wu /* 104765db7a0cSWilliam Wu * Enable hardware control of sending remote wakeup 104865db7a0cSWilliam Wu * in HS when the device is in the L1 state. 104965db7a0cSWilliam Wu */ 10509af21dd6SThinh Nguyen if (!DWC3_VER_IS_PRIOR(DWC3, 290A)) 10510bb39ca1SJohn Youn reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW; 105265db7a0cSWilliam Wu 105365db7a0cSWilliam Wu if (dwc->dis_tx_ipgap_linecheck_quirk) 105465db7a0cSWilliam Wu reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS; 105565db7a0cSWilliam Wu 10567ba6b09fSNeil Armstrong if (dwc->parkmode_disable_ss_quirk) 10577ba6b09fSNeil Armstrong reg |= DWC3_GUCTL1_PARKMODE_DISABLE_SS; 10587ba6b09fSNeil Armstrong 10590bb39ca1SJohn Youn dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); 10600bb39ca1SJohn Youn } 10610bb39ca1SJohn Youn 1062b138e23dSAnurag Kumar Vulisha if (dwc->dr_mode == USB_DR_MODE_HOST || 1063b138e23dSAnurag Kumar Vulisha dwc->dr_mode == USB_DR_MODE_OTG) { 1064b138e23dSAnurag Kumar Vulisha reg = dwc3_readl(dwc->regs, DWC3_GUCTL); 1065b138e23dSAnurag Kumar Vulisha 1066b138e23dSAnurag Kumar Vulisha /* 1067b138e23dSAnurag Kumar Vulisha * Enable Auto retry Feature to make the controller operating in 1068b138e23dSAnurag Kumar Vulisha * Host mode on seeing transaction errors(CRC errors or internal 1069b138e23dSAnurag Kumar Vulisha * overrun scenerios) on IN transfers to reply to the device 1070b138e23dSAnurag Kumar Vulisha * with a non-terminating retry ACK (i.e, an ACK transcation 1071b138e23dSAnurag Kumar Vulisha * packet with Retry=1 & Nump != 0) 1072b138e23dSAnurag Kumar Vulisha */ 1073b138e23dSAnurag Kumar Vulisha reg |= DWC3_GUCTL_HSTINAUTORETRY; 1074b138e23dSAnurag Kumar Vulisha 1075b138e23dSAnurag Kumar Vulisha dwc3_writel(dwc->regs, DWC3_GUCTL, reg); 1076b138e23dSAnurag Kumar Vulisha } 1077b138e23dSAnurag Kumar Vulisha 1078938a5ad1SThinh Nguyen /* 1079938a5ad1SThinh Nguyen * Must config both number of packets and max burst settings to enable 1080938a5ad1SThinh Nguyen * RX and/or TX threshold. 1081938a5ad1SThinh Nguyen */ 10829af21dd6SThinh Nguyen if (!DWC3_IP_IS(DWC3) && dwc->dr_mode == USB_DR_MODE_HOST) { 1083938a5ad1SThinh Nguyen u8 rx_thr_num = dwc->rx_thr_num_pkt_prd; 1084938a5ad1SThinh Nguyen u8 rx_maxburst = dwc->rx_max_burst_prd; 1085938a5ad1SThinh Nguyen u8 tx_thr_num = dwc->tx_thr_num_pkt_prd; 1086938a5ad1SThinh Nguyen u8 tx_maxburst = dwc->tx_max_burst_prd; 1087938a5ad1SThinh Nguyen 1088938a5ad1SThinh Nguyen if (rx_thr_num && rx_maxburst) { 1089938a5ad1SThinh Nguyen reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG); 1090938a5ad1SThinh Nguyen reg |= DWC31_RXTHRNUMPKTSEL_PRD; 1091938a5ad1SThinh Nguyen 1092938a5ad1SThinh Nguyen reg &= ~DWC31_RXTHRNUMPKT_PRD(~0); 1093938a5ad1SThinh Nguyen reg |= DWC31_RXTHRNUMPKT_PRD(rx_thr_num); 1094938a5ad1SThinh Nguyen 1095938a5ad1SThinh Nguyen reg &= ~DWC31_MAXRXBURSTSIZE_PRD(~0); 1096938a5ad1SThinh Nguyen reg |= DWC31_MAXRXBURSTSIZE_PRD(rx_maxburst); 1097938a5ad1SThinh Nguyen 1098938a5ad1SThinh Nguyen dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg); 1099938a5ad1SThinh Nguyen } 1100938a5ad1SThinh Nguyen 1101938a5ad1SThinh Nguyen if (tx_thr_num && tx_maxburst) { 1102938a5ad1SThinh Nguyen reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG); 1103938a5ad1SThinh Nguyen reg |= DWC31_TXTHRNUMPKTSEL_PRD; 1104938a5ad1SThinh Nguyen 1105938a5ad1SThinh Nguyen reg &= ~DWC31_TXTHRNUMPKT_PRD(~0); 1106938a5ad1SThinh Nguyen reg |= DWC31_TXTHRNUMPKT_PRD(tx_thr_num); 1107938a5ad1SThinh Nguyen 1108938a5ad1SThinh Nguyen reg &= ~DWC31_MAXTXBURSTSIZE_PRD(~0); 1109938a5ad1SThinh Nguyen reg |= DWC31_MAXTXBURSTSIZE_PRD(tx_maxburst); 1110938a5ad1SThinh Nguyen 1111938a5ad1SThinh Nguyen dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg); 1112938a5ad1SThinh Nguyen } 1113938a5ad1SThinh Nguyen } 1114938a5ad1SThinh Nguyen 111572246da4SFelipe Balbi return 0; 111672246da4SFelipe Balbi 1117c499ff71SFelipe Balbi err4: 11189b9d7cddSVivek Gautam phy_power_off(dwc->usb3_generic_phy); 1119c499ff71SFelipe Balbi 1120c499ff71SFelipe Balbi err3: 11219b9d7cddSVivek Gautam phy_power_off(dwc->usb2_generic_phy); 1122c499ff71SFelipe Balbi 11230ffcaf37SFelipe Balbi err2: 1124c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 1); 1125c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 1); 11260ffcaf37SFelipe Balbi 11270ffcaf37SFelipe Balbi err1: 11280ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 11290ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 113057303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 113157303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 11320ffcaf37SFelipe Balbi 113398112041SRoger Quadros err0a: 113498112041SRoger Quadros dwc3_ulpi_exit(dwc); 113598112041SRoger Quadros 113672246da4SFelipe Balbi err0: 113772246da4SFelipe Balbi return ret; 113872246da4SFelipe Balbi } 113972246da4SFelipe Balbi 11403c9f94acSFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc) 114172246da4SFelipe Balbi { 11423c9f94acSFelipe Balbi struct device *dev = dwc->dev; 1143941ea361SFelipe Balbi struct device_node *node = dev->of_node; 11443c9f94acSFelipe Balbi int ret; 114572246da4SFelipe Balbi 11465088b6f5SKishon Vijay Abraham I if (node) { 11475088b6f5SKishon Vijay Abraham I dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); 11485088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); 1149bb674907SFelipe Balbi } else { 1150bb674907SFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 1151bb674907SFelipe Balbi dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 11525088b6f5SKishon Vijay Abraham I } 11535088b6f5SKishon Vijay Abraham I 1154d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb2_phy)) { 1155d105e7f8SFelipe Balbi ret = PTR_ERR(dwc->usb2_phy); 1156122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 1157122f06e6SKishon Vijay Abraham I dwc->usb2_phy = NULL; 1158122f06e6SKishon Vijay Abraham I } else { 11590c0a20f6SAndy Shevchenko return dev_err_probe(dev, ret, "no usb2 phy configured\n"); 1160122f06e6SKishon Vijay Abraham I } 116151e1e7bcSFelipe Balbi } 116251e1e7bcSFelipe Balbi 1163d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb3_phy)) { 1164315955d7SRuchika Kharwar ret = PTR_ERR(dwc->usb3_phy); 1165122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 1166122f06e6SKishon Vijay Abraham I dwc->usb3_phy = NULL; 1167122f06e6SKishon Vijay Abraham I } else { 11680c0a20f6SAndy Shevchenko return dev_err_probe(dev, ret, "no usb3 phy configured\n"); 1169122f06e6SKishon Vijay Abraham I } 117051e1e7bcSFelipe Balbi } 117151e1e7bcSFelipe Balbi 117257303488SKishon Vijay Abraham I dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); 117357303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb2_generic_phy)) { 117457303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb2_generic_phy); 117557303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 117657303488SKishon Vijay Abraham I dwc->usb2_generic_phy = NULL; 117757303488SKishon Vijay Abraham I } else { 11780c0a20f6SAndy Shevchenko return dev_err_probe(dev, ret, "no usb2 phy configured\n"); 117957303488SKishon Vijay Abraham I } 118057303488SKishon Vijay Abraham I } 118157303488SKishon Vijay Abraham I 118257303488SKishon Vijay Abraham I dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy"); 118357303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb3_generic_phy)) { 118457303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb3_generic_phy); 118557303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 118657303488SKishon Vijay Abraham I dwc->usb3_generic_phy = NULL; 118757303488SKishon Vijay Abraham I } else { 11880c0a20f6SAndy Shevchenko return dev_err_probe(dev, ret, "no usb3 phy configured\n"); 118957303488SKishon Vijay Abraham I } 119057303488SKishon Vijay Abraham I } 119157303488SKishon Vijay Abraham I 11923c9f94acSFelipe Balbi return 0; 11933c9f94acSFelipe Balbi } 11943c9f94acSFelipe Balbi 11955f94adfeSFelipe Balbi static int dwc3_core_init_mode(struct dwc3 *dwc) 11965f94adfeSFelipe Balbi { 11975f94adfeSFelipe Balbi struct device *dev = dwc->dev; 11985f94adfeSFelipe Balbi int ret; 11995f94adfeSFelipe Balbi 12005f94adfeSFelipe Balbi switch (dwc->dr_mode) { 12015f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 120241ce1456SRoger Quadros dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); 1203958d1a4cSFelipe Balbi 1204958d1a4cSFelipe Balbi if (dwc->usb2_phy) 1205958d1a4cSFelipe Balbi otg_set_vbus(dwc->usb2_phy->otg, false); 1206958d1a4cSFelipe Balbi phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE); 1207644cbbc3SManu Gautam phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE); 1208958d1a4cSFelipe Balbi 12095f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 12100c0a20f6SAndy Shevchenko if (ret) 12110c0a20f6SAndy Shevchenko return dev_err_probe(dev, ret, "failed to initialize gadget\n"); 12125f94adfeSFelipe Balbi break; 12135f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 121441ce1456SRoger Quadros dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); 1215958d1a4cSFelipe Balbi 1216958d1a4cSFelipe Balbi if (dwc->usb2_phy) 1217958d1a4cSFelipe Balbi otg_set_vbus(dwc->usb2_phy->otg, true); 1218958d1a4cSFelipe Balbi phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); 1219644cbbc3SManu Gautam phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST); 1220958d1a4cSFelipe Balbi 12215f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 12220c0a20f6SAndy Shevchenko if (ret) 12230c0a20f6SAndy Shevchenko return dev_err_probe(dev, ret, "failed to initialize host\n"); 12245f94adfeSFelipe Balbi break; 12255f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 122641ce1456SRoger Quadros INIT_WORK(&dwc->drd_work, __dwc3_set_mode); 12279840354fSRoger Quadros ret = dwc3_drd_init(dwc); 12280c0a20f6SAndy Shevchenko if (ret) 12290c0a20f6SAndy Shevchenko return dev_err_probe(dev, ret, "failed to initialize dual-role\n"); 12305f94adfeSFelipe Balbi break; 12315f94adfeSFelipe Balbi default: 12325f94adfeSFelipe Balbi dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); 12335f94adfeSFelipe Balbi return -EINVAL; 12345f94adfeSFelipe Balbi } 12355f94adfeSFelipe Balbi 12365f94adfeSFelipe Balbi return 0; 12375f94adfeSFelipe Balbi } 12385f94adfeSFelipe Balbi 12395f94adfeSFelipe Balbi static void dwc3_core_exit_mode(struct dwc3 *dwc) 12405f94adfeSFelipe Balbi { 12415f94adfeSFelipe Balbi switch (dwc->dr_mode) { 12425f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 12435f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 12445f94adfeSFelipe Balbi break; 12455f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 12465f94adfeSFelipe Balbi dwc3_host_exit(dwc); 12475f94adfeSFelipe Balbi break; 12485f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 12499840354fSRoger Quadros dwc3_drd_exit(dwc); 12505f94adfeSFelipe Balbi break; 12515f94adfeSFelipe Balbi default: 12525f94adfeSFelipe Balbi /* do nothing */ 12535f94adfeSFelipe Balbi break; 12545f94adfeSFelipe Balbi } 125509ed259fSBin Liu 125609ed259fSBin Liu /* de-assert DRVVBUS for HOST and OTG mode */ 125709ed259fSBin Liu dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); 12585f94adfeSFelipe Balbi } 12595f94adfeSFelipe Balbi 1260c5ac6116SFelipe Balbi static void dwc3_get_properties(struct dwc3 *dwc) 12613c9f94acSFelipe Balbi { 1262c5ac6116SFelipe Balbi struct device *dev = dwc->dev; 126380caf7d2SHuang Rui u8 lpm_nyet_threshold; 12646b6a0c9aSHuang Rui u8 tx_de_emphasis; 1265460d098cSHuang Rui u8 hird_threshold; 1266938a5ad1SThinh Nguyen u8 rx_thr_num_pkt_prd; 1267938a5ad1SThinh Nguyen u8 rx_max_burst_prd; 1268938a5ad1SThinh Nguyen u8 tx_thr_num_pkt_prd; 1269938a5ad1SThinh Nguyen u8 tx_max_burst_prd; 12706f0764b5SRay Chi const char *usb_psy_name; 12716f0764b5SRay Chi int ret; 12723c9f94acSFelipe Balbi 127380caf7d2SHuang Rui /* default to highest possible threshold */ 12748d791929SThinh Nguyen lpm_nyet_threshold = 0xf; 127580caf7d2SHuang Rui 12766b6a0c9aSHuang Rui /* default to -3.5dB de-emphasis */ 12776b6a0c9aSHuang Rui tx_de_emphasis = 1; 12786b6a0c9aSHuang Rui 1279460d098cSHuang Rui /* 1280460d098cSHuang Rui * default to assert utmi_sleep_n and use maximum allowed HIRD 1281460d098cSHuang Rui * threshold value of 0b1100 1282460d098cSHuang Rui */ 1283460d098cSHuang Rui hird_threshold = 12; 1284460d098cSHuang Rui 128563863b98SHeikki Krogerus dwc->maximum_speed = usb_get_maximum_speed(dev); 128667848146SThinh Nguyen dwc->max_ssp_rate = usb_get_maximum_ssp_rate(dev); 128706e7114fSHeikki Krogerus dwc->dr_mode = usb_get_dr_mode(dev); 128832f2ed86SWilliam Wu dwc->hsphy_mode = of_usb_get_phy_mode(dev->of_node); 128963863b98SHeikki Krogerus 1290d64ff406SArnd Bergmann dwc->sysdev_is_parent = device_property_read_bool(dev, 1291d64ff406SArnd Bergmann "linux,sysdev_is_parent"); 1292d64ff406SArnd Bergmann if (dwc->sysdev_is_parent) 1293d64ff406SArnd Bergmann dwc->sysdev = dwc->dev->parent; 1294d64ff406SArnd Bergmann else 1295d64ff406SArnd Bergmann dwc->sysdev = dwc->dev; 1296d64ff406SArnd Bergmann 12976f0764b5SRay Chi ret = device_property_read_string(dev, "usb-psy-name", &usb_psy_name); 12986f0764b5SRay Chi if (ret >= 0) { 12996f0764b5SRay Chi dwc->usb_psy = power_supply_get_by_name(usb_psy_name); 13006f0764b5SRay Chi if (!dwc->usb_psy) 13016f0764b5SRay Chi dev_err(dev, "couldn't get usb power supply\n"); 13026f0764b5SRay Chi } 13036f0764b5SRay Chi 13043d128919SHeikki Krogerus dwc->has_lpm_erratum = device_property_read_bool(dev, 130580caf7d2SHuang Rui "snps,has-lpm-erratum"); 13063d128919SHeikki Krogerus device_property_read_u8(dev, "snps,lpm-nyet-threshold", 130780caf7d2SHuang Rui &lpm_nyet_threshold); 13083d128919SHeikki Krogerus dwc->is_utmi_l1_suspend = device_property_read_bool(dev, 1309460d098cSHuang Rui "snps,is-utmi-l1-suspend"); 13103d128919SHeikki Krogerus device_property_read_u8(dev, "snps,hird-threshold", 1311460d098cSHuang Rui &hird_threshold); 1312d92021f6SThinh Nguyen dwc->dis_start_transfer_quirk = device_property_read_bool(dev, 1313d92021f6SThinh Nguyen "snps,dis-start-transfer-quirk"); 13143d128919SHeikki Krogerus dwc->usb3_lpm_capable = device_property_read_bool(dev, 1315eac68e8fSRobert Baldyga "snps,usb3_lpm_capable"); 1316022a0208SThinh Nguyen dwc->usb2_lpm_disable = device_property_read_bool(dev, 1317022a0208SThinh Nguyen "snps,usb2-lpm-disable"); 1318475e8be5SThinh Nguyen dwc->usb2_gadget_lpm_disable = device_property_read_bool(dev, 1319475e8be5SThinh Nguyen "snps,usb2-gadget-lpm-disable"); 1320938a5ad1SThinh Nguyen device_property_read_u8(dev, "snps,rx-thr-num-pkt-prd", 1321938a5ad1SThinh Nguyen &rx_thr_num_pkt_prd); 1322938a5ad1SThinh Nguyen device_property_read_u8(dev, "snps,rx-max-burst-prd", 1323938a5ad1SThinh Nguyen &rx_max_burst_prd); 1324938a5ad1SThinh Nguyen device_property_read_u8(dev, "snps,tx-thr-num-pkt-prd", 1325938a5ad1SThinh Nguyen &tx_thr_num_pkt_prd); 1326938a5ad1SThinh Nguyen device_property_read_u8(dev, "snps,tx-max-burst-prd", 1327938a5ad1SThinh Nguyen &tx_max_burst_prd); 13283c9f94acSFelipe Balbi 13293d128919SHeikki Krogerus dwc->disable_scramble_quirk = device_property_read_bool(dev, 13303b81221aSHuang Rui "snps,disable_scramble_quirk"); 13313d128919SHeikki Krogerus dwc->u2exit_lfps_quirk = device_property_read_bool(dev, 13329a5b2f31SHuang Rui "snps,u2exit_lfps_quirk"); 13333d128919SHeikki Krogerus dwc->u2ss_inp3_quirk = device_property_read_bool(dev, 1334b5a65c40SHuang Rui "snps,u2ss_inp3_quirk"); 13353d128919SHeikki Krogerus dwc->req_p1p2p3_quirk = device_property_read_bool(dev, 1336df31f5b3SHuang Rui "snps,req_p1p2p3_quirk"); 13373d128919SHeikki Krogerus dwc->del_p1p2p3_quirk = device_property_read_bool(dev, 1338a2a1d0f5SHuang Rui "snps,del_p1p2p3_quirk"); 13393d128919SHeikki Krogerus dwc->del_phy_power_chg_quirk = device_property_read_bool(dev, 134041c06ffdSHuang Rui "snps,del_phy_power_chg_quirk"); 13413d128919SHeikki Krogerus dwc->lfps_filter_quirk = device_property_read_bool(dev, 1342fb67afcaSHuang Rui "snps,lfps_filter_quirk"); 13433d128919SHeikki Krogerus dwc->rx_detect_poll_quirk = device_property_read_bool(dev, 134414f4ac53SHuang Rui "snps,rx_detect_poll_quirk"); 13453d128919SHeikki Krogerus dwc->dis_u3_susphy_quirk = device_property_read_bool(dev, 134659acfa20SHuang Rui "snps,dis_u3_susphy_quirk"); 13473d128919SHeikki Krogerus dwc->dis_u2_susphy_quirk = device_property_read_bool(dev, 13480effe0a3SHuang Rui "snps,dis_u2_susphy_quirk"); 1349ec791d14SJohn Youn dwc->dis_enblslpm_quirk = device_property_read_bool(dev, 1350ec791d14SJohn Youn "snps,dis_enblslpm_quirk"); 1351729dcffdSAnurag Kumar Vulisha dwc->dis_u1_entry_quirk = device_property_read_bool(dev, 1352729dcffdSAnurag Kumar Vulisha "snps,dis-u1-entry-quirk"); 1353729dcffdSAnurag Kumar Vulisha dwc->dis_u2_entry_quirk = device_property_read_bool(dev, 1354729dcffdSAnurag Kumar Vulisha "snps,dis-u2-entry-quirk"); 1355e58dd357SRajesh Bhagat dwc->dis_rxdet_inp3_quirk = device_property_read_bool(dev, 1356e58dd357SRajesh Bhagat "snps,dis_rxdet_inp3_quirk"); 135716199f33SWilliam Wu dwc->dis_u2_freeclk_exists_quirk = device_property_read_bool(dev, 135816199f33SWilliam Wu "snps,dis-u2-freeclk-exists-quirk"); 135900fe081dSWilliam Wu dwc->dis_del_phy_power_chg_quirk = device_property_read_bool(dev, 136000fe081dSWilliam Wu "snps,dis-del-phy-power-chg-quirk"); 136165db7a0cSWilliam Wu dwc->dis_tx_ipgap_linecheck_quirk = device_property_read_bool(dev, 136265db7a0cSWilliam Wu "snps,dis-tx-ipgap-linecheck-quirk"); 13637ba6b09fSNeil Armstrong dwc->parkmode_disable_ss_quirk = device_property_read_bool(dev, 13647ba6b09fSNeil Armstrong "snps,parkmode-disable-ss-quirk"); 13656b6a0c9aSHuang Rui 13663d128919SHeikki Krogerus dwc->tx_de_emphasis_quirk = device_property_read_bool(dev, 13676b6a0c9aSHuang Rui "snps,tx_de_emphasis_quirk"); 13683d128919SHeikki Krogerus device_property_read_u8(dev, "snps,tx_de_emphasis", 13696b6a0c9aSHuang Rui &tx_de_emphasis); 13703d128919SHeikki Krogerus device_property_read_string(dev, "snps,hsphy_interface", 13713e10a2ceSHeikki Krogerus &dwc->hsphy_interface); 13723d128919SHeikki Krogerus device_property_read_u32(dev, "snps,quirk-frame-length-adjustment", 1373bcdb3272SFelipe Balbi &dwc->fladj); 13743d128919SHeikki Krogerus 137542bf02ecSRoger Quadros dwc->dis_metastability_quirk = device_property_read_bool(dev, 137642bf02ecSRoger Quadros "snps,dis_metastability_quirk"); 137742bf02ecSRoger Quadros 1378f580170fSYu Chen dwc->dis_split_quirk = device_property_read_bool(dev, 1379f580170fSYu Chen "snps,dis-split-quirk"); 1380f580170fSYu Chen 138180caf7d2SHuang Rui dwc->lpm_nyet_threshold = lpm_nyet_threshold; 13826b6a0c9aSHuang Rui dwc->tx_de_emphasis = tx_de_emphasis; 138380caf7d2SHuang Rui 138416fe4f30SThinh Nguyen dwc->hird_threshold = hird_threshold; 1385460d098cSHuang Rui 1386938a5ad1SThinh Nguyen dwc->rx_thr_num_pkt_prd = rx_thr_num_pkt_prd; 1387938a5ad1SThinh Nguyen dwc->rx_max_burst_prd = rx_max_burst_prd; 1388938a5ad1SThinh Nguyen 1389938a5ad1SThinh Nguyen dwc->tx_thr_num_pkt_prd = tx_thr_num_pkt_prd; 1390938a5ad1SThinh Nguyen dwc->tx_max_burst_prd = tx_max_burst_prd; 1391938a5ad1SThinh Nguyen 1392cf40b86bSJohn Youn dwc->imod_interval = 0; 1393cf40b86bSJohn Youn } 1394cf40b86bSJohn Youn 1395cf40b86bSJohn Youn /* check whether the core supports IMOD */ 1396cf40b86bSJohn Youn bool dwc3_has_imod(struct dwc3 *dwc) 1397cf40b86bSJohn Youn { 13989af21dd6SThinh Nguyen return DWC3_VER_IS_WITHIN(DWC3, 300A, ANY) || 13999af21dd6SThinh Nguyen DWC3_VER_IS_WITHIN(DWC31, 120A, ANY) || 14009af21dd6SThinh Nguyen DWC3_IP_IS(DWC32); 1401c5ac6116SFelipe Balbi } 1402c5ac6116SFelipe Balbi 14037ac51a12SJohn Youn static void dwc3_check_params(struct dwc3 *dwc) 14047ac51a12SJohn Youn { 14057ac51a12SJohn Youn struct device *dev = dwc->dev; 1406b574ce3eSThinh Nguyen unsigned int hwparam_gen = 1407b574ce3eSThinh Nguyen DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3); 14087ac51a12SJohn Youn 1409cf40b86bSJohn Youn /* Check for proper value of imod_interval */ 1410cf40b86bSJohn Youn if (dwc->imod_interval && !dwc3_has_imod(dwc)) { 1411cf40b86bSJohn Youn dev_warn(dwc->dev, "Interrupt moderation not supported\n"); 1412cf40b86bSJohn Youn dwc->imod_interval = 0; 1413cf40b86bSJohn Youn } 1414cf40b86bSJohn Youn 141528632b44SJohn Youn /* 141628632b44SJohn Youn * Workaround for STAR 9000961433 which affects only version 141728632b44SJohn Youn * 3.00a of the DWC_usb3 core. This prevents the controller 141828632b44SJohn Youn * interrupt from being masked while handling events. IMOD 141928632b44SJohn Youn * allows us to work around this issue. Enable it for the 142028632b44SJohn Youn * affected version. 142128632b44SJohn Youn */ 142228632b44SJohn Youn if (!dwc->imod_interval && 14239af21dd6SThinh Nguyen DWC3_VER_IS(DWC3, 300A)) 142428632b44SJohn Youn dwc->imod_interval = 1; 142528632b44SJohn Youn 14267ac51a12SJohn Youn /* Check the maximum_speed parameter */ 14277ac51a12SJohn Youn switch (dwc->maximum_speed) { 14287ac51a12SJohn Youn case USB_SPEED_FULL: 14297ac51a12SJohn Youn case USB_SPEED_HIGH: 1430e518bdd9SThinh Nguyen break; 14317ac51a12SJohn Youn case USB_SPEED_SUPER: 1432e518bdd9SThinh Nguyen if (hwparam_gen == DWC3_GHWPARAMS3_SSPHY_IFC_DIS) 1433e518bdd9SThinh Nguyen dev_warn(dev, "UDC doesn't support Gen 1\n"); 1434e518bdd9SThinh Nguyen break; 14357ac51a12SJohn Youn case USB_SPEED_SUPER_PLUS: 1436e518bdd9SThinh Nguyen if ((DWC3_IP_IS(DWC32) && 1437e518bdd9SThinh Nguyen hwparam_gen == DWC3_GHWPARAMS3_SSPHY_IFC_DIS) || 1438e518bdd9SThinh Nguyen (!DWC3_IP_IS(DWC32) && 1439e518bdd9SThinh Nguyen hwparam_gen != DWC3_GHWPARAMS3_SSPHY_IFC_GEN2)) 1440e518bdd9SThinh Nguyen dev_warn(dev, "UDC doesn't support SSP\n"); 14417ac51a12SJohn Youn break; 14427ac51a12SJohn Youn default: 14437ac51a12SJohn Youn dev_err(dev, "invalid maximum_speed parameter %d\n", 14447ac51a12SJohn Youn dwc->maximum_speed); 1445df561f66SGustavo A. R. Silva fallthrough; 14467ac51a12SJohn Youn case USB_SPEED_UNKNOWN: 1447b574ce3eSThinh Nguyen switch (hwparam_gen) { 1448b574ce3eSThinh Nguyen case DWC3_GHWPARAMS3_SSPHY_IFC_GEN2: 14497ac51a12SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER_PLUS; 1450b574ce3eSThinh Nguyen break; 1451b574ce3eSThinh Nguyen case DWC3_GHWPARAMS3_SSPHY_IFC_GEN1: 1452b574ce3eSThinh Nguyen if (DWC3_IP_IS(DWC32)) 1453b574ce3eSThinh Nguyen dwc->maximum_speed = USB_SPEED_SUPER_PLUS; 1454b574ce3eSThinh Nguyen else 1455b574ce3eSThinh Nguyen dwc->maximum_speed = USB_SPEED_SUPER; 1456b574ce3eSThinh Nguyen break; 1457b574ce3eSThinh Nguyen case DWC3_GHWPARAMS3_SSPHY_IFC_DIS: 1458b574ce3eSThinh Nguyen dwc->maximum_speed = USB_SPEED_HIGH; 1459b574ce3eSThinh Nguyen break; 1460b574ce3eSThinh Nguyen default: 1461b574ce3eSThinh Nguyen dwc->maximum_speed = USB_SPEED_SUPER; 1462b574ce3eSThinh Nguyen break; 1463b574ce3eSThinh Nguyen } 14647ac51a12SJohn Youn break; 14657ac51a12SJohn Youn } 146667848146SThinh Nguyen 146767848146SThinh Nguyen /* 146867848146SThinh Nguyen * Currently the controller does not have visibility into the HW 146967848146SThinh Nguyen * parameter to determine the maximum number of lanes the HW supports. 147067848146SThinh Nguyen * If the number of lanes is not specified in the device property, then 147167848146SThinh Nguyen * set the default to support dual-lane for DWC_usb32 and single-lane 147267848146SThinh Nguyen * for DWC_usb31 for super-speed-plus. 147367848146SThinh Nguyen */ 147467848146SThinh Nguyen if (dwc->maximum_speed == USB_SPEED_SUPER_PLUS) { 147567848146SThinh Nguyen switch (dwc->max_ssp_rate) { 147667848146SThinh Nguyen case USB_SSP_GEN_2x1: 147767848146SThinh Nguyen if (hwparam_gen == DWC3_GHWPARAMS3_SSPHY_IFC_GEN1) 147867848146SThinh Nguyen dev_warn(dev, "UDC only supports Gen 1\n"); 147967848146SThinh Nguyen break; 148067848146SThinh Nguyen case USB_SSP_GEN_1x2: 148167848146SThinh Nguyen case USB_SSP_GEN_2x2: 148267848146SThinh Nguyen if (DWC3_IP_IS(DWC31)) 148367848146SThinh Nguyen dev_warn(dev, "UDC only supports single lane\n"); 148467848146SThinh Nguyen break; 148567848146SThinh Nguyen case USB_SSP_GEN_UNKNOWN: 148667848146SThinh Nguyen default: 148767848146SThinh Nguyen switch (hwparam_gen) { 148867848146SThinh Nguyen case DWC3_GHWPARAMS3_SSPHY_IFC_GEN2: 148967848146SThinh Nguyen if (DWC3_IP_IS(DWC32)) 149067848146SThinh Nguyen dwc->max_ssp_rate = USB_SSP_GEN_2x2; 149167848146SThinh Nguyen else 149267848146SThinh Nguyen dwc->max_ssp_rate = USB_SSP_GEN_2x1; 149367848146SThinh Nguyen break; 149467848146SThinh Nguyen case DWC3_GHWPARAMS3_SSPHY_IFC_GEN1: 149567848146SThinh Nguyen if (DWC3_IP_IS(DWC32)) 149667848146SThinh Nguyen dwc->max_ssp_rate = USB_SSP_GEN_1x2; 149767848146SThinh Nguyen break; 149867848146SThinh Nguyen } 149967848146SThinh Nguyen break; 150067848146SThinh Nguyen } 150167848146SThinh Nguyen } 15027ac51a12SJohn Youn } 15037ac51a12SJohn Youn 1504c5ac6116SFelipe Balbi static int dwc3_probe(struct platform_device *pdev) 1505c5ac6116SFelipe Balbi { 1506c5ac6116SFelipe Balbi struct device *dev = &pdev->dev; 150744feb8e6SMasahiro Yamada struct resource *res, dwc_res; 1508c5ac6116SFelipe Balbi struct dwc3 *dwc; 1509c5ac6116SFelipe Balbi 1510c5ac6116SFelipe Balbi int ret; 1511c5ac6116SFelipe Balbi 1512c5ac6116SFelipe Balbi void __iomem *regs; 1513c5ac6116SFelipe Balbi 1514c5ac6116SFelipe Balbi dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL); 1515c5ac6116SFelipe Balbi if (!dwc) 1516c5ac6116SFelipe Balbi return -ENOMEM; 1517c5ac6116SFelipe Balbi 1518c5ac6116SFelipe Balbi dwc->dev = dev; 1519c5ac6116SFelipe Balbi 1520c5ac6116SFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1521c5ac6116SFelipe Balbi if (!res) { 1522c5ac6116SFelipe Balbi dev_err(dev, "missing memory resource\n"); 1523c5ac6116SFelipe Balbi return -ENODEV; 1524c5ac6116SFelipe Balbi } 1525c5ac6116SFelipe Balbi 1526c5ac6116SFelipe Balbi dwc->xhci_resources[0].start = res->start; 1527c5ac6116SFelipe Balbi dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 1528c5ac6116SFelipe Balbi DWC3_XHCI_REGS_END; 1529c5ac6116SFelipe Balbi dwc->xhci_resources[0].flags = res->flags; 1530c5ac6116SFelipe Balbi dwc->xhci_resources[0].name = res->name; 1531c5ac6116SFelipe Balbi 1532c5ac6116SFelipe Balbi /* 1533c5ac6116SFelipe Balbi * Request memory region but exclude xHCI regs, 1534c5ac6116SFelipe Balbi * since it will be requested by the xhci-plat driver. 1535c5ac6116SFelipe Balbi */ 153644feb8e6SMasahiro Yamada dwc_res = *res; 153744feb8e6SMasahiro Yamada dwc_res.start += DWC3_GLOBALS_REGS_START; 153844feb8e6SMasahiro Yamada 153944feb8e6SMasahiro Yamada regs = devm_ioremap_resource(dev, &dwc_res); 154044feb8e6SMasahiro Yamada if (IS_ERR(regs)) 154144feb8e6SMasahiro Yamada return PTR_ERR(regs); 1542c5ac6116SFelipe Balbi 1543c5ac6116SFelipe Balbi dwc->regs = regs; 154444feb8e6SMasahiro Yamada dwc->regs_size = resource_size(&dwc_res); 1545c5ac6116SFelipe Balbi 1546c5ac6116SFelipe Balbi dwc3_get_properties(dwc); 1547c5ac6116SFelipe Balbi 1548*45d39448SSven Peter ret = dma_set_mask_and_coherent(dwc->sysdev, DMA_BIT_MASK(64)); 1549*45d39448SSven Peter if (ret) 1550*45d39448SSven Peter return ret; 1551*45d39448SSven Peter 1552babbdfc9SYejune Deng dwc->reset = devm_reset_control_array_get_optional_shared(dev); 1553fe8abf33SMasahiro Yamada if (IS_ERR(dwc->reset)) 1554fe8abf33SMasahiro Yamada return PTR_ERR(dwc->reset); 1555fe8abf33SMasahiro Yamada 155661527777SHans de Goede if (dev->of_node) { 15570d3a9708SJohn Stultz ret = devm_clk_bulk_get_all(dev, &dwc->clks); 1558fe8abf33SMasahiro Yamada if (ret == -EPROBE_DEFER) 1559fe8abf33SMasahiro Yamada return ret; 1560fe8abf33SMasahiro Yamada /* 156161527777SHans de Goede * Clocks are optional, but new DT platforms should support all 156261527777SHans de Goede * clocks as required by the DT-binding. 1563fe8abf33SMasahiro Yamada */ 15640d3a9708SJohn Stultz if (ret < 0) 1565fe8abf33SMasahiro Yamada dwc->num_clks = 0; 15660d3a9708SJohn Stultz else 15670d3a9708SJohn Stultz dwc->num_clks = ret; 15680d3a9708SJohn Stultz 156961527777SHans de Goede } 1570fe8abf33SMasahiro Yamada 1571fe8abf33SMasahiro Yamada ret = reset_control_deassert(dwc->reset); 1572fe8abf33SMasahiro Yamada if (ret) 157303bf32bbSAndrey Smirnov return ret; 1574fe8abf33SMasahiro Yamada 1575240b65dcSAndrey Smirnov ret = clk_bulk_prepare_enable(dwc->num_clks, dwc->clks); 1576fe8abf33SMasahiro Yamada if (ret) 1577fe8abf33SMasahiro Yamada goto assert_reset; 1578fe8abf33SMasahiro Yamada 1579dc1b5d9aSEnric Balletbo i Serra if (!dwc3_core_is_valid(dwc)) { 1580dc1b5d9aSEnric Balletbo i Serra dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 1581dc1b5d9aSEnric Balletbo i Serra ret = -ENODEV; 1582dc1b5d9aSEnric Balletbo i Serra goto disable_clks; 1583dc1b5d9aSEnric Balletbo i Serra } 1584dc1b5d9aSEnric Balletbo i Serra 15856c89cce0SHeikki Krogerus platform_set_drvdata(pdev, dwc); 15862917e718SHeikki Krogerus dwc3_cache_hwparams(dwc); 15876c89cce0SHeikki Krogerus 158872246da4SFelipe Balbi spin_lock_init(&dwc->lock); 1589f88359e1SYu Chen mutex_init(&dwc->mutex); 159072246da4SFelipe Balbi 1591fc8bb91bSFelipe Balbi pm_runtime_set_active(dev); 1592fc8bb91bSFelipe Balbi pm_runtime_use_autosuspend(dev); 1593fc8bb91bSFelipe Balbi pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY); 1594802ca850SChanho Park pm_runtime_enable(dev); 159532808237SRoger Quadros ret = pm_runtime_get_sync(dev); 159632808237SRoger Quadros if (ret < 0) 159732808237SRoger Quadros goto err1; 159832808237SRoger Quadros 1599802ca850SChanho Park pm_runtime_forbid(dev); 160072246da4SFelipe Balbi 16013921426bSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 16023921426bSFelipe Balbi if (ret) { 16033921426bSFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 16043921426bSFelipe Balbi ret = -ENOMEM; 160532808237SRoger Quadros goto err2; 16063921426bSFelipe Balbi } 16073921426bSFelipe Balbi 16089d6173e1SThinh Nguyen ret = dwc3_get_dr_mode(dwc); 16099d6173e1SThinh Nguyen if (ret) 16109d6173e1SThinh Nguyen goto err3; 161132a4a135SFelipe Balbi 1612c499ff71SFelipe Balbi ret = dwc3_alloc_scratch_buffers(dwc); 1613c499ff71SFelipe Balbi if (ret) 161432808237SRoger Quadros goto err3; 1615c499ff71SFelipe Balbi 161672246da4SFelipe Balbi ret = dwc3_core_init(dwc); 161772246da4SFelipe Balbi if (ret) { 16180c0a20f6SAndy Shevchenko dev_err_probe(dev, ret, "failed to initialize core\n"); 161932808237SRoger Quadros goto err4; 162072246da4SFelipe Balbi } 162172246da4SFelipe Balbi 16227ac51a12SJohn Youn dwc3_check_params(dwc); 16232c7f1bd9SJohn Youn 16245f94adfeSFelipe Balbi ret = dwc3_core_init_mode(dwc); 16255f94adfeSFelipe Balbi if (ret) 162632808237SRoger Quadros goto err5; 162772246da4SFelipe Balbi 16284e9f3118SDu, Changbin dwc3_debugfs_init(dwc); 1629fc8bb91bSFelipe Balbi pm_runtime_put(dev); 163072246da4SFelipe Balbi 163172246da4SFelipe Balbi return 0; 163272246da4SFelipe Balbi 163332808237SRoger Quadros err5: 1634f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 163503c1fd62SLi Jun 163603c1fd62SLi Jun usb_phy_shutdown(dwc->usb2_phy); 163703c1fd62SLi Jun usb_phy_shutdown(dwc->usb3_phy); 163803c1fd62SLi Jun phy_exit(dwc->usb2_generic_phy); 163903c1fd62SLi Jun phy_exit(dwc->usb3_generic_phy); 164003c1fd62SLi Jun 164103c1fd62SLi Jun usb_phy_set_suspend(dwc->usb2_phy, 1); 164203c1fd62SLi Jun usb_phy_set_suspend(dwc->usb3_phy, 1); 164303c1fd62SLi Jun phy_power_off(dwc->usb2_generic_phy); 164403c1fd62SLi Jun phy_power_off(dwc->usb3_generic_phy); 164503c1fd62SLi Jun 164608fd9a82SAndy Shevchenko dwc3_ulpi_exit(dwc); 1647f122d33eSFelipe Balbi 164832808237SRoger Quadros err4: 1649c499ff71SFelipe Balbi dwc3_free_scratch_buffers(dwc); 165072246da4SFelipe Balbi 165132808237SRoger Quadros err3: 16523921426bSFelipe Balbi dwc3_free_event_buffers(dwc); 16533921426bSFelipe Balbi 165432808237SRoger Quadros err2: 165532808237SRoger Quadros pm_runtime_allow(&pdev->dev); 165632808237SRoger Quadros 165732808237SRoger Quadros err1: 165832808237SRoger Quadros pm_runtime_put_sync(&pdev->dev); 165932808237SRoger Quadros pm_runtime_disable(&pdev->dev); 166032808237SRoger Quadros 1661dc1b5d9aSEnric Balletbo i Serra disable_clks: 1662240b65dcSAndrey Smirnov clk_bulk_disable_unprepare(dwc->num_clks, dwc->clks); 1663fe8abf33SMasahiro Yamada assert_reset: 1664fe8abf33SMasahiro Yamada reset_control_assert(dwc->reset); 1665fe8abf33SMasahiro Yamada 1666b0bf77cdSColin Ian King if (dwc->usb_psy) 16676f0764b5SRay Chi power_supply_put(dwc->usb_psy); 16686f0764b5SRay Chi 166972246da4SFelipe Balbi return ret; 167072246da4SFelipe Balbi } 167172246da4SFelipe Balbi 1672fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev) 167372246da4SFelipe Balbi { 167472246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 16753da1f6eeSFelipe Balbi 1676fc8bb91bSFelipe Balbi pm_runtime_get_sync(&pdev->dev); 167772246da4SFelipe Balbi 1678dc99f16fSFelipe Balbi dwc3_core_exit_mode(dwc); 16792a042767SPeter Chen dwc3_debugfs_exit(dwc); 16808ba007a9SKishon Vijay Abraham I 168172246da4SFelipe Balbi dwc3_core_exit(dwc); 168288bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 168372246da4SFelipe Balbi 1684fc8bb91bSFelipe Balbi pm_runtime_disable(&pdev->dev); 1685266d0493SLi Jun pm_runtime_put_noidle(&pdev->dev); 1686266d0493SLi Jun pm_runtime_set_suspended(&pdev->dev); 1687fc8bb91bSFelipe Balbi 1688c499ff71SFelipe Balbi dwc3_free_event_buffers(dwc); 1689c499ff71SFelipe Balbi dwc3_free_scratch_buffers(dwc); 1690c499ff71SFelipe Balbi 1691b0bf77cdSColin Ian King if (dwc->usb_psy) 16926f0764b5SRay Chi power_supply_put(dwc->usb_psy); 16936f0764b5SRay Chi 169472246da4SFelipe Balbi return 0; 169572246da4SFelipe Balbi } 169672246da4SFelipe Balbi 1697568262bfSSandeep Maheswaram static void dwc3_shutdown(struct platform_device *pdev) 1698568262bfSSandeep Maheswaram { 1699568262bfSSandeep Maheswaram dwc3_remove(pdev); 1700568262bfSSandeep Maheswaram } 1701568262bfSSandeep Maheswaram 1702fc8bb91bSFelipe Balbi #ifdef CONFIG_PM 1703fe8abf33SMasahiro Yamada static int dwc3_core_init_for_resume(struct dwc3 *dwc) 1704fe8abf33SMasahiro Yamada { 1705fe8abf33SMasahiro Yamada int ret; 1706fe8abf33SMasahiro Yamada 1707fe8abf33SMasahiro Yamada ret = reset_control_deassert(dwc->reset); 1708fe8abf33SMasahiro Yamada if (ret) 1709fe8abf33SMasahiro Yamada return ret; 1710fe8abf33SMasahiro Yamada 1711240b65dcSAndrey Smirnov ret = clk_bulk_prepare_enable(dwc->num_clks, dwc->clks); 1712fe8abf33SMasahiro Yamada if (ret) 1713fe8abf33SMasahiro Yamada goto assert_reset; 1714fe8abf33SMasahiro Yamada 1715fe8abf33SMasahiro Yamada ret = dwc3_core_init(dwc); 1716fe8abf33SMasahiro Yamada if (ret) 1717fe8abf33SMasahiro Yamada goto disable_clks; 1718fe8abf33SMasahiro Yamada 1719fe8abf33SMasahiro Yamada return 0; 1720fe8abf33SMasahiro Yamada 1721fe8abf33SMasahiro Yamada disable_clks: 1722240b65dcSAndrey Smirnov clk_bulk_disable_unprepare(dwc->num_clks, dwc->clks); 1723fe8abf33SMasahiro Yamada assert_reset: 1724fe8abf33SMasahiro Yamada reset_control_assert(dwc->reset); 1725fe8abf33SMasahiro Yamada 1726fe8abf33SMasahiro Yamada return ret; 1727fe8abf33SMasahiro Yamada } 1728fe8abf33SMasahiro Yamada 1729c4a5153eSManu Gautam static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) 17307415f17cSFelipe Balbi { 1731fc8bb91bSFelipe Balbi unsigned long flags; 1732bcb12877SManu Gautam u32 reg; 17337415f17cSFelipe Balbi 1734689bf72cSManu Gautam switch (dwc->current_dr_role) { 1735689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_DEVICE: 17360227cc84SLi Jun if (pm_runtime_suspended(dwc->dev)) 17370227cc84SLi Jun break; 1738fc8bb91bSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 17397415f17cSFelipe Balbi dwc3_gadget_suspend(dwc); 1740fc8bb91bSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 174141a91c60SMarek Szyprowski synchronize_irq(dwc->irq_gadget); 1742689bf72cSManu Gautam dwc3_core_exit(dwc); 174351f5d49aSFelipe Balbi break; 1744689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_HOST: 1745bcb12877SManu Gautam if (!PMSG_IS_AUTO(msg)) { 1746c4a5153eSManu Gautam dwc3_core_exit(dwc); 1747c4a5153eSManu Gautam break; 1748bcb12877SManu Gautam } 1749bcb12877SManu Gautam 1750bcb12877SManu Gautam /* Let controller to suspend HSPHY before PHY driver suspends */ 1751bcb12877SManu Gautam if (dwc->dis_u2_susphy_quirk || 1752bcb12877SManu Gautam dwc->dis_enblslpm_quirk) { 1753bcb12877SManu Gautam reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 1754bcb12877SManu Gautam reg |= DWC3_GUSB2PHYCFG_ENBLSLPM | 1755bcb12877SManu Gautam DWC3_GUSB2PHYCFG_SUSPHY; 1756bcb12877SManu Gautam dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 1757bcb12877SManu Gautam 1758bcb12877SManu Gautam /* Give some time for USB2 PHY to suspend */ 1759bcb12877SManu Gautam usleep_range(5000, 6000); 1760bcb12877SManu Gautam } 1761bcb12877SManu Gautam 1762bcb12877SManu Gautam phy_pm_runtime_put_sync(dwc->usb2_generic_phy); 1763bcb12877SManu Gautam phy_pm_runtime_put_sync(dwc->usb3_generic_phy); 1764bcb12877SManu Gautam break; 1765f09cc79bSRoger Quadros case DWC3_GCTL_PRTCAP_OTG: 1766f09cc79bSRoger Quadros /* do nothing during runtime_suspend */ 1767f09cc79bSRoger Quadros if (PMSG_IS_AUTO(msg)) 1768f09cc79bSRoger Quadros break; 1769f09cc79bSRoger Quadros 1770f09cc79bSRoger Quadros if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) { 1771f09cc79bSRoger Quadros spin_lock_irqsave(&dwc->lock, flags); 1772f09cc79bSRoger Quadros dwc3_gadget_suspend(dwc); 1773f09cc79bSRoger Quadros spin_unlock_irqrestore(&dwc->lock, flags); 177441a91c60SMarek Szyprowski synchronize_irq(dwc->irq_gadget); 1775f09cc79bSRoger Quadros } 1776f09cc79bSRoger Quadros 1777f09cc79bSRoger Quadros dwc3_otg_exit(dwc); 1778f09cc79bSRoger Quadros dwc3_core_exit(dwc); 1779f09cc79bSRoger Quadros break; 17807415f17cSFelipe Balbi default: 178151f5d49aSFelipe Balbi /* do nothing */ 17827415f17cSFelipe Balbi break; 17837415f17cSFelipe Balbi } 17847415f17cSFelipe Balbi 1785fc8bb91bSFelipe Balbi return 0; 1786fc8bb91bSFelipe Balbi } 1787fc8bb91bSFelipe Balbi 1788c4a5153eSManu Gautam static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) 1789fc8bb91bSFelipe Balbi { 1790fc8bb91bSFelipe Balbi unsigned long flags; 1791fc8bb91bSFelipe Balbi int ret; 1792bcb12877SManu Gautam u32 reg; 1793fc8bb91bSFelipe Balbi 1794689bf72cSManu Gautam switch (dwc->current_dr_role) { 1795689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_DEVICE: 1796fe8abf33SMasahiro Yamada ret = dwc3_core_init_for_resume(dwc); 1797fc8bb91bSFelipe Balbi if (ret) 1798fc8bb91bSFelipe Balbi return ret; 1799fc8bb91bSFelipe Balbi 18007d11c3acSRoger Quadros dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); 1801fc8bb91bSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 1802fc8bb91bSFelipe Balbi dwc3_gadget_resume(dwc); 1803fc8bb91bSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 1804689bf72cSManu Gautam break; 1805689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_HOST: 1806c4a5153eSManu Gautam if (!PMSG_IS_AUTO(msg)) { 1807fe8abf33SMasahiro Yamada ret = dwc3_core_init_for_resume(dwc); 1808c4a5153eSManu Gautam if (ret) 1809c4a5153eSManu Gautam return ret; 18107d11c3acSRoger Quadros dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); 1811bcb12877SManu Gautam break; 1812c4a5153eSManu Gautam } 1813bcb12877SManu Gautam /* Restore GUSB2PHYCFG bits that were modified in suspend */ 1814bcb12877SManu Gautam reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 1815bcb12877SManu Gautam if (dwc->dis_u2_susphy_quirk) 1816bcb12877SManu Gautam reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 1817bcb12877SManu Gautam 1818bcb12877SManu Gautam if (dwc->dis_enblslpm_quirk) 1819bcb12877SManu Gautam reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; 1820bcb12877SManu Gautam 1821bcb12877SManu Gautam dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 1822bcb12877SManu Gautam 1823bcb12877SManu Gautam phy_pm_runtime_get_sync(dwc->usb2_generic_phy); 1824bcb12877SManu Gautam phy_pm_runtime_get_sync(dwc->usb3_generic_phy); 1825c4a5153eSManu Gautam break; 1826f09cc79bSRoger Quadros case DWC3_GCTL_PRTCAP_OTG: 1827f09cc79bSRoger Quadros /* nothing to do on runtime_resume */ 1828f09cc79bSRoger Quadros if (PMSG_IS_AUTO(msg)) 1829f09cc79bSRoger Quadros break; 1830f09cc79bSRoger Quadros 18310e5a3c82SGary Bisson ret = dwc3_core_init_for_resume(dwc); 1832f09cc79bSRoger Quadros if (ret) 1833f09cc79bSRoger Quadros return ret; 1834f09cc79bSRoger Quadros 1835f09cc79bSRoger Quadros dwc3_set_prtcap(dwc, dwc->current_dr_role); 1836f09cc79bSRoger Quadros 1837f09cc79bSRoger Quadros dwc3_otg_init(dwc); 1838f09cc79bSRoger Quadros if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST) { 1839f09cc79bSRoger Quadros dwc3_otg_host_init(dwc); 1840f09cc79bSRoger Quadros } else if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) { 1841f09cc79bSRoger Quadros spin_lock_irqsave(&dwc->lock, flags); 1842f09cc79bSRoger Quadros dwc3_gadget_resume(dwc); 1843f09cc79bSRoger Quadros spin_unlock_irqrestore(&dwc->lock, flags); 1844f09cc79bSRoger Quadros } 1845f09cc79bSRoger Quadros 1846f09cc79bSRoger Quadros break; 1847fc8bb91bSFelipe Balbi default: 1848fc8bb91bSFelipe Balbi /* do nothing */ 1849fc8bb91bSFelipe Balbi break; 1850fc8bb91bSFelipe Balbi } 1851fc8bb91bSFelipe Balbi 1852fc8bb91bSFelipe Balbi return 0; 1853fc8bb91bSFelipe Balbi } 1854fc8bb91bSFelipe Balbi 1855fc8bb91bSFelipe Balbi static int dwc3_runtime_checks(struct dwc3 *dwc) 1856fc8bb91bSFelipe Balbi { 1857689bf72cSManu Gautam switch (dwc->current_dr_role) { 1858c4a5153eSManu Gautam case DWC3_GCTL_PRTCAP_DEVICE: 1859fc8bb91bSFelipe Balbi if (dwc->connected) 1860fc8bb91bSFelipe Balbi return -EBUSY; 1861fc8bb91bSFelipe Balbi break; 1862c4a5153eSManu Gautam case DWC3_GCTL_PRTCAP_HOST: 1863fc8bb91bSFelipe Balbi default: 1864fc8bb91bSFelipe Balbi /* do nothing */ 1865fc8bb91bSFelipe Balbi break; 1866fc8bb91bSFelipe Balbi } 1867fc8bb91bSFelipe Balbi 1868fc8bb91bSFelipe Balbi return 0; 1869fc8bb91bSFelipe Balbi } 1870fc8bb91bSFelipe Balbi 1871fc8bb91bSFelipe Balbi static int dwc3_runtime_suspend(struct device *dev) 1872fc8bb91bSFelipe Balbi { 1873fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1874fc8bb91bSFelipe Balbi int ret; 1875fc8bb91bSFelipe Balbi 1876fc8bb91bSFelipe Balbi if (dwc3_runtime_checks(dwc)) 1877fc8bb91bSFelipe Balbi return -EBUSY; 1878fc8bb91bSFelipe Balbi 1879c4a5153eSManu Gautam ret = dwc3_suspend_common(dwc, PMSG_AUTO_SUSPEND); 1880fc8bb91bSFelipe Balbi if (ret) 1881fc8bb91bSFelipe Balbi return ret; 1882fc8bb91bSFelipe Balbi 1883fc8bb91bSFelipe Balbi device_init_wakeup(dev, true); 1884fc8bb91bSFelipe Balbi 1885fc8bb91bSFelipe Balbi return 0; 1886fc8bb91bSFelipe Balbi } 1887fc8bb91bSFelipe Balbi 1888fc8bb91bSFelipe Balbi static int dwc3_runtime_resume(struct device *dev) 1889fc8bb91bSFelipe Balbi { 1890fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1891fc8bb91bSFelipe Balbi int ret; 1892fc8bb91bSFelipe Balbi 1893fc8bb91bSFelipe Balbi device_init_wakeup(dev, false); 1894fc8bb91bSFelipe Balbi 1895c4a5153eSManu Gautam ret = dwc3_resume_common(dwc, PMSG_AUTO_RESUME); 1896fc8bb91bSFelipe Balbi if (ret) 1897fc8bb91bSFelipe Balbi return ret; 1898fc8bb91bSFelipe Balbi 1899689bf72cSManu Gautam switch (dwc->current_dr_role) { 1900689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_DEVICE: 1901fc8bb91bSFelipe Balbi dwc3_gadget_process_pending_events(dwc); 1902fc8bb91bSFelipe Balbi break; 1903689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_HOST: 1904fc8bb91bSFelipe Balbi default: 1905fc8bb91bSFelipe Balbi /* do nothing */ 1906fc8bb91bSFelipe Balbi break; 1907fc8bb91bSFelipe Balbi } 1908fc8bb91bSFelipe Balbi 1909fc8bb91bSFelipe Balbi pm_runtime_mark_last_busy(dev); 1910fc8bb91bSFelipe Balbi 1911fc8bb91bSFelipe Balbi return 0; 1912fc8bb91bSFelipe Balbi } 1913fc8bb91bSFelipe Balbi 1914fc8bb91bSFelipe Balbi static int dwc3_runtime_idle(struct device *dev) 1915fc8bb91bSFelipe Balbi { 1916fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1917fc8bb91bSFelipe Balbi 1918689bf72cSManu Gautam switch (dwc->current_dr_role) { 1919689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_DEVICE: 1920fc8bb91bSFelipe Balbi if (dwc3_runtime_checks(dwc)) 1921fc8bb91bSFelipe Balbi return -EBUSY; 1922fc8bb91bSFelipe Balbi break; 1923689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_HOST: 1924fc8bb91bSFelipe Balbi default: 1925fc8bb91bSFelipe Balbi /* do nothing */ 1926fc8bb91bSFelipe Balbi break; 1927fc8bb91bSFelipe Balbi } 1928fc8bb91bSFelipe Balbi 1929fc8bb91bSFelipe Balbi pm_runtime_mark_last_busy(dev); 1930fc8bb91bSFelipe Balbi pm_runtime_autosuspend(dev); 1931fc8bb91bSFelipe Balbi 1932fc8bb91bSFelipe Balbi return 0; 1933fc8bb91bSFelipe Balbi } 1934fc8bb91bSFelipe Balbi #endif /* CONFIG_PM */ 1935fc8bb91bSFelipe Balbi 1936fc8bb91bSFelipe Balbi #ifdef CONFIG_PM_SLEEP 1937fc8bb91bSFelipe Balbi static int dwc3_suspend(struct device *dev) 1938fc8bb91bSFelipe Balbi { 1939fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1940fc8bb91bSFelipe Balbi int ret; 1941fc8bb91bSFelipe Balbi 1942c4a5153eSManu Gautam ret = dwc3_suspend_common(dwc, PMSG_SUSPEND); 1943fc8bb91bSFelipe Balbi if (ret) 1944fc8bb91bSFelipe Balbi return ret; 1945fc8bb91bSFelipe Balbi 19466344475fSSekhar Nori pinctrl_pm_select_sleep_state(dev); 19476344475fSSekhar Nori 19487415f17cSFelipe Balbi return 0; 19497415f17cSFelipe Balbi } 19507415f17cSFelipe Balbi 19517415f17cSFelipe Balbi static int dwc3_resume(struct device *dev) 19527415f17cSFelipe Balbi { 19537415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 195457303488SKishon Vijay Abraham I int ret; 19557415f17cSFelipe Balbi 19566344475fSSekhar Nori pinctrl_pm_select_default_state(dev); 19576344475fSSekhar Nori 1958c4a5153eSManu Gautam ret = dwc3_resume_common(dwc, PMSG_RESUME); 195951f5d49aSFelipe Balbi if (ret) 19605c4ad318SFelipe Balbi return ret; 19615c4ad318SFelipe Balbi 19627415f17cSFelipe Balbi pm_runtime_disable(dev); 19637415f17cSFelipe Balbi pm_runtime_set_active(dev); 19647415f17cSFelipe Balbi pm_runtime_enable(dev); 19657415f17cSFelipe Balbi 19667415f17cSFelipe Balbi return 0; 19677415f17cSFelipe Balbi } 1968f580170fSYu Chen 1969f580170fSYu Chen static void dwc3_complete(struct device *dev) 1970f580170fSYu Chen { 1971f580170fSYu Chen struct dwc3 *dwc = dev_get_drvdata(dev); 1972f580170fSYu Chen u32 reg; 1973f580170fSYu Chen 1974f580170fSYu Chen if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST && 1975f580170fSYu Chen dwc->dis_split_quirk) { 1976f580170fSYu Chen reg = dwc3_readl(dwc->regs, DWC3_GUCTL3); 1977f580170fSYu Chen reg |= DWC3_GUCTL3_SPLITDISABLE; 1978f580170fSYu Chen dwc3_writel(dwc->regs, DWC3_GUCTL3, reg); 1979f580170fSYu Chen } 1980f580170fSYu Chen } 1981f580170fSYu Chen #else 1982f580170fSYu Chen #define dwc3_complete NULL 19837f370ed0SFelipe Balbi #endif /* CONFIG_PM_SLEEP */ 19847415f17cSFelipe Balbi 19857415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = { 19867415f17cSFelipe Balbi SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 1987f580170fSYu Chen .complete = dwc3_complete, 1988fc8bb91bSFelipe Balbi SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume, 1989fc8bb91bSFelipe Balbi dwc3_runtime_idle) 19907415f17cSFelipe Balbi }; 19917415f17cSFelipe Balbi 19925088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF 19935088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = { 19945088b6f5SKishon Vijay Abraham I { 199522a5aa17SFelipe Balbi .compatible = "snps,dwc3" 199622a5aa17SFelipe Balbi }, 199722a5aa17SFelipe Balbi { 19985088b6f5SKishon Vijay Abraham I .compatible = "synopsys,dwc3" 19995088b6f5SKishon Vijay Abraham I }, 20005088b6f5SKishon Vijay Abraham I { }, 20015088b6f5SKishon Vijay Abraham I }; 20025088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match); 20035088b6f5SKishon Vijay Abraham I #endif 20045088b6f5SKishon Vijay Abraham I 2005404905a6SHeikki Krogerus #ifdef CONFIG_ACPI 2006404905a6SHeikki Krogerus 2007404905a6SHeikki Krogerus #define ACPI_ID_INTEL_BSW "808622B7" 2008404905a6SHeikki Krogerus 2009404905a6SHeikki Krogerus static const struct acpi_device_id dwc3_acpi_match[] = { 2010404905a6SHeikki Krogerus { ACPI_ID_INTEL_BSW, 0 }, 2011404905a6SHeikki Krogerus { }, 2012404905a6SHeikki Krogerus }; 2013404905a6SHeikki Krogerus MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match); 2014404905a6SHeikki Krogerus #endif 2015404905a6SHeikki Krogerus 201672246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 201772246da4SFelipe Balbi .probe = dwc3_probe, 20187690417dSBill Pemberton .remove = dwc3_remove, 2019568262bfSSandeep Maheswaram .shutdown = dwc3_shutdown, 202072246da4SFelipe Balbi .driver = { 202172246da4SFelipe Balbi .name = "dwc3", 20225088b6f5SKishon Vijay Abraham I .of_match_table = of_match_ptr(of_dwc3_match), 2023404905a6SHeikki Krogerus .acpi_match_table = ACPI_PTR(dwc3_acpi_match), 20247f370ed0SFelipe Balbi .pm = &dwc3_dev_pm_ops, 202572246da4SFelipe Balbi }, 202672246da4SFelipe Balbi }; 202772246da4SFelipe Balbi 2028b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 2029b1116dccSTobias Klauser 20307ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 203172246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 20325945f789SFelipe Balbi MODULE_LICENSE("GPL v2"); 203372246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 2034