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 446462cbd5SFelipe Balbi #include "platform_data.h" 4572246da4SFelipe Balbi #include "core.h" 4672246da4SFelipe Balbi #include "gadget.h" 4772246da4SFelipe Balbi #include "io.h" 4872246da4SFelipe Balbi 4972246da4SFelipe Balbi #include "debug.h" 5072246da4SFelipe Balbi 518300dd23SFelipe Balbi /* -------------------------------------------------------------------------- */ 528300dd23SFelipe Balbi 533140e8cbSSebastian Andrzej Siewior void dwc3_set_mode(struct dwc3 *dwc, u32 mode) 543140e8cbSSebastian Andrzej Siewior { 553140e8cbSSebastian Andrzej Siewior u32 reg; 563140e8cbSSebastian Andrzej Siewior 573140e8cbSSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 583140e8cbSSebastian Andrzej Siewior reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); 593140e8cbSSebastian Andrzej Siewior reg |= DWC3_GCTL_PRTCAPDIR(mode); 603140e8cbSSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 613140e8cbSSebastian Andrzej Siewior } 628300dd23SFelipe Balbi 63cf6d867dSFelipe Balbi u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type) 64cf6d867dSFelipe Balbi { 65cf6d867dSFelipe Balbi struct dwc3 *dwc = dep->dwc; 66cf6d867dSFelipe Balbi u32 reg; 67cf6d867dSFelipe Balbi 68cf6d867dSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GDBGFIFOSPACE, 69cf6d867dSFelipe Balbi DWC3_GDBGFIFOSPACE_NUM(dep->number) | 70cf6d867dSFelipe Balbi DWC3_GDBGFIFOSPACE_TYPE(type)); 71cf6d867dSFelipe Balbi 72cf6d867dSFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GDBGFIFOSPACE); 73cf6d867dSFelipe Balbi 74cf6d867dSFelipe Balbi return DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(reg); 75cf6d867dSFelipe Balbi } 76cf6d867dSFelipe Balbi 7772246da4SFelipe Balbi /** 7872246da4SFelipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 7972246da4SFelipe Balbi * @dwc: pointer to our context structure 8072246da4SFelipe Balbi */ 8157303488SKishon Vijay Abraham I static int dwc3_core_soft_reset(struct dwc3 *dwc) 8272246da4SFelipe Balbi { 8372246da4SFelipe Balbi u32 reg; 84f59dcab1SFelipe Balbi int retries = 1000; 8557303488SKishon Vijay Abraham I int ret; 8672246da4SFelipe Balbi 8751e1e7bcSFelipe Balbi usb_phy_init(dwc->usb2_phy); 8851e1e7bcSFelipe Balbi usb_phy_init(dwc->usb3_phy); 8957303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 9057303488SKishon Vijay Abraham I if (ret < 0) 9157303488SKishon Vijay Abraham I return ret; 9257303488SKishon Vijay Abraham I 9357303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 9457303488SKishon Vijay Abraham I if (ret < 0) { 9557303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 9657303488SKishon Vijay Abraham I return ret; 9757303488SKishon Vijay Abraham I } 9872246da4SFelipe Balbi 99f59dcab1SFelipe Balbi /* 100f59dcab1SFelipe Balbi * We're resetting only the device side because, if we're in host mode, 101f59dcab1SFelipe Balbi * XHCI driver will reset the host block. If dwc3 was configured for 102f59dcab1SFelipe Balbi * host-only mode, then we can return early. 103f59dcab1SFelipe Balbi */ 104f59dcab1SFelipe Balbi if (dwc->dr_mode == USB_DR_MODE_HOST) 10557303488SKishon Vijay Abraham I return 0; 106f59dcab1SFelipe Balbi 107f59dcab1SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 108f59dcab1SFelipe Balbi reg |= DWC3_DCTL_CSFTRST; 109f59dcab1SFelipe Balbi dwc3_writel(dwc->regs, DWC3_DCTL, reg); 110f59dcab1SFelipe Balbi 111f59dcab1SFelipe Balbi do { 112f59dcab1SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 113f59dcab1SFelipe Balbi if (!(reg & DWC3_DCTL_CSFTRST)) 114f59dcab1SFelipe Balbi return 0; 115f59dcab1SFelipe Balbi 116f59dcab1SFelipe Balbi udelay(1); 117f59dcab1SFelipe Balbi } while (--retries); 118f59dcab1SFelipe Balbi 119f59dcab1SFelipe Balbi return -ETIMEDOUT; 12072246da4SFelipe Balbi } 12172246da4SFelipe Balbi 12272246da4SFelipe Balbi /** 123c5cc74e8SHeikki Krogerus * dwc3_soft_reset - Issue soft reset 124c5cc74e8SHeikki Krogerus * @dwc: Pointer to our controller context structure 125c5cc74e8SHeikki Krogerus */ 126c5cc74e8SHeikki Krogerus static int dwc3_soft_reset(struct dwc3 *dwc) 127c5cc74e8SHeikki Krogerus { 128c5cc74e8SHeikki Krogerus unsigned long timeout; 129c5cc74e8SHeikki Krogerus u32 reg; 130c5cc74e8SHeikki Krogerus 131c5cc74e8SHeikki Krogerus timeout = jiffies + msecs_to_jiffies(500); 132c5cc74e8SHeikki Krogerus dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); 133c5cc74e8SHeikki Krogerus do { 134c5cc74e8SHeikki Krogerus reg = dwc3_readl(dwc->regs, DWC3_DCTL); 135c5cc74e8SHeikki Krogerus if (!(reg & DWC3_DCTL_CSFTRST)) 136c5cc74e8SHeikki Krogerus break; 137c5cc74e8SHeikki Krogerus 138c5cc74e8SHeikki Krogerus if (time_after(jiffies, timeout)) { 139c5cc74e8SHeikki Krogerus dev_err(dwc->dev, "Reset Timed Out\n"); 140c5cc74e8SHeikki Krogerus return -ETIMEDOUT; 141c5cc74e8SHeikki Krogerus } 142c5cc74e8SHeikki Krogerus 143c5cc74e8SHeikki Krogerus cpu_relax(); 144c5cc74e8SHeikki Krogerus } while (true); 145c5cc74e8SHeikki Krogerus 146c5cc74e8SHeikki Krogerus return 0; 147c5cc74e8SHeikki Krogerus } 148c5cc74e8SHeikki Krogerus 149db2be4e9SNikhil Badola /* 150db2be4e9SNikhil Badola * dwc3_frame_length_adjustment - Adjusts frame length if required 151db2be4e9SNikhil Badola * @dwc3: Pointer to our controller context structure 152db2be4e9SNikhil Badola */ 153bcdb3272SFelipe Balbi static void dwc3_frame_length_adjustment(struct dwc3 *dwc) 154db2be4e9SNikhil Badola { 155db2be4e9SNikhil Badola u32 reg; 156db2be4e9SNikhil Badola u32 dft; 157db2be4e9SNikhil Badola 158db2be4e9SNikhil Badola if (dwc->revision < DWC3_REVISION_250A) 159db2be4e9SNikhil Badola return; 160db2be4e9SNikhil Badola 161bcdb3272SFelipe Balbi if (dwc->fladj == 0) 162db2be4e9SNikhil Badola return; 163db2be4e9SNikhil Badola 164db2be4e9SNikhil Badola reg = dwc3_readl(dwc->regs, DWC3_GFLADJ); 165db2be4e9SNikhil Badola dft = reg & DWC3_GFLADJ_30MHZ_MASK; 166bcdb3272SFelipe Balbi if (!dev_WARN_ONCE(dwc->dev, dft == dwc->fladj, 167db2be4e9SNikhil Badola "request value same as default, ignoring\n")) { 168db2be4e9SNikhil Badola reg &= ~DWC3_GFLADJ_30MHZ_MASK; 169bcdb3272SFelipe Balbi reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj; 170db2be4e9SNikhil Badola dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); 171db2be4e9SNikhil Badola } 172db2be4e9SNikhil Badola } 173db2be4e9SNikhil Badola 174c5cc74e8SHeikki Krogerus /** 17572246da4SFelipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 17672246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 17772246da4SFelipe Balbi * @evt: Pointer to event buffer to be freed 17872246da4SFelipe Balbi */ 17972246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc, 18072246da4SFelipe Balbi struct dwc3_event_buffer *evt) 18172246da4SFelipe Balbi { 18272246da4SFelipe Balbi dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); 18372246da4SFelipe Balbi } 18472246da4SFelipe Balbi 18572246da4SFelipe Balbi /** 1861d046793SPaul Zimmerman * dwc3_alloc_one_event_buffer - Allocates one event buffer structure 18772246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 18872246da4SFelipe Balbi * @length: size of the event buffer 18972246da4SFelipe Balbi * 1901d046793SPaul Zimmerman * Returns a pointer to the allocated event buffer structure on success 19172246da4SFelipe Balbi * otherwise ERR_PTR(errno). 19272246da4SFelipe Balbi */ 19367d0b500SFelipe Balbi static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, 19467d0b500SFelipe Balbi unsigned length) 19572246da4SFelipe Balbi { 19672246da4SFelipe Balbi struct dwc3_event_buffer *evt; 19772246da4SFelipe Balbi 198380f0d28SFelipe Balbi evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL); 19972246da4SFelipe Balbi if (!evt) 20072246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 20172246da4SFelipe Balbi 20272246da4SFelipe Balbi evt->dwc = dwc; 20372246da4SFelipe Balbi evt->length = length; 20472246da4SFelipe Balbi evt->buf = dma_alloc_coherent(dwc->dev, length, 20572246da4SFelipe Balbi &evt->dma, GFP_KERNEL); 206e32672f0SFelipe Balbi if (!evt->buf) 20772246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 20872246da4SFelipe Balbi 20972246da4SFelipe Balbi return evt; 21072246da4SFelipe Balbi } 21172246da4SFelipe Balbi 21272246da4SFelipe Balbi /** 21372246da4SFelipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 21472246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 21572246da4SFelipe Balbi */ 21672246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc) 21772246da4SFelipe Balbi { 21872246da4SFelipe Balbi struct dwc3_event_buffer *evt; 21972246da4SFelipe Balbi 220696c8b12SFelipe Balbi evt = dwc->ev_buf; 22164b6c8a7SAnton Tikhomirov if (evt) 22272246da4SFelipe Balbi dwc3_free_one_event_buffer(dwc, evt); 22372246da4SFelipe Balbi } 22472246da4SFelipe Balbi 22572246da4SFelipe Balbi /** 22672246da4SFelipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 2271d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 22872246da4SFelipe Balbi * @length: size of event buffer 22972246da4SFelipe Balbi * 2301d046793SPaul Zimmerman * Returns 0 on success otherwise negative errno. In the error case, dwc 23172246da4SFelipe Balbi * may contain some buffers allocated but not all which were requested. 23272246da4SFelipe Balbi */ 23341ac7b3aSBill Pemberton static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) 23472246da4SFelipe Balbi { 23572246da4SFelipe Balbi struct dwc3_event_buffer *evt; 23672246da4SFelipe Balbi 23772246da4SFelipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 23872246da4SFelipe Balbi if (IS_ERR(evt)) { 23972246da4SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 24072246da4SFelipe Balbi return PTR_ERR(evt); 24172246da4SFelipe Balbi } 242696c8b12SFelipe Balbi dwc->ev_buf = evt; 24372246da4SFelipe Balbi 24472246da4SFelipe Balbi return 0; 24572246da4SFelipe Balbi } 24672246da4SFelipe Balbi 24772246da4SFelipe Balbi /** 24872246da4SFelipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 2491d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 25072246da4SFelipe Balbi * 25172246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 25272246da4SFelipe Balbi */ 2537acd85e0SPaul Zimmerman static int dwc3_event_buffers_setup(struct dwc3 *dwc) 25472246da4SFelipe Balbi { 25572246da4SFelipe Balbi struct dwc3_event_buffer *evt; 25672246da4SFelipe Balbi 257696c8b12SFelipe Balbi evt = dwc->ev_buf; 2581407bf13SFelipe Balbi dwc3_trace(trace_dwc3_core, 2591407bf13SFelipe Balbi "Event buf %p dma %08llx length %d\n", 26072246da4SFelipe Balbi evt->buf, (unsigned long long) evt->dma, 26172246da4SFelipe Balbi evt->length); 26272246da4SFelipe Balbi 2637acd85e0SPaul Zimmerman evt->lpos = 0; 2647acd85e0SPaul Zimmerman 265660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 26672246da4SFelipe Balbi lower_32_bits(evt->dma)); 267660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 26872246da4SFelipe Balbi upper_32_bits(evt->dma)); 269660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), 27068d6a01bSFelipe Balbi DWC3_GEVNTSIZ_SIZE(evt->length)); 271660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 27272246da4SFelipe Balbi 27372246da4SFelipe Balbi return 0; 27472246da4SFelipe Balbi } 27572246da4SFelipe Balbi 27672246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 27772246da4SFelipe Balbi { 27872246da4SFelipe Balbi struct dwc3_event_buffer *evt; 27972246da4SFelipe Balbi 280696c8b12SFelipe Balbi evt = dwc->ev_buf; 2817acd85e0SPaul Zimmerman 2827acd85e0SPaul Zimmerman evt->lpos = 0; 2837acd85e0SPaul Zimmerman 284660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 0); 285660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 0); 286660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK 28768d6a01bSFelipe Balbi | DWC3_GEVNTSIZ_SIZE(0)); 288660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 28972246da4SFelipe Balbi } 29072246da4SFelipe Balbi 2910ffcaf37SFelipe Balbi static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) 2920ffcaf37SFelipe Balbi { 2930ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 2940ffcaf37SFelipe Balbi return 0; 2950ffcaf37SFelipe Balbi 2960ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 2970ffcaf37SFelipe Balbi return 0; 2980ffcaf37SFelipe Balbi 2990ffcaf37SFelipe Balbi dwc->scratchbuf = kmalloc_array(dwc->nr_scratch, 3000ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, GFP_KERNEL); 3010ffcaf37SFelipe Balbi if (!dwc->scratchbuf) 3020ffcaf37SFelipe Balbi return -ENOMEM; 3030ffcaf37SFelipe Balbi 3040ffcaf37SFelipe Balbi return 0; 3050ffcaf37SFelipe Balbi } 3060ffcaf37SFelipe Balbi 3070ffcaf37SFelipe Balbi static int dwc3_setup_scratch_buffers(struct dwc3 *dwc) 3080ffcaf37SFelipe Balbi { 3090ffcaf37SFelipe Balbi dma_addr_t scratch_addr; 3100ffcaf37SFelipe Balbi u32 param; 3110ffcaf37SFelipe Balbi int ret; 3120ffcaf37SFelipe Balbi 3130ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3140ffcaf37SFelipe Balbi return 0; 3150ffcaf37SFelipe Balbi 3160ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3170ffcaf37SFelipe Balbi return 0; 3180ffcaf37SFelipe Balbi 3190ffcaf37SFelipe Balbi /* should never fall here */ 3200ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 3210ffcaf37SFelipe Balbi return 0; 3220ffcaf37SFelipe Balbi 3230ffcaf37SFelipe Balbi scratch_addr = dma_map_single(dwc->dev, dwc->scratchbuf, 3240ffcaf37SFelipe Balbi dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, 3250ffcaf37SFelipe Balbi DMA_BIDIRECTIONAL); 3260ffcaf37SFelipe Balbi if (dma_mapping_error(dwc->dev, scratch_addr)) { 3270ffcaf37SFelipe Balbi dev_err(dwc->dev, "failed to map scratch buffer\n"); 3280ffcaf37SFelipe Balbi ret = -EFAULT; 3290ffcaf37SFelipe Balbi goto err0; 3300ffcaf37SFelipe Balbi } 3310ffcaf37SFelipe Balbi 3320ffcaf37SFelipe Balbi dwc->scratch_addr = scratch_addr; 3330ffcaf37SFelipe Balbi 3340ffcaf37SFelipe Balbi param = lower_32_bits(scratch_addr); 3350ffcaf37SFelipe Balbi 3360ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3370ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param); 3380ffcaf37SFelipe Balbi if (ret < 0) 3390ffcaf37SFelipe Balbi goto err1; 3400ffcaf37SFelipe Balbi 3410ffcaf37SFelipe Balbi param = upper_32_bits(scratch_addr); 3420ffcaf37SFelipe Balbi 3430ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3440ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param); 3450ffcaf37SFelipe Balbi if (ret < 0) 3460ffcaf37SFelipe Balbi goto err1; 3470ffcaf37SFelipe Balbi 3480ffcaf37SFelipe Balbi return 0; 3490ffcaf37SFelipe Balbi 3500ffcaf37SFelipe Balbi err1: 3510ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3520ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3530ffcaf37SFelipe Balbi 3540ffcaf37SFelipe Balbi err0: 3550ffcaf37SFelipe Balbi return ret; 3560ffcaf37SFelipe Balbi } 3570ffcaf37SFelipe Balbi 3580ffcaf37SFelipe Balbi static void dwc3_free_scratch_buffers(struct dwc3 *dwc) 3590ffcaf37SFelipe Balbi { 3600ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3610ffcaf37SFelipe Balbi return; 3620ffcaf37SFelipe Balbi 3630ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3640ffcaf37SFelipe Balbi return; 3650ffcaf37SFelipe Balbi 3660ffcaf37SFelipe Balbi /* should never fall here */ 3670ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 3680ffcaf37SFelipe Balbi return; 3690ffcaf37SFelipe Balbi 3700ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3710ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3720ffcaf37SFelipe Balbi kfree(dwc->scratchbuf); 3730ffcaf37SFelipe Balbi } 3740ffcaf37SFelipe Balbi 375789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc) 376789451f6SFelipe Balbi { 377789451f6SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 378789451f6SFelipe Balbi 379789451f6SFelipe Balbi dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); 380789451f6SFelipe Balbi dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; 381789451f6SFelipe Balbi 38273815280SFelipe Balbi dwc3_trace(trace_dwc3_core, "found %d IN and %d OUT endpoints", 383789451f6SFelipe Balbi dwc->num_in_eps, dwc->num_out_eps); 384789451f6SFelipe Balbi } 385789451f6SFelipe Balbi 38641ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc) 38726ceca97SFelipe Balbi { 38826ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 38926ceca97SFelipe Balbi 39026ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 39126ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 39226ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 39326ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 39426ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 39526ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 39626ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 39726ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 39826ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 39926ceca97SFelipe Balbi } 40026ceca97SFelipe Balbi 40172246da4SFelipe Balbi /** 402b5a65c40SHuang Rui * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core 403b5a65c40SHuang Rui * @dwc: Pointer to our controller context structure 40488bc9d19SHeikki Krogerus * 40588bc9d19SHeikki Krogerus * Returns 0 on success. The USB PHY interfaces are configured but not 40688bc9d19SHeikki Krogerus * initialized. The PHY interfaces and the PHYs get initialized together with 40788bc9d19SHeikki Krogerus * the core in dwc3_core_init. 408b5a65c40SHuang Rui */ 40988bc9d19SHeikki Krogerus static int dwc3_phy_setup(struct dwc3 *dwc) 410b5a65c40SHuang Rui { 411b5a65c40SHuang Rui u32 reg; 41288bc9d19SHeikki Krogerus int ret; 413b5a65c40SHuang Rui 414b5a65c40SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 415b5a65c40SHuang Rui 4162164a476SHuang Rui /* 4172164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY 4182164a476SHuang Rui * to '0' during coreConsultant configuration. So default value 4192164a476SHuang Rui * will be '0' when the core is reset. Application needs to set it 4202164a476SHuang Rui * to '1' after the core initialization is completed. 4212164a476SHuang Rui */ 4222164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 4232164a476SHuang Rui reg |= DWC3_GUSB3PIPECTL_SUSPHY; 4242164a476SHuang Rui 425b5a65c40SHuang Rui if (dwc->u2ss_inp3_quirk) 426b5a65c40SHuang Rui reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; 427b5a65c40SHuang Rui 428e58dd357SRajesh Bhagat if (dwc->dis_rxdet_inp3_quirk) 429e58dd357SRajesh Bhagat reg |= DWC3_GUSB3PIPECTL_DISRXDETINP3; 430e58dd357SRajesh Bhagat 431df31f5b3SHuang Rui if (dwc->req_p1p2p3_quirk) 432df31f5b3SHuang Rui reg |= DWC3_GUSB3PIPECTL_REQP1P2P3; 433df31f5b3SHuang Rui 434a2a1d0f5SHuang Rui if (dwc->del_p1p2p3_quirk) 435a2a1d0f5SHuang Rui reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN; 436a2a1d0f5SHuang Rui 43741c06ffdSHuang Rui if (dwc->del_phy_power_chg_quirk) 43841c06ffdSHuang Rui reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE; 43941c06ffdSHuang Rui 440fb67afcaSHuang Rui if (dwc->lfps_filter_quirk) 441fb67afcaSHuang Rui reg |= DWC3_GUSB3PIPECTL_LFPSFILT; 442fb67afcaSHuang Rui 44314f4ac53SHuang Rui if (dwc->rx_detect_poll_quirk) 44414f4ac53SHuang Rui reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL; 44514f4ac53SHuang Rui 4466b6a0c9aSHuang Rui if (dwc->tx_de_emphasis_quirk) 4476b6a0c9aSHuang Rui reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); 4486b6a0c9aSHuang Rui 449cd72f890SFelipe Balbi if (dwc->dis_u3_susphy_quirk) 45059acfa20SHuang Rui reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 45159acfa20SHuang Rui 452b5a65c40SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 453b5a65c40SHuang Rui 4542164a476SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 4552164a476SHuang Rui 4563e10a2ceSHeikki Krogerus /* Select the HS PHY interface */ 4573e10a2ceSHeikki Krogerus switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) { 4583e10a2ceSHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI: 45943cacb03SFelipe Balbi if (dwc->hsphy_interface && 46043cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "utmi", 4)) { 4613e10a2ceSHeikki Krogerus reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI; 46288bc9d19SHeikki Krogerus break; 46343cacb03SFelipe Balbi } else if (dwc->hsphy_interface && 46443cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "ulpi", 4)) { 4653e10a2ceSHeikki Krogerus reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI; 46688bc9d19SHeikki Krogerus dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 4673e10a2ceSHeikki Krogerus } else { 46888bc9d19SHeikki Krogerus /* Relying on default value. */ 46988bc9d19SHeikki Krogerus if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) 4703e10a2ceSHeikki Krogerus break; 4713e10a2ceSHeikki Krogerus } 4723e10a2ceSHeikki Krogerus /* FALLTHROUGH */ 47388bc9d19SHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: 47488bc9d19SHeikki Krogerus /* Making sure the interface and PHY are operational */ 47588bc9d19SHeikki Krogerus ret = dwc3_soft_reset(dwc); 47688bc9d19SHeikki Krogerus if (ret) 47788bc9d19SHeikki Krogerus return ret; 47888bc9d19SHeikki Krogerus 47988bc9d19SHeikki Krogerus udelay(1); 48088bc9d19SHeikki Krogerus 48188bc9d19SHeikki Krogerus ret = dwc3_ulpi_init(dwc); 48288bc9d19SHeikki Krogerus if (ret) 48388bc9d19SHeikki Krogerus return ret; 48488bc9d19SHeikki Krogerus /* FALLTHROUGH */ 4853e10a2ceSHeikki Krogerus default: 4863e10a2ceSHeikki Krogerus break; 4873e10a2ceSHeikki Krogerus } 4883e10a2ceSHeikki Krogerus 4892164a476SHuang Rui /* 4902164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to 4912164a476SHuang Rui * '0' during coreConsultant configuration. So default value will 4922164a476SHuang Rui * be '0' when the core is reset. Application needs to set it to 4932164a476SHuang Rui * '1' after the core initialization is completed. 4942164a476SHuang Rui */ 4952164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 4962164a476SHuang Rui reg |= DWC3_GUSB2PHYCFG_SUSPHY; 4972164a476SHuang Rui 498cd72f890SFelipe Balbi if (dwc->dis_u2_susphy_quirk) 4990effe0a3SHuang Rui reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 5000effe0a3SHuang Rui 501ec791d14SJohn Youn if (dwc->dis_enblslpm_quirk) 502ec791d14SJohn Youn reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; 503ec791d14SJohn Youn 5042164a476SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 50588bc9d19SHeikki Krogerus 50688bc9d19SHeikki Krogerus return 0; 507b5a65c40SHuang Rui } 508b5a65c40SHuang Rui 509c499ff71SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 510c499ff71SFelipe Balbi { 511c499ff71SFelipe Balbi dwc3_event_buffers_cleanup(dwc); 512c499ff71SFelipe Balbi 513c499ff71SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 514c499ff71SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 515c499ff71SFelipe Balbi phy_exit(dwc->usb2_generic_phy); 516c499ff71SFelipe Balbi phy_exit(dwc->usb3_generic_phy); 517c499ff71SFelipe Balbi 518c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 1); 519c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 1); 520c499ff71SFelipe Balbi phy_power_off(dwc->usb2_generic_phy); 521c499ff71SFelipe Balbi phy_power_off(dwc->usb3_generic_phy); 522c499ff71SFelipe Balbi } 523c499ff71SFelipe Balbi 524b5a65c40SHuang Rui /** 52572246da4SFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 52672246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 52772246da4SFelipe Balbi * 52872246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 52972246da4SFelipe Balbi */ 53041ac7b3aSBill Pemberton static int dwc3_core_init(struct dwc3 *dwc) 53172246da4SFelipe Balbi { 5320ffcaf37SFelipe Balbi u32 hwparams4 = dwc->hwparams.hwparams4; 53372246da4SFelipe Balbi u32 reg; 53472246da4SFelipe Balbi int ret; 53572246da4SFelipe Balbi 5367650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 5377650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 538690fb371SJohn Youn if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) { 539690fb371SJohn Youn /* Detected DWC_usb3 IP */ 540690fb371SJohn Youn dwc->revision = reg; 541690fb371SJohn Youn } else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) { 542690fb371SJohn Youn /* Detected DWC_usb31 IP */ 543690fb371SJohn Youn dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); 544690fb371SJohn Youn dwc->revision |= DWC3_REVISION_IS_DWC31; 545690fb371SJohn Youn } else { 5467650bd74SSebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 5477650bd74SSebastian Andrzej Siewior ret = -ENODEV; 5487650bd74SSebastian Andrzej Siewior goto err0; 5497650bd74SSebastian Andrzej Siewior } 5507650bd74SSebastian Andrzej Siewior 551fa0ea13eSFelipe Balbi /* 552fa0ea13eSFelipe Balbi * Write Linux Version Code to our GUID register so it's easy to figure 553fa0ea13eSFelipe Balbi * out which kernel version a bug was found. 554fa0ea13eSFelipe Balbi */ 555fa0ea13eSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); 556fa0ea13eSFelipe Balbi 5570e1e5c47SPaul Zimmerman /* Handle USB2.0-only core configuration */ 5580e1e5c47SPaul Zimmerman if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 5590e1e5c47SPaul Zimmerman DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { 5600e1e5c47SPaul Zimmerman if (dwc->maximum_speed == USB_SPEED_SUPER) 5610e1e5c47SPaul Zimmerman dwc->maximum_speed = USB_SPEED_HIGH; 5620e1e5c47SPaul Zimmerman } 5630e1e5c47SPaul Zimmerman 56472246da4SFelipe Balbi /* issue device SoftReset too */ 565c5cc74e8SHeikki Krogerus ret = dwc3_soft_reset(dwc); 566c5cc74e8SHeikki Krogerus if (ret) 56772246da4SFelipe Balbi goto err0; 56872246da4SFelipe Balbi 56957303488SKishon Vijay Abraham I ret = dwc3_core_soft_reset(dwc); 57057303488SKishon Vijay Abraham I if (ret) 57157303488SKishon Vijay Abraham I goto err0; 57258a0f23fSPratyush Anand 573c499ff71SFelipe Balbi ret = dwc3_phy_setup(dwc); 574c499ff71SFelipe Balbi if (ret) 575c499ff71SFelipe Balbi goto err0; 576c499ff71SFelipe Balbi 5774878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 5783e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 5794878a028SSebastian Andrzej Siewior 580164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 5814878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 58232a4a135SFelipe Balbi /** 58332a4a135SFelipe Balbi * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an 58432a4a135SFelipe Balbi * issue which would cause xHCI compliance tests to fail. 58532a4a135SFelipe Balbi * 58632a4a135SFelipe Balbi * Because of that we cannot enable clock gating on such 58732a4a135SFelipe Balbi * configurations. 58832a4a135SFelipe Balbi * 58932a4a135SFelipe Balbi * Refers to: 59032a4a135SFelipe Balbi * 59132a4a135SFelipe Balbi * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based 59232a4a135SFelipe Balbi * SOF/ITP Mode Used 59332a4a135SFelipe Balbi */ 59432a4a135SFelipe Balbi if ((dwc->dr_mode == USB_DR_MODE_HOST || 59532a4a135SFelipe Balbi dwc->dr_mode == USB_DR_MODE_OTG) && 59632a4a135SFelipe Balbi (dwc->revision >= DWC3_REVISION_210A && 59732a4a135SFelipe Balbi dwc->revision <= DWC3_REVISION_250A)) 59832a4a135SFelipe Balbi reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; 59932a4a135SFelipe Balbi else 6004878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 6014878a028SSebastian Andrzej Siewior break; 6020ffcaf37SFelipe Balbi case DWC3_GHWPARAMS1_EN_PWROPT_HIB: 6030ffcaf37SFelipe Balbi /* enable hibernation here */ 6040ffcaf37SFelipe Balbi dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); 6052eac3992SHuang Rui 6062eac3992SHuang Rui /* 6072eac3992SHuang Rui * REVISIT Enabling this bit so that host-mode hibernation 6082eac3992SHuang Rui * will work. Device-mode hibernation is not yet implemented. 6092eac3992SHuang Rui */ 6102eac3992SHuang Rui reg |= DWC3_GCTL_GBLHIBERNATIONEN; 6110ffcaf37SFelipe Balbi break; 6124878a028SSebastian Andrzej Siewior default: 6131407bf13SFelipe Balbi dwc3_trace(trace_dwc3_core, "No power optimization available\n"); 6144878a028SSebastian Andrzej Siewior } 6154878a028SSebastian Andrzej Siewior 616946bd579SHuang Rui /* check if current dwc3 is on simulation board */ 617946bd579SHuang Rui if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { 6181407bf13SFelipe Balbi dwc3_trace(trace_dwc3_core, 6191407bf13SFelipe Balbi "running on FPGA platform\n"); 620946bd579SHuang Rui dwc->is_fpga = true; 621946bd579SHuang Rui } 622946bd579SHuang Rui 6233b81221aSHuang Rui WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga, 6243b81221aSHuang Rui "disable_scramble cannot be used on non-FPGA builds\n"); 6253b81221aSHuang Rui 6263b81221aSHuang Rui if (dwc->disable_scramble_quirk && dwc->is_fpga) 6273b81221aSHuang Rui reg |= DWC3_GCTL_DISSCRAMBLE; 6283b81221aSHuang Rui else 6293b81221aSHuang Rui reg &= ~DWC3_GCTL_DISSCRAMBLE; 6303b81221aSHuang Rui 6319a5b2f31SHuang Rui if (dwc->u2exit_lfps_quirk) 6329a5b2f31SHuang Rui reg |= DWC3_GCTL_U2EXIT_LFPS; 6339a5b2f31SHuang Rui 6344878a028SSebastian Andrzej Siewior /* 6354878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 6361d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 6374878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 6381d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 6394878a028SSebastian Andrzej Siewior */ 6404878a028SSebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 6414878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 6424878a028SSebastian Andrzej Siewior 6434878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 6444878a028SSebastian Andrzej Siewior 645c499ff71SFelipe Balbi dwc3_core_num_eps(dwc); 6460ffcaf37SFelipe Balbi 6470ffcaf37SFelipe Balbi ret = dwc3_setup_scratch_buffers(dwc); 6480ffcaf37SFelipe Balbi if (ret) 649c499ff71SFelipe Balbi goto err1; 650c499ff71SFelipe Balbi 651c499ff71SFelipe Balbi /* Adjust Frame Length */ 652c499ff71SFelipe Balbi dwc3_frame_length_adjustment(dwc); 653c499ff71SFelipe Balbi 654c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 0); 655c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 0); 656c499ff71SFelipe Balbi ret = phy_power_on(dwc->usb2_generic_phy); 657c499ff71SFelipe Balbi if (ret < 0) 6580ffcaf37SFelipe Balbi goto err2; 6590ffcaf37SFelipe Balbi 660c499ff71SFelipe Balbi ret = phy_power_on(dwc->usb3_generic_phy); 661c499ff71SFelipe Balbi if (ret < 0) 662c499ff71SFelipe Balbi goto err3; 663c499ff71SFelipe Balbi 664c499ff71SFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 665c499ff71SFelipe Balbi if (ret) { 666c499ff71SFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 667c499ff71SFelipe Balbi goto err4; 668c499ff71SFelipe Balbi } 669c499ff71SFelipe Balbi 67072246da4SFelipe Balbi return 0; 67172246da4SFelipe Balbi 672c499ff71SFelipe Balbi err4: 673c499ff71SFelipe Balbi phy_power_off(dwc->usb2_generic_phy); 674c499ff71SFelipe Balbi 675c499ff71SFelipe Balbi err3: 676c499ff71SFelipe Balbi phy_power_off(dwc->usb3_generic_phy); 677c499ff71SFelipe Balbi 6780ffcaf37SFelipe Balbi err2: 679c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 1); 680c499ff71SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 1); 681c499ff71SFelipe Balbi dwc3_core_exit(dwc); 6820ffcaf37SFelipe Balbi 6830ffcaf37SFelipe Balbi err1: 6840ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 6850ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 68657303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 68757303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 6880ffcaf37SFelipe Balbi 68972246da4SFelipe Balbi err0: 69072246da4SFelipe Balbi return ret; 69172246da4SFelipe Balbi } 69272246da4SFelipe Balbi 6933c9f94acSFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc) 69472246da4SFelipe Balbi { 6953c9f94acSFelipe Balbi struct device *dev = dwc->dev; 696941ea361SFelipe Balbi struct device_node *node = dev->of_node; 6973c9f94acSFelipe Balbi int ret; 69872246da4SFelipe Balbi 6995088b6f5SKishon Vijay Abraham I if (node) { 7005088b6f5SKishon Vijay Abraham I dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); 7015088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); 702bb674907SFelipe Balbi } else { 703bb674907SFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 704bb674907SFelipe Balbi dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 7055088b6f5SKishon Vijay Abraham I } 7065088b6f5SKishon Vijay Abraham I 707d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb2_phy)) { 708d105e7f8SFelipe Balbi ret = PTR_ERR(dwc->usb2_phy); 709122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 710122f06e6SKishon Vijay Abraham I dwc->usb2_phy = NULL; 711122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 712d105e7f8SFelipe Balbi return ret; 713122f06e6SKishon Vijay Abraham I } else { 71451e1e7bcSFelipe Balbi dev_err(dev, "no usb2 phy configured\n"); 715122f06e6SKishon Vijay Abraham I return ret; 716122f06e6SKishon Vijay Abraham I } 71751e1e7bcSFelipe Balbi } 71851e1e7bcSFelipe Balbi 719d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb3_phy)) { 720315955d7SRuchika Kharwar ret = PTR_ERR(dwc->usb3_phy); 721122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 722122f06e6SKishon Vijay Abraham I dwc->usb3_phy = NULL; 723122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 724d105e7f8SFelipe Balbi return ret; 725122f06e6SKishon Vijay Abraham I } else { 72651e1e7bcSFelipe Balbi dev_err(dev, "no usb3 phy configured\n"); 727122f06e6SKishon Vijay Abraham I return ret; 728122f06e6SKishon Vijay Abraham I } 72951e1e7bcSFelipe Balbi } 73051e1e7bcSFelipe Balbi 73157303488SKishon Vijay Abraham I dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); 73257303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb2_generic_phy)) { 73357303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb2_generic_phy); 73457303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 73557303488SKishon Vijay Abraham I dwc->usb2_generic_phy = NULL; 73657303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 73757303488SKishon Vijay Abraham I return ret; 73857303488SKishon Vijay Abraham I } else { 73957303488SKishon Vijay Abraham I dev_err(dev, "no usb2 phy configured\n"); 74057303488SKishon Vijay Abraham I return ret; 74157303488SKishon Vijay Abraham I } 74257303488SKishon Vijay Abraham I } 74357303488SKishon Vijay Abraham I 74457303488SKishon Vijay Abraham I dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy"); 74557303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb3_generic_phy)) { 74657303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb3_generic_phy); 74757303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 74857303488SKishon Vijay Abraham I dwc->usb3_generic_phy = NULL; 74957303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 75057303488SKishon Vijay Abraham I return ret; 75157303488SKishon Vijay Abraham I } else { 75257303488SKishon Vijay Abraham I dev_err(dev, "no usb3 phy configured\n"); 75357303488SKishon Vijay Abraham I return ret; 75457303488SKishon Vijay Abraham I } 75557303488SKishon Vijay Abraham I } 75657303488SKishon Vijay Abraham I 7573c9f94acSFelipe Balbi return 0; 7583c9f94acSFelipe Balbi } 7593c9f94acSFelipe Balbi 7605f94adfeSFelipe Balbi static int dwc3_core_init_mode(struct dwc3 *dwc) 7615f94adfeSFelipe Balbi { 7625f94adfeSFelipe Balbi struct device *dev = dwc->dev; 7635f94adfeSFelipe Balbi int ret; 7645f94adfeSFelipe Balbi 7655f94adfeSFelipe Balbi switch (dwc->dr_mode) { 7665f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 7675f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); 7685f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 7695f94adfeSFelipe Balbi if (ret) { 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) { 7785f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 7795f94adfeSFelipe Balbi return ret; 7805f94adfeSFelipe Balbi } 7815f94adfeSFelipe Balbi break; 7825f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 7835f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); 7845f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 7855f94adfeSFelipe Balbi if (ret) { 7865f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 7875f94adfeSFelipe Balbi return ret; 7885f94adfeSFelipe Balbi } 7895f94adfeSFelipe Balbi 7905f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 7915f94adfeSFelipe Balbi if (ret) { 7925f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 7935f94adfeSFelipe Balbi return ret; 7945f94adfeSFelipe Balbi } 7955f94adfeSFelipe Balbi break; 7965f94adfeSFelipe Balbi default: 7975f94adfeSFelipe Balbi dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); 7985f94adfeSFelipe Balbi return -EINVAL; 7995f94adfeSFelipe Balbi } 8005f94adfeSFelipe Balbi 8015f94adfeSFelipe Balbi return 0; 8025f94adfeSFelipe Balbi } 8035f94adfeSFelipe Balbi 8045f94adfeSFelipe Balbi static void dwc3_core_exit_mode(struct dwc3 *dwc) 8055f94adfeSFelipe Balbi { 8065f94adfeSFelipe Balbi switch (dwc->dr_mode) { 8075f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 8085f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 8095f94adfeSFelipe Balbi break; 8105f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 8115f94adfeSFelipe Balbi dwc3_host_exit(dwc); 8125f94adfeSFelipe Balbi break; 8135f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 8145f94adfeSFelipe Balbi dwc3_host_exit(dwc); 8155f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 8165f94adfeSFelipe Balbi break; 8175f94adfeSFelipe Balbi default: 8185f94adfeSFelipe Balbi /* do nothing */ 8195f94adfeSFelipe Balbi break; 8205f94adfeSFelipe Balbi } 8215f94adfeSFelipe Balbi } 8225f94adfeSFelipe Balbi 8233c9f94acSFelipe Balbi #define DWC3_ALIGN_MASK (16 - 1) 8243c9f94acSFelipe Balbi 8253c9f94acSFelipe Balbi static int dwc3_probe(struct platform_device *pdev) 8263c9f94acSFelipe Balbi { 8273c9f94acSFelipe Balbi struct device *dev = &pdev->dev; 8283c9f94acSFelipe Balbi struct dwc3_platform_data *pdata = dev_get_platdata(dev); 8293c9f94acSFelipe Balbi struct resource *res; 8303c9f94acSFelipe Balbi struct dwc3 *dwc; 83180caf7d2SHuang Rui u8 lpm_nyet_threshold; 8326b6a0c9aSHuang Rui u8 tx_de_emphasis; 833460d098cSHuang Rui u8 hird_threshold; 8343c9f94acSFelipe Balbi 835b09e99eeSAndy Shevchenko int ret; 8363c9f94acSFelipe Balbi 8373c9f94acSFelipe Balbi void __iomem *regs; 8383c9f94acSFelipe Balbi void *mem; 8393c9f94acSFelipe Balbi 8403c9f94acSFelipe Balbi mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 841734d5a53SJingoo Han if (!mem) 8423c9f94acSFelipe Balbi return -ENOMEM; 843734d5a53SJingoo Han 8443c9f94acSFelipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 8453c9f94acSFelipe Balbi dwc->mem = mem; 8463c9f94acSFelipe Balbi dwc->dev = dev; 8473c9f94acSFelipe Balbi 8483c9f94acSFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 8493c9f94acSFelipe Balbi if (!res) { 8503c9f94acSFelipe Balbi dev_err(dev, "missing IRQ\n"); 8513c9f94acSFelipe Balbi return -ENODEV; 8523c9f94acSFelipe Balbi } 8533c9f94acSFelipe Balbi dwc->xhci_resources[1].start = res->start; 8543c9f94acSFelipe Balbi dwc->xhci_resources[1].end = res->end; 8553c9f94acSFelipe Balbi dwc->xhci_resources[1].flags = res->flags; 8563c9f94acSFelipe Balbi dwc->xhci_resources[1].name = res->name; 8573c9f94acSFelipe Balbi 8583c9f94acSFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 8593c9f94acSFelipe Balbi if (!res) { 8603c9f94acSFelipe Balbi dev_err(dev, "missing memory resource\n"); 8613c9f94acSFelipe Balbi return -ENODEV; 8623c9f94acSFelipe Balbi } 8633c9f94acSFelipe Balbi 864f32a5e23SVivek Gautam dwc->xhci_resources[0].start = res->start; 865f32a5e23SVivek Gautam dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 866f32a5e23SVivek Gautam DWC3_XHCI_REGS_END; 867f32a5e23SVivek Gautam dwc->xhci_resources[0].flags = res->flags; 868f32a5e23SVivek Gautam dwc->xhci_resources[0].name = res->name; 869f32a5e23SVivek Gautam 870f32a5e23SVivek Gautam res->start += DWC3_GLOBALS_REGS_START; 871f32a5e23SVivek Gautam 872f32a5e23SVivek Gautam /* 873f32a5e23SVivek Gautam * Request memory region but exclude xHCI regs, 874f32a5e23SVivek Gautam * since it will be requested by the xhci-plat driver. 875f32a5e23SVivek Gautam */ 876f32a5e23SVivek Gautam regs = devm_ioremap_resource(dev, res); 8773da1f6eeSFelipe Balbi if (IS_ERR(regs)) { 8783da1f6eeSFelipe Balbi ret = PTR_ERR(regs); 8793da1f6eeSFelipe Balbi goto err0; 8803da1f6eeSFelipe Balbi } 881f32a5e23SVivek Gautam 882f32a5e23SVivek Gautam dwc->regs = regs; 883f32a5e23SVivek Gautam dwc->regs_size = resource_size(res); 884f32a5e23SVivek Gautam 88580caf7d2SHuang Rui /* default to highest possible threshold */ 88680caf7d2SHuang Rui lpm_nyet_threshold = 0xff; 88780caf7d2SHuang Rui 8886b6a0c9aSHuang Rui /* default to -3.5dB de-emphasis */ 8896b6a0c9aSHuang Rui tx_de_emphasis = 1; 8906b6a0c9aSHuang Rui 891460d098cSHuang Rui /* 892460d098cSHuang Rui * default to assert utmi_sleep_n and use maximum allowed HIRD 893460d098cSHuang Rui * threshold value of 0b1100 894460d098cSHuang Rui */ 895460d098cSHuang Rui hird_threshold = 12; 896460d098cSHuang Rui 89763863b98SHeikki Krogerus dwc->maximum_speed = usb_get_maximum_speed(dev); 89806e7114fSHeikki Krogerus dwc->dr_mode = usb_get_dr_mode(dev); 89963863b98SHeikki Krogerus 9003d128919SHeikki Krogerus dwc->has_lpm_erratum = device_property_read_bool(dev, 90180caf7d2SHuang Rui "snps,has-lpm-erratum"); 9023d128919SHeikki Krogerus device_property_read_u8(dev, "snps,lpm-nyet-threshold", 90380caf7d2SHuang Rui &lpm_nyet_threshold); 9043d128919SHeikki Krogerus dwc->is_utmi_l1_suspend = device_property_read_bool(dev, 905460d098cSHuang Rui "snps,is-utmi-l1-suspend"); 9063d128919SHeikki Krogerus device_property_read_u8(dev, "snps,hird-threshold", 907460d098cSHuang Rui &hird_threshold); 9083d128919SHeikki Krogerus dwc->usb3_lpm_capable = device_property_read_bool(dev, 909eac68e8fSRobert Baldyga "snps,usb3_lpm_capable"); 9103c9f94acSFelipe Balbi 9113d128919SHeikki Krogerus dwc->disable_scramble_quirk = device_property_read_bool(dev, 9123b81221aSHuang Rui "snps,disable_scramble_quirk"); 9133d128919SHeikki Krogerus dwc->u2exit_lfps_quirk = device_property_read_bool(dev, 9149a5b2f31SHuang Rui "snps,u2exit_lfps_quirk"); 9153d128919SHeikki Krogerus dwc->u2ss_inp3_quirk = device_property_read_bool(dev, 916b5a65c40SHuang Rui "snps,u2ss_inp3_quirk"); 9173d128919SHeikki Krogerus dwc->req_p1p2p3_quirk = device_property_read_bool(dev, 918df31f5b3SHuang Rui "snps,req_p1p2p3_quirk"); 9193d128919SHeikki Krogerus dwc->del_p1p2p3_quirk = device_property_read_bool(dev, 920a2a1d0f5SHuang Rui "snps,del_p1p2p3_quirk"); 9213d128919SHeikki Krogerus dwc->del_phy_power_chg_quirk = device_property_read_bool(dev, 92241c06ffdSHuang Rui "snps,del_phy_power_chg_quirk"); 9233d128919SHeikki Krogerus dwc->lfps_filter_quirk = device_property_read_bool(dev, 924fb67afcaSHuang Rui "snps,lfps_filter_quirk"); 9253d128919SHeikki Krogerus dwc->rx_detect_poll_quirk = device_property_read_bool(dev, 92614f4ac53SHuang Rui "snps,rx_detect_poll_quirk"); 9273d128919SHeikki Krogerus dwc->dis_u3_susphy_quirk = device_property_read_bool(dev, 92859acfa20SHuang Rui "snps,dis_u3_susphy_quirk"); 9293d128919SHeikki Krogerus dwc->dis_u2_susphy_quirk = device_property_read_bool(dev, 9300effe0a3SHuang Rui "snps,dis_u2_susphy_quirk"); 931ec791d14SJohn Youn dwc->dis_enblslpm_quirk = device_property_read_bool(dev, 932ec791d14SJohn Youn "snps,dis_enblslpm_quirk"); 933e58dd357SRajesh Bhagat dwc->dis_rxdet_inp3_quirk = device_property_read_bool(dev, 934e58dd357SRajesh Bhagat "snps,dis_rxdet_inp3_quirk"); 9356b6a0c9aSHuang Rui 9363d128919SHeikki Krogerus dwc->tx_de_emphasis_quirk = device_property_read_bool(dev, 9376b6a0c9aSHuang Rui "snps,tx_de_emphasis_quirk"); 9383d128919SHeikki Krogerus device_property_read_u8(dev, "snps,tx_de_emphasis", 9396b6a0c9aSHuang Rui &tx_de_emphasis); 9403d128919SHeikki Krogerus device_property_read_string(dev, "snps,hsphy_interface", 9413e10a2ceSHeikki Krogerus &dwc->hsphy_interface); 9423d128919SHeikki Krogerus device_property_read_u32(dev, "snps,quirk-frame-length-adjustment", 943bcdb3272SFelipe Balbi &dwc->fladj); 9443d128919SHeikki Krogerus 9453d128919SHeikki Krogerus if (pdata) { 9463c9f94acSFelipe Balbi dwc->maximum_speed = pdata->maximum_speed; 94780caf7d2SHuang Rui dwc->has_lpm_erratum = pdata->has_lpm_erratum; 94880caf7d2SHuang Rui if (pdata->lpm_nyet_threshold) 94980caf7d2SHuang Rui lpm_nyet_threshold = pdata->lpm_nyet_threshold; 950460d098cSHuang Rui dwc->is_utmi_l1_suspend = pdata->is_utmi_l1_suspend; 951460d098cSHuang Rui if (pdata->hird_threshold) 952460d098cSHuang Rui hird_threshold = pdata->hird_threshold; 9533c9f94acSFelipe Balbi 954eac68e8fSRobert Baldyga dwc->usb3_lpm_capable = pdata->usb3_lpm_capable; 9553c9f94acSFelipe Balbi dwc->dr_mode = pdata->dr_mode; 9563b81221aSHuang Rui 9573b81221aSHuang Rui dwc->disable_scramble_quirk = pdata->disable_scramble_quirk; 9589a5b2f31SHuang Rui dwc->u2exit_lfps_quirk = pdata->u2exit_lfps_quirk; 959b5a65c40SHuang Rui dwc->u2ss_inp3_quirk = pdata->u2ss_inp3_quirk; 960df31f5b3SHuang Rui dwc->req_p1p2p3_quirk = pdata->req_p1p2p3_quirk; 961a2a1d0f5SHuang Rui dwc->del_p1p2p3_quirk = pdata->del_p1p2p3_quirk; 96241c06ffdSHuang Rui dwc->del_phy_power_chg_quirk = pdata->del_phy_power_chg_quirk; 963fb67afcaSHuang Rui dwc->lfps_filter_quirk = pdata->lfps_filter_quirk; 96414f4ac53SHuang Rui dwc->rx_detect_poll_quirk = pdata->rx_detect_poll_quirk; 96559acfa20SHuang Rui dwc->dis_u3_susphy_quirk = pdata->dis_u3_susphy_quirk; 9660effe0a3SHuang Rui dwc->dis_u2_susphy_quirk = pdata->dis_u2_susphy_quirk; 967ec791d14SJohn Youn dwc->dis_enblslpm_quirk = pdata->dis_enblslpm_quirk; 968e58dd357SRajesh Bhagat dwc->dis_rxdet_inp3_quirk = pdata->dis_rxdet_inp3_quirk; 9696b6a0c9aSHuang Rui 9706b6a0c9aSHuang Rui dwc->tx_de_emphasis_quirk = pdata->tx_de_emphasis_quirk; 9716b6a0c9aSHuang Rui if (pdata->tx_de_emphasis) 9726b6a0c9aSHuang Rui tx_de_emphasis = pdata->tx_de_emphasis; 9733e10a2ceSHeikki Krogerus 9743e10a2ceSHeikki Krogerus dwc->hsphy_interface = pdata->hsphy_interface; 975bcdb3272SFelipe Balbi dwc->fladj = pdata->fladj_value; 9763c9f94acSFelipe Balbi } 9773c9f94acSFelipe Balbi 97880caf7d2SHuang Rui dwc->lpm_nyet_threshold = lpm_nyet_threshold; 9796b6a0c9aSHuang Rui dwc->tx_de_emphasis = tx_de_emphasis; 98080caf7d2SHuang Rui 981460d098cSHuang Rui dwc->hird_threshold = hird_threshold 982460d098cSHuang Rui | (dwc->is_utmi_l1_suspend << 4); 983460d098cSHuang Rui 9846c89cce0SHeikki Krogerus platform_set_drvdata(pdev, dwc); 9852917e718SHeikki Krogerus dwc3_cache_hwparams(dwc); 9866c89cce0SHeikki Krogerus 9873c9f94acSFelipe Balbi ret = dwc3_core_get_phy(dwc); 9883c9f94acSFelipe Balbi if (ret) 9893da1f6eeSFelipe Balbi goto err0; 9903c9f94acSFelipe Balbi 99172246da4SFelipe Balbi spin_lock_init(&dwc->lock); 99272246da4SFelipe Balbi 99319bacdc9SHeikki Krogerus if (!dev->dma_mask) { 994ddff14f1SKishon Vijay Abraham I dev->dma_mask = dev->parent->dma_mask; 995ddff14f1SKishon Vijay Abraham I dev->dma_parms = dev->parent->dma_parms; 996ddff14f1SKishon Vijay Abraham I dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); 99719bacdc9SHeikki Krogerus } 998ddff14f1SKishon Vijay Abraham I 999802ca850SChanho Park pm_runtime_enable(dev); 1000802ca850SChanho Park pm_runtime_get_sync(dev); 1001802ca850SChanho Park pm_runtime_forbid(dev); 100272246da4SFelipe Balbi 10033921426bSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 10043921426bSFelipe Balbi if (ret) { 10053921426bSFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 10063921426bSFelipe Balbi ret = -ENOMEM; 1007c499ff71SFelipe Balbi goto err0; 10083921426bSFelipe Balbi } 10093921426bSFelipe Balbi 101032a4a135SFelipe Balbi if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) 101132a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_HOST; 101232a4a135SFelipe Balbi else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) 101332a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_PERIPHERAL; 101432a4a135SFelipe Balbi 101532a4a135SFelipe Balbi if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) 101632a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_OTG; 101732a4a135SFelipe Balbi 1018c499ff71SFelipe Balbi ret = dwc3_alloc_scratch_buffers(dwc); 1019c499ff71SFelipe Balbi if (ret) 1020c499ff71SFelipe Balbi goto err1; 1021c499ff71SFelipe Balbi 102272246da4SFelipe Balbi ret = dwc3_core_init(dwc); 102372246da4SFelipe Balbi if (ret) { 1024802ca850SChanho Park dev_err(dev, "failed to initialize core\n"); 1025c499ff71SFelipe Balbi goto err2; 102672246da4SFelipe Balbi } 102772246da4SFelipe Balbi 102877966eb8SJohn Youn /* Check the maximum_speed parameter */ 102977966eb8SJohn Youn switch (dwc->maximum_speed) { 103077966eb8SJohn Youn case USB_SPEED_LOW: 103177966eb8SJohn Youn case USB_SPEED_FULL: 103277966eb8SJohn Youn case USB_SPEED_HIGH: 103377966eb8SJohn Youn case USB_SPEED_SUPER: 103477966eb8SJohn Youn case USB_SPEED_SUPER_PLUS: 103577966eb8SJohn Youn break; 103677966eb8SJohn Youn default: 103777966eb8SJohn Youn dev_err(dev, "invalid maximum_speed parameter %d\n", 103877966eb8SJohn Youn dwc->maximum_speed); 103977966eb8SJohn Youn /* fall through */ 104077966eb8SJohn Youn case USB_SPEED_UNKNOWN: 104177966eb8SJohn Youn /* default to superspeed */ 10422c7f1bd9SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER; 10432c7f1bd9SJohn Youn 10442c7f1bd9SJohn Youn /* 10452c7f1bd9SJohn Youn * default to superspeed plus if we are capable. 10462c7f1bd9SJohn Youn */ 10472c7f1bd9SJohn Youn if (dwc3_is_usb31(dwc) && 10482c7f1bd9SJohn Youn (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 10492c7f1bd9SJohn Youn DWC3_GHWPARAMS3_SSPHY_IFC_GEN2)) 10502c7f1bd9SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER_PLUS; 105177966eb8SJohn Youn 105277966eb8SJohn Youn break; 10532c7f1bd9SJohn Youn } 10542c7f1bd9SJohn Youn 10555f94adfeSFelipe Balbi ret = dwc3_core_init_mode(dwc); 10565f94adfeSFelipe Balbi if (ret) 1057c499ff71SFelipe Balbi goto err3; 105872246da4SFelipe Balbi 10594e9f3118SDu, Changbin dwc3_debugfs_init(dwc); 1060802ca850SChanho Park pm_runtime_allow(dev); 106172246da4SFelipe Balbi 106272246da4SFelipe Balbi return 0; 106372246da4SFelipe Balbi 1064c499ff71SFelipe Balbi err3: 1065f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 1066f122d33eSFelipe Balbi 10673da1f6eeSFelipe Balbi err2: 1068c499ff71SFelipe Balbi dwc3_free_scratch_buffers(dwc); 106972246da4SFelipe Balbi 10703da1f6eeSFelipe Balbi err1: 10713921426bSFelipe Balbi dwc3_free_event_buffers(dwc); 107288bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 10733921426bSFelipe Balbi 10743da1f6eeSFelipe Balbi err0: 10753da1f6eeSFelipe Balbi /* 10763da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 10773da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 10783da1f6eeSFelipe Balbi * memory region the next time probe is called. 10793da1f6eeSFelipe Balbi */ 10803da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 10813da1f6eeSFelipe Balbi 108272246da4SFelipe Balbi return ret; 108372246da4SFelipe Balbi } 108472246da4SFelipe Balbi 1085fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev) 108672246da4SFelipe Balbi { 108772246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 10883da1f6eeSFelipe Balbi struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 10893da1f6eeSFelipe Balbi 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 1103c499ff71SFelipe Balbi dwc3_free_event_buffers(dwc); 1104c499ff71SFelipe Balbi dwc3_free_scratch_buffers(dwc); 1105c499ff71SFelipe Balbi 11067415f17cSFelipe Balbi pm_runtime_put_sync(&pdev->dev); 11077415f17cSFelipe Balbi pm_runtime_disable(&pdev->dev); 11087415f17cSFelipe Balbi 110972246da4SFelipe Balbi return 0; 111072246da4SFelipe Balbi } 111172246da4SFelipe Balbi 11127415f17cSFelipe Balbi #ifdef CONFIG_PM_SLEEP 11137415f17cSFelipe Balbi static int dwc3_suspend(struct device *dev) 11147415f17cSFelipe Balbi { 11157415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 11167415f17cSFelipe Balbi unsigned long flags; 11177415f17cSFelipe Balbi 11187415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 11197415f17cSFelipe Balbi 1120a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 1121a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 1122a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 11237415f17cSFelipe Balbi dwc3_gadget_suspend(dwc); 11247415f17cSFelipe Balbi /* FALLTHROUGH */ 1125a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 11267415f17cSFelipe Balbi default: 11270b0231aaSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 11287415f17cSFelipe Balbi break; 11297415f17cSFelipe Balbi } 11307415f17cSFelipe Balbi 11317415f17cSFelipe Balbi dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL); 11327415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 11337415f17cSFelipe Balbi 11347415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 11357415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 113657303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 113757303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 11387415f17cSFelipe Balbi 11395c4ad318SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 1); 11405c4ad318SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 1); 11415c4ad318SFelipe Balbi WARN_ON(phy_power_off(dwc->usb2_generic_phy) < 0); 11425c4ad318SFelipe Balbi WARN_ON(phy_power_off(dwc->usb3_generic_phy) < 0); 11435c4ad318SFelipe Balbi 11446344475fSSekhar Nori pinctrl_pm_select_sleep_state(dev); 11456344475fSSekhar Nori 11467415f17cSFelipe Balbi return 0; 11477415f17cSFelipe Balbi } 11487415f17cSFelipe Balbi 11497415f17cSFelipe Balbi static int dwc3_resume(struct device *dev) 11507415f17cSFelipe Balbi { 11517415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 11527415f17cSFelipe Balbi unsigned long flags; 115357303488SKishon Vijay Abraham I int ret; 11547415f17cSFelipe Balbi 11556344475fSSekhar Nori pinctrl_pm_select_default_state(dev); 11566344475fSSekhar Nori 11575c4ad318SFelipe Balbi usb_phy_set_suspend(dwc->usb2_phy, 0); 11585c4ad318SFelipe Balbi usb_phy_set_suspend(dwc->usb3_phy, 0); 11595c4ad318SFelipe Balbi ret = phy_power_on(dwc->usb2_generic_phy); 11605c4ad318SFelipe Balbi if (ret < 0) 11615c4ad318SFelipe Balbi return ret; 11625c4ad318SFelipe Balbi 11635c4ad318SFelipe Balbi ret = phy_power_on(dwc->usb3_generic_phy); 11645c4ad318SFelipe Balbi if (ret < 0) 11655c4ad318SFelipe Balbi goto err_usb2phy_power; 11665c4ad318SFelipe Balbi 11677415f17cSFelipe Balbi usb_phy_init(dwc->usb3_phy); 11687415f17cSFelipe Balbi usb_phy_init(dwc->usb2_phy); 116957303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 117057303488SKishon Vijay Abraham I if (ret < 0) 11715c4ad318SFelipe Balbi goto err_usb3phy_power; 117257303488SKishon Vijay Abraham I 117357303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 117457303488SKishon Vijay Abraham I if (ret < 0) 117557303488SKishon Vijay Abraham I goto err_usb2phy_init; 11767415f17cSFelipe Balbi 11777415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 11787415f17cSFelipe Balbi 11790b0231aaSFelipe Balbi dwc3_event_buffers_setup(dwc); 11807415f17cSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl); 11817415f17cSFelipe Balbi 1182a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 1183a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 1184a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 11857415f17cSFelipe Balbi dwc3_gadget_resume(dwc); 11867415f17cSFelipe Balbi /* FALLTHROUGH */ 1187a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 11887415f17cSFelipe Balbi default: 11897415f17cSFelipe Balbi /* do nothing */ 11907415f17cSFelipe Balbi break; 11917415f17cSFelipe Balbi } 11927415f17cSFelipe Balbi 11937415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 11947415f17cSFelipe Balbi 11957415f17cSFelipe Balbi pm_runtime_disable(dev); 11967415f17cSFelipe Balbi pm_runtime_set_active(dev); 11977415f17cSFelipe Balbi pm_runtime_enable(dev); 11987415f17cSFelipe Balbi 11997415f17cSFelipe Balbi return 0; 120057303488SKishon Vijay Abraham I 120157303488SKishon Vijay Abraham I err_usb2phy_init: 120257303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 120357303488SKishon Vijay Abraham I 12045c4ad318SFelipe Balbi err_usb3phy_power: 12055c4ad318SFelipe Balbi phy_power_off(dwc->usb3_generic_phy); 12065c4ad318SFelipe Balbi 12075c4ad318SFelipe Balbi err_usb2phy_power: 12085c4ad318SFelipe Balbi phy_power_off(dwc->usb2_generic_phy); 12095c4ad318SFelipe Balbi 121057303488SKishon Vijay Abraham I return ret; 12117415f17cSFelipe Balbi } 12127f370ed0SFelipe Balbi #endif /* CONFIG_PM_SLEEP */ 12137415f17cSFelipe Balbi 12147415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = { 12157415f17cSFelipe Balbi SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 12167415f17cSFelipe Balbi }; 12177415f17cSFelipe Balbi 12185088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF 12195088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = { 12205088b6f5SKishon Vijay Abraham I { 122122a5aa17SFelipe Balbi .compatible = "snps,dwc3" 122222a5aa17SFelipe Balbi }, 122322a5aa17SFelipe Balbi { 12245088b6f5SKishon Vijay Abraham I .compatible = "synopsys,dwc3" 12255088b6f5SKishon Vijay Abraham I }, 12265088b6f5SKishon Vijay Abraham I { }, 12275088b6f5SKishon Vijay Abraham I }; 12285088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match); 12295088b6f5SKishon Vijay Abraham I #endif 12305088b6f5SKishon Vijay Abraham I 1231404905a6SHeikki Krogerus #ifdef CONFIG_ACPI 1232404905a6SHeikki Krogerus 1233404905a6SHeikki Krogerus #define ACPI_ID_INTEL_BSW "808622B7" 1234404905a6SHeikki Krogerus 1235404905a6SHeikki Krogerus static const struct acpi_device_id dwc3_acpi_match[] = { 1236404905a6SHeikki Krogerus { ACPI_ID_INTEL_BSW, 0 }, 1237404905a6SHeikki Krogerus { }, 1238404905a6SHeikki Krogerus }; 1239404905a6SHeikki Krogerus MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match); 1240404905a6SHeikki Krogerus #endif 1241404905a6SHeikki Krogerus 124272246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 124372246da4SFelipe Balbi .probe = dwc3_probe, 12447690417dSBill Pemberton .remove = dwc3_remove, 124572246da4SFelipe Balbi .driver = { 124672246da4SFelipe Balbi .name = "dwc3", 12475088b6f5SKishon Vijay Abraham I .of_match_table = of_match_ptr(of_dwc3_match), 1248404905a6SHeikki Krogerus .acpi_match_table = ACPI_PTR(dwc3_acpi_match), 12497f370ed0SFelipe Balbi .pm = &dwc3_dev_pm_ops, 125072246da4SFelipe Balbi }, 125172246da4SFelipe Balbi }; 125272246da4SFelipe Balbi 1253b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 1254b1116dccSTobias Klauser 12557ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 125672246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 12575945f789SFelipe Balbi MODULE_LICENSE("GPL v2"); 125872246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 1259