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 22a72e658bSFelipe Balbi #include <linux/module.h> 2372246da4SFelipe Balbi #include <linux/kernel.h> 2472246da4SFelipe Balbi #include <linux/slab.h> 2572246da4SFelipe Balbi #include <linux/spinlock.h> 2672246da4SFelipe Balbi #include <linux/platform_device.h> 2772246da4SFelipe Balbi #include <linux/pm_runtime.h> 2872246da4SFelipe Balbi #include <linux/interrupt.h> 2972246da4SFelipe Balbi #include <linux/ioport.h> 3072246da4SFelipe Balbi #include <linux/io.h> 3172246da4SFelipe Balbi #include <linux/list.h> 3272246da4SFelipe Balbi #include <linux/delay.h> 3372246da4SFelipe Balbi #include <linux/dma-mapping.h> 34457e84b6SFelipe Balbi #include <linux/of.h> 3572246da4SFelipe Balbi 3672246da4SFelipe Balbi #include <linux/usb/ch9.h> 3772246da4SFelipe Balbi #include <linux/usb/gadget.h> 38f7e846f0SFelipe Balbi #include <linux/usb/of.h> 39a45c82b8SRuchika Kharwar #include <linux/usb/otg.h> 4072246da4SFelipe Balbi 416462cbd5SFelipe Balbi #include "platform_data.h" 4272246da4SFelipe Balbi #include "core.h" 4372246da4SFelipe Balbi #include "gadget.h" 4472246da4SFelipe Balbi #include "io.h" 4572246da4SFelipe Balbi 4672246da4SFelipe Balbi #include "debug.h" 4772246da4SFelipe Balbi 488300dd23SFelipe Balbi /* -------------------------------------------------------------------------- */ 498300dd23SFelipe Balbi 503140e8cbSSebastian Andrzej Siewior void dwc3_set_mode(struct dwc3 *dwc, u32 mode) 513140e8cbSSebastian Andrzej Siewior { 523140e8cbSSebastian Andrzej Siewior u32 reg; 533140e8cbSSebastian Andrzej Siewior 543140e8cbSSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 553140e8cbSSebastian Andrzej Siewior reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); 563140e8cbSSebastian Andrzej Siewior reg |= DWC3_GCTL_PRTCAPDIR(mode); 573140e8cbSSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 583140e8cbSSebastian Andrzej Siewior } 598300dd23SFelipe Balbi 6072246da4SFelipe Balbi /** 6172246da4SFelipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 6272246da4SFelipe Balbi * @dwc: pointer to our context structure 6372246da4SFelipe Balbi */ 6472246da4SFelipe Balbi static void dwc3_core_soft_reset(struct dwc3 *dwc) 6572246da4SFelipe Balbi { 6672246da4SFelipe Balbi u32 reg; 6772246da4SFelipe Balbi 6872246da4SFelipe Balbi /* Before Resetting PHY, put Core in Reset */ 6972246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 7072246da4SFelipe Balbi reg |= DWC3_GCTL_CORESOFTRESET; 7172246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 7272246da4SFelipe Balbi 7372246da4SFelipe Balbi /* Assert USB3 PHY reset */ 7472246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 7572246da4SFelipe Balbi reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; 7672246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 7772246da4SFelipe Balbi 7872246da4SFelipe Balbi /* Assert USB2 PHY reset */ 7972246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 8072246da4SFelipe Balbi reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; 8172246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 8272246da4SFelipe Balbi 8351e1e7bcSFelipe Balbi usb_phy_init(dwc->usb2_phy); 8451e1e7bcSFelipe Balbi usb_phy_init(dwc->usb3_phy); 8572246da4SFelipe Balbi mdelay(100); 8672246da4SFelipe Balbi 8772246da4SFelipe Balbi /* Clear USB3 PHY reset */ 8872246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 8972246da4SFelipe Balbi reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; 9072246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 9172246da4SFelipe Balbi 9272246da4SFelipe Balbi /* Clear USB2 PHY reset */ 9372246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 9472246da4SFelipe Balbi reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; 9572246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 9672246da4SFelipe Balbi 9745627ac6SPratyush Anand mdelay(100); 9845627ac6SPratyush Anand 9972246da4SFelipe Balbi /* After PHYs are stable we can take Core out of reset state */ 10072246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 10172246da4SFelipe Balbi reg &= ~DWC3_GCTL_CORESOFTRESET; 10272246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 10372246da4SFelipe Balbi } 10472246da4SFelipe Balbi 10572246da4SFelipe Balbi /** 10672246da4SFelipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 10772246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 10872246da4SFelipe Balbi * @evt: Pointer to event buffer to be freed 10972246da4SFelipe Balbi */ 11072246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc, 11172246da4SFelipe Balbi struct dwc3_event_buffer *evt) 11272246da4SFelipe Balbi { 11372246da4SFelipe Balbi dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); 11472246da4SFelipe Balbi } 11572246da4SFelipe Balbi 11672246da4SFelipe Balbi /** 1171d046793SPaul Zimmerman * dwc3_alloc_one_event_buffer - Allocates one event buffer structure 11872246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 11972246da4SFelipe Balbi * @length: size of the event buffer 12072246da4SFelipe Balbi * 1211d046793SPaul Zimmerman * Returns a pointer to the allocated event buffer structure on success 12272246da4SFelipe Balbi * otherwise ERR_PTR(errno). 12372246da4SFelipe Balbi */ 12467d0b500SFelipe Balbi static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, 12567d0b500SFelipe Balbi unsigned length) 12672246da4SFelipe Balbi { 12772246da4SFelipe Balbi struct dwc3_event_buffer *evt; 12872246da4SFelipe Balbi 129380f0d28SFelipe Balbi evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL); 13072246da4SFelipe Balbi if (!evt) 13172246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 13272246da4SFelipe Balbi 13372246da4SFelipe Balbi evt->dwc = dwc; 13472246da4SFelipe Balbi evt->length = length; 13572246da4SFelipe Balbi evt->buf = dma_alloc_coherent(dwc->dev, length, 13672246da4SFelipe Balbi &evt->dma, GFP_KERNEL); 137e32672f0SFelipe Balbi if (!evt->buf) 13872246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 13972246da4SFelipe Balbi 14072246da4SFelipe Balbi return evt; 14172246da4SFelipe Balbi } 14272246da4SFelipe Balbi 14372246da4SFelipe Balbi /** 14472246da4SFelipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 14572246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 14672246da4SFelipe Balbi */ 14772246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc) 14872246da4SFelipe Balbi { 14972246da4SFelipe Balbi struct dwc3_event_buffer *evt; 15072246da4SFelipe Balbi int i; 15172246da4SFelipe Balbi 1529f622b2aSFelipe Balbi for (i = 0; i < dwc->num_event_buffers; i++) { 15372246da4SFelipe Balbi evt = dwc->ev_buffs[i]; 15464b6c8a7SAnton Tikhomirov if (evt) 15572246da4SFelipe Balbi dwc3_free_one_event_buffer(dwc, evt); 15672246da4SFelipe Balbi } 15772246da4SFelipe Balbi } 15872246da4SFelipe Balbi 15972246da4SFelipe Balbi /** 16072246da4SFelipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 1611d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 16272246da4SFelipe Balbi * @length: size of event buffer 16372246da4SFelipe Balbi * 1641d046793SPaul Zimmerman * Returns 0 on success otherwise negative errno. In the error case, dwc 16572246da4SFelipe Balbi * may contain some buffers allocated but not all which were requested. 16672246da4SFelipe Balbi */ 16741ac7b3aSBill Pemberton static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) 16872246da4SFelipe Balbi { 1699f622b2aSFelipe Balbi int num; 17072246da4SFelipe Balbi int i; 17172246da4SFelipe Balbi 1729f622b2aSFelipe Balbi num = DWC3_NUM_INT(dwc->hwparams.hwparams1); 1739f622b2aSFelipe Balbi dwc->num_event_buffers = num; 1749f622b2aSFelipe Balbi 175380f0d28SFelipe Balbi dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num, 176380f0d28SFelipe Balbi GFP_KERNEL); 177457d3f21SFelipe Balbi if (!dwc->ev_buffs) { 178457d3f21SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffers array\n"); 179457d3f21SFelipe Balbi return -ENOMEM; 180457d3f21SFelipe Balbi } 181457d3f21SFelipe Balbi 18272246da4SFelipe Balbi for (i = 0; i < num; i++) { 18372246da4SFelipe Balbi struct dwc3_event_buffer *evt; 18472246da4SFelipe Balbi 18572246da4SFelipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 18672246da4SFelipe Balbi if (IS_ERR(evt)) { 18772246da4SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 18872246da4SFelipe Balbi return PTR_ERR(evt); 18972246da4SFelipe Balbi } 19072246da4SFelipe Balbi dwc->ev_buffs[i] = evt; 19172246da4SFelipe Balbi } 19272246da4SFelipe Balbi 19372246da4SFelipe Balbi return 0; 19472246da4SFelipe Balbi } 19572246da4SFelipe Balbi 19672246da4SFelipe Balbi /** 19772246da4SFelipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 1981d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 19972246da4SFelipe Balbi * 20072246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 20172246da4SFelipe Balbi */ 2027acd85e0SPaul Zimmerman static int dwc3_event_buffers_setup(struct dwc3 *dwc) 20372246da4SFelipe Balbi { 20472246da4SFelipe Balbi struct dwc3_event_buffer *evt; 20572246da4SFelipe Balbi int n; 20672246da4SFelipe Balbi 2079f622b2aSFelipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 20872246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 20972246da4SFelipe Balbi dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n", 21072246da4SFelipe Balbi evt->buf, (unsigned long long) evt->dma, 21172246da4SFelipe Balbi evt->length); 21272246da4SFelipe Balbi 2137acd85e0SPaul Zimmerman evt->lpos = 0; 2147acd85e0SPaul Zimmerman 21572246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 21672246da4SFelipe Balbi lower_32_bits(evt->dma)); 21772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 21872246da4SFelipe Balbi upper_32_bits(evt->dma)); 21972246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 22068d6a01bSFelipe Balbi DWC3_GEVNTSIZ_SIZE(evt->length)); 22172246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 22272246da4SFelipe Balbi } 22372246da4SFelipe Balbi 22472246da4SFelipe Balbi return 0; 22572246da4SFelipe Balbi } 22672246da4SFelipe Balbi 22772246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 22872246da4SFelipe Balbi { 22972246da4SFelipe Balbi struct dwc3_event_buffer *evt; 23072246da4SFelipe Balbi int n; 23172246da4SFelipe Balbi 2329f622b2aSFelipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 23372246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 2347acd85e0SPaul Zimmerman 2357acd85e0SPaul Zimmerman evt->lpos = 0; 2367acd85e0SPaul Zimmerman 23772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); 23872246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); 23968d6a01bSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK 24068d6a01bSFelipe Balbi | DWC3_GEVNTSIZ_SIZE(0)); 24172246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 24272246da4SFelipe Balbi } 24372246da4SFelipe Balbi } 24472246da4SFelipe Balbi 2450ffcaf37SFelipe Balbi static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) 2460ffcaf37SFelipe Balbi { 2470ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 2480ffcaf37SFelipe Balbi return 0; 2490ffcaf37SFelipe Balbi 2500ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 2510ffcaf37SFelipe Balbi return 0; 2520ffcaf37SFelipe Balbi 2530ffcaf37SFelipe Balbi dwc->scratchbuf = kmalloc_array(dwc->nr_scratch, 2540ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, GFP_KERNEL); 2550ffcaf37SFelipe Balbi if (!dwc->scratchbuf) 2560ffcaf37SFelipe Balbi return -ENOMEM; 2570ffcaf37SFelipe Balbi 2580ffcaf37SFelipe Balbi return 0; 2590ffcaf37SFelipe Balbi } 2600ffcaf37SFelipe Balbi 2610ffcaf37SFelipe Balbi static int dwc3_setup_scratch_buffers(struct dwc3 *dwc) 2620ffcaf37SFelipe Balbi { 2630ffcaf37SFelipe Balbi dma_addr_t scratch_addr; 2640ffcaf37SFelipe Balbi u32 param; 2650ffcaf37SFelipe Balbi int ret; 2660ffcaf37SFelipe Balbi 2670ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 2680ffcaf37SFelipe Balbi return 0; 2690ffcaf37SFelipe Balbi 2700ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 2710ffcaf37SFelipe Balbi return 0; 2720ffcaf37SFelipe Balbi 2730ffcaf37SFelipe Balbi /* should never fall here */ 2740ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 2750ffcaf37SFelipe Balbi return 0; 2760ffcaf37SFelipe Balbi 2770ffcaf37SFelipe Balbi scratch_addr = dma_map_single(dwc->dev, dwc->scratchbuf, 2780ffcaf37SFelipe Balbi dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, 2790ffcaf37SFelipe Balbi DMA_BIDIRECTIONAL); 2800ffcaf37SFelipe Balbi if (dma_mapping_error(dwc->dev, scratch_addr)) { 2810ffcaf37SFelipe Balbi dev_err(dwc->dev, "failed to map scratch buffer\n"); 2820ffcaf37SFelipe Balbi ret = -EFAULT; 2830ffcaf37SFelipe Balbi goto err0; 2840ffcaf37SFelipe Balbi } 2850ffcaf37SFelipe Balbi 2860ffcaf37SFelipe Balbi dwc->scratch_addr = scratch_addr; 2870ffcaf37SFelipe Balbi 2880ffcaf37SFelipe Balbi param = lower_32_bits(scratch_addr); 2890ffcaf37SFelipe Balbi 2900ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 2910ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param); 2920ffcaf37SFelipe Balbi if (ret < 0) 2930ffcaf37SFelipe Balbi goto err1; 2940ffcaf37SFelipe Balbi 2950ffcaf37SFelipe Balbi param = upper_32_bits(scratch_addr); 2960ffcaf37SFelipe Balbi 2970ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 2980ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param); 2990ffcaf37SFelipe Balbi if (ret < 0) 3000ffcaf37SFelipe Balbi goto err1; 3010ffcaf37SFelipe Balbi 3020ffcaf37SFelipe Balbi return 0; 3030ffcaf37SFelipe Balbi 3040ffcaf37SFelipe Balbi err1: 3050ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3060ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3070ffcaf37SFelipe Balbi 3080ffcaf37SFelipe Balbi err0: 3090ffcaf37SFelipe Balbi return ret; 3100ffcaf37SFelipe Balbi } 3110ffcaf37SFelipe Balbi 3120ffcaf37SFelipe Balbi static void dwc3_free_scratch_buffers(struct dwc3 *dwc) 3130ffcaf37SFelipe Balbi { 3140ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3150ffcaf37SFelipe Balbi return; 3160ffcaf37SFelipe Balbi 3170ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3180ffcaf37SFelipe Balbi return; 3190ffcaf37SFelipe Balbi 3200ffcaf37SFelipe Balbi /* should never fall here */ 3210ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 3220ffcaf37SFelipe Balbi return; 3230ffcaf37SFelipe Balbi 3240ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3250ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3260ffcaf37SFelipe Balbi kfree(dwc->scratchbuf); 3270ffcaf37SFelipe Balbi } 3280ffcaf37SFelipe Balbi 329789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc) 330789451f6SFelipe Balbi { 331789451f6SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 332789451f6SFelipe Balbi 333789451f6SFelipe Balbi dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); 334789451f6SFelipe Balbi dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; 335789451f6SFelipe Balbi 336789451f6SFelipe Balbi dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n", 337789451f6SFelipe Balbi dwc->num_in_eps, dwc->num_out_eps); 338789451f6SFelipe Balbi } 339789451f6SFelipe Balbi 34041ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc) 34126ceca97SFelipe Balbi { 34226ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 34326ceca97SFelipe Balbi 34426ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 34526ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 34626ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 34726ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 34826ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 34926ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 35026ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 35126ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 35226ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 35326ceca97SFelipe Balbi } 35426ceca97SFelipe Balbi 35572246da4SFelipe Balbi /** 35672246da4SFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 35772246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 35872246da4SFelipe Balbi * 35972246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 36072246da4SFelipe Balbi */ 36141ac7b3aSBill Pemberton static int dwc3_core_init(struct dwc3 *dwc) 36272246da4SFelipe Balbi { 36372246da4SFelipe Balbi unsigned long timeout; 3640ffcaf37SFelipe Balbi u32 hwparams4 = dwc->hwparams.hwparams4; 36572246da4SFelipe Balbi u32 reg; 36672246da4SFelipe Balbi int ret; 36772246da4SFelipe Balbi 3687650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 3697650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 3707650bd74SSebastian Andrzej Siewior if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { 3717650bd74SSebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 3727650bd74SSebastian Andrzej Siewior ret = -ENODEV; 3737650bd74SSebastian Andrzej Siewior goto err0; 3747650bd74SSebastian Andrzej Siewior } 375248b122bSFelipe Balbi dwc->revision = reg; 3767650bd74SSebastian Andrzej Siewior 37772246da4SFelipe Balbi /* issue device SoftReset too */ 37872246da4SFelipe Balbi timeout = jiffies + msecs_to_jiffies(500); 37972246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); 38072246da4SFelipe Balbi do { 38172246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 38272246da4SFelipe Balbi if (!(reg & DWC3_DCTL_CSFTRST)) 38372246da4SFelipe Balbi break; 38472246da4SFelipe Balbi 38572246da4SFelipe Balbi if (time_after(jiffies, timeout)) { 38672246da4SFelipe Balbi dev_err(dwc->dev, "Reset Timed Out\n"); 38772246da4SFelipe Balbi ret = -ETIMEDOUT; 38872246da4SFelipe Balbi goto err0; 38972246da4SFelipe Balbi } 39072246da4SFelipe Balbi 39172246da4SFelipe Balbi cpu_relax(); 39272246da4SFelipe Balbi } while (true); 39372246da4SFelipe Balbi 39458a0f23fSPratyush Anand dwc3_core_soft_reset(dwc); 39558a0f23fSPratyush Anand 3964878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 3973e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 3984878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DISSCRAMBLE; 3994878a028SSebastian Andrzej Siewior 400164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 4014878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 40232a4a135SFelipe Balbi /** 40332a4a135SFelipe Balbi * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an 40432a4a135SFelipe Balbi * issue which would cause xHCI compliance tests to fail. 40532a4a135SFelipe Balbi * 40632a4a135SFelipe Balbi * Because of that we cannot enable clock gating on such 40732a4a135SFelipe Balbi * configurations. 40832a4a135SFelipe Balbi * 40932a4a135SFelipe Balbi * Refers to: 41032a4a135SFelipe Balbi * 41132a4a135SFelipe Balbi * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based 41232a4a135SFelipe Balbi * SOF/ITP Mode Used 41332a4a135SFelipe Balbi */ 41432a4a135SFelipe Balbi if ((dwc->dr_mode == USB_DR_MODE_HOST || 41532a4a135SFelipe Balbi dwc->dr_mode == USB_DR_MODE_OTG) && 41632a4a135SFelipe Balbi (dwc->revision >= DWC3_REVISION_210A && 41732a4a135SFelipe Balbi dwc->revision <= DWC3_REVISION_250A)) 41832a4a135SFelipe Balbi reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; 41932a4a135SFelipe Balbi else 4204878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 4214878a028SSebastian Andrzej Siewior break; 4220ffcaf37SFelipe Balbi case DWC3_GHWPARAMS1_EN_PWROPT_HIB: 4230ffcaf37SFelipe Balbi /* enable hibernation here */ 4240ffcaf37SFelipe Balbi dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); 4250ffcaf37SFelipe Balbi break; 4264878a028SSebastian Andrzej Siewior default: 4274878a028SSebastian Andrzej Siewior dev_dbg(dwc->dev, "No power optimization available\n"); 4284878a028SSebastian Andrzej Siewior } 4294878a028SSebastian Andrzej Siewior 4304878a028SSebastian Andrzej Siewior /* 4314878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 4321d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 4334878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 4341d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 4354878a028SSebastian Andrzej Siewior */ 4364878a028SSebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 4374878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 4384878a028SSebastian Andrzej Siewior 439789451f6SFelipe Balbi dwc3_core_num_eps(dwc); 440789451f6SFelipe Balbi 4414878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 4424878a028SSebastian Andrzej Siewior 4430ffcaf37SFelipe Balbi ret = dwc3_alloc_scratch_buffers(dwc); 4440ffcaf37SFelipe Balbi if (ret) 4450ffcaf37SFelipe Balbi goto err1; 4460ffcaf37SFelipe Balbi 4470ffcaf37SFelipe Balbi ret = dwc3_setup_scratch_buffers(dwc); 4480ffcaf37SFelipe Balbi if (ret) 4490ffcaf37SFelipe Balbi goto err2; 4500ffcaf37SFelipe Balbi 45172246da4SFelipe Balbi return 0; 45272246da4SFelipe Balbi 4530ffcaf37SFelipe Balbi err2: 4540ffcaf37SFelipe Balbi dwc3_free_scratch_buffers(dwc); 4550ffcaf37SFelipe Balbi 4560ffcaf37SFelipe Balbi err1: 4570ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 4580ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 4590ffcaf37SFelipe Balbi 46072246da4SFelipe Balbi err0: 46172246da4SFelipe Balbi return ret; 46272246da4SFelipe Balbi } 46372246da4SFelipe Balbi 46472246da4SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 46572246da4SFelipe Balbi { 4660ffcaf37SFelipe Balbi dwc3_free_scratch_buffers(dwc); 46701b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb2_phy); 46801b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb3_phy); 46972246da4SFelipe Balbi } 47072246da4SFelipe Balbi 47172246da4SFelipe Balbi #define DWC3_ALIGN_MASK (16 - 1) 47272246da4SFelipe Balbi 47341ac7b3aSBill Pemberton static int dwc3_probe(struct platform_device *pdev) 47472246da4SFelipe Balbi { 475941ea361SFelipe Balbi struct device *dev = &pdev->dev; 476941ea361SFelipe Balbi struct dwc3_platform_data *pdata = dev_get_platdata(dev); 477941ea361SFelipe Balbi struct device_node *node = dev->of_node; 47872246da4SFelipe Balbi struct resource *res; 47972246da4SFelipe Balbi struct dwc3 *dwc; 4800949e99bSFelipe Balbi 48172246da4SFelipe Balbi int ret = -ENOMEM; 4820949e99bSFelipe Balbi 4830949e99bSFelipe Balbi void __iomem *regs; 48472246da4SFelipe Balbi void *mem; 48572246da4SFelipe Balbi 486802ca850SChanho Park mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 48772246da4SFelipe Balbi if (!mem) { 488802ca850SChanho Park dev_err(dev, "not enough memory\n"); 489802ca850SChanho Park return -ENOMEM; 49072246da4SFelipe Balbi } 49172246da4SFelipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 49272246da4SFelipe Balbi dwc->mem = mem; 49372246da4SFelipe Balbi 49451249dcaSIdo Shayevitz res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 49572246da4SFelipe Balbi if (!res) { 49651249dcaSIdo Shayevitz dev_err(dev, "missing IRQ\n"); 497802ca850SChanho Park return -ENODEV; 49872246da4SFelipe Balbi } 499066618bcSKishon Vijay Abraham I dwc->xhci_resources[1].start = res->start; 500066618bcSKishon Vijay Abraham I dwc->xhci_resources[1].end = res->end; 501066618bcSKishon Vijay Abraham I dwc->xhci_resources[1].flags = res->flags; 502066618bcSKishon Vijay Abraham I dwc->xhci_resources[1].name = res->name; 50372246da4SFelipe Balbi 50451249dcaSIdo Shayevitz res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 50551249dcaSIdo Shayevitz if (!res) { 50651249dcaSIdo Shayevitz dev_err(dev, "missing memory resource\n"); 50751249dcaSIdo Shayevitz return -ENODEV; 50851249dcaSIdo Shayevitz } 50972246da4SFelipe Balbi 5105088b6f5SKishon Vijay Abraham I if (node) { 511f7e846f0SFelipe Balbi dwc->maximum_speed = of_usb_get_maximum_speed(node); 512f7e846f0SFelipe Balbi 5135088b6f5SKishon Vijay Abraham I dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); 5145088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); 5156462cbd5SFelipe Balbi 5166462cbd5SFelipe Balbi dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize"); 517a45c82b8SRuchika Kharwar dwc->dr_mode = of_usb_get_dr_mode(node); 518bb674907SFelipe Balbi } else if (pdata) { 519f7e846f0SFelipe Balbi dwc->maximum_speed = pdata->maximum_speed; 520f7e846f0SFelipe Balbi 52151e1e7bcSFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 5225088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 5236462cbd5SFelipe Balbi 5246462cbd5SFelipe Balbi dwc->needs_fifo_resize = pdata->tx_fifo_resize; 525a45c82b8SRuchika Kharwar dwc->dr_mode = pdata->dr_mode; 526bb674907SFelipe Balbi } else { 527bb674907SFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 528bb674907SFelipe Balbi dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 5295088b6f5SKishon Vijay Abraham I } 5305088b6f5SKishon Vijay Abraham I 531f7e846f0SFelipe Balbi /* default to superspeed if no maximum_speed passed */ 532f7e846f0SFelipe Balbi if (dwc->maximum_speed == USB_SPEED_UNKNOWN) 533f7e846f0SFelipe Balbi dwc->maximum_speed = USB_SPEED_SUPER; 534f7e846f0SFelipe Balbi 535d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb2_phy)) { 536d105e7f8SFelipe Balbi ret = PTR_ERR(dwc->usb2_phy); 537d105e7f8SFelipe Balbi 538d105e7f8SFelipe Balbi /* 539d105e7f8SFelipe Balbi * if -ENXIO is returned, it means PHY layer wasn't 540d105e7f8SFelipe Balbi * enabled, so it makes no sense to return -EPROBE_DEFER 541d105e7f8SFelipe Balbi * in that case, since no PHY driver will ever probe. 542d105e7f8SFelipe Balbi */ 543d105e7f8SFelipe Balbi if (ret == -ENXIO) 544d105e7f8SFelipe Balbi return ret; 545d105e7f8SFelipe Balbi 54651e1e7bcSFelipe Balbi dev_err(dev, "no usb2 phy configured\n"); 54751e1e7bcSFelipe Balbi return -EPROBE_DEFER; 54851e1e7bcSFelipe Balbi } 54951e1e7bcSFelipe Balbi 550d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb3_phy)) { 551315955d7SRuchika Kharwar ret = PTR_ERR(dwc->usb3_phy); 552d105e7f8SFelipe Balbi 553d105e7f8SFelipe Balbi /* 554d105e7f8SFelipe Balbi * if -ENXIO is returned, it means PHY layer wasn't 555d105e7f8SFelipe Balbi * enabled, so it makes no sense to return -EPROBE_DEFER 556d105e7f8SFelipe Balbi * in that case, since no PHY driver will ever probe. 557d105e7f8SFelipe Balbi */ 558d105e7f8SFelipe Balbi if (ret == -ENXIO) 559d105e7f8SFelipe Balbi return ret; 560d105e7f8SFelipe Balbi 56151e1e7bcSFelipe Balbi dev_err(dev, "no usb3 phy configured\n"); 56251e1e7bcSFelipe Balbi return -EPROBE_DEFER; 56351e1e7bcSFelipe Balbi } 56451e1e7bcSFelipe Balbi 5652e112345SIvan T. Ivanov dwc->xhci_resources[0].start = res->start; 5662e112345SIvan T. Ivanov dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 5672e112345SIvan T. Ivanov DWC3_XHCI_REGS_END; 5682e112345SIvan T. Ivanov dwc->xhci_resources[0].flags = res->flags; 5692e112345SIvan T. Ivanov dwc->xhci_resources[0].name = res->name; 5702e112345SIvan T. Ivanov 5712e112345SIvan T. Ivanov res->start += DWC3_GLOBALS_REGS_START; 5722e112345SIvan T. Ivanov 5732e112345SIvan T. Ivanov /* 5742e112345SIvan T. Ivanov * Request memory region but exclude xHCI regs, 5752e112345SIvan T. Ivanov * since it will be requested by the xhci-plat driver. 5762e112345SIvan T. Ivanov */ 5772e112345SIvan T. Ivanov regs = devm_ioremap_resource(dev, res); 5782e112345SIvan T. Ivanov if (IS_ERR(regs)) 5792e112345SIvan T. Ivanov return PTR_ERR(regs); 5802e112345SIvan T. Ivanov 58172246da4SFelipe Balbi spin_lock_init(&dwc->lock); 58272246da4SFelipe Balbi platform_set_drvdata(pdev, dwc); 58372246da4SFelipe Balbi 58472246da4SFelipe Balbi dwc->regs = regs; 58572246da4SFelipe Balbi dwc->regs_size = resource_size(res); 586802ca850SChanho Park dwc->dev = dev; 58772246da4SFelipe Balbi 588ddff14f1SKishon Vijay Abraham I dev->dma_mask = dev->parent->dma_mask; 589ddff14f1SKishon Vijay Abraham I dev->dma_parms = dev->parent->dma_parms; 590ddff14f1SKishon Vijay Abraham I dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); 591ddff14f1SKishon Vijay Abraham I 592802ca850SChanho Park pm_runtime_enable(dev); 593802ca850SChanho Park pm_runtime_get_sync(dev); 594802ca850SChanho Park pm_runtime_forbid(dev); 59572246da4SFelipe Balbi 5964fd24483SKishon Vijay Abraham I dwc3_cache_hwparams(dwc); 5974fd24483SKishon Vijay Abraham I 5983921426bSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 5993921426bSFelipe Balbi if (ret) { 6003921426bSFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 6013921426bSFelipe Balbi ret = -ENOMEM; 6023921426bSFelipe Balbi goto err0; 6033921426bSFelipe Balbi } 6043921426bSFelipe Balbi 60532a4a135SFelipe Balbi if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) 60632a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_HOST; 60732a4a135SFelipe Balbi else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) 60832a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_PERIPHERAL; 60932a4a135SFelipe Balbi 61032a4a135SFelipe Balbi if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) 61132a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_OTG; 61232a4a135SFelipe Balbi 61372246da4SFelipe Balbi ret = dwc3_core_init(dwc); 61472246da4SFelipe Balbi if (ret) { 615802ca850SChanho Park dev_err(dev, "failed to initialize core\n"); 6163921426bSFelipe Balbi goto err0; 61772246da4SFelipe Balbi } 61872246da4SFelipe Balbi 6193088f108SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 0); 6203088f108SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 0); 6213088f108SKishon Vijay Abraham I 622f122d33eSFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 623f122d33eSFelipe Balbi if (ret) { 624f122d33eSFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 625f122d33eSFelipe Balbi goto err1; 626f122d33eSFelipe Balbi } 627f122d33eSFelipe Balbi 628a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 629a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 6303140e8cbSSebastian Andrzej Siewior dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); 63172246da4SFelipe Balbi ret = dwc3_gadget_init(dwc); 63272246da4SFelipe Balbi if (ret) { 633802ca850SChanho Park dev_err(dev, "failed to initialize gadget\n"); 634f122d33eSFelipe Balbi goto err2; 63572246da4SFelipe Balbi } 6360949e99bSFelipe Balbi break; 637a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 6383140e8cbSSebastian Andrzej Siewior dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); 639d07e8819SFelipe Balbi ret = dwc3_host_init(dwc); 640d07e8819SFelipe Balbi if (ret) { 641802ca850SChanho Park dev_err(dev, "failed to initialize host\n"); 642f122d33eSFelipe Balbi goto err2; 64372246da4SFelipe Balbi } 644d07e8819SFelipe Balbi break; 645a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 6463140e8cbSSebastian Andrzej Siewior dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); 647d07e8819SFelipe Balbi ret = dwc3_host_init(dwc); 648d07e8819SFelipe Balbi if (ret) { 649802ca850SChanho Park dev_err(dev, "failed to initialize host\n"); 650f122d33eSFelipe Balbi goto err2; 651d07e8819SFelipe Balbi } 652d07e8819SFelipe Balbi 653d07e8819SFelipe Balbi ret = dwc3_gadget_init(dwc); 654d07e8819SFelipe Balbi if (ret) { 655802ca850SChanho Park dev_err(dev, "failed to initialize gadget\n"); 656f122d33eSFelipe Balbi goto err2; 657d07e8819SFelipe Balbi } 658d07e8819SFelipe Balbi break; 6590949e99bSFelipe Balbi default: 660a45c82b8SRuchika Kharwar dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); 661f122d33eSFelipe Balbi goto err2; 66272246da4SFelipe Balbi } 66372246da4SFelipe Balbi 66472246da4SFelipe Balbi ret = dwc3_debugfs_init(dwc); 66572246da4SFelipe Balbi if (ret) { 666802ca850SChanho Park dev_err(dev, "failed to initialize debugfs\n"); 667f122d33eSFelipe Balbi goto err3; 66872246da4SFelipe Balbi } 66972246da4SFelipe Balbi 670802ca850SChanho Park pm_runtime_allow(dev); 67172246da4SFelipe Balbi 67272246da4SFelipe Balbi return 0; 67372246da4SFelipe Balbi 674f122d33eSFelipe Balbi err3: 675a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 676a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 67772246da4SFelipe Balbi dwc3_gadget_exit(dwc); 6780949e99bSFelipe Balbi break; 679a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 680d07e8819SFelipe Balbi dwc3_host_exit(dwc); 681d07e8819SFelipe Balbi break; 682a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 683d07e8819SFelipe Balbi dwc3_host_exit(dwc); 684d07e8819SFelipe Balbi dwc3_gadget_exit(dwc); 685d07e8819SFelipe Balbi break; 6860949e99bSFelipe Balbi default: 6870949e99bSFelipe Balbi /* do nothing */ 6880949e99bSFelipe Balbi break; 6890949e99bSFelipe Balbi } 69072246da4SFelipe Balbi 691f122d33eSFelipe Balbi err2: 692f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 693f122d33eSFelipe Balbi 694802ca850SChanho Park err1: 695501fae51SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 1); 696501fae51SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 1); 69772246da4SFelipe Balbi dwc3_core_exit(dwc); 69872246da4SFelipe Balbi 6993921426bSFelipe Balbi err0: 7003921426bSFelipe Balbi dwc3_free_event_buffers(dwc); 7013921426bSFelipe Balbi 70272246da4SFelipe Balbi return ret; 70372246da4SFelipe Balbi } 70472246da4SFelipe Balbi 705fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev) 70672246da4SFelipe Balbi { 70772246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 70872246da4SFelipe Balbi 7098ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 1); 7108ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 1); 7118ba007a9SKishon Vijay Abraham I 71216b972a5SFelipe Balbi pm_runtime_put_sync(&pdev->dev); 71372246da4SFelipe Balbi pm_runtime_disable(&pdev->dev); 71472246da4SFelipe Balbi 71572246da4SFelipe Balbi dwc3_debugfs_exit(dwc); 71672246da4SFelipe Balbi 717a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 718a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 71972246da4SFelipe Balbi dwc3_gadget_exit(dwc); 7200949e99bSFelipe Balbi break; 721a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 722d07e8819SFelipe Balbi dwc3_host_exit(dwc); 723d07e8819SFelipe Balbi break; 724a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 725d07e8819SFelipe Balbi dwc3_host_exit(dwc); 726d07e8819SFelipe Balbi dwc3_gadget_exit(dwc); 727d07e8819SFelipe Balbi break; 7280949e99bSFelipe Balbi default: 7290949e99bSFelipe Balbi /* do nothing */ 7300949e99bSFelipe Balbi break; 7310949e99bSFelipe Balbi } 73272246da4SFelipe Balbi 733f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 734d9b4330aSFelipe Balbi dwc3_free_event_buffers(dwc); 73572246da4SFelipe Balbi dwc3_core_exit(dwc); 73672246da4SFelipe Balbi 73772246da4SFelipe Balbi return 0; 73872246da4SFelipe Balbi } 73972246da4SFelipe Balbi 74019fda7cdSJingoo Han #ifdef CONFIG_PM_SLEEP 7417415f17cSFelipe Balbi static int dwc3_prepare(struct device *dev) 7427415f17cSFelipe Balbi { 7437415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 7447415f17cSFelipe Balbi unsigned long flags; 7457415f17cSFelipe Balbi 7467415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 7477415f17cSFelipe Balbi 748a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 749a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 750a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 7517415f17cSFelipe Balbi dwc3_gadget_prepare(dwc); 7527415f17cSFelipe Balbi /* FALLTHROUGH */ 753a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 7547415f17cSFelipe Balbi default: 7557415f17cSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 7567415f17cSFelipe Balbi break; 7577415f17cSFelipe Balbi } 7587415f17cSFelipe Balbi 7597415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 7607415f17cSFelipe Balbi 7617415f17cSFelipe Balbi return 0; 7627415f17cSFelipe Balbi } 7637415f17cSFelipe Balbi 7647415f17cSFelipe Balbi static void dwc3_complete(struct device *dev) 7657415f17cSFelipe Balbi { 7667415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 7677415f17cSFelipe Balbi unsigned long flags; 7687415f17cSFelipe Balbi 7697415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 7707415f17cSFelipe Balbi 771a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 772a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 773a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 7747415f17cSFelipe Balbi dwc3_gadget_complete(dwc); 7757415f17cSFelipe Balbi /* FALLTHROUGH */ 776a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 7777415f17cSFelipe Balbi default: 7787415f17cSFelipe Balbi dwc3_event_buffers_setup(dwc); 7797415f17cSFelipe Balbi break; 7807415f17cSFelipe Balbi } 7817415f17cSFelipe Balbi 7827415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 7837415f17cSFelipe Balbi } 7847415f17cSFelipe Balbi 7857415f17cSFelipe Balbi static int dwc3_suspend(struct device *dev) 7867415f17cSFelipe Balbi { 7877415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 7887415f17cSFelipe Balbi unsigned long flags; 7897415f17cSFelipe Balbi 7907415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 7917415f17cSFelipe Balbi 792a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 793a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 794a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 7957415f17cSFelipe Balbi dwc3_gadget_suspend(dwc); 7967415f17cSFelipe Balbi /* FALLTHROUGH */ 797a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 7987415f17cSFelipe Balbi default: 7997415f17cSFelipe Balbi /* do nothing */ 8007415f17cSFelipe Balbi break; 8017415f17cSFelipe Balbi } 8027415f17cSFelipe Balbi 8037415f17cSFelipe Balbi dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL); 8047415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 8057415f17cSFelipe Balbi 8067415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 8077415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 8087415f17cSFelipe Balbi 8097415f17cSFelipe Balbi return 0; 8107415f17cSFelipe Balbi } 8117415f17cSFelipe Balbi 8127415f17cSFelipe Balbi static int dwc3_resume(struct device *dev) 8137415f17cSFelipe Balbi { 8147415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 8157415f17cSFelipe Balbi unsigned long flags; 8167415f17cSFelipe Balbi 8177415f17cSFelipe Balbi usb_phy_init(dwc->usb3_phy); 8187415f17cSFelipe Balbi usb_phy_init(dwc->usb2_phy); 8197415f17cSFelipe Balbi 8207415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 8217415f17cSFelipe Balbi 8227415f17cSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl); 8237415f17cSFelipe Balbi 824a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 825a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 826a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 8277415f17cSFelipe Balbi dwc3_gadget_resume(dwc); 8287415f17cSFelipe Balbi /* FALLTHROUGH */ 829a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 8307415f17cSFelipe Balbi default: 8317415f17cSFelipe Balbi /* do nothing */ 8327415f17cSFelipe Balbi break; 8337415f17cSFelipe Balbi } 8347415f17cSFelipe Balbi 8357415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 8367415f17cSFelipe Balbi 8377415f17cSFelipe Balbi pm_runtime_disable(dev); 8387415f17cSFelipe Balbi pm_runtime_set_active(dev); 8397415f17cSFelipe Balbi pm_runtime_enable(dev); 8407415f17cSFelipe Balbi 8417415f17cSFelipe Balbi return 0; 8427415f17cSFelipe Balbi } 8437415f17cSFelipe Balbi 8447415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = { 8457415f17cSFelipe Balbi .prepare = dwc3_prepare, 8467415f17cSFelipe Balbi .complete = dwc3_complete, 8477415f17cSFelipe Balbi 8487415f17cSFelipe Balbi SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 8497415f17cSFelipe Balbi }; 8507415f17cSFelipe Balbi 8517415f17cSFelipe Balbi #define DWC3_PM_OPS &(dwc3_dev_pm_ops) 8527415f17cSFelipe Balbi #else 8537415f17cSFelipe Balbi #define DWC3_PM_OPS NULL 8547415f17cSFelipe Balbi #endif 8557415f17cSFelipe Balbi 8565088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF 8575088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = { 8585088b6f5SKishon Vijay Abraham I { 85922a5aa17SFelipe Balbi .compatible = "snps,dwc3" 86022a5aa17SFelipe Balbi }, 86122a5aa17SFelipe Balbi { 8625088b6f5SKishon Vijay Abraham I .compatible = "synopsys,dwc3" 8635088b6f5SKishon Vijay Abraham I }, 8645088b6f5SKishon Vijay Abraham I { }, 8655088b6f5SKishon Vijay Abraham I }; 8665088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match); 8675088b6f5SKishon Vijay Abraham I #endif 8685088b6f5SKishon Vijay Abraham I 86972246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 87072246da4SFelipe Balbi .probe = dwc3_probe, 8717690417dSBill Pemberton .remove = dwc3_remove, 87272246da4SFelipe Balbi .driver = { 87372246da4SFelipe Balbi .name = "dwc3", 8745088b6f5SKishon Vijay Abraham I .of_match_table = of_match_ptr(of_dwc3_match), 8757415f17cSFelipe Balbi .pm = DWC3_PM_OPS, 87672246da4SFelipe Balbi }, 87772246da4SFelipe Balbi }; 87872246da4SFelipe Balbi 879b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 880b1116dccSTobias Klauser 8817ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 88272246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 8835945f789SFelipe Balbi MODULE_LICENSE("GPL v2"); 88472246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 885