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> 3772246da4SFelipe Balbi 3872246da4SFelipe Balbi #include <linux/usb/ch9.h> 3972246da4SFelipe Balbi #include <linux/usb/gadget.h> 40f7e846f0SFelipe Balbi #include <linux/usb/of.h> 41a45c82b8SRuchika Kharwar #include <linux/usb/otg.h> 4272246da4SFelipe Balbi 436462cbd5SFelipe Balbi #include "platform_data.h" 4472246da4SFelipe Balbi #include "core.h" 4572246da4SFelipe Balbi #include "gadget.h" 4672246da4SFelipe Balbi #include "io.h" 4772246da4SFelipe Balbi 4872246da4SFelipe Balbi #include "debug.h" 4972246da4SFelipe Balbi 508300dd23SFelipe Balbi /* -------------------------------------------------------------------------- */ 518300dd23SFelipe Balbi 523140e8cbSSebastian Andrzej Siewior void dwc3_set_mode(struct dwc3 *dwc, u32 mode) 533140e8cbSSebastian Andrzej Siewior { 543140e8cbSSebastian Andrzej Siewior u32 reg; 553140e8cbSSebastian Andrzej Siewior 563140e8cbSSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 573140e8cbSSebastian Andrzej Siewior reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); 583140e8cbSSebastian Andrzej Siewior reg |= DWC3_GCTL_PRTCAPDIR(mode); 593140e8cbSSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 603140e8cbSSebastian Andrzej Siewior } 618300dd23SFelipe Balbi 6272246da4SFelipe Balbi /** 6372246da4SFelipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 6472246da4SFelipe Balbi * @dwc: pointer to our context structure 6572246da4SFelipe Balbi */ 6657303488SKishon Vijay Abraham I static int dwc3_core_soft_reset(struct dwc3 *dwc) 6772246da4SFelipe Balbi { 6872246da4SFelipe Balbi u32 reg; 6957303488SKishon Vijay Abraham I int ret; 7072246da4SFelipe Balbi 7172246da4SFelipe Balbi /* Before Resetting PHY, put Core in Reset */ 7272246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 7372246da4SFelipe Balbi reg |= DWC3_GCTL_CORESOFTRESET; 7472246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 7572246da4SFelipe Balbi 7672246da4SFelipe Balbi /* Assert USB3 PHY reset */ 7772246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 7872246da4SFelipe Balbi reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; 7972246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 8072246da4SFelipe Balbi 8172246da4SFelipe Balbi /* Assert USB2 PHY reset */ 8272246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 8372246da4SFelipe Balbi reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; 8472246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 8572246da4SFelipe Balbi 8651e1e7bcSFelipe Balbi usb_phy_init(dwc->usb2_phy); 8751e1e7bcSFelipe Balbi usb_phy_init(dwc->usb3_phy); 8857303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 8957303488SKishon Vijay Abraham I if (ret < 0) 9057303488SKishon Vijay Abraham I return ret; 9157303488SKishon Vijay Abraham I 9257303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 9357303488SKishon Vijay Abraham I if (ret < 0) { 9457303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 9557303488SKishon Vijay Abraham I return ret; 9657303488SKishon Vijay Abraham I } 9772246da4SFelipe Balbi mdelay(100); 9872246da4SFelipe Balbi 9972246da4SFelipe Balbi /* Clear USB3 PHY reset */ 10072246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 10172246da4SFelipe Balbi reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; 10272246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 10372246da4SFelipe Balbi 10472246da4SFelipe Balbi /* Clear USB2 PHY reset */ 10572246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 10672246da4SFelipe Balbi reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; 10772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 10872246da4SFelipe Balbi 10945627ac6SPratyush Anand mdelay(100); 11045627ac6SPratyush Anand 11172246da4SFelipe Balbi /* After PHYs are stable we can take Core out of reset state */ 11272246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 11372246da4SFelipe Balbi reg &= ~DWC3_GCTL_CORESOFTRESET; 11472246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 11557303488SKishon Vijay Abraham I 11657303488SKishon Vijay Abraham I return 0; 11772246da4SFelipe Balbi } 11872246da4SFelipe Balbi 11972246da4SFelipe Balbi /** 12072246da4SFelipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 12172246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 12272246da4SFelipe Balbi * @evt: Pointer to event buffer to be freed 12372246da4SFelipe Balbi */ 12472246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc, 12572246da4SFelipe Balbi struct dwc3_event_buffer *evt) 12672246da4SFelipe Balbi { 12772246da4SFelipe Balbi dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); 12872246da4SFelipe Balbi } 12972246da4SFelipe Balbi 13072246da4SFelipe Balbi /** 1311d046793SPaul Zimmerman * dwc3_alloc_one_event_buffer - Allocates one event buffer structure 13272246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 13372246da4SFelipe Balbi * @length: size of the event buffer 13472246da4SFelipe Balbi * 1351d046793SPaul Zimmerman * Returns a pointer to the allocated event buffer structure on success 13672246da4SFelipe Balbi * otherwise ERR_PTR(errno). 13772246da4SFelipe Balbi */ 13867d0b500SFelipe Balbi static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, 13967d0b500SFelipe Balbi unsigned length) 14072246da4SFelipe Balbi { 14172246da4SFelipe Balbi struct dwc3_event_buffer *evt; 14272246da4SFelipe Balbi 143380f0d28SFelipe Balbi evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL); 14472246da4SFelipe Balbi if (!evt) 14572246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 14672246da4SFelipe Balbi 14772246da4SFelipe Balbi evt->dwc = dwc; 14872246da4SFelipe Balbi evt->length = length; 14972246da4SFelipe Balbi evt->buf = dma_alloc_coherent(dwc->dev, length, 15072246da4SFelipe Balbi &evt->dma, GFP_KERNEL); 151e32672f0SFelipe Balbi if (!evt->buf) 15272246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 15372246da4SFelipe Balbi 15472246da4SFelipe Balbi return evt; 15572246da4SFelipe Balbi } 15672246da4SFelipe Balbi 15772246da4SFelipe Balbi /** 15872246da4SFelipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 15972246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 16072246da4SFelipe Balbi */ 16172246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc) 16272246da4SFelipe Balbi { 16372246da4SFelipe Balbi struct dwc3_event_buffer *evt; 16472246da4SFelipe Balbi int i; 16572246da4SFelipe Balbi 1669f622b2aSFelipe Balbi for (i = 0; i < dwc->num_event_buffers; i++) { 16772246da4SFelipe Balbi evt = dwc->ev_buffs[i]; 16864b6c8a7SAnton Tikhomirov if (evt) 16972246da4SFelipe Balbi dwc3_free_one_event_buffer(dwc, evt); 17072246da4SFelipe Balbi } 17172246da4SFelipe Balbi } 17272246da4SFelipe Balbi 17372246da4SFelipe Balbi /** 17472246da4SFelipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 1751d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 17672246da4SFelipe Balbi * @length: size of event buffer 17772246da4SFelipe Balbi * 1781d046793SPaul Zimmerman * Returns 0 on success otherwise negative errno. In the error case, dwc 17972246da4SFelipe Balbi * may contain some buffers allocated but not all which were requested. 18072246da4SFelipe Balbi */ 18141ac7b3aSBill Pemberton static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) 18272246da4SFelipe Balbi { 1839f622b2aSFelipe Balbi int num; 18472246da4SFelipe Balbi int i; 18572246da4SFelipe Balbi 1869f622b2aSFelipe Balbi num = DWC3_NUM_INT(dwc->hwparams.hwparams1); 1879f622b2aSFelipe Balbi dwc->num_event_buffers = num; 1889f622b2aSFelipe Balbi 189380f0d28SFelipe Balbi dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num, 190380f0d28SFelipe Balbi GFP_KERNEL); 191734d5a53SJingoo Han if (!dwc->ev_buffs) 192457d3f21SFelipe Balbi return -ENOMEM; 193457d3f21SFelipe Balbi 19472246da4SFelipe Balbi for (i = 0; i < num; i++) { 19572246da4SFelipe Balbi struct dwc3_event_buffer *evt; 19672246da4SFelipe Balbi 19772246da4SFelipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 19872246da4SFelipe Balbi if (IS_ERR(evt)) { 19972246da4SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 20072246da4SFelipe Balbi return PTR_ERR(evt); 20172246da4SFelipe Balbi } 20272246da4SFelipe Balbi dwc->ev_buffs[i] = evt; 20372246da4SFelipe Balbi } 20472246da4SFelipe Balbi 20572246da4SFelipe Balbi return 0; 20672246da4SFelipe Balbi } 20772246da4SFelipe Balbi 20872246da4SFelipe Balbi /** 20972246da4SFelipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 2101d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 21172246da4SFelipe Balbi * 21272246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 21372246da4SFelipe Balbi */ 2147acd85e0SPaul Zimmerman static int dwc3_event_buffers_setup(struct dwc3 *dwc) 21572246da4SFelipe Balbi { 21672246da4SFelipe Balbi struct dwc3_event_buffer *evt; 21772246da4SFelipe Balbi int n; 21872246da4SFelipe Balbi 2199f622b2aSFelipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 22072246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 22172246da4SFelipe Balbi dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n", 22272246da4SFelipe Balbi evt->buf, (unsigned long long) evt->dma, 22372246da4SFelipe Balbi evt->length); 22472246da4SFelipe Balbi 2257acd85e0SPaul Zimmerman evt->lpos = 0; 2267acd85e0SPaul Zimmerman 22772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 22872246da4SFelipe Balbi lower_32_bits(evt->dma)); 22972246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 23072246da4SFelipe Balbi upper_32_bits(evt->dma)); 23172246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 23268d6a01bSFelipe Balbi DWC3_GEVNTSIZ_SIZE(evt->length)); 23372246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 23472246da4SFelipe Balbi } 23572246da4SFelipe Balbi 23672246da4SFelipe Balbi return 0; 23772246da4SFelipe Balbi } 23872246da4SFelipe Balbi 23972246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 24072246da4SFelipe Balbi { 24172246da4SFelipe Balbi struct dwc3_event_buffer *evt; 24272246da4SFelipe Balbi int n; 24372246da4SFelipe Balbi 2449f622b2aSFelipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 24572246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 2467acd85e0SPaul Zimmerman 2477acd85e0SPaul Zimmerman evt->lpos = 0; 2487acd85e0SPaul Zimmerman 24972246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); 25072246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); 25168d6a01bSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK 25268d6a01bSFelipe Balbi | DWC3_GEVNTSIZ_SIZE(0)); 25372246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 25472246da4SFelipe Balbi } 25572246da4SFelipe Balbi } 25672246da4SFelipe Balbi 2570ffcaf37SFelipe Balbi static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) 2580ffcaf37SFelipe Balbi { 2590ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 2600ffcaf37SFelipe Balbi return 0; 2610ffcaf37SFelipe Balbi 2620ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 2630ffcaf37SFelipe Balbi return 0; 2640ffcaf37SFelipe Balbi 2650ffcaf37SFelipe Balbi dwc->scratchbuf = kmalloc_array(dwc->nr_scratch, 2660ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, GFP_KERNEL); 2670ffcaf37SFelipe Balbi if (!dwc->scratchbuf) 2680ffcaf37SFelipe Balbi return -ENOMEM; 2690ffcaf37SFelipe Balbi 2700ffcaf37SFelipe Balbi return 0; 2710ffcaf37SFelipe Balbi } 2720ffcaf37SFelipe Balbi 2730ffcaf37SFelipe Balbi static int dwc3_setup_scratch_buffers(struct dwc3 *dwc) 2740ffcaf37SFelipe Balbi { 2750ffcaf37SFelipe Balbi dma_addr_t scratch_addr; 2760ffcaf37SFelipe Balbi u32 param; 2770ffcaf37SFelipe Balbi int ret; 2780ffcaf37SFelipe Balbi 2790ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 2800ffcaf37SFelipe Balbi return 0; 2810ffcaf37SFelipe Balbi 2820ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 2830ffcaf37SFelipe Balbi return 0; 2840ffcaf37SFelipe Balbi 2850ffcaf37SFelipe Balbi /* should never fall here */ 2860ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 2870ffcaf37SFelipe Balbi return 0; 2880ffcaf37SFelipe Balbi 2890ffcaf37SFelipe Balbi scratch_addr = dma_map_single(dwc->dev, dwc->scratchbuf, 2900ffcaf37SFelipe Balbi dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, 2910ffcaf37SFelipe Balbi DMA_BIDIRECTIONAL); 2920ffcaf37SFelipe Balbi if (dma_mapping_error(dwc->dev, scratch_addr)) { 2930ffcaf37SFelipe Balbi dev_err(dwc->dev, "failed to map scratch buffer\n"); 2940ffcaf37SFelipe Balbi ret = -EFAULT; 2950ffcaf37SFelipe Balbi goto err0; 2960ffcaf37SFelipe Balbi } 2970ffcaf37SFelipe Balbi 2980ffcaf37SFelipe Balbi dwc->scratch_addr = scratch_addr; 2990ffcaf37SFelipe Balbi 3000ffcaf37SFelipe Balbi param = lower_32_bits(scratch_addr); 3010ffcaf37SFelipe Balbi 3020ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3030ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param); 3040ffcaf37SFelipe Balbi if (ret < 0) 3050ffcaf37SFelipe Balbi goto err1; 3060ffcaf37SFelipe Balbi 3070ffcaf37SFelipe Balbi param = upper_32_bits(scratch_addr); 3080ffcaf37SFelipe Balbi 3090ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3100ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param); 3110ffcaf37SFelipe Balbi if (ret < 0) 3120ffcaf37SFelipe Balbi goto err1; 3130ffcaf37SFelipe Balbi 3140ffcaf37SFelipe Balbi return 0; 3150ffcaf37SFelipe Balbi 3160ffcaf37SFelipe Balbi err1: 3170ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3180ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3190ffcaf37SFelipe Balbi 3200ffcaf37SFelipe Balbi err0: 3210ffcaf37SFelipe Balbi return ret; 3220ffcaf37SFelipe Balbi } 3230ffcaf37SFelipe Balbi 3240ffcaf37SFelipe Balbi static void dwc3_free_scratch_buffers(struct dwc3 *dwc) 3250ffcaf37SFelipe Balbi { 3260ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3270ffcaf37SFelipe Balbi return; 3280ffcaf37SFelipe Balbi 3290ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3300ffcaf37SFelipe Balbi return; 3310ffcaf37SFelipe Balbi 3320ffcaf37SFelipe Balbi /* should never fall here */ 3330ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 3340ffcaf37SFelipe Balbi return; 3350ffcaf37SFelipe Balbi 3360ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3370ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3380ffcaf37SFelipe Balbi kfree(dwc->scratchbuf); 3390ffcaf37SFelipe Balbi } 3400ffcaf37SFelipe Balbi 341789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc) 342789451f6SFelipe Balbi { 343789451f6SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 344789451f6SFelipe Balbi 345789451f6SFelipe Balbi dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); 346789451f6SFelipe Balbi dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; 347789451f6SFelipe Balbi 348789451f6SFelipe Balbi dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n", 349789451f6SFelipe Balbi dwc->num_in_eps, dwc->num_out_eps); 350789451f6SFelipe Balbi } 351789451f6SFelipe Balbi 35241ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc) 35326ceca97SFelipe Balbi { 35426ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 35526ceca97SFelipe Balbi 35626ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 35726ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 35826ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 35926ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 36026ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 36126ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 36226ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 36326ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 36426ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 36526ceca97SFelipe Balbi } 36626ceca97SFelipe Balbi 36772246da4SFelipe Balbi /** 368b5a65c40SHuang Rui * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core 369b5a65c40SHuang Rui * @dwc: Pointer to our controller context structure 370b5a65c40SHuang Rui */ 371b5a65c40SHuang Rui static void dwc3_phy_setup(struct dwc3 *dwc) 372b5a65c40SHuang Rui { 373b5a65c40SHuang Rui u32 reg; 374b5a65c40SHuang Rui 375b5a65c40SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 376b5a65c40SHuang Rui 3772164a476SHuang Rui /* 3782164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY 3792164a476SHuang Rui * to '0' during coreConsultant configuration. So default value 3802164a476SHuang Rui * will be '0' when the core is reset. Application needs to set it 3812164a476SHuang Rui * to '1' after the core initialization is completed. 3822164a476SHuang Rui */ 3832164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 3842164a476SHuang Rui reg |= DWC3_GUSB3PIPECTL_SUSPHY; 3852164a476SHuang Rui 386b5a65c40SHuang Rui if (dwc->u2ss_inp3_quirk) 387b5a65c40SHuang Rui reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; 388b5a65c40SHuang Rui 389df31f5b3SHuang Rui if (dwc->req_p1p2p3_quirk) 390df31f5b3SHuang Rui reg |= DWC3_GUSB3PIPECTL_REQP1P2P3; 391df31f5b3SHuang Rui 392a2a1d0f5SHuang Rui if (dwc->del_p1p2p3_quirk) 393a2a1d0f5SHuang Rui reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN; 394a2a1d0f5SHuang Rui 39541c06ffdSHuang Rui if (dwc->del_phy_power_chg_quirk) 39641c06ffdSHuang Rui reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE; 39741c06ffdSHuang Rui 398fb67afcaSHuang Rui if (dwc->lfps_filter_quirk) 399fb67afcaSHuang Rui reg |= DWC3_GUSB3PIPECTL_LFPSFILT; 400fb67afcaSHuang Rui 40114f4ac53SHuang Rui if (dwc->rx_detect_poll_quirk) 40214f4ac53SHuang Rui reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL; 40314f4ac53SHuang Rui 4046b6a0c9aSHuang Rui if (dwc->tx_de_emphasis_quirk) 4056b6a0c9aSHuang Rui reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); 4066b6a0c9aSHuang Rui 40759acfa20SHuang Rui if (dwc->dis_u3_susphy_quirk && dwc->is_fpga) 40859acfa20SHuang Rui reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 40959acfa20SHuang Rui 410b5a65c40SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 411b5a65c40SHuang Rui 412b5a65c40SHuang Rui mdelay(100); 4132164a476SHuang Rui 4142164a476SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 4152164a476SHuang Rui 4162164a476SHuang Rui /* 4172164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to 4182164a476SHuang Rui * '0' during coreConsultant configuration. So default value will 4192164a476SHuang Rui * be '0' when the core is reset. Application needs to set it to 4202164a476SHuang Rui * '1' after the core initialization is completed. 4212164a476SHuang Rui */ 4222164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 4232164a476SHuang Rui reg |= DWC3_GUSB2PHYCFG_SUSPHY; 4242164a476SHuang Rui 4250effe0a3SHuang Rui if (dwc->dis_u2_susphy_quirk && dwc->is_fpga) 4260effe0a3SHuang Rui reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 4270effe0a3SHuang Rui 4282164a476SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 4292164a476SHuang Rui 4302164a476SHuang Rui mdelay(100); 431b5a65c40SHuang Rui } 432b5a65c40SHuang Rui 433b5a65c40SHuang Rui /** 43472246da4SFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 43572246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 43672246da4SFelipe Balbi * 43772246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 43872246da4SFelipe Balbi */ 43941ac7b3aSBill Pemberton static int dwc3_core_init(struct dwc3 *dwc) 44072246da4SFelipe Balbi { 44172246da4SFelipe Balbi unsigned long timeout; 4420ffcaf37SFelipe Balbi u32 hwparams4 = dwc->hwparams.hwparams4; 44372246da4SFelipe Balbi u32 reg; 44472246da4SFelipe Balbi int ret; 44572246da4SFelipe Balbi 4467650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 4477650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 4487650bd74SSebastian Andrzej Siewior if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { 4497650bd74SSebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 4507650bd74SSebastian Andrzej Siewior ret = -ENODEV; 4517650bd74SSebastian Andrzej Siewior goto err0; 4527650bd74SSebastian Andrzej Siewior } 453248b122bSFelipe Balbi dwc->revision = reg; 4547650bd74SSebastian Andrzej Siewior 455fa0ea13eSFelipe Balbi /* 456fa0ea13eSFelipe Balbi * Write Linux Version Code to our GUID register so it's easy to figure 457fa0ea13eSFelipe Balbi * out which kernel version a bug was found. 458fa0ea13eSFelipe Balbi */ 459fa0ea13eSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); 460fa0ea13eSFelipe Balbi 4610e1e5c47SPaul Zimmerman /* Handle USB2.0-only core configuration */ 4620e1e5c47SPaul Zimmerman if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 4630e1e5c47SPaul Zimmerman DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { 4640e1e5c47SPaul Zimmerman if (dwc->maximum_speed == USB_SPEED_SUPER) 4650e1e5c47SPaul Zimmerman dwc->maximum_speed = USB_SPEED_HIGH; 4660e1e5c47SPaul Zimmerman } 4670e1e5c47SPaul Zimmerman 46872246da4SFelipe Balbi /* issue device SoftReset too */ 46972246da4SFelipe Balbi timeout = jiffies + msecs_to_jiffies(500); 47072246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); 47172246da4SFelipe Balbi do { 47272246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 47372246da4SFelipe Balbi if (!(reg & DWC3_DCTL_CSFTRST)) 47472246da4SFelipe Balbi break; 47572246da4SFelipe Balbi 47672246da4SFelipe Balbi if (time_after(jiffies, timeout)) { 47772246da4SFelipe Balbi dev_err(dwc->dev, "Reset Timed Out\n"); 47872246da4SFelipe Balbi ret = -ETIMEDOUT; 47972246da4SFelipe Balbi goto err0; 48072246da4SFelipe Balbi } 48172246da4SFelipe Balbi 48272246da4SFelipe Balbi cpu_relax(); 48372246da4SFelipe Balbi } while (true); 48472246da4SFelipe Balbi 48557303488SKishon Vijay Abraham I ret = dwc3_core_soft_reset(dwc); 48657303488SKishon Vijay Abraham I if (ret) 48757303488SKishon Vijay Abraham I goto err0; 48858a0f23fSPratyush Anand 4894878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 4903e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 4914878a028SSebastian Andrzej Siewior 492164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 4934878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 49432a4a135SFelipe Balbi /** 49532a4a135SFelipe Balbi * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an 49632a4a135SFelipe Balbi * issue which would cause xHCI compliance tests to fail. 49732a4a135SFelipe Balbi * 49832a4a135SFelipe Balbi * Because of that we cannot enable clock gating on such 49932a4a135SFelipe Balbi * configurations. 50032a4a135SFelipe Balbi * 50132a4a135SFelipe Balbi * Refers to: 50232a4a135SFelipe Balbi * 50332a4a135SFelipe Balbi * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based 50432a4a135SFelipe Balbi * SOF/ITP Mode Used 50532a4a135SFelipe Balbi */ 50632a4a135SFelipe Balbi if ((dwc->dr_mode == USB_DR_MODE_HOST || 50732a4a135SFelipe Balbi dwc->dr_mode == USB_DR_MODE_OTG) && 50832a4a135SFelipe Balbi (dwc->revision >= DWC3_REVISION_210A && 50932a4a135SFelipe Balbi dwc->revision <= DWC3_REVISION_250A)) 51032a4a135SFelipe Balbi reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; 51132a4a135SFelipe Balbi else 5124878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 5134878a028SSebastian Andrzej Siewior break; 5140ffcaf37SFelipe Balbi case DWC3_GHWPARAMS1_EN_PWROPT_HIB: 5150ffcaf37SFelipe Balbi /* enable hibernation here */ 5160ffcaf37SFelipe Balbi dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); 5172eac3992SHuang Rui 5182eac3992SHuang Rui /* 5192eac3992SHuang Rui * REVISIT Enabling this bit so that host-mode hibernation 5202eac3992SHuang Rui * will work. Device-mode hibernation is not yet implemented. 5212eac3992SHuang Rui */ 5222eac3992SHuang Rui reg |= DWC3_GCTL_GBLHIBERNATIONEN; 5230ffcaf37SFelipe Balbi break; 5244878a028SSebastian Andrzej Siewior default: 5254878a028SSebastian Andrzej Siewior dev_dbg(dwc->dev, "No power optimization available\n"); 5264878a028SSebastian Andrzej Siewior } 5274878a028SSebastian Andrzej Siewior 528946bd579SHuang Rui /* check if current dwc3 is on simulation board */ 529946bd579SHuang Rui if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { 530946bd579SHuang Rui dev_dbg(dwc->dev, "it is on FPGA board\n"); 531946bd579SHuang Rui dwc->is_fpga = true; 532946bd579SHuang Rui } 533946bd579SHuang Rui 5343b81221aSHuang Rui WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga, 5353b81221aSHuang Rui "disable_scramble cannot be used on non-FPGA builds\n"); 5363b81221aSHuang Rui 5373b81221aSHuang Rui if (dwc->disable_scramble_quirk && dwc->is_fpga) 5383b81221aSHuang Rui reg |= DWC3_GCTL_DISSCRAMBLE; 5393b81221aSHuang Rui else 5403b81221aSHuang Rui reg &= ~DWC3_GCTL_DISSCRAMBLE; 5413b81221aSHuang Rui 5429a5b2f31SHuang Rui if (dwc->u2exit_lfps_quirk) 5439a5b2f31SHuang Rui reg |= DWC3_GCTL_U2EXIT_LFPS; 5449a5b2f31SHuang Rui 5454878a028SSebastian Andrzej Siewior /* 5464878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 5471d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 5484878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 5491d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 5504878a028SSebastian Andrzej Siewior */ 5514878a028SSebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 5524878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 5534878a028SSebastian Andrzej Siewior 554789451f6SFelipe Balbi dwc3_core_num_eps(dwc); 555789451f6SFelipe Balbi 5564878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 5574878a028SSebastian Andrzej Siewior 558b5a65c40SHuang Rui dwc3_phy_setup(dwc); 559b5a65c40SHuang Rui 5600ffcaf37SFelipe Balbi ret = dwc3_alloc_scratch_buffers(dwc); 5610ffcaf37SFelipe Balbi if (ret) 5620ffcaf37SFelipe Balbi goto err1; 5630ffcaf37SFelipe Balbi 5640ffcaf37SFelipe Balbi ret = dwc3_setup_scratch_buffers(dwc); 5650ffcaf37SFelipe Balbi if (ret) 5660ffcaf37SFelipe Balbi goto err2; 5670ffcaf37SFelipe Balbi 56872246da4SFelipe Balbi return 0; 56972246da4SFelipe Balbi 5700ffcaf37SFelipe Balbi err2: 5710ffcaf37SFelipe Balbi dwc3_free_scratch_buffers(dwc); 5720ffcaf37SFelipe Balbi 5730ffcaf37SFelipe Balbi err1: 5740ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 5750ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 57657303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 57757303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 5780ffcaf37SFelipe Balbi 57972246da4SFelipe Balbi err0: 58072246da4SFelipe Balbi return ret; 58172246da4SFelipe Balbi } 58272246da4SFelipe Balbi 58372246da4SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 58472246da4SFelipe Balbi { 5850ffcaf37SFelipe Balbi dwc3_free_scratch_buffers(dwc); 58601b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb2_phy); 58701b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb3_phy); 58857303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 58957303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 59072246da4SFelipe Balbi } 59172246da4SFelipe Balbi 5923c9f94acSFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc) 59372246da4SFelipe Balbi { 5943c9f94acSFelipe Balbi struct device *dev = dwc->dev; 595941ea361SFelipe Balbi struct device_node *node = dev->of_node; 5963c9f94acSFelipe Balbi int ret; 59772246da4SFelipe Balbi 5985088b6f5SKishon Vijay Abraham I if (node) { 5995088b6f5SKishon Vijay Abraham I dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); 6005088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); 601bb674907SFelipe Balbi } else { 602bb674907SFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 603bb674907SFelipe Balbi dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 6045088b6f5SKishon Vijay Abraham I } 6055088b6f5SKishon Vijay Abraham I 606d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb2_phy)) { 607d105e7f8SFelipe Balbi ret = PTR_ERR(dwc->usb2_phy); 608122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 609122f06e6SKishon Vijay Abraham I dwc->usb2_phy = NULL; 610122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 611d105e7f8SFelipe Balbi return ret; 612122f06e6SKishon Vijay Abraham I } else { 61351e1e7bcSFelipe Balbi dev_err(dev, "no usb2 phy configured\n"); 614122f06e6SKishon Vijay Abraham I return ret; 615122f06e6SKishon Vijay Abraham I } 61651e1e7bcSFelipe Balbi } 61751e1e7bcSFelipe Balbi 618d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb3_phy)) { 619315955d7SRuchika Kharwar ret = PTR_ERR(dwc->usb3_phy); 620122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 621122f06e6SKishon Vijay Abraham I dwc->usb3_phy = NULL; 622122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 623d105e7f8SFelipe Balbi return ret; 624122f06e6SKishon Vijay Abraham I } else { 62551e1e7bcSFelipe Balbi dev_err(dev, "no usb3 phy configured\n"); 626122f06e6SKishon Vijay Abraham I return ret; 627122f06e6SKishon Vijay Abraham I } 62851e1e7bcSFelipe Balbi } 62951e1e7bcSFelipe Balbi 63057303488SKishon Vijay Abraham I dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); 63157303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb2_generic_phy)) { 63257303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb2_generic_phy); 63357303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 63457303488SKishon Vijay Abraham I dwc->usb2_generic_phy = NULL; 63557303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 63657303488SKishon Vijay Abraham I return ret; 63757303488SKishon Vijay Abraham I } else { 63857303488SKishon Vijay Abraham I dev_err(dev, "no usb2 phy configured\n"); 63957303488SKishon Vijay Abraham I return ret; 64057303488SKishon Vijay Abraham I } 64157303488SKishon Vijay Abraham I } 64257303488SKishon Vijay Abraham I 64357303488SKishon Vijay Abraham I dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy"); 64457303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb3_generic_phy)) { 64557303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb3_generic_phy); 64657303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 64757303488SKishon Vijay Abraham I dwc->usb3_generic_phy = NULL; 64857303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 64957303488SKishon Vijay Abraham I return ret; 65057303488SKishon Vijay Abraham I } else { 65157303488SKishon Vijay Abraham I dev_err(dev, "no usb3 phy configured\n"); 65257303488SKishon Vijay Abraham I return ret; 65357303488SKishon Vijay Abraham I } 65457303488SKishon Vijay Abraham I } 65557303488SKishon Vijay Abraham I 6563c9f94acSFelipe Balbi return 0; 6573c9f94acSFelipe Balbi } 6583c9f94acSFelipe Balbi 6595f94adfeSFelipe Balbi static int dwc3_core_init_mode(struct dwc3 *dwc) 6605f94adfeSFelipe Balbi { 6615f94adfeSFelipe Balbi struct device *dev = dwc->dev; 6625f94adfeSFelipe Balbi int ret; 6635f94adfeSFelipe Balbi 6645f94adfeSFelipe Balbi switch (dwc->dr_mode) { 6655f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 6665f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); 6675f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 6685f94adfeSFelipe Balbi if (ret) { 6695f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 6705f94adfeSFelipe Balbi return ret; 6715f94adfeSFelipe Balbi } 6725f94adfeSFelipe Balbi break; 6735f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 6745f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); 6755f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 6765f94adfeSFelipe Balbi if (ret) { 6775f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 6785f94adfeSFelipe Balbi return ret; 6795f94adfeSFelipe Balbi } 6805f94adfeSFelipe Balbi break; 6815f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 6825f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); 6835f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 6845f94adfeSFelipe Balbi if (ret) { 6855f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 6865f94adfeSFelipe Balbi return ret; 6875f94adfeSFelipe Balbi } 6885f94adfeSFelipe Balbi 6895f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 6905f94adfeSFelipe Balbi if (ret) { 6915f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 6925f94adfeSFelipe Balbi return ret; 6935f94adfeSFelipe Balbi } 6945f94adfeSFelipe Balbi break; 6955f94adfeSFelipe Balbi default: 6965f94adfeSFelipe Balbi dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); 6975f94adfeSFelipe Balbi return -EINVAL; 6985f94adfeSFelipe Balbi } 6995f94adfeSFelipe Balbi 7005f94adfeSFelipe Balbi return 0; 7015f94adfeSFelipe Balbi } 7025f94adfeSFelipe Balbi 7035f94adfeSFelipe Balbi static void dwc3_core_exit_mode(struct dwc3 *dwc) 7045f94adfeSFelipe Balbi { 7055f94adfeSFelipe Balbi switch (dwc->dr_mode) { 7065f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 7075f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 7085f94adfeSFelipe Balbi break; 7095f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 7105f94adfeSFelipe Balbi dwc3_host_exit(dwc); 7115f94adfeSFelipe Balbi break; 7125f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 7135f94adfeSFelipe Balbi dwc3_host_exit(dwc); 7145f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 7155f94adfeSFelipe Balbi break; 7165f94adfeSFelipe Balbi default: 7175f94adfeSFelipe Balbi /* do nothing */ 7185f94adfeSFelipe Balbi break; 7195f94adfeSFelipe Balbi } 7205f94adfeSFelipe Balbi } 7215f94adfeSFelipe Balbi 7223c9f94acSFelipe Balbi #define DWC3_ALIGN_MASK (16 - 1) 7233c9f94acSFelipe Balbi 7243c9f94acSFelipe Balbi static int dwc3_probe(struct platform_device *pdev) 7253c9f94acSFelipe Balbi { 7263c9f94acSFelipe Balbi struct device *dev = &pdev->dev; 7273c9f94acSFelipe Balbi struct dwc3_platform_data *pdata = dev_get_platdata(dev); 7283c9f94acSFelipe Balbi struct device_node *node = dev->of_node; 7293c9f94acSFelipe Balbi struct resource *res; 7303c9f94acSFelipe Balbi struct dwc3 *dwc; 73180caf7d2SHuang Rui u8 lpm_nyet_threshold; 7326b6a0c9aSHuang Rui u8 tx_de_emphasis; 733460d098cSHuang Rui u8 hird_threshold; 7343c9f94acSFelipe Balbi 735b09e99eeSAndy Shevchenko int ret; 7363c9f94acSFelipe Balbi 7373c9f94acSFelipe Balbi void __iomem *regs; 7383c9f94acSFelipe Balbi void *mem; 7393c9f94acSFelipe Balbi 7403c9f94acSFelipe Balbi mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 741734d5a53SJingoo Han if (!mem) 7423c9f94acSFelipe Balbi return -ENOMEM; 743734d5a53SJingoo Han 7443c9f94acSFelipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 7453c9f94acSFelipe Balbi dwc->mem = mem; 7463c9f94acSFelipe Balbi dwc->dev = dev; 7473c9f94acSFelipe Balbi 7483c9f94acSFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 7493c9f94acSFelipe Balbi if (!res) { 7503c9f94acSFelipe Balbi dev_err(dev, "missing IRQ\n"); 7513c9f94acSFelipe Balbi return -ENODEV; 7523c9f94acSFelipe Balbi } 7533c9f94acSFelipe Balbi dwc->xhci_resources[1].start = res->start; 7543c9f94acSFelipe Balbi dwc->xhci_resources[1].end = res->end; 7553c9f94acSFelipe Balbi dwc->xhci_resources[1].flags = res->flags; 7563c9f94acSFelipe Balbi dwc->xhci_resources[1].name = res->name; 7573c9f94acSFelipe Balbi 7583c9f94acSFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 7593c9f94acSFelipe Balbi if (!res) { 7603c9f94acSFelipe Balbi dev_err(dev, "missing memory resource\n"); 7613c9f94acSFelipe Balbi return -ENODEV; 7623c9f94acSFelipe Balbi } 7633c9f94acSFelipe Balbi 764f32a5e23SVivek Gautam dwc->xhci_resources[0].start = res->start; 765f32a5e23SVivek Gautam dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 766f32a5e23SVivek Gautam DWC3_XHCI_REGS_END; 767f32a5e23SVivek Gautam dwc->xhci_resources[0].flags = res->flags; 768f32a5e23SVivek Gautam dwc->xhci_resources[0].name = res->name; 769f32a5e23SVivek Gautam 770f32a5e23SVivek Gautam res->start += DWC3_GLOBALS_REGS_START; 771f32a5e23SVivek Gautam 772f32a5e23SVivek Gautam /* 773f32a5e23SVivek Gautam * Request memory region but exclude xHCI regs, 774f32a5e23SVivek Gautam * since it will be requested by the xhci-plat driver. 775f32a5e23SVivek Gautam */ 776f32a5e23SVivek Gautam regs = devm_ioremap_resource(dev, res); 777f32a5e23SVivek Gautam if (IS_ERR(regs)) 778f32a5e23SVivek Gautam return PTR_ERR(regs); 779f32a5e23SVivek Gautam 780f32a5e23SVivek Gautam dwc->regs = regs; 781f32a5e23SVivek Gautam dwc->regs_size = resource_size(res); 782f32a5e23SVivek Gautam /* 783f32a5e23SVivek Gautam * restore res->start back to its original value so that, 784f32a5e23SVivek Gautam * in case the probe is deferred, we don't end up getting error in 785f32a5e23SVivek Gautam * request the memory region the next time probe is called. 786f32a5e23SVivek Gautam */ 787f32a5e23SVivek Gautam res->start -= DWC3_GLOBALS_REGS_START; 788f32a5e23SVivek Gautam 78980caf7d2SHuang Rui /* default to highest possible threshold */ 79080caf7d2SHuang Rui lpm_nyet_threshold = 0xff; 79180caf7d2SHuang Rui 7926b6a0c9aSHuang Rui /* default to -3.5dB de-emphasis */ 7936b6a0c9aSHuang Rui tx_de_emphasis = 1; 7946b6a0c9aSHuang Rui 795460d098cSHuang Rui /* 796460d098cSHuang Rui * default to assert utmi_sleep_n and use maximum allowed HIRD 797460d098cSHuang Rui * threshold value of 0b1100 798460d098cSHuang Rui */ 799460d098cSHuang Rui hird_threshold = 12; 800460d098cSHuang Rui 8013c9f94acSFelipe Balbi if (node) { 8023c9f94acSFelipe Balbi dwc->maximum_speed = of_usb_get_maximum_speed(node); 80380caf7d2SHuang Rui dwc->has_lpm_erratum = of_property_read_bool(node, 80480caf7d2SHuang Rui "snps,has-lpm-erratum"); 80580caf7d2SHuang Rui of_property_read_u8(node, "snps,lpm-nyet-threshold", 80680caf7d2SHuang Rui &lpm_nyet_threshold); 807460d098cSHuang Rui dwc->is_utmi_l1_suspend = of_property_read_bool(node, 808460d098cSHuang Rui "snps,is-utmi-l1-suspend"); 809460d098cSHuang Rui of_property_read_u8(node, "snps,hird-threshold", 810460d098cSHuang Rui &hird_threshold); 8113c9f94acSFelipe Balbi 81280caf7d2SHuang Rui dwc->needs_fifo_resize = of_property_read_bool(node, 81380caf7d2SHuang Rui "tx-fifo-resize"); 8143c9f94acSFelipe Balbi dwc->dr_mode = of_usb_get_dr_mode(node); 8153b81221aSHuang Rui 8163b81221aSHuang Rui dwc->disable_scramble_quirk = of_property_read_bool(node, 8173b81221aSHuang Rui "snps,disable_scramble_quirk"); 8189a5b2f31SHuang Rui dwc->u2exit_lfps_quirk = of_property_read_bool(node, 8199a5b2f31SHuang Rui "snps,u2exit_lfps_quirk"); 820b5a65c40SHuang Rui dwc->u2ss_inp3_quirk = of_property_read_bool(node, 821b5a65c40SHuang Rui "snps,u2ss_inp3_quirk"); 822df31f5b3SHuang Rui dwc->req_p1p2p3_quirk = of_property_read_bool(node, 823df31f5b3SHuang Rui "snps,req_p1p2p3_quirk"); 824a2a1d0f5SHuang Rui dwc->del_p1p2p3_quirk = of_property_read_bool(node, 825a2a1d0f5SHuang Rui "snps,del_p1p2p3_quirk"); 82641c06ffdSHuang Rui dwc->del_phy_power_chg_quirk = of_property_read_bool(node, 82741c06ffdSHuang Rui "snps,del_phy_power_chg_quirk"); 828fb67afcaSHuang Rui dwc->lfps_filter_quirk = of_property_read_bool(node, 829fb67afcaSHuang Rui "snps,lfps_filter_quirk"); 83014f4ac53SHuang Rui dwc->rx_detect_poll_quirk = of_property_read_bool(node, 83114f4ac53SHuang Rui "snps,rx_detect_poll_quirk"); 83259acfa20SHuang Rui dwc->dis_u3_susphy_quirk = of_property_read_bool(node, 83359acfa20SHuang Rui "snps,dis_u3_susphy_quirk"); 8340effe0a3SHuang Rui dwc->dis_u2_susphy_quirk = of_property_read_bool(node, 8350effe0a3SHuang Rui "snps,dis_u2_susphy_quirk"); 8366b6a0c9aSHuang Rui 8376b6a0c9aSHuang Rui dwc->tx_de_emphasis_quirk = of_property_read_bool(node, 8386b6a0c9aSHuang Rui "snps,tx_de_emphasis_quirk"); 8396b6a0c9aSHuang Rui of_property_read_u8(node, "snps,tx_de_emphasis", 8406b6a0c9aSHuang Rui &tx_de_emphasis); 8413c9f94acSFelipe Balbi } else if (pdata) { 8423c9f94acSFelipe Balbi dwc->maximum_speed = pdata->maximum_speed; 84380caf7d2SHuang Rui dwc->has_lpm_erratum = pdata->has_lpm_erratum; 84480caf7d2SHuang Rui if (pdata->lpm_nyet_threshold) 84580caf7d2SHuang Rui lpm_nyet_threshold = pdata->lpm_nyet_threshold; 846460d098cSHuang Rui dwc->is_utmi_l1_suspend = pdata->is_utmi_l1_suspend; 847460d098cSHuang Rui if (pdata->hird_threshold) 848460d098cSHuang Rui hird_threshold = pdata->hird_threshold; 8493c9f94acSFelipe Balbi 8503c9f94acSFelipe Balbi dwc->needs_fifo_resize = pdata->tx_fifo_resize; 8513c9f94acSFelipe Balbi dwc->dr_mode = pdata->dr_mode; 8523b81221aSHuang Rui 8533b81221aSHuang Rui dwc->disable_scramble_quirk = pdata->disable_scramble_quirk; 8549a5b2f31SHuang Rui dwc->u2exit_lfps_quirk = pdata->u2exit_lfps_quirk; 855b5a65c40SHuang Rui dwc->u2ss_inp3_quirk = pdata->u2ss_inp3_quirk; 856df31f5b3SHuang Rui dwc->req_p1p2p3_quirk = pdata->req_p1p2p3_quirk; 857a2a1d0f5SHuang Rui dwc->del_p1p2p3_quirk = pdata->del_p1p2p3_quirk; 85841c06ffdSHuang Rui dwc->del_phy_power_chg_quirk = pdata->del_phy_power_chg_quirk; 859fb67afcaSHuang Rui dwc->lfps_filter_quirk = pdata->lfps_filter_quirk; 86014f4ac53SHuang Rui dwc->rx_detect_poll_quirk = pdata->rx_detect_poll_quirk; 86159acfa20SHuang Rui dwc->dis_u3_susphy_quirk = pdata->dis_u3_susphy_quirk; 8620effe0a3SHuang Rui dwc->dis_u2_susphy_quirk = pdata->dis_u2_susphy_quirk; 8636b6a0c9aSHuang Rui 8646b6a0c9aSHuang Rui dwc->tx_de_emphasis_quirk = pdata->tx_de_emphasis_quirk; 8656b6a0c9aSHuang Rui if (pdata->tx_de_emphasis) 8666b6a0c9aSHuang Rui tx_de_emphasis = pdata->tx_de_emphasis; 8673c9f94acSFelipe Balbi } 8683c9f94acSFelipe Balbi 8693c9f94acSFelipe Balbi /* default to superspeed if no maximum_speed passed */ 8703c9f94acSFelipe Balbi if (dwc->maximum_speed == USB_SPEED_UNKNOWN) 8713c9f94acSFelipe Balbi dwc->maximum_speed = USB_SPEED_SUPER; 8723c9f94acSFelipe Balbi 87380caf7d2SHuang Rui dwc->lpm_nyet_threshold = lpm_nyet_threshold; 8746b6a0c9aSHuang Rui dwc->tx_de_emphasis = tx_de_emphasis; 87580caf7d2SHuang Rui 876460d098cSHuang Rui dwc->hird_threshold = hird_threshold 877460d098cSHuang Rui | (dwc->is_utmi_l1_suspend << 4); 878460d098cSHuang Rui 8793c9f94acSFelipe Balbi ret = dwc3_core_get_phy(dwc); 8803c9f94acSFelipe Balbi if (ret) 8813c9f94acSFelipe Balbi return ret; 8823c9f94acSFelipe Balbi 88372246da4SFelipe Balbi spin_lock_init(&dwc->lock); 88472246da4SFelipe Balbi platform_set_drvdata(pdev, dwc); 88572246da4SFelipe Balbi 88619bacdc9SHeikki Krogerus if (!dev->dma_mask) { 887ddff14f1SKishon Vijay Abraham I dev->dma_mask = dev->parent->dma_mask; 888ddff14f1SKishon Vijay Abraham I dev->dma_parms = dev->parent->dma_parms; 889ddff14f1SKishon Vijay Abraham I dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); 89019bacdc9SHeikki Krogerus } 891ddff14f1SKishon Vijay Abraham I 892802ca850SChanho Park pm_runtime_enable(dev); 893802ca850SChanho Park pm_runtime_get_sync(dev); 894802ca850SChanho Park pm_runtime_forbid(dev); 89572246da4SFelipe Balbi 8964fd24483SKishon Vijay Abraham I dwc3_cache_hwparams(dwc); 8974fd24483SKishon Vijay Abraham I 8983921426bSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 8993921426bSFelipe Balbi if (ret) { 9003921426bSFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 9013921426bSFelipe Balbi ret = -ENOMEM; 9023921426bSFelipe Balbi goto err0; 9033921426bSFelipe Balbi } 9043921426bSFelipe Balbi 90532a4a135SFelipe Balbi if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) 90632a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_HOST; 90732a4a135SFelipe Balbi else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) 90832a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_PERIPHERAL; 90932a4a135SFelipe Balbi 91032a4a135SFelipe Balbi if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) 91132a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_OTG; 91232a4a135SFelipe Balbi 91372246da4SFelipe Balbi ret = dwc3_core_init(dwc); 91472246da4SFelipe Balbi if (ret) { 915802ca850SChanho Park dev_err(dev, "failed to initialize core\n"); 9163921426bSFelipe Balbi goto err0; 91772246da4SFelipe Balbi } 91872246da4SFelipe Balbi 9193088f108SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 0); 9203088f108SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 0); 92157303488SKishon Vijay Abraham I ret = phy_power_on(dwc->usb2_generic_phy); 92257303488SKishon Vijay Abraham I if (ret < 0) 92357303488SKishon Vijay Abraham I goto err1; 92457303488SKishon Vijay Abraham I 92557303488SKishon Vijay Abraham I ret = phy_power_on(dwc->usb3_generic_phy); 92657303488SKishon Vijay Abraham I if (ret < 0) 92757303488SKishon Vijay Abraham I goto err_usb2phy_power; 9283088f108SKishon Vijay Abraham I 929f122d33eSFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 930f122d33eSFelipe Balbi if (ret) { 931f122d33eSFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 93257303488SKishon Vijay Abraham I goto err_usb3phy_power; 933f122d33eSFelipe Balbi } 934f122d33eSFelipe Balbi 9355f94adfeSFelipe Balbi ret = dwc3_core_init_mode(dwc); 9365f94adfeSFelipe Balbi if (ret) 937f122d33eSFelipe Balbi goto err2; 93872246da4SFelipe Balbi 93972246da4SFelipe Balbi ret = dwc3_debugfs_init(dwc); 94072246da4SFelipe Balbi if (ret) { 941802ca850SChanho Park dev_err(dev, "failed to initialize debugfs\n"); 942f122d33eSFelipe Balbi goto err3; 94372246da4SFelipe Balbi } 94472246da4SFelipe Balbi 945802ca850SChanho Park pm_runtime_allow(dev); 94672246da4SFelipe Balbi 94772246da4SFelipe Balbi return 0; 94872246da4SFelipe Balbi 949f122d33eSFelipe Balbi err3: 9505f94adfeSFelipe Balbi dwc3_core_exit_mode(dwc); 95172246da4SFelipe Balbi 952f122d33eSFelipe Balbi err2: 953f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 954f122d33eSFelipe Balbi 95557303488SKishon Vijay Abraham I err_usb3phy_power: 95657303488SKishon Vijay Abraham I phy_power_off(dwc->usb3_generic_phy); 95757303488SKishon Vijay Abraham I 95857303488SKishon Vijay Abraham I err_usb2phy_power: 95957303488SKishon Vijay Abraham I phy_power_off(dwc->usb2_generic_phy); 96057303488SKishon Vijay Abraham I 961802ca850SChanho Park err1: 962501fae51SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 1); 963501fae51SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 1); 96472246da4SFelipe Balbi dwc3_core_exit(dwc); 96572246da4SFelipe Balbi 9663921426bSFelipe Balbi err0: 9673921426bSFelipe Balbi dwc3_free_event_buffers(dwc); 9683921426bSFelipe Balbi 96972246da4SFelipe Balbi return ret; 97072246da4SFelipe Balbi } 97172246da4SFelipe Balbi 972fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev) 97372246da4SFelipe Balbi { 97472246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 97572246da4SFelipe Balbi 976dc99f16fSFelipe Balbi dwc3_debugfs_exit(dwc); 977dc99f16fSFelipe Balbi dwc3_core_exit_mode(dwc); 978dc99f16fSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 979dc99f16fSFelipe Balbi dwc3_free_event_buffers(dwc); 980dc99f16fSFelipe Balbi 9818ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 1); 9828ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 1); 98357303488SKishon Vijay Abraham I phy_power_off(dwc->usb2_generic_phy); 98457303488SKishon Vijay Abraham I phy_power_off(dwc->usb3_generic_phy); 9858ba007a9SKishon Vijay Abraham I 98672246da4SFelipe Balbi dwc3_core_exit(dwc); 98772246da4SFelipe Balbi 9887415f17cSFelipe Balbi pm_runtime_put_sync(&pdev->dev); 9897415f17cSFelipe Balbi pm_runtime_disable(&pdev->dev); 9907415f17cSFelipe Balbi 99172246da4SFelipe Balbi return 0; 99272246da4SFelipe Balbi } 99372246da4SFelipe Balbi 9947415f17cSFelipe Balbi #ifdef CONFIG_PM_SLEEP 9957415f17cSFelipe Balbi static int dwc3_suspend(struct device *dev) 9967415f17cSFelipe Balbi { 9977415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 9987415f17cSFelipe Balbi unsigned long flags; 9997415f17cSFelipe Balbi 10007415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 10017415f17cSFelipe Balbi 1002a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 1003a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 1004a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 10057415f17cSFelipe Balbi dwc3_gadget_suspend(dwc); 10067415f17cSFelipe Balbi /* FALLTHROUGH */ 1007a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 10087415f17cSFelipe Balbi default: 10090b0231aaSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 10107415f17cSFelipe Balbi break; 10117415f17cSFelipe Balbi } 10127415f17cSFelipe Balbi 10137415f17cSFelipe Balbi dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL); 10147415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 10157415f17cSFelipe Balbi 10167415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 10177415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 101857303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 101957303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 10207415f17cSFelipe Balbi 10217415f17cSFelipe Balbi return 0; 10227415f17cSFelipe Balbi } 10237415f17cSFelipe Balbi 10247415f17cSFelipe Balbi static int dwc3_resume(struct device *dev) 10257415f17cSFelipe Balbi { 10267415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 10277415f17cSFelipe Balbi unsigned long flags; 102857303488SKishon Vijay Abraham I int ret; 10297415f17cSFelipe Balbi 10307415f17cSFelipe Balbi usb_phy_init(dwc->usb3_phy); 10317415f17cSFelipe Balbi usb_phy_init(dwc->usb2_phy); 103257303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 103357303488SKishon Vijay Abraham I if (ret < 0) 103457303488SKishon Vijay Abraham I return ret; 103557303488SKishon Vijay Abraham I 103657303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 103757303488SKishon Vijay Abraham I if (ret < 0) 103857303488SKishon Vijay Abraham I goto err_usb2phy_init; 10397415f17cSFelipe Balbi 10407415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 10417415f17cSFelipe Balbi 10420b0231aaSFelipe Balbi dwc3_event_buffers_setup(dwc); 10437415f17cSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl); 10447415f17cSFelipe Balbi 1045a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 1046a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 1047a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 10487415f17cSFelipe Balbi dwc3_gadget_resume(dwc); 10497415f17cSFelipe Balbi /* FALLTHROUGH */ 1050a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 10517415f17cSFelipe Balbi default: 10527415f17cSFelipe Balbi /* do nothing */ 10537415f17cSFelipe Balbi break; 10547415f17cSFelipe Balbi } 10557415f17cSFelipe Balbi 10567415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 10577415f17cSFelipe Balbi 10587415f17cSFelipe Balbi pm_runtime_disable(dev); 10597415f17cSFelipe Balbi pm_runtime_set_active(dev); 10607415f17cSFelipe Balbi pm_runtime_enable(dev); 10617415f17cSFelipe Balbi 10627415f17cSFelipe Balbi return 0; 106357303488SKishon Vijay Abraham I 106457303488SKishon Vijay Abraham I err_usb2phy_init: 106557303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 106657303488SKishon Vijay Abraham I 106757303488SKishon Vijay Abraham I return ret; 10687415f17cSFelipe Balbi } 10697415f17cSFelipe Balbi 10707415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = { 10717415f17cSFelipe Balbi SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 10727415f17cSFelipe Balbi }; 10737415f17cSFelipe Balbi 10747415f17cSFelipe Balbi #define DWC3_PM_OPS &(dwc3_dev_pm_ops) 10757415f17cSFelipe Balbi #else 10767415f17cSFelipe Balbi #define DWC3_PM_OPS NULL 10777415f17cSFelipe Balbi #endif 10787415f17cSFelipe Balbi 10795088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF 10805088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = { 10815088b6f5SKishon Vijay Abraham I { 108222a5aa17SFelipe Balbi .compatible = "snps,dwc3" 108322a5aa17SFelipe Balbi }, 108422a5aa17SFelipe Balbi { 10855088b6f5SKishon Vijay Abraham I .compatible = "synopsys,dwc3" 10865088b6f5SKishon Vijay Abraham I }, 10875088b6f5SKishon Vijay Abraham I { }, 10885088b6f5SKishon Vijay Abraham I }; 10895088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match); 10905088b6f5SKishon Vijay Abraham I #endif 10915088b6f5SKishon Vijay Abraham I 1092404905a6SHeikki Krogerus #ifdef CONFIG_ACPI 1093404905a6SHeikki Krogerus 1094404905a6SHeikki Krogerus #define ACPI_ID_INTEL_BSW "808622B7" 1095404905a6SHeikki Krogerus 1096404905a6SHeikki Krogerus static const struct acpi_device_id dwc3_acpi_match[] = { 1097404905a6SHeikki Krogerus { ACPI_ID_INTEL_BSW, 0 }, 1098404905a6SHeikki Krogerus { }, 1099404905a6SHeikki Krogerus }; 1100404905a6SHeikki Krogerus MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match); 1101404905a6SHeikki Krogerus #endif 1102404905a6SHeikki Krogerus 110372246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 110472246da4SFelipe Balbi .probe = dwc3_probe, 11057690417dSBill Pemberton .remove = dwc3_remove, 110672246da4SFelipe Balbi .driver = { 110772246da4SFelipe Balbi .name = "dwc3", 11085088b6f5SKishon Vijay Abraham I .of_match_table = of_match_ptr(of_dwc3_match), 1109404905a6SHeikki Krogerus .acpi_match_table = ACPI_PTR(dwc3_acpi_match), 11107415f17cSFelipe Balbi .pm = DWC3_PM_OPS, 111172246da4SFelipe Balbi }, 111272246da4SFelipe Balbi }; 111372246da4SFelipe Balbi 1114b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 1115b1116dccSTobias Klauser 11167ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 111772246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 11185945f789SFelipe Balbi MODULE_LICENSE("GPL v2"); 111972246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 1120