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 92f09cc79bSRoger Quadros void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode) 933140e8cbSSebastian Andrzej Siewior { 943140e8cbSSebastian Andrzej Siewior u32 reg; 953140e8cbSSebastian Andrzej Siewior 963140e8cbSSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 973140e8cbSSebastian Andrzej Siewior reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); 983140e8cbSSebastian Andrzej Siewior reg |= DWC3_GCTL_PRTCAPDIR(mode); 993140e8cbSSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 100c4a5153eSManu Gautam 101c4a5153eSManu Gautam dwc->current_dr_role = mode; 10241ce1456SRoger Quadros } 1036b3261a2SRoger Quadros 10441ce1456SRoger Quadros static void __dwc3_set_mode(struct work_struct *work) 10541ce1456SRoger Quadros { 10641ce1456SRoger Quadros struct dwc3 *dwc = work_to_dwc(work); 10741ce1456SRoger Quadros unsigned long flags; 10841ce1456SRoger Quadros int ret; 10941ce1456SRoger Quadros 110f09cc79bSRoger Quadros if (dwc->dr_mode != USB_DR_MODE_OTG) 111f09cc79bSRoger Quadros return; 112f09cc79bSRoger Quadros 113f09cc79bSRoger Quadros if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_OTG) 114f09cc79bSRoger Quadros dwc3_otg_update(dwc, 0); 115f09cc79bSRoger Quadros 11641ce1456SRoger Quadros if (!dwc->desired_dr_role) 11741ce1456SRoger Quadros return; 11841ce1456SRoger Quadros 11941ce1456SRoger Quadros if (dwc->desired_dr_role == dwc->current_dr_role) 12041ce1456SRoger Quadros return; 12141ce1456SRoger Quadros 122f09cc79bSRoger Quadros if (dwc->desired_dr_role == DWC3_GCTL_PRTCAP_OTG && dwc->edev) 123daaecc65SRoger Quadros return; 124daaecc65SRoger Quadros 12541ce1456SRoger Quadros switch (dwc->current_dr_role) { 12641ce1456SRoger Quadros case DWC3_GCTL_PRTCAP_HOST: 12741ce1456SRoger Quadros dwc3_host_exit(dwc); 12841ce1456SRoger Quadros break; 12941ce1456SRoger Quadros case DWC3_GCTL_PRTCAP_DEVICE: 13041ce1456SRoger Quadros dwc3_gadget_exit(dwc); 13141ce1456SRoger Quadros dwc3_event_buffers_cleanup(dwc); 13241ce1456SRoger Quadros break; 133f09cc79bSRoger Quadros case DWC3_GCTL_PRTCAP_OTG: 134f09cc79bSRoger Quadros dwc3_otg_exit(dwc); 135f09cc79bSRoger Quadros spin_lock_irqsave(&dwc->lock, flags); 136f09cc79bSRoger Quadros dwc->desired_otg_role = DWC3_OTG_ROLE_IDLE; 137f09cc79bSRoger Quadros spin_unlock_irqrestore(&dwc->lock, flags); 138f09cc79bSRoger Quadros dwc3_otg_update(dwc, 1); 139f09cc79bSRoger Quadros break; 14041ce1456SRoger Quadros default: 14141ce1456SRoger Quadros break; 14241ce1456SRoger Quadros } 14341ce1456SRoger Quadros 14441ce1456SRoger Quadros spin_lock_irqsave(&dwc->lock, flags); 14541ce1456SRoger Quadros 14641ce1456SRoger Quadros dwc3_set_prtcap(dwc, dwc->desired_dr_role); 14741ce1456SRoger Quadros 14841ce1456SRoger Quadros spin_unlock_irqrestore(&dwc->lock, flags); 14941ce1456SRoger Quadros 15041ce1456SRoger Quadros switch (dwc->desired_dr_role) { 15141ce1456SRoger Quadros case DWC3_GCTL_PRTCAP_HOST: 15241ce1456SRoger Quadros ret = dwc3_host_init(dwc); 153958d1a4cSFelipe Balbi if (ret) { 15441ce1456SRoger Quadros dev_err(dwc->dev, "failed to initialize host\n"); 155958d1a4cSFelipe Balbi } else { 156958d1a4cSFelipe Balbi if (dwc->usb2_phy) 157958d1a4cSFelipe Balbi otg_set_vbus(dwc->usb2_phy->otg, true); 158958d1a4cSFelipe Balbi phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); 159644cbbc3SManu Gautam phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST); 160d8c80bb3SVivek Gautam phy_calibrate(dwc->usb2_generic_phy); 161958d1a4cSFelipe Balbi } 16241ce1456SRoger Quadros break; 16341ce1456SRoger Quadros case DWC3_GCTL_PRTCAP_DEVICE: 16441ce1456SRoger Quadros dwc3_event_buffers_setup(dwc); 165958d1a4cSFelipe Balbi 166958d1a4cSFelipe Balbi if (dwc->usb2_phy) 167958d1a4cSFelipe Balbi otg_set_vbus(dwc->usb2_phy->otg, false); 168958d1a4cSFelipe Balbi phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE); 169644cbbc3SManu Gautam phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE); 170958d1a4cSFelipe Balbi 17141ce1456SRoger Quadros ret = dwc3_gadget_init(dwc); 17241ce1456SRoger Quadros if (ret) 17341ce1456SRoger Quadros dev_err(dwc->dev, "failed to initialize peripheral\n"); 17441ce1456SRoger Quadros break; 175f09cc79bSRoger Quadros case DWC3_GCTL_PRTCAP_OTG: 176f09cc79bSRoger Quadros dwc3_otg_init(dwc); 177f09cc79bSRoger Quadros dwc3_otg_update(dwc, 0); 178f09cc79bSRoger Quadros break; 17941ce1456SRoger Quadros default: 18041ce1456SRoger Quadros break; 18141ce1456SRoger Quadros } 182f09cc79bSRoger Quadros 18341ce1456SRoger Quadros } 18441ce1456SRoger Quadros 18541ce1456SRoger Quadros void dwc3_set_mode(struct dwc3 *dwc, u32 mode) 18641ce1456SRoger Quadros { 18741ce1456SRoger Quadros unsigned long flags; 18841ce1456SRoger Quadros 18941ce1456SRoger Quadros spin_lock_irqsave(&dwc->lock, flags); 19041ce1456SRoger Quadros dwc->desired_dr_role = mode; 19141ce1456SRoger Quadros spin_unlock_irqrestore(&dwc->lock, flags); 19241ce1456SRoger Quadros 19341ce1456SRoger Quadros queue_work(system_power_efficient_wq, &dwc->drd_work); 1943140e8cbSSebastian Andrzej Siewior } 1958300dd23SFelipe Balbi 196cf6d867dSFelipe Balbi u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type) 197cf6d867dSFelipe Balbi { 198cf6d867dSFelipe Balbi struct dwc3 *dwc = dep->dwc; 199cf6d867dSFelipe Balbi u32 reg; 200cf6d867dSFelipe Balbi 201cf6d867dSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GDBGFIFOSPACE, 202cf6d867dSFelipe Balbi DWC3_GDBGFIFOSPACE_NUM(dep->number) | 203cf6d867dSFelipe Balbi DWC3_GDBGFIFOSPACE_TYPE(type)); 204cf6d867dSFelipe Balbi 205cf6d867dSFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GDBGFIFOSPACE); 206cf6d867dSFelipe Balbi 207cf6d867dSFelipe Balbi return DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(reg); 208cf6d867dSFelipe Balbi } 209cf6d867dSFelipe Balbi 21072246da4SFelipe Balbi /** 21172246da4SFelipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 21272246da4SFelipe Balbi * @dwc: pointer to our context structure 21372246da4SFelipe Balbi */ 21457303488SKishon Vijay Abraham I static int dwc3_core_soft_reset(struct dwc3 *dwc) 21572246da4SFelipe Balbi { 21672246da4SFelipe Balbi u32 reg; 217f59dcab1SFelipe Balbi int retries = 1000; 21857303488SKishon Vijay Abraham I int ret; 21972246da4SFelipe Balbi 22051e1e7bcSFelipe Balbi usb_phy_init(dwc->usb2_phy); 22151e1e7bcSFelipe Balbi usb_phy_init(dwc->usb3_phy); 22257303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 22357303488SKishon Vijay Abraham I if (ret < 0) 22457303488SKishon Vijay Abraham I return ret; 22557303488SKishon Vijay Abraham I 22657303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 22757303488SKishon Vijay Abraham I if (ret < 0) { 22857303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 22957303488SKishon Vijay Abraham I return ret; 23057303488SKishon Vijay Abraham I } 23172246da4SFelipe Balbi 232f59dcab1SFelipe Balbi /* 233f59dcab1SFelipe Balbi * We're resetting only the device side because, if we're in host mode, 234f59dcab1SFelipe Balbi * XHCI driver will reset the host block. If dwc3 was configured for 235f59dcab1SFelipe Balbi * host-only mode, then we can return early. 236f59dcab1SFelipe Balbi */ 237c4a5153eSManu Gautam if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) 23857303488SKishon Vijay Abraham I return 0; 239f59dcab1SFelipe Balbi 240f59dcab1SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 241f59dcab1SFelipe Balbi reg |= DWC3_DCTL_CSFTRST; 242f59dcab1SFelipe Balbi dwc3_writel(dwc->regs, DWC3_DCTL, reg); 243f59dcab1SFelipe Balbi 244f59dcab1SFelipe Balbi do { 245f59dcab1SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 246f59dcab1SFelipe Balbi if (!(reg & DWC3_DCTL_CSFTRST)) 247f59dcab1SFelipe Balbi return 0; 248f59dcab1SFelipe Balbi 249f59dcab1SFelipe Balbi udelay(1); 250f59dcab1SFelipe Balbi } while (--retries); 251f59dcab1SFelipe Balbi 25200b42170SBrian Norris phy_exit(dwc->usb3_generic_phy); 25300b42170SBrian Norris phy_exit(dwc->usb2_generic_phy); 25400b42170SBrian Norris 255f59dcab1SFelipe Balbi return -ETIMEDOUT; 25672246da4SFelipe Balbi } 25772246da4SFelipe Balbi 258db2be4e9SNikhil Badola /* 259db2be4e9SNikhil Badola * dwc3_frame_length_adjustment - Adjusts frame length if required 260db2be4e9SNikhil Badola * @dwc3: Pointer to our controller context structure 261db2be4e9SNikhil Badola */ 262bcdb3272SFelipe Balbi static void dwc3_frame_length_adjustment(struct dwc3 *dwc) 263db2be4e9SNikhil Badola { 264db2be4e9SNikhil Badola u32 reg; 265db2be4e9SNikhil Badola u32 dft; 266db2be4e9SNikhil Badola 267db2be4e9SNikhil Badola if (dwc->revision < DWC3_REVISION_250A) 268db2be4e9SNikhil Badola return; 269db2be4e9SNikhil Badola 270bcdb3272SFelipe Balbi if (dwc->fladj == 0) 271db2be4e9SNikhil Badola return; 272db2be4e9SNikhil Badola 273db2be4e9SNikhil Badola reg = dwc3_readl(dwc->regs, DWC3_GFLADJ); 274db2be4e9SNikhil Badola dft = reg & DWC3_GFLADJ_30MHZ_MASK; 275bcdb3272SFelipe Balbi if (!dev_WARN_ONCE(dwc->dev, dft == dwc->fladj, 276db2be4e9SNikhil Badola "request value same as default, ignoring\n")) { 277db2be4e9SNikhil Badola reg &= ~DWC3_GFLADJ_30MHZ_MASK; 278bcdb3272SFelipe Balbi reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj; 279db2be4e9SNikhil Badola dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); 280db2be4e9SNikhil Badola } 281db2be4e9SNikhil Badola } 282db2be4e9SNikhil Badola 283c5cc74e8SHeikki Krogerus /** 28472246da4SFelipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 28572246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 28672246da4SFelipe Balbi * @evt: Pointer to event buffer to be freed 28772246da4SFelipe Balbi */ 28872246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc, 28972246da4SFelipe Balbi struct dwc3_event_buffer *evt) 29072246da4SFelipe Balbi { 291d64ff406SArnd Bergmann dma_free_coherent(dwc->sysdev, evt->length, evt->buf, evt->dma); 29272246da4SFelipe Balbi } 29372246da4SFelipe Balbi 29472246da4SFelipe Balbi /** 2951d046793SPaul Zimmerman * dwc3_alloc_one_event_buffer - Allocates one event buffer structure 29672246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 29772246da4SFelipe Balbi * @length: size of the event buffer 29872246da4SFelipe Balbi * 2991d046793SPaul Zimmerman * Returns a pointer to the allocated event buffer structure on success 30072246da4SFelipe Balbi * otherwise ERR_PTR(errno). 30172246da4SFelipe Balbi */ 30267d0b500SFelipe Balbi static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, 30367d0b500SFelipe Balbi unsigned length) 30472246da4SFelipe Balbi { 30572246da4SFelipe Balbi struct dwc3_event_buffer *evt; 30672246da4SFelipe Balbi 307380f0d28SFelipe Balbi evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL); 30872246da4SFelipe Balbi if (!evt) 30972246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 31072246da4SFelipe Balbi 31172246da4SFelipe Balbi evt->dwc = dwc; 31272246da4SFelipe Balbi evt->length = length; 313d9fa4c63SJohn Youn evt->cache = devm_kzalloc(dwc->dev, length, GFP_KERNEL); 314d9fa4c63SJohn Youn if (!evt->cache) 315d9fa4c63SJohn Youn return ERR_PTR(-ENOMEM); 316d9fa4c63SJohn Youn 317d64ff406SArnd Bergmann evt->buf = dma_alloc_coherent(dwc->sysdev, length, 31872246da4SFelipe Balbi &evt->dma, GFP_KERNEL); 319e32672f0SFelipe Balbi if (!evt->buf) 32072246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 32172246da4SFelipe Balbi 32272246da4SFelipe Balbi return evt; 32372246da4SFelipe Balbi } 32472246da4SFelipe Balbi 32572246da4SFelipe Balbi /** 32672246da4SFelipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 32772246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 32872246da4SFelipe Balbi */ 32972246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc) 33072246da4SFelipe Balbi { 33172246da4SFelipe Balbi struct dwc3_event_buffer *evt; 33272246da4SFelipe Balbi 333696c8b12SFelipe Balbi evt = dwc->ev_buf; 33464b6c8a7SAnton Tikhomirov if (evt) 33572246da4SFelipe Balbi dwc3_free_one_event_buffer(dwc, evt); 33672246da4SFelipe Balbi } 33772246da4SFelipe Balbi 33872246da4SFelipe Balbi /** 33972246da4SFelipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 3401d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 34172246da4SFelipe Balbi * @length: size of event buffer 34272246da4SFelipe Balbi * 3431d046793SPaul Zimmerman * Returns 0 on success otherwise negative errno. In the error case, dwc 34472246da4SFelipe Balbi * may contain some buffers allocated but not all which were requested. 34572246da4SFelipe Balbi */ 34641ac7b3aSBill Pemberton static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) 34772246da4SFelipe Balbi { 34872246da4SFelipe Balbi struct dwc3_event_buffer *evt; 34972246da4SFelipe Balbi 35072246da4SFelipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 35172246da4SFelipe Balbi if (IS_ERR(evt)) { 35272246da4SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 35372246da4SFelipe Balbi return PTR_ERR(evt); 35472246da4SFelipe Balbi } 355696c8b12SFelipe Balbi dwc->ev_buf = evt; 35672246da4SFelipe Balbi 35772246da4SFelipe Balbi return 0; 35872246da4SFelipe Balbi } 35972246da4SFelipe Balbi 36072246da4SFelipe Balbi /** 36172246da4SFelipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 3621d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 36372246da4SFelipe Balbi * 36472246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 36572246da4SFelipe Balbi */ 366f09cc79bSRoger Quadros int dwc3_event_buffers_setup(struct dwc3 *dwc) 36772246da4SFelipe Balbi { 36872246da4SFelipe Balbi struct dwc3_event_buffer *evt; 36972246da4SFelipe Balbi 370696c8b12SFelipe Balbi evt = dwc->ev_buf; 3717acd85e0SPaul Zimmerman evt->lpos = 0; 372660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 37372246da4SFelipe Balbi lower_32_bits(evt->dma)); 374660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 37572246da4SFelipe Balbi upper_32_bits(evt->dma)); 376660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), 37768d6a01bSFelipe Balbi DWC3_GEVNTSIZ_SIZE(evt->length)); 378660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 37972246da4SFelipe Balbi 38072246da4SFelipe Balbi return 0; 38172246da4SFelipe Balbi } 38272246da4SFelipe Balbi 383f09cc79bSRoger Quadros void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 38472246da4SFelipe Balbi { 38572246da4SFelipe Balbi struct dwc3_event_buffer *evt; 38672246da4SFelipe Balbi 387696c8b12SFelipe Balbi evt = dwc->ev_buf; 3887acd85e0SPaul Zimmerman 3897acd85e0SPaul Zimmerman evt->lpos = 0; 3907acd85e0SPaul Zimmerman 391660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 0); 392660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 0); 393660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK 39468d6a01bSFelipe Balbi | DWC3_GEVNTSIZ_SIZE(0)); 395660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 39672246da4SFelipe Balbi } 39772246da4SFelipe Balbi 3980ffcaf37SFelipe Balbi static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) 3990ffcaf37SFelipe Balbi { 4000ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 4010ffcaf37SFelipe Balbi return 0; 4020ffcaf37SFelipe Balbi 4030ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 4040ffcaf37SFelipe Balbi return 0; 4050ffcaf37SFelipe Balbi 4060ffcaf37SFelipe Balbi dwc->scratchbuf = kmalloc_array(dwc->nr_scratch, 4070ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, GFP_KERNEL); 4080ffcaf37SFelipe Balbi if (!dwc->scratchbuf) 4090ffcaf37SFelipe Balbi return -ENOMEM; 4100ffcaf37SFelipe Balbi 4110ffcaf37SFelipe Balbi return 0; 4120ffcaf37SFelipe Balbi } 4130ffcaf37SFelipe Balbi 4140ffcaf37SFelipe Balbi static int dwc3_setup_scratch_buffers(struct dwc3 *dwc) 4150ffcaf37SFelipe Balbi { 4160ffcaf37SFelipe Balbi dma_addr_t scratch_addr; 4170ffcaf37SFelipe Balbi u32 param; 4180ffcaf37SFelipe Balbi int ret; 4190ffcaf37SFelipe Balbi 4200ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 4210ffcaf37SFelipe Balbi return 0; 4220ffcaf37SFelipe Balbi 4230ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 4240ffcaf37SFelipe Balbi return 0; 4250ffcaf37SFelipe Balbi 4260ffcaf37SFelipe Balbi /* should never fall here */ 4270ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 4280ffcaf37SFelipe Balbi return 0; 4290ffcaf37SFelipe Balbi 430d64ff406SArnd Bergmann scratch_addr = dma_map_single(dwc->sysdev, dwc->scratchbuf, 4310ffcaf37SFelipe Balbi dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, 4320ffcaf37SFelipe Balbi DMA_BIDIRECTIONAL); 433d64ff406SArnd Bergmann if (dma_mapping_error(dwc->sysdev, scratch_addr)) { 434d64ff406SArnd Bergmann dev_err(dwc->sysdev, "failed to map scratch buffer\n"); 4350ffcaf37SFelipe Balbi ret = -EFAULT; 4360ffcaf37SFelipe Balbi goto err0; 4370ffcaf37SFelipe Balbi } 4380ffcaf37SFelipe Balbi 4390ffcaf37SFelipe Balbi dwc->scratch_addr = scratch_addr; 4400ffcaf37SFelipe Balbi 4410ffcaf37SFelipe Balbi param = lower_32_bits(scratch_addr); 4420ffcaf37SFelipe Balbi 4430ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 4440ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param); 4450ffcaf37SFelipe Balbi if (ret < 0) 4460ffcaf37SFelipe Balbi goto err1; 4470ffcaf37SFelipe Balbi 4480ffcaf37SFelipe Balbi param = upper_32_bits(scratch_addr); 4490ffcaf37SFelipe Balbi 4500ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 4510ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param); 4520ffcaf37SFelipe Balbi if (ret < 0) 4530ffcaf37SFelipe Balbi goto err1; 4540ffcaf37SFelipe Balbi 4550ffcaf37SFelipe Balbi return 0; 4560ffcaf37SFelipe Balbi 4570ffcaf37SFelipe Balbi err1: 458d64ff406SArnd Bergmann dma_unmap_single(dwc->sysdev, dwc->scratch_addr, dwc->nr_scratch * 4590ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 4600ffcaf37SFelipe Balbi 4610ffcaf37SFelipe Balbi err0: 4620ffcaf37SFelipe Balbi return ret; 4630ffcaf37SFelipe Balbi } 4640ffcaf37SFelipe Balbi 4650ffcaf37SFelipe Balbi static void dwc3_free_scratch_buffers(struct dwc3 *dwc) 4660ffcaf37SFelipe Balbi { 4670ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 4680ffcaf37SFelipe Balbi return; 4690ffcaf37SFelipe Balbi 4700ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 4710ffcaf37SFelipe Balbi return; 4720ffcaf37SFelipe Balbi 4730ffcaf37SFelipe Balbi /* should never fall here */ 4740ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 4750ffcaf37SFelipe Balbi return; 4760ffcaf37SFelipe Balbi 477d64ff406SArnd Bergmann dma_unmap_single(dwc->sysdev, dwc->scratch_addr, dwc->nr_scratch * 4780ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 4790ffcaf37SFelipe Balbi kfree(dwc->scratchbuf); 4800ffcaf37SFelipe Balbi } 4810ffcaf37SFelipe Balbi 482789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc) 483789451f6SFelipe Balbi { 484789451f6SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 485789451f6SFelipe Balbi 48647d3946eSBryan O'Donoghue dwc->num_eps = DWC3_NUM_EPS(parms); 487789451f6SFelipe Balbi } 488789451f6SFelipe Balbi 48941ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc) 49026ceca97SFelipe Balbi { 49126ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 49226ceca97SFelipe Balbi 49326ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 49426ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 49526ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 49626ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 49726ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 49826ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 49926ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 50026ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 50126ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 50226ceca97SFelipe Balbi } 50326ceca97SFelipe Balbi 50498112041SRoger Quadros static int dwc3_core_ulpi_init(struct dwc3 *dwc) 50598112041SRoger Quadros { 50698112041SRoger Quadros int intf; 50798112041SRoger Quadros int ret = 0; 50898112041SRoger Quadros 50998112041SRoger Quadros intf = DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3); 51098112041SRoger Quadros 51198112041SRoger Quadros if (intf == DWC3_GHWPARAMS3_HSPHY_IFC_ULPI || 51298112041SRoger Quadros (intf == DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI && 51398112041SRoger Quadros dwc->hsphy_interface && 51498112041SRoger Quadros !strncmp(dwc->hsphy_interface, "ulpi", 4))) 51598112041SRoger Quadros ret = dwc3_ulpi_init(dwc); 51698112041SRoger Quadros 51798112041SRoger Quadros return ret; 51898112041SRoger Quadros } 51998112041SRoger Quadros 52072246da4SFelipe Balbi /** 521b5a65c40SHuang Rui * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core 522b5a65c40SHuang Rui * @dwc: Pointer to our controller context structure 52388bc9d19SHeikki Krogerus * 52488bc9d19SHeikki Krogerus * Returns 0 on success. The USB PHY interfaces are configured but not 52588bc9d19SHeikki Krogerus * initialized. The PHY interfaces and the PHYs get initialized together with 52688bc9d19SHeikki Krogerus * the core in dwc3_core_init. 527b5a65c40SHuang Rui */ 52888bc9d19SHeikki Krogerus static int dwc3_phy_setup(struct dwc3 *dwc) 529b5a65c40SHuang Rui { 530b5a65c40SHuang Rui u32 reg; 531b5a65c40SHuang Rui 532b5a65c40SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 533b5a65c40SHuang Rui 5342164a476SHuang Rui /* 5351966b865SFelipe Balbi * Make sure UX_EXIT_PX is cleared as that causes issues with some 5361966b865SFelipe Balbi * PHYs. Also, this bit is not supposed to be used in normal operation. 5371966b865SFelipe Balbi */ 5381966b865SFelipe Balbi reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX; 5391966b865SFelipe Balbi 5401966b865SFelipe Balbi /* 5412164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY 5422164a476SHuang Rui * to '0' during coreConsultant configuration. So default value 5432164a476SHuang Rui * will be '0' when the core is reset. Application needs to set it 5442164a476SHuang Rui * to '1' after the core initialization is completed. 5452164a476SHuang Rui */ 5462164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 5472164a476SHuang Rui reg |= DWC3_GUSB3PIPECTL_SUSPHY; 5482164a476SHuang Rui 549b5a65c40SHuang Rui if (dwc->u2ss_inp3_quirk) 550b5a65c40SHuang Rui reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; 551b5a65c40SHuang Rui 552e58dd357SRajesh Bhagat if (dwc->dis_rxdet_inp3_quirk) 553e58dd357SRajesh Bhagat reg |= DWC3_GUSB3PIPECTL_DISRXDETINP3; 554e58dd357SRajesh Bhagat 555df31f5b3SHuang Rui if (dwc->req_p1p2p3_quirk) 556df31f5b3SHuang Rui reg |= DWC3_GUSB3PIPECTL_REQP1P2P3; 557df31f5b3SHuang Rui 558a2a1d0f5SHuang Rui if (dwc->del_p1p2p3_quirk) 559a2a1d0f5SHuang Rui reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN; 560a2a1d0f5SHuang Rui 56141c06ffdSHuang Rui if (dwc->del_phy_power_chg_quirk) 56241c06ffdSHuang Rui reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE; 56341c06ffdSHuang Rui 564fb67afcaSHuang Rui if (dwc->lfps_filter_quirk) 565fb67afcaSHuang Rui reg |= DWC3_GUSB3PIPECTL_LFPSFILT; 566fb67afcaSHuang Rui 56714f4ac53SHuang Rui if (dwc->rx_detect_poll_quirk) 56814f4ac53SHuang Rui reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL; 56914f4ac53SHuang Rui 5706b6a0c9aSHuang Rui if (dwc->tx_de_emphasis_quirk) 5716b6a0c9aSHuang Rui reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); 5726b6a0c9aSHuang Rui 573cd72f890SFelipe Balbi if (dwc->dis_u3_susphy_quirk) 57459acfa20SHuang Rui reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 57559acfa20SHuang Rui 57600fe081dSWilliam Wu if (dwc->dis_del_phy_power_chg_quirk) 57700fe081dSWilliam Wu reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE; 57800fe081dSWilliam Wu 579b5a65c40SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 580b5a65c40SHuang Rui 5812164a476SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 5822164a476SHuang Rui 5833e10a2ceSHeikki Krogerus /* Select the HS PHY interface */ 5843e10a2ceSHeikki Krogerus switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) { 5853e10a2ceSHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI: 58643cacb03SFelipe Balbi if (dwc->hsphy_interface && 58743cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "utmi", 4)) { 5883e10a2ceSHeikki Krogerus reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI; 58988bc9d19SHeikki Krogerus break; 59043cacb03SFelipe Balbi } else if (dwc->hsphy_interface && 59143cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "ulpi", 4)) { 5923e10a2ceSHeikki Krogerus reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI; 59388bc9d19SHeikki Krogerus dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 5943e10a2ceSHeikki Krogerus } else { 59588bc9d19SHeikki Krogerus /* Relying on default value. */ 59688bc9d19SHeikki Krogerus if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) 5973e10a2ceSHeikki Krogerus break; 5983e10a2ceSHeikki Krogerus } 5993e10a2ceSHeikki Krogerus /* FALLTHROUGH */ 60088bc9d19SHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: 60188bc9d19SHeikki Krogerus /* FALLTHROUGH */ 6023e10a2ceSHeikki Krogerus default: 6033e10a2ceSHeikki Krogerus break; 6043e10a2ceSHeikki Krogerus } 6053e10a2ceSHeikki Krogerus 60632f2ed86SWilliam Wu switch (dwc->hsphy_mode) { 60732f2ed86SWilliam Wu case USBPHY_INTERFACE_MODE_UTMI: 60832f2ed86SWilliam Wu reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | 60932f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); 61032f2ed86SWilliam Wu reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) | 61132f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT); 61232f2ed86SWilliam Wu break; 61332f2ed86SWilliam Wu case USBPHY_INTERFACE_MODE_UTMIW: 61432f2ed86SWilliam Wu reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | 61532f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); 61632f2ed86SWilliam Wu reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) | 61732f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT); 61832f2ed86SWilliam Wu break; 61932f2ed86SWilliam Wu default: 62032f2ed86SWilliam Wu break; 62132f2ed86SWilliam Wu } 62232f2ed86SWilliam Wu 6232164a476SHuang Rui /* 6242164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to 6252164a476SHuang Rui * '0' during coreConsultant configuration. So default value will 6262164a476SHuang Rui * be '0' when the core is reset. Application needs to set it to 6272164a476SHuang Rui * '1' after the core initialization is completed. 6282164a476SHuang Rui */ 6292164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 6302164a476SHuang Rui reg |= DWC3_GUSB2PHYCFG_SUSPHY; 6312164a476SHuang Rui 632cd72f890SFelipe Balbi if (dwc->dis_u2_susphy_quirk) 6330effe0a3SHuang Rui reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 6340effe0a3SHuang Rui 635ec791d14SJohn Youn if (dwc->dis_enblslpm_quirk) 636ec791d14SJohn Youn reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; 637ec791d14SJohn Youn 63816199f33SWilliam Wu if (dwc->dis_u2_freeclk_exists_quirk) 63916199f33SWilliam Wu reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS; 64016199f33SWilliam Wu 6412164a476SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 64288bc9d19SHeikki Krogerus 64388bc9d19SHeikki Krogerus return 0; 644b5a65c40SHuang Rui } 645b5a65c40SHuang Rui 646c499ff71SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 647c499ff71SFelipe Balbi { 648c499ff71SFelipe Balbi dwc3_event_buffers_cleanup(dwc); 649c499ff71SFelipe Balbi 650c499ff71SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 651c499ff71SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 652c499ff71SFelipe Balbi phy_exit(dwc->usb2_generic_phy); 653c499ff71SFelipe Balbi phy_exit(dwc->usb3_generic_phy); 654c499ff71SFelipe Balbi 655c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 1); 656c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 1); 657c499ff71SFelipe Balbi phy_power_off(dwc->usb2_generic_phy); 658c499ff71SFelipe Balbi phy_power_off(dwc->usb3_generic_phy); 659c499ff71SFelipe Balbi } 660c499ff71SFelipe Balbi 6610759956fSFelipe Balbi static bool dwc3_core_is_valid(struct dwc3 *dwc) 66272246da4SFelipe Balbi { 66372246da4SFelipe Balbi u32 reg; 66472246da4SFelipe Balbi 6657650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 6660759956fSFelipe Balbi 6677650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 668690fb371SJohn Youn if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) { 669690fb371SJohn Youn /* Detected DWC_usb3 IP */ 670690fb371SJohn Youn dwc->revision = reg; 671690fb371SJohn Youn } else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) { 672690fb371SJohn Youn /* Detected DWC_usb31 IP */ 673690fb371SJohn Youn dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); 674690fb371SJohn Youn dwc->revision |= DWC3_REVISION_IS_DWC31; 675690fb371SJohn Youn } else { 6760759956fSFelipe Balbi return false; 6777650bd74SSebastian Andrzej Siewior } 6787650bd74SSebastian Andrzej Siewior 6790759956fSFelipe Balbi return true; 6800e1e5c47SPaul Zimmerman } 6810e1e5c47SPaul Zimmerman 682941f918eSFelipe Balbi static void dwc3_core_setup_global_control(struct dwc3 *dwc) 68372246da4SFelipe Balbi { 68472246da4SFelipe Balbi u32 hwparams4 = dwc->hwparams.hwparams4; 68572246da4SFelipe Balbi u32 reg; 686c499ff71SFelipe Balbi 6874878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 6883e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 6894878a028SSebastian Andrzej Siewior 690164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 6914878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 69232a4a135SFelipe Balbi /** 69332a4a135SFelipe Balbi * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an 69432a4a135SFelipe Balbi * issue which would cause xHCI compliance tests to fail. 69532a4a135SFelipe Balbi * 69632a4a135SFelipe Balbi * Because of that we cannot enable clock gating on such 69732a4a135SFelipe Balbi * configurations. 69832a4a135SFelipe Balbi * 69932a4a135SFelipe Balbi * Refers to: 70032a4a135SFelipe Balbi * 70132a4a135SFelipe Balbi * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based 70232a4a135SFelipe Balbi * SOF/ITP Mode Used 70332a4a135SFelipe Balbi */ 70432a4a135SFelipe Balbi if ((dwc->dr_mode == USB_DR_MODE_HOST || 70532a4a135SFelipe Balbi dwc->dr_mode == USB_DR_MODE_OTG) && 70632a4a135SFelipe Balbi (dwc->revision >= DWC3_REVISION_210A && 70732a4a135SFelipe Balbi dwc->revision <= DWC3_REVISION_250A)) 70832a4a135SFelipe Balbi reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; 70932a4a135SFelipe Balbi else 7104878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 7114878a028SSebastian Andrzej Siewior break; 7120ffcaf37SFelipe Balbi case DWC3_GHWPARAMS1_EN_PWROPT_HIB: 7130ffcaf37SFelipe Balbi /* enable hibernation here */ 7140ffcaf37SFelipe Balbi dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); 7152eac3992SHuang Rui 7162eac3992SHuang Rui /* 7172eac3992SHuang Rui * REVISIT Enabling this bit so that host-mode hibernation 7182eac3992SHuang Rui * will work. Device-mode hibernation is not yet implemented. 7192eac3992SHuang Rui */ 7202eac3992SHuang Rui reg |= DWC3_GCTL_GBLHIBERNATIONEN; 7210ffcaf37SFelipe Balbi break; 7224878a028SSebastian Andrzej Siewior default: 7235eb30cedSFelipe Balbi /* nothing */ 7245eb30cedSFelipe Balbi break; 7254878a028SSebastian Andrzej Siewior } 7264878a028SSebastian Andrzej Siewior 727946bd579SHuang Rui /* check if current dwc3 is on simulation board */ 728946bd579SHuang Rui if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { 7295eb30cedSFelipe Balbi dev_info(dwc->dev, "Running with FPGA optmizations\n"); 730946bd579SHuang Rui dwc->is_fpga = true; 731946bd579SHuang Rui } 732946bd579SHuang Rui 7333b81221aSHuang Rui WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga, 7343b81221aSHuang Rui "disable_scramble cannot be used on non-FPGA builds\n"); 7353b81221aSHuang Rui 7363b81221aSHuang Rui if (dwc->disable_scramble_quirk && dwc->is_fpga) 7373b81221aSHuang Rui reg |= DWC3_GCTL_DISSCRAMBLE; 7383b81221aSHuang Rui else 7393b81221aSHuang Rui reg &= ~DWC3_GCTL_DISSCRAMBLE; 7403b81221aSHuang Rui 7419a5b2f31SHuang Rui if (dwc->u2exit_lfps_quirk) 7429a5b2f31SHuang Rui reg |= DWC3_GCTL_U2EXIT_LFPS; 7439a5b2f31SHuang Rui 7444878a028SSebastian Andrzej Siewior /* 7454878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 7461d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 7474878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 7481d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 7494878a028SSebastian Andrzej Siewior */ 7504878a028SSebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 7514878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 7524878a028SSebastian Andrzej Siewior 7534878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 754941f918eSFelipe Balbi } 7554878a028SSebastian Andrzej Siewior 756f54edb53SFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc); 75798112041SRoger Quadros static int dwc3_core_ulpi_init(struct dwc3 *dwc); 758f54edb53SFelipe Balbi 759941f918eSFelipe Balbi /** 760941f918eSFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 761941f918eSFelipe Balbi * @dwc: Pointer to our controller context structure 762941f918eSFelipe Balbi * 763941f918eSFelipe Balbi * Returns 0 on success otherwise negative errno. 764941f918eSFelipe Balbi */ 765941f918eSFelipe Balbi static int dwc3_core_init(struct dwc3 *dwc) 766941f918eSFelipe Balbi { 767941f918eSFelipe Balbi u32 reg; 768941f918eSFelipe Balbi int ret; 769941f918eSFelipe Balbi 770941f918eSFelipe Balbi if (!dwc3_core_is_valid(dwc)) { 771941f918eSFelipe Balbi dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 772941f918eSFelipe Balbi ret = -ENODEV; 773941f918eSFelipe Balbi goto err0; 774941f918eSFelipe Balbi } 775941f918eSFelipe Balbi 776941f918eSFelipe Balbi /* 777941f918eSFelipe Balbi * Write Linux Version Code to our GUID register so it's easy to figure 778941f918eSFelipe Balbi * out which kernel version a bug was found. 779941f918eSFelipe Balbi */ 780941f918eSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); 781941f918eSFelipe Balbi 782941f918eSFelipe Balbi /* Handle USB2.0-only core configuration */ 783941f918eSFelipe Balbi if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 784941f918eSFelipe Balbi DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { 785941f918eSFelipe Balbi if (dwc->maximum_speed == USB_SPEED_SUPER) 786941f918eSFelipe Balbi dwc->maximum_speed = USB_SPEED_HIGH; 787941f918eSFelipe Balbi } 788941f918eSFelipe Balbi 789941f918eSFelipe Balbi ret = dwc3_phy_setup(dwc); 790941f918eSFelipe Balbi if (ret) 791941f918eSFelipe Balbi goto err0; 792941f918eSFelipe Balbi 79398112041SRoger Quadros if (!dwc->ulpi_ready) { 79498112041SRoger Quadros ret = dwc3_core_ulpi_init(dwc); 79598112041SRoger Quadros if (ret) 79698112041SRoger Quadros goto err0; 79798112041SRoger Quadros dwc->ulpi_ready = true; 79898112041SRoger Quadros } 79998112041SRoger Quadros 80098112041SRoger Quadros if (!dwc->phys_ready) { 80198112041SRoger Quadros ret = dwc3_core_get_phy(dwc); 80298112041SRoger Quadros if (ret) 80398112041SRoger Quadros goto err0a; 80498112041SRoger Quadros dwc->phys_ready = true; 80598112041SRoger Quadros } 80698112041SRoger Quadros 80798112041SRoger Quadros ret = dwc3_core_soft_reset(dwc); 80898112041SRoger Quadros if (ret) 80998112041SRoger Quadros goto err0a; 81098112041SRoger Quadros 811941f918eSFelipe Balbi dwc3_core_setup_global_control(dwc); 812c499ff71SFelipe Balbi dwc3_core_num_eps(dwc); 8130ffcaf37SFelipe Balbi 8140ffcaf37SFelipe Balbi ret = dwc3_setup_scratch_buffers(dwc); 8150ffcaf37SFelipe Balbi if (ret) 816c499ff71SFelipe Balbi goto err1; 817c499ff71SFelipe Balbi 818c499ff71SFelipe Balbi /* Adjust Frame Length */ 819c499ff71SFelipe Balbi dwc3_frame_length_adjustment(dwc); 820c499ff71SFelipe Balbi 821c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 0); 822c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 0); 823c499ff71SFelipe Balbi ret = phy_power_on(dwc->usb2_generic_phy); 824c499ff71SFelipe Balbi if (ret < 0) 8250ffcaf37SFelipe Balbi goto err2; 8260ffcaf37SFelipe Balbi 827c499ff71SFelipe Balbi ret = phy_power_on(dwc->usb3_generic_phy); 828c499ff71SFelipe Balbi if (ret < 0) 829c499ff71SFelipe Balbi goto err3; 830c499ff71SFelipe Balbi 831c499ff71SFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 832c499ff71SFelipe Balbi if (ret) { 833c499ff71SFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 834c499ff71SFelipe Balbi goto err4; 835c499ff71SFelipe Balbi } 836c499ff71SFelipe Balbi 83706281d46SJohn Youn /* 83806281d46SJohn Youn * ENDXFER polling is available on version 3.10a and later of 83906281d46SJohn Youn * the DWC_usb3 controller. It is NOT available in the 84006281d46SJohn Youn * DWC_usb31 controller. 84106281d46SJohn Youn */ 84206281d46SJohn Youn if (!dwc3_is_usb31(dwc) && dwc->revision >= DWC3_REVISION_310A) { 84306281d46SJohn Youn reg = dwc3_readl(dwc->regs, DWC3_GUCTL2); 84406281d46SJohn Youn reg |= DWC3_GUCTL2_RST_ACTBITLATER; 84506281d46SJohn Youn dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); 84606281d46SJohn Youn } 84706281d46SJohn Youn 84865db7a0cSWilliam Wu if (dwc->revision >= DWC3_REVISION_250A) { 8490bb39ca1SJohn Youn reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); 85065db7a0cSWilliam Wu 85165db7a0cSWilliam Wu /* 85265db7a0cSWilliam Wu * Enable hardware control of sending remote wakeup 85365db7a0cSWilliam Wu * in HS when the device is in the L1 state. 85465db7a0cSWilliam Wu */ 85565db7a0cSWilliam Wu if (dwc->revision >= DWC3_REVISION_290A) 8560bb39ca1SJohn Youn reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW; 85765db7a0cSWilliam Wu 85865db7a0cSWilliam Wu if (dwc->dis_tx_ipgap_linecheck_quirk) 85965db7a0cSWilliam Wu reg |= DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS; 86065db7a0cSWilliam Wu 8610bb39ca1SJohn Youn dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); 8620bb39ca1SJohn Youn } 8630bb39ca1SJohn Youn 86472246da4SFelipe Balbi return 0; 86572246da4SFelipe Balbi 866c499ff71SFelipe Balbi err4: 8679b9d7cddSVivek Gautam phy_power_off(dwc->usb3_generic_phy); 868c499ff71SFelipe Balbi 869c499ff71SFelipe Balbi err3: 8709b9d7cddSVivek Gautam phy_power_off(dwc->usb2_generic_phy); 871c499ff71SFelipe Balbi 8720ffcaf37SFelipe Balbi err2: 873c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 1); 874c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 1); 8750ffcaf37SFelipe Balbi 8760ffcaf37SFelipe Balbi err1: 8770ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 8780ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 87957303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 88057303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 8810ffcaf37SFelipe Balbi 88298112041SRoger Quadros err0a: 88398112041SRoger Quadros dwc3_ulpi_exit(dwc); 88498112041SRoger Quadros 88572246da4SFelipe Balbi err0: 88672246da4SFelipe Balbi return ret; 88772246da4SFelipe Balbi } 88872246da4SFelipe Balbi 8893c9f94acSFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc) 89072246da4SFelipe Balbi { 8913c9f94acSFelipe Balbi struct device *dev = dwc->dev; 892941ea361SFelipe Balbi struct device_node *node = dev->of_node; 8933c9f94acSFelipe Balbi int ret; 89472246da4SFelipe Balbi 8955088b6f5SKishon Vijay Abraham I if (node) { 8965088b6f5SKishon Vijay Abraham I dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); 8975088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); 898bb674907SFelipe Balbi } else { 899bb674907SFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 900bb674907SFelipe Balbi dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 9015088b6f5SKishon Vijay Abraham I } 9025088b6f5SKishon Vijay Abraham I 903d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb2_phy)) { 904d105e7f8SFelipe Balbi ret = PTR_ERR(dwc->usb2_phy); 905122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 906122f06e6SKishon Vijay Abraham I dwc->usb2_phy = NULL; 907122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 908d105e7f8SFelipe Balbi return ret; 909122f06e6SKishon Vijay Abraham I } else { 91051e1e7bcSFelipe Balbi dev_err(dev, "no usb2 phy configured\n"); 911122f06e6SKishon Vijay Abraham I return ret; 912122f06e6SKishon Vijay Abraham I } 91351e1e7bcSFelipe Balbi } 91451e1e7bcSFelipe Balbi 915d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb3_phy)) { 916315955d7SRuchika Kharwar ret = PTR_ERR(dwc->usb3_phy); 917122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 918122f06e6SKishon Vijay Abraham I dwc->usb3_phy = NULL; 919122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 920d105e7f8SFelipe Balbi return ret; 921122f06e6SKishon Vijay Abraham I } else { 92251e1e7bcSFelipe Balbi dev_err(dev, "no usb3 phy configured\n"); 923122f06e6SKishon Vijay Abraham I return ret; 924122f06e6SKishon Vijay Abraham I } 92551e1e7bcSFelipe Balbi } 92651e1e7bcSFelipe Balbi 92757303488SKishon Vijay Abraham I dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); 92857303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb2_generic_phy)) { 92957303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb2_generic_phy); 93057303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 93157303488SKishon Vijay Abraham I dwc->usb2_generic_phy = NULL; 93257303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 93357303488SKishon Vijay Abraham I return ret; 93457303488SKishon Vijay Abraham I } else { 93557303488SKishon Vijay Abraham I dev_err(dev, "no usb2 phy configured\n"); 93657303488SKishon Vijay Abraham I return ret; 93757303488SKishon Vijay Abraham I } 93857303488SKishon Vijay Abraham I } 93957303488SKishon Vijay Abraham I 94057303488SKishon Vijay Abraham I dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy"); 94157303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb3_generic_phy)) { 94257303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb3_generic_phy); 94357303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 94457303488SKishon Vijay Abraham I dwc->usb3_generic_phy = NULL; 94557303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 94657303488SKishon Vijay Abraham I return ret; 94757303488SKishon Vijay Abraham I } else { 94857303488SKishon Vijay Abraham I dev_err(dev, "no usb3 phy configured\n"); 94957303488SKishon Vijay Abraham I return ret; 95057303488SKishon Vijay Abraham I } 95157303488SKishon Vijay Abraham I } 95257303488SKishon Vijay Abraham I 9533c9f94acSFelipe Balbi return 0; 9543c9f94acSFelipe Balbi } 9553c9f94acSFelipe Balbi 9565f94adfeSFelipe Balbi static int dwc3_core_init_mode(struct dwc3 *dwc) 9575f94adfeSFelipe Balbi { 9585f94adfeSFelipe Balbi struct device *dev = dwc->dev; 9595f94adfeSFelipe Balbi int ret; 9605f94adfeSFelipe Balbi 9615f94adfeSFelipe Balbi switch (dwc->dr_mode) { 9625f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 96341ce1456SRoger Quadros dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); 964958d1a4cSFelipe Balbi 965958d1a4cSFelipe Balbi if (dwc->usb2_phy) 966958d1a4cSFelipe Balbi otg_set_vbus(dwc->usb2_phy->otg, false); 967958d1a4cSFelipe Balbi phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_DEVICE); 968644cbbc3SManu Gautam phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_DEVICE); 969958d1a4cSFelipe Balbi 9705f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 9715f94adfeSFelipe Balbi if (ret) { 9729522def4SRoger Quadros if (ret != -EPROBE_DEFER) 9735f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 9745f94adfeSFelipe Balbi return ret; 9755f94adfeSFelipe Balbi } 9765f94adfeSFelipe Balbi break; 9775f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 97841ce1456SRoger Quadros dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST); 979958d1a4cSFelipe Balbi 980958d1a4cSFelipe Balbi if (dwc->usb2_phy) 981958d1a4cSFelipe Balbi otg_set_vbus(dwc->usb2_phy->otg, true); 982958d1a4cSFelipe Balbi phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST); 983644cbbc3SManu Gautam phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST); 984958d1a4cSFelipe Balbi 9855f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 9865f94adfeSFelipe Balbi if (ret) { 9879522def4SRoger Quadros if (ret != -EPROBE_DEFER) 9885f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 9895f94adfeSFelipe Balbi return ret; 9905f94adfeSFelipe Balbi } 991d8c80bb3SVivek Gautam phy_calibrate(dwc->usb2_generic_phy); 9925f94adfeSFelipe Balbi break; 9935f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 99441ce1456SRoger Quadros INIT_WORK(&dwc->drd_work, __dwc3_set_mode); 9959840354fSRoger Quadros ret = dwc3_drd_init(dwc); 9969840354fSRoger Quadros if (ret) { 9979840354fSRoger Quadros if (ret != -EPROBE_DEFER) 9989840354fSRoger Quadros dev_err(dev, "failed to initialize dual-role\n"); 9999840354fSRoger Quadros return ret; 10009840354fSRoger Quadros } 10015f94adfeSFelipe Balbi break; 10025f94adfeSFelipe Balbi default: 10035f94adfeSFelipe Balbi dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); 10045f94adfeSFelipe Balbi return -EINVAL; 10055f94adfeSFelipe Balbi } 10065f94adfeSFelipe Balbi 10075f94adfeSFelipe Balbi return 0; 10085f94adfeSFelipe Balbi } 10095f94adfeSFelipe Balbi 10105f94adfeSFelipe Balbi static void dwc3_core_exit_mode(struct dwc3 *dwc) 10115f94adfeSFelipe Balbi { 10125f94adfeSFelipe Balbi switch (dwc->dr_mode) { 10135f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 10145f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 10155f94adfeSFelipe Balbi break; 10165f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 10175f94adfeSFelipe Balbi dwc3_host_exit(dwc); 10185f94adfeSFelipe Balbi break; 10195f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 10209840354fSRoger Quadros dwc3_drd_exit(dwc); 10215f94adfeSFelipe Balbi break; 10225f94adfeSFelipe Balbi default: 10235f94adfeSFelipe Balbi /* do nothing */ 10245f94adfeSFelipe Balbi break; 10255f94adfeSFelipe Balbi } 10265f94adfeSFelipe Balbi } 10275f94adfeSFelipe Balbi 1028c5ac6116SFelipe Balbi static void dwc3_get_properties(struct dwc3 *dwc) 10293c9f94acSFelipe Balbi { 1030c5ac6116SFelipe Balbi struct device *dev = dwc->dev; 103180caf7d2SHuang Rui u8 lpm_nyet_threshold; 10326b6a0c9aSHuang Rui u8 tx_de_emphasis; 1033460d098cSHuang Rui u8 hird_threshold; 10343c9f94acSFelipe Balbi 103580caf7d2SHuang Rui /* default to highest possible threshold */ 103680caf7d2SHuang Rui lpm_nyet_threshold = 0xff; 103780caf7d2SHuang Rui 10386b6a0c9aSHuang Rui /* default to -3.5dB de-emphasis */ 10396b6a0c9aSHuang Rui tx_de_emphasis = 1; 10406b6a0c9aSHuang Rui 1041460d098cSHuang Rui /* 1042460d098cSHuang Rui * default to assert utmi_sleep_n and use maximum allowed HIRD 1043460d098cSHuang Rui * threshold value of 0b1100 1044460d098cSHuang Rui */ 1045460d098cSHuang Rui hird_threshold = 12; 1046460d098cSHuang Rui 104763863b98SHeikki Krogerus dwc->maximum_speed = usb_get_maximum_speed(dev); 104806e7114fSHeikki Krogerus dwc->dr_mode = usb_get_dr_mode(dev); 104932f2ed86SWilliam Wu dwc->hsphy_mode = of_usb_get_phy_mode(dev->of_node); 105063863b98SHeikki Krogerus 1051d64ff406SArnd Bergmann dwc->sysdev_is_parent = device_property_read_bool(dev, 1052d64ff406SArnd Bergmann "linux,sysdev_is_parent"); 1053d64ff406SArnd Bergmann if (dwc->sysdev_is_parent) 1054d64ff406SArnd Bergmann dwc->sysdev = dwc->dev->parent; 1055d64ff406SArnd Bergmann else 1056d64ff406SArnd Bergmann dwc->sysdev = dwc->dev; 1057d64ff406SArnd Bergmann 10583d128919SHeikki Krogerus dwc->has_lpm_erratum = device_property_read_bool(dev, 105980caf7d2SHuang Rui "snps,has-lpm-erratum"); 10603d128919SHeikki Krogerus device_property_read_u8(dev, "snps,lpm-nyet-threshold", 106180caf7d2SHuang Rui &lpm_nyet_threshold); 10623d128919SHeikki Krogerus dwc->is_utmi_l1_suspend = device_property_read_bool(dev, 1063460d098cSHuang Rui "snps,is-utmi-l1-suspend"); 10643d128919SHeikki Krogerus device_property_read_u8(dev, "snps,hird-threshold", 1065460d098cSHuang Rui &hird_threshold); 10663d128919SHeikki Krogerus dwc->usb3_lpm_capable = device_property_read_bool(dev, 1067eac68e8fSRobert Baldyga "snps,usb3_lpm_capable"); 10683c9f94acSFelipe Balbi 10693d128919SHeikki Krogerus dwc->disable_scramble_quirk = device_property_read_bool(dev, 10703b81221aSHuang Rui "snps,disable_scramble_quirk"); 10713d128919SHeikki Krogerus dwc->u2exit_lfps_quirk = device_property_read_bool(dev, 10729a5b2f31SHuang Rui "snps,u2exit_lfps_quirk"); 10733d128919SHeikki Krogerus dwc->u2ss_inp3_quirk = device_property_read_bool(dev, 1074b5a65c40SHuang Rui "snps,u2ss_inp3_quirk"); 10753d128919SHeikki Krogerus dwc->req_p1p2p3_quirk = device_property_read_bool(dev, 1076df31f5b3SHuang Rui "snps,req_p1p2p3_quirk"); 10773d128919SHeikki Krogerus dwc->del_p1p2p3_quirk = device_property_read_bool(dev, 1078a2a1d0f5SHuang Rui "snps,del_p1p2p3_quirk"); 10793d128919SHeikki Krogerus dwc->del_phy_power_chg_quirk = device_property_read_bool(dev, 108041c06ffdSHuang Rui "snps,del_phy_power_chg_quirk"); 10813d128919SHeikki Krogerus dwc->lfps_filter_quirk = device_property_read_bool(dev, 1082fb67afcaSHuang Rui "snps,lfps_filter_quirk"); 10833d128919SHeikki Krogerus dwc->rx_detect_poll_quirk = device_property_read_bool(dev, 108414f4ac53SHuang Rui "snps,rx_detect_poll_quirk"); 10853d128919SHeikki Krogerus dwc->dis_u3_susphy_quirk = device_property_read_bool(dev, 108659acfa20SHuang Rui "snps,dis_u3_susphy_quirk"); 10873d128919SHeikki Krogerus dwc->dis_u2_susphy_quirk = device_property_read_bool(dev, 10880effe0a3SHuang Rui "snps,dis_u2_susphy_quirk"); 1089ec791d14SJohn Youn dwc->dis_enblslpm_quirk = device_property_read_bool(dev, 1090ec791d14SJohn Youn "snps,dis_enblslpm_quirk"); 1091e58dd357SRajesh Bhagat dwc->dis_rxdet_inp3_quirk = device_property_read_bool(dev, 1092e58dd357SRajesh Bhagat "snps,dis_rxdet_inp3_quirk"); 109316199f33SWilliam Wu dwc->dis_u2_freeclk_exists_quirk = device_property_read_bool(dev, 109416199f33SWilliam Wu "snps,dis-u2-freeclk-exists-quirk"); 109500fe081dSWilliam Wu dwc->dis_del_phy_power_chg_quirk = device_property_read_bool(dev, 109600fe081dSWilliam Wu "snps,dis-del-phy-power-chg-quirk"); 109765db7a0cSWilliam Wu dwc->dis_tx_ipgap_linecheck_quirk = device_property_read_bool(dev, 109865db7a0cSWilliam Wu "snps,dis-tx-ipgap-linecheck-quirk"); 10996b6a0c9aSHuang Rui 11003d128919SHeikki Krogerus dwc->tx_de_emphasis_quirk = device_property_read_bool(dev, 11016b6a0c9aSHuang Rui "snps,tx_de_emphasis_quirk"); 11023d128919SHeikki Krogerus device_property_read_u8(dev, "snps,tx_de_emphasis", 11036b6a0c9aSHuang Rui &tx_de_emphasis); 11043d128919SHeikki Krogerus device_property_read_string(dev, "snps,hsphy_interface", 11053e10a2ceSHeikki Krogerus &dwc->hsphy_interface); 11063d128919SHeikki Krogerus device_property_read_u32(dev, "snps,quirk-frame-length-adjustment", 1107bcdb3272SFelipe Balbi &dwc->fladj); 11083d128919SHeikki Krogerus 110942bf02ecSRoger Quadros dwc->dis_metastability_quirk = device_property_read_bool(dev, 111042bf02ecSRoger Quadros "snps,dis_metastability_quirk"); 111142bf02ecSRoger Quadros 111280caf7d2SHuang Rui dwc->lpm_nyet_threshold = lpm_nyet_threshold; 11136b6a0c9aSHuang Rui dwc->tx_de_emphasis = tx_de_emphasis; 111480caf7d2SHuang Rui 1115460d098cSHuang Rui dwc->hird_threshold = hird_threshold 1116460d098cSHuang Rui | (dwc->is_utmi_l1_suspend << 4); 1117460d098cSHuang Rui 1118cf40b86bSJohn Youn dwc->imod_interval = 0; 1119cf40b86bSJohn Youn } 1120cf40b86bSJohn Youn 1121cf40b86bSJohn Youn /* check whether the core supports IMOD */ 1122cf40b86bSJohn Youn bool dwc3_has_imod(struct dwc3 *dwc) 1123cf40b86bSJohn Youn { 1124cf40b86bSJohn Youn return ((dwc3_is_usb3(dwc) && 1125cf40b86bSJohn Youn dwc->revision >= DWC3_REVISION_300A) || 1126cf40b86bSJohn Youn (dwc3_is_usb31(dwc) && 1127cf40b86bSJohn Youn dwc->revision >= DWC3_USB31_REVISION_120A)); 1128c5ac6116SFelipe Balbi } 1129c5ac6116SFelipe Balbi 11307ac51a12SJohn Youn static void dwc3_check_params(struct dwc3 *dwc) 11317ac51a12SJohn Youn { 11327ac51a12SJohn Youn struct device *dev = dwc->dev; 11337ac51a12SJohn Youn 1134cf40b86bSJohn Youn /* Check for proper value of imod_interval */ 1135cf40b86bSJohn Youn if (dwc->imod_interval && !dwc3_has_imod(dwc)) { 1136cf40b86bSJohn Youn dev_warn(dwc->dev, "Interrupt moderation not supported\n"); 1137cf40b86bSJohn Youn dwc->imod_interval = 0; 1138cf40b86bSJohn Youn } 1139cf40b86bSJohn Youn 114028632b44SJohn Youn /* 114128632b44SJohn Youn * Workaround for STAR 9000961433 which affects only version 114228632b44SJohn Youn * 3.00a of the DWC_usb3 core. This prevents the controller 114328632b44SJohn Youn * interrupt from being masked while handling events. IMOD 114428632b44SJohn Youn * allows us to work around this issue. Enable it for the 114528632b44SJohn Youn * affected version. 114628632b44SJohn Youn */ 114728632b44SJohn Youn if (!dwc->imod_interval && 114828632b44SJohn Youn (dwc->revision == DWC3_REVISION_300A)) 114928632b44SJohn Youn dwc->imod_interval = 1; 115028632b44SJohn Youn 11517ac51a12SJohn Youn /* Check the maximum_speed parameter */ 11527ac51a12SJohn Youn switch (dwc->maximum_speed) { 11537ac51a12SJohn Youn case USB_SPEED_LOW: 11547ac51a12SJohn Youn case USB_SPEED_FULL: 11557ac51a12SJohn Youn case USB_SPEED_HIGH: 11567ac51a12SJohn Youn case USB_SPEED_SUPER: 11577ac51a12SJohn Youn case USB_SPEED_SUPER_PLUS: 11587ac51a12SJohn Youn break; 11597ac51a12SJohn Youn default: 11607ac51a12SJohn Youn dev_err(dev, "invalid maximum_speed parameter %d\n", 11617ac51a12SJohn Youn dwc->maximum_speed); 11627ac51a12SJohn Youn /* fall through */ 11637ac51a12SJohn Youn case USB_SPEED_UNKNOWN: 11647ac51a12SJohn Youn /* default to superspeed */ 11657ac51a12SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER; 11667ac51a12SJohn Youn 11677ac51a12SJohn Youn /* 11687ac51a12SJohn Youn * default to superspeed plus if we are capable. 11697ac51a12SJohn Youn */ 11707ac51a12SJohn Youn if (dwc3_is_usb31(dwc) && 11717ac51a12SJohn Youn (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 11727ac51a12SJohn Youn DWC3_GHWPARAMS3_SSPHY_IFC_GEN2)) 11737ac51a12SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER_PLUS; 11747ac51a12SJohn Youn 11757ac51a12SJohn Youn break; 11767ac51a12SJohn Youn } 11777ac51a12SJohn Youn } 11787ac51a12SJohn Youn 1179c5ac6116SFelipe Balbi static int dwc3_probe(struct platform_device *pdev) 1180c5ac6116SFelipe Balbi { 1181c5ac6116SFelipe Balbi struct device *dev = &pdev->dev; 1182c5ac6116SFelipe Balbi struct resource *res; 1183c5ac6116SFelipe Balbi struct dwc3 *dwc; 1184c5ac6116SFelipe Balbi 1185c5ac6116SFelipe Balbi int ret; 1186c5ac6116SFelipe Balbi 1187c5ac6116SFelipe Balbi void __iomem *regs; 1188c5ac6116SFelipe Balbi 1189c5ac6116SFelipe Balbi dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL); 1190c5ac6116SFelipe Balbi if (!dwc) 1191c5ac6116SFelipe Balbi return -ENOMEM; 1192c5ac6116SFelipe Balbi 1193c5ac6116SFelipe Balbi dwc->dev = dev; 1194c5ac6116SFelipe Balbi 1195c5ac6116SFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1196c5ac6116SFelipe Balbi if (!res) { 1197c5ac6116SFelipe Balbi dev_err(dev, "missing memory resource\n"); 1198c5ac6116SFelipe Balbi return -ENODEV; 1199c5ac6116SFelipe Balbi } 1200c5ac6116SFelipe Balbi 1201c5ac6116SFelipe Balbi dwc->xhci_resources[0].start = res->start; 1202c5ac6116SFelipe Balbi dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 1203c5ac6116SFelipe Balbi DWC3_XHCI_REGS_END; 1204c5ac6116SFelipe Balbi dwc->xhci_resources[0].flags = res->flags; 1205c5ac6116SFelipe Balbi dwc->xhci_resources[0].name = res->name; 1206c5ac6116SFelipe Balbi 1207c5ac6116SFelipe Balbi res->start += DWC3_GLOBALS_REGS_START; 1208c5ac6116SFelipe Balbi 1209c5ac6116SFelipe Balbi /* 1210c5ac6116SFelipe Balbi * Request memory region but exclude xHCI regs, 1211c5ac6116SFelipe Balbi * since it will be requested by the xhci-plat driver. 1212c5ac6116SFelipe Balbi */ 1213c5ac6116SFelipe Balbi regs = devm_ioremap_resource(dev, res); 1214c5ac6116SFelipe Balbi if (IS_ERR(regs)) { 1215c5ac6116SFelipe Balbi ret = PTR_ERR(regs); 1216c5ac6116SFelipe Balbi goto err0; 1217c5ac6116SFelipe Balbi } 1218c5ac6116SFelipe Balbi 1219c5ac6116SFelipe Balbi dwc->regs = regs; 1220c5ac6116SFelipe Balbi dwc->regs_size = resource_size(res); 1221c5ac6116SFelipe Balbi 1222c5ac6116SFelipe Balbi dwc3_get_properties(dwc); 1223c5ac6116SFelipe Balbi 12246c89cce0SHeikki Krogerus platform_set_drvdata(pdev, dwc); 12252917e718SHeikki Krogerus dwc3_cache_hwparams(dwc); 12266c89cce0SHeikki Krogerus 122772246da4SFelipe Balbi spin_lock_init(&dwc->lock); 122872246da4SFelipe Balbi 1229fc8bb91bSFelipe Balbi pm_runtime_set_active(dev); 1230fc8bb91bSFelipe Balbi pm_runtime_use_autosuspend(dev); 1231fc8bb91bSFelipe Balbi pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY); 1232802ca850SChanho Park pm_runtime_enable(dev); 123332808237SRoger Quadros ret = pm_runtime_get_sync(dev); 123432808237SRoger Quadros if (ret < 0) 123532808237SRoger Quadros goto err1; 123632808237SRoger Quadros 1237802ca850SChanho Park pm_runtime_forbid(dev); 123872246da4SFelipe Balbi 12393921426bSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 12403921426bSFelipe Balbi if (ret) { 12413921426bSFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 12423921426bSFelipe Balbi ret = -ENOMEM; 124332808237SRoger Quadros goto err2; 12443921426bSFelipe Balbi } 12453921426bSFelipe Balbi 12469d6173e1SThinh Nguyen ret = dwc3_get_dr_mode(dwc); 12479d6173e1SThinh Nguyen if (ret) 12489d6173e1SThinh Nguyen goto err3; 124932a4a135SFelipe Balbi 1250c499ff71SFelipe Balbi ret = dwc3_alloc_scratch_buffers(dwc); 1251c499ff71SFelipe Balbi if (ret) 125232808237SRoger Quadros goto err3; 1253c499ff71SFelipe Balbi 125472246da4SFelipe Balbi ret = dwc3_core_init(dwc); 125572246da4SFelipe Balbi if (ret) { 1256802ca850SChanho Park dev_err(dev, "failed to initialize core\n"); 125732808237SRoger Quadros goto err4; 125872246da4SFelipe Balbi } 125972246da4SFelipe Balbi 12607ac51a12SJohn Youn dwc3_check_params(dwc); 12612c7f1bd9SJohn Youn 12625f94adfeSFelipe Balbi ret = dwc3_core_init_mode(dwc); 12635f94adfeSFelipe Balbi if (ret) 126432808237SRoger Quadros goto err5; 126572246da4SFelipe Balbi 12664e9f3118SDu, Changbin dwc3_debugfs_init(dwc); 1267fc8bb91bSFelipe Balbi pm_runtime_put(dev); 126872246da4SFelipe Balbi 126972246da4SFelipe Balbi return 0; 127072246da4SFelipe Balbi 127132808237SRoger Quadros err5: 1272f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 1273f122d33eSFelipe Balbi 127432808237SRoger Quadros err4: 1275c499ff71SFelipe Balbi dwc3_free_scratch_buffers(dwc); 127672246da4SFelipe Balbi 127732808237SRoger Quadros err3: 12783921426bSFelipe Balbi dwc3_free_event_buffers(dwc); 12793921426bSFelipe Balbi 128032808237SRoger Quadros err2: 128132808237SRoger Quadros pm_runtime_allow(&pdev->dev); 128232808237SRoger Quadros 128332808237SRoger Quadros err1: 128432808237SRoger Quadros pm_runtime_put_sync(&pdev->dev); 128532808237SRoger Quadros pm_runtime_disable(&pdev->dev); 128632808237SRoger Quadros 12873da1f6eeSFelipe Balbi err0: 12883da1f6eeSFelipe Balbi /* 12893da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 12903da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 12913da1f6eeSFelipe Balbi * memory region the next time probe is called. 12923da1f6eeSFelipe Balbi */ 12933da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 12943da1f6eeSFelipe Balbi 129572246da4SFelipe Balbi return ret; 129672246da4SFelipe Balbi } 129772246da4SFelipe Balbi 1298fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev) 129972246da4SFelipe Balbi { 130072246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 13013da1f6eeSFelipe Balbi struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 13023da1f6eeSFelipe Balbi 1303fc8bb91bSFelipe Balbi pm_runtime_get_sync(&pdev->dev); 13043da1f6eeSFelipe Balbi /* 13053da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 13063da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 13073da1f6eeSFelipe Balbi * memory region the next time probe is called. 13083da1f6eeSFelipe Balbi */ 13093da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 131072246da4SFelipe Balbi 1311dc99f16fSFelipe Balbi dwc3_debugfs_exit(dwc); 1312dc99f16fSFelipe Balbi dwc3_core_exit_mode(dwc); 13138ba007a9SKishon Vijay Abraham I 131472246da4SFelipe Balbi dwc3_core_exit(dwc); 131588bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 131672246da4SFelipe Balbi 1317fc8bb91bSFelipe Balbi pm_runtime_put_sync(&pdev->dev); 1318fc8bb91bSFelipe Balbi pm_runtime_allow(&pdev->dev); 1319fc8bb91bSFelipe Balbi pm_runtime_disable(&pdev->dev); 1320fc8bb91bSFelipe Balbi 1321c499ff71SFelipe Balbi dwc3_free_event_buffers(dwc); 1322c499ff71SFelipe Balbi dwc3_free_scratch_buffers(dwc); 1323c499ff71SFelipe Balbi 132472246da4SFelipe Balbi return 0; 132572246da4SFelipe Balbi } 132672246da4SFelipe Balbi 1327fc8bb91bSFelipe Balbi #ifdef CONFIG_PM 1328c4a5153eSManu Gautam static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) 13297415f17cSFelipe Balbi { 1330fc8bb91bSFelipe Balbi unsigned long flags; 13317415f17cSFelipe Balbi 1332689bf72cSManu Gautam switch (dwc->current_dr_role) { 1333689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_DEVICE: 1334fc8bb91bSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 13357415f17cSFelipe Balbi dwc3_gadget_suspend(dwc); 1336fc8bb91bSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 1337689bf72cSManu Gautam dwc3_core_exit(dwc); 133851f5d49aSFelipe Balbi break; 1339689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_HOST: 1340c4a5153eSManu Gautam /* do nothing during host runtime_suspend */ 1341c4a5153eSManu Gautam if (!PMSG_IS_AUTO(msg)) 1342c4a5153eSManu Gautam dwc3_core_exit(dwc); 1343c4a5153eSManu Gautam break; 1344f09cc79bSRoger Quadros case DWC3_GCTL_PRTCAP_OTG: 1345f09cc79bSRoger Quadros /* do nothing during runtime_suspend */ 1346f09cc79bSRoger Quadros if (PMSG_IS_AUTO(msg)) 1347f09cc79bSRoger Quadros break; 1348f09cc79bSRoger Quadros 1349f09cc79bSRoger Quadros if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) { 1350f09cc79bSRoger Quadros spin_lock_irqsave(&dwc->lock, flags); 1351f09cc79bSRoger Quadros dwc3_gadget_suspend(dwc); 1352f09cc79bSRoger Quadros spin_unlock_irqrestore(&dwc->lock, flags); 1353f09cc79bSRoger Quadros } 1354f09cc79bSRoger Quadros 1355f09cc79bSRoger Quadros dwc3_otg_exit(dwc); 1356f09cc79bSRoger Quadros dwc3_core_exit(dwc); 1357f09cc79bSRoger Quadros break; 13587415f17cSFelipe Balbi default: 135951f5d49aSFelipe Balbi /* do nothing */ 13607415f17cSFelipe Balbi break; 13617415f17cSFelipe Balbi } 13627415f17cSFelipe Balbi 1363fc8bb91bSFelipe Balbi return 0; 1364fc8bb91bSFelipe Balbi } 1365fc8bb91bSFelipe Balbi 1366c4a5153eSManu Gautam static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) 1367fc8bb91bSFelipe Balbi { 1368fc8bb91bSFelipe Balbi unsigned long flags; 1369fc8bb91bSFelipe Balbi int ret; 1370fc8bb91bSFelipe Balbi 1371689bf72cSManu Gautam switch (dwc->current_dr_role) { 1372689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_DEVICE: 1373fc8bb91bSFelipe Balbi ret = dwc3_core_init(dwc); 1374fc8bb91bSFelipe Balbi if (ret) 1375fc8bb91bSFelipe Balbi return ret; 1376fc8bb91bSFelipe Balbi 1377fc8bb91bSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 1378fc8bb91bSFelipe Balbi dwc3_gadget_resume(dwc); 1379fc8bb91bSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 1380689bf72cSManu Gautam break; 1381689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_HOST: 1382c4a5153eSManu Gautam /* nothing to do on host runtime_resume */ 1383c4a5153eSManu Gautam if (!PMSG_IS_AUTO(msg)) { 1384c4a5153eSManu Gautam ret = dwc3_core_init(dwc); 1385c4a5153eSManu Gautam if (ret) 1386c4a5153eSManu Gautam return ret; 1387c4a5153eSManu Gautam } 1388c4a5153eSManu Gautam break; 1389f09cc79bSRoger Quadros case DWC3_GCTL_PRTCAP_OTG: 1390f09cc79bSRoger Quadros /* nothing to do on runtime_resume */ 1391f09cc79bSRoger Quadros if (PMSG_IS_AUTO(msg)) 1392f09cc79bSRoger Quadros break; 1393f09cc79bSRoger Quadros 1394f09cc79bSRoger Quadros ret = dwc3_core_init(dwc); 1395f09cc79bSRoger Quadros if (ret) 1396f09cc79bSRoger Quadros return ret; 1397f09cc79bSRoger Quadros 1398f09cc79bSRoger Quadros dwc3_set_prtcap(dwc, dwc->current_dr_role); 1399f09cc79bSRoger Quadros 1400f09cc79bSRoger Quadros dwc3_otg_init(dwc); 1401f09cc79bSRoger Quadros if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST) { 1402f09cc79bSRoger Quadros dwc3_otg_host_init(dwc); 1403f09cc79bSRoger Quadros } else if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) { 1404f09cc79bSRoger Quadros spin_lock_irqsave(&dwc->lock, flags); 1405f09cc79bSRoger Quadros dwc3_gadget_resume(dwc); 1406f09cc79bSRoger Quadros spin_unlock_irqrestore(&dwc->lock, flags); 1407f09cc79bSRoger Quadros } 1408f09cc79bSRoger Quadros 1409f09cc79bSRoger Quadros break; 1410fc8bb91bSFelipe Balbi default: 1411fc8bb91bSFelipe Balbi /* do nothing */ 1412fc8bb91bSFelipe Balbi break; 1413fc8bb91bSFelipe Balbi } 1414fc8bb91bSFelipe Balbi 1415fc8bb91bSFelipe Balbi return 0; 1416fc8bb91bSFelipe Balbi } 1417fc8bb91bSFelipe Balbi 1418fc8bb91bSFelipe Balbi static int dwc3_runtime_checks(struct dwc3 *dwc) 1419fc8bb91bSFelipe Balbi { 1420689bf72cSManu Gautam switch (dwc->current_dr_role) { 1421c4a5153eSManu Gautam case DWC3_GCTL_PRTCAP_DEVICE: 1422fc8bb91bSFelipe Balbi if (dwc->connected) 1423fc8bb91bSFelipe Balbi return -EBUSY; 1424fc8bb91bSFelipe Balbi break; 1425c4a5153eSManu Gautam case DWC3_GCTL_PRTCAP_HOST: 1426fc8bb91bSFelipe Balbi default: 1427fc8bb91bSFelipe Balbi /* do nothing */ 1428fc8bb91bSFelipe Balbi break; 1429fc8bb91bSFelipe Balbi } 1430fc8bb91bSFelipe Balbi 1431fc8bb91bSFelipe Balbi return 0; 1432fc8bb91bSFelipe Balbi } 1433fc8bb91bSFelipe Balbi 1434fc8bb91bSFelipe Balbi static int dwc3_runtime_suspend(struct device *dev) 1435fc8bb91bSFelipe Balbi { 1436fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1437fc8bb91bSFelipe Balbi int ret; 1438fc8bb91bSFelipe Balbi 1439fc8bb91bSFelipe Balbi if (dwc3_runtime_checks(dwc)) 1440fc8bb91bSFelipe Balbi return -EBUSY; 1441fc8bb91bSFelipe Balbi 1442c4a5153eSManu Gautam ret = dwc3_suspend_common(dwc, PMSG_AUTO_SUSPEND); 1443fc8bb91bSFelipe Balbi if (ret) 1444fc8bb91bSFelipe Balbi return ret; 1445fc8bb91bSFelipe Balbi 1446fc8bb91bSFelipe Balbi device_init_wakeup(dev, true); 1447fc8bb91bSFelipe Balbi 1448fc8bb91bSFelipe Balbi return 0; 1449fc8bb91bSFelipe Balbi } 1450fc8bb91bSFelipe Balbi 1451fc8bb91bSFelipe Balbi static int dwc3_runtime_resume(struct device *dev) 1452fc8bb91bSFelipe Balbi { 1453fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1454fc8bb91bSFelipe Balbi int ret; 1455fc8bb91bSFelipe Balbi 1456fc8bb91bSFelipe Balbi device_init_wakeup(dev, false); 1457fc8bb91bSFelipe Balbi 1458c4a5153eSManu Gautam ret = dwc3_resume_common(dwc, PMSG_AUTO_RESUME); 1459fc8bb91bSFelipe Balbi if (ret) 1460fc8bb91bSFelipe Balbi return ret; 1461fc8bb91bSFelipe Balbi 1462689bf72cSManu Gautam switch (dwc->current_dr_role) { 1463689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_DEVICE: 1464fc8bb91bSFelipe Balbi dwc3_gadget_process_pending_events(dwc); 1465fc8bb91bSFelipe Balbi break; 1466689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_HOST: 1467fc8bb91bSFelipe Balbi default: 1468fc8bb91bSFelipe Balbi /* do nothing */ 1469fc8bb91bSFelipe Balbi break; 1470fc8bb91bSFelipe Balbi } 1471fc8bb91bSFelipe Balbi 1472fc8bb91bSFelipe Balbi pm_runtime_mark_last_busy(dev); 1473fc8bb91bSFelipe Balbi 1474fc8bb91bSFelipe Balbi return 0; 1475fc8bb91bSFelipe Balbi } 1476fc8bb91bSFelipe Balbi 1477fc8bb91bSFelipe Balbi static int dwc3_runtime_idle(struct device *dev) 1478fc8bb91bSFelipe Balbi { 1479fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1480fc8bb91bSFelipe Balbi 1481689bf72cSManu Gautam switch (dwc->current_dr_role) { 1482689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_DEVICE: 1483fc8bb91bSFelipe Balbi if (dwc3_runtime_checks(dwc)) 1484fc8bb91bSFelipe Balbi return -EBUSY; 1485fc8bb91bSFelipe Balbi break; 1486689bf72cSManu Gautam case DWC3_GCTL_PRTCAP_HOST: 1487fc8bb91bSFelipe Balbi default: 1488fc8bb91bSFelipe Balbi /* do nothing */ 1489fc8bb91bSFelipe Balbi break; 1490fc8bb91bSFelipe Balbi } 1491fc8bb91bSFelipe Balbi 1492fc8bb91bSFelipe Balbi pm_runtime_mark_last_busy(dev); 1493fc8bb91bSFelipe Balbi pm_runtime_autosuspend(dev); 1494fc8bb91bSFelipe Balbi 1495fc8bb91bSFelipe Balbi return 0; 1496fc8bb91bSFelipe Balbi } 1497fc8bb91bSFelipe Balbi #endif /* CONFIG_PM */ 1498fc8bb91bSFelipe Balbi 1499fc8bb91bSFelipe Balbi #ifdef CONFIG_PM_SLEEP 1500fc8bb91bSFelipe Balbi static int dwc3_suspend(struct device *dev) 1501fc8bb91bSFelipe Balbi { 1502fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1503fc8bb91bSFelipe Balbi int ret; 1504fc8bb91bSFelipe Balbi 1505c4a5153eSManu Gautam ret = dwc3_suspend_common(dwc, PMSG_SUSPEND); 1506fc8bb91bSFelipe Balbi if (ret) 1507fc8bb91bSFelipe Balbi return ret; 1508fc8bb91bSFelipe Balbi 15096344475fSSekhar Nori pinctrl_pm_select_sleep_state(dev); 15106344475fSSekhar Nori 15117415f17cSFelipe Balbi return 0; 15127415f17cSFelipe Balbi } 15137415f17cSFelipe Balbi 15147415f17cSFelipe Balbi static int dwc3_resume(struct device *dev) 15157415f17cSFelipe Balbi { 15167415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 151757303488SKishon Vijay Abraham I int ret; 15187415f17cSFelipe Balbi 15196344475fSSekhar Nori pinctrl_pm_select_default_state(dev); 15206344475fSSekhar Nori 1521c4a5153eSManu Gautam ret = dwc3_resume_common(dwc, PMSG_RESUME); 152251f5d49aSFelipe Balbi if (ret) 15235c4ad318SFelipe Balbi return ret; 15245c4ad318SFelipe Balbi 15257415f17cSFelipe Balbi pm_runtime_disable(dev); 15267415f17cSFelipe Balbi pm_runtime_set_active(dev); 15277415f17cSFelipe Balbi pm_runtime_enable(dev); 15287415f17cSFelipe Balbi 15297415f17cSFelipe Balbi return 0; 15307415f17cSFelipe Balbi } 15317f370ed0SFelipe Balbi #endif /* CONFIG_PM_SLEEP */ 15327415f17cSFelipe Balbi 15337415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = { 15347415f17cSFelipe Balbi SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 1535fc8bb91bSFelipe Balbi SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume, 1536fc8bb91bSFelipe Balbi dwc3_runtime_idle) 15377415f17cSFelipe Balbi }; 15387415f17cSFelipe Balbi 15395088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF 15405088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = { 15415088b6f5SKishon Vijay Abraham I { 154222a5aa17SFelipe Balbi .compatible = "snps,dwc3" 154322a5aa17SFelipe Balbi }, 154422a5aa17SFelipe Balbi { 15455088b6f5SKishon Vijay Abraham I .compatible = "synopsys,dwc3" 15465088b6f5SKishon Vijay Abraham I }, 15475088b6f5SKishon Vijay Abraham I { }, 15485088b6f5SKishon Vijay Abraham I }; 15495088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match); 15505088b6f5SKishon Vijay Abraham I #endif 15515088b6f5SKishon Vijay Abraham I 1552404905a6SHeikki Krogerus #ifdef CONFIG_ACPI 1553404905a6SHeikki Krogerus 1554404905a6SHeikki Krogerus #define ACPI_ID_INTEL_BSW "808622B7" 1555404905a6SHeikki Krogerus 1556404905a6SHeikki Krogerus static const struct acpi_device_id dwc3_acpi_match[] = { 1557404905a6SHeikki Krogerus { ACPI_ID_INTEL_BSW, 0 }, 1558404905a6SHeikki Krogerus { }, 1559404905a6SHeikki Krogerus }; 1560404905a6SHeikki Krogerus MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match); 1561404905a6SHeikki Krogerus #endif 1562404905a6SHeikki Krogerus 156372246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 156472246da4SFelipe Balbi .probe = dwc3_probe, 15657690417dSBill Pemberton .remove = dwc3_remove, 156672246da4SFelipe Balbi .driver = { 156772246da4SFelipe Balbi .name = "dwc3", 15685088b6f5SKishon Vijay Abraham I .of_match_table = of_match_ptr(of_dwc3_match), 1569404905a6SHeikki Krogerus .acpi_match_table = ACPI_PTR(dwc3_acpi_match), 15707f370ed0SFelipe Balbi .pm = &dwc3_dev_pm_ops, 157172246da4SFelipe Balbi }, 157272246da4SFelipe Balbi }; 157372246da4SFelipe Balbi 1574b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 1575b1116dccSTobias Klauser 15767ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 157772246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 15785945f789SFelipe Balbi MODULE_LICENSE("GPL v2"); 157972246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 1580