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; 3081407bf13SFelipe Balbi dwc3_trace(trace_dwc3_core, 3091407bf13SFelipe Balbi "Event buf %p dma %08llx length %d\n", 31072246da4SFelipe Balbi evt->buf, (unsigned long long) evt->dma, 31172246da4SFelipe Balbi evt->length); 31272246da4SFelipe Balbi 3137acd85e0SPaul Zimmerman evt->lpos = 0; 3147acd85e0SPaul Zimmerman 315660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 31672246da4SFelipe Balbi lower_32_bits(evt->dma)); 317660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 31872246da4SFelipe Balbi upper_32_bits(evt->dma)); 319660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), 32068d6a01bSFelipe Balbi DWC3_GEVNTSIZ_SIZE(evt->length)); 321660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 32272246da4SFelipe Balbi 32372246da4SFelipe Balbi return 0; 32472246da4SFelipe Balbi } 32572246da4SFelipe Balbi 32672246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 32772246da4SFelipe Balbi { 32872246da4SFelipe Balbi struct dwc3_event_buffer *evt; 32972246da4SFelipe Balbi 330696c8b12SFelipe Balbi evt = dwc->ev_buf; 3317acd85e0SPaul Zimmerman 3327acd85e0SPaul Zimmerman evt->lpos = 0; 3337acd85e0SPaul Zimmerman 334660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 0); 335660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 0); 336660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK 33768d6a01bSFelipe Balbi | DWC3_GEVNTSIZ_SIZE(0)); 338660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 33972246da4SFelipe Balbi } 34072246da4SFelipe Balbi 3410ffcaf37SFelipe Balbi static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) 3420ffcaf37SFelipe Balbi { 3430ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3440ffcaf37SFelipe Balbi return 0; 3450ffcaf37SFelipe Balbi 3460ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3470ffcaf37SFelipe Balbi return 0; 3480ffcaf37SFelipe Balbi 3490ffcaf37SFelipe Balbi dwc->scratchbuf = kmalloc_array(dwc->nr_scratch, 3500ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, GFP_KERNEL); 3510ffcaf37SFelipe Balbi if (!dwc->scratchbuf) 3520ffcaf37SFelipe Balbi return -ENOMEM; 3530ffcaf37SFelipe Balbi 3540ffcaf37SFelipe Balbi return 0; 3550ffcaf37SFelipe Balbi } 3560ffcaf37SFelipe Balbi 3570ffcaf37SFelipe Balbi static int dwc3_setup_scratch_buffers(struct dwc3 *dwc) 3580ffcaf37SFelipe Balbi { 3590ffcaf37SFelipe Balbi dma_addr_t scratch_addr; 3600ffcaf37SFelipe Balbi u32 param; 3610ffcaf37SFelipe Balbi int ret; 3620ffcaf37SFelipe Balbi 3630ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3640ffcaf37SFelipe Balbi return 0; 3650ffcaf37SFelipe Balbi 3660ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3670ffcaf37SFelipe Balbi return 0; 3680ffcaf37SFelipe Balbi 3690ffcaf37SFelipe Balbi /* should never fall here */ 3700ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 3710ffcaf37SFelipe Balbi return 0; 3720ffcaf37SFelipe Balbi 3730ffcaf37SFelipe Balbi scratch_addr = dma_map_single(dwc->dev, dwc->scratchbuf, 3740ffcaf37SFelipe Balbi dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, 3750ffcaf37SFelipe Balbi DMA_BIDIRECTIONAL); 3760ffcaf37SFelipe Balbi if (dma_mapping_error(dwc->dev, scratch_addr)) { 3770ffcaf37SFelipe Balbi dev_err(dwc->dev, "failed to map scratch buffer\n"); 3780ffcaf37SFelipe Balbi ret = -EFAULT; 3790ffcaf37SFelipe Balbi goto err0; 3800ffcaf37SFelipe Balbi } 3810ffcaf37SFelipe Balbi 3820ffcaf37SFelipe Balbi dwc->scratch_addr = scratch_addr; 3830ffcaf37SFelipe Balbi 3840ffcaf37SFelipe Balbi param = lower_32_bits(scratch_addr); 3850ffcaf37SFelipe Balbi 3860ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3870ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param); 3880ffcaf37SFelipe Balbi if (ret < 0) 3890ffcaf37SFelipe Balbi goto err1; 3900ffcaf37SFelipe Balbi 3910ffcaf37SFelipe Balbi param = upper_32_bits(scratch_addr); 3920ffcaf37SFelipe Balbi 3930ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3940ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param); 3950ffcaf37SFelipe Balbi if (ret < 0) 3960ffcaf37SFelipe Balbi goto err1; 3970ffcaf37SFelipe Balbi 3980ffcaf37SFelipe Balbi return 0; 3990ffcaf37SFelipe Balbi 4000ffcaf37SFelipe Balbi err1: 4010ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 4020ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 4030ffcaf37SFelipe Balbi 4040ffcaf37SFelipe Balbi err0: 4050ffcaf37SFelipe Balbi return ret; 4060ffcaf37SFelipe Balbi } 4070ffcaf37SFelipe Balbi 4080ffcaf37SFelipe Balbi static void dwc3_free_scratch_buffers(struct dwc3 *dwc) 4090ffcaf37SFelipe Balbi { 4100ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 4110ffcaf37SFelipe Balbi return; 4120ffcaf37SFelipe Balbi 4130ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 4140ffcaf37SFelipe Balbi return; 4150ffcaf37SFelipe Balbi 4160ffcaf37SFelipe Balbi /* should never fall here */ 4170ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 4180ffcaf37SFelipe Balbi return; 4190ffcaf37SFelipe Balbi 4200ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 4210ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 4220ffcaf37SFelipe Balbi kfree(dwc->scratchbuf); 4230ffcaf37SFelipe Balbi } 4240ffcaf37SFelipe Balbi 425789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc) 426789451f6SFelipe Balbi { 427789451f6SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 428789451f6SFelipe Balbi 429789451f6SFelipe Balbi dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); 430789451f6SFelipe Balbi dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; 431789451f6SFelipe Balbi 43273815280SFelipe Balbi dwc3_trace(trace_dwc3_core, "found %d IN and %d OUT endpoints", 433789451f6SFelipe Balbi dwc->num_in_eps, dwc->num_out_eps); 434789451f6SFelipe Balbi } 435789451f6SFelipe Balbi 43641ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc) 43726ceca97SFelipe Balbi { 43826ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 43926ceca97SFelipe Balbi 44026ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 44126ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 44226ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 44326ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 44426ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 44526ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 44626ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 44726ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 44826ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 44926ceca97SFelipe Balbi } 45026ceca97SFelipe Balbi 45172246da4SFelipe Balbi /** 452b5a65c40SHuang Rui * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core 453b5a65c40SHuang Rui * @dwc: Pointer to our controller context structure 45488bc9d19SHeikki Krogerus * 45588bc9d19SHeikki Krogerus * Returns 0 on success. The USB PHY interfaces are configured but not 45688bc9d19SHeikki Krogerus * initialized. The PHY interfaces and the PHYs get initialized together with 45788bc9d19SHeikki Krogerus * the core in dwc3_core_init. 458b5a65c40SHuang Rui */ 45988bc9d19SHeikki Krogerus static int dwc3_phy_setup(struct dwc3 *dwc) 460b5a65c40SHuang Rui { 461b5a65c40SHuang Rui u32 reg; 46288bc9d19SHeikki Krogerus int ret; 463b5a65c40SHuang Rui 464b5a65c40SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 465b5a65c40SHuang Rui 4662164a476SHuang Rui /* 4672164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY 4682164a476SHuang Rui * to '0' during coreConsultant configuration. So default value 4692164a476SHuang Rui * will be '0' when the core is reset. Application needs to set it 4702164a476SHuang Rui * to '1' after the core initialization is completed. 4712164a476SHuang Rui */ 4722164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 4732164a476SHuang Rui reg |= DWC3_GUSB3PIPECTL_SUSPHY; 4742164a476SHuang Rui 475b5a65c40SHuang Rui if (dwc->u2ss_inp3_quirk) 476b5a65c40SHuang Rui reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; 477b5a65c40SHuang Rui 478e58dd357SRajesh Bhagat if (dwc->dis_rxdet_inp3_quirk) 479e58dd357SRajesh Bhagat reg |= DWC3_GUSB3PIPECTL_DISRXDETINP3; 480e58dd357SRajesh Bhagat 481df31f5b3SHuang Rui if (dwc->req_p1p2p3_quirk) 482df31f5b3SHuang Rui reg |= DWC3_GUSB3PIPECTL_REQP1P2P3; 483df31f5b3SHuang Rui 484a2a1d0f5SHuang Rui if (dwc->del_p1p2p3_quirk) 485a2a1d0f5SHuang Rui reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN; 486a2a1d0f5SHuang Rui 48741c06ffdSHuang Rui if (dwc->del_phy_power_chg_quirk) 48841c06ffdSHuang Rui reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE; 48941c06ffdSHuang Rui 490fb67afcaSHuang Rui if (dwc->lfps_filter_quirk) 491fb67afcaSHuang Rui reg |= DWC3_GUSB3PIPECTL_LFPSFILT; 492fb67afcaSHuang Rui 49314f4ac53SHuang Rui if (dwc->rx_detect_poll_quirk) 49414f4ac53SHuang Rui reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL; 49514f4ac53SHuang Rui 4966b6a0c9aSHuang Rui if (dwc->tx_de_emphasis_quirk) 4976b6a0c9aSHuang Rui reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); 4986b6a0c9aSHuang Rui 499cd72f890SFelipe Balbi if (dwc->dis_u3_susphy_quirk) 50059acfa20SHuang Rui reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 50159acfa20SHuang Rui 50200fe081dSWilliam Wu if (dwc->dis_del_phy_power_chg_quirk) 50300fe081dSWilliam Wu reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE; 50400fe081dSWilliam Wu 505b5a65c40SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 506b5a65c40SHuang Rui 5072164a476SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 5082164a476SHuang Rui 5093e10a2ceSHeikki Krogerus /* Select the HS PHY interface */ 5103e10a2ceSHeikki Krogerus switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) { 5113e10a2ceSHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI: 51243cacb03SFelipe Balbi if (dwc->hsphy_interface && 51343cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "utmi", 4)) { 5143e10a2ceSHeikki Krogerus reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI; 51588bc9d19SHeikki Krogerus break; 51643cacb03SFelipe Balbi } else if (dwc->hsphy_interface && 51743cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "ulpi", 4)) { 5183e10a2ceSHeikki Krogerus reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI; 51988bc9d19SHeikki Krogerus dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 5203e10a2ceSHeikki Krogerus } else { 52188bc9d19SHeikki Krogerus /* Relying on default value. */ 52288bc9d19SHeikki Krogerus if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) 5233e10a2ceSHeikki Krogerus break; 5243e10a2ceSHeikki Krogerus } 5253e10a2ceSHeikki Krogerus /* FALLTHROUGH */ 52688bc9d19SHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: 52788bc9d19SHeikki Krogerus /* Making sure the interface and PHY are operational */ 52888bc9d19SHeikki Krogerus ret = dwc3_soft_reset(dwc); 52988bc9d19SHeikki Krogerus if (ret) 53088bc9d19SHeikki Krogerus return ret; 53188bc9d19SHeikki Krogerus 53288bc9d19SHeikki Krogerus udelay(1); 53388bc9d19SHeikki Krogerus 53488bc9d19SHeikki Krogerus ret = dwc3_ulpi_init(dwc); 53588bc9d19SHeikki Krogerus if (ret) 53688bc9d19SHeikki Krogerus return ret; 53788bc9d19SHeikki Krogerus /* FALLTHROUGH */ 5383e10a2ceSHeikki Krogerus default: 5393e10a2ceSHeikki Krogerus break; 5403e10a2ceSHeikki Krogerus } 5413e10a2ceSHeikki Krogerus 54232f2ed86SWilliam Wu switch (dwc->hsphy_mode) { 54332f2ed86SWilliam Wu case USBPHY_INTERFACE_MODE_UTMI: 54432f2ed86SWilliam Wu reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | 54532f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); 54632f2ed86SWilliam Wu reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) | 54732f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT); 54832f2ed86SWilliam Wu break; 54932f2ed86SWilliam Wu case USBPHY_INTERFACE_MODE_UTMIW: 55032f2ed86SWilliam Wu reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | 55132f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); 55232f2ed86SWilliam Wu reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) | 55332f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT); 55432f2ed86SWilliam Wu break; 55532f2ed86SWilliam Wu default: 55632f2ed86SWilliam Wu break; 55732f2ed86SWilliam Wu } 55832f2ed86SWilliam Wu 5592164a476SHuang Rui /* 5602164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to 5612164a476SHuang Rui * '0' during coreConsultant configuration. So default value will 5622164a476SHuang Rui * be '0' when the core is reset. Application needs to set it to 5632164a476SHuang Rui * '1' after the core initialization is completed. 5642164a476SHuang Rui */ 5652164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 5662164a476SHuang Rui reg |= DWC3_GUSB2PHYCFG_SUSPHY; 5672164a476SHuang Rui 568cd72f890SFelipe Balbi if (dwc->dis_u2_susphy_quirk) 5690effe0a3SHuang Rui reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 5700effe0a3SHuang Rui 571ec791d14SJohn Youn if (dwc->dis_enblslpm_quirk) 572ec791d14SJohn Youn reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; 573ec791d14SJohn Youn 57416199f33SWilliam Wu if (dwc->dis_u2_freeclk_exists_quirk) 57516199f33SWilliam Wu reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS; 57616199f33SWilliam Wu 5772164a476SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 57888bc9d19SHeikki Krogerus 57988bc9d19SHeikki Krogerus return 0; 580b5a65c40SHuang Rui } 581b5a65c40SHuang Rui 582c499ff71SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 583c499ff71SFelipe Balbi { 584c499ff71SFelipe Balbi dwc3_event_buffers_cleanup(dwc); 585c499ff71SFelipe Balbi 586c499ff71SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 587c499ff71SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 588c499ff71SFelipe Balbi phy_exit(dwc->usb2_generic_phy); 589c499ff71SFelipe Balbi phy_exit(dwc->usb3_generic_phy); 590c499ff71SFelipe Balbi 591c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 1); 592c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 1); 593c499ff71SFelipe Balbi phy_power_off(dwc->usb2_generic_phy); 594c499ff71SFelipe Balbi phy_power_off(dwc->usb3_generic_phy); 595c499ff71SFelipe Balbi } 596c499ff71SFelipe Balbi 597b5a65c40SHuang Rui /** 59872246da4SFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 59972246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 60072246da4SFelipe Balbi * 60172246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 60272246da4SFelipe Balbi */ 60341ac7b3aSBill Pemberton static int dwc3_core_init(struct dwc3 *dwc) 60472246da4SFelipe Balbi { 6050ffcaf37SFelipe Balbi u32 hwparams4 = dwc->hwparams.hwparams4; 60672246da4SFelipe Balbi u32 reg; 60772246da4SFelipe Balbi int ret; 60872246da4SFelipe Balbi 6097650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 6107650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 611690fb371SJohn Youn if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) { 612690fb371SJohn Youn /* Detected DWC_usb3 IP */ 613690fb371SJohn Youn dwc->revision = reg; 614690fb371SJohn Youn } else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) { 615690fb371SJohn Youn /* Detected DWC_usb31 IP */ 616690fb371SJohn Youn dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); 617690fb371SJohn Youn dwc->revision |= DWC3_REVISION_IS_DWC31; 618690fb371SJohn Youn } else { 6197650bd74SSebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 6207650bd74SSebastian Andrzej Siewior ret = -ENODEV; 6217650bd74SSebastian Andrzej Siewior goto err0; 6227650bd74SSebastian Andrzej Siewior } 6237650bd74SSebastian Andrzej Siewior 624fa0ea13eSFelipe Balbi /* 625fa0ea13eSFelipe Balbi * Write Linux Version Code to our GUID register so it's easy to figure 626fa0ea13eSFelipe Balbi * out which kernel version a bug was found. 627fa0ea13eSFelipe Balbi */ 628fa0ea13eSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); 629fa0ea13eSFelipe Balbi 6300e1e5c47SPaul Zimmerman /* Handle USB2.0-only core configuration */ 6310e1e5c47SPaul Zimmerman if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 6320e1e5c47SPaul Zimmerman DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { 6330e1e5c47SPaul Zimmerman if (dwc->maximum_speed == USB_SPEED_SUPER) 6340e1e5c47SPaul Zimmerman dwc->maximum_speed = USB_SPEED_HIGH; 6350e1e5c47SPaul Zimmerman } 6360e1e5c47SPaul Zimmerman 63772246da4SFelipe Balbi /* issue device SoftReset too */ 638c5cc74e8SHeikki Krogerus ret = dwc3_soft_reset(dwc); 639c5cc74e8SHeikki Krogerus if (ret) 64072246da4SFelipe Balbi goto err0; 64172246da4SFelipe Balbi 64257303488SKishon Vijay Abraham I ret = dwc3_core_soft_reset(dwc); 64357303488SKishon Vijay Abraham I if (ret) 64457303488SKishon Vijay Abraham I goto err0; 64558a0f23fSPratyush Anand 646c499ff71SFelipe Balbi ret = dwc3_phy_setup(dwc); 647c499ff71SFelipe Balbi if (ret) 648c499ff71SFelipe Balbi goto err0; 649c499ff71SFelipe Balbi 6504878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 6513e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 6524878a028SSebastian Andrzej Siewior 653164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 6544878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 65532a4a135SFelipe Balbi /** 65632a4a135SFelipe Balbi * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an 65732a4a135SFelipe Balbi * issue which would cause xHCI compliance tests to fail. 65832a4a135SFelipe Balbi * 65932a4a135SFelipe Balbi * Because of that we cannot enable clock gating on such 66032a4a135SFelipe Balbi * configurations. 66132a4a135SFelipe Balbi * 66232a4a135SFelipe Balbi * Refers to: 66332a4a135SFelipe Balbi * 66432a4a135SFelipe Balbi * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based 66532a4a135SFelipe Balbi * SOF/ITP Mode Used 66632a4a135SFelipe Balbi */ 66732a4a135SFelipe Balbi if ((dwc->dr_mode == USB_DR_MODE_HOST || 66832a4a135SFelipe Balbi dwc->dr_mode == USB_DR_MODE_OTG) && 66932a4a135SFelipe Balbi (dwc->revision >= DWC3_REVISION_210A && 67032a4a135SFelipe Balbi dwc->revision <= DWC3_REVISION_250A)) 67132a4a135SFelipe Balbi reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; 67232a4a135SFelipe Balbi else 6734878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 6744878a028SSebastian Andrzej Siewior break; 6750ffcaf37SFelipe Balbi case DWC3_GHWPARAMS1_EN_PWROPT_HIB: 6760ffcaf37SFelipe Balbi /* enable hibernation here */ 6770ffcaf37SFelipe Balbi dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); 6782eac3992SHuang Rui 6792eac3992SHuang Rui /* 6802eac3992SHuang Rui * REVISIT Enabling this bit so that host-mode hibernation 6812eac3992SHuang Rui * will work. Device-mode hibernation is not yet implemented. 6822eac3992SHuang Rui */ 6832eac3992SHuang Rui reg |= DWC3_GCTL_GBLHIBERNATIONEN; 6840ffcaf37SFelipe Balbi break; 6854878a028SSebastian Andrzej Siewior default: 6861407bf13SFelipe Balbi dwc3_trace(trace_dwc3_core, "No power optimization available\n"); 6874878a028SSebastian Andrzej Siewior } 6884878a028SSebastian Andrzej Siewior 689946bd579SHuang Rui /* check if current dwc3 is on simulation board */ 690946bd579SHuang Rui if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { 6911407bf13SFelipe Balbi dwc3_trace(trace_dwc3_core, 6921407bf13SFelipe Balbi "running on FPGA platform\n"); 693946bd579SHuang Rui dwc->is_fpga = true; 694946bd579SHuang Rui } 695946bd579SHuang Rui 6963b81221aSHuang Rui WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga, 6973b81221aSHuang Rui "disable_scramble cannot be used on non-FPGA builds\n"); 6983b81221aSHuang Rui 6993b81221aSHuang Rui if (dwc->disable_scramble_quirk && dwc->is_fpga) 7003b81221aSHuang Rui reg |= DWC3_GCTL_DISSCRAMBLE; 7013b81221aSHuang Rui else 7023b81221aSHuang Rui reg &= ~DWC3_GCTL_DISSCRAMBLE; 7033b81221aSHuang Rui 7049a5b2f31SHuang Rui if (dwc->u2exit_lfps_quirk) 7059a5b2f31SHuang Rui reg |= DWC3_GCTL_U2EXIT_LFPS; 7069a5b2f31SHuang Rui 7074878a028SSebastian Andrzej Siewior /* 7084878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 7091d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 7104878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 7111d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 7124878a028SSebastian Andrzej Siewior */ 7134878a028SSebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 7144878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 7154878a028SSebastian Andrzej Siewior 7164878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 7174878a028SSebastian Andrzej Siewior 718c499ff71SFelipe Balbi dwc3_core_num_eps(dwc); 7190ffcaf37SFelipe Balbi 7200ffcaf37SFelipe Balbi ret = dwc3_setup_scratch_buffers(dwc); 7210ffcaf37SFelipe Balbi if (ret) 722c499ff71SFelipe Balbi goto err1; 723c499ff71SFelipe Balbi 724c499ff71SFelipe Balbi /* Adjust Frame Length */ 725c499ff71SFelipe Balbi dwc3_frame_length_adjustment(dwc); 726c499ff71SFelipe Balbi 727c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 0); 728c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 0); 729c499ff71SFelipe Balbi ret = phy_power_on(dwc->usb2_generic_phy); 730c499ff71SFelipe Balbi if (ret < 0) 7310ffcaf37SFelipe Balbi goto err2; 7320ffcaf37SFelipe Balbi 733c499ff71SFelipe Balbi ret = phy_power_on(dwc->usb3_generic_phy); 734c499ff71SFelipe Balbi if (ret < 0) 735c499ff71SFelipe Balbi goto err3; 736c499ff71SFelipe Balbi 737c499ff71SFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 738c499ff71SFelipe Balbi if (ret) { 739c499ff71SFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 740c499ff71SFelipe Balbi goto err4; 741c499ff71SFelipe Balbi } 742c499ff71SFelipe Balbi 74300af6233SBaolin Wang switch (dwc->dr_mode) { 74400af6233SBaolin Wang case USB_DR_MODE_PERIPHERAL: 74500af6233SBaolin Wang dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); 74600af6233SBaolin Wang break; 74700af6233SBaolin Wang case USB_DR_MODE_HOST: 74800af6233SBaolin Wang dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); 74900af6233SBaolin Wang break; 75000af6233SBaolin Wang case USB_DR_MODE_OTG: 75100af6233SBaolin Wang dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); 75200af6233SBaolin Wang break; 75300af6233SBaolin Wang default: 75400af6233SBaolin Wang dev_warn(dwc->dev, "Unsupported mode %d\n", dwc->dr_mode); 75500af6233SBaolin Wang break; 75600af6233SBaolin Wang } 75700af6233SBaolin Wang 75806281d46SJohn Youn /* 75906281d46SJohn Youn * ENDXFER polling is available on version 3.10a and later of 76006281d46SJohn Youn * the DWC_usb3 controller. It is NOT available in the 76106281d46SJohn Youn * DWC_usb31 controller. 76206281d46SJohn Youn */ 76306281d46SJohn Youn if (!dwc3_is_usb31(dwc) && dwc->revision >= DWC3_REVISION_310A) { 76406281d46SJohn Youn reg = dwc3_readl(dwc->regs, DWC3_GUCTL2); 76506281d46SJohn Youn reg |= DWC3_GUCTL2_RST_ACTBITLATER; 76606281d46SJohn Youn dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); 76706281d46SJohn Youn } 76806281d46SJohn Youn 76972246da4SFelipe Balbi return 0; 77072246da4SFelipe Balbi 771c499ff71SFelipe Balbi err4: 772c499ff71SFelipe Balbi phy_power_off(dwc->usb2_generic_phy); 773c499ff71SFelipe Balbi 774c499ff71SFelipe Balbi err3: 775c499ff71SFelipe Balbi phy_power_off(dwc->usb3_generic_phy); 776c499ff71SFelipe Balbi 7770ffcaf37SFelipe Balbi err2: 778c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 1); 779c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 1); 780c499ff71SFelipe Balbi dwc3_core_exit(dwc); 7810ffcaf37SFelipe Balbi 7820ffcaf37SFelipe Balbi err1: 7830ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 7840ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 78557303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 78657303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 7870ffcaf37SFelipe Balbi 78872246da4SFelipe Balbi err0: 78972246da4SFelipe Balbi return ret; 79072246da4SFelipe Balbi } 79172246da4SFelipe Balbi 7923c9f94acSFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc) 79372246da4SFelipe Balbi { 7943c9f94acSFelipe Balbi struct device *dev = dwc->dev; 795941ea361SFelipe Balbi struct device_node *node = dev->of_node; 7963c9f94acSFelipe Balbi int ret; 79772246da4SFelipe Balbi 7985088b6f5SKishon Vijay Abraham I if (node) { 7995088b6f5SKishon Vijay Abraham I dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); 8005088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); 801bb674907SFelipe Balbi } else { 802bb674907SFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 803bb674907SFelipe Balbi dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 8045088b6f5SKishon Vijay Abraham I } 8055088b6f5SKishon Vijay Abraham I 806d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb2_phy)) { 807d105e7f8SFelipe Balbi ret = PTR_ERR(dwc->usb2_phy); 808122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 809122f06e6SKishon Vijay Abraham I dwc->usb2_phy = NULL; 810122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 811d105e7f8SFelipe Balbi return ret; 812122f06e6SKishon Vijay Abraham I } else { 81351e1e7bcSFelipe Balbi dev_err(dev, "no usb2 phy configured\n"); 814122f06e6SKishon Vijay Abraham I return ret; 815122f06e6SKishon Vijay Abraham I } 81651e1e7bcSFelipe Balbi } 81751e1e7bcSFelipe Balbi 818d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb3_phy)) { 819315955d7SRuchika Kharwar ret = PTR_ERR(dwc->usb3_phy); 820122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 821122f06e6SKishon Vijay Abraham I dwc->usb3_phy = NULL; 822122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 823d105e7f8SFelipe Balbi return ret; 824122f06e6SKishon Vijay Abraham I } else { 82551e1e7bcSFelipe Balbi dev_err(dev, "no usb3 phy configured\n"); 826122f06e6SKishon Vijay Abraham I return ret; 827122f06e6SKishon Vijay Abraham I } 82851e1e7bcSFelipe Balbi } 82951e1e7bcSFelipe Balbi 83057303488SKishon Vijay Abraham I dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); 83157303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb2_generic_phy)) { 83257303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb2_generic_phy); 83357303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 83457303488SKishon Vijay Abraham I dwc->usb2_generic_phy = NULL; 83557303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 83657303488SKishon Vijay Abraham I return ret; 83757303488SKishon Vijay Abraham I } else { 83857303488SKishon Vijay Abraham I dev_err(dev, "no usb2 phy configured\n"); 83957303488SKishon Vijay Abraham I return ret; 84057303488SKishon Vijay Abraham I } 84157303488SKishon Vijay Abraham I } 84257303488SKishon Vijay Abraham I 84357303488SKishon Vijay Abraham I dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy"); 84457303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb3_generic_phy)) { 84557303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb3_generic_phy); 84657303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 84757303488SKishon Vijay Abraham I dwc->usb3_generic_phy = NULL; 84857303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 84957303488SKishon Vijay Abraham I return ret; 85057303488SKishon Vijay Abraham I } else { 85157303488SKishon Vijay Abraham I dev_err(dev, "no usb3 phy configured\n"); 85257303488SKishon Vijay Abraham I return ret; 85357303488SKishon Vijay Abraham I } 85457303488SKishon Vijay Abraham I } 85557303488SKishon Vijay Abraham I 8563c9f94acSFelipe Balbi return 0; 8573c9f94acSFelipe Balbi } 8583c9f94acSFelipe Balbi 8595f94adfeSFelipe Balbi static int dwc3_core_init_mode(struct dwc3 *dwc) 8605f94adfeSFelipe Balbi { 8615f94adfeSFelipe Balbi struct device *dev = dwc->dev; 8625f94adfeSFelipe Balbi int ret; 8635f94adfeSFelipe Balbi 8645f94adfeSFelipe Balbi switch (dwc->dr_mode) { 8655f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 8665f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 8675f94adfeSFelipe Balbi if (ret) { 8689522def4SRoger Quadros if (ret != -EPROBE_DEFER) 8695f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 8705f94adfeSFelipe Balbi return ret; 8715f94adfeSFelipe Balbi } 8725f94adfeSFelipe Balbi break; 8735f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 8745f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 8755f94adfeSFelipe Balbi if (ret) { 8769522def4SRoger Quadros if (ret != -EPROBE_DEFER) 8775f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 8785f94adfeSFelipe Balbi return ret; 8795f94adfeSFelipe Balbi } 8805f94adfeSFelipe Balbi break; 8815f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 8825f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 8835f94adfeSFelipe Balbi if (ret) { 8849522def4SRoger Quadros if (ret != -EPROBE_DEFER) 8855f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 8865f94adfeSFelipe Balbi return ret; 8875f94adfeSFelipe Balbi } 8885f94adfeSFelipe Balbi 8895f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 8905f94adfeSFelipe Balbi if (ret) { 8919522def4SRoger Quadros if (ret != -EPROBE_DEFER) 8925f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 8935f94adfeSFelipe Balbi return ret; 8945f94adfeSFelipe Balbi } 8955f94adfeSFelipe Balbi break; 8965f94adfeSFelipe Balbi default: 8975f94adfeSFelipe Balbi dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); 8985f94adfeSFelipe Balbi return -EINVAL; 8995f94adfeSFelipe Balbi } 9005f94adfeSFelipe Balbi 9015f94adfeSFelipe Balbi return 0; 9025f94adfeSFelipe Balbi } 9035f94adfeSFelipe Balbi 9045f94adfeSFelipe Balbi static void dwc3_core_exit_mode(struct dwc3 *dwc) 9055f94adfeSFelipe Balbi { 9065f94adfeSFelipe Balbi switch (dwc->dr_mode) { 9075f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 9085f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 9095f94adfeSFelipe Balbi break; 9105f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 9115f94adfeSFelipe Balbi dwc3_host_exit(dwc); 9125f94adfeSFelipe Balbi break; 9135f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 9145f94adfeSFelipe Balbi dwc3_host_exit(dwc); 9155f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 9165f94adfeSFelipe Balbi break; 9175f94adfeSFelipe Balbi default: 9185f94adfeSFelipe Balbi /* do nothing */ 9195f94adfeSFelipe Balbi break; 9205f94adfeSFelipe Balbi } 9215f94adfeSFelipe Balbi } 9225f94adfeSFelipe Balbi 9233c9f94acSFelipe Balbi #define DWC3_ALIGN_MASK (16 - 1) 9243c9f94acSFelipe Balbi 9253c9f94acSFelipe Balbi static int dwc3_probe(struct platform_device *pdev) 9263c9f94acSFelipe Balbi { 9273c9f94acSFelipe Balbi struct device *dev = &pdev->dev; 9283c9f94acSFelipe Balbi struct resource *res; 9293c9f94acSFelipe Balbi struct dwc3 *dwc; 93080caf7d2SHuang Rui u8 lpm_nyet_threshold; 9316b6a0c9aSHuang Rui u8 tx_de_emphasis; 932460d098cSHuang Rui u8 hird_threshold; 9333c9f94acSFelipe Balbi 934b09e99eeSAndy Shevchenko int ret; 9353c9f94acSFelipe Balbi 9363c9f94acSFelipe Balbi void __iomem *regs; 9373c9f94acSFelipe Balbi void *mem; 9383c9f94acSFelipe Balbi 9393c9f94acSFelipe Balbi mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 940734d5a53SJingoo Han if (!mem) 9413c9f94acSFelipe Balbi return -ENOMEM; 942734d5a53SJingoo Han 9433c9f94acSFelipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 9443c9f94acSFelipe Balbi dwc->mem = mem; 9453c9f94acSFelipe Balbi dwc->dev = dev; 9463c9f94acSFelipe Balbi 9473c9f94acSFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 9483c9f94acSFelipe Balbi if (!res) { 9493c9f94acSFelipe Balbi dev_err(dev, "missing memory resource\n"); 9503c9f94acSFelipe Balbi return -ENODEV; 9513c9f94acSFelipe Balbi } 9523c9f94acSFelipe Balbi 953f32a5e23SVivek Gautam dwc->xhci_resources[0].start = res->start; 954f32a5e23SVivek Gautam dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 955f32a5e23SVivek Gautam DWC3_XHCI_REGS_END; 956f32a5e23SVivek Gautam dwc->xhci_resources[0].flags = res->flags; 957f32a5e23SVivek Gautam dwc->xhci_resources[0].name = res->name; 958f32a5e23SVivek Gautam 959f32a5e23SVivek Gautam res->start += DWC3_GLOBALS_REGS_START; 960f32a5e23SVivek Gautam 961f32a5e23SVivek Gautam /* 962f32a5e23SVivek Gautam * Request memory region but exclude xHCI regs, 963f32a5e23SVivek Gautam * since it will be requested by the xhci-plat driver. 964f32a5e23SVivek Gautam */ 965f32a5e23SVivek Gautam regs = devm_ioremap_resource(dev, res); 9663da1f6eeSFelipe Balbi if (IS_ERR(regs)) { 9673da1f6eeSFelipe Balbi ret = PTR_ERR(regs); 9683da1f6eeSFelipe Balbi goto err0; 9693da1f6eeSFelipe Balbi } 970f32a5e23SVivek Gautam 971f32a5e23SVivek Gautam dwc->regs = regs; 972f32a5e23SVivek Gautam dwc->regs_size = resource_size(res); 973f32a5e23SVivek Gautam 97480caf7d2SHuang Rui /* default to highest possible threshold */ 97580caf7d2SHuang Rui lpm_nyet_threshold = 0xff; 97680caf7d2SHuang Rui 9776b6a0c9aSHuang Rui /* default to -3.5dB de-emphasis */ 9786b6a0c9aSHuang Rui tx_de_emphasis = 1; 9796b6a0c9aSHuang Rui 980460d098cSHuang Rui /* 981460d098cSHuang Rui * default to assert utmi_sleep_n and use maximum allowed HIRD 982460d098cSHuang Rui * threshold value of 0b1100 983460d098cSHuang Rui */ 984460d098cSHuang Rui hird_threshold = 12; 985460d098cSHuang Rui 98663863b98SHeikki Krogerus dwc->maximum_speed = usb_get_maximum_speed(dev); 98706e7114fSHeikki Krogerus dwc->dr_mode = usb_get_dr_mode(dev); 98832f2ed86SWilliam Wu dwc->hsphy_mode = of_usb_get_phy_mode(dev->of_node); 98963863b98SHeikki Krogerus 9903d128919SHeikki Krogerus dwc->has_lpm_erratum = device_property_read_bool(dev, 99180caf7d2SHuang Rui "snps,has-lpm-erratum"); 9923d128919SHeikki Krogerus device_property_read_u8(dev, "snps,lpm-nyet-threshold", 99380caf7d2SHuang Rui &lpm_nyet_threshold); 9943d128919SHeikki Krogerus dwc->is_utmi_l1_suspend = device_property_read_bool(dev, 995460d098cSHuang Rui "snps,is-utmi-l1-suspend"); 9963d128919SHeikki Krogerus device_property_read_u8(dev, "snps,hird-threshold", 997460d098cSHuang Rui &hird_threshold); 9983d128919SHeikki Krogerus dwc->usb3_lpm_capable = device_property_read_bool(dev, 999eac68e8fSRobert Baldyga "snps,usb3_lpm_capable"); 10003c9f94acSFelipe Balbi 10013d128919SHeikki Krogerus dwc->disable_scramble_quirk = device_property_read_bool(dev, 10023b81221aSHuang Rui "snps,disable_scramble_quirk"); 10033d128919SHeikki Krogerus dwc->u2exit_lfps_quirk = device_property_read_bool(dev, 10049a5b2f31SHuang Rui "snps,u2exit_lfps_quirk"); 10053d128919SHeikki Krogerus dwc->u2ss_inp3_quirk = device_property_read_bool(dev, 1006b5a65c40SHuang Rui "snps,u2ss_inp3_quirk"); 10073d128919SHeikki Krogerus dwc->req_p1p2p3_quirk = device_property_read_bool(dev, 1008df31f5b3SHuang Rui "snps,req_p1p2p3_quirk"); 10093d128919SHeikki Krogerus dwc->del_p1p2p3_quirk = device_property_read_bool(dev, 1010a2a1d0f5SHuang Rui "snps,del_p1p2p3_quirk"); 10113d128919SHeikki Krogerus dwc->del_phy_power_chg_quirk = device_property_read_bool(dev, 101241c06ffdSHuang Rui "snps,del_phy_power_chg_quirk"); 10133d128919SHeikki Krogerus dwc->lfps_filter_quirk = device_property_read_bool(dev, 1014fb67afcaSHuang Rui "snps,lfps_filter_quirk"); 10153d128919SHeikki Krogerus dwc->rx_detect_poll_quirk = device_property_read_bool(dev, 101614f4ac53SHuang Rui "snps,rx_detect_poll_quirk"); 10173d128919SHeikki Krogerus dwc->dis_u3_susphy_quirk = device_property_read_bool(dev, 101859acfa20SHuang Rui "snps,dis_u3_susphy_quirk"); 10193d128919SHeikki Krogerus dwc->dis_u2_susphy_quirk = device_property_read_bool(dev, 10200effe0a3SHuang Rui "snps,dis_u2_susphy_quirk"); 1021ec791d14SJohn Youn dwc->dis_enblslpm_quirk = device_property_read_bool(dev, 1022ec791d14SJohn Youn "snps,dis_enblslpm_quirk"); 1023e58dd357SRajesh Bhagat dwc->dis_rxdet_inp3_quirk = device_property_read_bool(dev, 1024e58dd357SRajesh Bhagat "snps,dis_rxdet_inp3_quirk"); 102516199f33SWilliam Wu dwc->dis_u2_freeclk_exists_quirk = device_property_read_bool(dev, 102616199f33SWilliam Wu "snps,dis-u2-freeclk-exists-quirk"); 102700fe081dSWilliam Wu dwc->dis_del_phy_power_chg_quirk = device_property_read_bool(dev, 102800fe081dSWilliam Wu "snps,dis-del-phy-power-chg-quirk"); 10296b6a0c9aSHuang Rui 10303d128919SHeikki Krogerus dwc->tx_de_emphasis_quirk = device_property_read_bool(dev, 10316b6a0c9aSHuang Rui "snps,tx_de_emphasis_quirk"); 10323d128919SHeikki Krogerus device_property_read_u8(dev, "snps,tx_de_emphasis", 10336b6a0c9aSHuang Rui &tx_de_emphasis); 10343d128919SHeikki Krogerus device_property_read_string(dev, "snps,hsphy_interface", 10353e10a2ceSHeikki Krogerus &dwc->hsphy_interface); 10363d128919SHeikki Krogerus device_property_read_u32(dev, "snps,quirk-frame-length-adjustment", 1037bcdb3272SFelipe Balbi &dwc->fladj); 10383d128919SHeikki Krogerus 103980caf7d2SHuang Rui dwc->lpm_nyet_threshold = lpm_nyet_threshold; 10406b6a0c9aSHuang Rui dwc->tx_de_emphasis = tx_de_emphasis; 104180caf7d2SHuang Rui 1042460d098cSHuang Rui dwc->hird_threshold = hird_threshold 1043460d098cSHuang Rui | (dwc->is_utmi_l1_suspend << 4); 1044460d098cSHuang Rui 10456c89cce0SHeikki Krogerus platform_set_drvdata(pdev, dwc); 10462917e718SHeikki Krogerus dwc3_cache_hwparams(dwc); 10476c89cce0SHeikki Krogerus 10483c9f94acSFelipe Balbi ret = dwc3_core_get_phy(dwc); 10493c9f94acSFelipe Balbi if (ret) 10503da1f6eeSFelipe Balbi goto err0; 10513c9f94acSFelipe Balbi 105272246da4SFelipe Balbi spin_lock_init(&dwc->lock); 105372246da4SFelipe Balbi 105419bacdc9SHeikki Krogerus if (!dev->dma_mask) { 1055ddff14f1SKishon Vijay Abraham I dev->dma_mask = dev->parent->dma_mask; 1056ddff14f1SKishon Vijay Abraham I dev->dma_parms = dev->parent->dma_parms; 1057ddff14f1SKishon Vijay Abraham I dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); 105819bacdc9SHeikki Krogerus } 1059ddff14f1SKishon Vijay Abraham I 1060fc8bb91bSFelipe Balbi pm_runtime_set_active(dev); 1061fc8bb91bSFelipe Balbi pm_runtime_use_autosuspend(dev); 1062fc8bb91bSFelipe Balbi pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY); 1063802ca850SChanho Park pm_runtime_enable(dev); 106432808237SRoger Quadros ret = pm_runtime_get_sync(dev); 106532808237SRoger Quadros if (ret < 0) 106632808237SRoger Quadros goto err1; 106732808237SRoger Quadros 1068802ca850SChanho Park pm_runtime_forbid(dev); 106972246da4SFelipe Balbi 10703921426bSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 10713921426bSFelipe Balbi if (ret) { 10723921426bSFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 10733921426bSFelipe Balbi ret = -ENOMEM; 107432808237SRoger Quadros goto err2; 10753921426bSFelipe Balbi } 10763921426bSFelipe Balbi 10779d6173e1SThinh Nguyen ret = dwc3_get_dr_mode(dwc); 10789d6173e1SThinh Nguyen if (ret) 10799d6173e1SThinh Nguyen goto err3; 108032a4a135SFelipe Balbi 1081c499ff71SFelipe Balbi ret = dwc3_alloc_scratch_buffers(dwc); 1082c499ff71SFelipe Balbi if (ret) 108332808237SRoger Quadros goto err3; 1084c499ff71SFelipe Balbi 108572246da4SFelipe Balbi ret = dwc3_core_init(dwc); 108672246da4SFelipe Balbi if (ret) { 1087802ca850SChanho Park dev_err(dev, "failed to initialize core\n"); 108832808237SRoger Quadros goto err4; 108972246da4SFelipe Balbi } 109072246da4SFelipe Balbi 109177966eb8SJohn Youn /* Check the maximum_speed parameter */ 109277966eb8SJohn Youn switch (dwc->maximum_speed) { 109377966eb8SJohn Youn case USB_SPEED_LOW: 109477966eb8SJohn Youn case USB_SPEED_FULL: 109577966eb8SJohn Youn case USB_SPEED_HIGH: 109677966eb8SJohn Youn case USB_SPEED_SUPER: 109777966eb8SJohn Youn case USB_SPEED_SUPER_PLUS: 109877966eb8SJohn Youn break; 109977966eb8SJohn Youn default: 110077966eb8SJohn Youn dev_err(dev, "invalid maximum_speed parameter %d\n", 110177966eb8SJohn Youn dwc->maximum_speed); 110277966eb8SJohn Youn /* fall through */ 110377966eb8SJohn Youn case USB_SPEED_UNKNOWN: 110477966eb8SJohn Youn /* default to superspeed */ 11052c7f1bd9SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER; 11062c7f1bd9SJohn Youn 11072c7f1bd9SJohn Youn /* 11082c7f1bd9SJohn Youn * default to superspeed plus if we are capable. 11092c7f1bd9SJohn Youn */ 11102c7f1bd9SJohn Youn if (dwc3_is_usb31(dwc) && 11112c7f1bd9SJohn Youn (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 11122c7f1bd9SJohn Youn DWC3_GHWPARAMS3_SSPHY_IFC_GEN2)) 11132c7f1bd9SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER_PLUS; 111477966eb8SJohn Youn 111577966eb8SJohn Youn break; 11162c7f1bd9SJohn Youn } 11172c7f1bd9SJohn Youn 11185f94adfeSFelipe Balbi ret = dwc3_core_init_mode(dwc); 11195f94adfeSFelipe Balbi if (ret) 112032808237SRoger Quadros goto err5; 112172246da4SFelipe Balbi 11224e9f3118SDu, Changbin dwc3_debugfs_init(dwc); 1123fc8bb91bSFelipe Balbi pm_runtime_put(dev); 112472246da4SFelipe Balbi 112572246da4SFelipe Balbi return 0; 112672246da4SFelipe Balbi 112732808237SRoger Quadros err5: 1128f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 1129f122d33eSFelipe Balbi 113032808237SRoger Quadros err4: 1131c499ff71SFelipe Balbi dwc3_free_scratch_buffers(dwc); 113272246da4SFelipe Balbi 113332808237SRoger Quadros err3: 11343921426bSFelipe Balbi dwc3_free_event_buffers(dwc); 113588bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 11363921426bSFelipe Balbi 113732808237SRoger Quadros err2: 113832808237SRoger Quadros pm_runtime_allow(&pdev->dev); 113932808237SRoger Quadros 114032808237SRoger Quadros err1: 114132808237SRoger Quadros pm_runtime_put_sync(&pdev->dev); 114232808237SRoger Quadros pm_runtime_disable(&pdev->dev); 114332808237SRoger Quadros 11443da1f6eeSFelipe Balbi err0: 11453da1f6eeSFelipe Balbi /* 11463da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 11473da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 11483da1f6eeSFelipe Balbi * memory region the next time probe is called. 11493da1f6eeSFelipe Balbi */ 11503da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 11513da1f6eeSFelipe Balbi 115272246da4SFelipe Balbi return ret; 115372246da4SFelipe Balbi } 115472246da4SFelipe Balbi 1155fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev) 115672246da4SFelipe Balbi { 115772246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 11583da1f6eeSFelipe Balbi struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 11593da1f6eeSFelipe Balbi 1160fc8bb91bSFelipe Balbi pm_runtime_get_sync(&pdev->dev); 11613da1f6eeSFelipe Balbi /* 11623da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 11633da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 11643da1f6eeSFelipe Balbi * memory region the next time probe is called. 11653da1f6eeSFelipe Balbi */ 11663da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 116772246da4SFelipe Balbi 1168dc99f16fSFelipe Balbi dwc3_debugfs_exit(dwc); 1169dc99f16fSFelipe Balbi dwc3_core_exit_mode(dwc); 11708ba007a9SKishon Vijay Abraham I 117172246da4SFelipe Balbi dwc3_core_exit(dwc); 117288bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 117372246da4SFelipe Balbi 1174fc8bb91bSFelipe Balbi pm_runtime_put_sync(&pdev->dev); 1175fc8bb91bSFelipe Balbi pm_runtime_allow(&pdev->dev); 1176fc8bb91bSFelipe Balbi pm_runtime_disable(&pdev->dev); 1177fc8bb91bSFelipe Balbi 1178c499ff71SFelipe Balbi dwc3_free_event_buffers(dwc); 1179c499ff71SFelipe Balbi dwc3_free_scratch_buffers(dwc); 1180c499ff71SFelipe Balbi 118172246da4SFelipe Balbi return 0; 118272246da4SFelipe Balbi } 118372246da4SFelipe Balbi 1184fc8bb91bSFelipe Balbi #ifdef CONFIG_PM 1185fc8bb91bSFelipe Balbi static int dwc3_suspend_common(struct dwc3 *dwc) 11867415f17cSFelipe Balbi { 1187fc8bb91bSFelipe Balbi unsigned long flags; 11887415f17cSFelipe Balbi 1189a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 1190a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 1191a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 1192fc8bb91bSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 11937415f17cSFelipe Balbi dwc3_gadget_suspend(dwc); 1194fc8bb91bSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 119551f5d49aSFelipe Balbi break; 1196a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 11977415f17cSFelipe Balbi default: 119851f5d49aSFelipe Balbi /* do nothing */ 11997415f17cSFelipe Balbi break; 12007415f17cSFelipe Balbi } 12017415f17cSFelipe Balbi 120251f5d49aSFelipe Balbi dwc3_core_exit(dwc); 12035c4ad318SFelipe Balbi 1204fc8bb91bSFelipe Balbi return 0; 1205fc8bb91bSFelipe Balbi } 1206fc8bb91bSFelipe Balbi 1207fc8bb91bSFelipe Balbi static int dwc3_resume_common(struct dwc3 *dwc) 1208fc8bb91bSFelipe Balbi { 1209fc8bb91bSFelipe Balbi unsigned long flags; 1210fc8bb91bSFelipe Balbi int ret; 1211fc8bb91bSFelipe Balbi 1212fc8bb91bSFelipe Balbi ret = dwc3_core_init(dwc); 1213fc8bb91bSFelipe Balbi if (ret) 1214fc8bb91bSFelipe Balbi return ret; 1215fc8bb91bSFelipe Balbi 1216fc8bb91bSFelipe Balbi switch (dwc->dr_mode) { 1217fc8bb91bSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 1218fc8bb91bSFelipe Balbi case USB_DR_MODE_OTG: 1219fc8bb91bSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 1220fc8bb91bSFelipe Balbi dwc3_gadget_resume(dwc); 1221fc8bb91bSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 1222fc8bb91bSFelipe Balbi /* FALLTHROUGH */ 1223fc8bb91bSFelipe Balbi case USB_DR_MODE_HOST: 1224fc8bb91bSFelipe Balbi default: 1225fc8bb91bSFelipe Balbi /* do nothing */ 1226fc8bb91bSFelipe Balbi break; 1227fc8bb91bSFelipe Balbi } 1228fc8bb91bSFelipe Balbi 1229fc8bb91bSFelipe Balbi return 0; 1230fc8bb91bSFelipe Balbi } 1231fc8bb91bSFelipe Balbi 1232fc8bb91bSFelipe Balbi static int dwc3_runtime_checks(struct dwc3 *dwc) 1233fc8bb91bSFelipe Balbi { 1234fc8bb91bSFelipe Balbi switch (dwc->dr_mode) { 1235fc8bb91bSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 1236fc8bb91bSFelipe Balbi case USB_DR_MODE_OTG: 1237fc8bb91bSFelipe Balbi if (dwc->connected) 1238fc8bb91bSFelipe Balbi return -EBUSY; 1239fc8bb91bSFelipe Balbi break; 1240fc8bb91bSFelipe Balbi case USB_DR_MODE_HOST: 1241fc8bb91bSFelipe Balbi default: 1242fc8bb91bSFelipe Balbi /* do nothing */ 1243fc8bb91bSFelipe Balbi break; 1244fc8bb91bSFelipe Balbi } 1245fc8bb91bSFelipe Balbi 1246fc8bb91bSFelipe Balbi return 0; 1247fc8bb91bSFelipe Balbi } 1248fc8bb91bSFelipe Balbi 1249fc8bb91bSFelipe Balbi static int dwc3_runtime_suspend(struct device *dev) 1250fc8bb91bSFelipe Balbi { 1251fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1252fc8bb91bSFelipe Balbi int ret; 1253fc8bb91bSFelipe Balbi 1254fc8bb91bSFelipe Balbi if (dwc3_runtime_checks(dwc)) 1255fc8bb91bSFelipe Balbi return -EBUSY; 1256fc8bb91bSFelipe Balbi 1257fc8bb91bSFelipe Balbi ret = dwc3_suspend_common(dwc); 1258fc8bb91bSFelipe Balbi if (ret) 1259fc8bb91bSFelipe Balbi return ret; 1260fc8bb91bSFelipe Balbi 1261fc8bb91bSFelipe Balbi device_init_wakeup(dev, true); 1262fc8bb91bSFelipe Balbi 1263fc8bb91bSFelipe Balbi return 0; 1264fc8bb91bSFelipe Balbi } 1265fc8bb91bSFelipe Balbi 1266fc8bb91bSFelipe Balbi static int dwc3_runtime_resume(struct device *dev) 1267fc8bb91bSFelipe Balbi { 1268fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1269fc8bb91bSFelipe Balbi int ret; 1270fc8bb91bSFelipe Balbi 1271fc8bb91bSFelipe Balbi device_init_wakeup(dev, false); 1272fc8bb91bSFelipe Balbi 1273fc8bb91bSFelipe Balbi ret = dwc3_resume_common(dwc); 1274fc8bb91bSFelipe Balbi if (ret) 1275fc8bb91bSFelipe Balbi return ret; 1276fc8bb91bSFelipe Balbi 1277fc8bb91bSFelipe Balbi switch (dwc->dr_mode) { 1278fc8bb91bSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 1279fc8bb91bSFelipe Balbi case USB_DR_MODE_OTG: 1280fc8bb91bSFelipe Balbi dwc3_gadget_process_pending_events(dwc); 1281fc8bb91bSFelipe Balbi break; 1282fc8bb91bSFelipe Balbi case USB_DR_MODE_HOST: 1283fc8bb91bSFelipe Balbi default: 1284fc8bb91bSFelipe Balbi /* do nothing */ 1285fc8bb91bSFelipe Balbi break; 1286fc8bb91bSFelipe Balbi } 1287fc8bb91bSFelipe Balbi 1288fc8bb91bSFelipe Balbi pm_runtime_mark_last_busy(dev); 1289fc8bb91bSFelipe Balbi 1290fc8bb91bSFelipe Balbi return 0; 1291fc8bb91bSFelipe Balbi } 1292fc8bb91bSFelipe Balbi 1293fc8bb91bSFelipe Balbi static int dwc3_runtime_idle(struct device *dev) 1294fc8bb91bSFelipe Balbi { 1295fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1296fc8bb91bSFelipe Balbi 1297fc8bb91bSFelipe Balbi switch (dwc->dr_mode) { 1298fc8bb91bSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 1299fc8bb91bSFelipe Balbi case USB_DR_MODE_OTG: 1300fc8bb91bSFelipe Balbi if (dwc3_runtime_checks(dwc)) 1301fc8bb91bSFelipe Balbi return -EBUSY; 1302fc8bb91bSFelipe Balbi break; 1303fc8bb91bSFelipe Balbi case USB_DR_MODE_HOST: 1304fc8bb91bSFelipe Balbi default: 1305fc8bb91bSFelipe Balbi /* do nothing */ 1306fc8bb91bSFelipe Balbi break; 1307fc8bb91bSFelipe Balbi } 1308fc8bb91bSFelipe Balbi 1309fc8bb91bSFelipe Balbi pm_runtime_mark_last_busy(dev); 1310fc8bb91bSFelipe Balbi pm_runtime_autosuspend(dev); 1311fc8bb91bSFelipe Balbi 1312fc8bb91bSFelipe Balbi return 0; 1313fc8bb91bSFelipe Balbi } 1314fc8bb91bSFelipe Balbi #endif /* CONFIG_PM */ 1315fc8bb91bSFelipe Balbi 1316fc8bb91bSFelipe Balbi #ifdef CONFIG_PM_SLEEP 1317fc8bb91bSFelipe Balbi static int dwc3_suspend(struct device *dev) 1318fc8bb91bSFelipe Balbi { 1319fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1320fc8bb91bSFelipe Balbi int ret; 1321fc8bb91bSFelipe Balbi 1322fc8bb91bSFelipe Balbi ret = dwc3_suspend_common(dwc); 1323fc8bb91bSFelipe Balbi if (ret) 1324fc8bb91bSFelipe Balbi return ret; 1325fc8bb91bSFelipe Balbi 13266344475fSSekhar Nori pinctrl_pm_select_sleep_state(dev); 13276344475fSSekhar Nori 13287415f17cSFelipe Balbi return 0; 13297415f17cSFelipe Balbi } 13307415f17cSFelipe Balbi 13317415f17cSFelipe Balbi static int dwc3_resume(struct device *dev) 13327415f17cSFelipe Balbi { 13337415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 133457303488SKishon Vijay Abraham I int ret; 13357415f17cSFelipe Balbi 13366344475fSSekhar Nori pinctrl_pm_select_default_state(dev); 13376344475fSSekhar Nori 1338fc8bb91bSFelipe Balbi ret = dwc3_resume_common(dwc); 133951f5d49aSFelipe Balbi if (ret) 13405c4ad318SFelipe Balbi return ret; 13415c4ad318SFelipe Balbi 13427415f17cSFelipe Balbi pm_runtime_disable(dev); 13437415f17cSFelipe Balbi pm_runtime_set_active(dev); 13447415f17cSFelipe Balbi pm_runtime_enable(dev); 13457415f17cSFelipe Balbi 13467415f17cSFelipe Balbi return 0; 13477415f17cSFelipe Balbi } 13487f370ed0SFelipe Balbi #endif /* CONFIG_PM_SLEEP */ 13497415f17cSFelipe Balbi 13507415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = { 13517415f17cSFelipe Balbi SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 1352fc8bb91bSFelipe Balbi SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume, 1353fc8bb91bSFelipe Balbi dwc3_runtime_idle) 13547415f17cSFelipe Balbi }; 13557415f17cSFelipe Balbi 13565088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF 13575088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = { 13585088b6f5SKishon Vijay Abraham I { 135922a5aa17SFelipe Balbi .compatible = "snps,dwc3" 136022a5aa17SFelipe Balbi }, 136122a5aa17SFelipe Balbi { 13625088b6f5SKishon Vijay Abraham I .compatible = "synopsys,dwc3" 13635088b6f5SKishon Vijay Abraham I }, 13645088b6f5SKishon Vijay Abraham I { }, 13655088b6f5SKishon Vijay Abraham I }; 13665088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match); 13675088b6f5SKishon Vijay Abraham I #endif 13685088b6f5SKishon Vijay Abraham I 1369404905a6SHeikki Krogerus #ifdef CONFIG_ACPI 1370404905a6SHeikki Krogerus 1371404905a6SHeikki Krogerus #define ACPI_ID_INTEL_BSW "808622B7" 1372404905a6SHeikki Krogerus 1373404905a6SHeikki Krogerus static const struct acpi_device_id dwc3_acpi_match[] = { 1374404905a6SHeikki Krogerus { ACPI_ID_INTEL_BSW, 0 }, 1375404905a6SHeikki Krogerus { }, 1376404905a6SHeikki Krogerus }; 1377404905a6SHeikki Krogerus MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match); 1378404905a6SHeikki Krogerus #endif 1379404905a6SHeikki Krogerus 138072246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 138172246da4SFelipe Balbi .probe = dwc3_probe, 13827690417dSBill Pemberton .remove = dwc3_remove, 138372246da4SFelipe Balbi .driver = { 138472246da4SFelipe Balbi .name = "dwc3", 13855088b6f5SKishon Vijay Abraham I .of_match_table = of_match_ptr(of_dwc3_match), 1386404905a6SHeikki Krogerus .acpi_match_table = ACPI_PTR(dwc3_acpi_match), 13877f370ed0SFelipe Balbi .pm = &dwc3_dev_pm_ops, 138872246da4SFelipe Balbi }, 138972246da4SFelipe Balbi }; 139072246da4SFelipe Balbi 1391b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 1392b1116dccSTobias Klauser 13937ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 139472246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 13955945f789SFelipe Balbi MODULE_LICENSE("GPL v2"); 139672246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 1397