172246da4SFelipe Balbi /** 272246da4SFelipe Balbi * core.c - DesignWare USB3 DRD Controller Core file 372246da4SFelipe Balbi * 472246da4SFelipe Balbi * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com 572246da4SFelipe Balbi * 672246da4SFelipe Balbi * Authors: Felipe Balbi <balbi@ti.com>, 772246da4SFelipe Balbi * Sebastian Andrzej Siewior <bigeasy@linutronix.de> 872246da4SFelipe Balbi * 95945f789SFelipe Balbi * This program is free software: you can redistribute it and/or modify 105945f789SFelipe Balbi * it under the terms of the GNU General Public License version 2 of 115945f789SFelipe Balbi * the License as published by the Free Software Foundation. 1272246da4SFelipe Balbi * 135945f789SFelipe Balbi * This program is distributed in the hope that it will be useful, 145945f789SFelipe Balbi * but WITHOUT ANY WARRANTY; without even the implied warranty of 155945f789SFelipe Balbi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 165945f789SFelipe Balbi * GNU General Public License for more details. 1772246da4SFelipe Balbi * 185945f789SFelipe Balbi * You should have received a copy of the GNU General Public License 195945f789SFelipe Balbi * along with this program. If not, see <http://www.gnu.org/licenses/>. 2072246da4SFelipe Balbi */ 2172246da4SFelipe Balbi 22fa0ea13eSFelipe Balbi #include <linux/version.h> 23a72e658bSFelipe Balbi #include <linux/module.h> 2472246da4SFelipe Balbi #include <linux/kernel.h> 2572246da4SFelipe Balbi #include <linux/slab.h> 2672246da4SFelipe Balbi #include <linux/spinlock.h> 2772246da4SFelipe Balbi #include <linux/platform_device.h> 2872246da4SFelipe Balbi #include <linux/pm_runtime.h> 2972246da4SFelipe Balbi #include <linux/interrupt.h> 3072246da4SFelipe Balbi #include <linux/ioport.h> 3172246da4SFelipe Balbi #include <linux/io.h> 3272246da4SFelipe Balbi #include <linux/list.h> 3372246da4SFelipe Balbi #include <linux/delay.h> 3472246da4SFelipe Balbi #include <linux/dma-mapping.h> 35457e84b6SFelipe Balbi #include <linux/of.h> 36404905a6SHeikki Krogerus #include <linux/acpi.h> 3772246da4SFelipe Balbi 3872246da4SFelipe Balbi #include <linux/usb/ch9.h> 3972246da4SFelipe Balbi #include <linux/usb/gadget.h> 40f7e846f0SFelipe Balbi #include <linux/usb/of.h> 41a45c82b8SRuchika Kharwar #include <linux/usb/otg.h> 4272246da4SFelipe Balbi 436462cbd5SFelipe Balbi #include "platform_data.h" 4472246da4SFelipe Balbi #include "core.h" 4572246da4SFelipe Balbi #include "gadget.h" 4672246da4SFelipe Balbi #include "io.h" 4772246da4SFelipe Balbi 4872246da4SFelipe Balbi #include "debug.h" 4972246da4SFelipe Balbi 508300dd23SFelipe Balbi /* -------------------------------------------------------------------------- */ 518300dd23SFelipe Balbi 523140e8cbSSebastian Andrzej Siewior void dwc3_set_mode(struct dwc3 *dwc, u32 mode) 533140e8cbSSebastian Andrzej Siewior { 543140e8cbSSebastian Andrzej Siewior u32 reg; 553140e8cbSSebastian Andrzej Siewior 563140e8cbSSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 573140e8cbSSebastian Andrzej Siewior reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); 583140e8cbSSebastian Andrzej Siewior reg |= DWC3_GCTL_PRTCAPDIR(mode); 593140e8cbSSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 603140e8cbSSebastian Andrzej Siewior } 618300dd23SFelipe Balbi 6272246da4SFelipe Balbi /** 6372246da4SFelipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 6472246da4SFelipe Balbi * @dwc: pointer to our context structure 6572246da4SFelipe Balbi */ 6657303488SKishon Vijay Abraham I static int dwc3_core_soft_reset(struct dwc3 *dwc) 6772246da4SFelipe Balbi { 6872246da4SFelipe Balbi u32 reg; 6957303488SKishon Vijay Abraham I int ret; 7072246da4SFelipe Balbi 7172246da4SFelipe Balbi /* Before Resetting PHY, put Core in Reset */ 7272246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 7372246da4SFelipe Balbi reg |= DWC3_GCTL_CORESOFTRESET; 7472246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 7572246da4SFelipe Balbi 7672246da4SFelipe Balbi /* Assert USB3 PHY reset */ 7772246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 7872246da4SFelipe Balbi reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; 7972246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 8072246da4SFelipe Balbi 8172246da4SFelipe Balbi /* Assert USB2 PHY reset */ 8272246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 8372246da4SFelipe Balbi reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; 8472246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 8572246da4SFelipe Balbi 8651e1e7bcSFelipe Balbi usb_phy_init(dwc->usb2_phy); 8751e1e7bcSFelipe Balbi usb_phy_init(dwc->usb3_phy); 8857303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 8957303488SKishon Vijay Abraham I if (ret < 0) 9057303488SKishon Vijay Abraham I return ret; 9157303488SKishon Vijay Abraham I 9257303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 9357303488SKishon Vijay Abraham I if (ret < 0) { 9457303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 9557303488SKishon Vijay Abraham I return ret; 9657303488SKishon Vijay Abraham I } 9772246da4SFelipe Balbi mdelay(100); 9872246da4SFelipe Balbi 9972246da4SFelipe Balbi /* Clear USB3 PHY reset */ 10072246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 10172246da4SFelipe Balbi reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; 10272246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 10372246da4SFelipe Balbi 10472246da4SFelipe Balbi /* Clear USB2 PHY reset */ 10572246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 10672246da4SFelipe Balbi reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; 10772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 10872246da4SFelipe Balbi 10945627ac6SPratyush Anand mdelay(100); 11045627ac6SPratyush Anand 11172246da4SFelipe Balbi /* After PHYs are stable we can take Core out of reset state */ 11272246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 11372246da4SFelipe Balbi reg &= ~DWC3_GCTL_CORESOFTRESET; 11472246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 11557303488SKishon Vijay Abraham I 11657303488SKishon Vijay Abraham I return 0; 11772246da4SFelipe Balbi } 11872246da4SFelipe Balbi 11972246da4SFelipe Balbi /** 120c5cc74e8SHeikki Krogerus * dwc3_soft_reset - Issue soft reset 121c5cc74e8SHeikki Krogerus * @dwc: Pointer to our controller context structure 122c5cc74e8SHeikki Krogerus */ 123c5cc74e8SHeikki Krogerus static int dwc3_soft_reset(struct dwc3 *dwc) 124c5cc74e8SHeikki Krogerus { 125c5cc74e8SHeikki Krogerus unsigned long timeout; 126c5cc74e8SHeikki Krogerus u32 reg; 127c5cc74e8SHeikki Krogerus 128c5cc74e8SHeikki Krogerus timeout = jiffies + msecs_to_jiffies(500); 129c5cc74e8SHeikki Krogerus dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); 130c5cc74e8SHeikki Krogerus do { 131c5cc74e8SHeikki Krogerus reg = dwc3_readl(dwc->regs, DWC3_DCTL); 132c5cc74e8SHeikki Krogerus if (!(reg & DWC3_DCTL_CSFTRST)) 133c5cc74e8SHeikki Krogerus break; 134c5cc74e8SHeikki Krogerus 135c5cc74e8SHeikki Krogerus if (time_after(jiffies, timeout)) { 136c5cc74e8SHeikki Krogerus dev_err(dwc->dev, "Reset Timed Out\n"); 137c5cc74e8SHeikki Krogerus return -ETIMEDOUT; 138c5cc74e8SHeikki Krogerus } 139c5cc74e8SHeikki Krogerus 140c5cc74e8SHeikki Krogerus cpu_relax(); 141c5cc74e8SHeikki Krogerus } while (true); 142c5cc74e8SHeikki Krogerus 143c5cc74e8SHeikki Krogerus return 0; 144c5cc74e8SHeikki Krogerus } 145c5cc74e8SHeikki Krogerus 146c5cc74e8SHeikki Krogerus /** 14772246da4SFelipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 14872246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 14972246da4SFelipe Balbi * @evt: Pointer to event buffer to be freed 15072246da4SFelipe Balbi */ 15172246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc, 15272246da4SFelipe Balbi struct dwc3_event_buffer *evt) 15372246da4SFelipe Balbi { 15472246da4SFelipe Balbi dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); 15572246da4SFelipe Balbi } 15672246da4SFelipe Balbi 15772246da4SFelipe Balbi /** 1581d046793SPaul Zimmerman * dwc3_alloc_one_event_buffer - Allocates one event buffer structure 15972246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 16072246da4SFelipe Balbi * @length: size of the event buffer 16172246da4SFelipe Balbi * 1621d046793SPaul Zimmerman * Returns a pointer to the allocated event buffer structure on success 16372246da4SFelipe Balbi * otherwise ERR_PTR(errno). 16472246da4SFelipe Balbi */ 16567d0b500SFelipe Balbi static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, 16667d0b500SFelipe Balbi unsigned length) 16772246da4SFelipe Balbi { 16872246da4SFelipe Balbi struct dwc3_event_buffer *evt; 16972246da4SFelipe Balbi 170380f0d28SFelipe Balbi evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL); 17172246da4SFelipe Balbi if (!evt) 17272246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 17372246da4SFelipe Balbi 17472246da4SFelipe Balbi evt->dwc = dwc; 17572246da4SFelipe Balbi evt->length = length; 17672246da4SFelipe Balbi evt->buf = dma_alloc_coherent(dwc->dev, length, 17772246da4SFelipe Balbi &evt->dma, GFP_KERNEL); 178e32672f0SFelipe Balbi if (!evt->buf) 17972246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 18072246da4SFelipe Balbi 18172246da4SFelipe Balbi return evt; 18272246da4SFelipe Balbi } 18372246da4SFelipe Balbi 18472246da4SFelipe Balbi /** 18572246da4SFelipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 18672246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 18772246da4SFelipe Balbi */ 18872246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc) 18972246da4SFelipe Balbi { 19072246da4SFelipe Balbi struct dwc3_event_buffer *evt; 19172246da4SFelipe Balbi int i; 19272246da4SFelipe Balbi 1939f622b2aSFelipe Balbi for (i = 0; i < dwc->num_event_buffers; i++) { 19472246da4SFelipe Balbi evt = dwc->ev_buffs[i]; 19564b6c8a7SAnton Tikhomirov if (evt) 19672246da4SFelipe Balbi dwc3_free_one_event_buffer(dwc, evt); 19772246da4SFelipe Balbi } 19872246da4SFelipe Balbi } 19972246da4SFelipe Balbi 20072246da4SFelipe Balbi /** 20172246da4SFelipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 2021d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 20372246da4SFelipe Balbi * @length: size of event buffer 20472246da4SFelipe Balbi * 2051d046793SPaul Zimmerman * Returns 0 on success otherwise negative errno. In the error case, dwc 20672246da4SFelipe Balbi * may contain some buffers allocated but not all which were requested. 20772246da4SFelipe Balbi */ 20841ac7b3aSBill Pemberton static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) 20972246da4SFelipe Balbi { 2109f622b2aSFelipe Balbi int num; 21172246da4SFelipe Balbi int i; 21272246da4SFelipe Balbi 2139f622b2aSFelipe Balbi num = DWC3_NUM_INT(dwc->hwparams.hwparams1); 2149f622b2aSFelipe Balbi dwc->num_event_buffers = num; 2159f622b2aSFelipe Balbi 216380f0d28SFelipe Balbi dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num, 217380f0d28SFelipe Balbi GFP_KERNEL); 218734d5a53SJingoo Han if (!dwc->ev_buffs) 219457d3f21SFelipe Balbi return -ENOMEM; 220457d3f21SFelipe Balbi 22172246da4SFelipe Balbi for (i = 0; i < num; i++) { 22272246da4SFelipe Balbi struct dwc3_event_buffer *evt; 22372246da4SFelipe Balbi 22472246da4SFelipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 22572246da4SFelipe Balbi if (IS_ERR(evt)) { 22672246da4SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 22772246da4SFelipe Balbi return PTR_ERR(evt); 22872246da4SFelipe Balbi } 22972246da4SFelipe Balbi dwc->ev_buffs[i] = evt; 23072246da4SFelipe Balbi } 23172246da4SFelipe Balbi 23272246da4SFelipe Balbi return 0; 23372246da4SFelipe Balbi } 23472246da4SFelipe Balbi 23572246da4SFelipe Balbi /** 23672246da4SFelipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 2371d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 23872246da4SFelipe Balbi * 23972246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 24072246da4SFelipe Balbi */ 2417acd85e0SPaul Zimmerman static int dwc3_event_buffers_setup(struct dwc3 *dwc) 24272246da4SFelipe Balbi { 24372246da4SFelipe Balbi struct dwc3_event_buffer *evt; 24472246da4SFelipe Balbi int n; 24572246da4SFelipe Balbi 2469f622b2aSFelipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 24772246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 24872246da4SFelipe Balbi dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n", 24972246da4SFelipe Balbi evt->buf, (unsigned long long) evt->dma, 25072246da4SFelipe Balbi evt->length); 25172246da4SFelipe Balbi 2527acd85e0SPaul Zimmerman evt->lpos = 0; 2537acd85e0SPaul Zimmerman 25472246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 25572246da4SFelipe Balbi lower_32_bits(evt->dma)); 25672246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 25772246da4SFelipe Balbi upper_32_bits(evt->dma)); 25872246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 25968d6a01bSFelipe Balbi DWC3_GEVNTSIZ_SIZE(evt->length)); 26072246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 26172246da4SFelipe Balbi } 26272246da4SFelipe Balbi 26372246da4SFelipe Balbi return 0; 26472246da4SFelipe Balbi } 26572246da4SFelipe Balbi 26672246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 26772246da4SFelipe Balbi { 26872246da4SFelipe Balbi struct dwc3_event_buffer *evt; 26972246da4SFelipe Balbi int n; 27072246da4SFelipe Balbi 2719f622b2aSFelipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 27272246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 2737acd85e0SPaul Zimmerman 2747acd85e0SPaul Zimmerman evt->lpos = 0; 2757acd85e0SPaul Zimmerman 27672246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); 27772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); 27868d6a01bSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK 27968d6a01bSFelipe Balbi | DWC3_GEVNTSIZ_SIZE(0)); 28072246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 28172246da4SFelipe Balbi } 28272246da4SFelipe Balbi } 28372246da4SFelipe Balbi 2840ffcaf37SFelipe Balbi static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) 2850ffcaf37SFelipe Balbi { 2860ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 2870ffcaf37SFelipe Balbi return 0; 2880ffcaf37SFelipe Balbi 2890ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 2900ffcaf37SFelipe Balbi return 0; 2910ffcaf37SFelipe Balbi 2920ffcaf37SFelipe Balbi dwc->scratchbuf = kmalloc_array(dwc->nr_scratch, 2930ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, GFP_KERNEL); 2940ffcaf37SFelipe Balbi if (!dwc->scratchbuf) 2950ffcaf37SFelipe Balbi return -ENOMEM; 2960ffcaf37SFelipe Balbi 2970ffcaf37SFelipe Balbi return 0; 2980ffcaf37SFelipe Balbi } 2990ffcaf37SFelipe Balbi 3000ffcaf37SFelipe Balbi static int dwc3_setup_scratch_buffers(struct dwc3 *dwc) 3010ffcaf37SFelipe Balbi { 3020ffcaf37SFelipe Balbi dma_addr_t scratch_addr; 3030ffcaf37SFelipe Balbi u32 param; 3040ffcaf37SFelipe Balbi int ret; 3050ffcaf37SFelipe Balbi 3060ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3070ffcaf37SFelipe Balbi return 0; 3080ffcaf37SFelipe Balbi 3090ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3100ffcaf37SFelipe Balbi return 0; 3110ffcaf37SFelipe Balbi 3120ffcaf37SFelipe Balbi /* should never fall here */ 3130ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 3140ffcaf37SFelipe Balbi return 0; 3150ffcaf37SFelipe Balbi 3160ffcaf37SFelipe Balbi scratch_addr = dma_map_single(dwc->dev, dwc->scratchbuf, 3170ffcaf37SFelipe Balbi dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, 3180ffcaf37SFelipe Balbi DMA_BIDIRECTIONAL); 3190ffcaf37SFelipe Balbi if (dma_mapping_error(dwc->dev, scratch_addr)) { 3200ffcaf37SFelipe Balbi dev_err(dwc->dev, "failed to map scratch buffer\n"); 3210ffcaf37SFelipe Balbi ret = -EFAULT; 3220ffcaf37SFelipe Balbi goto err0; 3230ffcaf37SFelipe Balbi } 3240ffcaf37SFelipe Balbi 3250ffcaf37SFelipe Balbi dwc->scratch_addr = scratch_addr; 3260ffcaf37SFelipe Balbi 3270ffcaf37SFelipe Balbi param = lower_32_bits(scratch_addr); 3280ffcaf37SFelipe Balbi 3290ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3300ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param); 3310ffcaf37SFelipe Balbi if (ret < 0) 3320ffcaf37SFelipe Balbi goto err1; 3330ffcaf37SFelipe Balbi 3340ffcaf37SFelipe Balbi param = upper_32_bits(scratch_addr); 3350ffcaf37SFelipe Balbi 3360ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3370ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param); 3380ffcaf37SFelipe Balbi if (ret < 0) 3390ffcaf37SFelipe Balbi goto err1; 3400ffcaf37SFelipe Balbi 3410ffcaf37SFelipe Balbi return 0; 3420ffcaf37SFelipe Balbi 3430ffcaf37SFelipe Balbi err1: 3440ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3450ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3460ffcaf37SFelipe Balbi 3470ffcaf37SFelipe Balbi err0: 3480ffcaf37SFelipe Balbi return ret; 3490ffcaf37SFelipe Balbi } 3500ffcaf37SFelipe Balbi 3510ffcaf37SFelipe Balbi static void dwc3_free_scratch_buffers(struct dwc3 *dwc) 3520ffcaf37SFelipe Balbi { 3530ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3540ffcaf37SFelipe Balbi return; 3550ffcaf37SFelipe Balbi 3560ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3570ffcaf37SFelipe Balbi return; 3580ffcaf37SFelipe Balbi 3590ffcaf37SFelipe Balbi /* should never fall here */ 3600ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 3610ffcaf37SFelipe Balbi return; 3620ffcaf37SFelipe Balbi 3630ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3640ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3650ffcaf37SFelipe Balbi kfree(dwc->scratchbuf); 3660ffcaf37SFelipe Balbi } 3670ffcaf37SFelipe Balbi 368789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc) 369789451f6SFelipe Balbi { 370789451f6SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 371789451f6SFelipe Balbi 372789451f6SFelipe Balbi dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); 373789451f6SFelipe Balbi dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; 374789451f6SFelipe Balbi 37573815280SFelipe Balbi dwc3_trace(trace_dwc3_core, "found %d IN and %d OUT endpoints", 376789451f6SFelipe Balbi dwc->num_in_eps, dwc->num_out_eps); 377789451f6SFelipe Balbi } 378789451f6SFelipe Balbi 37941ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc) 38026ceca97SFelipe Balbi { 38126ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 38226ceca97SFelipe Balbi 38326ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 38426ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 38526ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 38626ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 38726ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 38826ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 38926ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 39026ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 39126ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 39226ceca97SFelipe Balbi } 39326ceca97SFelipe Balbi 39472246da4SFelipe Balbi /** 395b5a65c40SHuang Rui * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core 396b5a65c40SHuang Rui * @dwc: Pointer to our controller context structure 39788bc9d19SHeikki Krogerus * 39888bc9d19SHeikki Krogerus * Returns 0 on success. The USB PHY interfaces are configured but not 39988bc9d19SHeikki Krogerus * initialized. The PHY interfaces and the PHYs get initialized together with 40088bc9d19SHeikki Krogerus * the core in dwc3_core_init. 401b5a65c40SHuang Rui */ 40288bc9d19SHeikki Krogerus static int dwc3_phy_setup(struct dwc3 *dwc) 403b5a65c40SHuang Rui { 404b5a65c40SHuang Rui u32 reg; 40588bc9d19SHeikki Krogerus int ret; 406b5a65c40SHuang Rui 407b5a65c40SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 408b5a65c40SHuang Rui 4092164a476SHuang Rui /* 4102164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY 4112164a476SHuang Rui * to '0' during coreConsultant configuration. So default value 4122164a476SHuang Rui * will be '0' when the core is reset. Application needs to set it 4132164a476SHuang Rui * to '1' after the core initialization is completed. 4142164a476SHuang Rui */ 4152164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 4162164a476SHuang Rui reg |= DWC3_GUSB3PIPECTL_SUSPHY; 4172164a476SHuang Rui 418b5a65c40SHuang Rui if (dwc->u2ss_inp3_quirk) 419b5a65c40SHuang Rui reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; 420b5a65c40SHuang Rui 421df31f5b3SHuang Rui if (dwc->req_p1p2p3_quirk) 422df31f5b3SHuang Rui reg |= DWC3_GUSB3PIPECTL_REQP1P2P3; 423df31f5b3SHuang Rui 424a2a1d0f5SHuang Rui if (dwc->del_p1p2p3_quirk) 425a2a1d0f5SHuang Rui reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN; 426a2a1d0f5SHuang Rui 42741c06ffdSHuang Rui if (dwc->del_phy_power_chg_quirk) 42841c06ffdSHuang Rui reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE; 42941c06ffdSHuang Rui 430fb67afcaSHuang Rui if (dwc->lfps_filter_quirk) 431fb67afcaSHuang Rui reg |= DWC3_GUSB3PIPECTL_LFPSFILT; 432fb67afcaSHuang Rui 43314f4ac53SHuang Rui if (dwc->rx_detect_poll_quirk) 43414f4ac53SHuang Rui reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL; 43514f4ac53SHuang Rui 4366b6a0c9aSHuang Rui if (dwc->tx_de_emphasis_quirk) 4376b6a0c9aSHuang Rui reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); 4386b6a0c9aSHuang Rui 439cd72f890SFelipe Balbi if (dwc->dis_u3_susphy_quirk) 44059acfa20SHuang Rui reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 44159acfa20SHuang Rui 442b5a65c40SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 443b5a65c40SHuang Rui 4442164a476SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 4452164a476SHuang Rui 4463e10a2ceSHeikki Krogerus /* Select the HS PHY interface */ 4473e10a2ceSHeikki Krogerus switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) { 4483e10a2ceSHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI: 4493e10a2ceSHeikki Krogerus if (!strncmp(dwc->hsphy_interface, "utmi", 4)) { 4503e10a2ceSHeikki Krogerus reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI; 45188bc9d19SHeikki Krogerus break; 4523e10a2ceSHeikki Krogerus } else if (!strncmp(dwc->hsphy_interface, "ulpi", 4)) { 4533e10a2ceSHeikki Krogerus reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI; 45488bc9d19SHeikki Krogerus dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 4553e10a2ceSHeikki Krogerus } else { 4563e10a2ceSHeikki Krogerus dev_warn(dwc->dev, "HSPHY Interface not defined\n"); 45788bc9d19SHeikki Krogerus 45888bc9d19SHeikki Krogerus /* Relying on default value. */ 45988bc9d19SHeikki Krogerus if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) 4603e10a2ceSHeikki Krogerus break; 4613e10a2ceSHeikki Krogerus } 4623e10a2ceSHeikki Krogerus /* FALLTHROUGH */ 46388bc9d19SHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: 46488bc9d19SHeikki Krogerus /* Making sure the interface and PHY are operational */ 46588bc9d19SHeikki Krogerus ret = dwc3_soft_reset(dwc); 46688bc9d19SHeikki Krogerus if (ret) 46788bc9d19SHeikki Krogerus return ret; 46888bc9d19SHeikki Krogerus 46988bc9d19SHeikki Krogerus udelay(1); 47088bc9d19SHeikki Krogerus 47188bc9d19SHeikki Krogerus ret = dwc3_ulpi_init(dwc); 47288bc9d19SHeikki Krogerus if (ret) 47388bc9d19SHeikki Krogerus return ret; 47488bc9d19SHeikki Krogerus /* FALLTHROUGH */ 4753e10a2ceSHeikki Krogerus default: 4763e10a2ceSHeikki Krogerus break; 4773e10a2ceSHeikki Krogerus } 4783e10a2ceSHeikki Krogerus 4792164a476SHuang Rui /* 4802164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to 4812164a476SHuang Rui * '0' during coreConsultant configuration. So default value will 4822164a476SHuang Rui * be '0' when the core is reset. Application needs to set it to 4832164a476SHuang Rui * '1' after the core initialization is completed. 4842164a476SHuang Rui */ 4852164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 4862164a476SHuang Rui reg |= DWC3_GUSB2PHYCFG_SUSPHY; 4872164a476SHuang Rui 488cd72f890SFelipe Balbi if (dwc->dis_u2_susphy_quirk) 4890effe0a3SHuang Rui reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 4900effe0a3SHuang Rui 4912164a476SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 49288bc9d19SHeikki Krogerus 49388bc9d19SHeikki Krogerus return 0; 494b5a65c40SHuang Rui } 495b5a65c40SHuang Rui 496b5a65c40SHuang Rui /** 49772246da4SFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 49872246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 49972246da4SFelipe Balbi * 50072246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 50172246da4SFelipe Balbi */ 50241ac7b3aSBill Pemberton static int dwc3_core_init(struct dwc3 *dwc) 50372246da4SFelipe Balbi { 5040ffcaf37SFelipe Balbi u32 hwparams4 = dwc->hwparams.hwparams4; 50572246da4SFelipe Balbi u32 reg; 50672246da4SFelipe Balbi int ret; 50772246da4SFelipe Balbi 5087650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 5097650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 5107650bd74SSebastian Andrzej Siewior if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { 5117650bd74SSebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 5127650bd74SSebastian Andrzej Siewior ret = -ENODEV; 5137650bd74SSebastian Andrzej Siewior goto err0; 5147650bd74SSebastian Andrzej Siewior } 515248b122bSFelipe Balbi dwc->revision = reg; 5167650bd74SSebastian Andrzej Siewior 517fa0ea13eSFelipe Balbi /* 518fa0ea13eSFelipe Balbi * Write Linux Version Code to our GUID register so it's easy to figure 519fa0ea13eSFelipe Balbi * out which kernel version a bug was found. 520fa0ea13eSFelipe Balbi */ 521fa0ea13eSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); 522fa0ea13eSFelipe Balbi 5230e1e5c47SPaul Zimmerman /* Handle USB2.0-only core configuration */ 5240e1e5c47SPaul Zimmerman if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 5250e1e5c47SPaul Zimmerman DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { 5260e1e5c47SPaul Zimmerman if (dwc->maximum_speed == USB_SPEED_SUPER) 5270e1e5c47SPaul Zimmerman dwc->maximum_speed = USB_SPEED_HIGH; 5280e1e5c47SPaul Zimmerman } 5290e1e5c47SPaul Zimmerman 53072246da4SFelipe Balbi /* issue device SoftReset too */ 531c5cc74e8SHeikki Krogerus ret = dwc3_soft_reset(dwc); 532c5cc74e8SHeikki Krogerus if (ret) 53372246da4SFelipe Balbi goto err0; 53472246da4SFelipe Balbi 53557303488SKishon Vijay Abraham I ret = dwc3_core_soft_reset(dwc); 53657303488SKishon Vijay Abraham I if (ret) 53757303488SKishon Vijay Abraham I goto err0; 53858a0f23fSPratyush Anand 5394878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 5403e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 5414878a028SSebastian Andrzej Siewior 542164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 5434878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 54432a4a135SFelipe Balbi /** 54532a4a135SFelipe Balbi * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an 54632a4a135SFelipe Balbi * issue which would cause xHCI compliance tests to fail. 54732a4a135SFelipe Balbi * 54832a4a135SFelipe Balbi * Because of that we cannot enable clock gating on such 54932a4a135SFelipe Balbi * configurations. 55032a4a135SFelipe Balbi * 55132a4a135SFelipe Balbi * Refers to: 55232a4a135SFelipe Balbi * 55332a4a135SFelipe Balbi * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based 55432a4a135SFelipe Balbi * SOF/ITP Mode Used 55532a4a135SFelipe Balbi */ 55632a4a135SFelipe Balbi if ((dwc->dr_mode == USB_DR_MODE_HOST || 55732a4a135SFelipe Balbi dwc->dr_mode == USB_DR_MODE_OTG) && 55832a4a135SFelipe Balbi (dwc->revision >= DWC3_REVISION_210A && 55932a4a135SFelipe Balbi dwc->revision <= DWC3_REVISION_250A)) 56032a4a135SFelipe Balbi reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; 56132a4a135SFelipe Balbi else 5624878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 5634878a028SSebastian Andrzej Siewior break; 5640ffcaf37SFelipe Balbi case DWC3_GHWPARAMS1_EN_PWROPT_HIB: 5650ffcaf37SFelipe Balbi /* enable hibernation here */ 5660ffcaf37SFelipe Balbi dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); 5672eac3992SHuang Rui 5682eac3992SHuang Rui /* 5692eac3992SHuang Rui * REVISIT Enabling this bit so that host-mode hibernation 5702eac3992SHuang Rui * will work. Device-mode hibernation is not yet implemented. 5712eac3992SHuang Rui */ 5722eac3992SHuang Rui reg |= DWC3_GCTL_GBLHIBERNATIONEN; 5730ffcaf37SFelipe Balbi break; 5744878a028SSebastian Andrzej Siewior default: 5754878a028SSebastian Andrzej Siewior dev_dbg(dwc->dev, "No power optimization available\n"); 5764878a028SSebastian Andrzej Siewior } 5774878a028SSebastian Andrzej Siewior 578946bd579SHuang Rui /* check if current dwc3 is on simulation board */ 579946bd579SHuang Rui if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { 580946bd579SHuang Rui dev_dbg(dwc->dev, "it is on FPGA board\n"); 581946bd579SHuang Rui dwc->is_fpga = true; 582946bd579SHuang Rui } 583946bd579SHuang Rui 5843b81221aSHuang Rui WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga, 5853b81221aSHuang Rui "disable_scramble cannot be used on non-FPGA builds\n"); 5863b81221aSHuang Rui 5873b81221aSHuang Rui if (dwc->disable_scramble_quirk && dwc->is_fpga) 5883b81221aSHuang Rui reg |= DWC3_GCTL_DISSCRAMBLE; 5893b81221aSHuang Rui else 5903b81221aSHuang Rui reg &= ~DWC3_GCTL_DISSCRAMBLE; 5913b81221aSHuang Rui 5929a5b2f31SHuang Rui if (dwc->u2exit_lfps_quirk) 5939a5b2f31SHuang Rui reg |= DWC3_GCTL_U2EXIT_LFPS; 5949a5b2f31SHuang Rui 5954878a028SSebastian Andrzej Siewior /* 5964878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 5971d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 5984878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 5991d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 6004878a028SSebastian Andrzej Siewior */ 6014878a028SSebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 6024878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 6034878a028SSebastian Andrzej Siewior 604789451f6SFelipe Balbi dwc3_core_num_eps(dwc); 605789451f6SFelipe Balbi 6064878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 6074878a028SSebastian Andrzej Siewior 6080ffcaf37SFelipe Balbi ret = dwc3_alloc_scratch_buffers(dwc); 6090ffcaf37SFelipe Balbi if (ret) 6100ffcaf37SFelipe Balbi goto err1; 6110ffcaf37SFelipe Balbi 6120ffcaf37SFelipe Balbi ret = dwc3_setup_scratch_buffers(dwc); 6130ffcaf37SFelipe Balbi if (ret) 6140ffcaf37SFelipe Balbi goto err2; 6150ffcaf37SFelipe Balbi 61672246da4SFelipe Balbi return 0; 61772246da4SFelipe Balbi 6180ffcaf37SFelipe Balbi err2: 6190ffcaf37SFelipe Balbi dwc3_free_scratch_buffers(dwc); 6200ffcaf37SFelipe Balbi 6210ffcaf37SFelipe Balbi err1: 6220ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 6230ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 62457303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 62557303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 6260ffcaf37SFelipe Balbi 62772246da4SFelipe Balbi err0: 62872246da4SFelipe Balbi return ret; 62972246da4SFelipe Balbi } 63072246da4SFelipe Balbi 63172246da4SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 63272246da4SFelipe Balbi { 6330ffcaf37SFelipe Balbi dwc3_free_scratch_buffers(dwc); 63401b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb2_phy); 63501b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb3_phy); 63657303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 63757303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 63872246da4SFelipe Balbi } 63972246da4SFelipe Balbi 6403c9f94acSFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc) 64172246da4SFelipe Balbi { 6423c9f94acSFelipe Balbi struct device *dev = dwc->dev; 643941ea361SFelipe Balbi struct device_node *node = dev->of_node; 6443c9f94acSFelipe Balbi int ret; 64572246da4SFelipe Balbi 6465088b6f5SKishon Vijay Abraham I if (node) { 6475088b6f5SKishon Vijay Abraham I dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); 6485088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); 649bb674907SFelipe Balbi } else { 650bb674907SFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 651bb674907SFelipe Balbi dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 6525088b6f5SKishon Vijay Abraham I } 6535088b6f5SKishon Vijay Abraham I 654d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb2_phy)) { 655d105e7f8SFelipe Balbi ret = PTR_ERR(dwc->usb2_phy); 656122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 657122f06e6SKishon Vijay Abraham I dwc->usb2_phy = NULL; 658122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 659d105e7f8SFelipe Balbi return ret; 660122f06e6SKishon Vijay Abraham I } else { 66151e1e7bcSFelipe Balbi dev_err(dev, "no usb2 phy configured\n"); 662122f06e6SKishon Vijay Abraham I return ret; 663122f06e6SKishon Vijay Abraham I } 66451e1e7bcSFelipe Balbi } 66551e1e7bcSFelipe Balbi 666d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb3_phy)) { 667315955d7SRuchika Kharwar ret = PTR_ERR(dwc->usb3_phy); 668122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 669122f06e6SKishon Vijay Abraham I dwc->usb3_phy = NULL; 670122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 671d105e7f8SFelipe Balbi return ret; 672122f06e6SKishon Vijay Abraham I } else { 67351e1e7bcSFelipe Balbi dev_err(dev, "no usb3 phy configured\n"); 674122f06e6SKishon Vijay Abraham I return ret; 675122f06e6SKishon Vijay Abraham I } 67651e1e7bcSFelipe Balbi } 67751e1e7bcSFelipe Balbi 67857303488SKishon Vijay Abraham I dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); 67957303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb2_generic_phy)) { 68057303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb2_generic_phy); 68157303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 68257303488SKishon Vijay Abraham I dwc->usb2_generic_phy = NULL; 68357303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 68457303488SKishon Vijay Abraham I return ret; 68557303488SKishon Vijay Abraham I } else { 68657303488SKishon Vijay Abraham I dev_err(dev, "no usb2 phy configured\n"); 68757303488SKishon Vijay Abraham I return ret; 68857303488SKishon Vijay Abraham I } 68957303488SKishon Vijay Abraham I } 69057303488SKishon Vijay Abraham I 69157303488SKishon Vijay Abraham I dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy"); 69257303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb3_generic_phy)) { 69357303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb3_generic_phy); 69457303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 69557303488SKishon Vijay Abraham I dwc->usb3_generic_phy = NULL; 69657303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 69757303488SKishon Vijay Abraham I return ret; 69857303488SKishon Vijay Abraham I } else { 69957303488SKishon Vijay Abraham I dev_err(dev, "no usb3 phy configured\n"); 70057303488SKishon Vijay Abraham I return ret; 70157303488SKishon Vijay Abraham I } 70257303488SKishon Vijay Abraham I } 70357303488SKishon Vijay Abraham I 7043c9f94acSFelipe Balbi return 0; 7053c9f94acSFelipe Balbi } 7063c9f94acSFelipe Balbi 7075f94adfeSFelipe Balbi static int dwc3_core_init_mode(struct dwc3 *dwc) 7085f94adfeSFelipe Balbi { 7095f94adfeSFelipe Balbi struct device *dev = dwc->dev; 7105f94adfeSFelipe Balbi int ret; 7115f94adfeSFelipe Balbi 7125f94adfeSFelipe Balbi switch (dwc->dr_mode) { 7135f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 7145f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); 7155f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 7165f94adfeSFelipe Balbi if (ret) { 7175f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 7185f94adfeSFelipe Balbi return ret; 7195f94adfeSFelipe Balbi } 7205f94adfeSFelipe Balbi break; 7215f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 7225f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); 7235f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 7245f94adfeSFelipe Balbi if (ret) { 7255f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 7265f94adfeSFelipe Balbi return ret; 7275f94adfeSFelipe Balbi } 7285f94adfeSFelipe Balbi break; 7295f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 7305f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); 7315f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 7325f94adfeSFelipe Balbi if (ret) { 7335f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 7345f94adfeSFelipe Balbi return ret; 7355f94adfeSFelipe Balbi } 7365f94adfeSFelipe Balbi 7375f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 7385f94adfeSFelipe Balbi if (ret) { 7395f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 7405f94adfeSFelipe Balbi return ret; 7415f94adfeSFelipe Balbi } 7425f94adfeSFelipe Balbi break; 7435f94adfeSFelipe Balbi default: 7445f94adfeSFelipe Balbi dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); 7455f94adfeSFelipe Balbi return -EINVAL; 7465f94adfeSFelipe Balbi } 7475f94adfeSFelipe Balbi 7485f94adfeSFelipe Balbi return 0; 7495f94adfeSFelipe Balbi } 7505f94adfeSFelipe Balbi 7515f94adfeSFelipe Balbi static void dwc3_core_exit_mode(struct dwc3 *dwc) 7525f94adfeSFelipe Balbi { 7535f94adfeSFelipe Balbi switch (dwc->dr_mode) { 7545f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 7555f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 7565f94adfeSFelipe Balbi break; 7575f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 7585f94adfeSFelipe Balbi dwc3_host_exit(dwc); 7595f94adfeSFelipe Balbi break; 7605f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 7615f94adfeSFelipe Balbi dwc3_host_exit(dwc); 7625f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 7635f94adfeSFelipe Balbi break; 7645f94adfeSFelipe Balbi default: 7655f94adfeSFelipe Balbi /* do nothing */ 7665f94adfeSFelipe Balbi break; 7675f94adfeSFelipe Balbi } 7685f94adfeSFelipe Balbi } 7695f94adfeSFelipe Balbi 7703c9f94acSFelipe Balbi #define DWC3_ALIGN_MASK (16 - 1) 7713c9f94acSFelipe Balbi 7723c9f94acSFelipe Balbi static int dwc3_probe(struct platform_device *pdev) 7733c9f94acSFelipe Balbi { 7743c9f94acSFelipe Balbi struct device *dev = &pdev->dev; 7753c9f94acSFelipe Balbi struct dwc3_platform_data *pdata = dev_get_platdata(dev); 7763c9f94acSFelipe Balbi struct device_node *node = dev->of_node; 7773c9f94acSFelipe Balbi struct resource *res; 7783c9f94acSFelipe Balbi struct dwc3 *dwc; 77980caf7d2SHuang Rui u8 lpm_nyet_threshold; 7806b6a0c9aSHuang Rui u8 tx_de_emphasis; 781460d098cSHuang Rui u8 hird_threshold; 7823c9f94acSFelipe Balbi 783b09e99eeSAndy Shevchenko int ret; 7843c9f94acSFelipe Balbi 7853c9f94acSFelipe Balbi void __iomem *regs; 7863c9f94acSFelipe Balbi void *mem; 7873c9f94acSFelipe Balbi 7883c9f94acSFelipe Balbi mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 789734d5a53SJingoo Han if (!mem) 7903c9f94acSFelipe Balbi return -ENOMEM; 791734d5a53SJingoo Han 7923c9f94acSFelipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 7933c9f94acSFelipe Balbi dwc->mem = mem; 7943c9f94acSFelipe Balbi dwc->dev = dev; 7953c9f94acSFelipe Balbi 7963c9f94acSFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 7973c9f94acSFelipe Balbi if (!res) { 7983c9f94acSFelipe Balbi dev_err(dev, "missing IRQ\n"); 7993c9f94acSFelipe Balbi return -ENODEV; 8003c9f94acSFelipe Balbi } 8013c9f94acSFelipe Balbi dwc->xhci_resources[1].start = res->start; 8023c9f94acSFelipe Balbi dwc->xhci_resources[1].end = res->end; 8033c9f94acSFelipe Balbi dwc->xhci_resources[1].flags = res->flags; 8043c9f94acSFelipe Balbi dwc->xhci_resources[1].name = res->name; 8053c9f94acSFelipe Balbi 8063c9f94acSFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 8073c9f94acSFelipe Balbi if (!res) { 8083c9f94acSFelipe Balbi dev_err(dev, "missing memory resource\n"); 8093c9f94acSFelipe Balbi return -ENODEV; 8103c9f94acSFelipe Balbi } 8113c9f94acSFelipe Balbi 812f32a5e23SVivek Gautam dwc->xhci_resources[0].start = res->start; 813f32a5e23SVivek Gautam dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 814f32a5e23SVivek Gautam DWC3_XHCI_REGS_END; 815f32a5e23SVivek Gautam dwc->xhci_resources[0].flags = res->flags; 816f32a5e23SVivek Gautam dwc->xhci_resources[0].name = res->name; 817f32a5e23SVivek Gautam 818f32a5e23SVivek Gautam res->start += DWC3_GLOBALS_REGS_START; 819f32a5e23SVivek Gautam 820f32a5e23SVivek Gautam /* 821f32a5e23SVivek Gautam * Request memory region but exclude xHCI regs, 822f32a5e23SVivek Gautam * since it will be requested by the xhci-plat driver. 823f32a5e23SVivek Gautam */ 824f32a5e23SVivek Gautam regs = devm_ioremap_resource(dev, res); 8253da1f6eeSFelipe Balbi if (IS_ERR(regs)) { 8263da1f6eeSFelipe Balbi ret = PTR_ERR(regs); 8273da1f6eeSFelipe Balbi goto err0; 8283da1f6eeSFelipe Balbi } 829f32a5e23SVivek Gautam 830f32a5e23SVivek Gautam dwc->regs = regs; 831f32a5e23SVivek Gautam dwc->regs_size = resource_size(res); 832f32a5e23SVivek Gautam 83380caf7d2SHuang Rui /* default to highest possible threshold */ 83480caf7d2SHuang Rui lpm_nyet_threshold = 0xff; 83580caf7d2SHuang Rui 8366b6a0c9aSHuang Rui /* default to -3.5dB de-emphasis */ 8376b6a0c9aSHuang Rui tx_de_emphasis = 1; 8386b6a0c9aSHuang Rui 839460d098cSHuang Rui /* 840460d098cSHuang Rui * default to assert utmi_sleep_n and use maximum allowed HIRD 841460d098cSHuang Rui * threshold value of 0b1100 842460d098cSHuang Rui */ 843460d098cSHuang Rui hird_threshold = 12; 844460d098cSHuang Rui 8453c9f94acSFelipe Balbi if (node) { 8463c9f94acSFelipe Balbi dwc->maximum_speed = of_usb_get_maximum_speed(node); 84780caf7d2SHuang Rui dwc->has_lpm_erratum = of_property_read_bool(node, 84880caf7d2SHuang Rui "snps,has-lpm-erratum"); 84980caf7d2SHuang Rui of_property_read_u8(node, "snps,lpm-nyet-threshold", 85080caf7d2SHuang Rui &lpm_nyet_threshold); 851460d098cSHuang Rui dwc->is_utmi_l1_suspend = of_property_read_bool(node, 852460d098cSHuang Rui "snps,is-utmi-l1-suspend"); 853460d098cSHuang Rui of_property_read_u8(node, "snps,hird-threshold", 854460d098cSHuang Rui &hird_threshold); 855eac68e8fSRobert Baldyga dwc->usb3_lpm_capable = of_property_read_bool(node, 856eac68e8fSRobert Baldyga "snps,usb3_lpm_capable"); 8573c9f94acSFelipe Balbi 85880caf7d2SHuang Rui dwc->needs_fifo_resize = of_property_read_bool(node, 85980caf7d2SHuang Rui "tx-fifo-resize"); 8603c9f94acSFelipe Balbi dwc->dr_mode = of_usb_get_dr_mode(node); 8613b81221aSHuang Rui 8623b81221aSHuang Rui dwc->disable_scramble_quirk = of_property_read_bool(node, 8633b81221aSHuang Rui "snps,disable_scramble_quirk"); 8649a5b2f31SHuang Rui dwc->u2exit_lfps_quirk = of_property_read_bool(node, 8659a5b2f31SHuang Rui "snps,u2exit_lfps_quirk"); 866b5a65c40SHuang Rui dwc->u2ss_inp3_quirk = of_property_read_bool(node, 867b5a65c40SHuang Rui "snps,u2ss_inp3_quirk"); 868df31f5b3SHuang Rui dwc->req_p1p2p3_quirk = of_property_read_bool(node, 869df31f5b3SHuang Rui "snps,req_p1p2p3_quirk"); 870a2a1d0f5SHuang Rui dwc->del_p1p2p3_quirk = of_property_read_bool(node, 871a2a1d0f5SHuang Rui "snps,del_p1p2p3_quirk"); 87241c06ffdSHuang Rui dwc->del_phy_power_chg_quirk = of_property_read_bool(node, 87341c06ffdSHuang Rui "snps,del_phy_power_chg_quirk"); 874fb67afcaSHuang Rui dwc->lfps_filter_quirk = of_property_read_bool(node, 875fb67afcaSHuang Rui "snps,lfps_filter_quirk"); 87614f4ac53SHuang Rui dwc->rx_detect_poll_quirk = of_property_read_bool(node, 87714f4ac53SHuang Rui "snps,rx_detect_poll_quirk"); 87859acfa20SHuang Rui dwc->dis_u3_susphy_quirk = of_property_read_bool(node, 87959acfa20SHuang Rui "snps,dis_u3_susphy_quirk"); 8800effe0a3SHuang Rui dwc->dis_u2_susphy_quirk = of_property_read_bool(node, 8810effe0a3SHuang Rui "snps,dis_u2_susphy_quirk"); 8826b6a0c9aSHuang Rui 8836b6a0c9aSHuang Rui dwc->tx_de_emphasis_quirk = of_property_read_bool(node, 8846b6a0c9aSHuang Rui "snps,tx_de_emphasis_quirk"); 8856b6a0c9aSHuang Rui of_property_read_u8(node, "snps,tx_de_emphasis", 8866b6a0c9aSHuang Rui &tx_de_emphasis); 8873e10a2ceSHeikki Krogerus of_property_read_string(node, "snps,hsphy_interface", 8883e10a2ceSHeikki Krogerus &dwc->hsphy_interface); 8893c9f94acSFelipe Balbi } else if (pdata) { 8903c9f94acSFelipe Balbi dwc->maximum_speed = pdata->maximum_speed; 89180caf7d2SHuang Rui dwc->has_lpm_erratum = pdata->has_lpm_erratum; 89280caf7d2SHuang Rui if (pdata->lpm_nyet_threshold) 89380caf7d2SHuang Rui lpm_nyet_threshold = pdata->lpm_nyet_threshold; 894460d098cSHuang Rui dwc->is_utmi_l1_suspend = pdata->is_utmi_l1_suspend; 895460d098cSHuang Rui if (pdata->hird_threshold) 896460d098cSHuang Rui hird_threshold = pdata->hird_threshold; 8973c9f94acSFelipe Balbi 8983c9f94acSFelipe Balbi dwc->needs_fifo_resize = pdata->tx_fifo_resize; 899eac68e8fSRobert Baldyga dwc->usb3_lpm_capable = pdata->usb3_lpm_capable; 9003c9f94acSFelipe Balbi dwc->dr_mode = pdata->dr_mode; 9013b81221aSHuang Rui 9023b81221aSHuang Rui dwc->disable_scramble_quirk = pdata->disable_scramble_quirk; 9039a5b2f31SHuang Rui dwc->u2exit_lfps_quirk = pdata->u2exit_lfps_quirk; 904b5a65c40SHuang Rui dwc->u2ss_inp3_quirk = pdata->u2ss_inp3_quirk; 905df31f5b3SHuang Rui dwc->req_p1p2p3_quirk = pdata->req_p1p2p3_quirk; 906a2a1d0f5SHuang Rui dwc->del_p1p2p3_quirk = pdata->del_p1p2p3_quirk; 90741c06ffdSHuang Rui dwc->del_phy_power_chg_quirk = pdata->del_phy_power_chg_quirk; 908fb67afcaSHuang Rui dwc->lfps_filter_quirk = pdata->lfps_filter_quirk; 90914f4ac53SHuang Rui dwc->rx_detect_poll_quirk = pdata->rx_detect_poll_quirk; 91059acfa20SHuang Rui dwc->dis_u3_susphy_quirk = pdata->dis_u3_susphy_quirk; 9110effe0a3SHuang Rui dwc->dis_u2_susphy_quirk = pdata->dis_u2_susphy_quirk; 9126b6a0c9aSHuang Rui 9136b6a0c9aSHuang Rui dwc->tx_de_emphasis_quirk = pdata->tx_de_emphasis_quirk; 9146b6a0c9aSHuang Rui if (pdata->tx_de_emphasis) 9156b6a0c9aSHuang Rui tx_de_emphasis = pdata->tx_de_emphasis; 9163e10a2ceSHeikki Krogerus 9173e10a2ceSHeikki Krogerus dwc->hsphy_interface = pdata->hsphy_interface; 9183c9f94acSFelipe Balbi } 9193c9f94acSFelipe Balbi 9203c9f94acSFelipe Balbi /* default to superspeed if no maximum_speed passed */ 9213c9f94acSFelipe Balbi if (dwc->maximum_speed == USB_SPEED_UNKNOWN) 9223c9f94acSFelipe Balbi dwc->maximum_speed = USB_SPEED_SUPER; 9233c9f94acSFelipe Balbi 92480caf7d2SHuang Rui dwc->lpm_nyet_threshold = lpm_nyet_threshold; 9256b6a0c9aSHuang Rui dwc->tx_de_emphasis = tx_de_emphasis; 92680caf7d2SHuang Rui 927460d098cSHuang Rui dwc->hird_threshold = hird_threshold 928460d098cSHuang Rui | (dwc->is_utmi_l1_suspend << 4); 929460d098cSHuang Rui 9306c89cce0SHeikki Krogerus platform_set_drvdata(pdev, dwc); 9312917e718SHeikki Krogerus dwc3_cache_hwparams(dwc); 9326c89cce0SHeikki Krogerus 93388bc9d19SHeikki Krogerus ret = dwc3_phy_setup(dwc); 93488bc9d19SHeikki Krogerus if (ret) 93588bc9d19SHeikki Krogerus goto err0; 93645bb7de2SHeikki Krogerus 9373c9f94acSFelipe Balbi ret = dwc3_core_get_phy(dwc); 9383c9f94acSFelipe Balbi if (ret) 9393da1f6eeSFelipe Balbi goto err0; 9403c9f94acSFelipe Balbi 94172246da4SFelipe Balbi spin_lock_init(&dwc->lock); 94272246da4SFelipe Balbi 94319bacdc9SHeikki Krogerus if (!dev->dma_mask) { 944ddff14f1SKishon Vijay Abraham I dev->dma_mask = dev->parent->dma_mask; 945ddff14f1SKishon Vijay Abraham I dev->dma_parms = dev->parent->dma_parms; 946ddff14f1SKishon Vijay Abraham I dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); 94719bacdc9SHeikki Krogerus } 948ddff14f1SKishon Vijay Abraham I 949802ca850SChanho Park pm_runtime_enable(dev); 950802ca850SChanho Park pm_runtime_get_sync(dev); 951802ca850SChanho Park pm_runtime_forbid(dev); 95272246da4SFelipe Balbi 9533921426bSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 9543921426bSFelipe Balbi if (ret) { 9553921426bSFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 9563921426bSFelipe Balbi ret = -ENOMEM; 9573da1f6eeSFelipe Balbi goto err1; 9583921426bSFelipe Balbi } 9593921426bSFelipe Balbi 96032a4a135SFelipe Balbi if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) 96132a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_HOST; 96232a4a135SFelipe Balbi else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) 96332a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_PERIPHERAL; 96432a4a135SFelipe Balbi 96532a4a135SFelipe Balbi if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) 96632a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_OTG; 96732a4a135SFelipe Balbi 96872246da4SFelipe Balbi ret = dwc3_core_init(dwc); 96972246da4SFelipe Balbi if (ret) { 970802ca850SChanho Park dev_err(dev, "failed to initialize core\n"); 9713da1f6eeSFelipe Balbi goto err1; 97272246da4SFelipe Balbi } 97372246da4SFelipe Balbi 9743088f108SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 0); 9753088f108SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 0); 97657303488SKishon Vijay Abraham I ret = phy_power_on(dwc->usb2_generic_phy); 97757303488SKishon Vijay Abraham I if (ret < 0) 9783da1f6eeSFelipe Balbi goto err2; 97957303488SKishon Vijay Abraham I 98057303488SKishon Vijay Abraham I ret = phy_power_on(dwc->usb3_generic_phy); 98157303488SKishon Vijay Abraham I if (ret < 0) 9823da1f6eeSFelipe Balbi goto err3; 9833088f108SKishon Vijay Abraham I 984f122d33eSFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 985f122d33eSFelipe Balbi if (ret) { 986f122d33eSFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 9873da1f6eeSFelipe Balbi goto err4; 988f122d33eSFelipe Balbi } 989f122d33eSFelipe Balbi 9905f94adfeSFelipe Balbi ret = dwc3_core_init_mode(dwc); 9915f94adfeSFelipe Balbi if (ret) 9923da1f6eeSFelipe Balbi goto err5; 99372246da4SFelipe Balbi 99472246da4SFelipe Balbi ret = dwc3_debugfs_init(dwc); 99572246da4SFelipe Balbi if (ret) { 996802ca850SChanho Park dev_err(dev, "failed to initialize debugfs\n"); 9973da1f6eeSFelipe Balbi goto err6; 99872246da4SFelipe Balbi } 99972246da4SFelipe Balbi 1000802ca850SChanho Park pm_runtime_allow(dev); 100172246da4SFelipe Balbi 100272246da4SFelipe Balbi return 0; 100372246da4SFelipe Balbi 10043da1f6eeSFelipe Balbi err6: 10055f94adfeSFelipe Balbi dwc3_core_exit_mode(dwc); 100672246da4SFelipe Balbi 10073da1f6eeSFelipe Balbi err5: 1008f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 1009f122d33eSFelipe Balbi 10103da1f6eeSFelipe Balbi err4: 101157303488SKishon Vijay Abraham I phy_power_off(dwc->usb3_generic_phy); 101257303488SKishon Vijay Abraham I 10133da1f6eeSFelipe Balbi err3: 101457303488SKishon Vijay Abraham I phy_power_off(dwc->usb2_generic_phy); 101557303488SKishon Vijay Abraham I 10163da1f6eeSFelipe Balbi err2: 1017501fae51SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 1); 1018501fae51SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 1); 101972246da4SFelipe Balbi dwc3_core_exit(dwc); 102072246da4SFelipe Balbi 10213da1f6eeSFelipe Balbi err1: 10223921426bSFelipe Balbi dwc3_free_event_buffers(dwc); 102388bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 10243921426bSFelipe Balbi 10253da1f6eeSFelipe Balbi err0: 10263da1f6eeSFelipe Balbi /* 10273da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 10283da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 10293da1f6eeSFelipe Balbi * memory region the next time probe is called. 10303da1f6eeSFelipe Balbi */ 10313da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 10323da1f6eeSFelipe Balbi 103372246da4SFelipe Balbi return ret; 103472246da4SFelipe Balbi } 103572246da4SFelipe Balbi 1036fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev) 103772246da4SFelipe Balbi { 103872246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 10393da1f6eeSFelipe Balbi struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 10403da1f6eeSFelipe Balbi 10413da1f6eeSFelipe Balbi /* 10423da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 10433da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 10443da1f6eeSFelipe Balbi * memory region the next time probe is called. 10453da1f6eeSFelipe Balbi */ 10463da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 104772246da4SFelipe Balbi 1048dc99f16fSFelipe Balbi dwc3_debugfs_exit(dwc); 1049dc99f16fSFelipe Balbi dwc3_core_exit_mode(dwc); 1050dc99f16fSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 1051dc99f16fSFelipe Balbi dwc3_free_event_buffers(dwc); 1052dc99f16fSFelipe Balbi 10538ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 1); 10548ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 1); 105557303488SKishon Vijay Abraham I phy_power_off(dwc->usb2_generic_phy); 105657303488SKishon Vijay Abraham I phy_power_off(dwc->usb3_generic_phy); 10578ba007a9SKishon Vijay Abraham I 105872246da4SFelipe Balbi dwc3_core_exit(dwc); 105988bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 106072246da4SFelipe Balbi 10617415f17cSFelipe Balbi pm_runtime_put_sync(&pdev->dev); 10627415f17cSFelipe Balbi pm_runtime_disable(&pdev->dev); 10637415f17cSFelipe Balbi 106472246da4SFelipe Balbi return 0; 106572246da4SFelipe Balbi } 106672246da4SFelipe Balbi 10677415f17cSFelipe Balbi #ifdef CONFIG_PM_SLEEP 10687415f17cSFelipe Balbi static int dwc3_suspend(struct device *dev) 10697415f17cSFelipe Balbi { 10707415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 10717415f17cSFelipe Balbi unsigned long flags; 10727415f17cSFelipe Balbi 10737415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 10747415f17cSFelipe Balbi 1075a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 1076a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 1077a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 10787415f17cSFelipe Balbi dwc3_gadget_suspend(dwc); 10797415f17cSFelipe Balbi /* FALLTHROUGH */ 1080a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 10817415f17cSFelipe Balbi default: 10820b0231aaSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 10837415f17cSFelipe Balbi break; 10847415f17cSFelipe Balbi } 10857415f17cSFelipe Balbi 10867415f17cSFelipe Balbi dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL); 10877415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 10887415f17cSFelipe Balbi 10897415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 10907415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 109157303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 109257303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 10937415f17cSFelipe Balbi 10947415f17cSFelipe Balbi return 0; 10957415f17cSFelipe Balbi } 10967415f17cSFelipe Balbi 10977415f17cSFelipe Balbi static int dwc3_resume(struct device *dev) 10987415f17cSFelipe Balbi { 10997415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 11007415f17cSFelipe Balbi unsigned long flags; 110157303488SKishon Vijay Abraham I int ret; 11027415f17cSFelipe Balbi 11037415f17cSFelipe Balbi usb_phy_init(dwc->usb3_phy); 11047415f17cSFelipe Balbi usb_phy_init(dwc->usb2_phy); 110557303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 110657303488SKishon Vijay Abraham I if (ret < 0) 110757303488SKishon Vijay Abraham I return ret; 110857303488SKishon Vijay Abraham I 110957303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 111057303488SKishon Vijay Abraham I if (ret < 0) 111157303488SKishon Vijay Abraham I goto err_usb2phy_init; 11127415f17cSFelipe Balbi 11137415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 11147415f17cSFelipe Balbi 11150b0231aaSFelipe Balbi dwc3_event_buffers_setup(dwc); 11167415f17cSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl); 11177415f17cSFelipe Balbi 1118a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 1119a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 1120a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 11217415f17cSFelipe Balbi dwc3_gadget_resume(dwc); 11227415f17cSFelipe Balbi /* FALLTHROUGH */ 1123a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 11247415f17cSFelipe Balbi default: 11257415f17cSFelipe Balbi /* do nothing */ 11267415f17cSFelipe Balbi break; 11277415f17cSFelipe Balbi } 11287415f17cSFelipe Balbi 11297415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 11307415f17cSFelipe Balbi 11317415f17cSFelipe Balbi pm_runtime_disable(dev); 11327415f17cSFelipe Balbi pm_runtime_set_active(dev); 11337415f17cSFelipe Balbi pm_runtime_enable(dev); 11347415f17cSFelipe Balbi 11357415f17cSFelipe Balbi return 0; 113657303488SKishon Vijay Abraham I 113757303488SKishon Vijay Abraham I err_usb2phy_init: 113857303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 113957303488SKishon Vijay Abraham I 114057303488SKishon Vijay Abraham I return ret; 11417415f17cSFelipe Balbi } 11427415f17cSFelipe Balbi 11437415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = { 11447415f17cSFelipe Balbi SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 11457415f17cSFelipe Balbi }; 11467415f17cSFelipe Balbi 11477415f17cSFelipe Balbi #define DWC3_PM_OPS &(dwc3_dev_pm_ops) 11487415f17cSFelipe Balbi #else 11497415f17cSFelipe Balbi #define DWC3_PM_OPS NULL 11507415f17cSFelipe Balbi #endif 11517415f17cSFelipe Balbi 11525088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF 11535088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = { 11545088b6f5SKishon Vijay Abraham I { 115522a5aa17SFelipe Balbi .compatible = "snps,dwc3" 115622a5aa17SFelipe Balbi }, 115722a5aa17SFelipe Balbi { 11585088b6f5SKishon Vijay Abraham I .compatible = "synopsys,dwc3" 11595088b6f5SKishon Vijay Abraham I }, 11605088b6f5SKishon Vijay Abraham I { }, 11615088b6f5SKishon Vijay Abraham I }; 11625088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match); 11635088b6f5SKishon Vijay Abraham I #endif 11645088b6f5SKishon Vijay Abraham I 1165404905a6SHeikki Krogerus #ifdef CONFIG_ACPI 1166404905a6SHeikki Krogerus 1167404905a6SHeikki Krogerus #define ACPI_ID_INTEL_BSW "808622B7" 1168404905a6SHeikki Krogerus 1169404905a6SHeikki Krogerus static const struct acpi_device_id dwc3_acpi_match[] = { 1170404905a6SHeikki Krogerus { ACPI_ID_INTEL_BSW, 0 }, 1171404905a6SHeikki Krogerus { }, 1172404905a6SHeikki Krogerus }; 1173404905a6SHeikki Krogerus MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match); 1174404905a6SHeikki Krogerus #endif 1175404905a6SHeikki Krogerus 117672246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 117772246da4SFelipe Balbi .probe = dwc3_probe, 11787690417dSBill Pemberton .remove = dwc3_remove, 117972246da4SFelipe Balbi .driver = { 118072246da4SFelipe Balbi .name = "dwc3", 11815088b6f5SKishon Vijay Abraham I .of_match_table = of_match_ptr(of_dwc3_match), 1182404905a6SHeikki Krogerus .acpi_match_table = ACPI_PTR(dwc3_acpi_match), 11837415f17cSFelipe Balbi .pm = DWC3_PM_OPS, 118472246da4SFelipe Balbi }, 118572246da4SFelipe Balbi }; 118672246da4SFelipe Balbi 1187b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 1188b1116dccSTobias Klauser 11897ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 119072246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 11915945f789SFelipe Balbi MODULE_LICENSE("GPL v2"); 119272246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 1193