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 6372246da4SFelipe Balbi /** 6472246da4SFelipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 6572246da4SFelipe Balbi * @dwc: pointer to our context structure 6672246da4SFelipe Balbi */ 6757303488SKishon Vijay Abraham I static int dwc3_core_soft_reset(struct dwc3 *dwc) 6872246da4SFelipe Balbi { 6972246da4SFelipe Balbi u32 reg; 70f59dcab1SFelipe Balbi int retries = 1000; 7157303488SKishon Vijay Abraham I int ret; 7272246da4SFelipe Balbi 7351e1e7bcSFelipe Balbi usb_phy_init(dwc->usb2_phy); 7451e1e7bcSFelipe Balbi usb_phy_init(dwc->usb3_phy); 7557303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 7657303488SKishon Vijay Abraham I if (ret < 0) 7757303488SKishon Vijay Abraham I return ret; 7857303488SKishon Vijay Abraham I 7957303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 8057303488SKishon Vijay Abraham I if (ret < 0) { 8157303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 8257303488SKishon Vijay Abraham I return ret; 8357303488SKishon Vijay Abraham I } 8472246da4SFelipe Balbi 85f59dcab1SFelipe Balbi /* 86f59dcab1SFelipe Balbi * We're resetting only the device side because, if we're in host mode, 87f59dcab1SFelipe Balbi * XHCI driver will reset the host block. If dwc3 was configured for 88f59dcab1SFelipe Balbi * host-only mode, then we can return early. 89f59dcab1SFelipe Balbi */ 90f59dcab1SFelipe Balbi if (dwc->dr_mode == USB_DR_MODE_HOST) 9157303488SKishon Vijay Abraham I return 0; 92f59dcab1SFelipe Balbi 93f59dcab1SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 94f59dcab1SFelipe Balbi reg |= DWC3_DCTL_CSFTRST; 95f59dcab1SFelipe Balbi dwc3_writel(dwc->regs, DWC3_DCTL, reg); 96f59dcab1SFelipe Balbi 97f59dcab1SFelipe Balbi do { 98f59dcab1SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 99f59dcab1SFelipe Balbi if (!(reg & DWC3_DCTL_CSFTRST)) 100f59dcab1SFelipe Balbi return 0; 101f59dcab1SFelipe Balbi 102f59dcab1SFelipe Balbi udelay(1); 103f59dcab1SFelipe Balbi } while (--retries); 104f59dcab1SFelipe Balbi 105f59dcab1SFelipe Balbi return -ETIMEDOUT; 10672246da4SFelipe Balbi } 10772246da4SFelipe Balbi 10872246da4SFelipe Balbi /** 109c5cc74e8SHeikki Krogerus * dwc3_soft_reset - Issue soft reset 110c5cc74e8SHeikki Krogerus * @dwc: Pointer to our controller context structure 111c5cc74e8SHeikki Krogerus */ 112c5cc74e8SHeikki Krogerus static int dwc3_soft_reset(struct dwc3 *dwc) 113c5cc74e8SHeikki Krogerus { 114c5cc74e8SHeikki Krogerus unsigned long timeout; 115c5cc74e8SHeikki Krogerus u32 reg; 116c5cc74e8SHeikki Krogerus 117c5cc74e8SHeikki Krogerus timeout = jiffies + msecs_to_jiffies(500); 118c5cc74e8SHeikki Krogerus dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); 119c5cc74e8SHeikki Krogerus do { 120c5cc74e8SHeikki Krogerus reg = dwc3_readl(dwc->regs, DWC3_DCTL); 121c5cc74e8SHeikki Krogerus if (!(reg & DWC3_DCTL_CSFTRST)) 122c5cc74e8SHeikki Krogerus break; 123c5cc74e8SHeikki Krogerus 124c5cc74e8SHeikki Krogerus if (time_after(jiffies, timeout)) { 125c5cc74e8SHeikki Krogerus dev_err(dwc->dev, "Reset Timed Out\n"); 126c5cc74e8SHeikki Krogerus return -ETIMEDOUT; 127c5cc74e8SHeikki Krogerus } 128c5cc74e8SHeikki Krogerus 129c5cc74e8SHeikki Krogerus cpu_relax(); 130c5cc74e8SHeikki Krogerus } while (true); 131c5cc74e8SHeikki Krogerus 132c5cc74e8SHeikki Krogerus return 0; 133c5cc74e8SHeikki Krogerus } 134c5cc74e8SHeikki Krogerus 135db2be4e9SNikhil Badola /* 136db2be4e9SNikhil Badola * dwc3_frame_length_adjustment - Adjusts frame length if required 137db2be4e9SNikhil Badola * @dwc3: Pointer to our controller context structure 138db2be4e9SNikhil Badola * @fladj: Value of GFLADJ_30MHZ to adjust frame length 139db2be4e9SNikhil Badola */ 140db2be4e9SNikhil Badola static void dwc3_frame_length_adjustment(struct dwc3 *dwc, u32 fladj) 141db2be4e9SNikhil Badola { 142db2be4e9SNikhil Badola u32 reg; 143db2be4e9SNikhil Badola u32 dft; 144db2be4e9SNikhil Badola 145db2be4e9SNikhil Badola if (dwc->revision < DWC3_REVISION_250A) 146db2be4e9SNikhil Badola return; 147db2be4e9SNikhil Badola 148db2be4e9SNikhil Badola if (fladj == 0) 149db2be4e9SNikhil Badola return; 150db2be4e9SNikhil Badola 151db2be4e9SNikhil Badola reg = dwc3_readl(dwc->regs, DWC3_GFLADJ); 152db2be4e9SNikhil Badola dft = reg & DWC3_GFLADJ_30MHZ_MASK; 153db2be4e9SNikhil Badola if (!dev_WARN_ONCE(dwc->dev, dft == fladj, 154db2be4e9SNikhil Badola "request value same as default, ignoring\n")) { 155db2be4e9SNikhil Badola reg &= ~DWC3_GFLADJ_30MHZ_MASK; 156db2be4e9SNikhil Badola reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | fladj; 157db2be4e9SNikhil Badola dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); 158db2be4e9SNikhil Badola } 159db2be4e9SNikhil Badola } 160db2be4e9SNikhil Badola 161c5cc74e8SHeikki Krogerus /** 16272246da4SFelipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 16372246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 16472246da4SFelipe Balbi * @evt: Pointer to event buffer to be freed 16572246da4SFelipe Balbi */ 16672246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc, 16772246da4SFelipe Balbi struct dwc3_event_buffer *evt) 16872246da4SFelipe Balbi { 16972246da4SFelipe Balbi dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); 17072246da4SFelipe Balbi } 17172246da4SFelipe Balbi 17272246da4SFelipe Balbi /** 1731d046793SPaul Zimmerman * dwc3_alloc_one_event_buffer - Allocates one event buffer structure 17472246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 17572246da4SFelipe Balbi * @length: size of the event buffer 17672246da4SFelipe Balbi * 1771d046793SPaul Zimmerman * Returns a pointer to the allocated event buffer structure on success 17872246da4SFelipe Balbi * otherwise ERR_PTR(errno). 17972246da4SFelipe Balbi */ 18067d0b500SFelipe Balbi static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, 18167d0b500SFelipe Balbi unsigned length) 18272246da4SFelipe Balbi { 18372246da4SFelipe Balbi struct dwc3_event_buffer *evt; 18472246da4SFelipe Balbi 185380f0d28SFelipe Balbi evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL); 18672246da4SFelipe Balbi if (!evt) 18772246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 18872246da4SFelipe Balbi 18972246da4SFelipe Balbi evt->dwc = dwc; 19072246da4SFelipe Balbi evt->length = length; 19172246da4SFelipe Balbi evt->buf = dma_alloc_coherent(dwc->dev, length, 19272246da4SFelipe Balbi &evt->dma, GFP_KERNEL); 193e32672f0SFelipe Balbi if (!evt->buf) 19472246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 19572246da4SFelipe Balbi 19672246da4SFelipe Balbi return evt; 19772246da4SFelipe Balbi } 19872246da4SFelipe Balbi 19972246da4SFelipe Balbi /** 20072246da4SFelipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 20172246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 20272246da4SFelipe Balbi */ 20372246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc) 20472246da4SFelipe Balbi { 20572246da4SFelipe Balbi struct dwc3_event_buffer *evt; 20672246da4SFelipe Balbi 207*696c8b12SFelipe Balbi evt = dwc->ev_buf; 20864b6c8a7SAnton Tikhomirov if (evt) 20972246da4SFelipe Balbi dwc3_free_one_event_buffer(dwc, evt); 21072246da4SFelipe Balbi } 21172246da4SFelipe Balbi 21272246da4SFelipe Balbi /** 21372246da4SFelipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 2141d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 21572246da4SFelipe Balbi * @length: size of event buffer 21672246da4SFelipe Balbi * 2171d046793SPaul Zimmerman * Returns 0 on success otherwise negative errno. In the error case, dwc 21872246da4SFelipe Balbi * may contain some buffers allocated but not all which were requested. 21972246da4SFelipe Balbi */ 22041ac7b3aSBill Pemberton static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) 22172246da4SFelipe Balbi { 222660e9bdeSFelipe Balbi struct dwc3_event_buffer *evt; 22372246da4SFelipe Balbi 22472246da4SFelipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 22572246da4SFelipe Balbi if (IS_ERR(evt)) { 22672246da4SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 22772246da4SFelipe Balbi return PTR_ERR(evt); 22872246da4SFelipe Balbi } 229*696c8b12SFelipe Balbi dwc->ev_buf = evt; 23072246da4SFelipe Balbi 23172246da4SFelipe Balbi return 0; 23272246da4SFelipe Balbi } 23372246da4SFelipe Balbi 23472246da4SFelipe Balbi /** 23572246da4SFelipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 2361d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 23772246da4SFelipe Balbi * 23872246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 23972246da4SFelipe Balbi */ 2407acd85e0SPaul Zimmerman static int dwc3_event_buffers_setup(struct dwc3 *dwc) 24172246da4SFelipe Balbi { 24272246da4SFelipe Balbi struct dwc3_event_buffer *evt; 24372246da4SFelipe Balbi 244*696c8b12SFelipe Balbi evt = dwc->ev_buf; 2451407bf13SFelipe Balbi dwc3_trace(trace_dwc3_core, 2461407bf13SFelipe Balbi "Event buf %p dma %08llx length %d\n", 24772246da4SFelipe Balbi evt->buf, (unsigned long long) evt->dma, 24872246da4SFelipe Balbi evt->length); 24972246da4SFelipe Balbi 2507acd85e0SPaul Zimmerman evt->lpos = 0; 2517acd85e0SPaul Zimmerman 252660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 25372246da4SFelipe Balbi lower_32_bits(evt->dma)); 254660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 25572246da4SFelipe Balbi upper_32_bits(evt->dma)); 256660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), 25768d6a01bSFelipe Balbi DWC3_GEVNTSIZ_SIZE(evt->length)); 258660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 25972246da4SFelipe Balbi 26072246da4SFelipe Balbi return 0; 26172246da4SFelipe Balbi } 26272246da4SFelipe Balbi 26372246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 26472246da4SFelipe Balbi { 26572246da4SFelipe Balbi struct dwc3_event_buffer *evt; 26672246da4SFelipe Balbi 267*696c8b12SFelipe Balbi evt = dwc->ev_buf; 2687acd85e0SPaul Zimmerman 2697acd85e0SPaul Zimmerman evt->lpos = 0; 2707acd85e0SPaul Zimmerman 271660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 0); 272660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 0); 273660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK 27468d6a01bSFelipe Balbi | DWC3_GEVNTSIZ_SIZE(0)); 275660e9bdeSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0); 27672246da4SFelipe Balbi } 27772246da4SFelipe Balbi 2780ffcaf37SFelipe Balbi static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) 2790ffcaf37SFelipe Balbi { 2800ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 2810ffcaf37SFelipe Balbi return 0; 2820ffcaf37SFelipe Balbi 2830ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 2840ffcaf37SFelipe Balbi return 0; 2850ffcaf37SFelipe Balbi 2860ffcaf37SFelipe Balbi dwc->scratchbuf = kmalloc_array(dwc->nr_scratch, 2870ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, GFP_KERNEL); 2880ffcaf37SFelipe Balbi if (!dwc->scratchbuf) 2890ffcaf37SFelipe Balbi return -ENOMEM; 2900ffcaf37SFelipe Balbi 2910ffcaf37SFelipe Balbi return 0; 2920ffcaf37SFelipe Balbi } 2930ffcaf37SFelipe Balbi 2940ffcaf37SFelipe Balbi static int dwc3_setup_scratch_buffers(struct dwc3 *dwc) 2950ffcaf37SFelipe Balbi { 2960ffcaf37SFelipe Balbi dma_addr_t scratch_addr; 2970ffcaf37SFelipe Balbi u32 param; 2980ffcaf37SFelipe Balbi int ret; 2990ffcaf37SFelipe Balbi 3000ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3010ffcaf37SFelipe Balbi return 0; 3020ffcaf37SFelipe Balbi 3030ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3040ffcaf37SFelipe Balbi return 0; 3050ffcaf37SFelipe Balbi 3060ffcaf37SFelipe Balbi /* should never fall here */ 3070ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 3080ffcaf37SFelipe Balbi return 0; 3090ffcaf37SFelipe Balbi 3100ffcaf37SFelipe Balbi scratch_addr = dma_map_single(dwc->dev, dwc->scratchbuf, 3110ffcaf37SFelipe Balbi dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, 3120ffcaf37SFelipe Balbi DMA_BIDIRECTIONAL); 3130ffcaf37SFelipe Balbi if (dma_mapping_error(dwc->dev, scratch_addr)) { 3140ffcaf37SFelipe Balbi dev_err(dwc->dev, "failed to map scratch buffer\n"); 3150ffcaf37SFelipe Balbi ret = -EFAULT; 3160ffcaf37SFelipe Balbi goto err0; 3170ffcaf37SFelipe Balbi } 3180ffcaf37SFelipe Balbi 3190ffcaf37SFelipe Balbi dwc->scratch_addr = scratch_addr; 3200ffcaf37SFelipe Balbi 3210ffcaf37SFelipe Balbi param = lower_32_bits(scratch_addr); 3220ffcaf37SFelipe Balbi 3230ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3240ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param); 3250ffcaf37SFelipe Balbi if (ret < 0) 3260ffcaf37SFelipe Balbi goto err1; 3270ffcaf37SFelipe Balbi 3280ffcaf37SFelipe Balbi param = upper_32_bits(scratch_addr); 3290ffcaf37SFelipe Balbi 3300ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3310ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param); 3320ffcaf37SFelipe Balbi if (ret < 0) 3330ffcaf37SFelipe Balbi goto err1; 3340ffcaf37SFelipe Balbi 3350ffcaf37SFelipe Balbi return 0; 3360ffcaf37SFelipe Balbi 3370ffcaf37SFelipe Balbi err1: 3380ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3390ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3400ffcaf37SFelipe Balbi 3410ffcaf37SFelipe Balbi err0: 3420ffcaf37SFelipe Balbi return ret; 3430ffcaf37SFelipe Balbi } 3440ffcaf37SFelipe Balbi 3450ffcaf37SFelipe Balbi static void dwc3_free_scratch_buffers(struct dwc3 *dwc) 3460ffcaf37SFelipe Balbi { 3470ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3480ffcaf37SFelipe Balbi return; 3490ffcaf37SFelipe Balbi 3500ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3510ffcaf37SFelipe Balbi return; 3520ffcaf37SFelipe Balbi 3530ffcaf37SFelipe Balbi /* should never fall here */ 3540ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 3550ffcaf37SFelipe Balbi return; 3560ffcaf37SFelipe Balbi 3570ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3580ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3590ffcaf37SFelipe Balbi kfree(dwc->scratchbuf); 3600ffcaf37SFelipe Balbi } 3610ffcaf37SFelipe Balbi 362789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc) 363789451f6SFelipe Balbi { 364789451f6SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 365789451f6SFelipe Balbi 366789451f6SFelipe Balbi dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); 367789451f6SFelipe Balbi dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; 368789451f6SFelipe Balbi 36973815280SFelipe Balbi dwc3_trace(trace_dwc3_core, "found %d IN and %d OUT endpoints", 370789451f6SFelipe Balbi dwc->num_in_eps, dwc->num_out_eps); 371789451f6SFelipe Balbi } 372789451f6SFelipe Balbi 37341ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc) 37426ceca97SFelipe Balbi { 37526ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 37626ceca97SFelipe Balbi 37726ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 37826ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 37926ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 38026ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 38126ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 38226ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 38326ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 38426ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 38526ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 38626ceca97SFelipe Balbi } 38726ceca97SFelipe Balbi 38872246da4SFelipe Balbi /** 389b5a65c40SHuang Rui * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core 390b5a65c40SHuang Rui * @dwc: Pointer to our controller context structure 39188bc9d19SHeikki Krogerus * 39288bc9d19SHeikki Krogerus * Returns 0 on success. The USB PHY interfaces are configured but not 39388bc9d19SHeikki Krogerus * initialized. The PHY interfaces and the PHYs get initialized together with 39488bc9d19SHeikki Krogerus * the core in dwc3_core_init. 395b5a65c40SHuang Rui */ 39688bc9d19SHeikki Krogerus static int dwc3_phy_setup(struct dwc3 *dwc) 397b5a65c40SHuang Rui { 398b5a65c40SHuang Rui u32 reg; 39988bc9d19SHeikki Krogerus int ret; 400b5a65c40SHuang Rui 401b5a65c40SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 402b5a65c40SHuang Rui 4032164a476SHuang Rui /* 4042164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY 4052164a476SHuang Rui * to '0' during coreConsultant configuration. So default value 4062164a476SHuang Rui * will be '0' when the core is reset. Application needs to set it 4072164a476SHuang Rui * to '1' after the core initialization is completed. 4082164a476SHuang Rui */ 4092164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 4102164a476SHuang Rui reg |= DWC3_GUSB3PIPECTL_SUSPHY; 4112164a476SHuang Rui 412b5a65c40SHuang Rui if (dwc->u2ss_inp3_quirk) 413b5a65c40SHuang Rui reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; 414b5a65c40SHuang Rui 415df31f5b3SHuang Rui if (dwc->req_p1p2p3_quirk) 416df31f5b3SHuang Rui reg |= DWC3_GUSB3PIPECTL_REQP1P2P3; 417df31f5b3SHuang Rui 418a2a1d0f5SHuang Rui if (dwc->del_p1p2p3_quirk) 419a2a1d0f5SHuang Rui reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN; 420a2a1d0f5SHuang Rui 42141c06ffdSHuang Rui if (dwc->del_phy_power_chg_quirk) 42241c06ffdSHuang Rui reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE; 42341c06ffdSHuang Rui 424fb67afcaSHuang Rui if (dwc->lfps_filter_quirk) 425fb67afcaSHuang Rui reg |= DWC3_GUSB3PIPECTL_LFPSFILT; 426fb67afcaSHuang Rui 42714f4ac53SHuang Rui if (dwc->rx_detect_poll_quirk) 42814f4ac53SHuang Rui reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL; 42914f4ac53SHuang Rui 4306b6a0c9aSHuang Rui if (dwc->tx_de_emphasis_quirk) 4316b6a0c9aSHuang Rui reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); 4326b6a0c9aSHuang Rui 433cd72f890SFelipe Balbi if (dwc->dis_u3_susphy_quirk) 43459acfa20SHuang Rui reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 43559acfa20SHuang Rui 436b5a65c40SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 437b5a65c40SHuang Rui 4382164a476SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 4392164a476SHuang Rui 4403e10a2ceSHeikki Krogerus /* Select the HS PHY interface */ 4413e10a2ceSHeikki Krogerus switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) { 4423e10a2ceSHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI: 44343cacb03SFelipe Balbi if (dwc->hsphy_interface && 44443cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "utmi", 4)) { 4453e10a2ceSHeikki Krogerus reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI; 44688bc9d19SHeikki Krogerus break; 44743cacb03SFelipe Balbi } else if (dwc->hsphy_interface && 44843cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "ulpi", 4)) { 4493e10a2ceSHeikki Krogerus reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI; 45088bc9d19SHeikki Krogerus dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 4513e10a2ceSHeikki Krogerus } else { 45288bc9d19SHeikki Krogerus /* Relying on default value. */ 45388bc9d19SHeikki Krogerus if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) 4543e10a2ceSHeikki Krogerus break; 4553e10a2ceSHeikki Krogerus } 4563e10a2ceSHeikki Krogerus /* FALLTHROUGH */ 45788bc9d19SHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: 45888bc9d19SHeikki Krogerus /* Making sure the interface and PHY are operational */ 45988bc9d19SHeikki Krogerus ret = dwc3_soft_reset(dwc); 46088bc9d19SHeikki Krogerus if (ret) 46188bc9d19SHeikki Krogerus return ret; 46288bc9d19SHeikki Krogerus 46388bc9d19SHeikki Krogerus udelay(1); 46488bc9d19SHeikki Krogerus 46588bc9d19SHeikki Krogerus ret = dwc3_ulpi_init(dwc); 46688bc9d19SHeikki Krogerus if (ret) 46788bc9d19SHeikki Krogerus return ret; 46888bc9d19SHeikki Krogerus /* FALLTHROUGH */ 4693e10a2ceSHeikki Krogerus default: 4703e10a2ceSHeikki Krogerus break; 4713e10a2ceSHeikki Krogerus } 4723e10a2ceSHeikki Krogerus 4732164a476SHuang Rui /* 4742164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to 4752164a476SHuang Rui * '0' during coreConsultant configuration. So default value will 4762164a476SHuang Rui * be '0' when the core is reset. Application needs to set it to 4772164a476SHuang Rui * '1' after the core initialization is completed. 4782164a476SHuang Rui */ 4792164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 4802164a476SHuang Rui reg |= DWC3_GUSB2PHYCFG_SUSPHY; 4812164a476SHuang Rui 482cd72f890SFelipe Balbi if (dwc->dis_u2_susphy_quirk) 4830effe0a3SHuang Rui reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 4840effe0a3SHuang Rui 485ec791d14SJohn Youn if (dwc->dis_enblslpm_quirk) 486ec791d14SJohn Youn reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; 487ec791d14SJohn Youn 4882164a476SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 48988bc9d19SHeikki Krogerus 49088bc9d19SHeikki Krogerus return 0; 491b5a65c40SHuang Rui } 492b5a65c40SHuang Rui 493b5a65c40SHuang Rui /** 49472246da4SFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 49572246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 49672246da4SFelipe Balbi * 49772246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 49872246da4SFelipe Balbi */ 49941ac7b3aSBill Pemberton static int dwc3_core_init(struct dwc3 *dwc) 50072246da4SFelipe Balbi { 5010ffcaf37SFelipe Balbi u32 hwparams4 = dwc->hwparams.hwparams4; 50272246da4SFelipe Balbi u32 reg; 50372246da4SFelipe Balbi int ret; 50472246da4SFelipe Balbi 5057650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 5067650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 507690fb371SJohn Youn if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) { 508690fb371SJohn Youn /* Detected DWC_usb3 IP */ 509690fb371SJohn Youn dwc->revision = reg; 510690fb371SJohn Youn } else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) { 511690fb371SJohn Youn /* Detected DWC_usb31 IP */ 512690fb371SJohn Youn dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); 513690fb371SJohn Youn dwc->revision |= DWC3_REVISION_IS_DWC31; 514690fb371SJohn Youn } else { 5157650bd74SSebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 5167650bd74SSebastian Andrzej Siewior ret = -ENODEV; 5177650bd74SSebastian Andrzej Siewior goto err0; 5187650bd74SSebastian Andrzej Siewior } 5197650bd74SSebastian Andrzej Siewior 520fa0ea13eSFelipe Balbi /* 521fa0ea13eSFelipe Balbi * Write Linux Version Code to our GUID register so it's easy to figure 522fa0ea13eSFelipe Balbi * out which kernel version a bug was found. 523fa0ea13eSFelipe Balbi */ 524fa0ea13eSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); 525fa0ea13eSFelipe Balbi 5260e1e5c47SPaul Zimmerman /* Handle USB2.0-only core configuration */ 5270e1e5c47SPaul Zimmerman if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 5280e1e5c47SPaul Zimmerman DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { 5290e1e5c47SPaul Zimmerman if (dwc->maximum_speed == USB_SPEED_SUPER) 5300e1e5c47SPaul Zimmerman dwc->maximum_speed = USB_SPEED_HIGH; 5310e1e5c47SPaul Zimmerman } 5320e1e5c47SPaul Zimmerman 53372246da4SFelipe Balbi /* issue device SoftReset too */ 534c5cc74e8SHeikki Krogerus ret = dwc3_soft_reset(dwc); 535c5cc74e8SHeikki Krogerus if (ret) 53672246da4SFelipe Balbi goto err0; 53772246da4SFelipe Balbi 53857303488SKishon Vijay Abraham I ret = dwc3_core_soft_reset(dwc); 53957303488SKishon Vijay Abraham I if (ret) 54057303488SKishon Vijay Abraham I goto err0; 54158a0f23fSPratyush Anand 5424878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 5433e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 5444878a028SSebastian Andrzej Siewior 545164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 5464878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 54732a4a135SFelipe Balbi /** 54832a4a135SFelipe Balbi * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an 54932a4a135SFelipe Balbi * issue which would cause xHCI compliance tests to fail. 55032a4a135SFelipe Balbi * 55132a4a135SFelipe Balbi * Because of that we cannot enable clock gating on such 55232a4a135SFelipe Balbi * configurations. 55332a4a135SFelipe Balbi * 55432a4a135SFelipe Balbi * Refers to: 55532a4a135SFelipe Balbi * 55632a4a135SFelipe Balbi * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based 55732a4a135SFelipe Balbi * SOF/ITP Mode Used 55832a4a135SFelipe Balbi */ 55932a4a135SFelipe Balbi if ((dwc->dr_mode == USB_DR_MODE_HOST || 56032a4a135SFelipe Balbi dwc->dr_mode == USB_DR_MODE_OTG) && 56132a4a135SFelipe Balbi (dwc->revision >= DWC3_REVISION_210A && 56232a4a135SFelipe Balbi dwc->revision <= DWC3_REVISION_250A)) 56332a4a135SFelipe Balbi reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; 56432a4a135SFelipe Balbi else 5654878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 5664878a028SSebastian Andrzej Siewior break; 5670ffcaf37SFelipe Balbi case DWC3_GHWPARAMS1_EN_PWROPT_HIB: 5680ffcaf37SFelipe Balbi /* enable hibernation here */ 5690ffcaf37SFelipe Balbi dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); 5702eac3992SHuang Rui 5712eac3992SHuang Rui /* 5722eac3992SHuang Rui * REVISIT Enabling this bit so that host-mode hibernation 5732eac3992SHuang Rui * will work. Device-mode hibernation is not yet implemented. 5742eac3992SHuang Rui */ 5752eac3992SHuang Rui reg |= DWC3_GCTL_GBLHIBERNATIONEN; 5760ffcaf37SFelipe Balbi break; 5774878a028SSebastian Andrzej Siewior default: 5781407bf13SFelipe Balbi dwc3_trace(trace_dwc3_core, "No power optimization available\n"); 5794878a028SSebastian Andrzej Siewior } 5804878a028SSebastian Andrzej Siewior 581946bd579SHuang Rui /* check if current dwc3 is on simulation board */ 582946bd579SHuang Rui if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { 5831407bf13SFelipe Balbi dwc3_trace(trace_dwc3_core, 5841407bf13SFelipe Balbi "running on FPGA platform\n"); 585946bd579SHuang Rui dwc->is_fpga = true; 586946bd579SHuang Rui } 587946bd579SHuang Rui 5883b81221aSHuang Rui WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga, 5893b81221aSHuang Rui "disable_scramble cannot be used on non-FPGA builds\n"); 5903b81221aSHuang Rui 5913b81221aSHuang Rui if (dwc->disable_scramble_quirk && dwc->is_fpga) 5923b81221aSHuang Rui reg |= DWC3_GCTL_DISSCRAMBLE; 5933b81221aSHuang Rui else 5943b81221aSHuang Rui reg &= ~DWC3_GCTL_DISSCRAMBLE; 5953b81221aSHuang Rui 5969a5b2f31SHuang Rui if (dwc->u2exit_lfps_quirk) 5979a5b2f31SHuang Rui reg |= DWC3_GCTL_U2EXIT_LFPS; 5989a5b2f31SHuang Rui 5994878a028SSebastian Andrzej Siewior /* 6004878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 6011d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 6024878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 6031d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 6044878a028SSebastian Andrzej Siewior */ 6054878a028SSebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 6064878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 6074878a028SSebastian Andrzej Siewior 608789451f6SFelipe Balbi dwc3_core_num_eps(dwc); 609789451f6SFelipe Balbi 6104878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 6114878a028SSebastian Andrzej Siewior 6120ffcaf37SFelipe Balbi ret = dwc3_alloc_scratch_buffers(dwc); 6130ffcaf37SFelipe Balbi if (ret) 6140ffcaf37SFelipe Balbi goto err1; 6150ffcaf37SFelipe Balbi 6160ffcaf37SFelipe Balbi ret = dwc3_setup_scratch_buffers(dwc); 6170ffcaf37SFelipe Balbi if (ret) 6180ffcaf37SFelipe Balbi goto err2; 6190ffcaf37SFelipe Balbi 62072246da4SFelipe Balbi return 0; 62172246da4SFelipe Balbi 6220ffcaf37SFelipe Balbi err2: 6230ffcaf37SFelipe Balbi dwc3_free_scratch_buffers(dwc); 6240ffcaf37SFelipe Balbi 6250ffcaf37SFelipe Balbi err1: 6260ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 6270ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 62857303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 62957303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 6300ffcaf37SFelipe Balbi 63172246da4SFelipe Balbi err0: 63272246da4SFelipe Balbi return ret; 63372246da4SFelipe Balbi } 63472246da4SFelipe Balbi 63572246da4SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 63672246da4SFelipe Balbi { 6370ffcaf37SFelipe Balbi dwc3_free_scratch_buffers(dwc); 63801b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb2_phy); 63901b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb3_phy); 64057303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 64157303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 64272246da4SFelipe Balbi } 64372246da4SFelipe Balbi 6443c9f94acSFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc) 64572246da4SFelipe Balbi { 6463c9f94acSFelipe Balbi struct device *dev = dwc->dev; 647941ea361SFelipe Balbi struct device_node *node = dev->of_node; 6483c9f94acSFelipe Balbi int ret; 64972246da4SFelipe Balbi 6505088b6f5SKishon Vijay Abraham I if (node) { 6515088b6f5SKishon Vijay Abraham I dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); 6525088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); 653bb674907SFelipe Balbi } else { 654bb674907SFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 655bb674907SFelipe Balbi dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 6565088b6f5SKishon Vijay Abraham I } 6575088b6f5SKishon Vijay Abraham I 658d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb2_phy)) { 659d105e7f8SFelipe Balbi ret = PTR_ERR(dwc->usb2_phy); 660122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 661122f06e6SKishon Vijay Abraham I dwc->usb2_phy = NULL; 662122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 663d105e7f8SFelipe Balbi return ret; 664122f06e6SKishon Vijay Abraham I } else { 66551e1e7bcSFelipe Balbi dev_err(dev, "no usb2 phy configured\n"); 666122f06e6SKishon Vijay Abraham I return ret; 667122f06e6SKishon Vijay Abraham I } 66851e1e7bcSFelipe Balbi } 66951e1e7bcSFelipe Balbi 670d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb3_phy)) { 671315955d7SRuchika Kharwar ret = PTR_ERR(dwc->usb3_phy); 672122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 673122f06e6SKishon Vijay Abraham I dwc->usb3_phy = NULL; 674122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 675d105e7f8SFelipe Balbi return ret; 676122f06e6SKishon Vijay Abraham I } else { 67751e1e7bcSFelipe Balbi dev_err(dev, "no usb3 phy configured\n"); 678122f06e6SKishon Vijay Abraham I return ret; 679122f06e6SKishon Vijay Abraham I } 68051e1e7bcSFelipe Balbi } 68151e1e7bcSFelipe Balbi 68257303488SKishon Vijay Abraham I dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); 68357303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb2_generic_phy)) { 68457303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb2_generic_phy); 68557303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 68657303488SKishon Vijay Abraham I dwc->usb2_generic_phy = NULL; 68757303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 68857303488SKishon Vijay Abraham I return ret; 68957303488SKishon Vijay Abraham I } else { 69057303488SKishon Vijay Abraham I dev_err(dev, "no usb2 phy configured\n"); 69157303488SKishon Vijay Abraham I return ret; 69257303488SKishon Vijay Abraham I } 69357303488SKishon Vijay Abraham I } 69457303488SKishon Vijay Abraham I 69557303488SKishon Vijay Abraham I dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy"); 69657303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb3_generic_phy)) { 69757303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb3_generic_phy); 69857303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 69957303488SKishon Vijay Abraham I dwc->usb3_generic_phy = NULL; 70057303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 70157303488SKishon Vijay Abraham I return ret; 70257303488SKishon Vijay Abraham I } else { 70357303488SKishon Vijay Abraham I dev_err(dev, "no usb3 phy configured\n"); 70457303488SKishon Vijay Abraham I return ret; 70557303488SKishon Vijay Abraham I } 70657303488SKishon Vijay Abraham I } 70757303488SKishon Vijay Abraham I 7083c9f94acSFelipe Balbi return 0; 7093c9f94acSFelipe Balbi } 7103c9f94acSFelipe Balbi 7115f94adfeSFelipe Balbi static int dwc3_core_init_mode(struct dwc3 *dwc) 7125f94adfeSFelipe Balbi { 7135f94adfeSFelipe Balbi struct device *dev = dwc->dev; 7145f94adfeSFelipe Balbi int ret; 7155f94adfeSFelipe Balbi 7165f94adfeSFelipe Balbi switch (dwc->dr_mode) { 7175f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 7185f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); 7195f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 7205f94adfeSFelipe Balbi if (ret) { 7215f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 7225f94adfeSFelipe Balbi return ret; 7235f94adfeSFelipe Balbi } 7245f94adfeSFelipe Balbi break; 7255f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 7265f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); 7275f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 7285f94adfeSFelipe Balbi if (ret) { 7295f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 7305f94adfeSFelipe Balbi return ret; 7315f94adfeSFelipe Balbi } 7325f94adfeSFelipe Balbi break; 7335f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 7345f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); 7355f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 7365f94adfeSFelipe Balbi if (ret) { 7375f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 7385f94adfeSFelipe Balbi return ret; 7395f94adfeSFelipe Balbi } 7405f94adfeSFelipe Balbi 7415f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 7425f94adfeSFelipe Balbi if (ret) { 7435f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 7445f94adfeSFelipe Balbi return ret; 7455f94adfeSFelipe Balbi } 7465f94adfeSFelipe Balbi break; 7475f94adfeSFelipe Balbi default: 7485f94adfeSFelipe Balbi dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); 7495f94adfeSFelipe Balbi return -EINVAL; 7505f94adfeSFelipe Balbi } 7515f94adfeSFelipe Balbi 7525f94adfeSFelipe Balbi return 0; 7535f94adfeSFelipe Balbi } 7545f94adfeSFelipe Balbi 7555f94adfeSFelipe Balbi static void dwc3_core_exit_mode(struct dwc3 *dwc) 7565f94adfeSFelipe Balbi { 7575f94adfeSFelipe Balbi switch (dwc->dr_mode) { 7585f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 7595f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 7605f94adfeSFelipe Balbi break; 7615f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 7625f94adfeSFelipe Balbi dwc3_host_exit(dwc); 7635f94adfeSFelipe Balbi break; 7645f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 7655f94adfeSFelipe Balbi dwc3_host_exit(dwc); 7665f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 7675f94adfeSFelipe Balbi break; 7685f94adfeSFelipe Balbi default: 7695f94adfeSFelipe Balbi /* do nothing */ 7705f94adfeSFelipe Balbi break; 7715f94adfeSFelipe Balbi } 7725f94adfeSFelipe Balbi } 7735f94adfeSFelipe Balbi 7743c9f94acSFelipe Balbi #define DWC3_ALIGN_MASK (16 - 1) 7753c9f94acSFelipe Balbi 7763c9f94acSFelipe Balbi static int dwc3_probe(struct platform_device *pdev) 7773c9f94acSFelipe Balbi { 7783c9f94acSFelipe Balbi struct device *dev = &pdev->dev; 7793c9f94acSFelipe Balbi struct dwc3_platform_data *pdata = dev_get_platdata(dev); 7803c9f94acSFelipe Balbi struct resource *res; 7813c9f94acSFelipe Balbi struct dwc3 *dwc; 78280caf7d2SHuang Rui u8 lpm_nyet_threshold; 7836b6a0c9aSHuang Rui u8 tx_de_emphasis; 784460d098cSHuang Rui u8 hird_threshold; 785db2be4e9SNikhil Badola u32 fladj = 0; 7863c9f94acSFelipe Balbi 787b09e99eeSAndy Shevchenko int ret; 7883c9f94acSFelipe Balbi 7893c9f94acSFelipe Balbi void __iomem *regs; 7903c9f94acSFelipe Balbi void *mem; 7913c9f94acSFelipe Balbi 7923c9f94acSFelipe Balbi mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 793734d5a53SJingoo Han if (!mem) 7943c9f94acSFelipe Balbi return -ENOMEM; 795734d5a53SJingoo Han 7963c9f94acSFelipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 7973c9f94acSFelipe Balbi dwc->mem = mem; 7983c9f94acSFelipe Balbi dwc->dev = dev; 7993c9f94acSFelipe Balbi 8003c9f94acSFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 8013c9f94acSFelipe Balbi if (!res) { 8023c9f94acSFelipe Balbi dev_err(dev, "missing IRQ\n"); 8033c9f94acSFelipe Balbi return -ENODEV; 8043c9f94acSFelipe Balbi } 8053c9f94acSFelipe Balbi dwc->xhci_resources[1].start = res->start; 8063c9f94acSFelipe Balbi dwc->xhci_resources[1].end = res->end; 8073c9f94acSFelipe Balbi dwc->xhci_resources[1].flags = res->flags; 8083c9f94acSFelipe Balbi dwc->xhci_resources[1].name = res->name; 8093c9f94acSFelipe Balbi 8103c9f94acSFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 8113c9f94acSFelipe Balbi if (!res) { 8123c9f94acSFelipe Balbi dev_err(dev, "missing memory resource\n"); 8133c9f94acSFelipe Balbi return -ENODEV; 8143c9f94acSFelipe Balbi } 8153c9f94acSFelipe Balbi 816f32a5e23SVivek Gautam dwc->xhci_resources[0].start = res->start; 817f32a5e23SVivek Gautam dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 818f32a5e23SVivek Gautam DWC3_XHCI_REGS_END; 819f32a5e23SVivek Gautam dwc->xhci_resources[0].flags = res->flags; 820f32a5e23SVivek Gautam dwc->xhci_resources[0].name = res->name; 821f32a5e23SVivek Gautam 822f32a5e23SVivek Gautam res->start += DWC3_GLOBALS_REGS_START; 823f32a5e23SVivek Gautam 824f32a5e23SVivek Gautam /* 825f32a5e23SVivek Gautam * Request memory region but exclude xHCI regs, 826f32a5e23SVivek Gautam * since it will be requested by the xhci-plat driver. 827f32a5e23SVivek Gautam */ 828f32a5e23SVivek Gautam regs = devm_ioremap_resource(dev, res); 8293da1f6eeSFelipe Balbi if (IS_ERR(regs)) { 8303da1f6eeSFelipe Balbi ret = PTR_ERR(regs); 8313da1f6eeSFelipe Balbi goto err0; 8323da1f6eeSFelipe Balbi } 833f32a5e23SVivek Gautam 834f32a5e23SVivek Gautam dwc->regs = regs; 835f32a5e23SVivek Gautam dwc->regs_size = resource_size(res); 836f32a5e23SVivek Gautam 83780caf7d2SHuang Rui /* default to highest possible threshold */ 83880caf7d2SHuang Rui lpm_nyet_threshold = 0xff; 83980caf7d2SHuang Rui 8406b6a0c9aSHuang Rui /* default to -3.5dB de-emphasis */ 8416b6a0c9aSHuang Rui tx_de_emphasis = 1; 8426b6a0c9aSHuang Rui 843460d098cSHuang Rui /* 844460d098cSHuang Rui * default to assert utmi_sleep_n and use maximum allowed HIRD 845460d098cSHuang Rui * threshold value of 0b1100 846460d098cSHuang Rui */ 847460d098cSHuang Rui hird_threshold = 12; 848460d098cSHuang Rui 84963863b98SHeikki Krogerus dwc->maximum_speed = usb_get_maximum_speed(dev); 85006e7114fSHeikki Krogerus dwc->dr_mode = usb_get_dr_mode(dev); 85163863b98SHeikki Krogerus 8523d128919SHeikki Krogerus dwc->has_lpm_erratum = device_property_read_bool(dev, 85380caf7d2SHuang Rui "snps,has-lpm-erratum"); 8543d128919SHeikki Krogerus device_property_read_u8(dev, "snps,lpm-nyet-threshold", 85580caf7d2SHuang Rui &lpm_nyet_threshold); 8563d128919SHeikki Krogerus dwc->is_utmi_l1_suspend = device_property_read_bool(dev, 857460d098cSHuang Rui "snps,is-utmi-l1-suspend"); 8583d128919SHeikki Krogerus device_property_read_u8(dev, "snps,hird-threshold", 859460d098cSHuang Rui &hird_threshold); 8603d128919SHeikki Krogerus dwc->usb3_lpm_capable = device_property_read_bool(dev, 861eac68e8fSRobert Baldyga "snps,usb3_lpm_capable"); 8623c9f94acSFelipe Balbi 8633d128919SHeikki Krogerus dwc->disable_scramble_quirk = device_property_read_bool(dev, 8643b81221aSHuang Rui "snps,disable_scramble_quirk"); 8653d128919SHeikki Krogerus dwc->u2exit_lfps_quirk = device_property_read_bool(dev, 8669a5b2f31SHuang Rui "snps,u2exit_lfps_quirk"); 8673d128919SHeikki Krogerus dwc->u2ss_inp3_quirk = device_property_read_bool(dev, 868b5a65c40SHuang Rui "snps,u2ss_inp3_quirk"); 8693d128919SHeikki Krogerus dwc->req_p1p2p3_quirk = device_property_read_bool(dev, 870df31f5b3SHuang Rui "snps,req_p1p2p3_quirk"); 8713d128919SHeikki Krogerus dwc->del_p1p2p3_quirk = device_property_read_bool(dev, 872a2a1d0f5SHuang Rui "snps,del_p1p2p3_quirk"); 8733d128919SHeikki Krogerus dwc->del_phy_power_chg_quirk = device_property_read_bool(dev, 87441c06ffdSHuang Rui "snps,del_phy_power_chg_quirk"); 8753d128919SHeikki Krogerus dwc->lfps_filter_quirk = device_property_read_bool(dev, 876fb67afcaSHuang Rui "snps,lfps_filter_quirk"); 8773d128919SHeikki Krogerus dwc->rx_detect_poll_quirk = device_property_read_bool(dev, 87814f4ac53SHuang Rui "snps,rx_detect_poll_quirk"); 8793d128919SHeikki Krogerus dwc->dis_u3_susphy_quirk = device_property_read_bool(dev, 88059acfa20SHuang Rui "snps,dis_u3_susphy_quirk"); 8813d128919SHeikki Krogerus dwc->dis_u2_susphy_quirk = device_property_read_bool(dev, 8820effe0a3SHuang Rui "snps,dis_u2_susphy_quirk"); 883ec791d14SJohn Youn dwc->dis_enblslpm_quirk = device_property_read_bool(dev, 884ec791d14SJohn Youn "snps,dis_enblslpm_quirk"); 8856b6a0c9aSHuang Rui 8863d128919SHeikki Krogerus dwc->tx_de_emphasis_quirk = device_property_read_bool(dev, 8876b6a0c9aSHuang Rui "snps,tx_de_emphasis_quirk"); 8883d128919SHeikki Krogerus device_property_read_u8(dev, "snps,tx_de_emphasis", 8896b6a0c9aSHuang Rui &tx_de_emphasis); 8903d128919SHeikki Krogerus device_property_read_string(dev, "snps,hsphy_interface", 8913e10a2ceSHeikki Krogerus &dwc->hsphy_interface); 8923d128919SHeikki Krogerus device_property_read_u32(dev, "snps,quirk-frame-length-adjustment", 893db2be4e9SNikhil Badola &fladj); 8943d128919SHeikki Krogerus 8953d128919SHeikki Krogerus if (pdata) { 8963c9f94acSFelipe Balbi dwc->maximum_speed = pdata->maximum_speed; 89780caf7d2SHuang Rui dwc->has_lpm_erratum = pdata->has_lpm_erratum; 89880caf7d2SHuang Rui if (pdata->lpm_nyet_threshold) 89980caf7d2SHuang Rui lpm_nyet_threshold = pdata->lpm_nyet_threshold; 900460d098cSHuang Rui dwc->is_utmi_l1_suspend = pdata->is_utmi_l1_suspend; 901460d098cSHuang Rui if (pdata->hird_threshold) 902460d098cSHuang Rui hird_threshold = pdata->hird_threshold; 9033c9f94acSFelipe Balbi 904eac68e8fSRobert Baldyga dwc->usb3_lpm_capable = pdata->usb3_lpm_capable; 9053c9f94acSFelipe Balbi dwc->dr_mode = pdata->dr_mode; 9063b81221aSHuang Rui 9073b81221aSHuang Rui dwc->disable_scramble_quirk = pdata->disable_scramble_quirk; 9089a5b2f31SHuang Rui dwc->u2exit_lfps_quirk = pdata->u2exit_lfps_quirk; 909b5a65c40SHuang Rui dwc->u2ss_inp3_quirk = pdata->u2ss_inp3_quirk; 910df31f5b3SHuang Rui dwc->req_p1p2p3_quirk = pdata->req_p1p2p3_quirk; 911a2a1d0f5SHuang Rui dwc->del_p1p2p3_quirk = pdata->del_p1p2p3_quirk; 91241c06ffdSHuang Rui dwc->del_phy_power_chg_quirk = pdata->del_phy_power_chg_quirk; 913fb67afcaSHuang Rui dwc->lfps_filter_quirk = pdata->lfps_filter_quirk; 91414f4ac53SHuang Rui dwc->rx_detect_poll_quirk = pdata->rx_detect_poll_quirk; 91559acfa20SHuang Rui dwc->dis_u3_susphy_quirk = pdata->dis_u3_susphy_quirk; 9160effe0a3SHuang Rui dwc->dis_u2_susphy_quirk = pdata->dis_u2_susphy_quirk; 917ec791d14SJohn Youn dwc->dis_enblslpm_quirk = pdata->dis_enblslpm_quirk; 9186b6a0c9aSHuang Rui 9196b6a0c9aSHuang Rui dwc->tx_de_emphasis_quirk = pdata->tx_de_emphasis_quirk; 9206b6a0c9aSHuang Rui if (pdata->tx_de_emphasis) 9216b6a0c9aSHuang Rui tx_de_emphasis = pdata->tx_de_emphasis; 9223e10a2ceSHeikki Krogerus 9233e10a2ceSHeikki Krogerus dwc->hsphy_interface = pdata->hsphy_interface; 924db2be4e9SNikhil Badola fladj = pdata->fladj_value; 9253c9f94acSFelipe Balbi } 9263c9f94acSFelipe Balbi 92780caf7d2SHuang Rui dwc->lpm_nyet_threshold = lpm_nyet_threshold; 9286b6a0c9aSHuang Rui dwc->tx_de_emphasis = tx_de_emphasis; 92980caf7d2SHuang Rui 930460d098cSHuang Rui dwc->hird_threshold = hird_threshold 931460d098cSHuang Rui | (dwc->is_utmi_l1_suspend << 4); 932460d098cSHuang Rui 9336c89cce0SHeikki Krogerus platform_set_drvdata(pdev, dwc); 9342917e718SHeikki Krogerus dwc3_cache_hwparams(dwc); 9356c89cce0SHeikki Krogerus 93688bc9d19SHeikki Krogerus ret = dwc3_phy_setup(dwc); 93788bc9d19SHeikki Krogerus if (ret) 93888bc9d19SHeikki Krogerus goto err0; 93945bb7de2SHeikki Krogerus 9403c9f94acSFelipe Balbi ret = dwc3_core_get_phy(dwc); 9413c9f94acSFelipe Balbi if (ret) 9423da1f6eeSFelipe Balbi goto err0; 9433c9f94acSFelipe Balbi 94472246da4SFelipe Balbi spin_lock_init(&dwc->lock); 94572246da4SFelipe Balbi 94619bacdc9SHeikki Krogerus if (!dev->dma_mask) { 947ddff14f1SKishon Vijay Abraham I dev->dma_mask = dev->parent->dma_mask; 948ddff14f1SKishon Vijay Abraham I dev->dma_parms = dev->parent->dma_parms; 949ddff14f1SKishon Vijay Abraham I dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); 95019bacdc9SHeikki Krogerus } 951ddff14f1SKishon Vijay Abraham I 952802ca850SChanho Park pm_runtime_enable(dev); 953802ca850SChanho Park pm_runtime_get_sync(dev); 954802ca850SChanho Park pm_runtime_forbid(dev); 95572246da4SFelipe Balbi 9563921426bSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 9573921426bSFelipe Balbi if (ret) { 9583921426bSFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 9593921426bSFelipe Balbi ret = -ENOMEM; 9603da1f6eeSFelipe Balbi goto err1; 9613921426bSFelipe Balbi } 9623921426bSFelipe Balbi 96332a4a135SFelipe Balbi if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) 96432a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_HOST; 96532a4a135SFelipe Balbi else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) 96632a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_PERIPHERAL; 96732a4a135SFelipe Balbi 96832a4a135SFelipe Balbi if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) 96932a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_OTG; 97032a4a135SFelipe Balbi 97172246da4SFelipe Balbi ret = dwc3_core_init(dwc); 97272246da4SFelipe Balbi if (ret) { 973802ca850SChanho Park dev_err(dev, "failed to initialize core\n"); 9743da1f6eeSFelipe Balbi goto err1; 97572246da4SFelipe Balbi } 97672246da4SFelipe Balbi 97777966eb8SJohn Youn /* Check the maximum_speed parameter */ 97877966eb8SJohn Youn switch (dwc->maximum_speed) { 97977966eb8SJohn Youn case USB_SPEED_LOW: 98077966eb8SJohn Youn case USB_SPEED_FULL: 98177966eb8SJohn Youn case USB_SPEED_HIGH: 98277966eb8SJohn Youn case USB_SPEED_SUPER: 98377966eb8SJohn Youn case USB_SPEED_SUPER_PLUS: 98477966eb8SJohn Youn break; 98577966eb8SJohn Youn default: 98677966eb8SJohn Youn dev_err(dev, "invalid maximum_speed parameter %d\n", 98777966eb8SJohn Youn dwc->maximum_speed); 98877966eb8SJohn Youn /* fall through */ 98977966eb8SJohn Youn case USB_SPEED_UNKNOWN: 99077966eb8SJohn Youn /* default to superspeed */ 9912c7f1bd9SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER; 9922c7f1bd9SJohn Youn 9932c7f1bd9SJohn Youn /* 9942c7f1bd9SJohn Youn * default to superspeed plus if we are capable. 9952c7f1bd9SJohn Youn */ 9962c7f1bd9SJohn Youn if (dwc3_is_usb31(dwc) && 9972c7f1bd9SJohn Youn (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 9982c7f1bd9SJohn Youn DWC3_GHWPARAMS3_SSPHY_IFC_GEN2)) 9992c7f1bd9SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER_PLUS; 100077966eb8SJohn Youn 100177966eb8SJohn Youn break; 10022c7f1bd9SJohn Youn } 10032c7f1bd9SJohn Youn 1004db2be4e9SNikhil Badola /* Adjust Frame Length */ 1005db2be4e9SNikhil Badola dwc3_frame_length_adjustment(dwc, fladj); 1006db2be4e9SNikhil Badola 10073088f108SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 0); 10083088f108SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 0); 100957303488SKishon Vijay Abraham I ret = phy_power_on(dwc->usb2_generic_phy); 101057303488SKishon Vijay Abraham I if (ret < 0) 10113da1f6eeSFelipe Balbi goto err2; 101257303488SKishon Vijay Abraham I 101357303488SKishon Vijay Abraham I ret = phy_power_on(dwc->usb3_generic_phy); 101457303488SKishon Vijay Abraham I if (ret < 0) 10153da1f6eeSFelipe Balbi goto err3; 10163088f108SKishon Vijay Abraham I 1017f122d33eSFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 1018f122d33eSFelipe Balbi if (ret) { 1019f122d33eSFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 10203da1f6eeSFelipe Balbi goto err4; 1021f122d33eSFelipe Balbi } 1022f122d33eSFelipe Balbi 10235f94adfeSFelipe Balbi ret = dwc3_core_init_mode(dwc); 10245f94adfeSFelipe Balbi if (ret) 10253da1f6eeSFelipe Balbi goto err5; 102672246da4SFelipe Balbi 102772246da4SFelipe Balbi ret = dwc3_debugfs_init(dwc); 102872246da4SFelipe Balbi if (ret) { 1029802ca850SChanho Park dev_err(dev, "failed to initialize debugfs\n"); 10303da1f6eeSFelipe Balbi goto err6; 103172246da4SFelipe Balbi } 103272246da4SFelipe Balbi 1033802ca850SChanho Park pm_runtime_allow(dev); 103472246da4SFelipe Balbi 103572246da4SFelipe Balbi return 0; 103672246da4SFelipe Balbi 10373da1f6eeSFelipe Balbi err6: 10385f94adfeSFelipe Balbi dwc3_core_exit_mode(dwc); 103972246da4SFelipe Balbi 10403da1f6eeSFelipe Balbi err5: 1041f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 1042f122d33eSFelipe Balbi 10433da1f6eeSFelipe Balbi err4: 104457303488SKishon Vijay Abraham I phy_power_off(dwc->usb3_generic_phy); 104557303488SKishon Vijay Abraham I 10463da1f6eeSFelipe Balbi err3: 104757303488SKishon Vijay Abraham I phy_power_off(dwc->usb2_generic_phy); 104857303488SKishon Vijay Abraham I 10493da1f6eeSFelipe Balbi err2: 1050501fae51SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 1); 1051501fae51SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 1); 105272246da4SFelipe Balbi dwc3_core_exit(dwc); 105372246da4SFelipe Balbi 10543da1f6eeSFelipe Balbi err1: 10553921426bSFelipe Balbi dwc3_free_event_buffers(dwc); 105688bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 10573921426bSFelipe Balbi 10583da1f6eeSFelipe Balbi err0: 10593da1f6eeSFelipe Balbi /* 10603da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 10613da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 10623da1f6eeSFelipe Balbi * memory region the next time probe is called. 10633da1f6eeSFelipe Balbi */ 10643da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 10653da1f6eeSFelipe Balbi 106672246da4SFelipe Balbi return ret; 106772246da4SFelipe Balbi } 106872246da4SFelipe Balbi 1069fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev) 107072246da4SFelipe Balbi { 107172246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 10723da1f6eeSFelipe Balbi struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 10733da1f6eeSFelipe Balbi 10743da1f6eeSFelipe Balbi /* 10753da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 10763da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 10773da1f6eeSFelipe Balbi * memory region the next time probe is called. 10783da1f6eeSFelipe Balbi */ 10793da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 108072246da4SFelipe Balbi 1081dc99f16fSFelipe Balbi dwc3_debugfs_exit(dwc); 1082dc99f16fSFelipe Balbi dwc3_core_exit_mode(dwc); 1083dc99f16fSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 1084dc99f16fSFelipe Balbi dwc3_free_event_buffers(dwc); 1085dc99f16fSFelipe Balbi 10868ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 1); 10878ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 1); 108857303488SKishon Vijay Abraham I phy_power_off(dwc->usb2_generic_phy); 108957303488SKishon Vijay Abraham I phy_power_off(dwc->usb3_generic_phy); 10908ba007a9SKishon Vijay Abraham I 109172246da4SFelipe Balbi dwc3_core_exit(dwc); 109288bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 109372246da4SFelipe Balbi 10947415f17cSFelipe Balbi pm_runtime_put_sync(&pdev->dev); 10957415f17cSFelipe Balbi pm_runtime_disable(&pdev->dev); 10967415f17cSFelipe Balbi 109772246da4SFelipe Balbi return 0; 109872246da4SFelipe Balbi } 109972246da4SFelipe Balbi 11007415f17cSFelipe Balbi #ifdef CONFIG_PM_SLEEP 11017415f17cSFelipe Balbi static int dwc3_suspend(struct device *dev) 11027415f17cSFelipe Balbi { 11037415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 11047415f17cSFelipe Balbi unsigned long flags; 11057415f17cSFelipe Balbi 11067415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 11077415f17cSFelipe Balbi 1108a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 1109a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 1110a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 11117415f17cSFelipe Balbi dwc3_gadget_suspend(dwc); 11127415f17cSFelipe Balbi /* FALLTHROUGH */ 1113a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 11147415f17cSFelipe Balbi default: 11150b0231aaSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 11167415f17cSFelipe Balbi break; 11177415f17cSFelipe Balbi } 11187415f17cSFelipe Balbi 11197415f17cSFelipe Balbi dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL); 11207415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 11217415f17cSFelipe Balbi 11227415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 11237415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 112457303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 112557303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 11267415f17cSFelipe Balbi 11276344475fSSekhar Nori pinctrl_pm_select_sleep_state(dev); 11286344475fSSekhar Nori 11297415f17cSFelipe Balbi return 0; 11307415f17cSFelipe Balbi } 11317415f17cSFelipe Balbi 11327415f17cSFelipe Balbi static int dwc3_resume(struct device *dev) 11337415f17cSFelipe Balbi { 11347415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 11357415f17cSFelipe Balbi unsigned long flags; 113657303488SKishon Vijay Abraham I int ret; 11377415f17cSFelipe Balbi 11386344475fSSekhar Nori pinctrl_pm_select_default_state(dev); 11396344475fSSekhar Nori 11407415f17cSFelipe Balbi usb_phy_init(dwc->usb3_phy); 11417415f17cSFelipe Balbi usb_phy_init(dwc->usb2_phy); 114257303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 114357303488SKishon Vijay Abraham I if (ret < 0) 114457303488SKishon Vijay Abraham I return ret; 114557303488SKishon Vijay Abraham I 114657303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 114757303488SKishon Vijay Abraham I if (ret < 0) 114857303488SKishon Vijay Abraham I goto err_usb2phy_init; 11497415f17cSFelipe Balbi 11507415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 11517415f17cSFelipe Balbi 11520b0231aaSFelipe Balbi dwc3_event_buffers_setup(dwc); 11537415f17cSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl); 11547415f17cSFelipe Balbi 1155a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 1156a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 1157a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 11587415f17cSFelipe Balbi dwc3_gadget_resume(dwc); 11597415f17cSFelipe Balbi /* FALLTHROUGH */ 1160a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 11617415f17cSFelipe Balbi default: 11627415f17cSFelipe Balbi /* do nothing */ 11637415f17cSFelipe Balbi break; 11647415f17cSFelipe Balbi } 11657415f17cSFelipe Balbi 11667415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 11677415f17cSFelipe Balbi 11687415f17cSFelipe Balbi pm_runtime_disable(dev); 11697415f17cSFelipe Balbi pm_runtime_set_active(dev); 11707415f17cSFelipe Balbi pm_runtime_enable(dev); 11717415f17cSFelipe Balbi 11727415f17cSFelipe Balbi return 0; 117357303488SKishon Vijay Abraham I 117457303488SKishon Vijay Abraham I err_usb2phy_init: 117557303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 117657303488SKishon Vijay Abraham I 117757303488SKishon Vijay Abraham I return ret; 11787415f17cSFelipe Balbi } 11797415f17cSFelipe Balbi 11807415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = { 11817415f17cSFelipe Balbi SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 11827415f17cSFelipe Balbi }; 11837415f17cSFelipe Balbi 11847415f17cSFelipe Balbi #define DWC3_PM_OPS &(dwc3_dev_pm_ops) 11857415f17cSFelipe Balbi #else 11867415f17cSFelipe Balbi #define DWC3_PM_OPS NULL 11877415f17cSFelipe Balbi #endif 11887415f17cSFelipe Balbi 11895088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF 11905088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = { 11915088b6f5SKishon Vijay Abraham I { 119222a5aa17SFelipe Balbi .compatible = "snps,dwc3" 119322a5aa17SFelipe Balbi }, 119422a5aa17SFelipe Balbi { 11955088b6f5SKishon Vijay Abraham I .compatible = "synopsys,dwc3" 11965088b6f5SKishon Vijay Abraham I }, 11975088b6f5SKishon Vijay Abraham I { }, 11985088b6f5SKishon Vijay Abraham I }; 11995088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match); 12005088b6f5SKishon Vijay Abraham I #endif 12015088b6f5SKishon Vijay Abraham I 1202404905a6SHeikki Krogerus #ifdef CONFIG_ACPI 1203404905a6SHeikki Krogerus 1204404905a6SHeikki Krogerus #define ACPI_ID_INTEL_BSW "808622B7" 1205404905a6SHeikki Krogerus 1206404905a6SHeikki Krogerus static const struct acpi_device_id dwc3_acpi_match[] = { 1207404905a6SHeikki Krogerus { ACPI_ID_INTEL_BSW, 0 }, 1208404905a6SHeikki Krogerus { }, 1209404905a6SHeikki Krogerus }; 1210404905a6SHeikki Krogerus MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match); 1211404905a6SHeikki Krogerus #endif 1212404905a6SHeikki Krogerus 121372246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 121472246da4SFelipe Balbi .probe = dwc3_probe, 12157690417dSBill Pemberton .remove = dwc3_remove, 121672246da4SFelipe Balbi .driver = { 121772246da4SFelipe Balbi .name = "dwc3", 12185088b6f5SKishon Vijay Abraham I .of_match_table = of_match_ptr(of_dwc3_match), 1219404905a6SHeikki Krogerus .acpi_match_table = ACPI_PTR(dwc3_acpi_match), 12207415f17cSFelipe Balbi .pm = DWC3_PM_OPS, 122172246da4SFelipe Balbi }, 122272246da4SFelipe Balbi }; 122372246da4SFelipe Balbi 1224b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 1225b1116dccSTobias Klauser 12267ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 122772246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 12285945f789SFelipe Balbi MODULE_LICENSE("GPL v2"); 122972246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 1230