15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 272246da4SFelipe Balbi /** 372246da4SFelipe Balbi * core.c - DesignWare USB3 DRD Controller Core file 472246da4SFelipe Balbi * 572246da4SFelipe Balbi * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://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 11fa0ea13eSFelipe Balbi #include <linux/version.h> 12a72e658bSFelipe Balbi #include <linux/module.h> 1372246da4SFelipe Balbi #include <linux/kernel.h> 1472246da4SFelipe Balbi #include <linux/slab.h> 1572246da4SFelipe Balbi #include <linux/spinlock.h> 1672246da4SFelipe Balbi #include <linux/platform_device.h> 1772246da4SFelipe Balbi #include <linux/pm_runtime.h> 1872246da4SFelipe Balbi #include <linux/interrupt.h> 1972246da4SFelipe Balbi #include <linux/ioport.h> 2072246da4SFelipe Balbi #include <linux/io.h> 2172246da4SFelipe Balbi #include <linux/list.h> 2272246da4SFelipe Balbi #include <linux/delay.h> 2372246da4SFelipe Balbi #include <linux/dma-mapping.h> 24457e84b6SFelipe Balbi #include <linux/of.h> 25404905a6SHeikki Krogerus #include <linux/acpi.h> 266344475fSSekhar Nori #include <linux/pinctrl/consumer.h> 2772246da4SFelipe Balbi 2872246da4SFelipe Balbi #include <linux/usb/ch9.h> 2972246da4SFelipe Balbi #include <linux/usb/gadget.h> 30f7e846f0SFelipe Balbi #include <linux/usb/of.h> 31a45c82b8SRuchika Kharwar #include <linux/usb/otg.h> 3272246da4SFelipe Balbi 3372246da4SFelipe Balbi #include "core.h" 3472246da4SFelipe Balbi #include "gadget.h" 3572246da4SFelipe Balbi #include "io.h" 3672246da4SFelipe Balbi 3772246da4SFelipe Balbi #include "debug.h" 3872246da4SFelipe Balbi 39fc8bb91bSFelipe Balbi #define DWC3_DEFAULT_AUTOSUSPEND_DELAY 5000 /* ms */ 408300dd23SFelipe Balbi 419d6173e1SThinh Nguyen /** 429d6173e1SThinh Nguyen * dwc3_get_dr_mode - Validates and sets dr_mode 439d6173e1SThinh Nguyen * @dwc: pointer to our context structure 449d6173e1SThinh Nguyen */ 459d6173e1SThinh Nguyen static int dwc3_get_dr_mode(struct dwc3 *dwc) 469d6173e1SThinh Nguyen { 479d6173e1SThinh Nguyen enum usb_dr_mode mode; 489d6173e1SThinh Nguyen struct device *dev = dwc->dev; 499d6173e1SThinh Nguyen unsigned int hw_mode; 509d6173e1SThinh Nguyen 519d6173e1SThinh Nguyen if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) 529d6173e1SThinh Nguyen dwc->dr_mode = USB_DR_MODE_OTG; 539d6173e1SThinh Nguyen 549d6173e1SThinh Nguyen mode = dwc->dr_mode; 559d6173e1SThinh Nguyen hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0); 569d6173e1SThinh Nguyen 579d6173e1SThinh Nguyen switch (hw_mode) { 589d6173e1SThinh Nguyen case DWC3_GHWPARAMS0_MODE_GADGET: 599d6173e1SThinh Nguyen if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) { 609d6173e1SThinh Nguyen dev_err(dev, 619d6173e1SThinh Nguyen "Controller does not support host mode.\n"); 629d6173e1SThinh Nguyen return -EINVAL; 639d6173e1SThinh Nguyen } 649d6173e1SThinh Nguyen mode = USB_DR_MODE_PERIPHERAL; 659d6173e1SThinh Nguyen break; 669d6173e1SThinh Nguyen case DWC3_GHWPARAMS0_MODE_HOST: 679d6173e1SThinh Nguyen if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) { 689d6173e1SThinh Nguyen dev_err(dev, 699d6173e1SThinh Nguyen "Controller does not support device mode.\n"); 709d6173e1SThinh Nguyen return -EINVAL; 719d6173e1SThinh Nguyen } 729d6173e1SThinh Nguyen mode = USB_DR_MODE_HOST; 739d6173e1SThinh Nguyen break; 749d6173e1SThinh Nguyen default: 759d6173e1SThinh Nguyen if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) 769d6173e1SThinh Nguyen mode = USB_DR_MODE_HOST; 779d6173e1SThinh Nguyen else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) 789d6173e1SThinh Nguyen mode = USB_DR_MODE_PERIPHERAL; 799d6173e1SThinh Nguyen } 809d6173e1SThinh Nguyen 819d6173e1SThinh Nguyen if (mode != dwc->dr_mode) { 829d6173e1SThinh Nguyen dev_warn(dev, 839d6173e1SThinh Nguyen "Configuration mismatch. dr_mode forced to %s\n", 849d6173e1SThinh Nguyen mode == USB_DR_MODE_HOST ? "host" : "gadget"); 859d6173e1SThinh Nguyen 869d6173e1SThinh Nguyen dwc->dr_mode = mode; 879d6173e1SThinh Nguyen } 889d6173e1SThinh Nguyen 899d6173e1SThinh Nguyen return 0; 909d6173e1SThinh Nguyen } 919d6173e1SThinh Nguyen 9241ce1456SRoger Quadros static void dwc3_event_buffers_cleanup(struct dwc3 *dwc); 9341ce1456SRoger Quadros static int dwc3_event_buffers_setup(struct dwc3 *dwc); 9441ce1456SRoger Quadros 9541ce1456SRoger Quadros static void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode) 963140e8cbSSebastian Andrzej Siewior { 973140e8cbSSebastian Andrzej Siewior u32 reg; 983140e8cbSSebastian Andrzej Siewior 993140e8cbSSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 1003140e8cbSSebastian Andrzej Siewior reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); 1013140e8cbSSebastian Andrzej Siewior reg |= DWC3_GCTL_PRTCAPDIR(mode); 1023140e8cbSSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 10341ce1456SRoger Quadros } 1046b3261a2SRoger Quadros 10541ce1456SRoger Quadros static void __dwc3_set_mode(struct work_struct *work) 10641ce1456SRoger Quadros { 10741ce1456SRoger Quadros struct dwc3 *dwc = work_to_dwc(work); 10841ce1456SRoger Quadros unsigned long flags; 10941ce1456SRoger Quadros int ret; 11041ce1456SRoger Quadros 11141ce1456SRoger Quadros if (!dwc->desired_dr_role) 11241ce1456SRoger Quadros return; 11341ce1456SRoger Quadros 11441ce1456SRoger Quadros if (dwc->desired_dr_role == dwc->current_dr_role) 11541ce1456SRoger Quadros return; 11641ce1456SRoger Quadros 11741ce1456SRoger Quadros if (dwc->dr_mode != USB_DR_MODE_OTG) 11841ce1456SRoger Quadros return; 11941ce1456SRoger Quadros 12041ce1456SRoger Quadros switch (dwc->current_dr_role) { 12141ce1456SRoger Quadros case DWC3_GCTL_PRTCAP_HOST: 12241ce1456SRoger Quadros dwc3_host_exit(dwc); 12341ce1456SRoger Quadros break; 12441ce1456SRoger Quadros case DWC3_GCTL_PRTCAP_DEVICE: 12541ce1456SRoger Quadros dwc3_gadget_exit(dwc); 12641ce1456SRoger Quadros dwc3_event_buffers_cleanup(dwc); 12741ce1456SRoger Quadros break; 12841ce1456SRoger Quadros default: 12941ce1456SRoger Quadros break; 13041ce1456SRoger Quadros } 13141ce1456SRoger Quadros 13241ce1456SRoger Quadros spin_lock_irqsave(&dwc->lock, flags); 13341ce1456SRoger Quadros 13441ce1456SRoger Quadros dwc3_set_prtcap(dwc, dwc->desired_dr_role); 13541ce1456SRoger Quadros 13641ce1456SRoger Quadros dwc->current_dr_role = dwc->desired_dr_role; 13741ce1456SRoger Quadros 13841ce1456SRoger Quadros spin_unlock_irqrestore(&dwc->lock, flags); 13941ce1456SRoger Quadros 14041ce1456SRoger Quadros switch (dwc->desired_dr_role) { 14141ce1456SRoger Quadros case DWC3_GCTL_PRTCAP_HOST: 14241ce1456SRoger Quadros ret = dwc3_host_init(dwc); 143958d1a4cSFelipe Balbi if (ret) { 14441ce1456SRoger Quadros dev_err(dwc->dev, "failed to initialize host\n"); 145958d1a4cSFelipe Balbi } else { 146958d1a4cSFelipe Balbi if (dwc->usb2_phy) 147958d1a4cSFelipe Balbi otg_set_vbus(dwc->usb2_phy->otg, true); 148958d1a4cSFelipe Balbi phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); 149644cbbc3SManu Gautam phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST); 150d8c80bb3SVivek Gautam phy_calibrate(dwc->usb2_generic_phy); 151958d1a4cSFelipe Balbi } 15241ce1456SRoger Quadros break; 15341ce1456SRoger Quadros case DWC3_GCTL_PRTCAP_DEVICE: 15441ce1456SRoger Quadros dwc3_event_buffers_setup(dwc); 155958d1a4cSFelipe Balbi 156958d1a4cSFelipe Balbi if (dwc->usb2_phy) 157958d1a4cSFelipe Balbi otg_set_vbus(dwc->usb2_phy->otg, false); 158958d1a4cSFelipe Balbi phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE); 159644cbbc3SManu Gautam phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE); 160958d1a4cSFelipe Balbi 16141ce1456SRoger Quadros ret = dwc3_gadget_init(dwc); 16241ce1456SRoger Quadros if (ret) 16341ce1456SRoger Quadros dev_err(dwc->dev, "failed to initialize peripheral\n"); 16441ce1456SRoger Quadros break; 16541ce1456SRoger Quadros default: 16641ce1456SRoger Quadros break; 16741ce1456SRoger Quadros } 16841ce1456SRoger Quadros } 16941ce1456SRoger Quadros 17041ce1456SRoger Quadros void dwc3_set_mode(struct dwc3 *dwc, u32 mode) 17141ce1456SRoger Quadros { 17241ce1456SRoger Quadros unsigned long flags; 17341ce1456SRoger Quadros 17441ce1456SRoger Quadros spin_lock_irqsave(&dwc->lock, flags); 17541ce1456SRoger Quadros dwc->desired_dr_role = mode; 17641ce1456SRoger Quadros spin_unlock_irqrestore(&dwc->lock, flags); 17741ce1456SRoger Quadros 17841ce1456SRoger Quadros queue_work(system_power_efficient_wq, &dwc->drd_work); 1793140e8cbSSebastian Andrzej Siewior } 1808300dd23SFelipe Balbi 181cf6d867dSFelipe Balbi u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type) 182cf6d867dSFelipe Balbi { 183cf6d867dSFelipe Balbi struct dwc3 *dwc = dep->dwc; 184cf6d867dSFelipe Balbi u32 reg; 185cf6d867dSFelipe Balbi 186cf6d867dSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GDBGFIFOSPACE, 187cf6d867dSFelipe Balbi DWC3_GDBGFIFOSPACE_NUM(dep->number) | 188cf6d867dSFelipe Balbi DWC3_GDBGFIFOSPACE_TYPE(type)); 189cf6d867dSFelipe Balbi 190cf6d867dSFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GDBGFIFOSPACE); 191cf6d867dSFelipe Balbi 192cf6d867dSFelipe Balbi return DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(reg); 193cf6d867dSFelipe Balbi } 194cf6d867dSFelipe Balbi 19572246da4SFelipe Balbi /** 19672246da4SFelipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 19772246da4SFelipe Balbi * @dwc: pointer to our context structure 19872246da4SFelipe Balbi */ 19957303488SKishon Vijay Abraham I static int dwc3_core_soft_reset(struct dwc3 *dwc) 20072246da4SFelipe Balbi { 20172246da4SFelipe Balbi u32 reg; 202f59dcab1SFelipe Balbi int retries = 1000; 20357303488SKishon Vijay Abraham I int ret; 20472246da4SFelipe Balbi 20551e1e7bcSFelipe Balbi usb_phy_init(dwc->usb2_phy); 20651e1e7bcSFelipe Balbi usb_phy_init(dwc->usb3_phy); 20757303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 20857303488SKishon Vijay Abraham I if (ret < 0) 20957303488SKishon Vijay Abraham I return ret; 21057303488SKishon Vijay Abraham I 21157303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 21257303488SKishon Vijay Abraham I if (ret < 0) { 21357303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 21457303488SKishon Vijay Abraham I return ret; 21557303488SKishon Vijay Abraham I } 21672246da4SFelipe Balbi 217f59dcab1SFelipe Balbi /* 218f59dcab1SFelipe Balbi * We're resetting only the device side because, if we're in host mode, 219f59dcab1SFelipe Balbi * XHCI driver will reset the host block. If dwc3 was configured for 220f59dcab1SFelipe Balbi * host-only mode, then we can return early. 221f59dcab1SFelipe Balbi */ 222f59dcab1SFelipe Balbi if (dwc->dr_mode == USB_DR_MODE_HOST) 22357303488SKishon Vijay Abraham I return 0; 224f59dcab1SFelipe Balbi 225f59dcab1SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 226f59dcab1SFelipe Balbi reg |= DWC3_DCTL_CSFTRST; 227f59dcab1SFelipe Balbi dwc3_writel(dwc->regs, DWC3_DCTL, reg); 228f59dcab1SFelipe Balbi 229f59dcab1SFelipe Balbi do { 230f59dcab1SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 231f59dcab1SFelipe Balbi if (!(reg & DWC3_DCTL_CSFTRST)) 232f59dcab1SFelipe Balbi return 0; 233f59dcab1SFelipe Balbi 234f59dcab1SFelipe Balbi udelay(1); 235f59dcab1SFelipe Balbi } while (--retries); 236f59dcab1SFelipe Balbi 237f59dcab1SFelipe Balbi return -ETIMEDOUT; 23872246da4SFelipe Balbi } 23972246da4SFelipe Balbi 240db2be4e9SNikhil Badola /* 241db2be4e9SNikhil Badola * dwc3_frame_length_adjustment - Adjusts frame length if required 242db2be4e9SNikhil Badola * @dwc3: Pointer to our controller context structure 243db2be4e9SNikhil Badola */ 244bcdb3272SFelipe Balbi static void dwc3_frame_length_adjustment(struct dwc3 *dwc) 245db2be4e9SNikhil Badola { 246db2be4e9SNikhil Badola u32 reg; 247db2be4e9SNikhil Badola u32 dft; 248db2be4e9SNikhil Badola 249db2be4e9SNikhil Badola if (dwc->revision < DWC3_REVISION_250A) 250db2be4e9SNikhil Badola return; 251db2be4e9SNikhil Badola 252bcdb3272SFelipe Balbi if (dwc->fladj == 0) 253db2be4e9SNikhil Badola return; 254db2be4e9SNikhil Badola 255db2be4e9SNikhil Badola reg = dwc3_readl(dwc->regs, DWC3_GFLADJ); 256db2be4e9SNikhil Badola dft = reg & DWC3_GFLADJ_30MHZ_MASK; 257bcdb3272SFelipe Balbi if (!dev_WARN_ONCE(dwc->dev, dft == dwc->fladj, 258db2be4e9SNikhil Badola "request value same as default, ignoring\n")) { 259db2be4e9SNikhil Badola reg &= ~DWC3_GFLADJ_30MHZ_MASK; 260bcdb3272SFelipe Balbi reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj; 261db2be4e9SNikhil Badola dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); 262db2be4e9SNikhil Badola } 263db2be4e9SNikhil Badola } 264db2be4e9SNikhil Badola 265c5cc74e8SHeikki Krogerus /** 26672246da4SFelipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 26772246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 26872246da4SFelipe Balbi * @evt: Pointer to event buffer to be freed 26972246da4SFelipe Balbi */ 27072246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc, 27172246da4SFelipe Balbi struct dwc3_event_buffer *evt) 27272246da4SFelipe Balbi { 273d64ff406SArnd Bergmann dma_free_coherent(dwc->sysdev, evt->length, evt->buf, evt->dma); 27472246da4SFelipe Balbi } 27572246da4SFelipe Balbi 27672246da4SFelipe Balbi /** 2771d046793SPaul Zimmerman * dwc3_alloc_one_event_buffer - Allocates one event buffer structure 27872246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 27972246da4SFelipe Balbi * @length: size of the event buffer 28072246da4SFelipe Balbi * 2811d046793SPaul Zimmerman * Returns a pointer to the allocated event buffer structure on success 28272246da4SFelipe Balbi * otherwise ERR_PTR(errno). 28372246da4SFelipe Balbi */ 28467d0b500SFelipe Balbi static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, 28567d0b500SFelipe Balbi unsigned length) 28672246da4SFelipe Balbi { 28772246da4SFelipe Balbi struct dwc3_event_buffer *evt; 28872246da4SFelipe Balbi 289380f0d28SFelipe Balbi evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL); 29072246da4SFelipe Balbi if (!evt) 29172246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 29272246da4SFelipe Balbi 29372246da4SFelipe Balbi evt->dwc = dwc; 29472246da4SFelipe Balbi evt->length = length; 295d9fa4c63SJohn Youn evt->cache = devm_kzalloc(dwc->dev, length, GFP_KERNEL); 296d9fa4c63SJohn Youn if (!evt->cache) 297d9fa4c63SJohn Youn return ERR_PTR(-ENOMEM); 298d9fa4c63SJohn Youn 299d64ff406SArnd Bergmann evt->buf = dma_alloc_coherent(dwc->sysdev, length, 30072246da4SFelipe Balbi &evt->dma, GFP_KERNEL); 301e32672f0SFelipe Balbi if (!evt->buf) 30272246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 30372246da4SFelipe Balbi 30472246da4SFelipe Balbi return evt; 30572246da4SFelipe Balbi } 30672246da4SFelipe Balbi 30772246da4SFelipe Balbi /** 30872246da4SFelipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 30972246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 31072246da4SFelipe Balbi */ 31172246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc) 31272246da4SFelipe Balbi { 31372246da4SFelipe Balbi struct dwc3_event_buffer *evt; 31472246da4SFelipe Balbi 315696c8b12SFelipe Balbi evt = dwc->ev_buf; 31664b6c8a7SAnton Tikhomirov if (evt) 31772246da4SFelipe Balbi dwc3_free_one_event_buffer(dwc, evt); 31872246da4SFelipe Balbi } 31972246da4SFelipe Balbi 32072246da4SFelipe Balbi /** 32172246da4SFelipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 3221d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 32372246da4SFelipe Balbi * @length: size of event buffer 32472246da4SFelipe Balbi * 3251d046793SPaul Zimmerman * Returns 0 on success otherwise negative errno. In the error case, dwc 32672246da4SFelipe Balbi * may contain some buffers allocated but not all which were requested. 32772246da4SFelipe Balbi */ 32841ac7b3aSBill Pemberton static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) 32972246da4SFelipe Balbi { 33072246da4SFelipe Balbi struct dwc3_event_buffer *evt; 33172246da4SFelipe Balbi 33272246da4SFelipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 33372246da4SFelipe Balbi if (IS_ERR(evt)) { 33472246da4SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 33572246da4SFelipe Balbi return PTR_ERR(evt); 33672246da4SFelipe Balbi } 337696c8b12SFelipe Balbi dwc->ev_buf = evt; 33872246da4SFelipe Balbi 33972246da4SFelipe Balbi return 0; 34072246da4SFelipe Balbi } 34172246da4SFelipe Balbi 34272246da4SFelipe Balbi /** 34372246da4SFelipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 3441d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 34572246da4SFelipe Balbi * 34672246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 34772246da4SFelipe Balbi */ 3487acd85e0SPaul Zimmerman static int dwc3_event_buffers_setup(struct dwc3 *dwc) 34972246da4SFelipe Balbi { 35072246da4SFelipe Balbi struct dwc3_event_buffer *evt; 35172246da4SFelipe Balbi 352696c8b12SFelipe Balbi evt = dwc->ev_buf; 3537acd85e0SPaul Zimmerman evt->lpos = 0; 354660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 35572246da4SFelipe Balbi lower_32_bits(evt->dma)); 356660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 35772246da4SFelipe Balbi upper_32_bits(evt->dma)); 358660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), 35968d6a01bSFelipe Balbi DWC3_GEVNTSIZ_SIZE(evt->length)); 360660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 36172246da4SFelipe Balbi 36272246da4SFelipe Balbi return 0; 36372246da4SFelipe Balbi } 36472246da4SFelipe Balbi 36572246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 36672246da4SFelipe Balbi { 36772246da4SFelipe Balbi struct dwc3_event_buffer *evt; 36872246da4SFelipe Balbi 369696c8b12SFelipe Balbi evt = dwc->ev_buf; 3707acd85e0SPaul Zimmerman 3717acd85e0SPaul Zimmerman evt->lpos = 0; 3727acd85e0SPaul Zimmerman 373660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 0); 374660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 0); 375660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK 37668d6a01bSFelipe Balbi | DWC3_GEVNTSIZ_SIZE(0)); 377660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 37872246da4SFelipe Balbi } 37972246da4SFelipe Balbi 3800ffcaf37SFelipe Balbi static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) 3810ffcaf37SFelipe Balbi { 3820ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3830ffcaf37SFelipe Balbi return 0; 3840ffcaf37SFelipe Balbi 3850ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3860ffcaf37SFelipe Balbi return 0; 3870ffcaf37SFelipe Balbi 3880ffcaf37SFelipe Balbi dwc->scratchbuf = kmalloc_array(dwc->nr_scratch, 3890ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, GFP_KERNEL); 3900ffcaf37SFelipe Balbi if (!dwc->scratchbuf) 3910ffcaf37SFelipe Balbi return -ENOMEM; 3920ffcaf37SFelipe Balbi 3930ffcaf37SFelipe Balbi return 0; 3940ffcaf37SFelipe Balbi } 3950ffcaf37SFelipe Balbi 3960ffcaf37SFelipe Balbi static int dwc3_setup_scratch_buffers(struct dwc3 *dwc) 3970ffcaf37SFelipe Balbi { 3980ffcaf37SFelipe Balbi dma_addr_t scratch_addr; 3990ffcaf37SFelipe Balbi u32 param; 4000ffcaf37SFelipe Balbi int ret; 4010ffcaf37SFelipe Balbi 4020ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 4030ffcaf37SFelipe Balbi return 0; 4040ffcaf37SFelipe Balbi 4050ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 4060ffcaf37SFelipe Balbi return 0; 4070ffcaf37SFelipe Balbi 4080ffcaf37SFelipe Balbi /* should never fall here */ 4090ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 4100ffcaf37SFelipe Balbi return 0; 4110ffcaf37SFelipe Balbi 412d64ff406SArnd Bergmann scratch_addr = dma_map_single(dwc->sysdev, dwc->scratchbuf, 4130ffcaf37SFelipe Balbi dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, 4140ffcaf37SFelipe Balbi DMA_BIDIRECTIONAL); 415d64ff406SArnd Bergmann if (dma_mapping_error(dwc->sysdev, scratch_addr)) { 416d64ff406SArnd Bergmann dev_err(dwc->sysdev, "failed to map scratch buffer\n"); 4170ffcaf37SFelipe Balbi ret = -EFAULT; 4180ffcaf37SFelipe Balbi goto err0; 4190ffcaf37SFelipe Balbi } 4200ffcaf37SFelipe Balbi 4210ffcaf37SFelipe Balbi dwc->scratch_addr = scratch_addr; 4220ffcaf37SFelipe Balbi 4230ffcaf37SFelipe Balbi param = lower_32_bits(scratch_addr); 4240ffcaf37SFelipe Balbi 4250ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 4260ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param); 4270ffcaf37SFelipe Balbi if (ret < 0) 4280ffcaf37SFelipe Balbi goto err1; 4290ffcaf37SFelipe Balbi 4300ffcaf37SFelipe Balbi param = upper_32_bits(scratch_addr); 4310ffcaf37SFelipe Balbi 4320ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 4330ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param); 4340ffcaf37SFelipe Balbi if (ret < 0) 4350ffcaf37SFelipe Balbi goto err1; 4360ffcaf37SFelipe Balbi 4370ffcaf37SFelipe Balbi return 0; 4380ffcaf37SFelipe Balbi 4390ffcaf37SFelipe Balbi err1: 440d64ff406SArnd Bergmann dma_unmap_single(dwc->sysdev, dwc->scratch_addr, dwc->nr_scratch * 4410ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 4420ffcaf37SFelipe Balbi 4430ffcaf37SFelipe Balbi err0: 4440ffcaf37SFelipe Balbi return ret; 4450ffcaf37SFelipe Balbi } 4460ffcaf37SFelipe Balbi 4470ffcaf37SFelipe Balbi static void dwc3_free_scratch_buffers(struct dwc3 *dwc) 4480ffcaf37SFelipe Balbi { 4490ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 4500ffcaf37SFelipe Balbi return; 4510ffcaf37SFelipe Balbi 4520ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 4530ffcaf37SFelipe Balbi return; 4540ffcaf37SFelipe Balbi 4550ffcaf37SFelipe Balbi /* should never fall here */ 4560ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 4570ffcaf37SFelipe Balbi return; 4580ffcaf37SFelipe Balbi 459d64ff406SArnd Bergmann dma_unmap_single(dwc->sysdev, dwc->scratch_addr, dwc->nr_scratch * 4600ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 4610ffcaf37SFelipe Balbi kfree(dwc->scratchbuf); 4620ffcaf37SFelipe Balbi } 4630ffcaf37SFelipe Balbi 464789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc) 465789451f6SFelipe Balbi { 466789451f6SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 467789451f6SFelipe Balbi 46847d3946eSBryan O'Donoghue dwc->num_eps = DWC3_NUM_EPS(parms); 469789451f6SFelipe Balbi } 470789451f6SFelipe Balbi 47141ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc) 47226ceca97SFelipe Balbi { 47326ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 47426ceca97SFelipe Balbi 47526ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 47626ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 47726ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 47826ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 47926ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 48026ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 48126ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 48226ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 48326ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 48426ceca97SFelipe Balbi } 48526ceca97SFelipe Balbi 48672246da4SFelipe Balbi /** 487b5a65c40SHuang Rui * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core 488b5a65c40SHuang Rui * @dwc: Pointer to our controller context structure 48988bc9d19SHeikki Krogerus * 49088bc9d19SHeikki Krogerus * Returns 0 on success. The USB PHY interfaces are configured but not 49188bc9d19SHeikki Krogerus * initialized. The PHY interfaces and the PHYs get initialized together with 49288bc9d19SHeikki Krogerus * the core in dwc3_core_init. 493b5a65c40SHuang Rui */ 49488bc9d19SHeikki Krogerus static int dwc3_phy_setup(struct dwc3 *dwc) 495b5a65c40SHuang Rui { 496b5a65c40SHuang Rui u32 reg; 49788bc9d19SHeikki Krogerus int ret; 498b5a65c40SHuang Rui 499b5a65c40SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 500b5a65c40SHuang Rui 5012164a476SHuang Rui /* 5021966b865SFelipe Balbi * Make sure UX_EXIT_PX is cleared as that causes issues with some 5031966b865SFelipe Balbi * PHYs. Also, this bit is not supposed to be used in normal operation. 5041966b865SFelipe Balbi */ 5051966b865SFelipe Balbi reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX; 5061966b865SFelipe Balbi 5071966b865SFelipe Balbi /* 5082164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY 5092164a476SHuang Rui * to '0' during coreConsultant configuration. So default value 5102164a476SHuang Rui * will be '0' when the core is reset. Application needs to set it 5112164a476SHuang Rui * to '1' after the core initialization is completed. 5122164a476SHuang Rui */ 5132164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 5142164a476SHuang Rui reg |= DWC3_GUSB3PIPECTL_SUSPHY; 5152164a476SHuang Rui 516b5a65c40SHuang Rui if (dwc->u2ss_inp3_quirk) 517b5a65c40SHuang Rui reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; 518b5a65c40SHuang Rui 519e58dd357SRajesh Bhagat if (dwc->dis_rxdet_inp3_quirk) 520e58dd357SRajesh Bhagat reg |= DWC3_GUSB3PIPECTL_DISRXDETINP3; 521e58dd357SRajesh Bhagat 522df31f5b3SHuang Rui if (dwc->req_p1p2p3_quirk) 523df31f5b3SHuang Rui reg |= DWC3_GUSB3PIPECTL_REQP1P2P3; 524df31f5b3SHuang Rui 525a2a1d0f5SHuang Rui if (dwc->del_p1p2p3_quirk) 526a2a1d0f5SHuang Rui reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN; 527a2a1d0f5SHuang Rui 52841c06ffdSHuang Rui if (dwc->del_phy_power_chg_quirk) 52941c06ffdSHuang Rui reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE; 53041c06ffdSHuang Rui 531fb67afcaSHuang Rui if (dwc->lfps_filter_quirk) 532fb67afcaSHuang Rui reg |= DWC3_GUSB3PIPECTL_LFPSFILT; 533fb67afcaSHuang Rui 53414f4ac53SHuang Rui if (dwc->rx_detect_poll_quirk) 53514f4ac53SHuang Rui reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL; 53614f4ac53SHuang Rui 5376b6a0c9aSHuang Rui if (dwc->tx_de_emphasis_quirk) 5386b6a0c9aSHuang Rui reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); 5396b6a0c9aSHuang Rui 540cd72f890SFelipe Balbi if (dwc->dis_u3_susphy_quirk) 54159acfa20SHuang Rui reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 54259acfa20SHuang Rui 54300fe081dSWilliam Wu if (dwc->dis_del_phy_power_chg_quirk) 54400fe081dSWilliam Wu reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE; 54500fe081dSWilliam Wu 546b5a65c40SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 547b5a65c40SHuang Rui 5482164a476SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 5492164a476SHuang Rui 5503e10a2ceSHeikki Krogerus /* Select the HS PHY interface */ 5513e10a2ceSHeikki Krogerus switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) { 5523e10a2ceSHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI: 55343cacb03SFelipe Balbi if (dwc->hsphy_interface && 55443cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "utmi", 4)) { 5553e10a2ceSHeikki Krogerus reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI; 55688bc9d19SHeikki Krogerus break; 55743cacb03SFelipe Balbi } else if (dwc->hsphy_interface && 55843cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "ulpi", 4)) { 5593e10a2ceSHeikki Krogerus reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI; 56088bc9d19SHeikki Krogerus dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 5613e10a2ceSHeikki Krogerus } else { 56288bc9d19SHeikki Krogerus /* Relying on default value. */ 56388bc9d19SHeikki Krogerus if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) 5643e10a2ceSHeikki Krogerus break; 5653e10a2ceSHeikki Krogerus } 5663e10a2ceSHeikki Krogerus /* FALLTHROUGH */ 56788bc9d19SHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: 56888bc9d19SHeikki Krogerus ret = dwc3_ulpi_init(dwc); 56988bc9d19SHeikki Krogerus if (ret) 57088bc9d19SHeikki Krogerus return ret; 57188bc9d19SHeikki Krogerus /* FALLTHROUGH */ 5723e10a2ceSHeikki Krogerus default: 5733e10a2ceSHeikki Krogerus break; 5743e10a2ceSHeikki Krogerus } 5753e10a2ceSHeikki Krogerus 57632f2ed86SWilliam Wu switch (dwc->hsphy_mode) { 57732f2ed86SWilliam Wu case USBPHY_INTERFACE_MODE_UTMI: 57832f2ed86SWilliam Wu reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | 57932f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); 58032f2ed86SWilliam Wu reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) | 58132f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT); 58232f2ed86SWilliam Wu break; 58332f2ed86SWilliam Wu case USBPHY_INTERFACE_MODE_UTMIW: 58432f2ed86SWilliam Wu reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | 58532f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); 58632f2ed86SWilliam Wu reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) | 58732f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT); 58832f2ed86SWilliam Wu break; 58932f2ed86SWilliam Wu default: 59032f2ed86SWilliam Wu break; 59132f2ed86SWilliam Wu } 59232f2ed86SWilliam Wu 5932164a476SHuang Rui /* 5942164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to 5952164a476SHuang Rui * '0' during coreConsultant configuration. So default value will 5962164a476SHuang Rui * be '0' when the core is reset. Application needs to set it to 5972164a476SHuang Rui * '1' after the core initialization is completed. 5982164a476SHuang Rui */ 5992164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 6002164a476SHuang Rui reg |= DWC3_GUSB2PHYCFG_SUSPHY; 6012164a476SHuang Rui 602cd72f890SFelipe Balbi if (dwc->dis_u2_susphy_quirk) 6030effe0a3SHuang Rui reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 6040effe0a3SHuang Rui 605ec791d14SJohn Youn if (dwc->dis_enblslpm_quirk) 606ec791d14SJohn Youn reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; 607ec791d14SJohn Youn 60816199f33SWilliam Wu if (dwc->dis_u2_freeclk_exists_quirk) 60916199f33SWilliam Wu reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS; 61016199f33SWilliam Wu 6112164a476SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 61288bc9d19SHeikki Krogerus 61388bc9d19SHeikki Krogerus return 0; 614b5a65c40SHuang Rui } 615b5a65c40SHuang Rui 616c499ff71SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 617c499ff71SFelipe Balbi { 618c499ff71SFelipe Balbi dwc3_event_buffers_cleanup(dwc); 619c499ff71SFelipe Balbi 620c499ff71SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 621c499ff71SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 622c499ff71SFelipe Balbi phy_exit(dwc->usb2_generic_phy); 623c499ff71SFelipe Balbi phy_exit(dwc->usb3_generic_phy); 624c499ff71SFelipe Balbi 625c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 1); 626c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 1); 627c499ff71SFelipe Balbi phy_power_off(dwc->usb2_generic_phy); 628c499ff71SFelipe Balbi phy_power_off(dwc->usb3_generic_phy); 629c499ff71SFelipe Balbi } 630c499ff71SFelipe Balbi 6310759956fSFelipe Balbi static bool dwc3_core_is_valid(struct dwc3 *dwc) 63272246da4SFelipe Balbi { 63372246da4SFelipe Balbi u32 reg; 63472246da4SFelipe Balbi 6357650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 6360759956fSFelipe Balbi 6377650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 638690fb371SJohn Youn if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) { 639690fb371SJohn Youn /* Detected DWC_usb3 IP */ 640690fb371SJohn Youn dwc->revision = reg; 641690fb371SJohn Youn } else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) { 642690fb371SJohn Youn /* Detected DWC_usb31 IP */ 643690fb371SJohn Youn dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); 644690fb371SJohn Youn dwc->revision |= DWC3_REVISION_IS_DWC31; 645690fb371SJohn Youn } else { 6460759956fSFelipe Balbi return false; 6477650bd74SSebastian Andrzej Siewior } 6487650bd74SSebastian Andrzej Siewior 6490759956fSFelipe Balbi return true; 6500e1e5c47SPaul Zimmerman } 6510e1e5c47SPaul Zimmerman 652941f918eSFelipe Balbi static void dwc3_core_setup_global_control(struct dwc3 *dwc) 65372246da4SFelipe Balbi { 65472246da4SFelipe Balbi u32 hwparams4 = dwc->hwparams.hwparams4; 65572246da4SFelipe Balbi u32 reg; 656c499ff71SFelipe Balbi 6574878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 6583e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 6594878a028SSebastian Andrzej Siewior 660164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 6614878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 66232a4a135SFelipe Balbi /** 66332a4a135SFelipe Balbi * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an 66432a4a135SFelipe Balbi * issue which would cause xHCI compliance tests to fail. 66532a4a135SFelipe Balbi * 66632a4a135SFelipe Balbi * Because of that we cannot enable clock gating on such 66732a4a135SFelipe Balbi * configurations. 66832a4a135SFelipe Balbi * 66932a4a135SFelipe Balbi * Refers to: 67032a4a135SFelipe Balbi * 67132a4a135SFelipe Balbi * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based 67232a4a135SFelipe Balbi * SOF/ITP Mode Used 67332a4a135SFelipe Balbi */ 67432a4a135SFelipe Balbi if ((dwc->dr_mode == USB_DR_MODE_HOST || 67532a4a135SFelipe Balbi dwc->dr_mode == USB_DR_MODE_OTG) && 67632a4a135SFelipe Balbi (dwc->revision >= DWC3_REVISION_210A && 67732a4a135SFelipe Balbi dwc->revision <= DWC3_REVISION_250A)) 67832a4a135SFelipe Balbi reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; 67932a4a135SFelipe Balbi else 6804878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 6814878a028SSebastian Andrzej Siewior break; 6820ffcaf37SFelipe Balbi case DWC3_GHWPARAMS1_EN_PWROPT_HIB: 6830ffcaf37SFelipe Balbi /* enable hibernation here */ 6840ffcaf37SFelipe Balbi dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); 6852eac3992SHuang Rui 6862eac3992SHuang Rui /* 6872eac3992SHuang Rui * REVISIT Enabling this bit so that host-mode hibernation 6882eac3992SHuang Rui * will work. Device-mode hibernation is not yet implemented. 6892eac3992SHuang Rui */ 6902eac3992SHuang Rui reg |= DWC3_GCTL_GBLHIBERNATIONEN; 6910ffcaf37SFelipe Balbi break; 6924878a028SSebastian Andrzej Siewior default: 6935eb30cedSFelipe Balbi /* nothing */ 6945eb30cedSFelipe Balbi break; 6954878a028SSebastian Andrzej Siewior } 6964878a028SSebastian Andrzej Siewior 697946bd579SHuang Rui /* check if current dwc3 is on simulation board */ 698946bd579SHuang Rui if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { 6995eb30cedSFelipe Balbi dev_info(dwc->dev, "Running with FPGA optmizations\n"); 700946bd579SHuang Rui dwc->is_fpga = true; 701946bd579SHuang Rui } 702946bd579SHuang Rui 7033b81221aSHuang Rui WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga, 7043b81221aSHuang Rui "disable_scramble cannot be used on non-FPGA builds\n"); 7053b81221aSHuang Rui 7063b81221aSHuang Rui if (dwc->disable_scramble_quirk && dwc->is_fpga) 7073b81221aSHuang Rui reg |= DWC3_GCTL_DISSCRAMBLE; 7083b81221aSHuang Rui else 7093b81221aSHuang Rui reg &= ~DWC3_GCTL_DISSCRAMBLE; 7103b81221aSHuang Rui 7119a5b2f31SHuang Rui if (dwc->u2exit_lfps_quirk) 7129a5b2f31SHuang Rui reg |= DWC3_GCTL_U2EXIT_LFPS; 7139a5b2f31SHuang Rui 7144878a028SSebastian Andrzej Siewior /* 7154878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 7161d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 7174878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 7181d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 7194878a028SSebastian Andrzej Siewior */ 7204878a028SSebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 7214878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 7224878a028SSebastian Andrzej Siewior 7234878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 724941f918eSFelipe Balbi } 7254878a028SSebastian Andrzej Siewior 726f54edb53SFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc); 727f54edb53SFelipe Balbi 728941f918eSFelipe Balbi /** 729941f918eSFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 730941f918eSFelipe Balbi * @dwc: Pointer to our controller context structure 731941f918eSFelipe Balbi * 732941f918eSFelipe Balbi * Returns 0 on success otherwise negative errno. 733941f918eSFelipe Balbi */ 734941f918eSFelipe Balbi static int dwc3_core_init(struct dwc3 *dwc) 735941f918eSFelipe Balbi { 736941f918eSFelipe Balbi u32 reg; 737941f918eSFelipe Balbi int ret; 738941f918eSFelipe Balbi 739941f918eSFelipe Balbi if (!dwc3_core_is_valid(dwc)) { 740941f918eSFelipe Balbi dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 741941f918eSFelipe Balbi ret = -ENODEV; 742941f918eSFelipe Balbi goto err0; 743941f918eSFelipe Balbi } 744941f918eSFelipe Balbi 745941f918eSFelipe Balbi /* 746941f918eSFelipe Balbi * Write Linux Version Code to our GUID register so it's easy to figure 747941f918eSFelipe Balbi * out which kernel version a bug was found. 748941f918eSFelipe Balbi */ 749941f918eSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); 750941f918eSFelipe Balbi 751941f918eSFelipe Balbi /* Handle USB2.0-only core configuration */ 752941f918eSFelipe Balbi if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 753941f918eSFelipe Balbi DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { 754941f918eSFelipe Balbi if (dwc->maximum_speed == USB_SPEED_SUPER) 755941f918eSFelipe Balbi dwc->maximum_speed = USB_SPEED_HIGH; 756941f918eSFelipe Balbi } 757941f918eSFelipe Balbi 758541768b0SVignesh R ret = dwc3_core_get_phy(dwc); 759541768b0SVignesh R if (ret) 760541768b0SVignesh R goto err0; 761541768b0SVignesh R 762941f918eSFelipe Balbi ret = dwc3_core_soft_reset(dwc); 763941f918eSFelipe Balbi if (ret) 764941f918eSFelipe Balbi goto err0; 765941f918eSFelipe Balbi 766941f918eSFelipe Balbi ret = dwc3_phy_setup(dwc); 767941f918eSFelipe Balbi if (ret) 768941f918eSFelipe Balbi goto err0; 769941f918eSFelipe Balbi 770941f918eSFelipe Balbi dwc3_core_setup_global_control(dwc); 771c499ff71SFelipe Balbi dwc3_core_num_eps(dwc); 7720ffcaf37SFelipe Balbi 7730ffcaf37SFelipe Balbi ret = dwc3_setup_scratch_buffers(dwc); 7740ffcaf37SFelipe Balbi if (ret) 775c499ff71SFelipe Balbi goto err1; 776c499ff71SFelipe Balbi 777c499ff71SFelipe Balbi /* Adjust Frame Length */ 778c499ff71SFelipe Balbi dwc3_frame_length_adjustment(dwc); 779c499ff71SFelipe Balbi 780c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 0); 781c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 0); 782c499ff71SFelipe Balbi ret = phy_power_on(dwc->usb2_generic_phy); 783c499ff71SFelipe Balbi if (ret < 0) 7840ffcaf37SFelipe Balbi goto err2; 7850ffcaf37SFelipe Balbi 786c499ff71SFelipe Balbi ret = phy_power_on(dwc->usb3_generic_phy); 787c499ff71SFelipe Balbi if (ret < 0) 788c499ff71SFelipe Balbi goto err3; 789c499ff71SFelipe Balbi 790c499ff71SFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 791c499ff71SFelipe Balbi if (ret) { 792c499ff71SFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 793c499ff71SFelipe Balbi goto err4; 794c499ff71SFelipe Balbi } 795c499ff71SFelipe Balbi 79606281d46SJohn Youn /* 79706281d46SJohn Youn * ENDXFER polling is available on version 3.10a and later of 79806281d46SJohn Youn * the DWC_usb3 controller. It is NOT available in the 79906281d46SJohn Youn * DWC_usb31 controller. 80006281d46SJohn Youn */ 80106281d46SJohn Youn if (!dwc3_is_usb31(dwc) && dwc->revision >= DWC3_REVISION_310A) { 80206281d46SJohn Youn reg = dwc3_readl(dwc->regs, DWC3_GUCTL2); 80306281d46SJohn Youn reg |= DWC3_GUCTL2_RST_ACTBITLATER; 80406281d46SJohn Youn dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); 80506281d46SJohn Youn } 80606281d46SJohn Youn 80765db7a0cSWilliam Wu if (dwc->revision >= DWC3_REVISION_250A) { 8080bb39ca1SJohn Youn reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); 80965db7a0cSWilliam Wu 81065db7a0cSWilliam Wu /* 81165db7a0cSWilliam Wu * Enable hardware control of sending remote wakeup 81265db7a0cSWilliam Wu * in HS when the device is in the L1 state. 81365db7a0cSWilliam Wu */ 81465db7a0cSWilliam Wu if (dwc->revision >= DWC3_REVISION_290A) 8150bb39ca1SJohn Youn reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW; 81665db7a0cSWilliam Wu 81765db7a0cSWilliam Wu if (dwc->dis_tx_ipgap_linecheck_quirk) 81865db7a0cSWilliam Wu reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS; 81965db7a0cSWilliam Wu 8200bb39ca1SJohn Youn dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); 8210bb39ca1SJohn Youn } 8220bb39ca1SJohn Youn 82372246da4SFelipe Balbi return 0; 82472246da4SFelipe Balbi 825c499ff71SFelipe Balbi err4: 8269b9d7cddSVivek Gautam phy_power_off(dwc->usb3_generic_phy); 827c499ff71SFelipe Balbi 828c499ff71SFelipe Balbi err3: 8299b9d7cddSVivek Gautam phy_power_off(dwc->usb2_generic_phy); 830c499ff71SFelipe Balbi 8310ffcaf37SFelipe Balbi err2: 832c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 1); 833c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 1); 8340ffcaf37SFelipe Balbi 8350ffcaf37SFelipe Balbi err1: 8360ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 8370ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 83857303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 83957303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 8400ffcaf37SFelipe Balbi 84172246da4SFelipe Balbi err0: 84272246da4SFelipe Balbi return ret; 84372246da4SFelipe Balbi } 84472246da4SFelipe Balbi 8453c9f94acSFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc) 84672246da4SFelipe Balbi { 8473c9f94acSFelipe Balbi struct device *dev = dwc->dev; 848941ea361SFelipe Balbi struct device_node *node = dev->of_node; 8493c9f94acSFelipe Balbi int ret; 85072246da4SFelipe Balbi 8515088b6f5SKishon Vijay Abraham I if (node) { 8525088b6f5SKishon Vijay Abraham I dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); 8535088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); 854bb674907SFelipe Balbi } else { 855bb674907SFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 856bb674907SFelipe Balbi dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 8575088b6f5SKishon Vijay Abraham I } 8585088b6f5SKishon Vijay Abraham I 859d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb2_phy)) { 860d105e7f8SFelipe Balbi ret = PTR_ERR(dwc->usb2_phy); 861122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 862122f06e6SKishon Vijay Abraham I dwc->usb2_phy = NULL; 863122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 864d105e7f8SFelipe Balbi return ret; 865122f06e6SKishon Vijay Abraham I } else { 86651e1e7bcSFelipe Balbi dev_err(dev, "no usb2 phy configured\n"); 867122f06e6SKishon Vijay Abraham I return ret; 868122f06e6SKishon Vijay Abraham I } 86951e1e7bcSFelipe Balbi } 87051e1e7bcSFelipe Balbi 871d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb3_phy)) { 872315955d7SRuchika Kharwar ret = PTR_ERR(dwc->usb3_phy); 873122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 874122f06e6SKishon Vijay Abraham I dwc->usb3_phy = NULL; 875122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 876d105e7f8SFelipe Balbi return ret; 877122f06e6SKishon Vijay Abraham I } else { 87851e1e7bcSFelipe Balbi dev_err(dev, "no usb3 phy configured\n"); 879122f06e6SKishon Vijay Abraham I return ret; 880122f06e6SKishon Vijay Abraham I } 88151e1e7bcSFelipe Balbi } 88251e1e7bcSFelipe Balbi 88357303488SKishon Vijay Abraham I dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); 88457303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb2_generic_phy)) { 88557303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb2_generic_phy); 88657303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 88757303488SKishon Vijay Abraham I dwc->usb2_generic_phy = NULL; 88857303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 88957303488SKishon Vijay Abraham I return ret; 89057303488SKishon Vijay Abraham I } else { 89157303488SKishon Vijay Abraham I dev_err(dev, "no usb2 phy configured\n"); 89257303488SKishon Vijay Abraham I return ret; 89357303488SKishon Vijay Abraham I } 89457303488SKishon Vijay Abraham I } 89557303488SKishon Vijay Abraham I 89657303488SKishon Vijay Abraham I dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy"); 89757303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb3_generic_phy)) { 89857303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb3_generic_phy); 89957303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 90057303488SKishon Vijay Abraham I dwc->usb3_generic_phy = NULL; 90157303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 90257303488SKishon Vijay Abraham I return ret; 90357303488SKishon Vijay Abraham I } else { 90457303488SKishon Vijay Abraham I dev_err(dev, "no usb3 phy configured\n"); 90557303488SKishon Vijay Abraham I return ret; 90657303488SKishon Vijay Abraham I } 90757303488SKishon Vijay Abraham I } 90857303488SKishon Vijay Abraham I 9093c9f94acSFelipe Balbi return 0; 9103c9f94acSFelipe Balbi } 9113c9f94acSFelipe Balbi 9125f94adfeSFelipe Balbi static int dwc3_core_init_mode(struct dwc3 *dwc) 9135f94adfeSFelipe Balbi { 9145f94adfeSFelipe Balbi struct device *dev = dwc->dev; 9155f94adfeSFelipe Balbi int ret; 9165f94adfeSFelipe Balbi 9175f94adfeSFelipe Balbi switch (dwc->dr_mode) { 9185f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 919689bf72cSManu Gautam dwc->current_dr_role = DWC3_GCTL_PRTCAP_DEVICE; 92041ce1456SRoger Quadros dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); 921958d1a4cSFelipe Balbi 922958d1a4cSFelipe Balbi if (dwc->usb2_phy) 923958d1a4cSFelipe Balbi otg_set_vbus(dwc->usb2_phy->otg, false); 924958d1a4cSFelipe Balbi phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE); 925644cbbc3SManu Gautam phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE); 926958d1a4cSFelipe Balbi 9275f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 9285f94adfeSFelipe Balbi if (ret) { 9299522def4SRoger Quadros if (ret != -EPROBE_DEFER) 9305f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 9315f94adfeSFelipe Balbi return ret; 9325f94adfeSFelipe Balbi } 9335f94adfeSFelipe Balbi break; 9345f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 935689bf72cSManu Gautam dwc->current_dr_role = DWC3_GCTL_PRTCAP_HOST; 93641ce1456SRoger Quadros dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); 937958d1a4cSFelipe Balbi 938958d1a4cSFelipe Balbi if (dwc->usb2_phy) 939958d1a4cSFelipe Balbi otg_set_vbus(dwc->usb2_phy->otg, true); 940958d1a4cSFelipe Balbi phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); 941644cbbc3SManu Gautam phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST); 942958d1a4cSFelipe Balbi 9435f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 9445f94adfeSFelipe Balbi if (ret) { 9459522def4SRoger Quadros if (ret != -EPROBE_DEFER) 9465f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 9475f94adfeSFelipe Balbi return ret; 9485f94adfeSFelipe Balbi } 949d8c80bb3SVivek Gautam phy_calibrate(dwc->usb2_generic_phy); 9505f94adfeSFelipe Balbi break; 9515f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 95241ce1456SRoger Quadros INIT_WORK(&dwc->drd_work, __dwc3_set_mode); 9539840354fSRoger Quadros ret = dwc3_drd_init(dwc); 9549840354fSRoger Quadros if (ret) { 9559840354fSRoger Quadros if (ret != -EPROBE_DEFER) 9569840354fSRoger Quadros dev_err(dev, "failed to initialize dual-role\n"); 9579840354fSRoger Quadros return ret; 9589840354fSRoger Quadros } 9595f94adfeSFelipe Balbi break; 9605f94adfeSFelipe Balbi default: 9615f94adfeSFelipe Balbi dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); 9625f94adfeSFelipe Balbi return -EINVAL; 9635f94adfeSFelipe Balbi } 9645f94adfeSFelipe Balbi 9655f94adfeSFelipe Balbi return 0; 9665f94adfeSFelipe Balbi } 9675f94adfeSFelipe Balbi 9685f94adfeSFelipe Balbi static void dwc3_core_exit_mode(struct dwc3 *dwc) 9695f94adfeSFelipe Balbi { 9705f94adfeSFelipe Balbi switch (dwc->dr_mode) { 9715f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 9725f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 9735f94adfeSFelipe Balbi break; 9745f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 9755f94adfeSFelipe Balbi dwc3_host_exit(dwc); 9765f94adfeSFelipe Balbi break; 9775f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 9789840354fSRoger Quadros dwc3_drd_exit(dwc); 9795f94adfeSFelipe Balbi break; 9805f94adfeSFelipe Balbi default: 9815f94adfeSFelipe Balbi /* do nothing */ 9825f94adfeSFelipe Balbi break; 9835f94adfeSFelipe Balbi } 9845f94adfeSFelipe Balbi } 9855f94adfeSFelipe Balbi 986c5ac6116SFelipe Balbi static void dwc3_get_properties(struct dwc3 *dwc) 9873c9f94acSFelipe Balbi { 988c5ac6116SFelipe Balbi struct device *dev = dwc->dev; 98980caf7d2SHuang Rui u8 lpm_nyet_threshold; 9906b6a0c9aSHuang Rui u8 tx_de_emphasis; 991460d098cSHuang Rui u8 hird_threshold; 9923c9f94acSFelipe Balbi 99380caf7d2SHuang Rui /* default to highest possible threshold */ 99480caf7d2SHuang Rui lpm_nyet_threshold = 0xff; 99580caf7d2SHuang Rui 9966b6a0c9aSHuang Rui /* default to -3.5dB de-emphasis */ 9976b6a0c9aSHuang Rui tx_de_emphasis = 1; 9986b6a0c9aSHuang Rui 999460d098cSHuang Rui /* 1000460d098cSHuang Rui * default to assert utmi_sleep_n and use maximum allowed HIRD 1001460d098cSHuang Rui * threshold value of 0b1100 1002460d098cSHuang Rui */ 1003460d098cSHuang Rui hird_threshold = 12; 1004460d098cSHuang Rui 100563863b98SHeikki Krogerus dwc->maximum_speed = usb_get_maximum_speed(dev); 100606e7114fSHeikki Krogerus dwc->dr_mode = usb_get_dr_mode(dev); 100732f2ed86SWilliam Wu dwc->hsphy_mode = of_usb_get_phy_mode(dev->of_node); 100863863b98SHeikki Krogerus 1009d64ff406SArnd Bergmann dwc->sysdev_is_parent = device_property_read_bool(dev, 1010d64ff406SArnd Bergmann "linux,sysdev_is_parent"); 1011d64ff406SArnd Bergmann if (dwc->sysdev_is_parent) 1012d64ff406SArnd Bergmann dwc->sysdev = dwc->dev->parent; 1013d64ff406SArnd Bergmann else 1014d64ff406SArnd Bergmann dwc->sysdev = dwc->dev; 1015d64ff406SArnd Bergmann 10163d128919SHeikki Krogerus dwc->has_lpm_erratum = device_property_read_bool(dev, 101780caf7d2SHuang Rui "snps,has-lpm-erratum"); 10183d128919SHeikki Krogerus device_property_read_u8(dev, "snps,lpm-nyet-threshold", 101980caf7d2SHuang Rui &lpm_nyet_threshold); 10203d128919SHeikki Krogerus dwc->is_utmi_l1_suspend = device_property_read_bool(dev, 1021460d098cSHuang Rui "snps,is-utmi-l1-suspend"); 10223d128919SHeikki Krogerus device_property_read_u8(dev, "snps,hird-threshold", 1023460d098cSHuang Rui &hird_threshold); 10243d128919SHeikki Krogerus dwc->usb3_lpm_capable = device_property_read_bool(dev, 1025eac68e8fSRobert Baldyga "snps,usb3_lpm_capable"); 10263c9f94acSFelipe Balbi 10273d128919SHeikki Krogerus dwc->disable_scramble_quirk = device_property_read_bool(dev, 10283b81221aSHuang Rui "snps,disable_scramble_quirk"); 10293d128919SHeikki Krogerus dwc->u2exit_lfps_quirk = device_property_read_bool(dev, 10309a5b2f31SHuang Rui "snps,u2exit_lfps_quirk"); 10313d128919SHeikki Krogerus dwc->u2ss_inp3_quirk = device_property_read_bool(dev, 1032b5a65c40SHuang Rui "snps,u2ss_inp3_quirk"); 10333d128919SHeikki Krogerus dwc->req_p1p2p3_quirk = device_property_read_bool(dev, 1034df31f5b3SHuang Rui "snps,req_p1p2p3_quirk"); 10353d128919SHeikki Krogerus dwc->del_p1p2p3_quirk = device_property_read_bool(dev, 1036a2a1d0f5SHuang Rui "snps,del_p1p2p3_quirk"); 10373d128919SHeikki Krogerus dwc->del_phy_power_chg_quirk = device_property_read_bool(dev, 103841c06ffdSHuang Rui "snps,del_phy_power_chg_quirk"); 10393d128919SHeikki Krogerus dwc->lfps_filter_quirk = device_property_read_bool(dev, 1040fb67afcaSHuang Rui "snps,lfps_filter_quirk"); 10413d128919SHeikki Krogerus dwc->rx_detect_poll_quirk = device_property_read_bool(dev, 104214f4ac53SHuang Rui "snps,rx_detect_poll_quirk"); 10433d128919SHeikki Krogerus dwc->dis_u3_susphy_quirk = device_property_read_bool(dev, 104459acfa20SHuang Rui "snps,dis_u3_susphy_quirk"); 10453d128919SHeikki Krogerus dwc->dis_u2_susphy_quirk = device_property_read_bool(dev, 10460effe0a3SHuang Rui "snps,dis_u2_susphy_quirk"); 1047ec791d14SJohn Youn dwc->dis_enblslpm_quirk = device_property_read_bool(dev, 1048ec791d14SJohn Youn "snps,dis_enblslpm_quirk"); 1049e58dd357SRajesh Bhagat dwc->dis_rxdet_inp3_quirk = device_property_read_bool(dev, 1050e58dd357SRajesh Bhagat "snps,dis_rxdet_inp3_quirk"); 105116199f33SWilliam Wu dwc->dis_u2_freeclk_exists_quirk = device_property_read_bool(dev, 105216199f33SWilliam Wu "snps,dis-u2-freeclk-exists-quirk"); 105300fe081dSWilliam Wu dwc->dis_del_phy_power_chg_quirk = device_property_read_bool(dev, 105400fe081dSWilliam Wu "snps,dis-del-phy-power-chg-quirk"); 105565db7a0cSWilliam Wu dwc->dis_tx_ipgap_linecheck_quirk = device_property_read_bool(dev, 105665db7a0cSWilliam Wu "snps,dis-tx-ipgap-linecheck-quirk"); 10576b6a0c9aSHuang Rui 10583d128919SHeikki Krogerus dwc->tx_de_emphasis_quirk = device_property_read_bool(dev, 10596b6a0c9aSHuang Rui "snps,tx_de_emphasis_quirk"); 10603d128919SHeikki Krogerus device_property_read_u8(dev, "snps,tx_de_emphasis", 10616b6a0c9aSHuang Rui &tx_de_emphasis); 10623d128919SHeikki Krogerus device_property_read_string(dev, "snps,hsphy_interface", 10633e10a2ceSHeikki Krogerus &dwc->hsphy_interface); 10643d128919SHeikki Krogerus device_property_read_u32(dev, "snps,quirk-frame-length-adjustment", 1065bcdb3272SFelipe Balbi &dwc->fladj); 10663d128919SHeikki Krogerus 106780caf7d2SHuang Rui dwc->lpm_nyet_threshold = lpm_nyet_threshold; 10686b6a0c9aSHuang Rui dwc->tx_de_emphasis = tx_de_emphasis; 106980caf7d2SHuang Rui 1070460d098cSHuang Rui dwc->hird_threshold = hird_threshold 1071460d098cSHuang Rui | (dwc->is_utmi_l1_suspend << 4); 1072460d098cSHuang Rui 1073cf40b86bSJohn Youn dwc->imod_interval = 0; 1074cf40b86bSJohn Youn } 1075cf40b86bSJohn Youn 1076cf40b86bSJohn Youn /* check whether the core supports IMOD */ 1077cf40b86bSJohn Youn bool dwc3_has_imod(struct dwc3 *dwc) 1078cf40b86bSJohn Youn { 1079cf40b86bSJohn Youn return ((dwc3_is_usb3(dwc) && 1080cf40b86bSJohn Youn dwc->revision >= DWC3_REVISION_300A) || 1081cf40b86bSJohn Youn (dwc3_is_usb31(dwc) && 1082cf40b86bSJohn Youn dwc->revision >= DWC3_USB31_REVISION_120A)); 1083c5ac6116SFelipe Balbi } 1084c5ac6116SFelipe Balbi 10857ac51a12SJohn Youn static void dwc3_check_params(struct dwc3 *dwc) 10867ac51a12SJohn Youn { 10877ac51a12SJohn Youn struct device *dev = dwc->dev; 10887ac51a12SJohn Youn 1089cf40b86bSJohn Youn /* Check for proper value of imod_interval */ 1090cf40b86bSJohn Youn if (dwc->imod_interval && !dwc3_has_imod(dwc)) { 1091cf40b86bSJohn Youn dev_warn(dwc->dev, "Interrupt moderation not supported\n"); 1092cf40b86bSJohn Youn dwc->imod_interval = 0; 1093cf40b86bSJohn Youn } 1094cf40b86bSJohn Youn 109528632b44SJohn Youn /* 109628632b44SJohn Youn * Workaround for STAR 9000961433 which affects only version 109728632b44SJohn Youn * 3.00a of the DWC_usb3 core. This prevents the controller 109828632b44SJohn Youn * interrupt from being masked while handling events. IMOD 109928632b44SJohn Youn * allows us to work around this issue. Enable it for the 110028632b44SJohn Youn * affected version. 110128632b44SJohn Youn */ 110228632b44SJohn Youn if (!dwc->imod_interval && 110328632b44SJohn Youn (dwc->revision == DWC3_REVISION_300A)) 110428632b44SJohn Youn dwc->imod_interval = 1; 110528632b44SJohn Youn 11067ac51a12SJohn Youn /* Check the maximum_speed parameter */ 11077ac51a12SJohn Youn switch (dwc->maximum_speed) { 11087ac51a12SJohn Youn case USB_SPEED_LOW: 11097ac51a12SJohn Youn case USB_SPEED_FULL: 11107ac51a12SJohn Youn case USB_SPEED_HIGH: 11117ac51a12SJohn Youn case USB_SPEED_SUPER: 11127ac51a12SJohn Youn case USB_SPEED_SUPER_PLUS: 11137ac51a12SJohn Youn break; 11147ac51a12SJohn Youn default: 11157ac51a12SJohn Youn dev_err(dev, "invalid maximum_speed parameter %d\n", 11167ac51a12SJohn Youn dwc->maximum_speed); 11177ac51a12SJohn Youn /* fall through */ 11187ac51a12SJohn Youn case USB_SPEED_UNKNOWN: 11197ac51a12SJohn Youn /* default to superspeed */ 11207ac51a12SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER; 11217ac51a12SJohn Youn 11227ac51a12SJohn Youn /* 11237ac51a12SJohn Youn * default to superspeed plus if we are capable. 11247ac51a12SJohn Youn */ 11257ac51a12SJohn Youn if (dwc3_is_usb31(dwc) && 11267ac51a12SJohn Youn (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 11277ac51a12SJohn Youn DWC3_GHWPARAMS3_SSPHY_IFC_GEN2)) 11287ac51a12SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER_PLUS; 11297ac51a12SJohn Youn 11307ac51a12SJohn Youn break; 11317ac51a12SJohn Youn } 11327ac51a12SJohn Youn } 11337ac51a12SJohn Youn 1134c5ac6116SFelipe Balbi static int dwc3_probe(struct platform_device *pdev) 1135c5ac6116SFelipe Balbi { 1136c5ac6116SFelipe Balbi struct device *dev = &pdev->dev; 1137c5ac6116SFelipe Balbi struct resource *res; 1138c5ac6116SFelipe Balbi struct dwc3 *dwc; 1139c5ac6116SFelipe Balbi 1140c5ac6116SFelipe Balbi int ret; 1141c5ac6116SFelipe Balbi 1142c5ac6116SFelipe Balbi void __iomem *regs; 1143c5ac6116SFelipe Balbi 1144c5ac6116SFelipe Balbi dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL); 1145c5ac6116SFelipe Balbi if (!dwc) 1146c5ac6116SFelipe Balbi return -ENOMEM; 1147c5ac6116SFelipe Balbi 1148c5ac6116SFelipe Balbi dwc->dev = dev; 1149c5ac6116SFelipe Balbi 1150c5ac6116SFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1151c5ac6116SFelipe Balbi if (!res) { 1152c5ac6116SFelipe Balbi dev_err(dev, "missing memory resource\n"); 1153c5ac6116SFelipe Balbi return -ENODEV; 1154c5ac6116SFelipe Balbi } 1155c5ac6116SFelipe Balbi 1156c5ac6116SFelipe Balbi dwc->xhci_resources[0].start = res->start; 1157c5ac6116SFelipe Balbi dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 1158c5ac6116SFelipe Balbi DWC3_XHCI_REGS_END; 1159c5ac6116SFelipe Balbi dwc->xhci_resources[0].flags = res->flags; 1160c5ac6116SFelipe Balbi dwc->xhci_resources[0].name = res->name; 1161c5ac6116SFelipe Balbi 1162c5ac6116SFelipe Balbi res->start += DWC3_GLOBALS_REGS_START; 1163c5ac6116SFelipe Balbi 1164c5ac6116SFelipe Balbi /* 1165c5ac6116SFelipe Balbi * Request memory region but exclude xHCI regs, 1166c5ac6116SFelipe Balbi * since it will be requested by the xhci-plat driver. 1167c5ac6116SFelipe Balbi */ 1168c5ac6116SFelipe Balbi regs = devm_ioremap_resource(dev, res); 1169c5ac6116SFelipe Balbi if (IS_ERR(regs)) { 1170c5ac6116SFelipe Balbi ret = PTR_ERR(regs); 1171c5ac6116SFelipe Balbi goto err0; 1172c5ac6116SFelipe Balbi } 1173c5ac6116SFelipe Balbi 1174c5ac6116SFelipe Balbi dwc->regs = regs; 1175c5ac6116SFelipe Balbi dwc->regs_size = resource_size(res); 1176c5ac6116SFelipe Balbi 1177c5ac6116SFelipe Balbi dwc3_get_properties(dwc); 1178c5ac6116SFelipe Balbi 11796c89cce0SHeikki Krogerus platform_set_drvdata(pdev, dwc); 11802917e718SHeikki Krogerus dwc3_cache_hwparams(dwc); 11816c89cce0SHeikki Krogerus 118272246da4SFelipe Balbi spin_lock_init(&dwc->lock); 118372246da4SFelipe Balbi 1184fc8bb91bSFelipe Balbi pm_runtime_set_active(dev); 1185fc8bb91bSFelipe Balbi pm_runtime_use_autosuspend(dev); 1186fc8bb91bSFelipe Balbi pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY); 1187802ca850SChanho Park pm_runtime_enable(dev); 118832808237SRoger Quadros ret = pm_runtime_get_sync(dev); 118932808237SRoger Quadros if (ret < 0) 119032808237SRoger Quadros goto err1; 119132808237SRoger Quadros 1192802ca850SChanho Park pm_runtime_forbid(dev); 119372246da4SFelipe Balbi 11943921426bSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 11953921426bSFelipe Balbi if (ret) { 11963921426bSFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 11973921426bSFelipe Balbi ret = -ENOMEM; 119832808237SRoger Quadros goto err2; 11993921426bSFelipe Balbi } 12003921426bSFelipe Balbi 12019d6173e1SThinh Nguyen ret = dwc3_get_dr_mode(dwc); 12029d6173e1SThinh Nguyen if (ret) 12039d6173e1SThinh Nguyen goto err3; 120432a4a135SFelipe Balbi 1205c499ff71SFelipe Balbi ret = dwc3_alloc_scratch_buffers(dwc); 1206c499ff71SFelipe Balbi if (ret) 120732808237SRoger Quadros goto err3; 1208c499ff71SFelipe Balbi 120972246da4SFelipe Balbi ret = dwc3_core_init(dwc); 121072246da4SFelipe Balbi if (ret) { 1211802ca850SChanho Park dev_err(dev, "failed to initialize core\n"); 121232808237SRoger Quadros goto err4; 121372246da4SFelipe Balbi } 121472246da4SFelipe Balbi 12157ac51a12SJohn Youn dwc3_check_params(dwc); 12162c7f1bd9SJohn Youn 12175f94adfeSFelipe Balbi ret = dwc3_core_init_mode(dwc); 12185f94adfeSFelipe Balbi if (ret) 121932808237SRoger Quadros goto err5; 122072246da4SFelipe Balbi 12214e9f3118SDu, Changbin dwc3_debugfs_init(dwc); 1222fc8bb91bSFelipe Balbi pm_runtime_put(dev); 122372246da4SFelipe Balbi 122472246da4SFelipe Balbi return 0; 122572246da4SFelipe Balbi 122632808237SRoger Quadros err5: 1227f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 1228f122d33eSFelipe Balbi 122932808237SRoger Quadros err4: 1230c499ff71SFelipe Balbi dwc3_free_scratch_buffers(dwc); 123172246da4SFelipe Balbi 123232808237SRoger Quadros err3: 12333921426bSFelipe Balbi dwc3_free_event_buffers(dwc); 123488bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 12353921426bSFelipe Balbi 123632808237SRoger Quadros err2: 123732808237SRoger Quadros pm_runtime_allow(&pdev->dev); 123832808237SRoger Quadros 123932808237SRoger Quadros err1: 124032808237SRoger Quadros pm_runtime_put_sync(&pdev->dev); 124132808237SRoger Quadros pm_runtime_disable(&pdev->dev); 124232808237SRoger Quadros 12433da1f6eeSFelipe Balbi err0: 12443da1f6eeSFelipe Balbi /* 12453da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 12463da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 12473da1f6eeSFelipe Balbi * memory region the next time probe is called. 12483da1f6eeSFelipe Balbi */ 12493da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 12503da1f6eeSFelipe Balbi 125172246da4SFelipe Balbi return ret; 125272246da4SFelipe Balbi } 125372246da4SFelipe Balbi 1254fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev) 125572246da4SFelipe Balbi { 125672246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 12573da1f6eeSFelipe Balbi struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 12583da1f6eeSFelipe Balbi 1259fc8bb91bSFelipe Balbi pm_runtime_get_sync(&pdev->dev); 12603da1f6eeSFelipe Balbi /* 12613da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 12623da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 12633da1f6eeSFelipe Balbi * memory region the next time probe is called. 12643da1f6eeSFelipe Balbi */ 12653da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 126672246da4SFelipe Balbi 1267dc99f16fSFelipe Balbi dwc3_debugfs_exit(dwc); 1268dc99f16fSFelipe Balbi dwc3_core_exit_mode(dwc); 12698ba007a9SKishon Vijay Abraham I 127072246da4SFelipe Balbi dwc3_core_exit(dwc); 127188bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 127272246da4SFelipe Balbi 1273fc8bb91bSFelipe Balbi pm_runtime_put_sync(&pdev->dev); 1274fc8bb91bSFelipe Balbi pm_runtime_allow(&pdev->dev); 1275fc8bb91bSFelipe Balbi pm_runtime_disable(&pdev->dev); 1276fc8bb91bSFelipe Balbi 1277c499ff71SFelipe Balbi dwc3_free_event_buffers(dwc); 1278c499ff71SFelipe Balbi dwc3_free_scratch_buffers(dwc); 1279c499ff71SFelipe Balbi 128072246da4SFelipe Balbi return 0; 128172246da4SFelipe Balbi } 128272246da4SFelipe Balbi 1283fc8bb91bSFelipe Balbi #ifdef CONFIG_PM 1284fc8bb91bSFelipe Balbi static int dwc3_suspend_common(struct dwc3 *dwc) 12857415f17cSFelipe Balbi { 1286fc8bb91bSFelipe Balbi unsigned long flags; 12877415f17cSFelipe Balbi 1288689bf72cSManu Gautam switch (dwc->current_dr_role) { 1289689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_DEVICE: 1290fc8bb91bSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 12917415f17cSFelipe Balbi dwc3_gadget_suspend(dwc); 1292fc8bb91bSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 1293689bf72cSManu Gautam dwc3_core_exit(dwc); 129451f5d49aSFelipe Balbi break; 1295689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_HOST: 12967415f17cSFelipe Balbi default: 129751f5d49aSFelipe Balbi /* do nothing */ 12987415f17cSFelipe Balbi break; 12997415f17cSFelipe Balbi } 13007415f17cSFelipe Balbi 1301fc8bb91bSFelipe Balbi return 0; 1302fc8bb91bSFelipe Balbi } 1303fc8bb91bSFelipe Balbi 1304fc8bb91bSFelipe Balbi static int dwc3_resume_common(struct dwc3 *dwc) 1305fc8bb91bSFelipe Balbi { 1306fc8bb91bSFelipe Balbi unsigned long flags; 1307fc8bb91bSFelipe Balbi int ret; 1308fc8bb91bSFelipe Balbi 1309689bf72cSManu Gautam switch (dwc->current_dr_role) { 1310689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_DEVICE: 1311fc8bb91bSFelipe Balbi ret = dwc3_core_init(dwc); 1312fc8bb91bSFelipe Balbi if (ret) 1313fc8bb91bSFelipe Balbi return ret; 1314fc8bb91bSFelipe Balbi 1315fc8bb91bSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 1316fc8bb91bSFelipe Balbi dwc3_gadget_resume(dwc); 1317fc8bb91bSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 1318689bf72cSManu Gautam break; 1319689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_HOST: 1320fc8bb91bSFelipe Balbi default: 1321fc8bb91bSFelipe Balbi /* do nothing */ 1322fc8bb91bSFelipe Balbi break; 1323fc8bb91bSFelipe Balbi } 1324fc8bb91bSFelipe Balbi 1325fc8bb91bSFelipe Balbi return 0; 1326fc8bb91bSFelipe Balbi } 1327fc8bb91bSFelipe Balbi 1328fc8bb91bSFelipe Balbi static int dwc3_runtime_checks(struct dwc3 *dwc) 1329fc8bb91bSFelipe Balbi { 1330689bf72cSManu Gautam switch (dwc->current_dr_role) { 1331fc8bb91bSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 1332fc8bb91bSFelipe Balbi case USB_DR_MODE_OTG: 1333fc8bb91bSFelipe Balbi if (dwc->connected) 1334fc8bb91bSFelipe Balbi return -EBUSY; 1335fc8bb91bSFelipe Balbi break; 1336fc8bb91bSFelipe Balbi case USB_DR_MODE_HOST: 1337fc8bb91bSFelipe Balbi default: 1338fc8bb91bSFelipe Balbi /* do nothing */ 1339fc8bb91bSFelipe Balbi break; 1340fc8bb91bSFelipe Balbi } 1341fc8bb91bSFelipe Balbi 1342fc8bb91bSFelipe Balbi return 0; 1343fc8bb91bSFelipe Balbi } 1344fc8bb91bSFelipe Balbi 1345fc8bb91bSFelipe Balbi static int dwc3_runtime_suspend(struct device *dev) 1346fc8bb91bSFelipe Balbi { 1347fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1348fc8bb91bSFelipe Balbi int ret; 1349fc8bb91bSFelipe Balbi 1350fc8bb91bSFelipe Balbi if (dwc3_runtime_checks(dwc)) 1351fc8bb91bSFelipe Balbi return -EBUSY; 1352fc8bb91bSFelipe Balbi 1353fc8bb91bSFelipe Balbi ret = dwc3_suspend_common(dwc); 1354fc8bb91bSFelipe Balbi if (ret) 1355fc8bb91bSFelipe Balbi return ret; 1356fc8bb91bSFelipe Balbi 1357fc8bb91bSFelipe Balbi device_init_wakeup(dev, true); 1358fc8bb91bSFelipe Balbi 1359fc8bb91bSFelipe Balbi return 0; 1360fc8bb91bSFelipe Balbi } 1361fc8bb91bSFelipe Balbi 1362fc8bb91bSFelipe Balbi static int dwc3_runtime_resume(struct device *dev) 1363fc8bb91bSFelipe Balbi { 1364fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1365fc8bb91bSFelipe Balbi int ret; 1366fc8bb91bSFelipe Balbi 1367fc8bb91bSFelipe Balbi device_init_wakeup(dev, false); 1368fc8bb91bSFelipe Balbi 1369fc8bb91bSFelipe Balbi ret = dwc3_resume_common(dwc); 1370fc8bb91bSFelipe Balbi if (ret) 1371fc8bb91bSFelipe Balbi return ret; 1372fc8bb91bSFelipe Balbi 1373689bf72cSManu Gautam switch (dwc->current_dr_role) { 1374689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_DEVICE: 1375fc8bb91bSFelipe Balbi dwc3_gadget_process_pending_events(dwc); 1376fc8bb91bSFelipe Balbi break; 1377689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_HOST: 1378fc8bb91bSFelipe Balbi default: 1379fc8bb91bSFelipe Balbi /* do nothing */ 1380fc8bb91bSFelipe Balbi break; 1381fc8bb91bSFelipe Balbi } 1382fc8bb91bSFelipe Balbi 1383fc8bb91bSFelipe Balbi pm_runtime_mark_last_busy(dev); 1384fc8bb91bSFelipe Balbi 1385fc8bb91bSFelipe Balbi return 0; 1386fc8bb91bSFelipe Balbi } 1387fc8bb91bSFelipe Balbi 1388fc8bb91bSFelipe Balbi static int dwc3_runtime_idle(struct device *dev) 1389fc8bb91bSFelipe Balbi { 1390fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1391fc8bb91bSFelipe Balbi 1392689bf72cSManu Gautam switch (dwc->current_dr_role) { 1393689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_DEVICE: 1394fc8bb91bSFelipe Balbi if (dwc3_runtime_checks(dwc)) 1395fc8bb91bSFelipe Balbi return -EBUSY; 1396fc8bb91bSFelipe Balbi break; 1397689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_HOST: 1398fc8bb91bSFelipe Balbi default: 1399fc8bb91bSFelipe Balbi /* do nothing */ 1400fc8bb91bSFelipe Balbi break; 1401fc8bb91bSFelipe Balbi } 1402fc8bb91bSFelipe Balbi 1403fc8bb91bSFelipe Balbi pm_runtime_mark_last_busy(dev); 1404fc8bb91bSFelipe Balbi pm_runtime_autosuspend(dev); 1405fc8bb91bSFelipe Balbi 1406fc8bb91bSFelipe Balbi return 0; 1407fc8bb91bSFelipe Balbi } 1408fc8bb91bSFelipe Balbi #endif /* CONFIG_PM */ 1409fc8bb91bSFelipe Balbi 1410fc8bb91bSFelipe Balbi #ifdef CONFIG_PM_SLEEP 1411fc8bb91bSFelipe Balbi static int dwc3_suspend(struct device *dev) 1412fc8bb91bSFelipe Balbi { 1413fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1414fc8bb91bSFelipe Balbi int ret; 1415fc8bb91bSFelipe Balbi 1416fc8bb91bSFelipe Balbi ret = dwc3_suspend_common(dwc); 1417fc8bb91bSFelipe Balbi if (ret) 1418fc8bb91bSFelipe Balbi return ret; 1419fc8bb91bSFelipe Balbi 14206344475fSSekhar Nori pinctrl_pm_select_sleep_state(dev); 14216344475fSSekhar Nori 14227415f17cSFelipe Balbi return 0; 14237415f17cSFelipe Balbi } 14247415f17cSFelipe Balbi 14257415f17cSFelipe Balbi static int dwc3_resume(struct device *dev) 14267415f17cSFelipe Balbi { 14277415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 142857303488SKishon Vijay Abraham I int ret; 14297415f17cSFelipe Balbi 14306344475fSSekhar Nori pinctrl_pm_select_default_state(dev); 14316344475fSSekhar Nori 1432fc8bb91bSFelipe Balbi ret = dwc3_resume_common(dwc); 143351f5d49aSFelipe Balbi if (ret) 14345c4ad318SFelipe Balbi return ret; 14355c4ad318SFelipe Balbi 14367415f17cSFelipe Balbi pm_runtime_disable(dev); 14377415f17cSFelipe Balbi pm_runtime_set_active(dev); 14387415f17cSFelipe Balbi pm_runtime_enable(dev); 14397415f17cSFelipe Balbi 14407415f17cSFelipe Balbi return 0; 14417415f17cSFelipe Balbi } 14427f370ed0SFelipe Balbi #endif /* CONFIG_PM_SLEEP */ 14437415f17cSFelipe Balbi 14447415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = { 14457415f17cSFelipe Balbi SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 1446fc8bb91bSFelipe Balbi SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume, 1447fc8bb91bSFelipe Balbi dwc3_runtime_idle) 14487415f17cSFelipe Balbi }; 14497415f17cSFelipe Balbi 14505088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF 14515088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = { 14525088b6f5SKishon Vijay Abraham I { 145322a5aa17SFelipe Balbi .compatible = "snps,dwc3" 145422a5aa17SFelipe Balbi }, 145522a5aa17SFelipe Balbi { 14565088b6f5SKishon Vijay Abraham I .compatible = "synopsys,dwc3" 14575088b6f5SKishon Vijay Abraham I }, 14585088b6f5SKishon Vijay Abraham I { }, 14595088b6f5SKishon Vijay Abraham I }; 14605088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match); 14615088b6f5SKishon Vijay Abraham I #endif 14625088b6f5SKishon Vijay Abraham I 1463404905a6SHeikki Krogerus #ifdef CONFIG_ACPI 1464404905a6SHeikki Krogerus 1465404905a6SHeikki Krogerus #define ACPI_ID_INTEL_BSW "808622B7" 1466404905a6SHeikki Krogerus 1467404905a6SHeikki Krogerus static const struct acpi_device_id dwc3_acpi_match[] = { 1468404905a6SHeikki Krogerus { ACPI_ID_INTEL_BSW, 0 }, 1469404905a6SHeikki Krogerus { }, 1470404905a6SHeikki Krogerus }; 1471404905a6SHeikki Krogerus MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match); 1472404905a6SHeikki Krogerus #endif 1473404905a6SHeikki Krogerus 147472246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 147572246da4SFelipe Balbi .probe = dwc3_probe, 14767690417dSBill Pemberton .remove = dwc3_remove, 147772246da4SFelipe Balbi .driver = { 147872246da4SFelipe Balbi .name = "dwc3", 14795088b6f5SKishon Vijay Abraham I .of_match_table = of_match_ptr(of_dwc3_match), 1480404905a6SHeikki Krogerus .acpi_match_table = ACPI_PTR(dwc3_acpi_match), 14817f370ed0SFelipe Balbi .pm = &dwc3_dev_pm_ops, 148272246da4SFelipe Balbi }, 148372246da4SFelipe Balbi }; 148472246da4SFelipe Balbi 1485b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 1486b1116dccSTobias Klauser 14877ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 148872246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 14895945f789SFelipe Balbi MODULE_LICENSE("GPL v2"); 149072246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 1491