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 4882164a476SHuang Rui /* 4892164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to 4902164a476SHuang Rui * '0' during coreConsultant configuration. So default value will 4912164a476SHuang Rui * be '0' when the core is reset. Application needs to set it to 4922164a476SHuang Rui * '1' after the core initialization is completed. 4932164a476SHuang Rui */ 4942164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 4952164a476SHuang Rui reg |= DWC3_GUSB2PHYCFG_SUSPHY; 4962164a476SHuang Rui 497cd72f890SFelipe Balbi if (dwc->dis_u2_susphy_quirk) 4980effe0a3SHuang Rui reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 4990effe0a3SHuang Rui 500ec791d14SJohn Youn if (dwc->dis_enblslpm_quirk) 501ec791d14SJohn Youn reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; 502ec791d14SJohn Youn 5032164a476SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 50488bc9d19SHeikki Krogerus 50588bc9d19SHeikki Krogerus return 0; 506b5a65c40SHuang Rui } 507b5a65c40SHuang Rui 508c499ff71SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 509c499ff71SFelipe Balbi { 510c499ff71SFelipe Balbi dwc3_event_buffers_cleanup(dwc); 511c499ff71SFelipe Balbi 512c499ff71SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 513c499ff71SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 514c499ff71SFelipe Balbi phy_exit(dwc->usb2_generic_phy); 515c499ff71SFelipe Balbi phy_exit(dwc->usb3_generic_phy); 516c499ff71SFelipe Balbi 517c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 1); 518c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 1); 519c499ff71SFelipe Balbi phy_power_off(dwc->usb2_generic_phy); 520c499ff71SFelipe Balbi phy_power_off(dwc->usb3_generic_phy); 521c499ff71SFelipe Balbi } 522c499ff71SFelipe Balbi 523b5a65c40SHuang Rui /** 52472246da4SFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 52572246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 52672246da4SFelipe Balbi * 52772246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 52872246da4SFelipe Balbi */ 52941ac7b3aSBill Pemberton static int dwc3_core_init(struct dwc3 *dwc) 53072246da4SFelipe Balbi { 5310ffcaf37SFelipe Balbi u32 hwparams4 = dwc->hwparams.hwparams4; 53272246da4SFelipe Balbi u32 reg; 53372246da4SFelipe Balbi int ret; 53472246da4SFelipe Balbi 5357650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 5367650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 537690fb371SJohn Youn if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) { 538690fb371SJohn Youn /* Detected DWC_usb3 IP */ 539690fb371SJohn Youn dwc->revision = reg; 540690fb371SJohn Youn } else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) { 541690fb371SJohn Youn /* Detected DWC_usb31 IP */ 542690fb371SJohn Youn dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); 543690fb371SJohn Youn dwc->revision |= DWC3_REVISION_IS_DWC31; 544690fb371SJohn Youn } else { 5457650bd74SSebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 5467650bd74SSebastian Andrzej Siewior ret = -ENODEV; 5477650bd74SSebastian Andrzej Siewior goto err0; 5487650bd74SSebastian Andrzej Siewior } 5497650bd74SSebastian Andrzej Siewior 550fa0ea13eSFelipe Balbi /* 551fa0ea13eSFelipe Balbi * Write Linux Version Code to our GUID register so it's easy to figure 552fa0ea13eSFelipe Balbi * out which kernel version a bug was found. 553fa0ea13eSFelipe Balbi */ 554fa0ea13eSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); 555fa0ea13eSFelipe Balbi 5560e1e5c47SPaul Zimmerman /* Handle USB2.0-only core configuration */ 5570e1e5c47SPaul Zimmerman if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 5580e1e5c47SPaul Zimmerman DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { 5590e1e5c47SPaul Zimmerman if (dwc->maximum_speed == USB_SPEED_SUPER) 5600e1e5c47SPaul Zimmerman dwc->maximum_speed = USB_SPEED_HIGH; 5610e1e5c47SPaul Zimmerman } 5620e1e5c47SPaul Zimmerman 56372246da4SFelipe Balbi /* issue device SoftReset too */ 564c5cc74e8SHeikki Krogerus ret = dwc3_soft_reset(dwc); 565c5cc74e8SHeikki Krogerus if (ret) 56672246da4SFelipe Balbi goto err0; 56772246da4SFelipe Balbi 56857303488SKishon Vijay Abraham I ret = dwc3_core_soft_reset(dwc); 56957303488SKishon Vijay Abraham I if (ret) 57057303488SKishon Vijay Abraham I goto err0; 57158a0f23fSPratyush Anand 572c499ff71SFelipe Balbi ret = dwc3_phy_setup(dwc); 573c499ff71SFelipe Balbi if (ret) 574c499ff71SFelipe Balbi goto err0; 575c499ff71SFelipe Balbi 5764878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 5773e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 5784878a028SSebastian Andrzej Siewior 579164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 5804878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 58132a4a135SFelipe Balbi /** 58232a4a135SFelipe Balbi * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an 58332a4a135SFelipe Balbi * issue which would cause xHCI compliance tests to fail. 58432a4a135SFelipe Balbi * 58532a4a135SFelipe Balbi * Because of that we cannot enable clock gating on such 58632a4a135SFelipe Balbi * configurations. 58732a4a135SFelipe Balbi * 58832a4a135SFelipe Balbi * Refers to: 58932a4a135SFelipe Balbi * 59032a4a135SFelipe Balbi * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based 59132a4a135SFelipe Balbi * SOF/ITP Mode Used 59232a4a135SFelipe Balbi */ 59332a4a135SFelipe Balbi if ((dwc->dr_mode == USB_DR_MODE_HOST || 59432a4a135SFelipe Balbi dwc->dr_mode == USB_DR_MODE_OTG) && 59532a4a135SFelipe Balbi (dwc->revision >= DWC3_REVISION_210A && 59632a4a135SFelipe Balbi dwc->revision <= DWC3_REVISION_250A)) 59732a4a135SFelipe Balbi reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; 59832a4a135SFelipe Balbi else 5994878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 6004878a028SSebastian Andrzej Siewior break; 6010ffcaf37SFelipe Balbi case DWC3_GHWPARAMS1_EN_PWROPT_HIB: 6020ffcaf37SFelipe Balbi /* enable hibernation here */ 6030ffcaf37SFelipe Balbi dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); 6042eac3992SHuang Rui 6052eac3992SHuang Rui /* 6062eac3992SHuang Rui * REVISIT Enabling this bit so that host-mode hibernation 6072eac3992SHuang Rui * will work. Device-mode hibernation is not yet implemented. 6082eac3992SHuang Rui */ 6092eac3992SHuang Rui reg |= DWC3_GCTL_GBLHIBERNATIONEN; 6100ffcaf37SFelipe Balbi break; 6114878a028SSebastian Andrzej Siewior default: 6121407bf13SFelipe Balbi dwc3_trace(trace_dwc3_core, "No power optimization available\n"); 6134878a028SSebastian Andrzej Siewior } 6144878a028SSebastian Andrzej Siewior 615946bd579SHuang Rui /* check if current dwc3 is on simulation board */ 616946bd579SHuang Rui if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { 6171407bf13SFelipe Balbi dwc3_trace(trace_dwc3_core, 6181407bf13SFelipe Balbi "running on FPGA platform\n"); 619946bd579SHuang Rui dwc->is_fpga = true; 620946bd579SHuang Rui } 621946bd579SHuang Rui 6223b81221aSHuang Rui WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga, 6233b81221aSHuang Rui "disable_scramble cannot be used on non-FPGA builds\n"); 6243b81221aSHuang Rui 6253b81221aSHuang Rui if (dwc->disable_scramble_quirk && dwc->is_fpga) 6263b81221aSHuang Rui reg |= DWC3_GCTL_DISSCRAMBLE; 6273b81221aSHuang Rui else 6283b81221aSHuang Rui reg &= ~DWC3_GCTL_DISSCRAMBLE; 6293b81221aSHuang Rui 6309a5b2f31SHuang Rui if (dwc->u2exit_lfps_quirk) 6319a5b2f31SHuang Rui reg |= DWC3_GCTL_U2EXIT_LFPS; 6329a5b2f31SHuang Rui 6334878a028SSebastian Andrzej Siewior /* 6344878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 6351d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 6364878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 6371d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 6384878a028SSebastian Andrzej Siewior */ 6394878a028SSebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 6404878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 6414878a028SSebastian Andrzej Siewior 6424878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 6434878a028SSebastian Andrzej Siewior 644c499ff71SFelipe Balbi dwc3_core_num_eps(dwc); 6450ffcaf37SFelipe Balbi 6460ffcaf37SFelipe Balbi ret = dwc3_setup_scratch_buffers(dwc); 6470ffcaf37SFelipe Balbi if (ret) 648c499ff71SFelipe Balbi goto err1; 649c499ff71SFelipe Balbi 650c499ff71SFelipe Balbi /* Adjust Frame Length */ 651c499ff71SFelipe Balbi dwc3_frame_length_adjustment(dwc); 652c499ff71SFelipe Balbi 653c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 0); 654c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 0); 655c499ff71SFelipe Balbi ret = phy_power_on(dwc->usb2_generic_phy); 656c499ff71SFelipe Balbi if (ret < 0) 6570ffcaf37SFelipe Balbi goto err2; 6580ffcaf37SFelipe Balbi 659c499ff71SFelipe Balbi ret = phy_power_on(dwc->usb3_generic_phy); 660c499ff71SFelipe Balbi if (ret < 0) 661c499ff71SFelipe Balbi goto err3; 662c499ff71SFelipe Balbi 663c499ff71SFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 664c499ff71SFelipe Balbi if (ret) { 665c499ff71SFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 666c499ff71SFelipe Balbi goto err4; 667c499ff71SFelipe Balbi } 668c499ff71SFelipe Balbi 66972246da4SFelipe Balbi return 0; 67072246da4SFelipe Balbi 671c499ff71SFelipe Balbi err4: 672c499ff71SFelipe Balbi phy_power_off(dwc->usb2_generic_phy); 673c499ff71SFelipe Balbi 674c499ff71SFelipe Balbi err3: 675c499ff71SFelipe Balbi phy_power_off(dwc->usb3_generic_phy); 676c499ff71SFelipe Balbi 6770ffcaf37SFelipe Balbi err2: 678c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 1); 679c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 1); 680c499ff71SFelipe Balbi dwc3_core_exit(dwc); 6810ffcaf37SFelipe Balbi 6820ffcaf37SFelipe Balbi err1: 6830ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 6840ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 68557303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 68657303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 6870ffcaf37SFelipe Balbi 68872246da4SFelipe Balbi err0: 68972246da4SFelipe Balbi return ret; 69072246da4SFelipe Balbi } 69172246da4SFelipe Balbi 6923c9f94acSFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc) 69372246da4SFelipe Balbi { 6943c9f94acSFelipe Balbi struct device *dev = dwc->dev; 695941ea361SFelipe Balbi struct device_node *node = dev->of_node; 6963c9f94acSFelipe Balbi int ret; 69772246da4SFelipe Balbi 6985088b6f5SKishon Vijay Abraham I if (node) { 6995088b6f5SKishon Vijay Abraham I dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); 7005088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); 701bb674907SFelipe Balbi } else { 702bb674907SFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 703bb674907SFelipe Balbi dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 7045088b6f5SKishon Vijay Abraham I } 7055088b6f5SKishon Vijay Abraham I 706d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb2_phy)) { 707d105e7f8SFelipe Balbi ret = PTR_ERR(dwc->usb2_phy); 708122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 709122f06e6SKishon Vijay Abraham I dwc->usb2_phy = NULL; 710122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 711d105e7f8SFelipe Balbi return ret; 712122f06e6SKishon Vijay Abraham I } else { 71351e1e7bcSFelipe Balbi dev_err(dev, "no usb2 phy configured\n"); 714122f06e6SKishon Vijay Abraham I return ret; 715122f06e6SKishon Vijay Abraham I } 71651e1e7bcSFelipe Balbi } 71751e1e7bcSFelipe Balbi 718d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb3_phy)) { 719315955d7SRuchika Kharwar ret = PTR_ERR(dwc->usb3_phy); 720122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 721122f06e6SKishon Vijay Abraham I dwc->usb3_phy = NULL; 722122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 723d105e7f8SFelipe Balbi return ret; 724122f06e6SKishon Vijay Abraham I } else { 72551e1e7bcSFelipe Balbi dev_err(dev, "no usb3 phy configured\n"); 726122f06e6SKishon Vijay Abraham I return ret; 727122f06e6SKishon Vijay Abraham I } 72851e1e7bcSFelipe Balbi } 72951e1e7bcSFelipe Balbi 73057303488SKishon Vijay Abraham I dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); 73157303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb2_generic_phy)) { 73257303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb2_generic_phy); 73357303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 73457303488SKishon Vijay Abraham I dwc->usb2_generic_phy = NULL; 73557303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 73657303488SKishon Vijay Abraham I return ret; 73757303488SKishon Vijay Abraham I } else { 73857303488SKishon Vijay Abraham I dev_err(dev, "no usb2 phy configured\n"); 73957303488SKishon Vijay Abraham I return ret; 74057303488SKishon Vijay Abraham I } 74157303488SKishon Vijay Abraham I } 74257303488SKishon Vijay Abraham I 74357303488SKishon Vijay Abraham I dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy"); 74457303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb3_generic_phy)) { 74557303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb3_generic_phy); 74657303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 74757303488SKishon Vijay Abraham I dwc->usb3_generic_phy = NULL; 74857303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 74957303488SKishon Vijay Abraham I return ret; 75057303488SKishon Vijay Abraham I } else { 75157303488SKishon Vijay Abraham I dev_err(dev, "no usb3 phy configured\n"); 75257303488SKishon Vijay Abraham I return ret; 75357303488SKishon Vijay Abraham I } 75457303488SKishon Vijay Abraham I } 75557303488SKishon Vijay Abraham I 7563c9f94acSFelipe Balbi return 0; 7573c9f94acSFelipe Balbi } 7583c9f94acSFelipe Balbi 7595f94adfeSFelipe Balbi static int dwc3_core_init_mode(struct dwc3 *dwc) 7605f94adfeSFelipe Balbi { 7615f94adfeSFelipe Balbi struct device *dev = dwc->dev; 7625f94adfeSFelipe Balbi int ret; 7635f94adfeSFelipe Balbi 7645f94adfeSFelipe Balbi switch (dwc->dr_mode) { 7655f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 7665f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); 7675f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 7685f94adfeSFelipe Balbi if (ret) { 7699522def4SRoger Quadros if (ret != -EPROBE_DEFER) 7705f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 7715f94adfeSFelipe Balbi return ret; 7725f94adfeSFelipe Balbi } 7735f94adfeSFelipe Balbi break; 7745f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 7755f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); 7765f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 7775f94adfeSFelipe Balbi if (ret) { 7789522def4SRoger Quadros if (ret != -EPROBE_DEFER) 7795f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 7805f94adfeSFelipe Balbi return ret; 7815f94adfeSFelipe Balbi } 7825f94adfeSFelipe Balbi break; 7835f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 7845f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); 7855f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 7865f94adfeSFelipe Balbi if (ret) { 7879522def4SRoger Quadros if (ret != -EPROBE_DEFER) 7885f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 7895f94adfeSFelipe Balbi return ret; 7905f94adfeSFelipe Balbi } 7915f94adfeSFelipe Balbi 7925f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 7935f94adfeSFelipe Balbi if (ret) { 7949522def4SRoger Quadros if (ret != -EPROBE_DEFER) 7955f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 7965f94adfeSFelipe Balbi return ret; 7975f94adfeSFelipe Balbi } 7985f94adfeSFelipe Balbi break; 7995f94adfeSFelipe Balbi default: 8005f94adfeSFelipe Balbi dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); 8015f94adfeSFelipe Balbi return -EINVAL; 8025f94adfeSFelipe Balbi } 8035f94adfeSFelipe Balbi 8045f94adfeSFelipe Balbi return 0; 8055f94adfeSFelipe Balbi } 8065f94adfeSFelipe Balbi 8075f94adfeSFelipe Balbi static void dwc3_core_exit_mode(struct dwc3 *dwc) 8085f94adfeSFelipe Balbi { 8095f94adfeSFelipe Balbi switch (dwc->dr_mode) { 8105f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 8115f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 8125f94adfeSFelipe Balbi break; 8135f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 8145f94adfeSFelipe Balbi dwc3_host_exit(dwc); 8155f94adfeSFelipe Balbi break; 8165f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 8175f94adfeSFelipe Balbi dwc3_host_exit(dwc); 8185f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 8195f94adfeSFelipe Balbi break; 8205f94adfeSFelipe Balbi default: 8215f94adfeSFelipe Balbi /* do nothing */ 8225f94adfeSFelipe Balbi break; 8235f94adfeSFelipe Balbi } 8245f94adfeSFelipe Balbi } 8255f94adfeSFelipe Balbi 8263c9f94acSFelipe Balbi #define DWC3_ALIGN_MASK (16 - 1) 8273c9f94acSFelipe Balbi 8283c9f94acSFelipe Balbi static int dwc3_probe(struct platform_device *pdev) 8293c9f94acSFelipe Balbi { 8303c9f94acSFelipe Balbi struct device *dev = &pdev->dev; 8313c9f94acSFelipe Balbi struct resource *res; 8323c9f94acSFelipe Balbi struct dwc3 *dwc; 83380caf7d2SHuang Rui u8 lpm_nyet_threshold; 8346b6a0c9aSHuang Rui u8 tx_de_emphasis; 835460d098cSHuang Rui u8 hird_threshold; 8363c9f94acSFelipe Balbi 837b09e99eeSAndy Shevchenko int ret; 8383c9f94acSFelipe Balbi 8393c9f94acSFelipe Balbi void __iomem *regs; 8403c9f94acSFelipe Balbi void *mem; 8413c9f94acSFelipe Balbi 8423c9f94acSFelipe Balbi mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 843734d5a53SJingoo Han if (!mem) 8443c9f94acSFelipe Balbi return -ENOMEM; 845734d5a53SJingoo Han 8463c9f94acSFelipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 8473c9f94acSFelipe Balbi dwc->mem = mem; 8483c9f94acSFelipe Balbi dwc->dev = dev; 8493c9f94acSFelipe Balbi 8503c9f94acSFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 8513c9f94acSFelipe Balbi if (!res) { 8523c9f94acSFelipe Balbi dev_err(dev, "missing memory resource\n"); 8533c9f94acSFelipe Balbi return -ENODEV; 8543c9f94acSFelipe Balbi } 8553c9f94acSFelipe Balbi 856f32a5e23SVivek Gautam dwc->xhci_resources[0].start = res->start; 857f32a5e23SVivek Gautam dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 858f32a5e23SVivek Gautam DWC3_XHCI_REGS_END; 859f32a5e23SVivek Gautam dwc->xhci_resources[0].flags = res->flags; 860f32a5e23SVivek Gautam dwc->xhci_resources[0].name = res->name; 861f32a5e23SVivek Gautam 862f32a5e23SVivek Gautam res->start += DWC3_GLOBALS_REGS_START; 863f32a5e23SVivek Gautam 864f32a5e23SVivek Gautam /* 865f32a5e23SVivek Gautam * Request memory region but exclude xHCI regs, 866f32a5e23SVivek Gautam * since it will be requested by the xhci-plat driver. 867f32a5e23SVivek Gautam */ 868f32a5e23SVivek Gautam regs = devm_ioremap_resource(dev, res); 8693da1f6eeSFelipe Balbi if (IS_ERR(regs)) { 8703da1f6eeSFelipe Balbi ret = PTR_ERR(regs); 8713da1f6eeSFelipe Balbi goto err0; 8723da1f6eeSFelipe Balbi } 873f32a5e23SVivek Gautam 874f32a5e23SVivek Gautam dwc->regs = regs; 875f32a5e23SVivek Gautam dwc->regs_size = resource_size(res); 876f32a5e23SVivek Gautam 87780caf7d2SHuang Rui /* default to highest possible threshold */ 87880caf7d2SHuang Rui lpm_nyet_threshold = 0xff; 87980caf7d2SHuang Rui 8806b6a0c9aSHuang Rui /* default to -3.5dB de-emphasis */ 8816b6a0c9aSHuang Rui tx_de_emphasis = 1; 8826b6a0c9aSHuang Rui 883460d098cSHuang Rui /* 884460d098cSHuang Rui * default to assert utmi_sleep_n and use maximum allowed HIRD 885460d098cSHuang Rui * threshold value of 0b1100 886460d098cSHuang Rui */ 887460d098cSHuang Rui hird_threshold = 12; 888460d098cSHuang Rui 88963863b98SHeikki Krogerus dwc->maximum_speed = usb_get_maximum_speed(dev); 89006e7114fSHeikki Krogerus dwc->dr_mode = usb_get_dr_mode(dev); 89163863b98SHeikki Krogerus 8923d128919SHeikki Krogerus dwc->has_lpm_erratum = device_property_read_bool(dev, 89380caf7d2SHuang Rui "snps,has-lpm-erratum"); 8943d128919SHeikki Krogerus device_property_read_u8(dev, "snps,lpm-nyet-threshold", 89580caf7d2SHuang Rui &lpm_nyet_threshold); 8963d128919SHeikki Krogerus dwc->is_utmi_l1_suspend = device_property_read_bool(dev, 897460d098cSHuang Rui "snps,is-utmi-l1-suspend"); 8983d128919SHeikki Krogerus device_property_read_u8(dev, "snps,hird-threshold", 899460d098cSHuang Rui &hird_threshold); 9003d128919SHeikki Krogerus dwc->usb3_lpm_capable = device_property_read_bool(dev, 901eac68e8fSRobert Baldyga "snps,usb3_lpm_capable"); 9023c9f94acSFelipe Balbi 9033d128919SHeikki Krogerus dwc->disable_scramble_quirk = device_property_read_bool(dev, 9043b81221aSHuang Rui "snps,disable_scramble_quirk"); 9053d128919SHeikki Krogerus dwc->u2exit_lfps_quirk = device_property_read_bool(dev, 9069a5b2f31SHuang Rui "snps,u2exit_lfps_quirk"); 9073d128919SHeikki Krogerus dwc->u2ss_inp3_quirk = device_property_read_bool(dev, 908b5a65c40SHuang Rui "snps,u2ss_inp3_quirk"); 9093d128919SHeikki Krogerus dwc->req_p1p2p3_quirk = device_property_read_bool(dev, 910df31f5b3SHuang Rui "snps,req_p1p2p3_quirk"); 9113d128919SHeikki Krogerus dwc->del_p1p2p3_quirk = device_property_read_bool(dev, 912a2a1d0f5SHuang Rui "snps,del_p1p2p3_quirk"); 9133d128919SHeikki Krogerus dwc->del_phy_power_chg_quirk = device_property_read_bool(dev, 91441c06ffdSHuang Rui "snps,del_phy_power_chg_quirk"); 9153d128919SHeikki Krogerus dwc->lfps_filter_quirk = device_property_read_bool(dev, 916fb67afcaSHuang Rui "snps,lfps_filter_quirk"); 9173d128919SHeikki Krogerus dwc->rx_detect_poll_quirk = device_property_read_bool(dev, 91814f4ac53SHuang Rui "snps,rx_detect_poll_quirk"); 9193d128919SHeikki Krogerus dwc->dis_u3_susphy_quirk = device_property_read_bool(dev, 92059acfa20SHuang Rui "snps,dis_u3_susphy_quirk"); 9213d128919SHeikki Krogerus dwc->dis_u2_susphy_quirk = device_property_read_bool(dev, 9220effe0a3SHuang Rui "snps,dis_u2_susphy_quirk"); 923ec791d14SJohn Youn dwc->dis_enblslpm_quirk = device_property_read_bool(dev, 924ec791d14SJohn Youn "snps,dis_enblslpm_quirk"); 925e58dd357SRajesh Bhagat dwc->dis_rxdet_inp3_quirk = device_property_read_bool(dev, 926e58dd357SRajesh Bhagat "snps,dis_rxdet_inp3_quirk"); 9276b6a0c9aSHuang Rui 9283d128919SHeikki Krogerus dwc->tx_de_emphasis_quirk = device_property_read_bool(dev, 9296b6a0c9aSHuang Rui "snps,tx_de_emphasis_quirk"); 9303d128919SHeikki Krogerus device_property_read_u8(dev, "snps,tx_de_emphasis", 9316b6a0c9aSHuang Rui &tx_de_emphasis); 9323d128919SHeikki Krogerus device_property_read_string(dev, "snps,hsphy_interface", 9333e10a2ceSHeikki Krogerus &dwc->hsphy_interface); 9343d128919SHeikki Krogerus device_property_read_u32(dev, "snps,quirk-frame-length-adjustment", 935bcdb3272SFelipe Balbi &dwc->fladj); 9363d128919SHeikki Krogerus 93780caf7d2SHuang Rui dwc->lpm_nyet_threshold = lpm_nyet_threshold; 9386b6a0c9aSHuang Rui dwc->tx_de_emphasis = tx_de_emphasis; 93980caf7d2SHuang Rui 940460d098cSHuang Rui dwc->hird_threshold = hird_threshold 941460d098cSHuang Rui | (dwc->is_utmi_l1_suspend << 4); 942460d098cSHuang Rui 9436c89cce0SHeikki Krogerus platform_set_drvdata(pdev, dwc); 9442917e718SHeikki Krogerus dwc3_cache_hwparams(dwc); 9456c89cce0SHeikki Krogerus 9463c9f94acSFelipe Balbi ret = dwc3_core_get_phy(dwc); 9473c9f94acSFelipe Balbi if (ret) 9483da1f6eeSFelipe Balbi goto err0; 9493c9f94acSFelipe Balbi 95072246da4SFelipe Balbi spin_lock_init(&dwc->lock); 95172246da4SFelipe Balbi 95219bacdc9SHeikki Krogerus if (!dev->dma_mask) { 953ddff14f1SKishon Vijay Abraham I dev->dma_mask = dev->parent->dma_mask; 954ddff14f1SKishon Vijay Abraham I dev->dma_parms = dev->parent->dma_parms; 955ddff14f1SKishon Vijay Abraham I dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); 95619bacdc9SHeikki Krogerus } 957ddff14f1SKishon Vijay Abraham I 958fc8bb91bSFelipe Balbi pm_runtime_set_active(dev); 959fc8bb91bSFelipe Balbi pm_runtime_use_autosuspend(dev); 960fc8bb91bSFelipe Balbi pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY); 961802ca850SChanho Park pm_runtime_enable(dev); 96232808237SRoger Quadros ret = pm_runtime_get_sync(dev); 96332808237SRoger Quadros if (ret < 0) 96432808237SRoger Quadros goto err1; 96532808237SRoger Quadros 966802ca850SChanho Park pm_runtime_forbid(dev); 96772246da4SFelipe Balbi 9683921426bSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 9693921426bSFelipe Balbi if (ret) { 9703921426bSFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 9713921426bSFelipe Balbi ret = -ENOMEM; 97232808237SRoger Quadros goto err2; 9733921426bSFelipe Balbi } 9743921426bSFelipe Balbi 9755f82279aSFelipe Balbi if (IS_ENABLED(CONFIG_USB_DWC3_HOST) && 9765f82279aSFelipe Balbi (dwc->dr_mode == USB_DR_MODE_OTG || 9775f82279aSFelipe Balbi dwc->dr_mode == USB_DR_MODE_UNKNOWN)) 97832a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_HOST; 9795f82279aSFelipe Balbi else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET) && 9805f82279aSFelipe Balbi (dwc->dr_mode == USB_DR_MODE_OTG || 9815f82279aSFelipe Balbi dwc->dr_mode == USB_DR_MODE_UNKNOWN)) 98232a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_PERIPHERAL; 98332a4a135SFelipe Balbi 98432a4a135SFelipe Balbi if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) 98532a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_OTG; 98632a4a135SFelipe Balbi 987c499ff71SFelipe Balbi ret = dwc3_alloc_scratch_buffers(dwc); 988c499ff71SFelipe Balbi if (ret) 98932808237SRoger Quadros goto err3; 990c499ff71SFelipe Balbi 99172246da4SFelipe Balbi ret = dwc3_core_init(dwc); 99272246da4SFelipe Balbi if (ret) { 993802ca850SChanho Park dev_err(dev, "failed to initialize core\n"); 99432808237SRoger Quadros goto err4; 99572246da4SFelipe Balbi } 99672246da4SFelipe Balbi 99777966eb8SJohn Youn /* Check the maximum_speed parameter */ 99877966eb8SJohn Youn switch (dwc->maximum_speed) { 99977966eb8SJohn Youn case USB_SPEED_LOW: 100077966eb8SJohn Youn case USB_SPEED_FULL: 100177966eb8SJohn Youn case USB_SPEED_HIGH: 100277966eb8SJohn Youn case USB_SPEED_SUPER: 100377966eb8SJohn Youn case USB_SPEED_SUPER_PLUS: 100477966eb8SJohn Youn break; 100577966eb8SJohn Youn default: 100677966eb8SJohn Youn dev_err(dev, "invalid maximum_speed parameter %d\n", 100777966eb8SJohn Youn dwc->maximum_speed); 100877966eb8SJohn Youn /* fall through */ 100977966eb8SJohn Youn case USB_SPEED_UNKNOWN: 101077966eb8SJohn Youn /* default to superspeed */ 10112c7f1bd9SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER; 10122c7f1bd9SJohn Youn 10132c7f1bd9SJohn Youn /* 10142c7f1bd9SJohn Youn * default to superspeed plus if we are capable. 10152c7f1bd9SJohn Youn */ 10162c7f1bd9SJohn Youn if (dwc3_is_usb31(dwc) && 10172c7f1bd9SJohn Youn (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 10182c7f1bd9SJohn Youn DWC3_GHWPARAMS3_SSPHY_IFC_GEN2)) 10192c7f1bd9SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER_PLUS; 102077966eb8SJohn Youn 102177966eb8SJohn Youn break; 10222c7f1bd9SJohn Youn } 10232c7f1bd9SJohn Youn 10245f94adfeSFelipe Balbi ret = dwc3_core_init_mode(dwc); 10255f94adfeSFelipe Balbi if (ret) 102632808237SRoger Quadros goto err5; 102772246da4SFelipe Balbi 10284e9f3118SDu, Changbin dwc3_debugfs_init(dwc); 1029fc8bb91bSFelipe Balbi pm_runtime_put(dev); 103072246da4SFelipe Balbi 103172246da4SFelipe Balbi return 0; 103272246da4SFelipe Balbi 103332808237SRoger Quadros err5: 1034f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 1035f122d33eSFelipe Balbi 103632808237SRoger Quadros err4: 1037c499ff71SFelipe Balbi dwc3_free_scratch_buffers(dwc); 103872246da4SFelipe Balbi 103932808237SRoger Quadros err3: 10403921426bSFelipe Balbi dwc3_free_event_buffers(dwc); 104188bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 10423921426bSFelipe Balbi 104332808237SRoger Quadros err2: 104432808237SRoger Quadros pm_runtime_allow(&pdev->dev); 104532808237SRoger Quadros 104632808237SRoger Quadros err1: 104732808237SRoger Quadros pm_runtime_put_sync(&pdev->dev); 104832808237SRoger Quadros pm_runtime_disable(&pdev->dev); 104932808237SRoger Quadros 10503da1f6eeSFelipe Balbi err0: 10513da1f6eeSFelipe Balbi /* 10523da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 10533da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 10543da1f6eeSFelipe Balbi * memory region the next time probe is called. 10553da1f6eeSFelipe Balbi */ 10563da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 10573da1f6eeSFelipe Balbi 105872246da4SFelipe Balbi return ret; 105972246da4SFelipe Balbi } 106072246da4SFelipe Balbi 1061fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev) 106272246da4SFelipe Balbi { 106372246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 10643da1f6eeSFelipe Balbi struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 10653da1f6eeSFelipe Balbi 1066fc8bb91bSFelipe Balbi pm_runtime_get_sync(&pdev->dev); 10673da1f6eeSFelipe Balbi /* 10683da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 10693da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 10703da1f6eeSFelipe Balbi * memory region the next time probe is called. 10713da1f6eeSFelipe Balbi */ 10723da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 107372246da4SFelipe Balbi 1074dc99f16fSFelipe Balbi dwc3_debugfs_exit(dwc); 1075dc99f16fSFelipe Balbi dwc3_core_exit_mode(dwc); 10768ba007a9SKishon Vijay Abraham I 107772246da4SFelipe Balbi dwc3_core_exit(dwc); 107888bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 107972246da4SFelipe Balbi 1080fc8bb91bSFelipe Balbi pm_runtime_put_sync(&pdev->dev); 1081fc8bb91bSFelipe Balbi pm_runtime_allow(&pdev->dev); 1082fc8bb91bSFelipe Balbi pm_runtime_disable(&pdev->dev); 1083fc8bb91bSFelipe Balbi 1084c499ff71SFelipe Balbi dwc3_free_event_buffers(dwc); 1085c499ff71SFelipe Balbi dwc3_free_scratch_buffers(dwc); 1086c499ff71SFelipe Balbi 108772246da4SFelipe Balbi return 0; 108872246da4SFelipe Balbi } 108972246da4SFelipe Balbi 1090fc8bb91bSFelipe Balbi #ifdef CONFIG_PM 1091fc8bb91bSFelipe Balbi static int dwc3_suspend_common(struct dwc3 *dwc) 10927415f17cSFelipe Balbi { 1093fc8bb91bSFelipe Balbi unsigned long flags; 10947415f17cSFelipe Balbi 1095a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 1096a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 1097a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 1098fc8bb91bSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 10997415f17cSFelipe Balbi dwc3_gadget_suspend(dwc); 1100fc8bb91bSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 110151f5d49aSFelipe Balbi break; 1102a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 11037415f17cSFelipe Balbi default: 110451f5d49aSFelipe Balbi /* do nothing */ 11057415f17cSFelipe Balbi break; 11067415f17cSFelipe Balbi } 11077415f17cSFelipe Balbi 110851f5d49aSFelipe Balbi dwc3_core_exit(dwc); 11095c4ad318SFelipe Balbi 1110fc8bb91bSFelipe Balbi return 0; 1111fc8bb91bSFelipe Balbi } 1112fc8bb91bSFelipe Balbi 1113fc8bb91bSFelipe Balbi static int dwc3_resume_common(struct dwc3 *dwc) 1114fc8bb91bSFelipe Balbi { 1115fc8bb91bSFelipe Balbi unsigned long flags; 1116fc8bb91bSFelipe Balbi int ret; 1117fc8bb91bSFelipe Balbi 1118fc8bb91bSFelipe Balbi ret = dwc3_core_init(dwc); 1119fc8bb91bSFelipe Balbi if (ret) 1120fc8bb91bSFelipe Balbi return ret; 1121fc8bb91bSFelipe Balbi 1122fc8bb91bSFelipe Balbi switch (dwc->dr_mode) { 1123fc8bb91bSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 1124fc8bb91bSFelipe Balbi case USB_DR_MODE_OTG: 1125fc8bb91bSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 1126fc8bb91bSFelipe Balbi dwc3_gadget_resume(dwc); 1127fc8bb91bSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 1128fc8bb91bSFelipe Balbi /* FALLTHROUGH */ 1129fc8bb91bSFelipe Balbi case USB_DR_MODE_HOST: 1130fc8bb91bSFelipe Balbi default: 1131fc8bb91bSFelipe Balbi /* do nothing */ 1132fc8bb91bSFelipe Balbi break; 1133fc8bb91bSFelipe Balbi } 1134fc8bb91bSFelipe Balbi 1135fc8bb91bSFelipe Balbi return 0; 1136fc8bb91bSFelipe Balbi } 1137fc8bb91bSFelipe Balbi 1138fc8bb91bSFelipe Balbi static int dwc3_runtime_checks(struct dwc3 *dwc) 1139fc8bb91bSFelipe Balbi { 1140fc8bb91bSFelipe Balbi switch (dwc->dr_mode) { 1141fc8bb91bSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 1142fc8bb91bSFelipe Balbi case USB_DR_MODE_OTG: 1143fc8bb91bSFelipe Balbi if (dwc->connected) 1144fc8bb91bSFelipe Balbi return -EBUSY; 1145fc8bb91bSFelipe Balbi break; 1146fc8bb91bSFelipe Balbi case USB_DR_MODE_HOST: 1147fc8bb91bSFelipe Balbi default: 1148fc8bb91bSFelipe Balbi /* do nothing */ 1149fc8bb91bSFelipe Balbi break; 1150fc8bb91bSFelipe Balbi } 1151fc8bb91bSFelipe Balbi 1152fc8bb91bSFelipe Balbi return 0; 1153fc8bb91bSFelipe Balbi } 1154fc8bb91bSFelipe Balbi 1155fc8bb91bSFelipe Balbi static int dwc3_runtime_suspend(struct device *dev) 1156fc8bb91bSFelipe Balbi { 1157fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1158fc8bb91bSFelipe Balbi int ret; 1159fc8bb91bSFelipe Balbi 1160fc8bb91bSFelipe Balbi if (dwc3_runtime_checks(dwc)) 1161fc8bb91bSFelipe Balbi return -EBUSY; 1162fc8bb91bSFelipe Balbi 1163fc8bb91bSFelipe Balbi ret = dwc3_suspend_common(dwc); 1164fc8bb91bSFelipe Balbi if (ret) 1165fc8bb91bSFelipe Balbi return ret; 1166fc8bb91bSFelipe Balbi 1167fc8bb91bSFelipe Balbi device_init_wakeup(dev, true); 1168fc8bb91bSFelipe Balbi 1169fc8bb91bSFelipe Balbi return 0; 1170fc8bb91bSFelipe Balbi } 1171fc8bb91bSFelipe Balbi 1172fc8bb91bSFelipe Balbi static int dwc3_runtime_resume(struct device *dev) 1173fc8bb91bSFelipe Balbi { 1174fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1175fc8bb91bSFelipe Balbi int ret; 1176fc8bb91bSFelipe Balbi 1177fc8bb91bSFelipe Balbi device_init_wakeup(dev, false); 1178fc8bb91bSFelipe Balbi 1179fc8bb91bSFelipe Balbi ret = dwc3_resume_common(dwc); 1180fc8bb91bSFelipe Balbi if (ret) 1181fc8bb91bSFelipe Balbi return ret; 1182fc8bb91bSFelipe Balbi 1183fc8bb91bSFelipe Balbi switch (dwc->dr_mode) { 1184fc8bb91bSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 1185fc8bb91bSFelipe Balbi case USB_DR_MODE_OTG: 1186fc8bb91bSFelipe Balbi dwc3_gadget_process_pending_events(dwc); 1187fc8bb91bSFelipe Balbi break; 1188fc8bb91bSFelipe Balbi case USB_DR_MODE_HOST: 1189fc8bb91bSFelipe Balbi default: 1190fc8bb91bSFelipe Balbi /* do nothing */ 1191fc8bb91bSFelipe Balbi break; 1192fc8bb91bSFelipe Balbi } 1193fc8bb91bSFelipe Balbi 1194fc8bb91bSFelipe Balbi pm_runtime_mark_last_busy(dev); 1195b74c2d87SFelipe Balbi pm_runtime_put(dev); 1196fc8bb91bSFelipe Balbi 1197fc8bb91bSFelipe Balbi return 0; 1198fc8bb91bSFelipe Balbi } 1199fc8bb91bSFelipe Balbi 1200fc8bb91bSFelipe Balbi static int dwc3_runtime_idle(struct device *dev) 1201fc8bb91bSFelipe Balbi { 1202fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1203fc8bb91bSFelipe Balbi 1204fc8bb91bSFelipe Balbi switch (dwc->dr_mode) { 1205fc8bb91bSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 1206fc8bb91bSFelipe Balbi case USB_DR_MODE_OTG: 1207fc8bb91bSFelipe Balbi if (dwc3_runtime_checks(dwc)) 1208fc8bb91bSFelipe Balbi return -EBUSY; 1209fc8bb91bSFelipe Balbi break; 1210fc8bb91bSFelipe Balbi case USB_DR_MODE_HOST: 1211fc8bb91bSFelipe Balbi default: 1212fc8bb91bSFelipe Balbi /* do nothing */ 1213fc8bb91bSFelipe Balbi break; 1214fc8bb91bSFelipe Balbi } 1215fc8bb91bSFelipe Balbi 1216fc8bb91bSFelipe Balbi pm_runtime_mark_last_busy(dev); 1217fc8bb91bSFelipe Balbi pm_runtime_autosuspend(dev); 1218fc8bb91bSFelipe Balbi 1219fc8bb91bSFelipe Balbi return 0; 1220fc8bb91bSFelipe Balbi } 1221fc8bb91bSFelipe Balbi #endif /* CONFIG_PM */ 1222fc8bb91bSFelipe Balbi 1223fc8bb91bSFelipe Balbi #ifdef CONFIG_PM_SLEEP 1224fc8bb91bSFelipe Balbi static int dwc3_suspend(struct device *dev) 1225fc8bb91bSFelipe Balbi { 1226fc8bb91bSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 1227fc8bb91bSFelipe Balbi int ret; 1228fc8bb91bSFelipe Balbi 1229fc8bb91bSFelipe Balbi ret = dwc3_suspend_common(dwc); 1230fc8bb91bSFelipe Balbi if (ret) 1231fc8bb91bSFelipe Balbi return ret; 1232fc8bb91bSFelipe Balbi 12336344475fSSekhar Nori pinctrl_pm_select_sleep_state(dev); 12346344475fSSekhar Nori 12357415f17cSFelipe Balbi return 0; 12367415f17cSFelipe Balbi } 12377415f17cSFelipe Balbi 12387415f17cSFelipe Balbi static int dwc3_resume(struct device *dev) 12397415f17cSFelipe Balbi { 12407415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 124157303488SKishon Vijay Abraham I int ret; 12427415f17cSFelipe Balbi 12436344475fSSekhar Nori pinctrl_pm_select_default_state(dev); 12446344475fSSekhar Nori 1245fc8bb91bSFelipe Balbi ret = dwc3_resume_common(dwc); 124651f5d49aSFelipe Balbi if (ret) 12475c4ad318SFelipe Balbi return ret; 12485c4ad318SFelipe Balbi 12497415f17cSFelipe Balbi pm_runtime_disable(dev); 12507415f17cSFelipe Balbi pm_runtime_set_active(dev); 12517415f17cSFelipe Balbi pm_runtime_enable(dev); 12527415f17cSFelipe Balbi 12537415f17cSFelipe Balbi return 0; 12547415f17cSFelipe Balbi } 12557f370ed0SFelipe Balbi #endif /* CONFIG_PM_SLEEP */ 12567415f17cSFelipe Balbi 12577415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = { 12587415f17cSFelipe Balbi SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 1259fc8bb91bSFelipe Balbi SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume, 1260fc8bb91bSFelipe Balbi dwc3_runtime_idle) 12617415f17cSFelipe Balbi }; 12627415f17cSFelipe Balbi 12635088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF 12645088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = { 12655088b6f5SKishon Vijay Abraham I { 126622a5aa17SFelipe Balbi .compatible = "snps,dwc3" 126722a5aa17SFelipe Balbi }, 126822a5aa17SFelipe Balbi { 12695088b6f5SKishon Vijay Abraham I .compatible = "synopsys,dwc3" 12705088b6f5SKishon Vijay Abraham I }, 12715088b6f5SKishon Vijay Abraham I { }, 12725088b6f5SKishon Vijay Abraham I }; 12735088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match); 12745088b6f5SKishon Vijay Abraham I #endif 12755088b6f5SKishon Vijay Abraham I 1276404905a6SHeikki Krogerus #ifdef CONFIG_ACPI 1277404905a6SHeikki Krogerus 1278404905a6SHeikki Krogerus #define ACPI_ID_INTEL_BSW "808622B7" 1279404905a6SHeikki Krogerus 1280404905a6SHeikki Krogerus static const struct acpi_device_id dwc3_acpi_match[] = { 1281404905a6SHeikki Krogerus { ACPI_ID_INTEL_BSW, 0 }, 1282404905a6SHeikki Krogerus { }, 1283404905a6SHeikki Krogerus }; 1284404905a6SHeikki Krogerus MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match); 1285404905a6SHeikki Krogerus #endif 1286404905a6SHeikki Krogerus 128772246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 128872246da4SFelipe Balbi .probe = dwc3_probe, 12897690417dSBill Pemberton .remove = dwc3_remove, 129072246da4SFelipe Balbi .driver = { 129172246da4SFelipe Balbi .name = "dwc3", 12925088b6f5SKishon Vijay Abraham I .of_match_table = of_match_ptr(of_dwc3_match), 1293404905a6SHeikki Krogerus .acpi_match_table = ACPI_PTR(dwc3_acpi_match), 12947f370ed0SFelipe Balbi .pm = &dwc3_dev_pm_ops, 129572246da4SFelipe Balbi }, 129672246da4SFelipe Balbi }; 129772246da4SFelipe Balbi 1298b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 1299b1116dccSTobias Klauser 13007ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 130172246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 13025945f789SFelipe Balbi MODULE_LICENSE("GPL v2"); 130372246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 1304