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 523140e8cbSSebastian Andrzej Siewior void dwc3_set_mode(struct dwc3 *dwc, u32 mode) 533140e8cbSSebastian Andrzej Siewior { 543140e8cbSSebastian Andrzej Siewior u32 reg; 553140e8cbSSebastian Andrzej Siewior 563140e8cbSSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 573140e8cbSSebastian Andrzej Siewior reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); 583140e8cbSSebastian Andrzej Siewior reg |= DWC3_GCTL_PRTCAPDIR(mode); 593140e8cbSSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 603140e8cbSSebastian Andrzej Siewior } 618300dd23SFelipe Balbi 62cf6d867dSFelipe Balbi u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type) 63cf6d867dSFelipe Balbi { 64cf6d867dSFelipe Balbi struct dwc3 *dwc = dep->dwc; 65cf6d867dSFelipe Balbi u32 reg; 66cf6d867dSFelipe Balbi 67cf6d867dSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GDBGFIFOSPACE, 68cf6d867dSFelipe Balbi DWC3_GDBGFIFOSPACE_NUM(dep->number) | 69cf6d867dSFelipe Balbi DWC3_GDBGFIFOSPACE_TYPE(type)); 70cf6d867dSFelipe Balbi 71cf6d867dSFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GDBGFIFOSPACE); 72cf6d867dSFelipe Balbi 73cf6d867dSFelipe Balbi return DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(reg); 74cf6d867dSFelipe Balbi } 75cf6d867dSFelipe Balbi 7672246da4SFelipe Balbi /** 7772246da4SFelipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 7872246da4SFelipe Balbi * @dwc: pointer to our context structure 7972246da4SFelipe Balbi */ 8057303488SKishon Vijay Abraham I static int dwc3_core_soft_reset(struct dwc3 *dwc) 8172246da4SFelipe Balbi { 8272246da4SFelipe Balbi u32 reg; 83f59dcab1SFelipe Balbi int retries = 1000; 8457303488SKishon Vijay Abraham I int ret; 8572246da4SFelipe Balbi 8651e1e7bcSFelipe Balbi usb_phy_init(dwc->usb2_phy); 8751e1e7bcSFelipe Balbi usb_phy_init(dwc->usb3_phy); 8857303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 8957303488SKishon Vijay Abraham I if (ret < 0) 9057303488SKishon Vijay Abraham I return ret; 9157303488SKishon Vijay Abraham I 9257303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 9357303488SKishon Vijay Abraham I if (ret < 0) { 9457303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 9557303488SKishon Vijay Abraham I return ret; 9657303488SKishon Vijay Abraham I } 9772246da4SFelipe Balbi 98f59dcab1SFelipe Balbi /* 99f59dcab1SFelipe Balbi * We're resetting only the device side because, if we're in host mode, 100f59dcab1SFelipe Balbi * XHCI driver will reset the host block. If dwc3 was configured for 101f59dcab1SFelipe Balbi * host-only mode, then we can return early. 102f59dcab1SFelipe Balbi */ 103f59dcab1SFelipe Balbi if (dwc->dr_mode == USB_DR_MODE_HOST) 10457303488SKishon Vijay Abraham I return 0; 105f59dcab1SFelipe Balbi 106f59dcab1SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 107f59dcab1SFelipe Balbi reg |= DWC3_DCTL_CSFTRST; 108f59dcab1SFelipe Balbi dwc3_writel(dwc->regs, DWC3_DCTL, reg); 109f59dcab1SFelipe Balbi 110f59dcab1SFelipe Balbi do { 111f59dcab1SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 112f59dcab1SFelipe Balbi if (!(reg & DWC3_DCTL_CSFTRST)) 113f59dcab1SFelipe Balbi return 0; 114f59dcab1SFelipe Balbi 115f59dcab1SFelipe Balbi udelay(1); 116f59dcab1SFelipe Balbi } while (--retries); 117f59dcab1SFelipe Balbi 118f59dcab1SFelipe Balbi return -ETIMEDOUT; 11972246da4SFelipe Balbi } 12072246da4SFelipe Balbi 12172246da4SFelipe Balbi /** 122c5cc74e8SHeikki Krogerus * dwc3_soft_reset - Issue soft reset 123c5cc74e8SHeikki Krogerus * @dwc: Pointer to our controller context structure 124c5cc74e8SHeikki Krogerus */ 125c5cc74e8SHeikki Krogerus static int dwc3_soft_reset(struct dwc3 *dwc) 126c5cc74e8SHeikki Krogerus { 127c5cc74e8SHeikki Krogerus unsigned long timeout; 128c5cc74e8SHeikki Krogerus u32 reg; 129c5cc74e8SHeikki Krogerus 130c5cc74e8SHeikki Krogerus timeout = jiffies + msecs_to_jiffies(500); 131c5cc74e8SHeikki Krogerus dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); 132c5cc74e8SHeikki Krogerus do { 133c5cc74e8SHeikki Krogerus reg = dwc3_readl(dwc->regs, DWC3_DCTL); 134c5cc74e8SHeikki Krogerus if (!(reg & DWC3_DCTL_CSFTRST)) 135c5cc74e8SHeikki Krogerus break; 136c5cc74e8SHeikki Krogerus 137c5cc74e8SHeikki Krogerus if (time_after(jiffies, timeout)) { 138c5cc74e8SHeikki Krogerus dev_err(dwc->dev, "Reset Timed Out\n"); 139c5cc74e8SHeikki Krogerus return -ETIMEDOUT; 140c5cc74e8SHeikki Krogerus } 141c5cc74e8SHeikki Krogerus 142c5cc74e8SHeikki Krogerus cpu_relax(); 143c5cc74e8SHeikki Krogerus } while (true); 144c5cc74e8SHeikki Krogerus 145c5cc74e8SHeikki Krogerus return 0; 146c5cc74e8SHeikki Krogerus } 147c5cc74e8SHeikki Krogerus 148db2be4e9SNikhil Badola /* 149db2be4e9SNikhil Badola * dwc3_frame_length_adjustment - Adjusts frame length if required 150db2be4e9SNikhil Badola * @dwc3: Pointer to our controller context structure 151db2be4e9SNikhil Badola */ 152bcdb3272SFelipe Balbi static void dwc3_frame_length_adjustment(struct dwc3 *dwc) 153db2be4e9SNikhil Badola { 154db2be4e9SNikhil Badola u32 reg; 155db2be4e9SNikhil Badola u32 dft; 156db2be4e9SNikhil Badola 157db2be4e9SNikhil Badola if (dwc->revision < DWC3_REVISION_250A) 158db2be4e9SNikhil Badola return; 159db2be4e9SNikhil Badola 160bcdb3272SFelipe Balbi if (dwc->fladj == 0) 161db2be4e9SNikhil Badola return; 162db2be4e9SNikhil Badola 163db2be4e9SNikhil Badola reg = dwc3_readl(dwc->regs, DWC3_GFLADJ); 164db2be4e9SNikhil Badola dft = reg & DWC3_GFLADJ_30MHZ_MASK; 165bcdb3272SFelipe Balbi if (!dev_WARN_ONCE(dwc->dev, dft == dwc->fladj, 166db2be4e9SNikhil Badola "request value same as default, ignoring\n")) { 167db2be4e9SNikhil Badola reg &= ~DWC3_GFLADJ_30MHZ_MASK; 168bcdb3272SFelipe Balbi reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj; 169db2be4e9SNikhil Badola dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); 170db2be4e9SNikhil Badola } 171db2be4e9SNikhil Badola } 172db2be4e9SNikhil Badola 173c5cc74e8SHeikki Krogerus /** 17472246da4SFelipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 17572246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 17672246da4SFelipe Balbi * @evt: Pointer to event buffer to be freed 17772246da4SFelipe Balbi */ 17872246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc, 17972246da4SFelipe Balbi struct dwc3_event_buffer *evt) 18072246da4SFelipe Balbi { 18172246da4SFelipe Balbi dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); 18272246da4SFelipe Balbi } 18372246da4SFelipe Balbi 18472246da4SFelipe Balbi /** 1851d046793SPaul Zimmerman * dwc3_alloc_one_event_buffer - Allocates one event buffer structure 18672246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 18772246da4SFelipe Balbi * @length: size of the event buffer 18872246da4SFelipe Balbi * 1891d046793SPaul Zimmerman * Returns a pointer to the allocated event buffer structure on success 19072246da4SFelipe Balbi * otherwise ERR_PTR(errno). 19172246da4SFelipe Balbi */ 19267d0b500SFelipe Balbi static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, 19367d0b500SFelipe Balbi unsigned length) 19472246da4SFelipe Balbi { 19572246da4SFelipe Balbi struct dwc3_event_buffer *evt; 19672246da4SFelipe Balbi 197380f0d28SFelipe Balbi evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL); 19872246da4SFelipe Balbi if (!evt) 19972246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 20072246da4SFelipe Balbi 20172246da4SFelipe Balbi evt->dwc = dwc; 20272246da4SFelipe Balbi evt->length = length; 20372246da4SFelipe Balbi evt->buf = dma_alloc_coherent(dwc->dev, length, 20472246da4SFelipe Balbi &evt->dma, GFP_KERNEL); 205e32672f0SFelipe Balbi if (!evt->buf) 20672246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 20772246da4SFelipe Balbi 20872246da4SFelipe Balbi return evt; 20972246da4SFelipe Balbi } 21072246da4SFelipe Balbi 21172246da4SFelipe Balbi /** 21272246da4SFelipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 21372246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 21472246da4SFelipe Balbi */ 21572246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc) 21672246da4SFelipe Balbi { 21772246da4SFelipe Balbi struct dwc3_event_buffer *evt; 21872246da4SFelipe Balbi 219696c8b12SFelipe Balbi evt = dwc->ev_buf; 22064b6c8a7SAnton Tikhomirov if (evt) 22172246da4SFelipe Balbi dwc3_free_one_event_buffer(dwc, evt); 22272246da4SFelipe Balbi } 22372246da4SFelipe Balbi 22472246da4SFelipe Balbi /** 22572246da4SFelipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 2261d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 22772246da4SFelipe Balbi * @length: size of event buffer 22872246da4SFelipe Balbi * 2291d046793SPaul Zimmerman * Returns 0 on success otherwise negative errno. In the error case, dwc 23072246da4SFelipe Balbi * may contain some buffers allocated but not all which were requested. 23172246da4SFelipe Balbi */ 23241ac7b3aSBill Pemberton static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) 23372246da4SFelipe Balbi { 23472246da4SFelipe Balbi struct dwc3_event_buffer *evt; 23572246da4SFelipe Balbi 23672246da4SFelipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 23772246da4SFelipe Balbi if (IS_ERR(evt)) { 23872246da4SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 23972246da4SFelipe Balbi return PTR_ERR(evt); 24072246da4SFelipe Balbi } 241696c8b12SFelipe Balbi dwc->ev_buf = evt; 24272246da4SFelipe Balbi 24372246da4SFelipe Balbi return 0; 24472246da4SFelipe Balbi } 24572246da4SFelipe Balbi 24672246da4SFelipe Balbi /** 24772246da4SFelipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 2481d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 24972246da4SFelipe Balbi * 25072246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 25172246da4SFelipe Balbi */ 2527acd85e0SPaul Zimmerman static int dwc3_event_buffers_setup(struct dwc3 *dwc) 25372246da4SFelipe Balbi { 25472246da4SFelipe Balbi struct dwc3_event_buffer *evt; 25572246da4SFelipe Balbi 256696c8b12SFelipe Balbi evt = dwc->ev_buf; 2571407bf13SFelipe Balbi dwc3_trace(trace_dwc3_core, 2581407bf13SFelipe Balbi "Event buf %p dma %08llx length %d\n", 25972246da4SFelipe Balbi evt->buf, (unsigned long long) evt->dma, 26072246da4SFelipe Balbi evt->length); 26172246da4SFelipe Balbi 2627acd85e0SPaul Zimmerman evt->lpos = 0; 2637acd85e0SPaul Zimmerman 264660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 26572246da4SFelipe Balbi lower_32_bits(evt->dma)); 266660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 26772246da4SFelipe Balbi upper_32_bits(evt->dma)); 268660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), 26968d6a01bSFelipe Balbi DWC3_GEVNTSIZ_SIZE(evt->length)); 270660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 27172246da4SFelipe Balbi 27272246da4SFelipe Balbi return 0; 27372246da4SFelipe Balbi } 27472246da4SFelipe Balbi 27572246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 27672246da4SFelipe Balbi { 27772246da4SFelipe Balbi struct dwc3_event_buffer *evt; 27872246da4SFelipe Balbi 279696c8b12SFelipe Balbi evt = dwc->ev_buf; 2807acd85e0SPaul Zimmerman 2817acd85e0SPaul Zimmerman evt->lpos = 0; 2827acd85e0SPaul Zimmerman 283660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 0); 284660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 0); 285660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK 28668d6a01bSFelipe Balbi | DWC3_GEVNTSIZ_SIZE(0)); 287660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 28872246da4SFelipe Balbi } 28972246da4SFelipe Balbi 2900ffcaf37SFelipe Balbi static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) 2910ffcaf37SFelipe Balbi { 2920ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 2930ffcaf37SFelipe Balbi return 0; 2940ffcaf37SFelipe Balbi 2950ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 2960ffcaf37SFelipe Balbi return 0; 2970ffcaf37SFelipe Balbi 2980ffcaf37SFelipe Balbi dwc->scratchbuf = kmalloc_array(dwc->nr_scratch, 2990ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, GFP_KERNEL); 3000ffcaf37SFelipe Balbi if (!dwc->scratchbuf) 3010ffcaf37SFelipe Balbi return -ENOMEM; 3020ffcaf37SFelipe Balbi 3030ffcaf37SFelipe Balbi return 0; 3040ffcaf37SFelipe Balbi } 3050ffcaf37SFelipe Balbi 3060ffcaf37SFelipe Balbi static int dwc3_setup_scratch_buffers(struct dwc3 *dwc) 3070ffcaf37SFelipe Balbi { 3080ffcaf37SFelipe Balbi dma_addr_t scratch_addr; 3090ffcaf37SFelipe Balbi u32 param; 3100ffcaf37SFelipe Balbi int ret; 3110ffcaf37SFelipe Balbi 3120ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3130ffcaf37SFelipe Balbi return 0; 3140ffcaf37SFelipe Balbi 3150ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3160ffcaf37SFelipe Balbi return 0; 3170ffcaf37SFelipe Balbi 3180ffcaf37SFelipe Balbi /* should never fall here */ 3190ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 3200ffcaf37SFelipe Balbi return 0; 3210ffcaf37SFelipe Balbi 3220ffcaf37SFelipe Balbi scratch_addr = dma_map_single(dwc->dev, dwc->scratchbuf, 3230ffcaf37SFelipe Balbi dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, 3240ffcaf37SFelipe Balbi DMA_BIDIRECTIONAL); 3250ffcaf37SFelipe Balbi if (dma_mapping_error(dwc->dev, scratch_addr)) { 3260ffcaf37SFelipe Balbi dev_err(dwc->dev, "failed to map scratch buffer\n"); 3270ffcaf37SFelipe Balbi ret = -EFAULT; 3280ffcaf37SFelipe Balbi goto err0; 3290ffcaf37SFelipe Balbi } 3300ffcaf37SFelipe Balbi 3310ffcaf37SFelipe Balbi dwc->scratch_addr = scratch_addr; 3320ffcaf37SFelipe Balbi 3330ffcaf37SFelipe Balbi param = lower_32_bits(scratch_addr); 3340ffcaf37SFelipe Balbi 3350ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3360ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param); 3370ffcaf37SFelipe Balbi if (ret < 0) 3380ffcaf37SFelipe Balbi goto err1; 3390ffcaf37SFelipe Balbi 3400ffcaf37SFelipe Balbi param = upper_32_bits(scratch_addr); 3410ffcaf37SFelipe Balbi 3420ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3430ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param); 3440ffcaf37SFelipe Balbi if (ret < 0) 3450ffcaf37SFelipe Balbi goto err1; 3460ffcaf37SFelipe Balbi 3470ffcaf37SFelipe Balbi return 0; 3480ffcaf37SFelipe Balbi 3490ffcaf37SFelipe Balbi err1: 3500ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3510ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3520ffcaf37SFelipe Balbi 3530ffcaf37SFelipe Balbi err0: 3540ffcaf37SFelipe Balbi return ret; 3550ffcaf37SFelipe Balbi } 3560ffcaf37SFelipe Balbi 3570ffcaf37SFelipe Balbi static void dwc3_free_scratch_buffers(struct dwc3 *dwc) 3580ffcaf37SFelipe Balbi { 3590ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3600ffcaf37SFelipe Balbi return; 3610ffcaf37SFelipe Balbi 3620ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3630ffcaf37SFelipe Balbi return; 3640ffcaf37SFelipe Balbi 3650ffcaf37SFelipe Balbi /* should never fall here */ 3660ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 3670ffcaf37SFelipe Balbi return; 3680ffcaf37SFelipe Balbi 3690ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3700ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3710ffcaf37SFelipe Balbi kfree(dwc->scratchbuf); 3720ffcaf37SFelipe Balbi } 3730ffcaf37SFelipe Balbi 374789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc) 375789451f6SFelipe Balbi { 376789451f6SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 377789451f6SFelipe Balbi 378789451f6SFelipe Balbi dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); 379789451f6SFelipe Balbi dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; 380789451f6SFelipe Balbi 38173815280SFelipe Balbi dwc3_trace(trace_dwc3_core, "found %d IN and %d OUT endpoints", 382789451f6SFelipe Balbi dwc->num_in_eps, dwc->num_out_eps); 383789451f6SFelipe Balbi } 384789451f6SFelipe Balbi 38541ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc) 38626ceca97SFelipe Balbi { 38726ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 38826ceca97SFelipe Balbi 38926ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 39026ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 39126ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 39226ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 39326ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 39426ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 39526ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 39626ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 39726ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 39826ceca97SFelipe Balbi } 39926ceca97SFelipe Balbi 40072246da4SFelipe Balbi /** 401b5a65c40SHuang Rui * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core 402b5a65c40SHuang Rui * @dwc: Pointer to our controller context structure 40388bc9d19SHeikki Krogerus * 40488bc9d19SHeikki Krogerus * Returns 0 on success. The USB PHY interfaces are configured but not 40588bc9d19SHeikki Krogerus * initialized. The PHY interfaces and the PHYs get initialized together with 40688bc9d19SHeikki Krogerus * the core in dwc3_core_init. 407b5a65c40SHuang Rui */ 40888bc9d19SHeikki Krogerus static int dwc3_phy_setup(struct dwc3 *dwc) 409b5a65c40SHuang Rui { 410b5a65c40SHuang Rui u32 reg; 41188bc9d19SHeikki Krogerus int ret; 412b5a65c40SHuang Rui 413b5a65c40SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 414b5a65c40SHuang Rui 4152164a476SHuang Rui /* 4162164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY 4172164a476SHuang Rui * to '0' during coreConsultant configuration. So default value 4182164a476SHuang Rui * will be '0' when the core is reset. Application needs to set it 4192164a476SHuang Rui * to '1' after the core initialization is completed. 4202164a476SHuang Rui */ 4212164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 4222164a476SHuang Rui reg |= DWC3_GUSB3PIPECTL_SUSPHY; 4232164a476SHuang Rui 424b5a65c40SHuang Rui if (dwc->u2ss_inp3_quirk) 425b5a65c40SHuang Rui reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; 426b5a65c40SHuang Rui 427e58dd357SRajesh Bhagat if (dwc->dis_rxdet_inp3_quirk) 428e58dd357SRajesh Bhagat reg |= DWC3_GUSB3PIPECTL_DISRXDETINP3; 429e58dd357SRajesh Bhagat 430df31f5b3SHuang Rui if (dwc->req_p1p2p3_quirk) 431df31f5b3SHuang Rui reg |= DWC3_GUSB3PIPECTL_REQP1P2P3; 432df31f5b3SHuang Rui 433a2a1d0f5SHuang Rui if (dwc->del_p1p2p3_quirk) 434a2a1d0f5SHuang Rui reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN; 435a2a1d0f5SHuang Rui 43641c06ffdSHuang Rui if (dwc->del_phy_power_chg_quirk) 43741c06ffdSHuang Rui reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE; 43841c06ffdSHuang Rui 439fb67afcaSHuang Rui if (dwc->lfps_filter_quirk) 440fb67afcaSHuang Rui reg |= DWC3_GUSB3PIPECTL_LFPSFILT; 441fb67afcaSHuang Rui 44214f4ac53SHuang Rui if (dwc->rx_detect_poll_quirk) 44314f4ac53SHuang Rui reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL; 44414f4ac53SHuang Rui 4456b6a0c9aSHuang Rui if (dwc->tx_de_emphasis_quirk) 4466b6a0c9aSHuang Rui reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); 4476b6a0c9aSHuang Rui 448cd72f890SFelipe Balbi if (dwc->dis_u3_susphy_quirk) 44959acfa20SHuang Rui reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 45059acfa20SHuang Rui 451b5a65c40SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 452b5a65c40SHuang Rui 4532164a476SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 4542164a476SHuang Rui 4553e10a2ceSHeikki Krogerus /* Select the HS PHY interface */ 4563e10a2ceSHeikki Krogerus switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) { 4573e10a2ceSHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI: 45843cacb03SFelipe Balbi if (dwc->hsphy_interface && 45943cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "utmi", 4)) { 4603e10a2ceSHeikki Krogerus reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI; 46188bc9d19SHeikki Krogerus break; 46243cacb03SFelipe Balbi } else if (dwc->hsphy_interface && 46343cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "ulpi", 4)) { 4643e10a2ceSHeikki Krogerus reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI; 46588bc9d19SHeikki Krogerus dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 4663e10a2ceSHeikki Krogerus } else { 46788bc9d19SHeikki Krogerus /* Relying on default value. */ 46888bc9d19SHeikki Krogerus if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) 4693e10a2ceSHeikki Krogerus break; 4703e10a2ceSHeikki Krogerus } 4713e10a2ceSHeikki Krogerus /* FALLTHROUGH */ 47288bc9d19SHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: 47388bc9d19SHeikki Krogerus /* Making sure the interface and PHY are operational */ 47488bc9d19SHeikki Krogerus ret = dwc3_soft_reset(dwc); 47588bc9d19SHeikki Krogerus if (ret) 47688bc9d19SHeikki Krogerus return ret; 47788bc9d19SHeikki Krogerus 47888bc9d19SHeikki Krogerus udelay(1); 47988bc9d19SHeikki Krogerus 48088bc9d19SHeikki Krogerus ret = dwc3_ulpi_init(dwc); 48188bc9d19SHeikki Krogerus if (ret) 48288bc9d19SHeikki Krogerus return ret; 48388bc9d19SHeikki Krogerus /* FALLTHROUGH */ 4843e10a2ceSHeikki Krogerus default: 4853e10a2ceSHeikki Krogerus break; 4863e10a2ceSHeikki Krogerus } 4873e10a2ceSHeikki Krogerus 48832f2ed86SWilliam Wu switch (dwc->hsphy_mode) { 48932f2ed86SWilliam Wu case USBPHY_INTERFACE_MODE_UTMI: 49032f2ed86SWilliam Wu reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | 49132f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); 49232f2ed86SWilliam Wu reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_8_BIT) | 49332f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_8_BIT); 49432f2ed86SWilliam Wu break; 49532f2ed86SWilliam Wu case USBPHY_INTERFACE_MODE_UTMIW: 49632f2ed86SWilliam Wu reg &= ~(DWC3_GUSB2PHYCFG_PHYIF_MASK | 49732f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM_MASK); 49832f2ed86SWilliam Wu reg |= DWC3_GUSB2PHYCFG_PHYIF(UTMI_PHYIF_16_BIT) | 49932f2ed86SWilliam Wu DWC3_GUSB2PHYCFG_USBTRDTIM(USBTRDTIM_UTMI_16_BIT); 50032f2ed86SWilliam Wu break; 50132f2ed86SWilliam Wu default: 50232f2ed86SWilliam Wu break; 50332f2ed86SWilliam Wu } 50432f2ed86SWilliam Wu 5052164a476SHuang Rui /* 5062164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to 5072164a476SHuang Rui * '0' during coreConsultant configuration. So default value will 5082164a476SHuang Rui * be '0' when the core is reset. Application needs to set it to 5092164a476SHuang Rui * '1' after the core initialization is completed. 5102164a476SHuang Rui */ 5112164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 5122164a476SHuang Rui reg |= DWC3_GUSB2PHYCFG_SUSPHY; 5132164a476SHuang Rui 514cd72f890SFelipe Balbi if (dwc->dis_u2_susphy_quirk) 5150effe0a3SHuang Rui reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 5160effe0a3SHuang Rui 517ec791d14SJohn Youn if (dwc->dis_enblslpm_quirk) 518ec791d14SJohn Youn reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; 519ec791d14SJohn Youn 52016199f33SWilliam Wu if (dwc->dis_u2_freeclk_exists_quirk) 52116199f33SWilliam Wu reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS; 52216199f33SWilliam Wu 5232164a476SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 52488bc9d19SHeikki Krogerus 52588bc9d19SHeikki Krogerus return 0; 526b5a65c40SHuang Rui } 527b5a65c40SHuang Rui 528c499ff71SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 529c499ff71SFelipe Balbi { 530c499ff71SFelipe Balbi dwc3_event_buffers_cleanup(dwc); 531c499ff71SFelipe Balbi 532c499ff71SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 533c499ff71SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 534c499ff71SFelipe Balbi phy_exit(dwc->usb2_generic_phy); 535c499ff71SFelipe Balbi phy_exit(dwc->usb3_generic_phy); 536c499ff71SFelipe Balbi 537c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 1); 538c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 1); 539c499ff71SFelipe Balbi phy_power_off(dwc->usb2_generic_phy); 540c499ff71SFelipe Balbi phy_power_off(dwc->usb3_generic_phy); 541c499ff71SFelipe Balbi } 542c499ff71SFelipe Balbi 543b5a65c40SHuang Rui /** 54472246da4SFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 54572246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 54672246da4SFelipe Balbi * 54772246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 54872246da4SFelipe Balbi */ 54941ac7b3aSBill Pemberton static int dwc3_core_init(struct dwc3 *dwc) 55072246da4SFelipe Balbi { 5510ffcaf37SFelipe Balbi u32 hwparams4 = dwc->hwparams.hwparams4; 55272246da4SFelipe Balbi u32 reg; 55372246da4SFelipe Balbi int ret; 55472246da4SFelipe Balbi 5557650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 5567650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 557690fb371SJohn Youn if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) { 558690fb371SJohn Youn /* Detected DWC_usb3 IP */ 559690fb371SJohn Youn dwc->revision = reg; 560690fb371SJohn Youn } else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) { 561690fb371SJohn Youn /* Detected DWC_usb31 IP */ 562690fb371SJohn Youn dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); 563690fb371SJohn Youn dwc->revision |= DWC3_REVISION_IS_DWC31; 564690fb371SJohn Youn } else { 5657650bd74SSebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 5667650bd74SSebastian Andrzej Siewior ret = -ENODEV; 5677650bd74SSebastian Andrzej Siewior goto err0; 5687650bd74SSebastian Andrzej Siewior } 5697650bd74SSebastian Andrzej Siewior 570fa0ea13eSFelipe Balbi /* 571fa0ea13eSFelipe Balbi * Write Linux Version Code to our GUID register so it's easy to figure 572fa0ea13eSFelipe Balbi * out which kernel version a bug was found. 573fa0ea13eSFelipe Balbi */ 574fa0ea13eSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); 575fa0ea13eSFelipe Balbi 5760e1e5c47SPaul Zimmerman /* Handle USB2.0-only core configuration */ 5770e1e5c47SPaul Zimmerman if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 5780e1e5c47SPaul Zimmerman DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { 5790e1e5c47SPaul Zimmerman if (dwc->maximum_speed == USB_SPEED_SUPER) 5800e1e5c47SPaul Zimmerman dwc->maximum_speed = USB_SPEED_HIGH; 5810e1e5c47SPaul Zimmerman } 5820e1e5c47SPaul Zimmerman 58372246da4SFelipe Balbi /* issue device SoftReset too */ 584c5cc74e8SHeikki Krogerus ret = dwc3_soft_reset(dwc); 585c5cc74e8SHeikki Krogerus if (ret) 58672246da4SFelipe Balbi goto err0; 58772246da4SFelipe Balbi 58857303488SKishon Vijay Abraham I ret = dwc3_core_soft_reset(dwc); 58957303488SKishon Vijay Abraham I if (ret) 59057303488SKishon Vijay Abraham I goto err0; 59158a0f23fSPratyush Anand 592c499ff71SFelipe Balbi ret = dwc3_phy_setup(dwc); 593c499ff71SFelipe Balbi if (ret) 594c499ff71SFelipe Balbi goto err0; 595c499ff71SFelipe Balbi 5964878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 5973e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 5984878a028SSebastian Andrzej Siewior 599164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 6004878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 60132a4a135SFelipe Balbi /** 60232a4a135SFelipe Balbi * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an 60332a4a135SFelipe Balbi * issue which would cause xHCI compliance tests to fail. 60432a4a135SFelipe Balbi * 60532a4a135SFelipe Balbi * Because of that we cannot enable clock gating on such 60632a4a135SFelipe Balbi * configurations. 60732a4a135SFelipe Balbi * 60832a4a135SFelipe Balbi * Refers to: 60932a4a135SFelipe Balbi * 61032a4a135SFelipe Balbi * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based 61132a4a135SFelipe Balbi * SOF/ITP Mode Used 61232a4a135SFelipe Balbi */ 61332a4a135SFelipe Balbi if ((dwc->dr_mode == USB_DR_MODE_HOST || 61432a4a135SFelipe Balbi dwc->dr_mode == USB_DR_MODE_OTG) && 61532a4a135SFelipe Balbi (dwc->revision >= DWC3_REVISION_210A && 61632a4a135SFelipe Balbi dwc->revision <= DWC3_REVISION_250A)) 61732a4a135SFelipe Balbi reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; 61832a4a135SFelipe Balbi else 6194878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 6204878a028SSebastian Andrzej Siewior break; 6210ffcaf37SFelipe Balbi case DWC3_GHWPARAMS1_EN_PWROPT_HIB: 6220ffcaf37SFelipe Balbi /* enable hibernation here */ 6230ffcaf37SFelipe Balbi dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); 6242eac3992SHuang Rui 6252eac3992SHuang Rui /* 6262eac3992SHuang Rui * REVISIT Enabling this bit so that host-mode hibernation 6272eac3992SHuang Rui * will work. Device-mode hibernation is not yet implemented. 6282eac3992SHuang Rui */ 6292eac3992SHuang Rui reg |= DWC3_GCTL_GBLHIBERNATIONEN; 6300ffcaf37SFelipe Balbi break; 6314878a028SSebastian Andrzej Siewior default: 6321407bf13SFelipe Balbi dwc3_trace(trace_dwc3_core, "No power optimization available\n"); 6334878a028SSebastian Andrzej Siewior } 6344878a028SSebastian Andrzej Siewior 635946bd579SHuang Rui /* check if current dwc3 is on simulation board */ 636946bd579SHuang Rui if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { 6371407bf13SFelipe Balbi dwc3_trace(trace_dwc3_core, 6381407bf13SFelipe Balbi "running on FPGA platform\n"); 639946bd579SHuang Rui dwc->is_fpga = true; 640946bd579SHuang Rui } 641946bd579SHuang Rui 6423b81221aSHuang Rui WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga, 6433b81221aSHuang Rui "disable_scramble cannot be used on non-FPGA builds\n"); 6443b81221aSHuang Rui 6453b81221aSHuang Rui if (dwc->disable_scramble_quirk && dwc->is_fpga) 6463b81221aSHuang Rui reg |= DWC3_GCTL_DISSCRAMBLE; 6473b81221aSHuang Rui else 6483b81221aSHuang Rui reg &= ~DWC3_GCTL_DISSCRAMBLE; 6493b81221aSHuang Rui 6509a5b2f31SHuang Rui if (dwc->u2exit_lfps_quirk) 6519a5b2f31SHuang Rui reg |= DWC3_GCTL_U2EXIT_LFPS; 6529a5b2f31SHuang Rui 6534878a028SSebastian Andrzej Siewior /* 6544878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 6551d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 6564878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 6571d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 6584878a028SSebastian Andrzej Siewior */ 6594878a028SSebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 6604878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 6614878a028SSebastian Andrzej Siewior 6624878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 6634878a028SSebastian Andrzej Siewior 664c499ff71SFelipe Balbi dwc3_core_num_eps(dwc); 6650ffcaf37SFelipe Balbi 6660ffcaf37SFelipe Balbi ret = dwc3_setup_scratch_buffers(dwc); 6670ffcaf37SFelipe Balbi if (ret) 668c499ff71SFelipe Balbi goto err1; 669c499ff71SFelipe Balbi 670c499ff71SFelipe Balbi /* Adjust Frame Length */ 671c499ff71SFelipe Balbi dwc3_frame_length_adjustment(dwc); 672c499ff71SFelipe Balbi 673c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 0); 674c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 0); 675c499ff71SFelipe Balbi ret = phy_power_on(dwc->usb2_generic_phy); 676c499ff71SFelipe Balbi if (ret < 0) 6770ffcaf37SFelipe Balbi goto err2; 6780ffcaf37SFelipe Balbi 679c499ff71SFelipe Balbi ret = phy_power_on(dwc->usb3_generic_phy); 680c499ff71SFelipe Balbi if (ret < 0) 681c499ff71SFelipe Balbi goto err3; 682c499ff71SFelipe Balbi 683c499ff71SFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 684c499ff71SFelipe Balbi if (ret) { 685c499ff71SFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 686c499ff71SFelipe Balbi goto err4; 687c499ff71SFelipe Balbi } 688c499ff71SFelipe Balbi 68972246da4SFelipe Balbi return 0; 69072246da4SFelipe Balbi 691c499ff71SFelipe Balbi err4: 692c499ff71SFelipe Balbi phy_power_off(dwc->usb2_generic_phy); 693c499ff71SFelipe Balbi 694c499ff71SFelipe Balbi err3: 695c499ff71SFelipe Balbi phy_power_off(dwc->usb3_generic_phy); 696c499ff71SFelipe Balbi 6970ffcaf37SFelipe Balbi err2: 698c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 1); 699c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 1); 700c499ff71SFelipe Balbi dwc3_core_exit(dwc); 7010ffcaf37SFelipe Balbi 7020ffcaf37SFelipe Balbi err1: 7030ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 7040ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 70557303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 70657303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 7070ffcaf37SFelipe Balbi 70872246da4SFelipe Balbi err0: 70972246da4SFelipe Balbi return ret; 71072246da4SFelipe Balbi } 71172246da4SFelipe Balbi 7123c9f94acSFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc) 71372246da4SFelipe Balbi { 7143c9f94acSFelipe Balbi struct device *dev = dwc->dev; 715941ea361SFelipe Balbi struct device_node *node = dev->of_node; 7163c9f94acSFelipe Balbi int ret; 71772246da4SFelipe Balbi 7185088b6f5SKishon Vijay Abraham I if (node) { 7195088b6f5SKishon Vijay Abraham I dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); 7205088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); 721bb674907SFelipe Balbi } else { 722bb674907SFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 723bb674907SFelipe Balbi dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 7245088b6f5SKishon Vijay Abraham I } 7255088b6f5SKishon Vijay Abraham I 726d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb2_phy)) { 727d105e7f8SFelipe Balbi ret = PTR_ERR(dwc->usb2_phy); 728122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 729122f06e6SKishon Vijay Abraham I dwc->usb2_phy = NULL; 730122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 731d105e7f8SFelipe Balbi return ret; 732122f06e6SKishon Vijay Abraham I } else { 73351e1e7bcSFelipe Balbi dev_err(dev, "no usb2 phy configured\n"); 734122f06e6SKishon Vijay Abraham I return ret; 735122f06e6SKishon Vijay Abraham I } 73651e1e7bcSFelipe Balbi } 73751e1e7bcSFelipe Balbi 738d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb3_phy)) { 739315955d7SRuchika Kharwar ret = PTR_ERR(dwc->usb3_phy); 740122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 741122f06e6SKishon Vijay Abraham I dwc->usb3_phy = NULL; 742122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 743d105e7f8SFelipe Balbi return ret; 744122f06e6SKishon Vijay Abraham I } else { 74551e1e7bcSFelipe Balbi dev_err(dev, "no usb3 phy configured\n"); 746122f06e6SKishon Vijay Abraham I return ret; 747122f06e6SKishon Vijay Abraham I } 74851e1e7bcSFelipe Balbi } 74951e1e7bcSFelipe Balbi 75057303488SKishon Vijay Abraham I dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); 75157303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb2_generic_phy)) { 75257303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb2_generic_phy); 75357303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 75457303488SKishon Vijay Abraham I dwc->usb2_generic_phy = NULL; 75557303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 75657303488SKishon Vijay Abraham I return ret; 75757303488SKishon Vijay Abraham I } else { 75857303488SKishon Vijay Abraham I dev_err(dev, "no usb2 phy configured\n"); 75957303488SKishon Vijay Abraham I return ret; 76057303488SKishon Vijay Abraham I } 76157303488SKishon Vijay Abraham I } 76257303488SKishon Vijay Abraham I 76357303488SKishon Vijay Abraham I dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy"); 76457303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb3_generic_phy)) { 76557303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb3_generic_phy); 76657303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 76757303488SKishon Vijay Abraham I dwc->usb3_generic_phy = NULL; 76857303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 76957303488SKishon Vijay Abraham I return ret; 77057303488SKishon Vijay Abraham I } else { 77157303488SKishon Vijay Abraham I dev_err(dev, "no usb3 phy configured\n"); 77257303488SKishon Vijay Abraham I return ret; 77357303488SKishon Vijay Abraham I } 77457303488SKishon Vijay Abraham I } 77557303488SKishon Vijay Abraham I 7763c9f94acSFelipe Balbi return 0; 7773c9f94acSFelipe Balbi } 7783c9f94acSFelipe Balbi 7795f94adfeSFelipe Balbi static int dwc3_core_init_mode(struct dwc3 *dwc) 7805f94adfeSFelipe Balbi { 7815f94adfeSFelipe Balbi struct device *dev = dwc->dev; 7825f94adfeSFelipe Balbi int ret; 7835f94adfeSFelipe Balbi 7845f94adfeSFelipe Balbi switch (dwc->dr_mode) { 7855f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 7865f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); 7875f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 7885f94adfeSFelipe Balbi if (ret) { 7899522def4SRoger Quadros if (ret != -EPROBE_DEFER) 7905f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 7915f94adfeSFelipe Balbi return ret; 7925f94adfeSFelipe Balbi } 7935f94adfeSFelipe Balbi break; 7945f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 7955f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); 7965f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 7975f94adfeSFelipe Balbi if (ret) { 7989522def4SRoger Quadros if (ret != -EPROBE_DEFER) 7995f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 8005f94adfeSFelipe Balbi return ret; 8015f94adfeSFelipe Balbi } 8025f94adfeSFelipe Balbi break; 8035f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 8045f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); 8055f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 8065f94adfeSFelipe Balbi if (ret) { 8079522def4SRoger Quadros if (ret != -EPROBE_DEFER) 8085f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 8095f94adfeSFelipe Balbi return ret; 8105f94adfeSFelipe Balbi } 8115f94adfeSFelipe Balbi 8125f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 8135f94adfeSFelipe Balbi if (ret) { 8149522def4SRoger Quadros if (ret != -EPROBE_DEFER) 8155f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 8165f94adfeSFelipe Balbi return ret; 8175f94adfeSFelipe Balbi } 8185f94adfeSFelipe Balbi break; 8195f94adfeSFelipe Balbi default: 8205f94adfeSFelipe Balbi dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); 8215f94adfeSFelipe Balbi return -EINVAL; 8225f94adfeSFelipe Balbi } 8235f94adfeSFelipe Balbi 8245f94adfeSFelipe Balbi return 0; 8255f94adfeSFelipe Balbi } 8265f94adfeSFelipe Balbi 8275f94adfeSFelipe Balbi static void dwc3_core_exit_mode(struct dwc3 *dwc) 8285f94adfeSFelipe Balbi { 8295f94adfeSFelipe Balbi switch (dwc->dr_mode) { 8305f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 8315f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 8325f94adfeSFelipe Balbi break; 8335f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 8345f94adfeSFelipe Balbi dwc3_host_exit(dwc); 8355f94adfeSFelipe Balbi break; 8365f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 8375f94adfeSFelipe Balbi dwc3_host_exit(dwc); 8385f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 8395f94adfeSFelipe Balbi break; 8405f94adfeSFelipe Balbi default: 8415f94adfeSFelipe Balbi /* do nothing */ 8425f94adfeSFelipe Balbi break; 8435f94adfeSFelipe Balbi } 8445f94adfeSFelipe Balbi } 8455f94adfeSFelipe Balbi 8463c9f94acSFelipe Balbi #define DWC3_ALIGN_MASK (16 - 1) 8473c9f94acSFelipe Balbi 8483c9f94acSFelipe Balbi static int dwc3_probe(struct platform_device *pdev) 8493c9f94acSFelipe Balbi { 8503c9f94acSFelipe Balbi struct device *dev = &pdev->dev; 8513c9f94acSFelipe Balbi struct resource *res; 8523c9f94acSFelipe Balbi struct dwc3 *dwc; 85380caf7d2SHuang Rui u8 lpm_nyet_threshold; 8546b6a0c9aSHuang Rui u8 tx_de_emphasis; 855460d098cSHuang Rui u8 hird_threshold; 8563c9f94acSFelipe Balbi 857b09e99eeSAndy Shevchenko int ret; 8583c9f94acSFelipe Balbi 8593c9f94acSFelipe Balbi void __iomem *regs; 8603c9f94acSFelipe Balbi void *mem; 8613c9f94acSFelipe Balbi 8623c9f94acSFelipe Balbi mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 863734d5a53SJingoo Han if (!mem) 8643c9f94acSFelipe Balbi return -ENOMEM; 865734d5a53SJingoo Han 8663c9f94acSFelipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 8673c9f94acSFelipe Balbi dwc->mem = mem; 8683c9f94acSFelipe Balbi dwc->dev = dev; 8693c9f94acSFelipe Balbi 8703c9f94acSFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 8713c9f94acSFelipe Balbi if (!res) { 8723c9f94acSFelipe Balbi dev_err(dev, "missing memory resource\n"); 8733c9f94acSFelipe Balbi return -ENODEV; 8743c9f94acSFelipe Balbi } 8753c9f94acSFelipe Balbi 876f32a5e23SVivek Gautam dwc->xhci_resources[0].start = res->start; 877f32a5e23SVivek Gautam dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 878f32a5e23SVivek Gautam DWC3_XHCI_REGS_END; 879f32a5e23SVivek Gautam dwc->xhci_resources[0].flags = res->flags; 880f32a5e23SVivek Gautam dwc->xhci_resources[0].name = res->name; 881f32a5e23SVivek Gautam 882f32a5e23SVivek Gautam res->start += DWC3_GLOBALS_REGS_START; 883f32a5e23SVivek Gautam 884f32a5e23SVivek Gautam /* 885f32a5e23SVivek Gautam * Request memory region but exclude xHCI regs, 886f32a5e23SVivek Gautam * since it will be requested by the xhci-plat driver. 887f32a5e23SVivek Gautam */ 888f32a5e23SVivek Gautam regs = devm_ioremap_resource(dev, res); 8893da1f6eeSFelipe Balbi if (IS_ERR(regs)) { 8903da1f6eeSFelipe Balbi ret = PTR_ERR(regs); 8913da1f6eeSFelipe Balbi goto err0; 8923da1f6eeSFelipe Balbi } 893f32a5e23SVivek Gautam 894f32a5e23SVivek Gautam dwc->regs = regs; 895f32a5e23SVivek Gautam dwc->regs_size = resource_size(res); 896f32a5e23SVivek Gautam 89780caf7d2SHuang Rui /* default to highest possible threshold */ 89880caf7d2SHuang Rui lpm_nyet_threshold = 0xff; 89980caf7d2SHuang Rui 9006b6a0c9aSHuang Rui /* default to -3.5dB de-emphasis */ 9016b6a0c9aSHuang Rui tx_de_emphasis = 1; 9026b6a0c9aSHuang Rui 903460d098cSHuang Rui /* 904460d098cSHuang Rui * default to assert utmi_sleep_n and use maximum allowed HIRD 905460d098cSHuang Rui * threshold value of 0b1100 906460d098cSHuang Rui */ 907460d098cSHuang Rui hird_threshold = 12; 908460d098cSHuang Rui 90963863b98SHeikki Krogerus dwc->maximum_speed = usb_get_maximum_speed(dev); 91006e7114fSHeikki Krogerus dwc->dr_mode = usb_get_dr_mode(dev); 91132f2ed86SWilliam Wu dwc->hsphy_mode = of_usb_get_phy_mode(dev->of_node); 91263863b98SHeikki Krogerus 9133d128919SHeikki Krogerus dwc->has_lpm_erratum = device_property_read_bool(dev, 91480caf7d2SHuang Rui "snps,has-lpm-erratum"); 9153d128919SHeikki Krogerus device_property_read_u8(dev, "snps,lpm-nyet-threshold", 91680caf7d2SHuang Rui &lpm_nyet_threshold); 9173d128919SHeikki Krogerus dwc->is_utmi_l1_suspend = device_property_read_bool(dev, 918460d098cSHuang Rui "snps,is-utmi-l1-suspend"); 9193d128919SHeikki Krogerus device_property_read_u8(dev, "snps,hird-threshold", 920460d098cSHuang Rui &hird_threshold); 9213d128919SHeikki Krogerus dwc->usb3_lpm_capable = device_property_read_bool(dev, 922eac68e8fSRobert Baldyga "snps,usb3_lpm_capable"); 9233c9f94acSFelipe Balbi 9243d128919SHeikki Krogerus dwc->disable_scramble_quirk = device_property_read_bool(dev, 9253b81221aSHuang Rui "snps,disable_scramble_quirk"); 9263d128919SHeikki Krogerus dwc->u2exit_lfps_quirk = device_property_read_bool(dev, 9279a5b2f31SHuang Rui "snps,u2exit_lfps_quirk"); 9283d128919SHeikki Krogerus dwc->u2ss_inp3_quirk = device_property_read_bool(dev, 929b5a65c40SHuang Rui "snps,u2ss_inp3_quirk"); 9303d128919SHeikki Krogerus dwc->req_p1p2p3_quirk = device_property_read_bool(dev, 931df31f5b3SHuang Rui "snps,req_p1p2p3_quirk"); 9323d128919SHeikki Krogerus dwc->del_p1p2p3_quirk = device_property_read_bool(dev, 933a2a1d0f5SHuang Rui "snps,del_p1p2p3_quirk"); 9343d128919SHeikki Krogerus dwc->del_phy_power_chg_quirk = device_property_read_bool(dev, 93541c06ffdSHuang Rui "snps,del_phy_power_chg_quirk"); 9363d128919SHeikki Krogerus dwc->lfps_filter_quirk = device_property_read_bool(dev, 937fb67afcaSHuang Rui "snps,lfps_filter_quirk"); 9383d128919SHeikki Krogerus dwc->rx_detect_poll_quirk = device_property_read_bool(dev, 93914f4ac53SHuang Rui "snps,rx_detect_poll_quirk"); 9403d128919SHeikki Krogerus dwc->dis_u3_susphy_quirk = device_property_read_bool(dev, 94159acfa20SHuang Rui "snps,dis_u3_susphy_quirk"); 9423d128919SHeikki Krogerus dwc->dis_u2_susphy_quirk = device_property_read_bool(dev, 9430effe0a3SHuang Rui "snps,dis_u2_susphy_quirk"); 944ec791d14SJohn Youn dwc->dis_enblslpm_quirk = device_property_read_bool(dev, 945ec791d14SJohn Youn "snps,dis_enblslpm_quirk"); 946e58dd357SRajesh Bhagat dwc->dis_rxdet_inp3_quirk = device_property_read_bool(dev, 947e58dd357SRajesh Bhagat "snps,dis_rxdet_inp3_quirk"); 94816199f33SWilliam Wu dwc->dis_u2_freeclk_exists_quirk = device_property_read_bool(dev, 94916199f33SWilliam Wu "snps,dis-u2-freeclk-exists-quirk"); 9506b6a0c9aSHuang Rui 9513d128919SHeikki Krogerus dwc->tx_de_emphasis_quirk = device_property_read_bool(dev, 9526b6a0c9aSHuang Rui "snps,tx_de_emphasis_quirk"); 9533d128919SHeikki Krogerus device_property_read_u8(dev, "snps,tx_de_emphasis", 9546b6a0c9aSHuang Rui &tx_de_emphasis); 9553d128919SHeikki Krogerus device_property_read_string(dev, "snps,hsphy_interface", 9563e10a2ceSHeikki Krogerus &dwc->hsphy_interface); 9573d128919SHeikki Krogerus device_property_read_u32(dev, "snps,quirk-frame-length-adjustment", 958bcdb3272SFelipe Balbi &dwc->fladj); 9593d128919SHeikki Krogerus 96080caf7d2SHuang Rui dwc->lpm_nyet_threshold = lpm_nyet_threshold; 9616b6a0c9aSHuang Rui dwc->tx_de_emphasis = tx_de_emphasis; 96280caf7d2SHuang Rui 963460d098cSHuang Rui dwc->hird_threshold = hird_threshold 964460d098cSHuang Rui | (dwc->is_utmi_l1_suspend << 4); 965460d098cSHuang Rui 9666c89cce0SHeikki Krogerus platform_set_drvdata(pdev, dwc); 9672917e718SHeikki Krogerus dwc3_cache_hwparams(dwc); 9686c89cce0SHeikki Krogerus 9693c9f94acSFelipe Balbi ret = dwc3_core_get_phy(dwc); 9703c9f94acSFelipe Balbi if (ret) 9713da1f6eeSFelipe Balbi goto err0; 9723c9f94acSFelipe Balbi 97372246da4SFelipe Balbi spin_lock_init(&dwc->lock); 97472246da4SFelipe Balbi 97519bacdc9SHeikki Krogerus if (!dev->dma_mask) { 976ddff14f1SKishon Vijay Abraham I dev->dma_mask = dev->parent->dma_mask; 977ddff14f1SKishon Vijay Abraham I dev->dma_parms = dev->parent->dma_parms; 978ddff14f1SKishon Vijay Abraham I dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); 97919bacdc9SHeikki Krogerus } 980ddff14f1SKishon Vijay Abraham I 981fc8bb91bSFelipe Balbi pm_runtime_set_active(dev); 982fc8bb91bSFelipe Balbi pm_runtime_use_autosuspend(dev); 983fc8bb91bSFelipe Balbi pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY); 984802ca850SChanho Park pm_runtime_enable(dev); 98532808237SRoger Quadros ret = pm_runtime_get_sync(dev); 98632808237SRoger Quadros if (ret < 0) 98732808237SRoger Quadros goto err1; 98832808237SRoger Quadros 989802ca850SChanho Park pm_runtime_forbid(dev); 99072246da4SFelipe Balbi 9913921426bSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 9923921426bSFelipe Balbi if (ret) { 9933921426bSFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 9943921426bSFelipe Balbi ret = -ENOMEM; 99532808237SRoger Quadros goto err2; 9963921426bSFelipe Balbi } 9973921426bSFelipe Balbi 9985f82279aSFelipe Balbi if (IS_ENABLED(CONFIG_USB_DWC3_HOST) && 9995f82279aSFelipe Balbi (dwc->dr_mode == USB_DR_MODE_OTG || 10005f82279aSFelipe Balbi dwc->dr_mode == USB_DR_MODE_UNKNOWN)) 100132a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_HOST; 10025f82279aSFelipe Balbi else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET) && 10035f82279aSFelipe Balbi (dwc->dr_mode == USB_DR_MODE_OTG || 10045f82279aSFelipe Balbi dwc->dr_mode == USB_DR_MODE_UNKNOWN)) 100532a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_PERIPHERAL; 100632a4a135SFelipe Balbi 100732a4a135SFelipe Balbi if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) 100832a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_OTG; 100932a4a135SFelipe Balbi 1010c499ff71SFelipe Balbi ret = dwc3_alloc_scratch_buffers(dwc); 1011c499ff71SFelipe Balbi if (ret) 101232808237SRoger Quadros goto err3; 1013c499ff71SFelipe Balbi 101472246da4SFelipe Balbi ret = dwc3_core_init(dwc); 101572246da4SFelipe Balbi if (ret) { 1016802ca850SChanho Park dev_err(dev, "failed to initialize core\n"); 101732808237SRoger Quadros goto err4; 101872246da4SFelipe Balbi } 101972246da4SFelipe Balbi 102077966eb8SJohn Youn /* Check the maximum_speed parameter */ 102177966eb8SJohn Youn switch (dwc->maximum_speed) { 102277966eb8SJohn Youn case USB_SPEED_LOW: 102377966eb8SJohn Youn case USB_SPEED_FULL: 102477966eb8SJohn Youn case USB_SPEED_HIGH: 102577966eb8SJohn Youn case USB_SPEED_SUPER: 102677966eb8SJohn Youn case USB_SPEED_SUPER_PLUS: 102777966eb8SJohn Youn break; 102877966eb8SJohn Youn default: 102977966eb8SJohn Youn dev_err(dev, "invalid maximum_speed parameter %d\n", 103077966eb8SJohn Youn dwc->maximum_speed); 103177966eb8SJohn Youn /* fall through */ 103277966eb8SJohn Youn case USB_SPEED_UNKNOWN: 103377966eb8SJohn Youn /* default to superspeed */ 10342c7f1bd9SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER; 10352c7f1bd9SJohn Youn 10362c7f1bd9SJohn Youn /* 10372c7f1bd9SJohn Youn * default to superspeed plus if we are capable. 10382c7f1bd9SJohn Youn */ 10392c7f1bd9SJohn Youn if (dwc3_is_usb31(dwc) && 10402c7f1bd9SJohn Youn (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 10412c7f1bd9SJohn Youn DWC3_GHWPARAMS3_SSPHY_IFC_GEN2)) 10422c7f1bd9SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER_PLUS; 104377966eb8SJohn Youn 104477966eb8SJohn Youn break; 10452c7f1bd9SJohn Youn } 10462c7f1bd9SJohn Youn 10475f94adfeSFelipe Balbi ret = dwc3_core_init_mode(dwc); 10485f94adfeSFelipe Balbi if (ret) 104932808237SRoger Quadros goto err5; 105072246da4SFelipe Balbi 10514e9f3118SDu, Changbin dwc3_debugfs_init(dwc); 1052fc8bb91bSFelipe Balbi pm_runtime_put(dev); 105372246da4SFelipe Balbi 105472246da4SFelipe Balbi return 0; 105572246da4SFelipe Balbi 105632808237SRoger Quadros err5: 1057f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 1058f122d33eSFelipe Balbi 105932808237SRoger Quadros err4: 1060c499ff71SFelipe Balbi dwc3_free_scratch_buffers(dwc); 106172246da4SFelipe Balbi 106232808237SRoger Quadros err3: 10633921426bSFelipe Balbi dwc3_free_event_buffers(dwc); 106488bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 10653921426bSFelipe Balbi 106632808237SRoger Quadros err2: 106732808237SRoger Quadros pm_runtime_allow(&pdev->dev); 106832808237SRoger Quadros 106932808237SRoger Quadros err1: 107032808237SRoger Quadros pm_runtime_put_sync(&pdev->dev); 107132808237SRoger Quadros pm_runtime_disable(&pdev->dev); 107232808237SRoger Quadros 10733da1f6eeSFelipe Balbi err0: 10743da1f6eeSFelipe Balbi /* 10753da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 10763da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 10773da1f6eeSFelipe Balbi * memory region the next time probe is called. 10783da1f6eeSFelipe Balbi */ 10793da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 10803da1f6eeSFelipe Balbi 108172246da4SFelipe Balbi return ret; 108272246da4SFelipe Balbi } 108372246da4SFelipe Balbi 1084fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev) 108572246da4SFelipe Balbi { 108672246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 10873da1f6eeSFelipe Balbi struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 10883da1f6eeSFelipe Balbi 1089fc8bb91bSFelipe Balbi pm_runtime_get_sync(&pdev->dev); 10903da1f6eeSFelipe Balbi /* 10913da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 10923da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 10933da1f6eeSFelipe Balbi * memory region the next time probe is called. 10943da1f6eeSFelipe Balbi */ 10953da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 109672246da4SFelipe Balbi 1097dc99f16fSFelipe Balbi dwc3_debugfs_exit(dwc); 1098dc99f16fSFelipe Balbi dwc3_core_exit_mode(dwc); 10998ba007a9SKishon Vijay Abraham I 110072246da4SFelipe Balbi dwc3_core_exit(dwc); 110188bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 110272246da4SFelipe Balbi 1103fc8bb91bSFelipe Balbi pm_runtime_put_sync(&pdev->dev); 1104fc8bb91bSFelipe Balbi pm_runtime_allow(&pdev->dev); 1105fc8bb91bSFelipe Balbi pm_runtime_disable(&pdev->dev); 1106fc8bb91bSFelipe Balbi 1107c499ff71SFelipe Balbi dwc3_free_event_buffers(dwc); 1108c499ff71SFelipe Balbi dwc3_free_scratch_buffers(dwc); 1109c499ff71SFelipe Balbi 111072246da4SFelipe Balbi return 0; 111172246da4SFelipe Balbi } 111272246da4SFelipe Balbi 1113fc8bb91bSFelipe Balbi #ifdef CONFIG_PM 1114fc8bb91bSFelipe Balbi static int dwc3_suspend_common(struct dwc3 *dwc) 11157415f17cSFelipe Balbi { 1116fc8bb91bSFelipe Balbi unsigned long flags; 11177415f17cSFelipe Balbi 1118a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 1119a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 1120a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 1121fc8bb91bSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 11227415f17cSFelipe Balbi dwc3_gadget_suspend(dwc); 1123fc8bb91bSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 112451f5d49aSFelipe Balbi break; 1125a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 11267415f17cSFelipe Balbi default: 112751f5d49aSFelipe Balbi /* do nothing */ 11287415f17cSFelipe Balbi break; 11297415f17cSFelipe Balbi } 11307415f17cSFelipe Balbi 113151f5d49aSFelipe Balbi dwc3_core_exit(dwc); 11325c4ad318SFelipe Balbi 1133fc8bb91bSFelipe Balbi return 0; 1134fc8bb91bSFelipe Balbi } 1135fc8bb91bSFelipe Balbi 1136fc8bb91bSFelipe Balbi static int dwc3_resume_common(struct dwc3 *dwc) 1137fc8bb91bSFelipe Balbi { 1138fc8bb91bSFelipe Balbi unsigned long flags; 1139fc8bb91bSFelipe Balbi int ret; 1140fc8bb91bSFelipe Balbi 1141fc8bb91bSFelipe Balbi ret = dwc3_core_init(dwc); 1142fc8bb91bSFelipe Balbi if (ret) 1143fc8bb91bSFelipe Balbi return ret; 1144fc8bb91bSFelipe Balbi 1145fc8bb91bSFelipe Balbi switch (dwc->dr_mode) { 1146fc8bb91bSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 1147fc8bb91bSFelipe Balbi case USB_DR_MODE_OTG: 1148fc8bb91bSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 1149fc8bb91bSFelipe Balbi dwc3_gadget_resume(dwc); 1150fc8bb91bSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 1151fc8bb91bSFelipe Balbi /* FALLTHROUGH */ 1152fc8bb91bSFelipe Balbi case USB_DR_MODE_HOST: 1153fc8bb91bSFelipe Balbi default: 1154fc8bb91bSFelipe Balbi /* do nothing */ 1155fc8bb91bSFelipe Balbi break; 1156fc8bb91bSFelipe Balbi } 1157fc8bb91bSFelipe Balbi 1158fc8bb91bSFelipe Balbi return 0; 1159fc8bb91bSFelipe Balbi } 1160fc8bb91bSFelipe Balbi 1161fc8bb91bSFelipe Balbi static int dwc3_runtime_checks(struct dwc3 *dwc) 1162fc8bb91bSFelipe Balbi { 1163fc8bb91bSFelipe Balbi switch (dwc->dr_mode) { 1164fc8bb91bSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 1165fc8bb91bSFelipe Balbi case USB_DR_MODE_OTG: 1166fc8bb91bSFelipe Balbi if (dwc->connected) 1167fc8bb91bSFelipe Balbi return -EBUSY; 1168fc8bb91bSFelipe Balbi break; 1169fc8bb91bSFelipe Balbi case USB_DR_MODE_HOST: 1170fc8bb91bSFelipe Balbi default: 1171fc8bb91bSFelipe Balbi /* do nothing */ 1172fc8bb91bSFelipe Balbi break; 1173fc8bb91bSFelipe Balbi } 1174fc8bb91bSFelipe Balbi 1175fc8bb91bSFelipe Balbi return 0; 1176fc8bb91bSFelipe Balbi } 1177fc8bb91bSFelipe Balbi 1178fc8bb91bSFelipe Balbi static int dwc3_runtime_suspend(struct device *dev) 1179fc8bb91bSFelipe Balbi { 1180fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1181fc8bb91bSFelipe Balbi int ret; 1182fc8bb91bSFelipe Balbi 1183fc8bb91bSFelipe Balbi if (dwc3_runtime_checks(dwc)) 1184fc8bb91bSFelipe Balbi return -EBUSY; 1185fc8bb91bSFelipe Balbi 1186fc8bb91bSFelipe Balbi ret = dwc3_suspend_common(dwc); 1187fc8bb91bSFelipe Balbi if (ret) 1188fc8bb91bSFelipe Balbi return ret; 1189fc8bb91bSFelipe Balbi 1190fc8bb91bSFelipe Balbi device_init_wakeup(dev, true); 1191fc8bb91bSFelipe Balbi 1192fc8bb91bSFelipe Balbi return 0; 1193fc8bb91bSFelipe Balbi } 1194fc8bb91bSFelipe Balbi 1195fc8bb91bSFelipe Balbi static int dwc3_runtime_resume(struct device *dev) 1196fc8bb91bSFelipe Balbi { 1197fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1198fc8bb91bSFelipe Balbi int ret; 1199fc8bb91bSFelipe Balbi 1200fc8bb91bSFelipe Balbi device_init_wakeup(dev, false); 1201fc8bb91bSFelipe Balbi 1202fc8bb91bSFelipe Balbi ret = dwc3_resume_common(dwc); 1203fc8bb91bSFelipe Balbi if (ret) 1204fc8bb91bSFelipe Balbi return ret; 1205fc8bb91bSFelipe Balbi 1206fc8bb91bSFelipe Balbi switch (dwc->dr_mode) { 1207fc8bb91bSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 1208fc8bb91bSFelipe Balbi case USB_DR_MODE_OTG: 1209fc8bb91bSFelipe Balbi dwc3_gadget_process_pending_events(dwc); 1210fc8bb91bSFelipe Balbi break; 1211fc8bb91bSFelipe Balbi case USB_DR_MODE_HOST: 1212fc8bb91bSFelipe Balbi default: 1213fc8bb91bSFelipe Balbi /* do nothing */ 1214fc8bb91bSFelipe Balbi break; 1215fc8bb91bSFelipe Balbi } 1216fc8bb91bSFelipe Balbi 1217fc8bb91bSFelipe Balbi pm_runtime_mark_last_busy(dev); 1218fc8bb91bSFelipe Balbi 1219fc8bb91bSFelipe Balbi return 0; 1220fc8bb91bSFelipe Balbi } 1221fc8bb91bSFelipe Balbi 1222fc8bb91bSFelipe Balbi static int dwc3_runtime_idle(struct device *dev) 1223fc8bb91bSFelipe Balbi { 1224fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1225fc8bb91bSFelipe Balbi 1226fc8bb91bSFelipe Balbi switch (dwc->dr_mode) { 1227fc8bb91bSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 1228fc8bb91bSFelipe Balbi case USB_DR_MODE_OTG: 1229fc8bb91bSFelipe Balbi if (dwc3_runtime_checks(dwc)) 1230fc8bb91bSFelipe Balbi return -EBUSY; 1231fc8bb91bSFelipe Balbi break; 1232fc8bb91bSFelipe Balbi case USB_DR_MODE_HOST: 1233fc8bb91bSFelipe Balbi default: 1234fc8bb91bSFelipe Balbi /* do nothing */ 1235fc8bb91bSFelipe Balbi break; 1236fc8bb91bSFelipe Balbi } 1237fc8bb91bSFelipe Balbi 1238fc8bb91bSFelipe Balbi pm_runtime_mark_last_busy(dev); 1239fc8bb91bSFelipe Balbi pm_runtime_autosuspend(dev); 1240fc8bb91bSFelipe Balbi 1241fc8bb91bSFelipe Balbi return 0; 1242fc8bb91bSFelipe Balbi } 1243fc8bb91bSFelipe Balbi #endif /* CONFIG_PM */ 1244fc8bb91bSFelipe Balbi 1245fc8bb91bSFelipe Balbi #ifdef CONFIG_PM_SLEEP 1246fc8bb91bSFelipe Balbi static int dwc3_suspend(struct device *dev) 1247fc8bb91bSFelipe Balbi { 1248fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1249fc8bb91bSFelipe Balbi int ret; 1250fc8bb91bSFelipe Balbi 1251fc8bb91bSFelipe Balbi ret = dwc3_suspend_common(dwc); 1252fc8bb91bSFelipe Balbi if (ret) 1253fc8bb91bSFelipe Balbi return ret; 1254fc8bb91bSFelipe Balbi 12556344475fSSekhar Nori pinctrl_pm_select_sleep_state(dev); 12566344475fSSekhar Nori 12577415f17cSFelipe Balbi return 0; 12587415f17cSFelipe Balbi } 12597415f17cSFelipe Balbi 12607415f17cSFelipe Balbi static int dwc3_resume(struct device *dev) 12617415f17cSFelipe Balbi { 12627415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 126357303488SKishon Vijay Abraham I int ret; 12647415f17cSFelipe Balbi 12656344475fSSekhar Nori pinctrl_pm_select_default_state(dev); 12666344475fSSekhar Nori 1267fc8bb91bSFelipe Balbi ret = dwc3_resume_common(dwc); 126851f5d49aSFelipe Balbi if (ret) 12695c4ad318SFelipe Balbi return ret; 12705c4ad318SFelipe Balbi 12717415f17cSFelipe Balbi pm_runtime_disable(dev); 12727415f17cSFelipe Balbi pm_runtime_set_active(dev); 12737415f17cSFelipe Balbi pm_runtime_enable(dev); 12747415f17cSFelipe Balbi 12757415f17cSFelipe Balbi return 0; 12767415f17cSFelipe Balbi } 12777f370ed0SFelipe Balbi #endif /* CONFIG_PM_SLEEP */ 12787415f17cSFelipe Balbi 12797415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = { 12807415f17cSFelipe Balbi SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 1281fc8bb91bSFelipe Balbi SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume, 1282fc8bb91bSFelipe Balbi dwc3_runtime_idle) 12837415f17cSFelipe Balbi }; 12847415f17cSFelipe Balbi 12855088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF 12865088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = { 12875088b6f5SKishon Vijay Abraham I { 128822a5aa17SFelipe Balbi .compatible = "snps,dwc3" 128922a5aa17SFelipe Balbi }, 129022a5aa17SFelipe Balbi { 12915088b6f5SKishon Vijay Abraham I .compatible = "synopsys,dwc3" 12925088b6f5SKishon Vijay Abraham I }, 12935088b6f5SKishon Vijay Abraham I { }, 12945088b6f5SKishon Vijay Abraham I }; 12955088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match); 12965088b6f5SKishon Vijay Abraham I #endif 12975088b6f5SKishon Vijay Abraham I 1298404905a6SHeikki Krogerus #ifdef CONFIG_ACPI 1299404905a6SHeikki Krogerus 1300404905a6SHeikki Krogerus #define ACPI_ID_INTEL_BSW "808622B7" 1301404905a6SHeikki Krogerus 1302404905a6SHeikki Krogerus static const struct acpi_device_id dwc3_acpi_match[] = { 1303404905a6SHeikki Krogerus { ACPI_ID_INTEL_BSW, 0 }, 1304404905a6SHeikki Krogerus { }, 1305404905a6SHeikki Krogerus }; 1306404905a6SHeikki Krogerus MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match); 1307404905a6SHeikki Krogerus #endif 1308404905a6SHeikki Krogerus 130972246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 131072246da4SFelipe Balbi .probe = dwc3_probe, 13117690417dSBill Pemberton .remove = dwc3_remove, 131272246da4SFelipe Balbi .driver = { 131372246da4SFelipe Balbi .name = "dwc3", 13145088b6f5SKishon Vijay Abraham I .of_match_table = of_match_ptr(of_dwc3_match), 1315404905a6SHeikki Krogerus .acpi_match_table = ACPI_PTR(dwc3_acpi_match), 13167f370ed0SFelipe Balbi .pm = &dwc3_dev_pm_ops, 131772246da4SFelipe Balbi }, 131872246da4SFelipe Balbi }; 131972246da4SFelipe Balbi 1320b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 1321b1116dccSTobias Klauser 13227ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 132372246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 13245945f789SFelipe Balbi MODULE_LICENSE("GPL v2"); 132572246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 1326