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> 3672246da4SFelipe Balbi 3772246da4SFelipe Balbi #include <linux/usb/ch9.h> 3872246da4SFelipe Balbi #include <linux/usb/gadget.h> 39f7e846f0SFelipe Balbi #include <linux/usb/of.h> 40a45c82b8SRuchika Kharwar #include <linux/usb/otg.h> 4172246da4SFelipe Balbi 426462cbd5SFelipe Balbi #include "platform_data.h" 4372246da4SFelipe Balbi #include "core.h" 4472246da4SFelipe Balbi #include "gadget.h" 4572246da4SFelipe Balbi #include "io.h" 4672246da4SFelipe Balbi 4772246da4SFelipe Balbi #include "debug.h" 4872246da4SFelipe Balbi 498300dd23SFelipe Balbi /* -------------------------------------------------------------------------- */ 508300dd23SFelipe Balbi 513140e8cbSSebastian Andrzej Siewior void dwc3_set_mode(struct dwc3 *dwc, u32 mode) 523140e8cbSSebastian Andrzej Siewior { 533140e8cbSSebastian Andrzej Siewior u32 reg; 543140e8cbSSebastian Andrzej Siewior 553140e8cbSSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 563140e8cbSSebastian Andrzej Siewior reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); 573140e8cbSSebastian Andrzej Siewior reg |= DWC3_GCTL_PRTCAPDIR(mode); 583140e8cbSSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 593140e8cbSSebastian Andrzej Siewior } 608300dd23SFelipe Balbi 6172246da4SFelipe Balbi /** 6272246da4SFelipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 6372246da4SFelipe Balbi * @dwc: pointer to our context structure 6472246da4SFelipe Balbi */ 6557303488SKishon Vijay Abraham I static int dwc3_core_soft_reset(struct dwc3 *dwc) 6672246da4SFelipe Balbi { 6772246da4SFelipe Balbi u32 reg; 6857303488SKishon Vijay Abraham I int ret; 6972246da4SFelipe Balbi 7072246da4SFelipe Balbi /* Before Resetting PHY, put Core in Reset */ 7172246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 7272246da4SFelipe Balbi reg |= DWC3_GCTL_CORESOFTRESET; 7372246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 7472246da4SFelipe Balbi 7572246da4SFelipe Balbi /* Assert USB3 PHY reset */ 7672246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 7772246da4SFelipe Balbi reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; 7872246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 7972246da4SFelipe Balbi 8072246da4SFelipe Balbi /* Assert USB2 PHY reset */ 8172246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 8272246da4SFelipe Balbi reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; 8372246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 8472246da4SFelipe Balbi 8551e1e7bcSFelipe Balbi usb_phy_init(dwc->usb2_phy); 8651e1e7bcSFelipe Balbi usb_phy_init(dwc->usb3_phy); 8757303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 8857303488SKishon Vijay Abraham I if (ret < 0) 8957303488SKishon Vijay Abraham I return ret; 9057303488SKishon Vijay Abraham I 9157303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 9257303488SKishon Vijay Abraham I if (ret < 0) { 9357303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 9457303488SKishon Vijay Abraham I return ret; 9557303488SKishon Vijay Abraham I } 9672246da4SFelipe Balbi mdelay(100); 9772246da4SFelipe Balbi 9872246da4SFelipe Balbi /* Clear USB3 PHY reset */ 9972246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 10072246da4SFelipe Balbi reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; 10172246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 10272246da4SFelipe Balbi 10372246da4SFelipe Balbi /* Clear USB2 PHY reset */ 10472246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 10572246da4SFelipe Balbi reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; 10672246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 10772246da4SFelipe Balbi 10845627ac6SPratyush Anand mdelay(100); 10945627ac6SPratyush Anand 11072246da4SFelipe Balbi /* After PHYs are stable we can take Core out of reset state */ 11172246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 11272246da4SFelipe Balbi reg &= ~DWC3_GCTL_CORESOFTRESET; 11372246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 11457303488SKishon Vijay Abraham I 11557303488SKishon Vijay Abraham I return 0; 11672246da4SFelipe Balbi } 11772246da4SFelipe Balbi 11872246da4SFelipe Balbi /** 11972246da4SFelipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 12072246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 12172246da4SFelipe Balbi * @evt: Pointer to event buffer to be freed 12272246da4SFelipe Balbi */ 12372246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc, 12472246da4SFelipe Balbi struct dwc3_event_buffer *evt) 12572246da4SFelipe Balbi { 12672246da4SFelipe Balbi dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); 12772246da4SFelipe Balbi } 12872246da4SFelipe Balbi 12972246da4SFelipe Balbi /** 1301d046793SPaul Zimmerman * dwc3_alloc_one_event_buffer - Allocates one event buffer structure 13172246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 13272246da4SFelipe Balbi * @length: size of the event buffer 13372246da4SFelipe Balbi * 1341d046793SPaul Zimmerman * Returns a pointer to the allocated event buffer structure on success 13572246da4SFelipe Balbi * otherwise ERR_PTR(errno). 13672246da4SFelipe Balbi */ 13767d0b500SFelipe Balbi static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, 13867d0b500SFelipe Balbi unsigned length) 13972246da4SFelipe Balbi { 14072246da4SFelipe Balbi struct dwc3_event_buffer *evt; 14172246da4SFelipe Balbi 142380f0d28SFelipe Balbi evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL); 14372246da4SFelipe Balbi if (!evt) 14472246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 14572246da4SFelipe Balbi 14672246da4SFelipe Balbi evt->dwc = dwc; 14772246da4SFelipe Balbi evt->length = length; 14872246da4SFelipe Balbi evt->buf = dma_alloc_coherent(dwc->dev, length, 14972246da4SFelipe Balbi &evt->dma, GFP_KERNEL); 150e32672f0SFelipe Balbi if (!evt->buf) 15172246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 15272246da4SFelipe Balbi 15372246da4SFelipe Balbi return evt; 15472246da4SFelipe Balbi } 15572246da4SFelipe Balbi 15672246da4SFelipe Balbi /** 15772246da4SFelipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 15872246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 15972246da4SFelipe Balbi */ 16072246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc) 16172246da4SFelipe Balbi { 16272246da4SFelipe Balbi struct dwc3_event_buffer *evt; 16372246da4SFelipe Balbi int i; 16472246da4SFelipe Balbi 1659f622b2aSFelipe Balbi for (i = 0; i < dwc->num_event_buffers; i++) { 16672246da4SFelipe Balbi evt = dwc->ev_buffs[i]; 16764b6c8a7SAnton Tikhomirov if (evt) 16872246da4SFelipe Balbi dwc3_free_one_event_buffer(dwc, evt); 16972246da4SFelipe Balbi } 17072246da4SFelipe Balbi } 17172246da4SFelipe Balbi 17272246da4SFelipe Balbi /** 17372246da4SFelipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 1741d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 17572246da4SFelipe Balbi * @length: size of event buffer 17672246da4SFelipe Balbi * 1771d046793SPaul Zimmerman * Returns 0 on success otherwise negative errno. In the error case, dwc 17872246da4SFelipe Balbi * may contain some buffers allocated but not all which were requested. 17972246da4SFelipe Balbi */ 18041ac7b3aSBill Pemberton static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) 18172246da4SFelipe Balbi { 1829f622b2aSFelipe Balbi int num; 18372246da4SFelipe Balbi int i; 18472246da4SFelipe Balbi 1859f622b2aSFelipe Balbi num = DWC3_NUM_INT(dwc->hwparams.hwparams1); 1869f622b2aSFelipe Balbi dwc->num_event_buffers = num; 1879f622b2aSFelipe Balbi 188380f0d28SFelipe Balbi dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num, 189380f0d28SFelipe Balbi GFP_KERNEL); 190734d5a53SJingoo Han if (!dwc->ev_buffs) 191457d3f21SFelipe Balbi return -ENOMEM; 192457d3f21SFelipe Balbi 19372246da4SFelipe Balbi for (i = 0; i < num; i++) { 19472246da4SFelipe Balbi struct dwc3_event_buffer *evt; 19572246da4SFelipe Balbi 19672246da4SFelipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 19772246da4SFelipe Balbi if (IS_ERR(evt)) { 19872246da4SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 19972246da4SFelipe Balbi return PTR_ERR(evt); 20072246da4SFelipe Balbi } 20172246da4SFelipe Balbi dwc->ev_buffs[i] = evt; 20272246da4SFelipe Balbi } 20372246da4SFelipe Balbi 20472246da4SFelipe Balbi return 0; 20572246da4SFelipe Balbi } 20672246da4SFelipe Balbi 20772246da4SFelipe Balbi /** 20872246da4SFelipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 2091d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 21072246da4SFelipe Balbi * 21172246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 21272246da4SFelipe Balbi */ 2137acd85e0SPaul Zimmerman static int dwc3_event_buffers_setup(struct dwc3 *dwc) 21472246da4SFelipe Balbi { 21572246da4SFelipe Balbi struct dwc3_event_buffer *evt; 21672246da4SFelipe Balbi int n; 21772246da4SFelipe Balbi 2189f622b2aSFelipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 21972246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 22072246da4SFelipe Balbi dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n", 22172246da4SFelipe Balbi evt->buf, (unsigned long long) evt->dma, 22272246da4SFelipe Balbi evt->length); 22372246da4SFelipe Balbi 2247acd85e0SPaul Zimmerman evt->lpos = 0; 2257acd85e0SPaul Zimmerman 22672246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 22772246da4SFelipe Balbi lower_32_bits(evt->dma)); 22872246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 22972246da4SFelipe Balbi upper_32_bits(evt->dma)); 23072246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 23168d6a01bSFelipe Balbi DWC3_GEVNTSIZ_SIZE(evt->length)); 23272246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 23372246da4SFelipe Balbi } 23472246da4SFelipe Balbi 23572246da4SFelipe Balbi return 0; 23672246da4SFelipe Balbi } 23772246da4SFelipe Balbi 23872246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 23972246da4SFelipe Balbi { 24072246da4SFelipe Balbi struct dwc3_event_buffer *evt; 24172246da4SFelipe Balbi int n; 24272246da4SFelipe Balbi 2439f622b2aSFelipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 24472246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 2457acd85e0SPaul Zimmerman 2467acd85e0SPaul Zimmerman evt->lpos = 0; 2477acd85e0SPaul Zimmerman 24872246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); 24972246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); 25068d6a01bSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK 25168d6a01bSFelipe Balbi | DWC3_GEVNTSIZ_SIZE(0)); 25272246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 25372246da4SFelipe Balbi } 25472246da4SFelipe Balbi } 25572246da4SFelipe Balbi 2560ffcaf37SFelipe Balbi static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) 2570ffcaf37SFelipe Balbi { 2580ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 2590ffcaf37SFelipe Balbi return 0; 2600ffcaf37SFelipe Balbi 2610ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 2620ffcaf37SFelipe Balbi return 0; 2630ffcaf37SFelipe Balbi 2640ffcaf37SFelipe Balbi dwc->scratchbuf = kmalloc_array(dwc->nr_scratch, 2650ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, GFP_KERNEL); 2660ffcaf37SFelipe Balbi if (!dwc->scratchbuf) 2670ffcaf37SFelipe Balbi return -ENOMEM; 2680ffcaf37SFelipe Balbi 2690ffcaf37SFelipe Balbi return 0; 2700ffcaf37SFelipe Balbi } 2710ffcaf37SFelipe Balbi 2720ffcaf37SFelipe Balbi static int dwc3_setup_scratch_buffers(struct dwc3 *dwc) 2730ffcaf37SFelipe Balbi { 2740ffcaf37SFelipe Balbi dma_addr_t scratch_addr; 2750ffcaf37SFelipe Balbi u32 param; 2760ffcaf37SFelipe Balbi int ret; 2770ffcaf37SFelipe Balbi 2780ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 2790ffcaf37SFelipe Balbi return 0; 2800ffcaf37SFelipe Balbi 2810ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 2820ffcaf37SFelipe Balbi return 0; 2830ffcaf37SFelipe Balbi 2840ffcaf37SFelipe Balbi /* should never fall here */ 2850ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 2860ffcaf37SFelipe Balbi return 0; 2870ffcaf37SFelipe Balbi 2880ffcaf37SFelipe Balbi scratch_addr = dma_map_single(dwc->dev, dwc->scratchbuf, 2890ffcaf37SFelipe Balbi dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, 2900ffcaf37SFelipe Balbi DMA_BIDIRECTIONAL); 2910ffcaf37SFelipe Balbi if (dma_mapping_error(dwc->dev, scratch_addr)) { 2920ffcaf37SFelipe Balbi dev_err(dwc->dev, "failed to map scratch buffer\n"); 2930ffcaf37SFelipe Balbi ret = -EFAULT; 2940ffcaf37SFelipe Balbi goto err0; 2950ffcaf37SFelipe Balbi } 2960ffcaf37SFelipe Balbi 2970ffcaf37SFelipe Balbi dwc->scratch_addr = scratch_addr; 2980ffcaf37SFelipe Balbi 2990ffcaf37SFelipe Balbi param = lower_32_bits(scratch_addr); 3000ffcaf37SFelipe Balbi 3010ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3020ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param); 3030ffcaf37SFelipe Balbi if (ret < 0) 3040ffcaf37SFelipe Balbi goto err1; 3050ffcaf37SFelipe Balbi 3060ffcaf37SFelipe Balbi param = upper_32_bits(scratch_addr); 3070ffcaf37SFelipe Balbi 3080ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3090ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param); 3100ffcaf37SFelipe Balbi if (ret < 0) 3110ffcaf37SFelipe Balbi goto err1; 3120ffcaf37SFelipe Balbi 3130ffcaf37SFelipe Balbi return 0; 3140ffcaf37SFelipe Balbi 3150ffcaf37SFelipe Balbi err1: 3160ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3170ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3180ffcaf37SFelipe Balbi 3190ffcaf37SFelipe Balbi err0: 3200ffcaf37SFelipe Balbi return ret; 3210ffcaf37SFelipe Balbi } 3220ffcaf37SFelipe Balbi 3230ffcaf37SFelipe Balbi static void dwc3_free_scratch_buffers(struct dwc3 *dwc) 3240ffcaf37SFelipe Balbi { 3250ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3260ffcaf37SFelipe Balbi return; 3270ffcaf37SFelipe Balbi 3280ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3290ffcaf37SFelipe Balbi return; 3300ffcaf37SFelipe Balbi 3310ffcaf37SFelipe Balbi /* should never fall here */ 3320ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 3330ffcaf37SFelipe Balbi return; 3340ffcaf37SFelipe Balbi 3350ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3360ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3370ffcaf37SFelipe Balbi kfree(dwc->scratchbuf); 3380ffcaf37SFelipe Balbi } 3390ffcaf37SFelipe Balbi 340789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc) 341789451f6SFelipe Balbi { 342789451f6SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 343789451f6SFelipe Balbi 344789451f6SFelipe Balbi dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); 345789451f6SFelipe Balbi dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; 346789451f6SFelipe Balbi 347789451f6SFelipe Balbi dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n", 348789451f6SFelipe Balbi dwc->num_in_eps, dwc->num_out_eps); 349789451f6SFelipe Balbi } 350789451f6SFelipe Balbi 35141ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc) 35226ceca97SFelipe Balbi { 35326ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 35426ceca97SFelipe Balbi 35526ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 35626ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 35726ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 35826ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 35926ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 36026ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 36126ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 36226ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 36326ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 36426ceca97SFelipe Balbi } 36526ceca97SFelipe Balbi 36672246da4SFelipe Balbi /** 36772246da4SFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 36872246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 36972246da4SFelipe Balbi * 37072246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 37172246da4SFelipe Balbi */ 37241ac7b3aSBill Pemberton static int dwc3_core_init(struct dwc3 *dwc) 37372246da4SFelipe Balbi { 37472246da4SFelipe Balbi unsigned long timeout; 3750ffcaf37SFelipe Balbi u32 hwparams4 = dwc->hwparams.hwparams4; 37672246da4SFelipe Balbi u32 reg; 37772246da4SFelipe Balbi int ret; 37872246da4SFelipe Balbi 3797650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 3807650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 3817650bd74SSebastian Andrzej Siewior if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { 3827650bd74SSebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 3837650bd74SSebastian Andrzej Siewior ret = -ENODEV; 3847650bd74SSebastian Andrzej Siewior goto err0; 3857650bd74SSebastian Andrzej Siewior } 386248b122bSFelipe Balbi dwc->revision = reg; 3877650bd74SSebastian Andrzej Siewior 388fa0ea13eSFelipe Balbi /* 389fa0ea13eSFelipe Balbi * Write Linux Version Code to our GUID register so it's easy to figure 390fa0ea13eSFelipe Balbi * out which kernel version a bug was found. 391fa0ea13eSFelipe Balbi */ 392fa0ea13eSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); 393fa0ea13eSFelipe Balbi 3940e1e5c47SPaul Zimmerman /* Handle USB2.0-only core configuration */ 3950e1e5c47SPaul Zimmerman if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 3960e1e5c47SPaul Zimmerman DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { 3970e1e5c47SPaul Zimmerman if (dwc->maximum_speed == USB_SPEED_SUPER) 3980e1e5c47SPaul Zimmerman dwc->maximum_speed = USB_SPEED_HIGH; 3990e1e5c47SPaul Zimmerman } 4000e1e5c47SPaul Zimmerman 40172246da4SFelipe Balbi /* issue device SoftReset too */ 40272246da4SFelipe Balbi timeout = jiffies + msecs_to_jiffies(500); 40372246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); 40472246da4SFelipe Balbi do { 40572246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 40672246da4SFelipe Balbi if (!(reg & DWC3_DCTL_CSFTRST)) 40772246da4SFelipe Balbi break; 40872246da4SFelipe Balbi 40972246da4SFelipe Balbi if (time_after(jiffies, timeout)) { 41072246da4SFelipe Balbi dev_err(dwc->dev, "Reset Timed Out\n"); 41172246da4SFelipe Balbi ret = -ETIMEDOUT; 41272246da4SFelipe Balbi goto err0; 41372246da4SFelipe Balbi } 41472246da4SFelipe Balbi 41572246da4SFelipe Balbi cpu_relax(); 41672246da4SFelipe Balbi } while (true); 41772246da4SFelipe Balbi 41857303488SKishon Vijay Abraham I ret = dwc3_core_soft_reset(dwc); 41957303488SKishon Vijay Abraham I if (ret) 42057303488SKishon Vijay Abraham I goto err0; 42158a0f23fSPratyush Anand 4224878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 4233e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 4244878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DISSCRAMBLE; 4254878a028SSebastian Andrzej Siewior 426164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 4274878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 42832a4a135SFelipe Balbi /** 42932a4a135SFelipe Balbi * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an 43032a4a135SFelipe Balbi * issue which would cause xHCI compliance tests to fail. 43132a4a135SFelipe Balbi * 43232a4a135SFelipe Balbi * Because of that we cannot enable clock gating on such 43332a4a135SFelipe Balbi * configurations. 43432a4a135SFelipe Balbi * 43532a4a135SFelipe Balbi * Refers to: 43632a4a135SFelipe Balbi * 43732a4a135SFelipe Balbi * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based 43832a4a135SFelipe Balbi * SOF/ITP Mode Used 43932a4a135SFelipe Balbi */ 44032a4a135SFelipe Balbi if ((dwc->dr_mode == USB_DR_MODE_HOST || 44132a4a135SFelipe Balbi dwc->dr_mode == USB_DR_MODE_OTG) && 44232a4a135SFelipe Balbi (dwc->revision >= DWC3_REVISION_210A && 44332a4a135SFelipe Balbi dwc->revision <= DWC3_REVISION_250A)) 44432a4a135SFelipe Balbi reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; 44532a4a135SFelipe Balbi else 4464878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 4474878a028SSebastian Andrzej Siewior break; 4480ffcaf37SFelipe Balbi case DWC3_GHWPARAMS1_EN_PWROPT_HIB: 4490ffcaf37SFelipe Balbi /* enable hibernation here */ 4500ffcaf37SFelipe Balbi dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); 4510ffcaf37SFelipe Balbi break; 4524878a028SSebastian Andrzej Siewior default: 4534878a028SSebastian Andrzej Siewior dev_dbg(dwc->dev, "No power optimization available\n"); 4544878a028SSebastian Andrzej Siewior } 4554878a028SSebastian Andrzej Siewior 4564878a028SSebastian Andrzej Siewior /* 4574878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 4581d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 4594878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 4601d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 4614878a028SSebastian Andrzej Siewior */ 4624878a028SSebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 4634878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 4644878a028SSebastian Andrzej Siewior 465789451f6SFelipe Balbi dwc3_core_num_eps(dwc); 466789451f6SFelipe Balbi 4674878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 4684878a028SSebastian Andrzej Siewior 4690ffcaf37SFelipe Balbi ret = dwc3_alloc_scratch_buffers(dwc); 4700ffcaf37SFelipe Balbi if (ret) 4710ffcaf37SFelipe Balbi goto err1; 4720ffcaf37SFelipe Balbi 4730ffcaf37SFelipe Balbi ret = dwc3_setup_scratch_buffers(dwc); 4740ffcaf37SFelipe Balbi if (ret) 4750ffcaf37SFelipe Balbi goto err2; 4760ffcaf37SFelipe Balbi 47772246da4SFelipe Balbi return 0; 47872246da4SFelipe Balbi 4790ffcaf37SFelipe Balbi err2: 4800ffcaf37SFelipe Balbi dwc3_free_scratch_buffers(dwc); 4810ffcaf37SFelipe Balbi 4820ffcaf37SFelipe Balbi err1: 4830ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 4840ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 48557303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 48657303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 4870ffcaf37SFelipe Balbi 48872246da4SFelipe Balbi err0: 48972246da4SFelipe Balbi return ret; 49072246da4SFelipe Balbi } 49172246da4SFelipe Balbi 49272246da4SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 49372246da4SFelipe Balbi { 4940ffcaf37SFelipe Balbi dwc3_free_scratch_buffers(dwc); 49501b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb2_phy); 49601b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb3_phy); 49757303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 49857303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 49972246da4SFelipe Balbi } 50072246da4SFelipe Balbi 5013c9f94acSFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc) 50272246da4SFelipe Balbi { 5033c9f94acSFelipe Balbi struct device *dev = dwc->dev; 504941ea361SFelipe Balbi struct device_node *node = dev->of_node; 5053c9f94acSFelipe Balbi int ret; 50672246da4SFelipe Balbi 5075088b6f5SKishon Vijay Abraham I if (node) { 5085088b6f5SKishon Vijay Abraham I dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); 5095088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); 510bb674907SFelipe Balbi } else { 511bb674907SFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 512bb674907SFelipe Balbi dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 5135088b6f5SKishon Vijay Abraham I } 5145088b6f5SKishon Vijay Abraham I 515d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb2_phy)) { 516d105e7f8SFelipe Balbi ret = PTR_ERR(dwc->usb2_phy); 517122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 518122f06e6SKishon Vijay Abraham I dwc->usb2_phy = NULL; 519122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 520d105e7f8SFelipe Balbi return ret; 521122f06e6SKishon Vijay Abraham I } else { 52251e1e7bcSFelipe Balbi dev_err(dev, "no usb2 phy configured\n"); 523122f06e6SKishon Vijay Abraham I return ret; 524122f06e6SKishon Vijay Abraham I } 52551e1e7bcSFelipe Balbi } 52651e1e7bcSFelipe Balbi 527d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb3_phy)) { 528315955d7SRuchika Kharwar ret = PTR_ERR(dwc->usb3_phy); 529122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 530122f06e6SKishon Vijay Abraham I dwc->usb3_phy = NULL; 531122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 532d105e7f8SFelipe Balbi return ret; 533122f06e6SKishon Vijay Abraham I } else { 53451e1e7bcSFelipe Balbi dev_err(dev, "no usb3 phy configured\n"); 535122f06e6SKishon Vijay Abraham I return ret; 536122f06e6SKishon Vijay Abraham I } 53751e1e7bcSFelipe Balbi } 53851e1e7bcSFelipe Balbi 53957303488SKishon Vijay Abraham I dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); 54057303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb2_generic_phy)) { 54157303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb2_generic_phy); 54257303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 54357303488SKishon Vijay Abraham I dwc->usb2_generic_phy = NULL; 54457303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 54557303488SKishon Vijay Abraham I return ret; 54657303488SKishon Vijay Abraham I } else { 54757303488SKishon Vijay Abraham I dev_err(dev, "no usb2 phy configured\n"); 54857303488SKishon Vijay Abraham I return ret; 54957303488SKishon Vijay Abraham I } 55057303488SKishon Vijay Abraham I } 55157303488SKishon Vijay Abraham I 55257303488SKishon Vijay Abraham I dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy"); 55357303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb3_generic_phy)) { 55457303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb3_generic_phy); 55557303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 55657303488SKishon Vijay Abraham I dwc->usb3_generic_phy = NULL; 55757303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 55857303488SKishon Vijay Abraham I return ret; 55957303488SKishon Vijay Abraham I } else { 56057303488SKishon Vijay Abraham I dev_err(dev, "no usb3 phy configured\n"); 56157303488SKishon Vijay Abraham I return ret; 56257303488SKishon Vijay Abraham I } 56357303488SKishon Vijay Abraham I } 56457303488SKishon Vijay Abraham I 5653c9f94acSFelipe Balbi return 0; 5663c9f94acSFelipe Balbi } 5673c9f94acSFelipe Balbi 5685f94adfeSFelipe Balbi static int dwc3_core_init_mode(struct dwc3 *dwc) 5695f94adfeSFelipe Balbi { 5705f94adfeSFelipe Balbi struct device *dev = dwc->dev; 5715f94adfeSFelipe Balbi int ret; 5725f94adfeSFelipe Balbi 5735f94adfeSFelipe Balbi switch (dwc->dr_mode) { 5745f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 5755f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); 5765f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 5775f94adfeSFelipe Balbi if (ret) { 5785f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 5795f94adfeSFelipe Balbi return ret; 5805f94adfeSFelipe Balbi } 5815f94adfeSFelipe Balbi break; 5825f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 5835f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); 5845f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 5855f94adfeSFelipe Balbi if (ret) { 5865f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 5875f94adfeSFelipe Balbi return ret; 5885f94adfeSFelipe Balbi } 5895f94adfeSFelipe Balbi break; 5905f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 5915f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); 5925f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 5935f94adfeSFelipe Balbi if (ret) { 5945f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 5955f94adfeSFelipe Balbi return ret; 5965f94adfeSFelipe Balbi } 5975f94adfeSFelipe Balbi 5985f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 5995f94adfeSFelipe Balbi if (ret) { 6005f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 6015f94adfeSFelipe Balbi return ret; 6025f94adfeSFelipe Balbi } 6035f94adfeSFelipe Balbi break; 6045f94adfeSFelipe Balbi default: 6055f94adfeSFelipe Balbi dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); 6065f94adfeSFelipe Balbi return -EINVAL; 6075f94adfeSFelipe Balbi } 6085f94adfeSFelipe Balbi 6095f94adfeSFelipe Balbi return 0; 6105f94adfeSFelipe Balbi } 6115f94adfeSFelipe Balbi 6125f94adfeSFelipe Balbi static void dwc3_core_exit_mode(struct dwc3 *dwc) 6135f94adfeSFelipe Balbi { 6145f94adfeSFelipe Balbi switch (dwc->dr_mode) { 6155f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 6165f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 6175f94adfeSFelipe Balbi break; 6185f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 6195f94adfeSFelipe Balbi dwc3_host_exit(dwc); 6205f94adfeSFelipe Balbi break; 6215f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 6225f94adfeSFelipe Balbi dwc3_host_exit(dwc); 6235f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 6245f94adfeSFelipe Balbi break; 6255f94adfeSFelipe Balbi default: 6265f94adfeSFelipe Balbi /* do nothing */ 6275f94adfeSFelipe Balbi break; 6285f94adfeSFelipe Balbi } 6295f94adfeSFelipe Balbi } 6305f94adfeSFelipe Balbi 6313c9f94acSFelipe Balbi #define DWC3_ALIGN_MASK (16 - 1) 6323c9f94acSFelipe Balbi 6333c9f94acSFelipe Balbi static int dwc3_probe(struct platform_device *pdev) 6343c9f94acSFelipe Balbi { 6353c9f94acSFelipe Balbi struct device *dev = &pdev->dev; 6363c9f94acSFelipe Balbi struct dwc3_platform_data *pdata = dev_get_platdata(dev); 6373c9f94acSFelipe Balbi struct device_node *node = dev->of_node; 6383c9f94acSFelipe Balbi struct resource *res; 6393c9f94acSFelipe Balbi struct dwc3 *dwc; 6403c9f94acSFelipe Balbi 641b09e99eeSAndy Shevchenko int ret; 6423c9f94acSFelipe Balbi 6433c9f94acSFelipe Balbi void __iomem *regs; 6443c9f94acSFelipe Balbi void *mem; 6453c9f94acSFelipe Balbi 6463c9f94acSFelipe Balbi mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 647734d5a53SJingoo Han if (!mem) 6483c9f94acSFelipe Balbi return -ENOMEM; 649734d5a53SJingoo Han 6503c9f94acSFelipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 6513c9f94acSFelipe Balbi dwc->mem = mem; 6523c9f94acSFelipe Balbi dwc->dev = dev; 6533c9f94acSFelipe Balbi 6543c9f94acSFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 6553c9f94acSFelipe Balbi if (!res) { 6563c9f94acSFelipe Balbi dev_err(dev, "missing IRQ\n"); 6573c9f94acSFelipe Balbi return -ENODEV; 6583c9f94acSFelipe Balbi } 6593c9f94acSFelipe Balbi dwc->xhci_resources[1].start = res->start; 6603c9f94acSFelipe Balbi dwc->xhci_resources[1].end = res->end; 6613c9f94acSFelipe Balbi dwc->xhci_resources[1].flags = res->flags; 6623c9f94acSFelipe Balbi dwc->xhci_resources[1].name = res->name; 6633c9f94acSFelipe Balbi 6643c9f94acSFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 6653c9f94acSFelipe Balbi if (!res) { 6663c9f94acSFelipe Balbi dev_err(dev, "missing memory resource\n"); 6673c9f94acSFelipe Balbi return -ENODEV; 6683c9f94acSFelipe Balbi } 6693c9f94acSFelipe Balbi 670f32a5e23SVivek Gautam dwc->xhci_resources[0].start = res->start; 671f32a5e23SVivek Gautam dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 672f32a5e23SVivek Gautam DWC3_XHCI_REGS_END; 673f32a5e23SVivek Gautam dwc->xhci_resources[0].flags = res->flags; 674f32a5e23SVivek Gautam dwc->xhci_resources[0].name = res->name; 675f32a5e23SVivek Gautam 676f32a5e23SVivek Gautam res->start += DWC3_GLOBALS_REGS_START; 677f32a5e23SVivek Gautam 678f32a5e23SVivek Gautam /* 679f32a5e23SVivek Gautam * Request memory region but exclude xHCI regs, 680f32a5e23SVivek Gautam * since it will be requested by the xhci-plat driver. 681f32a5e23SVivek Gautam */ 682f32a5e23SVivek Gautam regs = devm_ioremap_resource(dev, res); 683f32a5e23SVivek Gautam if (IS_ERR(regs)) 684f32a5e23SVivek Gautam return PTR_ERR(regs); 685f32a5e23SVivek Gautam 686f32a5e23SVivek Gautam dwc->regs = regs; 687f32a5e23SVivek Gautam dwc->regs_size = resource_size(res); 688f32a5e23SVivek Gautam /* 689f32a5e23SVivek Gautam * restore res->start back to its original value so that, 690f32a5e23SVivek Gautam * in case the probe is deferred, we don't end up getting error in 691f32a5e23SVivek Gautam * request the memory region the next time probe is called. 692f32a5e23SVivek Gautam */ 693f32a5e23SVivek Gautam res->start -= DWC3_GLOBALS_REGS_START; 694f32a5e23SVivek Gautam 6953c9f94acSFelipe Balbi if (node) { 6963c9f94acSFelipe Balbi dwc->maximum_speed = of_usb_get_maximum_speed(node); 6973c9f94acSFelipe Balbi 6983c9f94acSFelipe Balbi dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize"); 6993c9f94acSFelipe Balbi dwc->dr_mode = of_usb_get_dr_mode(node); 7003c9f94acSFelipe Balbi } else if (pdata) { 7013c9f94acSFelipe Balbi dwc->maximum_speed = pdata->maximum_speed; 7023c9f94acSFelipe Balbi 7033c9f94acSFelipe Balbi dwc->needs_fifo_resize = pdata->tx_fifo_resize; 7043c9f94acSFelipe Balbi dwc->dr_mode = pdata->dr_mode; 7053c9f94acSFelipe Balbi } 7063c9f94acSFelipe Balbi 7073c9f94acSFelipe Balbi /* default to superspeed if no maximum_speed passed */ 7083c9f94acSFelipe Balbi if (dwc->maximum_speed == USB_SPEED_UNKNOWN) 7093c9f94acSFelipe Balbi dwc->maximum_speed = USB_SPEED_SUPER; 7103c9f94acSFelipe Balbi 7113c9f94acSFelipe Balbi ret = dwc3_core_get_phy(dwc); 7123c9f94acSFelipe Balbi if (ret) 7133c9f94acSFelipe Balbi return ret; 7143c9f94acSFelipe Balbi 71572246da4SFelipe Balbi spin_lock_init(&dwc->lock); 71672246da4SFelipe Balbi platform_set_drvdata(pdev, dwc); 71772246da4SFelipe Balbi 718*19bacdc9SHeikki Krogerus if (!dev->dma_mask) { 719ddff14f1SKishon Vijay Abraham I dev->dma_mask = dev->parent->dma_mask; 720ddff14f1SKishon Vijay Abraham I dev->dma_parms = dev->parent->dma_parms; 721ddff14f1SKishon Vijay Abraham I dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); 722*19bacdc9SHeikki Krogerus } 723ddff14f1SKishon Vijay Abraham I 724802ca850SChanho Park pm_runtime_enable(dev); 725802ca850SChanho Park pm_runtime_get_sync(dev); 726802ca850SChanho Park pm_runtime_forbid(dev); 72772246da4SFelipe Balbi 7284fd24483SKishon Vijay Abraham I dwc3_cache_hwparams(dwc); 7294fd24483SKishon Vijay Abraham I 7303921426bSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 7313921426bSFelipe Balbi if (ret) { 7323921426bSFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 7333921426bSFelipe Balbi ret = -ENOMEM; 7343921426bSFelipe Balbi goto err0; 7353921426bSFelipe Balbi } 7363921426bSFelipe Balbi 73732a4a135SFelipe Balbi if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) 73832a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_HOST; 73932a4a135SFelipe Balbi else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) 74032a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_PERIPHERAL; 74132a4a135SFelipe Balbi 74232a4a135SFelipe Balbi if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) 74332a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_OTG; 74432a4a135SFelipe Balbi 74572246da4SFelipe Balbi ret = dwc3_core_init(dwc); 74672246da4SFelipe Balbi if (ret) { 747802ca850SChanho Park dev_err(dev, "failed to initialize core\n"); 7483921426bSFelipe Balbi goto err0; 74972246da4SFelipe Balbi } 75072246da4SFelipe Balbi 7513088f108SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 0); 7523088f108SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 0); 75357303488SKishon Vijay Abraham I ret = phy_power_on(dwc->usb2_generic_phy); 75457303488SKishon Vijay Abraham I if (ret < 0) 75557303488SKishon Vijay Abraham I goto err1; 75657303488SKishon Vijay Abraham I 75757303488SKishon Vijay Abraham I ret = phy_power_on(dwc->usb3_generic_phy); 75857303488SKishon Vijay Abraham I if (ret < 0) 75957303488SKishon Vijay Abraham I goto err_usb2phy_power; 7603088f108SKishon Vijay Abraham I 761f122d33eSFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 762f122d33eSFelipe Balbi if (ret) { 763f122d33eSFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 76457303488SKishon Vijay Abraham I goto err_usb3phy_power; 765f122d33eSFelipe Balbi } 766f122d33eSFelipe Balbi 7675f94adfeSFelipe Balbi ret = dwc3_core_init_mode(dwc); 7685f94adfeSFelipe Balbi if (ret) 769f122d33eSFelipe Balbi goto err2; 77072246da4SFelipe Balbi 77172246da4SFelipe Balbi ret = dwc3_debugfs_init(dwc); 77272246da4SFelipe Balbi if (ret) { 773802ca850SChanho Park dev_err(dev, "failed to initialize debugfs\n"); 774f122d33eSFelipe Balbi goto err3; 77572246da4SFelipe Balbi } 77672246da4SFelipe Balbi 777802ca850SChanho Park pm_runtime_allow(dev); 77872246da4SFelipe Balbi 77972246da4SFelipe Balbi return 0; 78072246da4SFelipe Balbi 781f122d33eSFelipe Balbi err3: 7825f94adfeSFelipe Balbi dwc3_core_exit_mode(dwc); 78372246da4SFelipe Balbi 784f122d33eSFelipe Balbi err2: 785f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 786f122d33eSFelipe Balbi 78757303488SKishon Vijay Abraham I err_usb3phy_power: 78857303488SKishon Vijay Abraham I phy_power_off(dwc->usb3_generic_phy); 78957303488SKishon Vijay Abraham I 79057303488SKishon Vijay Abraham I err_usb2phy_power: 79157303488SKishon Vijay Abraham I phy_power_off(dwc->usb2_generic_phy); 79257303488SKishon Vijay Abraham I 793802ca850SChanho Park err1: 794501fae51SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 1); 795501fae51SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 1); 79672246da4SFelipe Balbi dwc3_core_exit(dwc); 79772246da4SFelipe Balbi 7983921426bSFelipe Balbi err0: 7993921426bSFelipe Balbi dwc3_free_event_buffers(dwc); 8003921426bSFelipe Balbi 80172246da4SFelipe Balbi return ret; 80272246da4SFelipe Balbi } 80372246da4SFelipe Balbi 804fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev) 80572246da4SFelipe Balbi { 80672246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 80772246da4SFelipe Balbi 808dc99f16fSFelipe Balbi dwc3_debugfs_exit(dwc); 809dc99f16fSFelipe Balbi dwc3_core_exit_mode(dwc); 810dc99f16fSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 811dc99f16fSFelipe Balbi dwc3_free_event_buffers(dwc); 812dc99f16fSFelipe Balbi 8138ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 1); 8148ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 1); 81557303488SKishon Vijay Abraham I phy_power_off(dwc->usb2_generic_phy); 81657303488SKishon Vijay Abraham I phy_power_off(dwc->usb3_generic_phy); 8178ba007a9SKishon Vijay Abraham I 81872246da4SFelipe Balbi dwc3_core_exit(dwc); 81972246da4SFelipe Balbi 8207415f17cSFelipe Balbi pm_runtime_put_sync(&pdev->dev); 8217415f17cSFelipe Balbi pm_runtime_disable(&pdev->dev); 8227415f17cSFelipe Balbi 82372246da4SFelipe Balbi return 0; 82472246da4SFelipe Balbi } 82572246da4SFelipe Balbi 8267415f17cSFelipe Balbi #ifdef CONFIG_PM_SLEEP 8277415f17cSFelipe Balbi static int dwc3_prepare(struct device *dev) 8287415f17cSFelipe Balbi { 8297415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 8307415f17cSFelipe Balbi unsigned long flags; 8317415f17cSFelipe Balbi 8327415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 8337415f17cSFelipe Balbi 834a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 835a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 836a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 8377415f17cSFelipe Balbi dwc3_gadget_prepare(dwc); 8387415f17cSFelipe Balbi /* FALLTHROUGH */ 839a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 8407415f17cSFelipe Balbi default: 8417415f17cSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 8427415f17cSFelipe Balbi break; 8437415f17cSFelipe Balbi } 8447415f17cSFelipe Balbi 8457415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 8467415f17cSFelipe Balbi 8477415f17cSFelipe Balbi return 0; 8487415f17cSFelipe Balbi } 8497415f17cSFelipe Balbi 8507415f17cSFelipe Balbi static void dwc3_complete(struct device *dev) 8517415f17cSFelipe Balbi { 8527415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 8537415f17cSFelipe Balbi unsigned long flags; 8547415f17cSFelipe Balbi 8557415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 8567415f17cSFelipe Balbi 857f45e5f00SRoger Quadros dwc3_event_buffers_setup(dwc); 858a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 859a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 860a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 8617415f17cSFelipe Balbi dwc3_gadget_complete(dwc); 8627415f17cSFelipe Balbi /* FALLTHROUGH */ 863a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 8647415f17cSFelipe Balbi default: 8657415f17cSFelipe Balbi break; 8667415f17cSFelipe Balbi } 8677415f17cSFelipe Balbi 8687415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 8697415f17cSFelipe Balbi } 8707415f17cSFelipe Balbi 8717415f17cSFelipe Balbi static int dwc3_suspend(struct device *dev) 8727415f17cSFelipe Balbi { 8737415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 8747415f17cSFelipe Balbi unsigned long flags; 8757415f17cSFelipe Balbi 8767415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 8777415f17cSFelipe Balbi 878a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 879a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 880a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 8817415f17cSFelipe Balbi dwc3_gadget_suspend(dwc); 8827415f17cSFelipe Balbi /* FALLTHROUGH */ 883a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 8847415f17cSFelipe Balbi default: 8857415f17cSFelipe Balbi /* do nothing */ 8867415f17cSFelipe Balbi break; 8877415f17cSFelipe Balbi } 8887415f17cSFelipe Balbi 8897415f17cSFelipe Balbi dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL); 8907415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 8917415f17cSFelipe Balbi 8927415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 8937415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 89457303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 89557303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 8967415f17cSFelipe Balbi 8977415f17cSFelipe Balbi return 0; 8987415f17cSFelipe Balbi } 8997415f17cSFelipe Balbi 9007415f17cSFelipe Balbi static int dwc3_resume(struct device *dev) 9017415f17cSFelipe Balbi { 9027415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 9037415f17cSFelipe Balbi unsigned long flags; 90457303488SKishon Vijay Abraham I int ret; 9057415f17cSFelipe Balbi 9067415f17cSFelipe Balbi usb_phy_init(dwc->usb3_phy); 9077415f17cSFelipe Balbi usb_phy_init(dwc->usb2_phy); 90857303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 90957303488SKishon Vijay Abraham I if (ret < 0) 91057303488SKishon Vijay Abraham I return ret; 91157303488SKishon Vijay Abraham I 91257303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 91357303488SKishon Vijay Abraham I if (ret < 0) 91457303488SKishon Vijay Abraham I goto err_usb2phy_init; 9157415f17cSFelipe Balbi 9167415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 9177415f17cSFelipe Balbi 9187415f17cSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl); 9197415f17cSFelipe Balbi 920a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 921a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 922a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 9237415f17cSFelipe Balbi dwc3_gadget_resume(dwc); 9247415f17cSFelipe Balbi /* FALLTHROUGH */ 925a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 9267415f17cSFelipe Balbi default: 9277415f17cSFelipe Balbi /* do nothing */ 9287415f17cSFelipe Balbi break; 9297415f17cSFelipe Balbi } 9307415f17cSFelipe Balbi 9317415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 9327415f17cSFelipe Balbi 9337415f17cSFelipe Balbi pm_runtime_disable(dev); 9347415f17cSFelipe Balbi pm_runtime_set_active(dev); 9357415f17cSFelipe Balbi pm_runtime_enable(dev); 9367415f17cSFelipe Balbi 9377415f17cSFelipe Balbi return 0; 93857303488SKishon Vijay Abraham I 93957303488SKishon Vijay Abraham I err_usb2phy_init: 94057303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 94157303488SKishon Vijay Abraham I 94257303488SKishon Vijay Abraham I return ret; 9437415f17cSFelipe Balbi } 9447415f17cSFelipe Balbi 9457415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = { 9467415f17cSFelipe Balbi .prepare = dwc3_prepare, 9477415f17cSFelipe Balbi .complete = dwc3_complete, 9487415f17cSFelipe Balbi 9497415f17cSFelipe Balbi SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 9507415f17cSFelipe Balbi }; 9517415f17cSFelipe Balbi 9527415f17cSFelipe Balbi #define DWC3_PM_OPS &(dwc3_dev_pm_ops) 9537415f17cSFelipe Balbi #else 9547415f17cSFelipe Balbi #define DWC3_PM_OPS NULL 9557415f17cSFelipe Balbi #endif 9567415f17cSFelipe Balbi 9575088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF 9585088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = { 9595088b6f5SKishon Vijay Abraham I { 96022a5aa17SFelipe Balbi .compatible = "snps,dwc3" 96122a5aa17SFelipe Balbi }, 96222a5aa17SFelipe Balbi { 9635088b6f5SKishon Vijay Abraham I .compatible = "synopsys,dwc3" 9645088b6f5SKishon Vijay Abraham I }, 9655088b6f5SKishon Vijay Abraham I { }, 9665088b6f5SKishon Vijay Abraham I }; 9675088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match); 9685088b6f5SKishon Vijay Abraham I #endif 9695088b6f5SKishon Vijay Abraham I 97072246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 97172246da4SFelipe Balbi .probe = dwc3_probe, 9727690417dSBill Pemberton .remove = dwc3_remove, 97372246da4SFelipe Balbi .driver = { 97472246da4SFelipe Balbi .name = "dwc3", 9755088b6f5SKishon Vijay Abraham I .of_match_table = of_match_ptr(of_dwc3_match), 9767415f17cSFelipe Balbi .pm = DWC3_PM_OPS, 97772246da4SFelipe Balbi }, 97872246da4SFelipe Balbi }; 97972246da4SFelipe Balbi 980b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 981b1116dccSTobias Klauser 9827ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 98372246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 9845945f789SFelipe Balbi MODULE_LICENSE("GPL v2"); 98572246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 986