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> 376344475fSSekhar Nori #include <linux/pinctrl/consumer.h> 3872246da4SFelipe Balbi 3972246da4SFelipe Balbi #include <linux/usb/ch9.h> 4072246da4SFelipe Balbi #include <linux/usb/gadget.h> 41f7e846f0SFelipe Balbi #include <linux/usb/of.h> 42a45c82b8SRuchika Kharwar #include <linux/usb/otg.h> 4372246da4SFelipe Balbi 446462cbd5SFelipe Balbi #include "platform_data.h" 4572246da4SFelipe Balbi #include "core.h" 4672246da4SFelipe Balbi #include "gadget.h" 4772246da4SFelipe Balbi #include "io.h" 4872246da4SFelipe Balbi 4972246da4SFelipe Balbi #include "debug.h" 5072246da4SFelipe Balbi 518300dd23SFelipe Balbi /* -------------------------------------------------------------------------- */ 528300dd23SFelipe Balbi 533140e8cbSSebastian Andrzej Siewior void dwc3_set_mode(struct dwc3 *dwc, u32 mode) 543140e8cbSSebastian Andrzej Siewior { 553140e8cbSSebastian Andrzej Siewior u32 reg; 563140e8cbSSebastian Andrzej Siewior 573140e8cbSSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 583140e8cbSSebastian Andrzej Siewior reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); 593140e8cbSSebastian Andrzej Siewior reg |= DWC3_GCTL_PRTCAPDIR(mode); 603140e8cbSSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 613140e8cbSSebastian Andrzej Siewior } 628300dd23SFelipe Balbi 6372246da4SFelipe Balbi /** 6472246da4SFelipe Balbi * dwc3_core_soft_reset - Issues core soft reset and PHY reset 6572246da4SFelipe Balbi * @dwc: pointer to our context structure 6672246da4SFelipe Balbi */ 6757303488SKishon Vijay Abraham I static int dwc3_core_soft_reset(struct dwc3 *dwc) 6872246da4SFelipe Balbi { 6972246da4SFelipe Balbi u32 reg; 7057303488SKishon Vijay Abraham I int ret; 7172246da4SFelipe Balbi 7272246da4SFelipe Balbi /* Before Resetting PHY, put Core in Reset */ 7372246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 7472246da4SFelipe Balbi reg |= DWC3_GCTL_CORESOFTRESET; 7572246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 7672246da4SFelipe Balbi 7772246da4SFelipe Balbi /* Assert USB3 PHY reset */ 7872246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 7972246da4SFelipe Balbi reg |= DWC3_GUSB3PIPECTL_PHYSOFTRST; 8072246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 8172246da4SFelipe Balbi 8272246da4SFelipe Balbi /* Assert USB2 PHY reset */ 8372246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 8472246da4SFelipe Balbi reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; 8572246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 8672246da4SFelipe Balbi 8751e1e7bcSFelipe Balbi usb_phy_init(dwc->usb2_phy); 8851e1e7bcSFelipe Balbi usb_phy_init(dwc->usb3_phy); 8957303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 9057303488SKishon Vijay Abraham I if (ret < 0) 9157303488SKishon Vijay Abraham I return ret; 9257303488SKishon Vijay Abraham I 9357303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 9457303488SKishon Vijay Abraham I if (ret < 0) { 9557303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 9657303488SKishon Vijay Abraham I return ret; 9757303488SKishon Vijay Abraham I } 9872246da4SFelipe Balbi mdelay(100); 9972246da4SFelipe Balbi 10072246da4SFelipe Balbi /* Clear USB3 PHY reset */ 10172246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 10272246da4SFelipe Balbi reg &= ~DWC3_GUSB3PIPECTL_PHYSOFTRST; 10372246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 10472246da4SFelipe Balbi 10572246da4SFelipe Balbi /* Clear USB2 PHY reset */ 10672246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 10772246da4SFelipe Balbi reg &= ~DWC3_GUSB2PHYCFG_PHYSOFTRST; 10872246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 10972246da4SFelipe Balbi 11045627ac6SPratyush Anand mdelay(100); 11145627ac6SPratyush Anand 11272246da4SFelipe Balbi /* After PHYs are stable we can take Core out of reset state */ 11372246da4SFelipe Balbi reg = dwc3_readl(dwc->regs, DWC3_GCTL); 11472246da4SFelipe Balbi reg &= ~DWC3_GCTL_CORESOFTRESET; 11572246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, reg); 11657303488SKishon Vijay Abraham I 11757303488SKishon Vijay Abraham I return 0; 11872246da4SFelipe Balbi } 11972246da4SFelipe Balbi 12072246da4SFelipe Balbi /** 121c5cc74e8SHeikki Krogerus * dwc3_soft_reset - Issue soft reset 122c5cc74e8SHeikki Krogerus * @dwc: Pointer to our controller context structure 123c5cc74e8SHeikki Krogerus */ 124c5cc74e8SHeikki Krogerus static int dwc3_soft_reset(struct dwc3 *dwc) 125c5cc74e8SHeikki Krogerus { 126c5cc74e8SHeikki Krogerus unsigned long timeout; 127c5cc74e8SHeikki Krogerus u32 reg; 128c5cc74e8SHeikki Krogerus 129c5cc74e8SHeikki Krogerus timeout = jiffies + msecs_to_jiffies(500); 130c5cc74e8SHeikki Krogerus dwc3_writel(dwc->regs, DWC3_DCTL, DWC3_DCTL_CSFTRST); 131c5cc74e8SHeikki Krogerus do { 132c5cc74e8SHeikki Krogerus reg = dwc3_readl(dwc->regs, DWC3_DCTL); 133c5cc74e8SHeikki Krogerus if (!(reg & DWC3_DCTL_CSFTRST)) 134c5cc74e8SHeikki Krogerus break; 135c5cc74e8SHeikki Krogerus 136c5cc74e8SHeikki Krogerus if (time_after(jiffies, timeout)) { 137c5cc74e8SHeikki Krogerus dev_err(dwc->dev, "Reset Timed Out\n"); 138c5cc74e8SHeikki Krogerus return -ETIMEDOUT; 139c5cc74e8SHeikki Krogerus } 140c5cc74e8SHeikki Krogerus 141c5cc74e8SHeikki Krogerus cpu_relax(); 142c5cc74e8SHeikki Krogerus } while (true); 143c5cc74e8SHeikki Krogerus 144c5cc74e8SHeikki Krogerus return 0; 145c5cc74e8SHeikki Krogerus } 146c5cc74e8SHeikki Krogerus 147db2be4e9SNikhil Badola /* 148db2be4e9SNikhil Badola * dwc3_frame_length_adjustment - Adjusts frame length if required 149db2be4e9SNikhil Badola * @dwc3: Pointer to our controller context structure 150db2be4e9SNikhil Badola * @fladj: Value of GFLADJ_30MHZ to adjust frame length 151db2be4e9SNikhil Badola */ 152db2be4e9SNikhil Badola static void dwc3_frame_length_adjustment(struct dwc3 *dwc, u32 fladj) 153db2be4e9SNikhil Badola { 154db2be4e9SNikhil Badola u32 reg; 155db2be4e9SNikhil Badola u32 dft; 156db2be4e9SNikhil Badola 157db2be4e9SNikhil Badola if (dwc->revision < DWC3_REVISION_250A) 158db2be4e9SNikhil Badola return; 159db2be4e9SNikhil Badola 160db2be4e9SNikhil Badola if (fladj == 0) 161db2be4e9SNikhil Badola return; 162db2be4e9SNikhil Badola 163db2be4e9SNikhil Badola reg = dwc3_readl(dwc->regs, DWC3_GFLADJ); 164db2be4e9SNikhil Badola dft = reg & DWC3_GFLADJ_30MHZ_MASK; 165db2be4e9SNikhil Badola if (!dev_WARN_ONCE(dwc->dev, dft == fladj, 166db2be4e9SNikhil Badola "request value same as default, ignoring\n")) { 167db2be4e9SNikhil Badola reg &= ~DWC3_GFLADJ_30MHZ_MASK; 168db2be4e9SNikhil Badola reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | fladj; 169db2be4e9SNikhil Badola dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); 170db2be4e9SNikhil Badola } 171db2be4e9SNikhil Badola } 172db2be4e9SNikhil Badola 173c5cc74e8SHeikki Krogerus /** 17472246da4SFelipe Balbi * dwc3_free_one_event_buffer - Frees one event buffer 17572246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 17672246da4SFelipe Balbi * @evt: Pointer to event buffer to be freed 17772246da4SFelipe Balbi */ 17872246da4SFelipe Balbi static void dwc3_free_one_event_buffer(struct dwc3 *dwc, 17972246da4SFelipe Balbi struct dwc3_event_buffer *evt) 18072246da4SFelipe Balbi { 18172246da4SFelipe Balbi dma_free_coherent(dwc->dev, evt->length, evt->buf, evt->dma); 18272246da4SFelipe Balbi } 18372246da4SFelipe Balbi 18472246da4SFelipe Balbi /** 1851d046793SPaul Zimmerman * dwc3_alloc_one_event_buffer - Allocates one event buffer structure 18672246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 18772246da4SFelipe Balbi * @length: size of the event buffer 18872246da4SFelipe Balbi * 1891d046793SPaul Zimmerman * Returns a pointer to the allocated event buffer structure on success 19072246da4SFelipe Balbi * otherwise ERR_PTR(errno). 19172246da4SFelipe Balbi */ 19267d0b500SFelipe Balbi static struct dwc3_event_buffer *dwc3_alloc_one_event_buffer(struct dwc3 *dwc, 19367d0b500SFelipe Balbi unsigned length) 19472246da4SFelipe Balbi { 19572246da4SFelipe Balbi struct dwc3_event_buffer *evt; 19672246da4SFelipe Balbi 197380f0d28SFelipe Balbi evt = devm_kzalloc(dwc->dev, sizeof(*evt), GFP_KERNEL); 19872246da4SFelipe Balbi if (!evt) 19972246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 20072246da4SFelipe Balbi 20172246da4SFelipe Balbi evt->dwc = dwc; 20272246da4SFelipe Balbi evt->length = length; 20372246da4SFelipe Balbi evt->buf = dma_alloc_coherent(dwc->dev, length, 20472246da4SFelipe Balbi &evt->dma, GFP_KERNEL); 205e32672f0SFelipe Balbi if (!evt->buf) 20672246da4SFelipe Balbi return ERR_PTR(-ENOMEM); 20772246da4SFelipe Balbi 20872246da4SFelipe Balbi return evt; 20972246da4SFelipe Balbi } 21072246da4SFelipe Balbi 21172246da4SFelipe Balbi /** 21272246da4SFelipe Balbi * dwc3_free_event_buffers - frees all allocated event buffers 21372246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 21472246da4SFelipe Balbi */ 21572246da4SFelipe Balbi static void dwc3_free_event_buffers(struct dwc3 *dwc) 21672246da4SFelipe Balbi { 21772246da4SFelipe Balbi struct dwc3_event_buffer *evt; 21872246da4SFelipe Balbi int i; 21972246da4SFelipe Balbi 2209f622b2aSFelipe Balbi for (i = 0; i < dwc->num_event_buffers; i++) { 22172246da4SFelipe Balbi evt = dwc->ev_buffs[i]; 22264b6c8a7SAnton Tikhomirov if (evt) 22372246da4SFelipe Balbi dwc3_free_one_event_buffer(dwc, evt); 22472246da4SFelipe Balbi } 22572246da4SFelipe Balbi } 22672246da4SFelipe Balbi 22772246da4SFelipe Balbi /** 22872246da4SFelipe Balbi * dwc3_alloc_event_buffers - Allocates @num event buffers of size @length 2291d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 23072246da4SFelipe Balbi * @length: size of event buffer 23172246da4SFelipe Balbi * 2321d046793SPaul Zimmerman * Returns 0 on success otherwise negative errno. In the error case, dwc 23372246da4SFelipe Balbi * may contain some buffers allocated but not all which were requested. 23472246da4SFelipe Balbi */ 23541ac7b3aSBill Pemberton static int dwc3_alloc_event_buffers(struct dwc3 *dwc, unsigned length) 23672246da4SFelipe Balbi { 2379f622b2aSFelipe Balbi int num; 23872246da4SFelipe Balbi int i; 23972246da4SFelipe Balbi 2409f622b2aSFelipe Balbi num = DWC3_NUM_INT(dwc->hwparams.hwparams1); 2419f622b2aSFelipe Balbi dwc->num_event_buffers = num; 2429f622b2aSFelipe Balbi 243380f0d28SFelipe Balbi dwc->ev_buffs = devm_kzalloc(dwc->dev, sizeof(*dwc->ev_buffs) * num, 244380f0d28SFelipe Balbi GFP_KERNEL); 245734d5a53SJingoo Han if (!dwc->ev_buffs) 246457d3f21SFelipe Balbi return -ENOMEM; 247457d3f21SFelipe Balbi 24872246da4SFelipe Balbi for (i = 0; i < num; i++) { 24972246da4SFelipe Balbi struct dwc3_event_buffer *evt; 25072246da4SFelipe Balbi 25172246da4SFelipe Balbi evt = dwc3_alloc_one_event_buffer(dwc, length); 25272246da4SFelipe Balbi if (IS_ERR(evt)) { 25372246da4SFelipe Balbi dev_err(dwc->dev, "can't allocate event buffer\n"); 25472246da4SFelipe Balbi return PTR_ERR(evt); 25572246da4SFelipe Balbi } 25672246da4SFelipe Balbi dwc->ev_buffs[i] = evt; 25772246da4SFelipe Balbi } 25872246da4SFelipe Balbi 25972246da4SFelipe Balbi return 0; 26072246da4SFelipe Balbi } 26172246da4SFelipe Balbi 26272246da4SFelipe Balbi /** 26372246da4SFelipe Balbi * dwc3_event_buffers_setup - setup our allocated event buffers 2641d046793SPaul Zimmerman * @dwc: pointer to our controller context structure 26572246da4SFelipe Balbi * 26672246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 26772246da4SFelipe Balbi */ 2687acd85e0SPaul Zimmerman static int dwc3_event_buffers_setup(struct dwc3 *dwc) 26972246da4SFelipe Balbi { 27072246da4SFelipe Balbi struct dwc3_event_buffer *evt; 27172246da4SFelipe Balbi int n; 27272246da4SFelipe Balbi 2739f622b2aSFelipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 27472246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 27572246da4SFelipe Balbi dev_dbg(dwc->dev, "Event buf %p dma %08llx length %d\n", 27672246da4SFelipe Balbi evt->buf, (unsigned long long) evt->dma, 27772246da4SFelipe Balbi evt->length); 27872246da4SFelipe Balbi 2797acd85e0SPaul Zimmerman evt->lpos = 0; 2807acd85e0SPaul Zimmerman 28172246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 28272246da4SFelipe Balbi lower_32_bits(evt->dma)); 28372246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 28472246da4SFelipe Balbi upper_32_bits(evt->dma)); 28572246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 28668d6a01bSFelipe Balbi DWC3_GEVNTSIZ_SIZE(evt->length)); 28772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 28872246da4SFelipe Balbi } 28972246da4SFelipe Balbi 29072246da4SFelipe Balbi return 0; 29172246da4SFelipe Balbi } 29272246da4SFelipe Balbi 29372246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 29472246da4SFelipe Balbi { 29572246da4SFelipe Balbi struct dwc3_event_buffer *evt; 29672246da4SFelipe Balbi int n; 29772246da4SFelipe Balbi 2989f622b2aSFelipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 29972246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 3007acd85e0SPaul Zimmerman 3017acd85e0SPaul Zimmerman evt->lpos = 0; 3027acd85e0SPaul Zimmerman 30372246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); 30472246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); 30568d6a01bSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK 30668d6a01bSFelipe Balbi | DWC3_GEVNTSIZ_SIZE(0)); 30772246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 30872246da4SFelipe Balbi } 30972246da4SFelipe Balbi } 31072246da4SFelipe Balbi 3110ffcaf37SFelipe Balbi static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) 3120ffcaf37SFelipe Balbi { 3130ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3140ffcaf37SFelipe Balbi return 0; 3150ffcaf37SFelipe Balbi 3160ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3170ffcaf37SFelipe Balbi return 0; 3180ffcaf37SFelipe Balbi 3190ffcaf37SFelipe Balbi dwc->scratchbuf = kmalloc_array(dwc->nr_scratch, 3200ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, GFP_KERNEL); 3210ffcaf37SFelipe Balbi if (!dwc->scratchbuf) 3220ffcaf37SFelipe Balbi return -ENOMEM; 3230ffcaf37SFelipe Balbi 3240ffcaf37SFelipe Balbi return 0; 3250ffcaf37SFelipe Balbi } 3260ffcaf37SFelipe Balbi 3270ffcaf37SFelipe Balbi static int dwc3_setup_scratch_buffers(struct dwc3 *dwc) 3280ffcaf37SFelipe Balbi { 3290ffcaf37SFelipe Balbi dma_addr_t scratch_addr; 3300ffcaf37SFelipe Balbi u32 param; 3310ffcaf37SFelipe Balbi int ret; 3320ffcaf37SFelipe Balbi 3330ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3340ffcaf37SFelipe Balbi return 0; 3350ffcaf37SFelipe Balbi 3360ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3370ffcaf37SFelipe Balbi return 0; 3380ffcaf37SFelipe Balbi 3390ffcaf37SFelipe Balbi /* should never fall here */ 3400ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 3410ffcaf37SFelipe Balbi return 0; 3420ffcaf37SFelipe Balbi 3430ffcaf37SFelipe Balbi scratch_addr = dma_map_single(dwc->dev, dwc->scratchbuf, 3440ffcaf37SFelipe Balbi dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, 3450ffcaf37SFelipe Balbi DMA_BIDIRECTIONAL); 3460ffcaf37SFelipe Balbi if (dma_mapping_error(dwc->dev, scratch_addr)) { 3470ffcaf37SFelipe Balbi dev_err(dwc->dev, "failed to map scratch buffer\n"); 3480ffcaf37SFelipe Balbi ret = -EFAULT; 3490ffcaf37SFelipe Balbi goto err0; 3500ffcaf37SFelipe Balbi } 3510ffcaf37SFelipe Balbi 3520ffcaf37SFelipe Balbi dwc->scratch_addr = scratch_addr; 3530ffcaf37SFelipe Balbi 3540ffcaf37SFelipe Balbi param = lower_32_bits(scratch_addr); 3550ffcaf37SFelipe Balbi 3560ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3570ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param); 3580ffcaf37SFelipe Balbi if (ret < 0) 3590ffcaf37SFelipe Balbi goto err1; 3600ffcaf37SFelipe Balbi 3610ffcaf37SFelipe Balbi param = upper_32_bits(scratch_addr); 3620ffcaf37SFelipe Balbi 3630ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3640ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param); 3650ffcaf37SFelipe Balbi if (ret < 0) 3660ffcaf37SFelipe Balbi goto err1; 3670ffcaf37SFelipe Balbi 3680ffcaf37SFelipe Balbi return 0; 3690ffcaf37SFelipe Balbi 3700ffcaf37SFelipe Balbi err1: 3710ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3720ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3730ffcaf37SFelipe Balbi 3740ffcaf37SFelipe Balbi err0: 3750ffcaf37SFelipe Balbi return ret; 3760ffcaf37SFelipe Balbi } 3770ffcaf37SFelipe Balbi 3780ffcaf37SFelipe Balbi static void dwc3_free_scratch_buffers(struct dwc3 *dwc) 3790ffcaf37SFelipe Balbi { 3800ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3810ffcaf37SFelipe Balbi return; 3820ffcaf37SFelipe Balbi 3830ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3840ffcaf37SFelipe Balbi return; 3850ffcaf37SFelipe Balbi 3860ffcaf37SFelipe Balbi /* should never fall here */ 3870ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 3880ffcaf37SFelipe Balbi return; 3890ffcaf37SFelipe Balbi 3900ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3910ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3920ffcaf37SFelipe Balbi kfree(dwc->scratchbuf); 3930ffcaf37SFelipe Balbi } 3940ffcaf37SFelipe Balbi 395789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc) 396789451f6SFelipe Balbi { 397789451f6SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 398789451f6SFelipe Balbi 399789451f6SFelipe Balbi dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); 400789451f6SFelipe Balbi dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; 401789451f6SFelipe Balbi 40273815280SFelipe Balbi dwc3_trace(trace_dwc3_core, "found %d IN and %d OUT endpoints", 403789451f6SFelipe Balbi dwc->num_in_eps, dwc->num_out_eps); 404789451f6SFelipe Balbi } 405789451f6SFelipe Balbi 40641ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc) 40726ceca97SFelipe Balbi { 40826ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 40926ceca97SFelipe Balbi 41026ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 41126ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 41226ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 41326ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 41426ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 41526ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 41626ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 41726ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 41826ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 41926ceca97SFelipe Balbi } 42026ceca97SFelipe Balbi 42172246da4SFelipe Balbi /** 422b5a65c40SHuang Rui * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core 423b5a65c40SHuang Rui * @dwc: Pointer to our controller context structure 42488bc9d19SHeikki Krogerus * 42588bc9d19SHeikki Krogerus * Returns 0 on success. The USB PHY interfaces are configured but not 42688bc9d19SHeikki Krogerus * initialized. The PHY interfaces and the PHYs get initialized together with 42788bc9d19SHeikki Krogerus * the core in dwc3_core_init. 428b5a65c40SHuang Rui */ 42988bc9d19SHeikki Krogerus static int dwc3_phy_setup(struct dwc3 *dwc) 430b5a65c40SHuang Rui { 431b5a65c40SHuang Rui u32 reg; 43288bc9d19SHeikki Krogerus int ret; 433b5a65c40SHuang Rui 434b5a65c40SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 435b5a65c40SHuang Rui 4362164a476SHuang Rui /* 4372164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY 4382164a476SHuang Rui * to '0' during coreConsultant configuration. So default value 4392164a476SHuang Rui * will be '0' when the core is reset. Application needs to set it 4402164a476SHuang Rui * to '1' after the core initialization is completed. 4412164a476SHuang Rui */ 4422164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 4432164a476SHuang Rui reg |= DWC3_GUSB3PIPECTL_SUSPHY; 4442164a476SHuang Rui 445b5a65c40SHuang Rui if (dwc->u2ss_inp3_quirk) 446b5a65c40SHuang Rui reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; 447b5a65c40SHuang Rui 448df31f5b3SHuang Rui if (dwc->req_p1p2p3_quirk) 449df31f5b3SHuang Rui reg |= DWC3_GUSB3PIPECTL_REQP1P2P3; 450df31f5b3SHuang Rui 451a2a1d0f5SHuang Rui if (dwc->del_p1p2p3_quirk) 452a2a1d0f5SHuang Rui reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN; 453a2a1d0f5SHuang Rui 45441c06ffdSHuang Rui if (dwc->del_phy_power_chg_quirk) 45541c06ffdSHuang Rui reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE; 45641c06ffdSHuang Rui 457fb67afcaSHuang Rui if (dwc->lfps_filter_quirk) 458fb67afcaSHuang Rui reg |= DWC3_GUSB3PIPECTL_LFPSFILT; 459fb67afcaSHuang Rui 46014f4ac53SHuang Rui if (dwc->rx_detect_poll_quirk) 46114f4ac53SHuang Rui reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL; 46214f4ac53SHuang Rui 4636b6a0c9aSHuang Rui if (dwc->tx_de_emphasis_quirk) 4646b6a0c9aSHuang Rui reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); 4656b6a0c9aSHuang Rui 466cd72f890SFelipe Balbi if (dwc->dis_u3_susphy_quirk) 46759acfa20SHuang Rui reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 46859acfa20SHuang Rui 469b5a65c40SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 470b5a65c40SHuang Rui 4712164a476SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 4722164a476SHuang Rui 4733e10a2ceSHeikki Krogerus /* Select the HS PHY interface */ 4743e10a2ceSHeikki Krogerus switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) { 4753e10a2ceSHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI: 47643cacb03SFelipe Balbi if (dwc->hsphy_interface && 47743cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "utmi", 4)) { 4783e10a2ceSHeikki Krogerus reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI; 47988bc9d19SHeikki Krogerus break; 48043cacb03SFelipe Balbi } else if (dwc->hsphy_interface && 48143cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "ulpi", 4)) { 4823e10a2ceSHeikki Krogerus reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI; 48388bc9d19SHeikki Krogerus dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 4843e10a2ceSHeikki Krogerus } else { 48588bc9d19SHeikki Krogerus /* Relying on default value. */ 48688bc9d19SHeikki Krogerus if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) 4873e10a2ceSHeikki Krogerus break; 4883e10a2ceSHeikki Krogerus } 4893e10a2ceSHeikki Krogerus /* FALLTHROUGH */ 49088bc9d19SHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: 49188bc9d19SHeikki Krogerus /* Making sure the interface and PHY are operational */ 49288bc9d19SHeikki Krogerus ret = dwc3_soft_reset(dwc); 49388bc9d19SHeikki Krogerus if (ret) 49488bc9d19SHeikki Krogerus return ret; 49588bc9d19SHeikki Krogerus 49688bc9d19SHeikki Krogerus udelay(1); 49788bc9d19SHeikki Krogerus 49888bc9d19SHeikki Krogerus ret = dwc3_ulpi_init(dwc); 49988bc9d19SHeikki Krogerus if (ret) 50088bc9d19SHeikki Krogerus return ret; 50188bc9d19SHeikki Krogerus /* FALLTHROUGH */ 5023e10a2ceSHeikki Krogerus default: 5033e10a2ceSHeikki Krogerus break; 5043e10a2ceSHeikki Krogerus } 5053e10a2ceSHeikki Krogerus 5062164a476SHuang Rui /* 5072164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to 5082164a476SHuang Rui * '0' during coreConsultant configuration. So default value will 5092164a476SHuang Rui * be '0' when the core is reset. Application needs to set it to 5102164a476SHuang Rui * '1' after the core initialization is completed. 5112164a476SHuang Rui */ 5122164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 5132164a476SHuang Rui reg |= DWC3_GUSB2PHYCFG_SUSPHY; 5142164a476SHuang Rui 515cd72f890SFelipe Balbi if (dwc->dis_u2_susphy_quirk) 5160effe0a3SHuang Rui reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 5170effe0a3SHuang Rui 5182164a476SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 51988bc9d19SHeikki Krogerus 52088bc9d19SHeikki Krogerus return 0; 521b5a65c40SHuang Rui } 522b5a65c40SHuang Rui 523b5a65c40SHuang Rui /** 52472246da4SFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 52572246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 52672246da4SFelipe Balbi * 52772246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 52872246da4SFelipe Balbi */ 52941ac7b3aSBill Pemberton static int dwc3_core_init(struct dwc3 *dwc) 53072246da4SFelipe Balbi { 5310ffcaf37SFelipe Balbi u32 hwparams4 = dwc->hwparams.hwparams4; 53272246da4SFelipe Balbi u32 reg; 53372246da4SFelipe Balbi int ret; 53472246da4SFelipe Balbi 5357650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 5367650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 5377650bd74SSebastian Andrzej Siewior if ((reg & DWC3_GSNPSID_MASK) != 0x55330000) { 5387650bd74SSebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 5397650bd74SSebastian Andrzej Siewior ret = -ENODEV; 5407650bd74SSebastian Andrzej Siewior goto err0; 5417650bd74SSebastian Andrzej Siewior } 542248b122bSFelipe Balbi dwc->revision = reg; 5437650bd74SSebastian Andrzej Siewior 544fa0ea13eSFelipe Balbi /* 545fa0ea13eSFelipe Balbi * Write Linux Version Code to our GUID register so it's easy to figure 546fa0ea13eSFelipe Balbi * out which kernel version a bug was found. 547fa0ea13eSFelipe Balbi */ 548fa0ea13eSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); 549fa0ea13eSFelipe Balbi 5500e1e5c47SPaul Zimmerman /* Handle USB2.0-only core configuration */ 5510e1e5c47SPaul Zimmerman if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 5520e1e5c47SPaul Zimmerman DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { 5530e1e5c47SPaul Zimmerman if (dwc->maximum_speed == USB_SPEED_SUPER) 5540e1e5c47SPaul Zimmerman dwc->maximum_speed = USB_SPEED_HIGH; 5550e1e5c47SPaul Zimmerman } 5560e1e5c47SPaul Zimmerman 55772246da4SFelipe Balbi /* issue device SoftReset too */ 558c5cc74e8SHeikki Krogerus ret = dwc3_soft_reset(dwc); 559c5cc74e8SHeikki Krogerus if (ret) 56072246da4SFelipe Balbi goto err0; 56172246da4SFelipe Balbi 56257303488SKishon Vijay Abraham I ret = dwc3_core_soft_reset(dwc); 56357303488SKishon Vijay Abraham I if (ret) 56457303488SKishon Vijay Abraham I goto err0; 56558a0f23fSPratyush Anand 5664878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 5673e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 5684878a028SSebastian Andrzej Siewior 569164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 5704878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 57132a4a135SFelipe Balbi /** 57232a4a135SFelipe Balbi * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an 57332a4a135SFelipe Balbi * issue which would cause xHCI compliance tests to fail. 57432a4a135SFelipe Balbi * 57532a4a135SFelipe Balbi * Because of that we cannot enable clock gating on such 57632a4a135SFelipe Balbi * configurations. 57732a4a135SFelipe Balbi * 57832a4a135SFelipe Balbi * Refers to: 57932a4a135SFelipe Balbi * 58032a4a135SFelipe Balbi * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based 58132a4a135SFelipe Balbi * SOF/ITP Mode Used 58232a4a135SFelipe Balbi */ 58332a4a135SFelipe Balbi if ((dwc->dr_mode == USB_DR_MODE_HOST || 58432a4a135SFelipe Balbi dwc->dr_mode == USB_DR_MODE_OTG) && 58532a4a135SFelipe Balbi (dwc->revision >= DWC3_REVISION_210A && 58632a4a135SFelipe Balbi dwc->revision <= DWC3_REVISION_250A)) 58732a4a135SFelipe Balbi reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; 58832a4a135SFelipe Balbi else 5894878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 5904878a028SSebastian Andrzej Siewior break; 5910ffcaf37SFelipe Balbi case DWC3_GHWPARAMS1_EN_PWROPT_HIB: 5920ffcaf37SFelipe Balbi /* enable hibernation here */ 5930ffcaf37SFelipe Balbi dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); 5942eac3992SHuang Rui 5952eac3992SHuang Rui /* 5962eac3992SHuang Rui * REVISIT Enabling this bit so that host-mode hibernation 5972eac3992SHuang Rui * will work. Device-mode hibernation is not yet implemented. 5982eac3992SHuang Rui */ 5992eac3992SHuang Rui reg |= DWC3_GCTL_GBLHIBERNATIONEN; 6000ffcaf37SFelipe Balbi break; 6014878a028SSebastian Andrzej Siewior default: 6024878a028SSebastian Andrzej Siewior dev_dbg(dwc->dev, "No power optimization available\n"); 6034878a028SSebastian Andrzej Siewior } 6044878a028SSebastian Andrzej Siewior 605946bd579SHuang Rui /* check if current dwc3 is on simulation board */ 606946bd579SHuang Rui if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { 607946bd579SHuang Rui dev_dbg(dwc->dev, "it is on FPGA board\n"); 608946bd579SHuang Rui dwc->is_fpga = true; 609946bd579SHuang Rui } 610946bd579SHuang Rui 6113b81221aSHuang Rui WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga, 6123b81221aSHuang Rui "disable_scramble cannot be used on non-FPGA builds\n"); 6133b81221aSHuang Rui 6143b81221aSHuang Rui if (dwc->disable_scramble_quirk && dwc->is_fpga) 6153b81221aSHuang Rui reg |= DWC3_GCTL_DISSCRAMBLE; 6163b81221aSHuang Rui else 6173b81221aSHuang Rui reg &= ~DWC3_GCTL_DISSCRAMBLE; 6183b81221aSHuang Rui 6199a5b2f31SHuang Rui if (dwc->u2exit_lfps_quirk) 6209a5b2f31SHuang Rui reg |= DWC3_GCTL_U2EXIT_LFPS; 6219a5b2f31SHuang Rui 6224878a028SSebastian Andrzej Siewior /* 6234878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 6241d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 6254878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 6261d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 6274878a028SSebastian Andrzej Siewior */ 6284878a028SSebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 6294878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 6304878a028SSebastian Andrzej Siewior 631789451f6SFelipe Balbi dwc3_core_num_eps(dwc); 632789451f6SFelipe Balbi 6334878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 6344878a028SSebastian Andrzej Siewior 6350ffcaf37SFelipe Balbi ret = dwc3_alloc_scratch_buffers(dwc); 6360ffcaf37SFelipe Balbi if (ret) 6370ffcaf37SFelipe Balbi goto err1; 6380ffcaf37SFelipe Balbi 6390ffcaf37SFelipe Balbi ret = dwc3_setup_scratch_buffers(dwc); 6400ffcaf37SFelipe Balbi if (ret) 6410ffcaf37SFelipe Balbi goto err2; 6420ffcaf37SFelipe Balbi 64372246da4SFelipe Balbi return 0; 64472246da4SFelipe Balbi 6450ffcaf37SFelipe Balbi err2: 6460ffcaf37SFelipe Balbi dwc3_free_scratch_buffers(dwc); 6470ffcaf37SFelipe Balbi 6480ffcaf37SFelipe Balbi err1: 6490ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 6500ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 65157303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 65257303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 6530ffcaf37SFelipe Balbi 65472246da4SFelipe Balbi err0: 65572246da4SFelipe Balbi return ret; 65672246da4SFelipe Balbi } 65772246da4SFelipe Balbi 65872246da4SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 65972246da4SFelipe Balbi { 6600ffcaf37SFelipe Balbi dwc3_free_scratch_buffers(dwc); 66101b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb2_phy); 66201b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb3_phy); 66357303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 66457303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 66572246da4SFelipe Balbi } 66672246da4SFelipe Balbi 6673c9f94acSFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc) 66872246da4SFelipe Balbi { 6693c9f94acSFelipe Balbi struct device *dev = dwc->dev; 670941ea361SFelipe Balbi struct device_node *node = dev->of_node; 6713c9f94acSFelipe Balbi int ret; 67272246da4SFelipe Balbi 6735088b6f5SKishon Vijay Abraham I if (node) { 6745088b6f5SKishon Vijay Abraham I dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); 6755088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); 676bb674907SFelipe Balbi } else { 677bb674907SFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 678bb674907SFelipe Balbi dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 6795088b6f5SKishon Vijay Abraham I } 6805088b6f5SKishon Vijay Abraham I 681d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb2_phy)) { 682d105e7f8SFelipe Balbi ret = PTR_ERR(dwc->usb2_phy); 683122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 684122f06e6SKishon Vijay Abraham I dwc->usb2_phy = NULL; 685122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 686d105e7f8SFelipe Balbi return ret; 687122f06e6SKishon Vijay Abraham I } else { 68851e1e7bcSFelipe Balbi dev_err(dev, "no usb2 phy configured\n"); 689122f06e6SKishon Vijay Abraham I return ret; 690122f06e6SKishon Vijay Abraham I } 69151e1e7bcSFelipe Balbi } 69251e1e7bcSFelipe Balbi 693d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb3_phy)) { 694315955d7SRuchika Kharwar ret = PTR_ERR(dwc->usb3_phy); 695122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 696122f06e6SKishon Vijay Abraham I dwc->usb3_phy = NULL; 697122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 698d105e7f8SFelipe Balbi return ret; 699122f06e6SKishon Vijay Abraham I } else { 70051e1e7bcSFelipe Balbi dev_err(dev, "no usb3 phy configured\n"); 701122f06e6SKishon Vijay Abraham I return ret; 702122f06e6SKishon Vijay Abraham I } 70351e1e7bcSFelipe Balbi } 70451e1e7bcSFelipe Balbi 70557303488SKishon Vijay Abraham I dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); 70657303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb2_generic_phy)) { 70757303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb2_generic_phy); 70857303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 70957303488SKishon Vijay Abraham I dwc->usb2_generic_phy = NULL; 71057303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 71157303488SKishon Vijay Abraham I return ret; 71257303488SKishon Vijay Abraham I } else { 71357303488SKishon Vijay Abraham I dev_err(dev, "no usb2 phy configured\n"); 71457303488SKishon Vijay Abraham I return ret; 71557303488SKishon Vijay Abraham I } 71657303488SKishon Vijay Abraham I } 71757303488SKishon Vijay Abraham I 71857303488SKishon Vijay Abraham I dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy"); 71957303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb3_generic_phy)) { 72057303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb3_generic_phy); 72157303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 72257303488SKishon Vijay Abraham I dwc->usb3_generic_phy = NULL; 72357303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 72457303488SKishon Vijay Abraham I return ret; 72557303488SKishon Vijay Abraham I } else { 72657303488SKishon Vijay Abraham I dev_err(dev, "no usb3 phy configured\n"); 72757303488SKishon Vijay Abraham I return ret; 72857303488SKishon Vijay Abraham I } 72957303488SKishon Vijay Abraham I } 73057303488SKishon Vijay Abraham I 7313c9f94acSFelipe Balbi return 0; 7323c9f94acSFelipe Balbi } 7333c9f94acSFelipe Balbi 7345f94adfeSFelipe Balbi static int dwc3_core_init_mode(struct dwc3 *dwc) 7355f94adfeSFelipe Balbi { 7365f94adfeSFelipe Balbi struct device *dev = dwc->dev; 7375f94adfeSFelipe Balbi int ret; 7385f94adfeSFelipe Balbi 7395f94adfeSFelipe Balbi switch (dwc->dr_mode) { 7405f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 7415f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); 7425f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 7435f94adfeSFelipe Balbi if (ret) { 7445f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 7455f94adfeSFelipe Balbi return ret; 7465f94adfeSFelipe Balbi } 7475f94adfeSFelipe Balbi break; 7485f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 7495f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); 7505f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 7515f94adfeSFelipe Balbi if (ret) { 7525f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 7535f94adfeSFelipe Balbi return ret; 7545f94adfeSFelipe Balbi } 7555f94adfeSFelipe Balbi break; 7565f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 7575f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); 7585f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 7595f94adfeSFelipe Balbi if (ret) { 7605f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 7615f94adfeSFelipe Balbi return ret; 7625f94adfeSFelipe Balbi } 7635f94adfeSFelipe Balbi 7645f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 7655f94adfeSFelipe Balbi if (ret) { 7665f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 7675f94adfeSFelipe Balbi return ret; 7685f94adfeSFelipe Balbi } 7695f94adfeSFelipe Balbi break; 7705f94adfeSFelipe Balbi default: 7715f94adfeSFelipe Balbi dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); 7725f94adfeSFelipe Balbi return -EINVAL; 7735f94adfeSFelipe Balbi } 7745f94adfeSFelipe Balbi 7755f94adfeSFelipe Balbi return 0; 7765f94adfeSFelipe Balbi } 7775f94adfeSFelipe Balbi 7785f94adfeSFelipe Balbi static void dwc3_core_exit_mode(struct dwc3 *dwc) 7795f94adfeSFelipe Balbi { 7805f94adfeSFelipe Balbi switch (dwc->dr_mode) { 7815f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 7825f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 7835f94adfeSFelipe Balbi break; 7845f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 7855f94adfeSFelipe Balbi dwc3_host_exit(dwc); 7865f94adfeSFelipe Balbi break; 7875f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 7885f94adfeSFelipe Balbi dwc3_host_exit(dwc); 7895f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 7905f94adfeSFelipe Balbi break; 7915f94adfeSFelipe Balbi default: 7925f94adfeSFelipe Balbi /* do nothing */ 7935f94adfeSFelipe Balbi break; 7945f94adfeSFelipe Balbi } 7955f94adfeSFelipe Balbi } 7965f94adfeSFelipe Balbi 7973c9f94acSFelipe Balbi #define DWC3_ALIGN_MASK (16 - 1) 7983c9f94acSFelipe Balbi 7993c9f94acSFelipe Balbi static int dwc3_probe(struct platform_device *pdev) 8003c9f94acSFelipe Balbi { 8013c9f94acSFelipe Balbi struct device *dev = &pdev->dev; 8023c9f94acSFelipe Balbi struct dwc3_platform_data *pdata = dev_get_platdata(dev); 8033c9f94acSFelipe Balbi struct device_node *node = dev->of_node; 8043c9f94acSFelipe Balbi struct resource *res; 8053c9f94acSFelipe Balbi struct dwc3 *dwc; 80680caf7d2SHuang Rui u8 lpm_nyet_threshold; 8076b6a0c9aSHuang Rui u8 tx_de_emphasis; 808460d098cSHuang Rui u8 hird_threshold; 809db2be4e9SNikhil Badola u32 fladj = 0; 8103c9f94acSFelipe Balbi 811b09e99eeSAndy Shevchenko int ret; 8123c9f94acSFelipe Balbi 8133c9f94acSFelipe Balbi void __iomem *regs; 8143c9f94acSFelipe Balbi void *mem; 8153c9f94acSFelipe Balbi 8163c9f94acSFelipe Balbi mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 817734d5a53SJingoo Han if (!mem) 8183c9f94acSFelipe Balbi return -ENOMEM; 819734d5a53SJingoo Han 8203c9f94acSFelipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 8213c9f94acSFelipe Balbi dwc->mem = mem; 8223c9f94acSFelipe Balbi dwc->dev = dev; 8233c9f94acSFelipe Balbi 8243c9f94acSFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 8253c9f94acSFelipe Balbi if (!res) { 8263c9f94acSFelipe Balbi dev_err(dev, "missing IRQ\n"); 8273c9f94acSFelipe Balbi return -ENODEV; 8283c9f94acSFelipe Balbi } 8293c9f94acSFelipe Balbi dwc->xhci_resources[1].start = res->start; 8303c9f94acSFelipe Balbi dwc->xhci_resources[1].end = res->end; 8313c9f94acSFelipe Balbi dwc->xhci_resources[1].flags = res->flags; 8323c9f94acSFelipe Balbi dwc->xhci_resources[1].name = res->name; 8333c9f94acSFelipe Balbi 8343c9f94acSFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 8353c9f94acSFelipe Balbi if (!res) { 8363c9f94acSFelipe Balbi dev_err(dev, "missing memory resource\n"); 8373c9f94acSFelipe Balbi return -ENODEV; 8383c9f94acSFelipe Balbi } 8393c9f94acSFelipe Balbi 840f32a5e23SVivek Gautam dwc->xhci_resources[0].start = res->start; 841f32a5e23SVivek Gautam dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 842f32a5e23SVivek Gautam DWC3_XHCI_REGS_END; 843f32a5e23SVivek Gautam dwc->xhci_resources[0].flags = res->flags; 844f32a5e23SVivek Gautam dwc->xhci_resources[0].name = res->name; 845f32a5e23SVivek Gautam 846f32a5e23SVivek Gautam res->start += DWC3_GLOBALS_REGS_START; 847f32a5e23SVivek Gautam 848f32a5e23SVivek Gautam /* 849f32a5e23SVivek Gautam * Request memory region but exclude xHCI regs, 850f32a5e23SVivek Gautam * since it will be requested by the xhci-plat driver. 851f32a5e23SVivek Gautam */ 852f32a5e23SVivek Gautam regs = devm_ioremap_resource(dev, res); 8533da1f6eeSFelipe Balbi if (IS_ERR(regs)) { 8543da1f6eeSFelipe Balbi ret = PTR_ERR(regs); 8553da1f6eeSFelipe Balbi goto err0; 8563da1f6eeSFelipe Balbi } 857f32a5e23SVivek Gautam 858f32a5e23SVivek Gautam dwc->regs = regs; 859f32a5e23SVivek Gautam dwc->regs_size = resource_size(res); 860f32a5e23SVivek Gautam 86180caf7d2SHuang Rui /* default to highest possible threshold */ 86280caf7d2SHuang Rui lpm_nyet_threshold = 0xff; 86380caf7d2SHuang Rui 8646b6a0c9aSHuang Rui /* default to -3.5dB de-emphasis */ 8656b6a0c9aSHuang Rui tx_de_emphasis = 1; 8666b6a0c9aSHuang Rui 867460d098cSHuang Rui /* 868460d098cSHuang Rui * default to assert utmi_sleep_n and use maximum allowed HIRD 869460d098cSHuang Rui * threshold value of 0b1100 870460d098cSHuang Rui */ 871460d098cSHuang Rui hird_threshold = 12; 872460d098cSHuang Rui 87363863b98SHeikki Krogerus dwc->maximum_speed = usb_get_maximum_speed(dev); 87463863b98SHeikki Krogerus 8753c9f94acSFelipe Balbi if (node) { 87680caf7d2SHuang Rui dwc->has_lpm_erratum = of_property_read_bool(node, 87780caf7d2SHuang Rui "snps,has-lpm-erratum"); 87880caf7d2SHuang Rui of_property_read_u8(node, "snps,lpm-nyet-threshold", 87980caf7d2SHuang Rui &lpm_nyet_threshold); 880460d098cSHuang Rui dwc->is_utmi_l1_suspend = of_property_read_bool(node, 881460d098cSHuang Rui "snps,is-utmi-l1-suspend"); 882460d098cSHuang Rui of_property_read_u8(node, "snps,hird-threshold", 883460d098cSHuang Rui &hird_threshold); 884eac68e8fSRobert Baldyga dwc->usb3_lpm_capable = of_property_read_bool(node, 885eac68e8fSRobert Baldyga "snps,usb3_lpm_capable"); 8863c9f94acSFelipe Balbi 88780caf7d2SHuang Rui dwc->needs_fifo_resize = of_property_read_bool(node, 88880caf7d2SHuang Rui "tx-fifo-resize"); 8893c9f94acSFelipe Balbi dwc->dr_mode = of_usb_get_dr_mode(node); 8903b81221aSHuang Rui 8913b81221aSHuang Rui dwc->disable_scramble_quirk = of_property_read_bool(node, 8923b81221aSHuang Rui "snps,disable_scramble_quirk"); 8939a5b2f31SHuang Rui dwc->u2exit_lfps_quirk = of_property_read_bool(node, 8949a5b2f31SHuang Rui "snps,u2exit_lfps_quirk"); 895b5a65c40SHuang Rui dwc->u2ss_inp3_quirk = of_property_read_bool(node, 896b5a65c40SHuang Rui "snps,u2ss_inp3_quirk"); 897df31f5b3SHuang Rui dwc->req_p1p2p3_quirk = of_property_read_bool(node, 898df31f5b3SHuang Rui "snps,req_p1p2p3_quirk"); 899a2a1d0f5SHuang Rui dwc->del_p1p2p3_quirk = of_property_read_bool(node, 900a2a1d0f5SHuang Rui "snps,del_p1p2p3_quirk"); 90141c06ffdSHuang Rui dwc->del_phy_power_chg_quirk = of_property_read_bool(node, 90241c06ffdSHuang Rui "snps,del_phy_power_chg_quirk"); 903fb67afcaSHuang Rui dwc->lfps_filter_quirk = of_property_read_bool(node, 904fb67afcaSHuang Rui "snps,lfps_filter_quirk"); 90514f4ac53SHuang Rui dwc->rx_detect_poll_quirk = of_property_read_bool(node, 90614f4ac53SHuang Rui "snps,rx_detect_poll_quirk"); 90759acfa20SHuang Rui dwc->dis_u3_susphy_quirk = of_property_read_bool(node, 90859acfa20SHuang Rui "snps,dis_u3_susphy_quirk"); 9090effe0a3SHuang Rui dwc->dis_u2_susphy_quirk = of_property_read_bool(node, 9100effe0a3SHuang Rui "snps,dis_u2_susphy_quirk"); 9116b6a0c9aSHuang Rui 9126b6a0c9aSHuang Rui dwc->tx_de_emphasis_quirk = of_property_read_bool(node, 9136b6a0c9aSHuang Rui "snps,tx_de_emphasis_quirk"); 9146b6a0c9aSHuang Rui of_property_read_u8(node, "snps,tx_de_emphasis", 9156b6a0c9aSHuang Rui &tx_de_emphasis); 9163e10a2ceSHeikki Krogerus of_property_read_string(node, "snps,hsphy_interface", 9173e10a2ceSHeikki Krogerus &dwc->hsphy_interface); 918db2be4e9SNikhil Badola of_property_read_u32(node, 919db2be4e9SNikhil Badola "snps,quirk-frame-length-adjustment", 920db2be4e9SNikhil Badola &fladj); 9213c9f94acSFelipe Balbi } else if (pdata) { 9223c9f94acSFelipe Balbi dwc->maximum_speed = pdata->maximum_speed; 92380caf7d2SHuang Rui dwc->has_lpm_erratum = pdata->has_lpm_erratum; 92480caf7d2SHuang Rui if (pdata->lpm_nyet_threshold) 92580caf7d2SHuang Rui lpm_nyet_threshold = pdata->lpm_nyet_threshold; 926460d098cSHuang Rui dwc->is_utmi_l1_suspend = pdata->is_utmi_l1_suspend; 927460d098cSHuang Rui if (pdata->hird_threshold) 928460d098cSHuang Rui hird_threshold = pdata->hird_threshold; 9293c9f94acSFelipe Balbi 9303c9f94acSFelipe Balbi dwc->needs_fifo_resize = pdata->tx_fifo_resize; 931eac68e8fSRobert Baldyga dwc->usb3_lpm_capable = pdata->usb3_lpm_capable; 9323c9f94acSFelipe Balbi dwc->dr_mode = pdata->dr_mode; 9333b81221aSHuang Rui 9343b81221aSHuang Rui dwc->disable_scramble_quirk = pdata->disable_scramble_quirk; 9359a5b2f31SHuang Rui dwc->u2exit_lfps_quirk = pdata->u2exit_lfps_quirk; 936b5a65c40SHuang Rui dwc->u2ss_inp3_quirk = pdata->u2ss_inp3_quirk; 937df31f5b3SHuang Rui dwc->req_p1p2p3_quirk = pdata->req_p1p2p3_quirk; 938a2a1d0f5SHuang Rui dwc->del_p1p2p3_quirk = pdata->del_p1p2p3_quirk; 93941c06ffdSHuang Rui dwc->del_phy_power_chg_quirk = pdata->del_phy_power_chg_quirk; 940fb67afcaSHuang Rui dwc->lfps_filter_quirk = pdata->lfps_filter_quirk; 94114f4ac53SHuang Rui dwc->rx_detect_poll_quirk = pdata->rx_detect_poll_quirk; 94259acfa20SHuang Rui dwc->dis_u3_susphy_quirk = pdata->dis_u3_susphy_quirk; 9430effe0a3SHuang Rui dwc->dis_u2_susphy_quirk = pdata->dis_u2_susphy_quirk; 9446b6a0c9aSHuang Rui 9456b6a0c9aSHuang Rui dwc->tx_de_emphasis_quirk = pdata->tx_de_emphasis_quirk; 9466b6a0c9aSHuang Rui if (pdata->tx_de_emphasis) 9476b6a0c9aSHuang Rui tx_de_emphasis = pdata->tx_de_emphasis; 9483e10a2ceSHeikki Krogerus 9493e10a2ceSHeikki Krogerus dwc->hsphy_interface = pdata->hsphy_interface; 950db2be4e9SNikhil Badola fladj = pdata->fladj_value; 9513c9f94acSFelipe Balbi } 9523c9f94acSFelipe Balbi 9533c9f94acSFelipe Balbi /* default to superspeed if no maximum_speed passed */ 9543c9f94acSFelipe Balbi if (dwc->maximum_speed == USB_SPEED_UNKNOWN) 9553c9f94acSFelipe Balbi dwc->maximum_speed = USB_SPEED_SUPER; 9563c9f94acSFelipe Balbi 95780caf7d2SHuang Rui dwc->lpm_nyet_threshold = lpm_nyet_threshold; 9586b6a0c9aSHuang Rui dwc->tx_de_emphasis = tx_de_emphasis; 95980caf7d2SHuang Rui 960460d098cSHuang Rui dwc->hird_threshold = hird_threshold 961460d098cSHuang Rui | (dwc->is_utmi_l1_suspend << 4); 962460d098cSHuang Rui 9636c89cce0SHeikki Krogerus platform_set_drvdata(pdev, dwc); 9642917e718SHeikki Krogerus dwc3_cache_hwparams(dwc); 9656c89cce0SHeikki Krogerus 96688bc9d19SHeikki Krogerus ret = dwc3_phy_setup(dwc); 96788bc9d19SHeikki Krogerus if (ret) 96888bc9d19SHeikki Krogerus goto err0; 96945bb7de2SHeikki Krogerus 9703c9f94acSFelipe Balbi ret = dwc3_core_get_phy(dwc); 9713c9f94acSFelipe Balbi if (ret) 9723da1f6eeSFelipe Balbi goto err0; 9733c9f94acSFelipe Balbi 97472246da4SFelipe Balbi spin_lock_init(&dwc->lock); 97572246da4SFelipe Balbi 97619bacdc9SHeikki Krogerus if (!dev->dma_mask) { 977ddff14f1SKishon Vijay Abraham I dev->dma_mask = dev->parent->dma_mask; 978ddff14f1SKishon Vijay Abraham I dev->dma_parms = dev->parent->dma_parms; 979ddff14f1SKishon Vijay Abraham I dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); 98019bacdc9SHeikki Krogerus } 981ddff14f1SKishon Vijay Abraham I 982802ca850SChanho Park pm_runtime_enable(dev); 983802ca850SChanho Park pm_runtime_get_sync(dev); 984802ca850SChanho Park pm_runtime_forbid(dev); 98572246da4SFelipe Balbi 9863921426bSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 9873921426bSFelipe Balbi if (ret) { 9883921426bSFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 9893921426bSFelipe Balbi ret = -ENOMEM; 9903da1f6eeSFelipe Balbi goto err1; 9913921426bSFelipe Balbi } 9923921426bSFelipe Balbi 99332a4a135SFelipe Balbi if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) 99432a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_HOST; 99532a4a135SFelipe Balbi else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) 99632a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_PERIPHERAL; 99732a4a135SFelipe Balbi 99832a4a135SFelipe Balbi if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) 99932a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_OTG; 100032a4a135SFelipe Balbi 100172246da4SFelipe Balbi ret = dwc3_core_init(dwc); 100272246da4SFelipe Balbi if (ret) { 1003802ca850SChanho Park dev_err(dev, "failed to initialize core\n"); 10043da1f6eeSFelipe Balbi goto err1; 100572246da4SFelipe Balbi } 100672246da4SFelipe Balbi 1007db2be4e9SNikhil Badola /* Adjust Frame Length */ 1008db2be4e9SNikhil Badola dwc3_frame_length_adjustment(dwc, fladj); 1009db2be4e9SNikhil Badola 10103088f108SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 0); 10113088f108SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 0); 101257303488SKishon Vijay Abraham I ret = phy_power_on(dwc->usb2_generic_phy); 101357303488SKishon Vijay Abraham I if (ret < 0) 10143da1f6eeSFelipe Balbi goto err2; 101557303488SKishon Vijay Abraham I 101657303488SKishon Vijay Abraham I ret = phy_power_on(dwc->usb3_generic_phy); 101757303488SKishon Vijay Abraham I if (ret < 0) 10183da1f6eeSFelipe Balbi goto err3; 10193088f108SKishon Vijay Abraham I 1020f122d33eSFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 1021f122d33eSFelipe Balbi if (ret) { 1022f122d33eSFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 10233da1f6eeSFelipe Balbi goto err4; 1024f122d33eSFelipe Balbi } 1025f122d33eSFelipe Balbi 10265f94adfeSFelipe Balbi ret = dwc3_core_init_mode(dwc); 10275f94adfeSFelipe Balbi if (ret) 10283da1f6eeSFelipe Balbi goto err5; 102972246da4SFelipe Balbi 103072246da4SFelipe Balbi ret = dwc3_debugfs_init(dwc); 103172246da4SFelipe Balbi if (ret) { 1032802ca850SChanho Park dev_err(dev, "failed to initialize debugfs\n"); 10333da1f6eeSFelipe Balbi goto err6; 103472246da4SFelipe Balbi } 103572246da4SFelipe Balbi 1036802ca850SChanho Park pm_runtime_allow(dev); 103772246da4SFelipe Balbi 103872246da4SFelipe Balbi return 0; 103972246da4SFelipe Balbi 10403da1f6eeSFelipe Balbi err6: 10415f94adfeSFelipe Balbi dwc3_core_exit_mode(dwc); 104272246da4SFelipe Balbi 10433da1f6eeSFelipe Balbi err5: 1044f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 1045f122d33eSFelipe Balbi 10463da1f6eeSFelipe Balbi err4: 104757303488SKishon Vijay Abraham I phy_power_off(dwc->usb3_generic_phy); 104857303488SKishon Vijay Abraham I 10493da1f6eeSFelipe Balbi err3: 105057303488SKishon Vijay Abraham I phy_power_off(dwc->usb2_generic_phy); 105157303488SKishon Vijay Abraham I 10523da1f6eeSFelipe Balbi err2: 1053501fae51SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 1); 1054501fae51SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 1); 105572246da4SFelipe Balbi dwc3_core_exit(dwc); 105672246da4SFelipe Balbi 10573da1f6eeSFelipe Balbi err1: 10583921426bSFelipe Balbi dwc3_free_event_buffers(dwc); 105988bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 10603921426bSFelipe Balbi 10613da1f6eeSFelipe Balbi err0: 10623da1f6eeSFelipe Balbi /* 10633da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 10643da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 10653da1f6eeSFelipe Balbi * memory region the next time probe is called. 10663da1f6eeSFelipe Balbi */ 10673da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 10683da1f6eeSFelipe Balbi 106972246da4SFelipe Balbi return ret; 107072246da4SFelipe Balbi } 107172246da4SFelipe Balbi 1072fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev) 107372246da4SFelipe Balbi { 107472246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 10753da1f6eeSFelipe Balbi struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 10763da1f6eeSFelipe Balbi 10773da1f6eeSFelipe Balbi /* 10783da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 10793da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 10803da1f6eeSFelipe Balbi * memory region the next time probe is called. 10813da1f6eeSFelipe Balbi */ 10823da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 108372246da4SFelipe Balbi 1084dc99f16fSFelipe Balbi dwc3_debugfs_exit(dwc); 1085dc99f16fSFelipe Balbi dwc3_core_exit_mode(dwc); 1086dc99f16fSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 1087dc99f16fSFelipe Balbi dwc3_free_event_buffers(dwc); 1088dc99f16fSFelipe Balbi 10898ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 1); 10908ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 1); 109157303488SKishon Vijay Abraham I phy_power_off(dwc->usb2_generic_phy); 109257303488SKishon Vijay Abraham I phy_power_off(dwc->usb3_generic_phy); 10938ba007a9SKishon Vijay Abraham I 109472246da4SFelipe Balbi dwc3_core_exit(dwc); 109588bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 109672246da4SFelipe Balbi 10977415f17cSFelipe Balbi pm_runtime_put_sync(&pdev->dev); 10987415f17cSFelipe Balbi pm_runtime_disable(&pdev->dev); 10997415f17cSFelipe Balbi 110072246da4SFelipe Balbi return 0; 110172246da4SFelipe Balbi } 110272246da4SFelipe Balbi 11037415f17cSFelipe Balbi #ifdef CONFIG_PM_SLEEP 11047415f17cSFelipe Balbi static int dwc3_suspend(struct device *dev) 11057415f17cSFelipe Balbi { 11067415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 11077415f17cSFelipe Balbi unsigned long flags; 11087415f17cSFelipe Balbi 11097415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 11107415f17cSFelipe Balbi 1111a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 1112a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 1113a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 11147415f17cSFelipe Balbi dwc3_gadget_suspend(dwc); 11157415f17cSFelipe Balbi /* FALLTHROUGH */ 1116a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 11177415f17cSFelipe Balbi default: 11180b0231aaSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 11197415f17cSFelipe Balbi break; 11207415f17cSFelipe Balbi } 11217415f17cSFelipe Balbi 11227415f17cSFelipe Balbi dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL); 11237415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 11247415f17cSFelipe Balbi 11257415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 11267415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 112757303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 112857303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 11297415f17cSFelipe Balbi 11306344475fSSekhar Nori pinctrl_pm_select_sleep_state(dev); 11316344475fSSekhar Nori 11327415f17cSFelipe Balbi return 0; 11337415f17cSFelipe Balbi } 11347415f17cSFelipe Balbi 11357415f17cSFelipe Balbi static int dwc3_resume(struct device *dev) 11367415f17cSFelipe Balbi { 11377415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 11387415f17cSFelipe Balbi unsigned long flags; 113957303488SKishon Vijay Abraham I int ret; 11407415f17cSFelipe Balbi 11416344475fSSekhar Nori pinctrl_pm_select_default_state(dev); 11426344475fSSekhar Nori 11437415f17cSFelipe Balbi usb_phy_init(dwc->usb3_phy); 11447415f17cSFelipe Balbi usb_phy_init(dwc->usb2_phy); 114557303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 114657303488SKishon Vijay Abraham I if (ret < 0) 114757303488SKishon Vijay Abraham I return ret; 114857303488SKishon Vijay Abraham I 114957303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 115057303488SKishon Vijay Abraham I if (ret < 0) 115157303488SKishon Vijay Abraham I goto err_usb2phy_init; 11527415f17cSFelipe Balbi 11537415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 11547415f17cSFelipe Balbi 11550b0231aaSFelipe Balbi dwc3_event_buffers_setup(dwc); 11567415f17cSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl); 11577415f17cSFelipe Balbi 1158a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 1159a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 1160a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 11617415f17cSFelipe Balbi dwc3_gadget_resume(dwc); 11627415f17cSFelipe Balbi /* FALLTHROUGH */ 1163a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 11647415f17cSFelipe Balbi default: 11657415f17cSFelipe Balbi /* do nothing */ 11667415f17cSFelipe Balbi break; 11677415f17cSFelipe Balbi } 11687415f17cSFelipe Balbi 11697415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 11707415f17cSFelipe Balbi 11717415f17cSFelipe Balbi pm_runtime_disable(dev); 11727415f17cSFelipe Balbi pm_runtime_set_active(dev); 11737415f17cSFelipe Balbi pm_runtime_enable(dev); 11747415f17cSFelipe Balbi 11757415f17cSFelipe Balbi return 0; 117657303488SKishon Vijay Abraham I 117757303488SKishon Vijay Abraham I err_usb2phy_init: 117857303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 117957303488SKishon Vijay Abraham I 118057303488SKishon Vijay Abraham I return ret; 11817415f17cSFelipe Balbi } 11827415f17cSFelipe Balbi 11837415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = { 11847415f17cSFelipe Balbi SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 11857415f17cSFelipe Balbi }; 11867415f17cSFelipe Balbi 11877415f17cSFelipe Balbi #define DWC3_PM_OPS &(dwc3_dev_pm_ops) 11887415f17cSFelipe Balbi #else 11897415f17cSFelipe Balbi #define DWC3_PM_OPS NULL 11907415f17cSFelipe Balbi #endif 11917415f17cSFelipe Balbi 11925088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF 11935088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = { 11945088b6f5SKishon Vijay Abraham I { 119522a5aa17SFelipe Balbi .compatible = "snps,dwc3" 119622a5aa17SFelipe Balbi }, 119722a5aa17SFelipe Balbi { 11985088b6f5SKishon Vijay Abraham I .compatible = "synopsys,dwc3" 11995088b6f5SKishon Vijay Abraham I }, 12005088b6f5SKishon Vijay Abraham I { }, 12015088b6f5SKishon Vijay Abraham I }; 12025088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match); 12035088b6f5SKishon Vijay Abraham I #endif 12045088b6f5SKishon Vijay Abraham I 1205404905a6SHeikki Krogerus #ifdef CONFIG_ACPI 1206404905a6SHeikki Krogerus 1207404905a6SHeikki Krogerus #define ACPI_ID_INTEL_BSW "808622B7" 1208404905a6SHeikki Krogerus 1209404905a6SHeikki Krogerus static const struct acpi_device_id dwc3_acpi_match[] = { 1210404905a6SHeikki Krogerus { ACPI_ID_INTEL_BSW, 0 }, 1211404905a6SHeikki Krogerus { }, 1212404905a6SHeikki Krogerus }; 1213404905a6SHeikki Krogerus MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match); 1214404905a6SHeikki Krogerus #endif 1215404905a6SHeikki Krogerus 121672246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 121772246da4SFelipe Balbi .probe = dwc3_probe, 12187690417dSBill Pemberton .remove = dwc3_remove, 121972246da4SFelipe Balbi .driver = { 122072246da4SFelipe Balbi .name = "dwc3", 12215088b6f5SKishon Vijay Abraham I .of_match_table = of_match_ptr(of_dwc3_match), 1222404905a6SHeikki Krogerus .acpi_match_table = ACPI_PTR(dwc3_acpi_match), 12237415f17cSFelipe Balbi .pm = DWC3_PM_OPS, 122472246da4SFelipe Balbi }, 122572246da4SFelipe Balbi }; 122672246da4SFelipe Balbi 1227b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 1228b1116dccSTobias Klauser 12297ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 123072246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 12315945f789SFelipe Balbi MODULE_LICENSE("GPL v2"); 123272246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 1233