172246da4SFelipe Balbi /** 272246da4SFelipe Balbi * core.c - DesignWare USB3 DRD Controller Core file 372246da4SFelipe Balbi * 472246da4SFelipe Balbi * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com 572246da4SFelipe Balbi * 672246da4SFelipe Balbi * Authors: Felipe Balbi <balbi@ti.com>, 772246da4SFelipe Balbi * Sebastian Andrzej Siewior <bigeasy@linutronix.de> 872246da4SFelipe Balbi * 95945f789SFelipe Balbi * This program is free software: you can redistribute it and/or modify 105945f789SFelipe Balbi * it under the terms of the GNU General Public License version 2 of 115945f789SFelipe Balbi * the License as published by the Free Software Foundation. 1272246da4SFelipe Balbi * 135945f789SFelipe Balbi * This program is distributed in the hope that it will be useful, 145945f789SFelipe Balbi * but WITHOUT ANY WARRANTY; without even the implied warranty of 155945f789SFelipe Balbi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 165945f789SFelipe Balbi * GNU General Public License for more details. 1772246da4SFelipe Balbi * 185945f789SFelipe Balbi * You should have received a copy of the GNU General Public License 195945f789SFelipe Balbi * along with this program. If not, see <http://www.gnu.org/licenses/>. 2072246da4SFelipe Balbi */ 2172246da4SFelipe Balbi 22fa0ea13eSFelipe Balbi #include <linux/version.h> 23a72e658bSFelipe Balbi #include <linux/module.h> 2472246da4SFelipe Balbi #include <linux/kernel.h> 2572246da4SFelipe Balbi #include <linux/slab.h> 2672246da4SFelipe Balbi #include <linux/spinlock.h> 2772246da4SFelipe Balbi #include <linux/platform_device.h> 2872246da4SFelipe Balbi #include <linux/pm_runtime.h> 2972246da4SFelipe Balbi #include <linux/interrupt.h> 3072246da4SFelipe Balbi #include <linux/ioport.h> 3172246da4SFelipe Balbi #include <linux/io.h> 3272246da4SFelipe Balbi #include <linux/list.h> 3372246da4SFelipe Balbi #include <linux/delay.h> 3472246da4SFelipe Balbi #include <linux/dma-mapping.h> 35457e84b6SFelipe Balbi #include <linux/of.h> 36404905a6SHeikki Krogerus #include <linux/acpi.h> 376344475fSSekhar Nori #include <linux/pinctrl/consumer.h> 3872246da4SFelipe Balbi 3972246da4SFelipe Balbi #include <linux/usb/ch9.h> 4072246da4SFelipe Balbi #include <linux/usb/gadget.h> 41f7e846f0SFelipe Balbi #include <linux/usb/of.h> 42a45c82b8SRuchika Kharwar #include <linux/usb/otg.h> 4372246da4SFelipe Balbi 4472246da4SFelipe Balbi #include "core.h" 4572246da4SFelipe Balbi #include "gadget.h" 4672246da4SFelipe Balbi #include "io.h" 4772246da4SFelipe Balbi 4872246da4SFelipe Balbi #include "debug.h" 4972246da4SFelipe Balbi 50fc8bb91bSFelipe Balbi #define DWC3_DEFAULT_AUTOSUSPEND_DELAY 5000 /* ms */ 518300dd23SFelipe Balbi 529d6173e1SThinh Nguyen /** 539d6173e1SThinh Nguyen * dwc3_get_dr_mode - Validates and sets dr_mode 549d6173e1SThinh Nguyen * @dwc: pointer to our context structure 559d6173e1SThinh Nguyen */ 569d6173e1SThinh Nguyen static int dwc3_get_dr_mode(struct dwc3 *dwc) 579d6173e1SThinh Nguyen { 589d6173e1SThinh Nguyen enum usb_dr_mode mode; 599d6173e1SThinh Nguyen struct device *dev = dwc->dev; 609d6173e1SThinh Nguyen unsigned int hw_mode; 619d6173e1SThinh Nguyen 629d6173e1SThinh Nguyen if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) 639d6173e1SThinh Nguyen dwc->dr_mode = USB_DR_MODE_OTG; 649d6173e1SThinh Nguyen 659d6173e1SThinh Nguyen mode = dwc->dr_mode; 669d6173e1SThinh Nguyen hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0); 679d6173e1SThinh Nguyen 689d6173e1SThinh Nguyen switch (hw_mode) { 699d6173e1SThinh Nguyen case DWC3_GHWPARAMS0_MODE_GADGET: 709d6173e1SThinh Nguyen if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) { 719d6173e1SThinh Nguyen dev_err(dev, 729d6173e1SThinh Nguyen "Controller does not support host mode.\n"); 739d6173e1SThinh Nguyen return -EINVAL; 749d6173e1SThinh Nguyen } 759d6173e1SThinh Nguyen mode = USB_DR_MODE_PERIPHERAL; 769d6173e1SThinh Nguyen break; 779d6173e1SThinh Nguyen case DWC3_GHWPARAMS0_MODE_HOST: 789d6173e1SThinh Nguyen if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) { 799d6173e1SThinh Nguyen dev_err(dev, 809d6173e1SThinh Nguyen "Controller does not support device mode.\n"); 819d6173e1SThinh Nguyen return -EINVAL; 829d6173e1SThinh Nguyen } 839d6173e1SThinh Nguyen mode = USB_DR_MODE_HOST; 849d6173e1SThinh Nguyen break; 859d6173e1SThinh Nguyen default: 869d6173e1SThinh Nguyen if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) 879d6173e1SThinh Nguyen mode = USB_DR_MODE_HOST; 889d6173e1SThinh Nguyen else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) 899d6173e1SThinh Nguyen mode = USB_DR_MODE_PERIPHERAL; 909d6173e1SThinh Nguyen } 919d6173e1SThinh Nguyen 929d6173e1SThinh Nguyen if (mode != dwc->dr_mode) { 939d6173e1SThinh Nguyen dev_warn(dev, 949d6173e1SThinh Nguyen "Configuration mismatch. dr_mode forced to %s\n", 959d6173e1SThinh Nguyen mode == USB_DR_MODE_HOST ? "host" : "gadget"); 969d6173e1SThinh Nguyen 979d6173e1SThinh Nguyen dwc->dr_mode = mode; 989d6173e1SThinh Nguyen } 999d6173e1SThinh Nguyen 1009d6173e1SThinh Nguyen return 0; 1019d6173e1SThinh Nguyen } 1029d6173e1SThinh Nguyen 1033140e8cbSSebastian Andrzej Siewior void dwc3_set_mode(struct dwc3 *dwc, u32 mode) 1043140e8cbSSebastian Andrzej Siewior { 1053140e8cbSSebastian Andrzej Siewior u32 reg; 1063140e8cbSSebastian Andrzej Siewior 1073140e8cbSSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 1083140e8cbSSebastian Andrzej Siewior reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); 1093140e8cbSSebastian Andrzej Siewior reg |= DWC3_GCTL_PRTCAPDIR(mode); 1103140e8cbSSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 1113140e8cbSSebastian Andrzej Siewior } 1128300dd23SFelipe Balbi 113cf6d867dSFelipe Balbi u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type) 114cf6d867dSFelipe Balbi { 115cf6d867dSFelipe Balbi struct dwc3 *dwc = dep->dwc; 116cf6d867dSFelipe Balbi u32 reg; 117cf6d867dSFelipe Balbi 118cf6d867dSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GDBGFIFOSPACE, 119cf6d867dSFelipe Balbi DWC3_GDBGFIFOSPACE_NUM(dep->number) | 120cf6d867dSFelipe Balbi DWC3_GDBGFIFOSPACE_TYPE(type)); 121cf6d867dSFelipe Balbi 122cf6d867dSFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GDBGFIFOSPACE); 123cf6d867dSFelipe Balbi 124cf6d867dSFelipe Balbi return DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(reg); 125cf6d867dSFelipe Balbi } 126cf6d867dSFelipe Balbi 12772246da4SFelipe Balbi /** 12872246da4SFelipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 12972246da4SFelipe Balbi * @dwc: pointer to our context structure 13072246da4SFelipe Balbi */ 13157303488SKishon Vijay Abraham I static int dwc3_core_soft_reset(struct dwc3 *dwc) 13272246da4SFelipe Balbi { 13372246da4SFelipe Balbi u32 reg; 134f59dcab1SFelipe Balbi int retries = 1000; 13557303488SKishon Vijay Abraham I int ret; 13672246da4SFelipe Balbi 13751e1e7bcSFelipe Balbi usb_phy_init(dwc->usb2_phy); 13851e1e7bcSFelipe Balbi usb_phy_init(dwc->usb3_phy); 13957303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 14057303488SKishon Vijay Abraham I if (ret < 0) 14157303488SKishon Vijay Abraham I return ret; 14257303488SKishon Vijay Abraham I 14357303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 14457303488SKishon Vijay Abraham I if (ret < 0) { 14557303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 14657303488SKishon Vijay Abraham I return ret; 14757303488SKishon Vijay Abraham I } 14872246da4SFelipe Balbi 149f59dcab1SFelipe Balbi /* 150f59dcab1SFelipe Balbi * We're resetting only the device side because, if we're in host mode, 151f59dcab1SFelipe Balbi * XHCI driver will reset the host block. If dwc3 was configured for 152f59dcab1SFelipe Balbi * host-only mode, then we can return early. 153f59dcab1SFelipe Balbi */ 154f59dcab1SFelipe Balbi if (dwc->dr_mode == USB_DR_MODE_HOST) 15557303488SKishon Vijay Abraham I return 0; 156f59dcab1SFelipe Balbi 157f59dcab1SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 158f59dcab1SFelipe Balbi reg |= DWC3_DCTL_CSFTRST; 159f59dcab1SFelipe Balbi dwc3_writel(dwc->regs, DWC3_DCTL, reg); 160f59dcab1SFelipe Balbi 161f59dcab1SFelipe Balbi do { 162f59dcab1SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 163f59dcab1SFelipe Balbi if (!(reg & DWC3_DCTL_CSFTRST)) 164f59dcab1SFelipe Balbi return 0; 165f59dcab1SFelipe Balbi 166f59dcab1SFelipe Balbi udelay(1); 167f59dcab1SFelipe Balbi } while (--retries); 168f59dcab1SFelipe Balbi 169f59dcab1SFelipe Balbi return -ETIMEDOUT; 17072246da4SFelipe Balbi } 17172246da4SFelipe Balbi 17272246da4SFelipe Balbi /** 173c5cc74e8SHeikki Krogerus * dwc3_soft_reset - Issue soft reset 174c5cc74e8SHeikki Krogerus * @dwc: Pointer to our controller context structure 175c5cc74e8SHeikki Krogerus */ 176c5cc74e8SHeikki Krogerus static int dwc3_soft_reset(struct dwc3 *dwc) 177c5cc74e8SHeikki Krogerus { 178c5cc74e8SHeikki Krogerus unsigned long timeout; 179c5cc74e8SHeikki Krogerus u32 reg; 180c5cc74e8SHeikki Krogerus 181c5cc74e8SHeikki Krogerus timeout = jiffies + msecs_to_jiffies(500); 182c5cc74e8SHeikki Krogerus dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); 183c5cc74e8SHeikki Krogerus do { 184c5cc74e8SHeikki Krogerus reg = dwc3_readl(dwc->regs, DWC3_DCTL); 185c5cc74e8SHeikki Krogerus if (!(reg & DWC3_DCTL_CSFTRST)) 186c5cc74e8SHeikki Krogerus break; 187c5cc74e8SHeikki Krogerus 188c5cc74e8SHeikki Krogerus if (time_after(jiffies, timeout)) { 189c5cc74e8SHeikki Krogerus dev_err(dwc->dev, "Reset Timed Out\n"); 190c5cc74e8SHeikki Krogerus return -ETIMEDOUT; 191c5cc74e8SHeikki Krogerus } 192c5cc74e8SHeikki Krogerus 193c5cc74e8SHeikki Krogerus cpu_relax(); 194c5cc74e8SHeikki Krogerus } while (true); 195c5cc74e8SHeikki Krogerus 196c5cc74e8SHeikki Krogerus return 0; 197c5cc74e8SHeikki Krogerus } 198c5cc74e8SHeikki Krogerus 199db2be4e9SNikhil Badola /* 200db2be4e9SNikhil Badola * dwc3_frame_length_adjustment - Adjusts frame length if required 201db2be4e9SNikhil Badola * @dwc3: Pointer to our controller context structure 202db2be4e9SNikhil Badola */ 203bcdb3272SFelipe Balbi static void dwc3_frame_length_adjustment(struct dwc3 *dwc) 204db2be4e9SNikhil Badola { 205db2be4e9SNikhil Badola u32 reg; 206db2be4e9SNikhil Badola u32 dft; 207db2be4e9SNikhil Badola 208db2be4e9SNikhil Badola if (dwc->revision < DWC3_REVISION_250A) 209db2be4e9SNikhil Badola return; 210db2be4e9SNikhil Badola 211bcdb3272SFelipe Balbi if (dwc->fladj == 0) 212db2be4e9SNikhil Badola return; 213db2be4e9SNikhil Badola 214db2be4e9SNikhil Badola reg = dwc3_readl(dwc->regs, DWC3_GFLADJ); 215db2be4e9SNikhil Badola dft = reg & DWC3_GFLADJ_30MHZ_MASK; 216bcdb3272SFelipe Balbi if (!dev_WARN_ONCE(dwc->dev, dft == dwc->fladj, 217db2be4e9SNikhil Badola "request value same as default, ignoring\n")) { 218db2be4e9SNikhil Badola reg &= ~DWC3_GFLADJ_30MHZ_MASK; 219bcdb3272SFelipe Balbi reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj; 220db2be4e9SNikhil Badola dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); 221db2be4e9SNikhil Badola } 222db2be4e9SNikhil Badola } 223db2be4e9SNikhil Badola 224c5cc74e8SHeikki Krogerus /** 22572246da4SFelipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 22672246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 22772246da4SFelipe Balbi * @evt: Pointer to event buffer to be freed 22872246da4SFelipe Balbi */ 22972246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc, 23072246da4SFelipe Balbi struct dwc3_event_buffer *evt) 23172246da4SFelipe Balbi { 23272246da4SFelipe Balbi dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); 23372246da4SFelipe Balbi } 23472246da4SFelipe Balbi 23572246da4SFelipe Balbi /** 2361d046793SPaul Zimmerman * dwc3_alloc_one_event_buffer - Allocates one event buffer structure 23772246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 23872246da4SFelipe Balbi * @length: size of the event buffer 23972246da4SFelipe Balbi * 2401d046793SPaul Zimmerman * Returns a pointer to the allocated event buffer structure on success 24172246da4SFelipe Balbi * otherwise ERR_PTR(errno). 24272246da4SFelipe Balbi */ 24367d0b500SFelipe Balbi static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, 24467d0b500SFelipe Balbi unsigned length) 24572246da4SFelipe Balbi { 24672246da4SFelipe Balbi struct dwc3_event_buffer *evt; 24772246da4SFelipe Balbi 248380f0d28SFelipe Balbi evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL); 24972246da4SFelipe Balbi if (!evt) 25072246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 25172246da4SFelipe Balbi 25272246da4SFelipe Balbi evt->dwc = dwc; 25372246da4SFelipe Balbi evt->length = length; 25472246da4SFelipe Balbi evt->buf = dma_alloc_coherent(dwc->dev, length, 25572246da4SFelipe Balbi &evt->dma, GFP_KERNEL); 256e32672f0SFelipe Balbi if (!evt->buf) 25772246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 25872246da4SFelipe Balbi 25972246da4SFelipe Balbi return evt; 26072246da4SFelipe Balbi } 26172246da4SFelipe Balbi 26272246da4SFelipe Balbi /** 26372246da4SFelipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 26472246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 26572246da4SFelipe Balbi */ 26672246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc) 26772246da4SFelipe Balbi { 26872246da4SFelipe Balbi struct dwc3_event_buffer *evt; 26972246da4SFelipe Balbi 270696c8b12SFelipe Balbi evt = dwc->ev_buf; 27164b6c8a7SAnton Tikhomirov if (evt) 27272246da4SFelipe Balbi dwc3_free_one_event_buffer(dwc, evt); 27372246da4SFelipe Balbi } 27472246da4SFelipe Balbi 27572246da4SFelipe Balbi /** 27672246da4SFelipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 2771d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 27872246da4SFelipe Balbi * @length: size of event buffer 27972246da4SFelipe Balbi * 2801d046793SPaul Zimmerman * Returns 0 on success otherwise negative errno. In the error case, dwc 28172246da4SFelipe Balbi * may contain some buffers allocated but not all which were requested. 28272246da4SFelipe Balbi */ 28341ac7b3aSBill Pemberton static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) 28472246da4SFelipe Balbi { 28572246da4SFelipe Balbi struct dwc3_event_buffer *evt; 28672246da4SFelipe Balbi 28772246da4SFelipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 28872246da4SFelipe Balbi if (IS_ERR(evt)) { 28972246da4SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 29072246da4SFelipe Balbi return PTR_ERR(evt); 29172246da4SFelipe Balbi } 292696c8b12SFelipe Balbi dwc->ev_buf = evt; 29372246da4SFelipe Balbi 29472246da4SFelipe Balbi return 0; 29572246da4SFelipe Balbi } 29672246da4SFelipe Balbi 29772246da4SFelipe Balbi /** 29872246da4SFelipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 2991d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 30072246da4SFelipe Balbi * 30172246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 30272246da4SFelipe Balbi */ 3037acd85e0SPaul Zimmerman static int dwc3_event_buffers_setup(struct dwc3 *dwc) 30472246da4SFelipe Balbi { 30572246da4SFelipe Balbi struct dwc3_event_buffer *evt; 30672246da4SFelipe Balbi 307696c8b12SFelipe Balbi evt = dwc->ev_buf; 3087acd85e0SPaul Zimmerman evt->lpos = 0; 309660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 31072246da4SFelipe Balbi lower_32_bits(evt->dma)); 311660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 31272246da4SFelipe Balbi upper_32_bits(evt->dma)); 313660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), 31468d6a01bSFelipe Balbi DWC3_GEVNTSIZ_SIZE(evt->length)); 315660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 31672246da4SFelipe Balbi 31772246da4SFelipe Balbi return 0; 31872246da4SFelipe Balbi } 31972246da4SFelipe Balbi 32072246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 32172246da4SFelipe Balbi { 32272246da4SFelipe Balbi struct dwc3_event_buffer *evt; 32372246da4SFelipe Balbi 324696c8b12SFelipe Balbi evt = dwc->ev_buf; 3257acd85e0SPaul Zimmerman 3267acd85e0SPaul Zimmerman evt->lpos = 0; 3277acd85e0SPaul Zimmerman 328660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 0); 329660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 0); 330660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK 33168d6a01bSFelipe Balbi | DWC3_GEVNTSIZ_SIZE(0)); 332660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 33372246da4SFelipe Balbi } 33472246da4SFelipe Balbi 3350ffcaf37SFelipe Balbi static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) 3360ffcaf37SFelipe Balbi { 3370ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3380ffcaf37SFelipe Balbi return 0; 3390ffcaf37SFelipe Balbi 3400ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3410ffcaf37SFelipe Balbi return 0; 3420ffcaf37SFelipe Balbi 3430ffcaf37SFelipe Balbi dwc->scratchbuf = kmalloc_array(dwc->nr_scratch, 3440ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, GFP_KERNEL); 3450ffcaf37SFelipe Balbi if (!dwc->scratchbuf) 3460ffcaf37SFelipe Balbi return -ENOMEM; 3470ffcaf37SFelipe Balbi 3480ffcaf37SFelipe Balbi return 0; 3490ffcaf37SFelipe Balbi } 3500ffcaf37SFelipe Balbi 3510ffcaf37SFelipe Balbi static int dwc3_setup_scratch_buffers(struct dwc3 *dwc) 3520ffcaf37SFelipe Balbi { 3530ffcaf37SFelipe Balbi dma_addr_t scratch_addr; 3540ffcaf37SFelipe Balbi u32 param; 3550ffcaf37SFelipe Balbi int ret; 3560ffcaf37SFelipe Balbi 3570ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3580ffcaf37SFelipe Balbi return 0; 3590ffcaf37SFelipe Balbi 3600ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3610ffcaf37SFelipe Balbi return 0; 3620ffcaf37SFelipe Balbi 3630ffcaf37SFelipe Balbi /* should never fall here */ 3640ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 3650ffcaf37SFelipe Balbi return 0; 3660ffcaf37SFelipe Balbi 3670ffcaf37SFelipe Balbi scratch_addr = dma_map_single(dwc->dev, dwc->scratchbuf, 3680ffcaf37SFelipe Balbi dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, 3690ffcaf37SFelipe Balbi DMA_BIDIRECTIONAL); 3700ffcaf37SFelipe Balbi if (dma_mapping_error(dwc->dev, scratch_addr)) { 3710ffcaf37SFelipe Balbi dev_err(dwc->dev, "failed to map scratch buffer\n"); 3720ffcaf37SFelipe Balbi ret = -EFAULT; 3730ffcaf37SFelipe Balbi goto err0; 3740ffcaf37SFelipe Balbi } 3750ffcaf37SFelipe Balbi 3760ffcaf37SFelipe Balbi dwc->scratch_addr = scratch_addr; 3770ffcaf37SFelipe Balbi 3780ffcaf37SFelipe Balbi param = lower_32_bits(scratch_addr); 3790ffcaf37SFelipe Balbi 3800ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3810ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param); 3820ffcaf37SFelipe Balbi if (ret < 0) 3830ffcaf37SFelipe Balbi goto err1; 3840ffcaf37SFelipe Balbi 3850ffcaf37SFelipe Balbi param = upper_32_bits(scratch_addr); 3860ffcaf37SFelipe Balbi 3870ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3880ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param); 3890ffcaf37SFelipe Balbi if (ret < 0) 3900ffcaf37SFelipe Balbi goto err1; 3910ffcaf37SFelipe Balbi 3920ffcaf37SFelipe Balbi return 0; 3930ffcaf37SFelipe Balbi 3940ffcaf37SFelipe Balbi err1: 3950ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3960ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3970ffcaf37SFelipe Balbi 3980ffcaf37SFelipe Balbi err0: 3990ffcaf37SFelipe Balbi return ret; 4000ffcaf37SFelipe Balbi } 4010ffcaf37SFelipe Balbi 4020ffcaf37SFelipe Balbi static void dwc3_free_scratch_buffers(struct dwc3 *dwc) 4030ffcaf37SFelipe Balbi { 4040ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 4050ffcaf37SFelipe Balbi return; 4060ffcaf37SFelipe Balbi 4070ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 4080ffcaf37SFelipe Balbi return; 4090ffcaf37SFelipe Balbi 4100ffcaf37SFelipe Balbi /* should never fall here */ 4110ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 4120ffcaf37SFelipe Balbi return; 4130ffcaf37SFelipe Balbi 4140ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 4150ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 4160ffcaf37SFelipe Balbi kfree(dwc->scratchbuf); 4170ffcaf37SFelipe Balbi } 4180ffcaf37SFelipe Balbi 419789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc) 420789451f6SFelipe Balbi { 421789451f6SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 422789451f6SFelipe Balbi 423789451f6SFelipe Balbi dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); 424789451f6SFelipe Balbi dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; 425789451f6SFelipe Balbi } 426789451f6SFelipe Balbi 42741ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc) 42826ceca97SFelipe Balbi { 42926ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 43026ceca97SFelipe Balbi 43126ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 43226ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 43326ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 43426ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 43526ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 43626ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 43726ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 43826ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 43926ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 44026ceca97SFelipe Balbi } 44126ceca97SFelipe Balbi 44272246da4SFelipe Balbi /** 443b5a65c40SHuang Rui * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core 444b5a65c40SHuang Rui * @dwc: Pointer to our controller context structure 44588bc9d19SHeikki Krogerus * 44688bc9d19SHeikki Krogerus * Returns 0 on success. The USB PHY interfaces are configured but not 44788bc9d19SHeikki Krogerus * initialized. The PHY interfaces and the PHYs get initialized together with 44888bc9d19SHeikki Krogerus * the core in dwc3_core_init. 449b5a65c40SHuang Rui */ 45088bc9d19SHeikki Krogerus static int dwc3_phy_setup(struct dwc3 *dwc) 451b5a65c40SHuang Rui { 452b5a65c40SHuang Rui u32 reg; 45388bc9d19SHeikki Krogerus int ret; 454b5a65c40SHuang Rui 455b5a65c40SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 456b5a65c40SHuang Rui 4572164a476SHuang Rui /* 4582164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY 4592164a476SHuang Rui * to '0' during coreConsultant configuration. So default value 4602164a476SHuang Rui * will be '0' when the core is reset. Application needs to set it 4612164a476SHuang Rui * to '1' after the core initialization is completed. 4622164a476SHuang Rui */ 4632164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 4642164a476SHuang Rui reg |= DWC3_GUSB3PIPECTL_SUSPHY; 4652164a476SHuang Rui 466b5a65c40SHuang Rui if (dwc->u2ss_inp3_quirk) 467b5a65c40SHuang Rui reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; 468b5a65c40SHuang Rui 469e58dd357SRajesh Bhagat if (dwc->dis_rxdet_inp3_quirk) 470e58dd357SRajesh Bhagat reg |= DWC3_GUSB3PIPECTL_DISRXDETINP3; 471e58dd357SRajesh Bhagat 472df31f5b3SHuang Rui if (dwc->req_p1p2p3_quirk) 473df31f5b3SHuang Rui reg |= DWC3_GUSB3PIPECTL_REQP1P2P3; 474df31f5b3SHuang Rui 475a2a1d0f5SHuang Rui if (dwc->del_p1p2p3_quirk) 476a2a1d0f5SHuang Rui reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN; 477a2a1d0f5SHuang Rui 47841c06ffdSHuang Rui if (dwc->del_phy_power_chg_quirk) 47941c06ffdSHuang Rui reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE; 48041c06ffdSHuang Rui 481fb67afcaSHuang Rui if (dwc->lfps_filter_quirk) 482fb67afcaSHuang Rui reg |= DWC3_GUSB3PIPECTL_LFPSFILT; 483fb67afcaSHuang Rui 48414f4ac53SHuang Rui if (dwc->rx_detect_poll_quirk) 48514f4ac53SHuang Rui reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL; 48614f4ac53SHuang Rui 4876b6a0c9aSHuang Rui if (dwc->tx_de_emphasis_quirk) 4886b6a0c9aSHuang Rui reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); 4896b6a0c9aSHuang Rui 490cd72f890SFelipe Balbi if (dwc->dis_u3_susphy_quirk) 49159acfa20SHuang Rui reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 49259acfa20SHuang Rui 49300fe081dSWilliam Wu if (dwc->dis_del_phy_power_chg_quirk) 49400fe081dSWilliam Wu reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE; 49500fe081dSWilliam Wu 496b5a65c40SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 497b5a65c40SHuang Rui 4982164a476SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 4992164a476SHuang Rui 5003e10a2ceSHeikki Krogerus /* Select the HS PHY interface */ 5013e10a2ceSHeikki Krogerus switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) { 5023e10a2ceSHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI: 50343cacb03SFelipe Balbi if (dwc->hsphy_interface && 50443cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "utmi", 4)) { 5053e10a2ceSHeikki Krogerus reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI; 50688bc9d19SHeikki Krogerus break; 50743cacb03SFelipe Balbi } else if (dwc->hsphy_interface && 50843cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "ulpi", 4)) { 5093e10a2ceSHeikki Krogerus reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI; 51088bc9d19SHeikki Krogerus dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 5113e10a2ceSHeikki Krogerus } else { 51288bc9d19SHeikki Krogerus /* Relying on default value. */ 51388bc9d19SHeikki Krogerus if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) 5143e10a2ceSHeikki Krogerus break; 5153e10a2ceSHeikki Krogerus } 5163e10a2ceSHeikki Krogerus /* FALLTHROUGH */ 51788bc9d19SHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: 51888bc9d19SHeikki Krogerus /* Making sure the interface and PHY are operational */ 51988bc9d19SHeikki Krogerus ret = dwc3_soft_reset(dwc); 52088bc9d19SHeikki Krogerus if (ret) 52188bc9d19SHeikki Krogerus return ret; 52288bc9d19SHeikki Krogerus 52388bc9d19SHeikki Krogerus udelay(1); 52488bc9d19SHeikki Krogerus 52588bc9d19SHeikki Krogerus ret = dwc3_ulpi_init(dwc); 52688bc9d19SHeikki Krogerus if (ret) 52788bc9d19SHeikki Krogerus return ret; 52888bc9d19SHeikki Krogerus /* FALLTHROUGH */ 5293e10a2ceSHeikki Krogerus default: 5303e10a2ceSHeikki Krogerus break; 5313e10a2ceSHeikki Krogerus } 5323e10a2ceSHeikki Krogerus 53332f2ed86SWilliam Wu switch (dwc->hsphy_mode) { 53432f2ed86SWilliam Wu case USBPHY_INTERFACE_MODE_UTMI: 53532f2ed86SWilliam Wu reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | 53632f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); 53732f2ed86SWilliam Wu reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) | 53832f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT); 53932f2ed86SWilliam Wu break; 54032f2ed86SWilliam Wu case USBPHY_INTERFACE_MODE_UTMIW: 54132f2ed86SWilliam Wu reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | 54232f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); 54332f2ed86SWilliam Wu reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) | 54432f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT); 54532f2ed86SWilliam Wu break; 54632f2ed86SWilliam Wu default: 54732f2ed86SWilliam Wu break; 54832f2ed86SWilliam Wu } 54932f2ed86SWilliam Wu 5502164a476SHuang Rui /* 5512164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to 5522164a476SHuang Rui * '0' during coreConsultant configuration. So default value will 5532164a476SHuang Rui * be '0' when the core is reset. Application needs to set it to 5542164a476SHuang Rui * '1' after the core initialization is completed. 5552164a476SHuang Rui */ 5562164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 5572164a476SHuang Rui reg |= DWC3_GUSB2PHYCFG_SUSPHY; 5582164a476SHuang Rui 559cd72f890SFelipe Balbi if (dwc->dis_u2_susphy_quirk) 5600effe0a3SHuang Rui reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 5610effe0a3SHuang Rui 562ec791d14SJohn Youn if (dwc->dis_enblslpm_quirk) 563ec791d14SJohn Youn reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; 564ec791d14SJohn Youn 56516199f33SWilliam Wu if (dwc->dis_u2_freeclk_exists_quirk) 56616199f33SWilliam Wu reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS; 56716199f33SWilliam Wu 5682164a476SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 56988bc9d19SHeikki Krogerus 57088bc9d19SHeikki Krogerus return 0; 571b5a65c40SHuang Rui } 572b5a65c40SHuang Rui 573c499ff71SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 574c499ff71SFelipe Balbi { 575c499ff71SFelipe Balbi dwc3_event_buffers_cleanup(dwc); 576c499ff71SFelipe Balbi 577c499ff71SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 578c499ff71SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 579c499ff71SFelipe Balbi phy_exit(dwc->usb2_generic_phy); 580c499ff71SFelipe Balbi phy_exit(dwc->usb3_generic_phy); 581c499ff71SFelipe Balbi 582c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 1); 583c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 1); 584c499ff71SFelipe Balbi phy_power_off(dwc->usb2_generic_phy); 585c499ff71SFelipe Balbi phy_power_off(dwc->usb3_generic_phy); 586c499ff71SFelipe Balbi } 587c499ff71SFelipe Balbi 5880759956fSFelipe Balbi static bool dwc3_core_is_valid(struct dwc3 *dwc) 5890759956fSFelipe Balbi { 5900759956fSFelipe Balbi u32 reg; 5910759956fSFelipe Balbi 5920759956fSFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 5930759956fSFelipe Balbi 5940759956fSFelipe Balbi /* This should read as U3 followed by revision number */ 5950759956fSFelipe Balbi if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) { 5960759956fSFelipe Balbi /* Detected DWC_usb3 IP */ 5970759956fSFelipe Balbi dwc->revision = reg; 5980759956fSFelipe Balbi } else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) { 5990759956fSFelipe Balbi /* Detected DWC_usb31 IP */ 6000759956fSFelipe Balbi dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); 6010759956fSFelipe Balbi dwc->revision |= DWC3_REVISION_IS_DWC31; 6020759956fSFelipe Balbi } else { 6030759956fSFelipe Balbi return false; 6040759956fSFelipe Balbi } 6050759956fSFelipe Balbi 6060759956fSFelipe Balbi return true; 6070759956fSFelipe Balbi } 6080759956fSFelipe Balbi 609941f918eSFelipe Balbi static void dwc3_core_setup_global_control(struct dwc3 *dwc) 61072246da4SFelipe Balbi { 6110ffcaf37SFelipe Balbi u32 hwparams4 = dwc->hwparams.hwparams4; 61272246da4SFelipe Balbi u32 reg; 613c499ff71SFelipe Balbi 6144878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 6153e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 6164878a028SSebastian Andrzej Siewior 617164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 6184878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 61932a4a135SFelipe Balbi /** 62032a4a135SFelipe Balbi * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an 62132a4a135SFelipe Balbi * issue which would cause xHCI compliance tests to fail. 62232a4a135SFelipe Balbi * 62332a4a135SFelipe Balbi * Because of that we cannot enable clock gating on such 62432a4a135SFelipe Balbi * configurations. 62532a4a135SFelipe Balbi * 62632a4a135SFelipe Balbi * Refers to: 62732a4a135SFelipe Balbi * 62832a4a135SFelipe Balbi * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based 62932a4a135SFelipe Balbi * SOF/ITP Mode Used 63032a4a135SFelipe Balbi */ 63132a4a135SFelipe Balbi if ((dwc->dr_mode == USB_DR_MODE_HOST || 63232a4a135SFelipe Balbi dwc->dr_mode == USB_DR_MODE_OTG) && 63332a4a135SFelipe Balbi (dwc->revision >= DWC3_REVISION_210A && 63432a4a135SFelipe Balbi dwc->revision <= DWC3_REVISION_250A)) 63532a4a135SFelipe Balbi reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; 63632a4a135SFelipe Balbi else 6374878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 6384878a028SSebastian Andrzej Siewior break; 6390ffcaf37SFelipe Balbi case DWC3_GHWPARAMS1_EN_PWROPT_HIB: 6400ffcaf37SFelipe Balbi /* enable hibernation here */ 6410ffcaf37SFelipe Balbi dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); 6422eac3992SHuang Rui 6432eac3992SHuang Rui /* 6442eac3992SHuang Rui * REVISIT Enabling this bit so that host-mode hibernation 6452eac3992SHuang Rui * will work. Device-mode hibernation is not yet implemented. 6462eac3992SHuang Rui */ 6472eac3992SHuang Rui reg |= DWC3_GCTL_GBLHIBERNATIONEN; 6480ffcaf37SFelipe Balbi break; 6494878a028SSebastian Andrzej Siewior default: 6505eb30cedSFelipe Balbi /* nothing */ 6515eb30cedSFelipe Balbi break; 6524878a028SSebastian Andrzej Siewior } 6534878a028SSebastian Andrzej Siewior 654946bd579SHuang Rui /* check if current dwc3 is on simulation board */ 655946bd579SHuang Rui if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { 6565eb30cedSFelipe Balbi dev_info(dwc->dev, "Running with FPGA optmizations\n"); 657946bd579SHuang Rui dwc->is_fpga = true; 658946bd579SHuang Rui } 659946bd579SHuang Rui 6603b81221aSHuang Rui WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga, 6613b81221aSHuang Rui "disable_scramble cannot be used on non-FPGA builds\n"); 6623b81221aSHuang Rui 6633b81221aSHuang Rui if (dwc->disable_scramble_quirk && dwc->is_fpga) 6643b81221aSHuang Rui reg |= DWC3_GCTL_DISSCRAMBLE; 6653b81221aSHuang Rui else 6663b81221aSHuang Rui reg &= ~DWC3_GCTL_DISSCRAMBLE; 6673b81221aSHuang Rui 6689a5b2f31SHuang Rui if (dwc->u2exit_lfps_quirk) 6699a5b2f31SHuang Rui reg |= DWC3_GCTL_U2EXIT_LFPS; 6709a5b2f31SHuang Rui 6714878a028SSebastian Andrzej Siewior /* 6724878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 6731d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 6744878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 6751d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 6764878a028SSebastian Andrzej Siewior */ 6774878a028SSebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 6784878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 6794878a028SSebastian Andrzej Siewior 6804878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 681941f918eSFelipe Balbi } 6824878a028SSebastian Andrzej Siewior 683941f918eSFelipe Balbi /** 684941f918eSFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 685941f918eSFelipe Balbi * @dwc: Pointer to our controller context structure 686941f918eSFelipe Balbi * 687941f918eSFelipe Balbi * Returns 0 on success otherwise negative errno. 688941f918eSFelipe Balbi */ 689941f918eSFelipe Balbi static int dwc3_core_init(struct dwc3 *dwc) 690941f918eSFelipe Balbi { 691941f918eSFelipe Balbi u32 reg; 692941f918eSFelipe Balbi int ret; 693941f918eSFelipe Balbi 694941f918eSFelipe Balbi if (!dwc3_core_is_valid(dwc)) { 695941f918eSFelipe Balbi dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 696941f918eSFelipe Balbi ret = -ENODEV; 697941f918eSFelipe Balbi goto err0; 698941f918eSFelipe Balbi } 699941f918eSFelipe Balbi 700941f918eSFelipe Balbi /* 701941f918eSFelipe Balbi * Write Linux Version Code to our GUID register so it's easy to figure 702941f918eSFelipe Balbi * out which kernel version a bug was found. 703941f918eSFelipe Balbi */ 704941f918eSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); 705941f918eSFelipe Balbi 706941f918eSFelipe Balbi /* Handle USB2.0-only core configuration */ 707941f918eSFelipe Balbi if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 708941f918eSFelipe Balbi DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { 709941f918eSFelipe Balbi if (dwc->maximum_speed == USB_SPEED_SUPER) 710941f918eSFelipe Balbi dwc->maximum_speed = USB_SPEED_HIGH; 711941f918eSFelipe Balbi } 712941f918eSFelipe Balbi 713941f918eSFelipe Balbi /* issue device SoftReset too */ 714941f918eSFelipe Balbi ret = dwc3_soft_reset(dwc); 715941f918eSFelipe Balbi if (ret) 716941f918eSFelipe Balbi goto err0; 717941f918eSFelipe Balbi 718941f918eSFelipe Balbi ret = dwc3_core_soft_reset(dwc); 719941f918eSFelipe Balbi if (ret) 720941f918eSFelipe Balbi goto err0; 721941f918eSFelipe Balbi 722941f918eSFelipe Balbi ret = dwc3_phy_setup(dwc); 723941f918eSFelipe Balbi if (ret) 724941f918eSFelipe Balbi goto err0; 725941f918eSFelipe Balbi 726941f918eSFelipe Balbi dwc3_core_setup_global_control(dwc); 727c499ff71SFelipe Balbi dwc3_core_num_eps(dwc); 7280ffcaf37SFelipe Balbi 7290ffcaf37SFelipe Balbi ret = dwc3_setup_scratch_buffers(dwc); 7300ffcaf37SFelipe Balbi if (ret) 731c499ff71SFelipe Balbi goto err1; 732c499ff71SFelipe Balbi 733c499ff71SFelipe Balbi /* Adjust Frame Length */ 734c499ff71SFelipe Balbi dwc3_frame_length_adjustment(dwc); 735c499ff71SFelipe Balbi 736c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 0); 737c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 0); 738c499ff71SFelipe Balbi ret = phy_power_on(dwc->usb2_generic_phy); 739c499ff71SFelipe Balbi if (ret < 0) 7400ffcaf37SFelipe Balbi goto err2; 7410ffcaf37SFelipe Balbi 742c499ff71SFelipe Balbi ret = phy_power_on(dwc->usb3_generic_phy); 743c499ff71SFelipe Balbi if (ret < 0) 744c499ff71SFelipe Balbi goto err3; 745c499ff71SFelipe Balbi 746c499ff71SFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 747c499ff71SFelipe Balbi if (ret) { 748c499ff71SFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 749c499ff71SFelipe Balbi goto err4; 750c499ff71SFelipe Balbi } 751c499ff71SFelipe Balbi 75200af6233SBaolin Wang switch (dwc->dr_mode) { 75300af6233SBaolin Wang case USB_DR_MODE_PERIPHERAL: 75400af6233SBaolin Wang dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); 75500af6233SBaolin Wang break; 75600af6233SBaolin Wang case USB_DR_MODE_HOST: 75700af6233SBaolin Wang dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); 75800af6233SBaolin Wang break; 75900af6233SBaolin Wang case USB_DR_MODE_OTG: 76000af6233SBaolin Wang dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); 76100af6233SBaolin Wang break; 76200af6233SBaolin Wang default: 76300af6233SBaolin Wang dev_warn(dwc->dev, "Unsupported mode %d\n", dwc->dr_mode); 76400af6233SBaolin Wang break; 76500af6233SBaolin Wang } 76600af6233SBaolin Wang 76706281d46SJohn Youn /* 76806281d46SJohn Youn * ENDXFER polling is available on version 3.10a and later of 76906281d46SJohn Youn * the DWC_usb3 controller. It is NOT available in the 77006281d46SJohn Youn * DWC_usb31 controller. 77106281d46SJohn Youn */ 77206281d46SJohn Youn if (!dwc3_is_usb31(dwc) && dwc->revision >= DWC3_REVISION_310A) { 77306281d46SJohn Youn reg = dwc3_readl(dwc->regs, DWC3_GUCTL2); 77406281d46SJohn Youn reg |= DWC3_GUCTL2_RST_ACTBITLATER; 77506281d46SJohn Youn dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); 77606281d46SJohn Youn } 77706281d46SJohn Youn 7780bb39ca1SJohn Youn /* 7790bb39ca1SJohn Youn * Enable hardware control of sending remote wakeup in HS when 7800bb39ca1SJohn Youn * the device is in the L1 state. 7810bb39ca1SJohn Youn */ 7820bb39ca1SJohn Youn if (dwc->revision >= DWC3_REVISION_290A) { 7830bb39ca1SJohn Youn reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); 7840bb39ca1SJohn Youn reg |= DWC3_GUCTL1_DEV_L1_EXIT_BY_HW; 7850bb39ca1SJohn Youn dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); 7860bb39ca1SJohn Youn } 7870bb39ca1SJohn Youn 78872246da4SFelipe Balbi return 0; 78972246da4SFelipe Balbi 790c499ff71SFelipe Balbi err4: 791c499ff71SFelipe Balbi phy_power_off(dwc->usb2_generic_phy); 792c499ff71SFelipe Balbi 793c499ff71SFelipe Balbi err3: 794c499ff71SFelipe Balbi phy_power_off(dwc->usb3_generic_phy); 795c499ff71SFelipe Balbi 7960ffcaf37SFelipe Balbi err2: 797c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 1); 798c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 1); 799c499ff71SFelipe Balbi dwc3_core_exit(dwc); 8000ffcaf37SFelipe Balbi 8010ffcaf37SFelipe Balbi err1: 8020ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 8030ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 80457303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 80557303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 8060ffcaf37SFelipe Balbi 80772246da4SFelipe Balbi err0: 80872246da4SFelipe Balbi return ret; 80972246da4SFelipe Balbi } 81072246da4SFelipe Balbi 8113c9f94acSFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc) 81272246da4SFelipe Balbi { 8133c9f94acSFelipe Balbi struct device *dev = dwc->dev; 814941ea361SFelipe Balbi struct device_node *node = dev->of_node; 8153c9f94acSFelipe Balbi int ret; 81672246da4SFelipe Balbi 8175088b6f5SKishon Vijay Abraham I if (node) { 8185088b6f5SKishon Vijay Abraham I dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); 8195088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); 820bb674907SFelipe Balbi } else { 821bb674907SFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 822bb674907SFelipe Balbi dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 8235088b6f5SKishon Vijay Abraham I } 8245088b6f5SKishon Vijay Abraham I 825d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb2_phy)) { 826d105e7f8SFelipe Balbi ret = PTR_ERR(dwc->usb2_phy); 827122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 828122f06e6SKishon Vijay Abraham I dwc->usb2_phy = NULL; 829122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 830d105e7f8SFelipe Balbi return ret; 831122f06e6SKishon Vijay Abraham I } else { 83251e1e7bcSFelipe Balbi dev_err(dev, "no usb2 phy configured\n"); 833122f06e6SKishon Vijay Abraham I return ret; 834122f06e6SKishon Vijay Abraham I } 83551e1e7bcSFelipe Balbi } 83651e1e7bcSFelipe Balbi 837d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb3_phy)) { 838315955d7SRuchika Kharwar ret = PTR_ERR(dwc->usb3_phy); 839122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 840122f06e6SKishon Vijay Abraham I dwc->usb3_phy = NULL; 841122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 842d105e7f8SFelipe Balbi return ret; 843122f06e6SKishon Vijay Abraham I } else { 84451e1e7bcSFelipe Balbi dev_err(dev, "no usb3 phy configured\n"); 845122f06e6SKishon Vijay Abraham I return ret; 846122f06e6SKishon Vijay Abraham I } 84751e1e7bcSFelipe Balbi } 84851e1e7bcSFelipe Balbi 84957303488SKishon Vijay Abraham I dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); 85057303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb2_generic_phy)) { 85157303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb2_generic_phy); 85257303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 85357303488SKishon Vijay Abraham I dwc->usb2_generic_phy = NULL; 85457303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 85557303488SKishon Vijay Abraham I return ret; 85657303488SKishon Vijay Abraham I } else { 85757303488SKishon Vijay Abraham I dev_err(dev, "no usb2 phy configured\n"); 85857303488SKishon Vijay Abraham I return ret; 85957303488SKishon Vijay Abraham I } 86057303488SKishon Vijay Abraham I } 86157303488SKishon Vijay Abraham I 86257303488SKishon Vijay Abraham I dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy"); 86357303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb3_generic_phy)) { 86457303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb3_generic_phy); 86557303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 86657303488SKishon Vijay Abraham I dwc->usb3_generic_phy = NULL; 86757303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 86857303488SKishon Vijay Abraham I return ret; 86957303488SKishon Vijay Abraham I } else { 87057303488SKishon Vijay Abraham I dev_err(dev, "no usb3 phy configured\n"); 87157303488SKishon Vijay Abraham I return ret; 87257303488SKishon Vijay Abraham I } 87357303488SKishon Vijay Abraham I } 87457303488SKishon Vijay Abraham I 8753c9f94acSFelipe Balbi return 0; 8763c9f94acSFelipe Balbi } 8773c9f94acSFelipe Balbi 8785f94adfeSFelipe Balbi static int dwc3_core_init_mode(struct dwc3 *dwc) 8795f94adfeSFelipe Balbi { 8805f94adfeSFelipe Balbi struct device *dev = dwc->dev; 8815f94adfeSFelipe Balbi int ret; 8825f94adfeSFelipe Balbi 8835f94adfeSFelipe Balbi switch (dwc->dr_mode) { 8845f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 8855f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 8865f94adfeSFelipe Balbi if (ret) { 8879522def4SRoger Quadros if (ret != -EPROBE_DEFER) 8885f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 8895f94adfeSFelipe Balbi return ret; 8905f94adfeSFelipe Balbi } 8915f94adfeSFelipe Balbi break; 8925f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 8935f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 8945f94adfeSFelipe Balbi if (ret) { 8959522def4SRoger Quadros if (ret != -EPROBE_DEFER) 8965f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 8975f94adfeSFelipe Balbi return ret; 8985f94adfeSFelipe Balbi } 8995f94adfeSFelipe Balbi break; 9005f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 9015f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 9025f94adfeSFelipe Balbi if (ret) { 9039522def4SRoger Quadros if (ret != -EPROBE_DEFER) 9045f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 9055f94adfeSFelipe Balbi return ret; 9065f94adfeSFelipe Balbi } 9075f94adfeSFelipe Balbi 9085f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 9095f94adfeSFelipe Balbi if (ret) { 9109522def4SRoger Quadros if (ret != -EPROBE_DEFER) 9115f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 9125f94adfeSFelipe Balbi return ret; 9135f94adfeSFelipe Balbi } 9145f94adfeSFelipe Balbi break; 9155f94adfeSFelipe Balbi default: 9165f94adfeSFelipe Balbi dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); 9175f94adfeSFelipe Balbi return -EINVAL; 9185f94adfeSFelipe Balbi } 9195f94adfeSFelipe Balbi 9205f94adfeSFelipe Balbi return 0; 9215f94adfeSFelipe Balbi } 9225f94adfeSFelipe Balbi 9235f94adfeSFelipe Balbi static void dwc3_core_exit_mode(struct dwc3 *dwc) 9245f94adfeSFelipe Balbi { 9255f94adfeSFelipe Balbi switch (dwc->dr_mode) { 9265f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 9275f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 9285f94adfeSFelipe Balbi break; 9295f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 9305f94adfeSFelipe Balbi dwc3_host_exit(dwc); 9315f94adfeSFelipe Balbi break; 9325f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 9335f94adfeSFelipe Balbi dwc3_host_exit(dwc); 9345f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 9355f94adfeSFelipe Balbi break; 9365f94adfeSFelipe Balbi default: 9375f94adfeSFelipe Balbi /* do nothing */ 9385f94adfeSFelipe Balbi break; 9395f94adfeSFelipe Balbi } 9405f94adfeSFelipe Balbi } 9415f94adfeSFelipe Balbi 942c5ac6116SFelipe Balbi static void dwc3_get_properties(struct dwc3 *dwc) 9433c9f94acSFelipe Balbi { 944c5ac6116SFelipe Balbi struct device *dev = dwc->dev; 94580caf7d2SHuang Rui u8 lpm_nyet_threshold; 9466b6a0c9aSHuang Rui u8 tx_de_emphasis; 947460d098cSHuang Rui u8 hird_threshold; 9483c9f94acSFelipe Balbi 94980caf7d2SHuang Rui /* default to highest possible threshold */ 95080caf7d2SHuang Rui lpm_nyet_threshold = 0xff; 95180caf7d2SHuang Rui 9526b6a0c9aSHuang Rui /* default to -3.5dB de-emphasis */ 9536b6a0c9aSHuang Rui tx_de_emphasis = 1; 9546b6a0c9aSHuang Rui 955460d098cSHuang Rui /* 956460d098cSHuang Rui * default to assert utmi_sleep_n and use maximum allowed HIRD 957460d098cSHuang Rui * threshold value of 0b1100 958460d098cSHuang Rui */ 959460d098cSHuang Rui hird_threshold = 12; 960460d098cSHuang Rui 96163863b98SHeikki Krogerus dwc->maximum_speed = usb_get_maximum_speed(dev); 96206e7114fSHeikki Krogerus dwc->dr_mode = usb_get_dr_mode(dev); 96332f2ed86SWilliam Wu dwc->hsphy_mode = of_usb_get_phy_mode(dev->of_node); 96463863b98SHeikki Krogerus 9653d128919SHeikki Krogerus dwc->has_lpm_erratum = device_property_read_bool(dev, 96680caf7d2SHuang Rui "snps,has-lpm-erratum"); 9673d128919SHeikki Krogerus device_property_read_u8(dev, "snps,lpm-nyet-threshold", 96880caf7d2SHuang Rui &lpm_nyet_threshold); 9693d128919SHeikki Krogerus dwc->is_utmi_l1_suspend = device_property_read_bool(dev, 970460d098cSHuang Rui "snps,is-utmi-l1-suspend"); 9713d128919SHeikki Krogerus device_property_read_u8(dev, "snps,hird-threshold", 972460d098cSHuang Rui &hird_threshold); 9733d128919SHeikki Krogerus dwc->usb3_lpm_capable = device_property_read_bool(dev, 974eac68e8fSRobert Baldyga "snps,usb3_lpm_capable"); 9753c9f94acSFelipe Balbi 9763d128919SHeikki Krogerus dwc->disable_scramble_quirk = device_property_read_bool(dev, 9773b81221aSHuang Rui "snps,disable_scramble_quirk"); 9783d128919SHeikki Krogerus dwc->u2exit_lfps_quirk = device_property_read_bool(dev, 9799a5b2f31SHuang Rui "snps,u2exit_lfps_quirk"); 9803d128919SHeikki Krogerus dwc->u2ss_inp3_quirk = device_property_read_bool(dev, 981b5a65c40SHuang Rui "snps,u2ss_inp3_quirk"); 9823d128919SHeikki Krogerus dwc->req_p1p2p3_quirk = device_property_read_bool(dev, 983df31f5b3SHuang Rui "snps,req_p1p2p3_quirk"); 9843d128919SHeikki Krogerus dwc->del_p1p2p3_quirk = device_property_read_bool(dev, 985a2a1d0f5SHuang Rui "snps,del_p1p2p3_quirk"); 9863d128919SHeikki Krogerus dwc->del_phy_power_chg_quirk = device_property_read_bool(dev, 98741c06ffdSHuang Rui "snps,del_phy_power_chg_quirk"); 9883d128919SHeikki Krogerus dwc->lfps_filter_quirk = device_property_read_bool(dev, 989fb67afcaSHuang Rui "snps,lfps_filter_quirk"); 9903d128919SHeikki Krogerus dwc->rx_detect_poll_quirk = device_property_read_bool(dev, 99114f4ac53SHuang Rui "snps,rx_detect_poll_quirk"); 9923d128919SHeikki Krogerus dwc->dis_u3_susphy_quirk = device_property_read_bool(dev, 99359acfa20SHuang Rui "snps,dis_u3_susphy_quirk"); 9943d128919SHeikki Krogerus dwc->dis_u2_susphy_quirk = device_property_read_bool(dev, 9950effe0a3SHuang Rui "snps,dis_u2_susphy_quirk"); 996ec791d14SJohn Youn dwc->dis_enblslpm_quirk = device_property_read_bool(dev, 997ec791d14SJohn Youn "snps,dis_enblslpm_quirk"); 998e58dd357SRajesh Bhagat dwc->dis_rxdet_inp3_quirk = device_property_read_bool(dev, 999e58dd357SRajesh Bhagat "snps,dis_rxdet_inp3_quirk"); 100016199f33SWilliam Wu dwc->dis_u2_freeclk_exists_quirk = device_property_read_bool(dev, 100116199f33SWilliam Wu "snps,dis-u2-freeclk-exists-quirk"); 100200fe081dSWilliam Wu dwc->dis_del_phy_power_chg_quirk = device_property_read_bool(dev, 100300fe081dSWilliam Wu "snps,dis-del-phy-power-chg-quirk"); 10046b6a0c9aSHuang Rui 10053d128919SHeikki Krogerus dwc->tx_de_emphasis_quirk = device_property_read_bool(dev, 10066b6a0c9aSHuang Rui "snps,tx_de_emphasis_quirk"); 10073d128919SHeikki Krogerus device_property_read_u8(dev, "snps,tx_de_emphasis", 10086b6a0c9aSHuang Rui &tx_de_emphasis); 10093d128919SHeikki Krogerus device_property_read_string(dev, "snps,hsphy_interface", 10103e10a2ceSHeikki Krogerus &dwc->hsphy_interface); 10113d128919SHeikki Krogerus device_property_read_u32(dev, "snps,quirk-frame-length-adjustment", 1012bcdb3272SFelipe Balbi &dwc->fladj); 10133d128919SHeikki Krogerus 101480caf7d2SHuang Rui dwc->lpm_nyet_threshold = lpm_nyet_threshold; 10156b6a0c9aSHuang Rui dwc->tx_de_emphasis = tx_de_emphasis; 101680caf7d2SHuang Rui 1017460d098cSHuang Rui dwc->hird_threshold = hird_threshold 1018460d098cSHuang Rui | (dwc->is_utmi_l1_suspend << 4); 1019460d098cSHuang Rui 1020c5ac6116SFelipe Balbi } 1021c5ac6116SFelipe Balbi 1022c5ac6116SFelipe Balbi static int dwc3_probe(struct platform_device *pdev) 1023c5ac6116SFelipe Balbi { 1024c5ac6116SFelipe Balbi struct device *dev = &pdev->dev; 1025c5ac6116SFelipe Balbi struct resource *res; 1026c5ac6116SFelipe Balbi struct dwc3 *dwc; 1027c5ac6116SFelipe Balbi 1028c5ac6116SFelipe Balbi int ret; 1029c5ac6116SFelipe Balbi 1030c5ac6116SFelipe Balbi void __iomem *regs; 1031c5ac6116SFelipe Balbi 1032c5ac6116SFelipe Balbi dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL); 1033c5ac6116SFelipe Balbi if (!dwc) 1034c5ac6116SFelipe Balbi return -ENOMEM; 1035c5ac6116SFelipe Balbi 1036c5ac6116SFelipe Balbi dwc->dev = dev; 1037c5ac6116SFelipe Balbi 1038c5ac6116SFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1039c5ac6116SFelipe Balbi if (!res) { 1040c5ac6116SFelipe Balbi dev_err(dev, "missing memory resource\n"); 1041c5ac6116SFelipe Balbi return -ENODEV; 1042c5ac6116SFelipe Balbi } 1043c5ac6116SFelipe Balbi 1044c5ac6116SFelipe Balbi dwc->xhci_resources[0].start = res->start; 1045c5ac6116SFelipe Balbi dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 1046c5ac6116SFelipe Balbi DWC3_XHCI_REGS_END; 1047c5ac6116SFelipe Balbi dwc->xhci_resources[0].flags = res->flags; 1048c5ac6116SFelipe Balbi dwc->xhci_resources[0].name = res->name; 1049c5ac6116SFelipe Balbi 1050c5ac6116SFelipe Balbi res->start += DWC3_GLOBALS_REGS_START; 1051c5ac6116SFelipe Balbi 1052c5ac6116SFelipe Balbi /* 1053c5ac6116SFelipe Balbi * Request memory region but exclude xHCI regs, 1054c5ac6116SFelipe Balbi * since it will be requested by the xhci-plat driver. 1055c5ac6116SFelipe Balbi */ 1056c5ac6116SFelipe Balbi regs = devm_ioremap_resource(dev, res); 1057c5ac6116SFelipe Balbi if (IS_ERR(regs)) { 1058c5ac6116SFelipe Balbi ret = PTR_ERR(regs); 1059c5ac6116SFelipe Balbi goto err0; 1060c5ac6116SFelipe Balbi } 1061c5ac6116SFelipe Balbi 1062c5ac6116SFelipe Balbi dwc->regs = regs; 1063c5ac6116SFelipe Balbi dwc->regs_size = resource_size(res); 1064c5ac6116SFelipe Balbi 1065c5ac6116SFelipe Balbi dwc3_get_properties(dwc); 1066c5ac6116SFelipe Balbi 10676c89cce0SHeikki Krogerus platform_set_drvdata(pdev, dwc); 10682917e718SHeikki Krogerus dwc3_cache_hwparams(dwc); 10696c89cce0SHeikki Krogerus 10703c9f94acSFelipe Balbi ret = dwc3_core_get_phy(dwc); 10713c9f94acSFelipe Balbi if (ret) 10723da1f6eeSFelipe Balbi goto err0; 10733c9f94acSFelipe Balbi 107472246da4SFelipe Balbi spin_lock_init(&dwc->lock); 107572246da4SFelipe Balbi 107619bacdc9SHeikki Krogerus if (!dev->dma_mask) { 1077ddff14f1SKishon Vijay Abraham I dev->dma_mask = dev->parent->dma_mask; 1078ddff14f1SKishon Vijay Abraham I dev->dma_parms = dev->parent->dma_parms; 1079ddff14f1SKishon Vijay Abraham I dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); 108019bacdc9SHeikki Krogerus } 1081ddff14f1SKishon Vijay Abraham I 1082fc8bb91bSFelipe Balbi pm_runtime_set_active(dev); 1083fc8bb91bSFelipe Balbi pm_runtime_use_autosuspend(dev); 1084fc8bb91bSFelipe Balbi pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY); 1085802ca850SChanho Park pm_runtime_enable(dev); 108632808237SRoger Quadros ret = pm_runtime_get_sync(dev); 108732808237SRoger Quadros if (ret < 0) 108832808237SRoger Quadros goto err1; 108932808237SRoger Quadros 1090802ca850SChanho Park pm_runtime_forbid(dev); 109172246da4SFelipe Balbi 10923921426bSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 10933921426bSFelipe Balbi if (ret) { 10943921426bSFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 10953921426bSFelipe Balbi ret = -ENOMEM; 109632808237SRoger Quadros goto err2; 10973921426bSFelipe Balbi } 10983921426bSFelipe Balbi 10999d6173e1SThinh Nguyen ret = dwc3_get_dr_mode(dwc); 11009d6173e1SThinh Nguyen if (ret) 11019d6173e1SThinh Nguyen goto err3; 110232a4a135SFelipe Balbi 1103c499ff71SFelipe Balbi ret = dwc3_alloc_scratch_buffers(dwc); 1104c499ff71SFelipe Balbi if (ret) 110532808237SRoger Quadros goto err3; 1106c499ff71SFelipe Balbi 110772246da4SFelipe Balbi ret = dwc3_core_init(dwc); 110872246da4SFelipe Balbi if (ret) { 1109802ca850SChanho Park dev_err(dev, "failed to initialize core\n"); 111032808237SRoger Quadros goto err4; 111172246da4SFelipe Balbi } 111272246da4SFelipe Balbi 111377966eb8SJohn Youn /* Check the maximum_speed parameter */ 111477966eb8SJohn Youn switch (dwc->maximum_speed) { 111577966eb8SJohn Youn case USB_SPEED_LOW: 111677966eb8SJohn Youn case USB_SPEED_FULL: 111777966eb8SJohn Youn case USB_SPEED_HIGH: 111877966eb8SJohn Youn case USB_SPEED_SUPER: 111977966eb8SJohn Youn case USB_SPEED_SUPER_PLUS: 112077966eb8SJohn Youn break; 112177966eb8SJohn Youn default: 112277966eb8SJohn Youn dev_err(dev, "invalid maximum_speed parameter %d\n", 112377966eb8SJohn Youn dwc->maximum_speed); 112477966eb8SJohn Youn /* fall through */ 112577966eb8SJohn Youn case USB_SPEED_UNKNOWN: 112677966eb8SJohn Youn /* default to superspeed */ 11272c7f1bd9SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER; 11282c7f1bd9SJohn Youn 11292c7f1bd9SJohn Youn /* 11302c7f1bd9SJohn Youn * default to superspeed plus if we are capable. 11312c7f1bd9SJohn Youn */ 11322c7f1bd9SJohn Youn if (dwc3_is_usb31(dwc) && 11332c7f1bd9SJohn Youn (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 11342c7f1bd9SJohn Youn DWC3_GHWPARAMS3_SSPHY_IFC_GEN2)) 11352c7f1bd9SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER_PLUS; 113677966eb8SJohn Youn 113777966eb8SJohn Youn break; 11382c7f1bd9SJohn Youn } 11392c7f1bd9SJohn Youn 11405f94adfeSFelipe Balbi ret = dwc3_core_init_mode(dwc); 11415f94adfeSFelipe Balbi if (ret) 114232808237SRoger Quadros goto err5; 114372246da4SFelipe Balbi 11444e9f3118SDu, Changbin dwc3_debugfs_init(dwc); 1145fc8bb91bSFelipe Balbi pm_runtime_put(dev); 114672246da4SFelipe Balbi 114772246da4SFelipe Balbi return 0; 114872246da4SFelipe Balbi 114932808237SRoger Quadros err5: 1150f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 1151f122d33eSFelipe Balbi 115232808237SRoger Quadros err4: 1153c499ff71SFelipe Balbi dwc3_free_scratch_buffers(dwc); 115472246da4SFelipe Balbi 115532808237SRoger Quadros err3: 11563921426bSFelipe Balbi dwc3_free_event_buffers(dwc); 115788bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 11583921426bSFelipe Balbi 115932808237SRoger Quadros err2: 116032808237SRoger Quadros pm_runtime_allow(&pdev->dev); 116132808237SRoger Quadros 116232808237SRoger Quadros err1: 116332808237SRoger Quadros pm_runtime_put_sync(&pdev->dev); 116432808237SRoger Quadros pm_runtime_disable(&pdev->dev); 116532808237SRoger Quadros 11663da1f6eeSFelipe Balbi err0: 11673da1f6eeSFelipe Balbi /* 11683da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 11693da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 11703da1f6eeSFelipe Balbi * memory region the next time probe is called. 11713da1f6eeSFelipe Balbi */ 11723da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 11733da1f6eeSFelipe Balbi 117472246da4SFelipe Balbi return ret; 117572246da4SFelipe Balbi } 117672246da4SFelipe Balbi 1177fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev) 117872246da4SFelipe Balbi { 117972246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 11803da1f6eeSFelipe Balbi struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 11813da1f6eeSFelipe Balbi 1182fc8bb91bSFelipe Balbi pm_runtime_get_sync(&pdev->dev); 11833da1f6eeSFelipe Balbi /* 11843da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 11853da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 11863da1f6eeSFelipe Balbi * memory region the next time probe is called. 11873da1f6eeSFelipe Balbi */ 11883da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 118972246da4SFelipe Balbi 1190dc99f16fSFelipe Balbi dwc3_debugfs_exit(dwc); 1191dc99f16fSFelipe Balbi dwc3_core_exit_mode(dwc); 11928ba007a9SKishon Vijay Abraham I 119372246da4SFelipe Balbi dwc3_core_exit(dwc); 119488bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 119572246da4SFelipe Balbi 1196fc8bb91bSFelipe Balbi pm_runtime_put_sync(&pdev->dev); 1197fc8bb91bSFelipe Balbi pm_runtime_allow(&pdev->dev); 1198fc8bb91bSFelipe Balbi pm_runtime_disable(&pdev->dev); 1199fc8bb91bSFelipe Balbi 1200c499ff71SFelipe Balbi dwc3_free_event_buffers(dwc); 1201c499ff71SFelipe Balbi dwc3_free_scratch_buffers(dwc); 1202c499ff71SFelipe Balbi 120372246da4SFelipe Balbi return 0; 120472246da4SFelipe Balbi } 120572246da4SFelipe Balbi 1206fc8bb91bSFelipe Balbi #ifdef CONFIG_PM 1207fc8bb91bSFelipe Balbi static int dwc3_suspend_common(struct dwc3 *dwc) 12087415f17cSFelipe Balbi { 1209fc8bb91bSFelipe Balbi unsigned long flags; 12107415f17cSFelipe Balbi 1211a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 1212a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 1213a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 1214fc8bb91bSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 12157415f17cSFelipe Balbi dwc3_gadget_suspend(dwc); 1216fc8bb91bSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 121751f5d49aSFelipe Balbi break; 1218a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 12197415f17cSFelipe Balbi default: 122051f5d49aSFelipe Balbi /* do nothing */ 12217415f17cSFelipe Balbi break; 12227415f17cSFelipe Balbi } 12237415f17cSFelipe Balbi 122451f5d49aSFelipe Balbi dwc3_core_exit(dwc); 12255c4ad318SFelipe Balbi 1226fc8bb91bSFelipe Balbi return 0; 1227fc8bb91bSFelipe Balbi } 1228fc8bb91bSFelipe Balbi 1229fc8bb91bSFelipe Balbi static int dwc3_resume_common(struct dwc3 *dwc) 1230fc8bb91bSFelipe Balbi { 1231fc8bb91bSFelipe Balbi unsigned long flags; 1232fc8bb91bSFelipe Balbi int ret; 1233fc8bb91bSFelipe Balbi 1234fc8bb91bSFelipe Balbi ret = dwc3_core_init(dwc); 1235fc8bb91bSFelipe Balbi if (ret) 1236fc8bb91bSFelipe Balbi return ret; 1237fc8bb91bSFelipe Balbi 1238fc8bb91bSFelipe Balbi switch (dwc->dr_mode) { 1239fc8bb91bSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 1240fc8bb91bSFelipe Balbi case USB_DR_MODE_OTG: 1241fc8bb91bSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 1242fc8bb91bSFelipe Balbi dwc3_gadget_resume(dwc); 1243fc8bb91bSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 1244fc8bb91bSFelipe Balbi /* FALLTHROUGH */ 1245fc8bb91bSFelipe Balbi case USB_DR_MODE_HOST: 1246fc8bb91bSFelipe Balbi default: 1247fc8bb91bSFelipe Balbi /* do nothing */ 1248fc8bb91bSFelipe Balbi break; 1249fc8bb91bSFelipe Balbi } 1250fc8bb91bSFelipe Balbi 1251fc8bb91bSFelipe Balbi return 0; 1252fc8bb91bSFelipe Balbi } 1253fc8bb91bSFelipe Balbi 1254fc8bb91bSFelipe Balbi static int dwc3_runtime_checks(struct dwc3 *dwc) 1255fc8bb91bSFelipe Balbi { 1256fc8bb91bSFelipe Balbi switch (dwc->dr_mode) { 1257fc8bb91bSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 1258fc8bb91bSFelipe Balbi case USB_DR_MODE_OTG: 1259fc8bb91bSFelipe Balbi if (dwc->connected) 1260fc8bb91bSFelipe Balbi return -EBUSY; 1261fc8bb91bSFelipe Balbi break; 1262fc8bb91bSFelipe Balbi case USB_DR_MODE_HOST: 1263fc8bb91bSFelipe Balbi default: 1264fc8bb91bSFelipe Balbi /* do nothing */ 1265fc8bb91bSFelipe Balbi break; 1266fc8bb91bSFelipe Balbi } 1267fc8bb91bSFelipe Balbi 1268fc8bb91bSFelipe Balbi return 0; 1269fc8bb91bSFelipe Balbi } 1270fc8bb91bSFelipe Balbi 1271fc8bb91bSFelipe Balbi static int dwc3_runtime_suspend(struct device *dev) 1272fc8bb91bSFelipe Balbi { 1273fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1274fc8bb91bSFelipe Balbi int ret; 1275fc8bb91bSFelipe Balbi 1276fc8bb91bSFelipe Balbi if (dwc3_runtime_checks(dwc)) 1277fc8bb91bSFelipe Balbi return -EBUSY; 1278fc8bb91bSFelipe Balbi 1279fc8bb91bSFelipe Balbi ret = dwc3_suspend_common(dwc); 1280fc8bb91bSFelipe Balbi if (ret) 1281fc8bb91bSFelipe Balbi return ret; 1282fc8bb91bSFelipe Balbi 1283fc8bb91bSFelipe Balbi device_init_wakeup(dev, true); 1284fc8bb91bSFelipe Balbi 1285fc8bb91bSFelipe Balbi return 0; 1286fc8bb91bSFelipe Balbi } 1287fc8bb91bSFelipe Balbi 1288fc8bb91bSFelipe Balbi static int dwc3_runtime_resume(struct device *dev) 1289fc8bb91bSFelipe Balbi { 1290fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1291fc8bb91bSFelipe Balbi int ret; 1292fc8bb91bSFelipe Balbi 1293fc8bb91bSFelipe Balbi device_init_wakeup(dev, false); 1294fc8bb91bSFelipe Balbi 1295fc8bb91bSFelipe Balbi ret = dwc3_resume_common(dwc); 1296fc8bb91bSFelipe Balbi if (ret) 1297fc8bb91bSFelipe Balbi return ret; 1298fc8bb91bSFelipe Balbi 1299fc8bb91bSFelipe Balbi switch (dwc->dr_mode) { 1300fc8bb91bSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 1301fc8bb91bSFelipe Balbi case USB_DR_MODE_OTG: 1302fc8bb91bSFelipe Balbi dwc3_gadget_process_pending_events(dwc); 1303fc8bb91bSFelipe Balbi break; 1304fc8bb91bSFelipe Balbi case USB_DR_MODE_HOST: 1305fc8bb91bSFelipe Balbi default: 1306fc8bb91bSFelipe Balbi /* do nothing */ 1307fc8bb91bSFelipe Balbi break; 1308fc8bb91bSFelipe Balbi } 1309fc8bb91bSFelipe Balbi 1310fc8bb91bSFelipe Balbi pm_runtime_mark_last_busy(dev); 1311b74c2d87SFelipe Balbi pm_runtime_put(dev); 1312fc8bb91bSFelipe Balbi 1313fc8bb91bSFelipe Balbi return 0; 1314fc8bb91bSFelipe Balbi } 1315fc8bb91bSFelipe Balbi 1316fc8bb91bSFelipe Balbi static int dwc3_runtime_idle(struct device *dev) 1317fc8bb91bSFelipe Balbi { 1318fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1319fc8bb91bSFelipe Balbi 1320fc8bb91bSFelipe Balbi switch (dwc->dr_mode) { 1321fc8bb91bSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 1322fc8bb91bSFelipe Balbi case USB_DR_MODE_OTG: 1323fc8bb91bSFelipe Balbi if (dwc3_runtime_checks(dwc)) 1324fc8bb91bSFelipe Balbi return -EBUSY; 1325fc8bb91bSFelipe Balbi break; 1326fc8bb91bSFelipe Balbi case USB_DR_MODE_HOST: 1327fc8bb91bSFelipe Balbi default: 1328fc8bb91bSFelipe Balbi /* do nothing */ 1329fc8bb91bSFelipe Balbi break; 1330fc8bb91bSFelipe Balbi } 1331fc8bb91bSFelipe Balbi 1332fc8bb91bSFelipe Balbi pm_runtime_mark_last_busy(dev); 1333fc8bb91bSFelipe Balbi pm_runtime_autosuspend(dev); 1334fc8bb91bSFelipe Balbi 1335fc8bb91bSFelipe Balbi return 0; 1336fc8bb91bSFelipe Balbi } 1337fc8bb91bSFelipe Balbi #endif /* CONFIG_PM */ 1338fc8bb91bSFelipe Balbi 1339fc8bb91bSFelipe Balbi #ifdef CONFIG_PM_SLEEP 1340fc8bb91bSFelipe Balbi static int dwc3_suspend(struct device *dev) 1341fc8bb91bSFelipe Balbi { 1342fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1343fc8bb91bSFelipe Balbi int ret; 1344fc8bb91bSFelipe Balbi 1345fc8bb91bSFelipe Balbi ret = dwc3_suspend_common(dwc); 1346fc8bb91bSFelipe Balbi if (ret) 1347fc8bb91bSFelipe Balbi return ret; 1348fc8bb91bSFelipe Balbi 13496344475fSSekhar Nori pinctrl_pm_select_sleep_state(dev); 13506344475fSSekhar Nori 13517415f17cSFelipe Balbi return 0; 13527415f17cSFelipe Balbi } 13537415f17cSFelipe Balbi 13547415f17cSFelipe Balbi static int dwc3_resume(struct device *dev) 13557415f17cSFelipe Balbi { 13567415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 135757303488SKishon Vijay Abraham I int ret; 13587415f17cSFelipe Balbi 13596344475fSSekhar Nori pinctrl_pm_select_default_state(dev); 13606344475fSSekhar Nori 1361fc8bb91bSFelipe Balbi ret = dwc3_resume_common(dwc); 136251f5d49aSFelipe Balbi if (ret) 13635c4ad318SFelipe Balbi return ret; 13645c4ad318SFelipe Balbi 13657415f17cSFelipe Balbi pm_runtime_disable(dev); 13667415f17cSFelipe Balbi pm_runtime_set_active(dev); 13677415f17cSFelipe Balbi pm_runtime_enable(dev); 13687415f17cSFelipe Balbi 13697415f17cSFelipe Balbi return 0; 13707415f17cSFelipe Balbi } 13717f370ed0SFelipe Balbi #endif /* CONFIG_PM_SLEEP */ 13727415f17cSFelipe Balbi 13737415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = { 13747415f17cSFelipe Balbi SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 1375fc8bb91bSFelipe Balbi SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume, 1376fc8bb91bSFelipe Balbi dwc3_runtime_idle) 13777415f17cSFelipe Balbi }; 13787415f17cSFelipe Balbi 13795088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF 13805088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = { 13815088b6f5SKishon Vijay Abraham I { 138222a5aa17SFelipe Balbi .compatible = "snps,dwc3" 138322a5aa17SFelipe Balbi }, 138422a5aa17SFelipe Balbi { 13855088b6f5SKishon Vijay Abraham I .compatible = "synopsys,dwc3" 13865088b6f5SKishon Vijay Abraham I }, 13875088b6f5SKishon Vijay Abraham I { }, 13885088b6f5SKishon Vijay Abraham I }; 13895088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match); 13905088b6f5SKishon Vijay Abraham I #endif 13915088b6f5SKishon Vijay Abraham I 1392404905a6SHeikki Krogerus #ifdef CONFIG_ACPI 1393404905a6SHeikki Krogerus 1394404905a6SHeikki Krogerus #define ACPI_ID_INTEL_BSW "808622B7" 1395404905a6SHeikki Krogerus 1396404905a6SHeikki Krogerus static const struct acpi_device_id dwc3_acpi_match[] = { 1397404905a6SHeikki Krogerus { ACPI_ID_INTEL_BSW, 0 }, 1398404905a6SHeikki Krogerus { }, 1399404905a6SHeikki Krogerus }; 1400404905a6SHeikki Krogerus MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match); 1401404905a6SHeikki Krogerus #endif 1402404905a6SHeikki Krogerus 140372246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 140472246da4SFelipe Balbi .probe = dwc3_probe, 14057690417dSBill Pemberton .remove = dwc3_remove, 140672246da4SFelipe Balbi .driver = { 140772246da4SFelipe Balbi .name = "dwc3", 14085088b6f5SKishon Vijay Abraham I .of_match_table = of_match_ptr(of_dwc3_match), 1409404905a6SHeikki Krogerus .acpi_match_table = ACPI_PTR(dwc3_acpi_match), 14107f370ed0SFelipe Balbi .pm = &dwc3_dev_pm_ops, 141172246da4SFelipe Balbi }, 141272246da4SFelipe Balbi }; 141372246da4SFelipe Balbi 1414b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 1415b1116dccSTobias Klauser 14167ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 141772246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 14185945f789SFelipe Balbi MODULE_LICENSE("GPL v2"); 141972246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 1420