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 245789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc) 246789451f6SFelipe Balbi { 247789451f6SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 248789451f6SFelipe Balbi 249789451f6SFelipe Balbi dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); 250789451f6SFelipe Balbi dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; 251789451f6SFelipe Balbi 252789451f6SFelipe Balbi dev_vdbg(dwc->dev, "found %d IN and %d OUT endpoints\n", 253789451f6SFelipe Balbi dwc->num_in_eps, dwc->num_out_eps); 254789451f6SFelipe Balbi } 255789451f6SFelipe Balbi 25641ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc) 25726ceca97SFelipe Balbi { 25826ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 25926ceca97SFelipe Balbi 26026ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 26126ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 26226ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 26326ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 26426ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 26526ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 26626ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 26726ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 26826ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 26926ceca97SFelipe Balbi } 27026ceca97SFelipe Balbi 27172246da4SFelipe Balbi /** 27272246da4SFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 27372246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 27472246da4SFelipe Balbi * 27572246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 27672246da4SFelipe Balbi */ 27741ac7b3aSBill Pemberton static int dwc3_core_init(struct dwc3 *dwc) 27872246da4SFelipe Balbi { 27972246da4SFelipe Balbi unsigned long timeout; 28072246da4SFelipe Balbi u32 reg; 28172246da4SFelipe Balbi int ret; 28272246da4SFelipe Balbi 2837650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 2847650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 2857650bd74SSebastian Andrzej Siewior if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { 2867650bd74SSebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 2877650bd74SSebastian Andrzej Siewior ret = -ENODEV; 2887650bd74SSebastian Andrzej Siewior goto err0; 2897650bd74SSebastian Andrzej Siewior } 290248b122bSFelipe Balbi dwc->revision = reg; 2917650bd74SSebastian Andrzej Siewior 29272246da4SFelipe Balbi /* issue device SoftReset too */ 29372246da4SFelipe Balbi timeout = jiffies + msecs_to_jiffies(500); 29472246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); 29572246da4SFelipe Balbi do { 29672246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_DCTL); 29772246da4SFelipe Balbi if (!(reg & DWC3_DCTL_CSFTRST)) 29872246da4SFelipe Balbi break; 29972246da4SFelipe Balbi 30072246da4SFelipe Balbi if (time_after(jiffies, timeout)) { 30172246da4SFelipe Balbi dev_err(dwc->dev, "Reset Timed Out\n"); 30272246da4SFelipe Balbi ret = -ETIMEDOUT; 30372246da4SFelipe Balbi goto err0; 30472246da4SFelipe Balbi } 30572246da4SFelipe Balbi 30672246da4SFelipe Balbi cpu_relax(); 30772246da4SFelipe Balbi } while (true); 30872246da4SFelipe Balbi 30958a0f23fSPratyush Anand dwc3_core_soft_reset(dwc); 31058a0f23fSPratyush Anand 3114878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 3123e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 3134878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DISSCRAMBLE; 3144878a028SSebastian Andrzej Siewior 315164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 3164878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 3174878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 3184878a028SSebastian Andrzej Siewior break; 3194878a028SSebastian Andrzej Siewior default: 3204878a028SSebastian Andrzej Siewior dev_dbg(dwc->dev, "No power optimization available\n"); 3214878a028SSebastian Andrzej Siewior } 3224878a028SSebastian Andrzej Siewior 3234878a028SSebastian Andrzej Siewior /* 3244878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 3251d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 3264878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 3271d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 3284878a028SSebastian Andrzej Siewior */ 3294878a028SSebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 3304878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 3314878a028SSebastian Andrzej Siewior 332789451f6SFelipe Balbi dwc3_core_num_eps(dwc); 333789451f6SFelipe Balbi 3344878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 3354878a028SSebastian Andrzej Siewior 33672246da4SFelipe Balbi return 0; 33772246da4SFelipe Balbi 33872246da4SFelipe Balbi err0: 33972246da4SFelipe Balbi return ret; 34072246da4SFelipe Balbi } 34172246da4SFelipe Balbi 34272246da4SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 34372246da4SFelipe Balbi { 34401b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb2_phy); 34501b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb3_phy); 34672246da4SFelipe Balbi } 34772246da4SFelipe Balbi 34872246da4SFelipe Balbi #define DWC3_ALIGN_MASK (16 - 1) 34972246da4SFelipe Balbi 35041ac7b3aSBill Pemberton static int dwc3_probe(struct platform_device *pdev) 35172246da4SFelipe Balbi { 352941ea361SFelipe Balbi struct device *dev = &pdev->dev; 353941ea361SFelipe Balbi struct dwc3_platform_data *pdata = dev_get_platdata(dev); 354941ea361SFelipe Balbi struct device_node *node = dev->of_node; 35572246da4SFelipe Balbi struct resource *res; 35672246da4SFelipe Balbi struct dwc3 *dwc; 3570949e99bSFelipe Balbi 35872246da4SFelipe Balbi int ret = -ENOMEM; 3590949e99bSFelipe Balbi 3600949e99bSFelipe Balbi void __iomem *regs; 36172246da4SFelipe Balbi void *mem; 36272246da4SFelipe Balbi 363802ca850SChanho Park mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 36472246da4SFelipe Balbi if (!mem) { 365802ca850SChanho Park dev_err(dev, "not enough memory\n"); 366802ca850SChanho Park return -ENOMEM; 36772246da4SFelipe Balbi } 36872246da4SFelipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 36972246da4SFelipe Balbi dwc->mem = mem; 37072246da4SFelipe Balbi 37151249dcaSIdo Shayevitz res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 37272246da4SFelipe Balbi if (!res) { 37351249dcaSIdo Shayevitz dev_err(dev, "missing IRQ\n"); 374802ca850SChanho Park return -ENODEV; 37572246da4SFelipe Balbi } 376066618bcSKishon Vijay Abraham I dwc->xhci_resources[1].start = res->start; 377066618bcSKishon Vijay Abraham I dwc->xhci_resources[1].end = res->end; 378066618bcSKishon Vijay Abraham I dwc->xhci_resources[1].flags = res->flags; 379066618bcSKishon Vijay Abraham I dwc->xhci_resources[1].name = res->name; 38072246da4SFelipe Balbi 38151249dcaSIdo Shayevitz res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 38251249dcaSIdo Shayevitz if (!res) { 38351249dcaSIdo Shayevitz dev_err(dev, "missing memory resource\n"); 38451249dcaSIdo Shayevitz return -ENODEV; 38551249dcaSIdo Shayevitz } 38672246da4SFelipe Balbi 3875088b6f5SKishon Vijay Abraham I if (node) { 388f7e846f0SFelipe Balbi dwc->maximum_speed = of_usb_get_maximum_speed(node); 389f7e846f0SFelipe Balbi 3905088b6f5SKishon Vijay Abraham I dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); 3915088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); 3926462cbd5SFelipe Balbi 3936462cbd5SFelipe Balbi dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize"); 394a45c82b8SRuchika Kharwar dwc->dr_mode = of_usb_get_dr_mode(node); 395bb674907SFelipe Balbi } else if (pdata) { 396f7e846f0SFelipe Balbi dwc->maximum_speed = pdata->maximum_speed; 397f7e846f0SFelipe Balbi 39851e1e7bcSFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 3995088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 4006462cbd5SFelipe Balbi 4016462cbd5SFelipe Balbi dwc->needs_fifo_resize = pdata->tx_fifo_resize; 402a45c82b8SRuchika Kharwar dwc->dr_mode = pdata->dr_mode; 403bb674907SFelipe Balbi } else { 404bb674907SFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 405bb674907SFelipe Balbi dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 4065088b6f5SKishon Vijay Abraham I } 4075088b6f5SKishon Vijay Abraham I 408f7e846f0SFelipe Balbi /* default to superspeed if no maximum_speed passed */ 409f7e846f0SFelipe Balbi if (dwc->maximum_speed == USB_SPEED_UNKNOWN) 410f7e846f0SFelipe Balbi dwc->maximum_speed = USB_SPEED_SUPER; 411f7e846f0SFelipe Balbi 412d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb2_phy)) { 413d105e7f8SFelipe Balbi ret = PTR_ERR(dwc->usb2_phy); 414d105e7f8SFelipe Balbi 415d105e7f8SFelipe Balbi /* 416d105e7f8SFelipe Balbi * if -ENXIO is returned, it means PHY layer wasn't 417d105e7f8SFelipe Balbi * enabled, so it makes no sense to return -EPROBE_DEFER 418d105e7f8SFelipe Balbi * in that case, since no PHY driver will ever probe. 419d105e7f8SFelipe Balbi */ 420d105e7f8SFelipe Balbi if (ret == -ENXIO) 421d105e7f8SFelipe Balbi return ret; 422d105e7f8SFelipe Balbi 42351e1e7bcSFelipe Balbi dev_err(dev, "no usb2 phy configured\n"); 42451e1e7bcSFelipe Balbi return -EPROBE_DEFER; 42551e1e7bcSFelipe Balbi } 42651e1e7bcSFelipe Balbi 427d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb3_phy)) { 428315955d7SRuchika Kharwar ret = PTR_ERR(dwc->usb3_phy); 429d105e7f8SFelipe Balbi 430d105e7f8SFelipe Balbi /* 431d105e7f8SFelipe Balbi * if -ENXIO is returned, it means PHY layer wasn't 432d105e7f8SFelipe Balbi * enabled, so it makes no sense to return -EPROBE_DEFER 433d105e7f8SFelipe Balbi * in that case, since no PHY driver will ever probe. 434d105e7f8SFelipe Balbi */ 435d105e7f8SFelipe Balbi if (ret == -ENXIO) 436d105e7f8SFelipe Balbi return ret; 437d105e7f8SFelipe Balbi 43851e1e7bcSFelipe Balbi dev_err(dev, "no usb3 phy configured\n"); 43951e1e7bcSFelipe Balbi return -EPROBE_DEFER; 44051e1e7bcSFelipe Balbi } 44151e1e7bcSFelipe Balbi 4422e112345SIvan T. Ivanov dwc->xhci_resources[0].start = res->start; 4432e112345SIvan T. Ivanov dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 4442e112345SIvan T. Ivanov DWC3_XHCI_REGS_END; 4452e112345SIvan T. Ivanov dwc->xhci_resources[0].flags = res->flags; 4462e112345SIvan T. Ivanov dwc->xhci_resources[0].name = res->name; 4472e112345SIvan T. Ivanov 4482e112345SIvan T. Ivanov res->start += DWC3_GLOBALS_REGS_START; 4492e112345SIvan T. Ivanov 4502e112345SIvan T. Ivanov /* 4512e112345SIvan T. Ivanov * Request memory region but exclude xHCI regs, 4522e112345SIvan T. Ivanov * since it will be requested by the xhci-plat driver. 4532e112345SIvan T. Ivanov */ 4542e112345SIvan T. Ivanov regs = devm_ioremap_resource(dev, res); 4552e112345SIvan T. Ivanov if (IS_ERR(regs)) 4562e112345SIvan T. Ivanov return PTR_ERR(regs); 4572e112345SIvan T. Ivanov 4588ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 0); 4598ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 0); 4608ba007a9SKishon Vijay Abraham I 46172246da4SFelipe Balbi spin_lock_init(&dwc->lock); 46272246da4SFelipe Balbi platform_set_drvdata(pdev, dwc); 46372246da4SFelipe Balbi 46472246da4SFelipe Balbi dwc->regs = regs; 46572246da4SFelipe Balbi dwc->regs_size = resource_size(res); 466802ca850SChanho Park dwc->dev = dev; 46772246da4SFelipe Balbi 468ddff14f1SKishon Vijay Abraham I dev->dma_mask = dev->parent->dma_mask; 469ddff14f1SKishon Vijay Abraham I dev->dma_parms = dev->parent->dma_parms; 470ddff14f1SKishon Vijay Abraham I dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); 471ddff14f1SKishon Vijay Abraham I 472802ca850SChanho Park pm_runtime_enable(dev); 473802ca850SChanho Park pm_runtime_get_sync(dev); 474802ca850SChanho Park pm_runtime_forbid(dev); 47572246da4SFelipe Balbi 4764fd24483SKishon Vijay Abraham I dwc3_cache_hwparams(dwc); 4774fd24483SKishon Vijay Abraham I 4783921426bSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 4793921426bSFelipe Balbi if (ret) { 4803921426bSFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 4813921426bSFelipe Balbi ret = -ENOMEM; 4823921426bSFelipe Balbi goto err0; 4833921426bSFelipe Balbi } 4843921426bSFelipe Balbi 48572246da4SFelipe Balbi ret = dwc3_core_init(dwc); 48672246da4SFelipe Balbi if (ret) { 487802ca850SChanho Park dev_err(dev, "failed to initialize core\n"); 4883921426bSFelipe Balbi goto err0; 48972246da4SFelipe Balbi } 49072246da4SFelipe Balbi 491f122d33eSFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 492f122d33eSFelipe Balbi if (ret) { 493f122d33eSFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 494f122d33eSFelipe Balbi goto err1; 495f122d33eSFelipe Balbi } 496f122d33eSFelipe Balbi 497cd051da2SVivek Gautam if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) 498a45c82b8SRuchika Kharwar dwc->dr_mode = USB_DR_MODE_HOST; 499cd051da2SVivek Gautam else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) 500a45c82b8SRuchika Kharwar dwc->dr_mode = USB_DR_MODE_PERIPHERAL; 5010949e99bSFelipe Balbi 502a45c82b8SRuchika Kharwar if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) 503a45c82b8SRuchika Kharwar dwc->dr_mode = USB_DR_MODE_OTG; 504a45c82b8SRuchika Kharwar 505a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 506a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 5073140e8cbSSebastian Andrzej Siewior dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); 50872246da4SFelipe Balbi ret = dwc3_gadget_init(dwc); 50972246da4SFelipe Balbi if (ret) { 510802ca850SChanho Park dev_err(dev, "failed to initialize gadget\n"); 511f122d33eSFelipe Balbi goto err2; 51272246da4SFelipe Balbi } 5130949e99bSFelipe Balbi break; 514a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 5153140e8cbSSebastian Andrzej Siewior dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); 516d07e8819SFelipe Balbi ret = dwc3_host_init(dwc); 517d07e8819SFelipe Balbi if (ret) { 518802ca850SChanho Park dev_err(dev, "failed to initialize host\n"); 519f122d33eSFelipe Balbi goto err2; 52072246da4SFelipe Balbi } 521d07e8819SFelipe Balbi break; 522a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 5233140e8cbSSebastian Andrzej Siewior dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); 524d07e8819SFelipe Balbi ret = dwc3_host_init(dwc); 525d07e8819SFelipe Balbi if (ret) { 526802ca850SChanho Park dev_err(dev, "failed to initialize host\n"); 527f122d33eSFelipe Balbi goto err2; 528d07e8819SFelipe Balbi } 529d07e8819SFelipe Balbi 530d07e8819SFelipe Balbi ret = dwc3_gadget_init(dwc); 531d07e8819SFelipe Balbi if (ret) { 532802ca850SChanho Park dev_err(dev, "failed to initialize gadget\n"); 533f122d33eSFelipe Balbi goto err2; 534d07e8819SFelipe Balbi } 535d07e8819SFelipe Balbi break; 5360949e99bSFelipe Balbi default: 537a45c82b8SRuchika Kharwar dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); 538f122d33eSFelipe Balbi goto err2; 53972246da4SFelipe Balbi } 54072246da4SFelipe Balbi 54172246da4SFelipe Balbi ret = dwc3_debugfs_init(dwc); 54272246da4SFelipe Balbi if (ret) { 543802ca850SChanho Park dev_err(dev, "failed to initialize debugfs\n"); 544f122d33eSFelipe Balbi goto err3; 54572246da4SFelipe Balbi } 54672246da4SFelipe Balbi 547802ca850SChanho Park pm_runtime_allow(dev); 54872246da4SFelipe Balbi 54972246da4SFelipe Balbi return 0; 55072246da4SFelipe Balbi 551f122d33eSFelipe Balbi err3: 552a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 553a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 55472246da4SFelipe Balbi dwc3_gadget_exit(dwc); 5550949e99bSFelipe Balbi break; 556a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 557d07e8819SFelipe Balbi dwc3_host_exit(dwc); 558d07e8819SFelipe Balbi break; 559a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 560d07e8819SFelipe Balbi dwc3_host_exit(dwc); 561d07e8819SFelipe Balbi dwc3_gadget_exit(dwc); 562d07e8819SFelipe Balbi break; 5630949e99bSFelipe Balbi default: 5640949e99bSFelipe Balbi /* do nothing */ 5650949e99bSFelipe Balbi break; 5660949e99bSFelipe Balbi } 56772246da4SFelipe Balbi 568f122d33eSFelipe Balbi err2: 569f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 570f122d33eSFelipe Balbi 571802ca850SChanho Park err1: 57272246da4SFelipe Balbi dwc3_core_exit(dwc); 57372246da4SFelipe Balbi 5743921426bSFelipe Balbi err0: 5753921426bSFelipe Balbi dwc3_free_event_buffers(dwc); 5763921426bSFelipe Balbi 57772246da4SFelipe Balbi return ret; 57872246da4SFelipe Balbi } 57972246da4SFelipe Balbi 580fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev) 58172246da4SFelipe Balbi { 58272246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 58372246da4SFelipe Balbi 5848ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 1); 5858ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 1); 5868ba007a9SKishon Vijay Abraham I 58716b972a5SFelipe Balbi pm_runtime_put_sync(&pdev->dev); 58872246da4SFelipe Balbi pm_runtime_disable(&pdev->dev); 58972246da4SFelipe Balbi 59072246da4SFelipe Balbi dwc3_debugfs_exit(dwc); 59172246da4SFelipe Balbi 592a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 593a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 59472246da4SFelipe Balbi dwc3_gadget_exit(dwc); 5950949e99bSFelipe Balbi break; 596a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 597d07e8819SFelipe Balbi dwc3_host_exit(dwc); 598d07e8819SFelipe Balbi break; 599a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 600d07e8819SFelipe Balbi dwc3_host_exit(dwc); 601d07e8819SFelipe Balbi dwc3_gadget_exit(dwc); 602d07e8819SFelipe Balbi break; 6030949e99bSFelipe Balbi default: 6040949e99bSFelipe Balbi /* do nothing */ 6050949e99bSFelipe Balbi break; 6060949e99bSFelipe Balbi } 60772246da4SFelipe Balbi 608f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 609d9b4330aSFelipe Balbi dwc3_free_event_buffers(dwc); 61072246da4SFelipe Balbi dwc3_core_exit(dwc); 61172246da4SFelipe Balbi 61272246da4SFelipe Balbi return 0; 61372246da4SFelipe Balbi } 61472246da4SFelipe Balbi 61519fda7cdSJingoo Han #ifdef CONFIG_PM_SLEEP 6167415f17cSFelipe Balbi static int dwc3_prepare(struct device *dev) 6177415f17cSFelipe Balbi { 6187415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 6197415f17cSFelipe Balbi unsigned long flags; 6207415f17cSFelipe Balbi 6217415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 6227415f17cSFelipe Balbi 623a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 624a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 625a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 6267415f17cSFelipe Balbi dwc3_gadget_prepare(dwc); 6277415f17cSFelipe Balbi /* FALLTHROUGH */ 628a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 6297415f17cSFelipe Balbi default: 6307415f17cSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 6317415f17cSFelipe Balbi break; 6327415f17cSFelipe Balbi } 6337415f17cSFelipe Balbi 6347415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 6357415f17cSFelipe Balbi 6367415f17cSFelipe Balbi return 0; 6377415f17cSFelipe Balbi } 6387415f17cSFelipe Balbi 6397415f17cSFelipe Balbi static void dwc3_complete(struct device *dev) 6407415f17cSFelipe Balbi { 6417415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 6427415f17cSFelipe Balbi unsigned long flags; 6437415f17cSFelipe Balbi 6447415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 6457415f17cSFelipe Balbi 646a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 647a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 648a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 6497415f17cSFelipe Balbi dwc3_gadget_complete(dwc); 6507415f17cSFelipe Balbi /* FALLTHROUGH */ 651a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 6527415f17cSFelipe Balbi default: 6537415f17cSFelipe Balbi dwc3_event_buffers_setup(dwc); 6547415f17cSFelipe Balbi break; 6557415f17cSFelipe Balbi } 6567415f17cSFelipe Balbi 6577415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 6587415f17cSFelipe Balbi } 6597415f17cSFelipe Balbi 6607415f17cSFelipe Balbi static int dwc3_suspend(struct device *dev) 6617415f17cSFelipe Balbi { 6627415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 6637415f17cSFelipe Balbi unsigned long flags; 6647415f17cSFelipe Balbi 6657415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 6667415f17cSFelipe Balbi 667a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 668a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 669a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 6707415f17cSFelipe Balbi dwc3_gadget_suspend(dwc); 6717415f17cSFelipe Balbi /* FALLTHROUGH */ 672a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 6737415f17cSFelipe Balbi default: 6747415f17cSFelipe Balbi /* do nothing */ 6757415f17cSFelipe Balbi break; 6767415f17cSFelipe Balbi } 6777415f17cSFelipe Balbi 6787415f17cSFelipe Balbi dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL); 6797415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 6807415f17cSFelipe Balbi 6817415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 6827415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 6837415f17cSFelipe Balbi 6847415f17cSFelipe Balbi return 0; 6857415f17cSFelipe Balbi } 6867415f17cSFelipe Balbi 6877415f17cSFelipe Balbi static int dwc3_resume(struct device *dev) 6887415f17cSFelipe Balbi { 6897415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 6907415f17cSFelipe Balbi unsigned long flags; 6917415f17cSFelipe Balbi 6927415f17cSFelipe Balbi usb_phy_init(dwc->usb3_phy); 6937415f17cSFelipe Balbi usb_phy_init(dwc->usb2_phy); 6947415f17cSFelipe Balbi 6957415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 6967415f17cSFelipe Balbi 6977415f17cSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl); 6987415f17cSFelipe Balbi 699a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 700a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 701a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 7027415f17cSFelipe Balbi dwc3_gadget_resume(dwc); 7037415f17cSFelipe Balbi /* FALLTHROUGH */ 704a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 7057415f17cSFelipe Balbi default: 7067415f17cSFelipe Balbi /* do nothing */ 7077415f17cSFelipe Balbi break; 7087415f17cSFelipe Balbi } 7097415f17cSFelipe Balbi 7107415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 7117415f17cSFelipe Balbi 7127415f17cSFelipe Balbi pm_runtime_disable(dev); 7137415f17cSFelipe Balbi pm_runtime_set_active(dev); 7147415f17cSFelipe Balbi pm_runtime_enable(dev); 7157415f17cSFelipe Balbi 7167415f17cSFelipe Balbi return 0; 7177415f17cSFelipe Balbi } 7187415f17cSFelipe Balbi 7197415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = { 7207415f17cSFelipe Balbi .prepare = dwc3_prepare, 7217415f17cSFelipe Balbi .complete = dwc3_complete, 7227415f17cSFelipe Balbi 7237415f17cSFelipe Balbi SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 7247415f17cSFelipe Balbi }; 7257415f17cSFelipe Balbi 7267415f17cSFelipe Balbi #define DWC3_PM_OPS &(dwc3_dev_pm_ops) 7277415f17cSFelipe Balbi #else 7287415f17cSFelipe Balbi #define DWC3_PM_OPS NULL 7297415f17cSFelipe Balbi #endif 7307415f17cSFelipe Balbi 7315088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF 7325088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = { 7335088b6f5SKishon Vijay Abraham I { 73422a5aa17SFelipe Balbi .compatible = "snps,dwc3" 73522a5aa17SFelipe Balbi }, 73622a5aa17SFelipe Balbi { 7375088b6f5SKishon Vijay Abraham I .compatible = "synopsys,dwc3" 7385088b6f5SKishon Vijay Abraham I }, 7395088b6f5SKishon Vijay Abraham I { }, 7405088b6f5SKishon Vijay Abraham I }; 7415088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match); 7425088b6f5SKishon Vijay Abraham I #endif 7435088b6f5SKishon Vijay Abraham I 74472246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 74572246da4SFelipe Balbi .probe = dwc3_probe, 7467690417dSBill Pemberton .remove = dwc3_remove, 74772246da4SFelipe Balbi .driver = { 74872246da4SFelipe Balbi .name = "dwc3", 7495088b6f5SKishon Vijay Abraham I .of_match_table = of_match_ptr(of_dwc3_match), 7507415f17cSFelipe Balbi .pm = DWC3_PM_OPS, 75172246da4SFelipe Balbi }, 75272246da4SFelipe Balbi }; 75372246da4SFelipe Balbi 754b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 755b1116dccSTobias Klauser 7567ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 75772246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 7585945f789SFelipe Balbi MODULE_LICENSE("GPL v2"); 75972246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 760