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]; 2751407bf13SFelipe Balbi dwc3_trace(trace_dwc3_core, 2761407bf13SFelipe Balbi "Event buf %p dma %08llx length %d\n", 27772246da4SFelipe Balbi evt->buf, (unsigned long long) evt->dma, 27872246da4SFelipe Balbi evt->length); 27972246da4SFelipe Balbi 2807acd85e0SPaul Zimmerman evt->lpos = 0; 2817acd85e0SPaul Zimmerman 28272246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 28372246da4SFelipe Balbi lower_32_bits(evt->dma)); 28472246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 28572246da4SFelipe Balbi upper_32_bits(evt->dma)); 28672246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), 28768d6a01bSFelipe Balbi DWC3_GEVNTSIZ_SIZE(evt->length)); 28872246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 28972246da4SFelipe Balbi } 29072246da4SFelipe Balbi 29172246da4SFelipe Balbi return 0; 29272246da4SFelipe Balbi } 29372246da4SFelipe Balbi 29472246da4SFelipe Balbi static void dwc3_event_buffers_cleanup(struct dwc3 *dwc) 29572246da4SFelipe Balbi { 29672246da4SFelipe Balbi struct dwc3_event_buffer *evt; 29772246da4SFelipe Balbi int n; 29872246da4SFelipe Balbi 2999f622b2aSFelipe Balbi for (n = 0; n < dwc->num_event_buffers; n++) { 30072246da4SFelipe Balbi evt = dwc->ev_buffs[n]; 3017acd85e0SPaul Zimmerman 3027acd85e0SPaul Zimmerman evt->lpos = 0; 3037acd85e0SPaul Zimmerman 30472246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(n), 0); 30572246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(n), 0); 30668d6a01bSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(n), DWC3_GEVNTSIZ_INTMASK 30768d6a01bSFelipe Balbi | DWC3_GEVNTSIZ_SIZE(0)); 30872246da4SFelipe Balbi dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(n), 0); 30972246da4SFelipe Balbi } 31072246da4SFelipe Balbi } 31172246da4SFelipe Balbi 3120ffcaf37SFelipe Balbi static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc) 3130ffcaf37SFelipe Balbi { 3140ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3150ffcaf37SFelipe Balbi return 0; 3160ffcaf37SFelipe Balbi 3170ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3180ffcaf37SFelipe Balbi return 0; 3190ffcaf37SFelipe Balbi 3200ffcaf37SFelipe Balbi dwc->scratchbuf = kmalloc_array(dwc->nr_scratch, 3210ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, GFP_KERNEL); 3220ffcaf37SFelipe Balbi if (!dwc->scratchbuf) 3230ffcaf37SFelipe Balbi return -ENOMEM; 3240ffcaf37SFelipe Balbi 3250ffcaf37SFelipe Balbi return 0; 3260ffcaf37SFelipe Balbi } 3270ffcaf37SFelipe Balbi 3280ffcaf37SFelipe Balbi static int dwc3_setup_scratch_buffers(struct dwc3 *dwc) 3290ffcaf37SFelipe Balbi { 3300ffcaf37SFelipe Balbi dma_addr_t scratch_addr; 3310ffcaf37SFelipe Balbi u32 param; 3320ffcaf37SFelipe Balbi int ret; 3330ffcaf37SFelipe Balbi 3340ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3350ffcaf37SFelipe Balbi return 0; 3360ffcaf37SFelipe Balbi 3370ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3380ffcaf37SFelipe Balbi return 0; 3390ffcaf37SFelipe Balbi 3400ffcaf37SFelipe Balbi /* should never fall here */ 3410ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 3420ffcaf37SFelipe Balbi return 0; 3430ffcaf37SFelipe Balbi 3440ffcaf37SFelipe Balbi scratch_addr = dma_map_single(dwc->dev, dwc->scratchbuf, 3450ffcaf37SFelipe Balbi dwc->nr_scratch * DWC3_SCRATCHBUF_SIZE, 3460ffcaf37SFelipe Balbi DMA_BIDIRECTIONAL); 3470ffcaf37SFelipe Balbi if (dma_mapping_error(dwc->dev, scratch_addr)) { 3480ffcaf37SFelipe Balbi dev_err(dwc->dev, "failed to map scratch buffer\n"); 3490ffcaf37SFelipe Balbi ret = -EFAULT; 3500ffcaf37SFelipe Balbi goto err0; 3510ffcaf37SFelipe Balbi } 3520ffcaf37SFelipe Balbi 3530ffcaf37SFelipe Balbi dwc->scratch_addr = scratch_addr; 3540ffcaf37SFelipe Balbi 3550ffcaf37SFelipe Balbi param = lower_32_bits(scratch_addr); 3560ffcaf37SFelipe Balbi 3570ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3580ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_LO, param); 3590ffcaf37SFelipe Balbi if (ret < 0) 3600ffcaf37SFelipe Balbi goto err1; 3610ffcaf37SFelipe Balbi 3620ffcaf37SFelipe Balbi param = upper_32_bits(scratch_addr); 3630ffcaf37SFelipe Balbi 3640ffcaf37SFelipe Balbi ret = dwc3_send_gadget_generic_command(dwc, 3650ffcaf37SFelipe Balbi DWC3_DGCMD_SET_SCRATCHPAD_ADDR_HI, param); 3660ffcaf37SFelipe Balbi if (ret < 0) 3670ffcaf37SFelipe Balbi goto err1; 3680ffcaf37SFelipe Balbi 3690ffcaf37SFelipe Balbi return 0; 3700ffcaf37SFelipe Balbi 3710ffcaf37SFelipe Balbi err1: 3720ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3730ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3740ffcaf37SFelipe Balbi 3750ffcaf37SFelipe Balbi err0: 3760ffcaf37SFelipe Balbi return ret; 3770ffcaf37SFelipe Balbi } 3780ffcaf37SFelipe Balbi 3790ffcaf37SFelipe Balbi static void dwc3_free_scratch_buffers(struct dwc3 *dwc) 3800ffcaf37SFelipe Balbi { 3810ffcaf37SFelipe Balbi if (!dwc->has_hibernation) 3820ffcaf37SFelipe Balbi return; 3830ffcaf37SFelipe Balbi 3840ffcaf37SFelipe Balbi if (!dwc->nr_scratch) 3850ffcaf37SFelipe Balbi return; 3860ffcaf37SFelipe Balbi 3870ffcaf37SFelipe Balbi /* should never fall here */ 3880ffcaf37SFelipe Balbi if (!WARN_ON(dwc->scratchbuf)) 3890ffcaf37SFelipe Balbi return; 3900ffcaf37SFelipe Balbi 3910ffcaf37SFelipe Balbi dma_unmap_single(dwc->dev, dwc->scratch_addr, dwc->nr_scratch * 3920ffcaf37SFelipe Balbi DWC3_SCRATCHBUF_SIZE, DMA_BIDIRECTIONAL); 3930ffcaf37SFelipe Balbi kfree(dwc->scratchbuf); 3940ffcaf37SFelipe Balbi } 3950ffcaf37SFelipe Balbi 396789451f6SFelipe Balbi static void dwc3_core_num_eps(struct dwc3 *dwc) 397789451f6SFelipe Balbi { 398789451f6SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 399789451f6SFelipe Balbi 400789451f6SFelipe Balbi dwc->num_in_eps = DWC3_NUM_IN_EPS(parms); 401789451f6SFelipe Balbi dwc->num_out_eps = DWC3_NUM_EPS(parms) - dwc->num_in_eps; 402789451f6SFelipe Balbi 40373815280SFelipe Balbi dwc3_trace(trace_dwc3_core, "found %d IN and %d OUT endpoints", 404789451f6SFelipe Balbi dwc->num_in_eps, dwc->num_out_eps); 405789451f6SFelipe Balbi } 406789451f6SFelipe Balbi 40741ac7b3aSBill Pemberton static void dwc3_cache_hwparams(struct dwc3 *dwc) 40826ceca97SFelipe Balbi { 40926ceca97SFelipe Balbi struct dwc3_hwparams *parms = &dwc->hwparams; 41026ceca97SFelipe Balbi 41126ceca97SFelipe Balbi parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); 41226ceca97SFelipe Balbi parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); 41326ceca97SFelipe Balbi parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); 41426ceca97SFelipe Balbi parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); 41526ceca97SFelipe Balbi parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); 41626ceca97SFelipe Balbi parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); 41726ceca97SFelipe Balbi parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); 41826ceca97SFelipe Balbi parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); 41926ceca97SFelipe Balbi parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); 42026ceca97SFelipe Balbi } 42126ceca97SFelipe Balbi 42272246da4SFelipe Balbi /** 423b5a65c40SHuang Rui * dwc3_phy_setup - Configure USB PHY Interface of DWC3 Core 424b5a65c40SHuang Rui * @dwc: Pointer to our controller context structure 42588bc9d19SHeikki Krogerus * 42688bc9d19SHeikki Krogerus * Returns 0 on success. The USB PHY interfaces are configured but not 42788bc9d19SHeikki Krogerus * initialized. The PHY interfaces and the PHYs get initialized together with 42888bc9d19SHeikki Krogerus * the core in dwc3_core_init. 429b5a65c40SHuang Rui */ 43088bc9d19SHeikki Krogerus static int dwc3_phy_setup(struct dwc3 *dwc) 431b5a65c40SHuang Rui { 432b5a65c40SHuang Rui u32 reg; 43388bc9d19SHeikki Krogerus int ret; 434b5a65c40SHuang Rui 435b5a65c40SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 436b5a65c40SHuang Rui 4372164a476SHuang Rui /* 4382164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY 4392164a476SHuang Rui * to '0' during coreConsultant configuration. So default value 4402164a476SHuang Rui * will be '0' when the core is reset. Application needs to set it 4412164a476SHuang Rui * to '1' after the core initialization is completed. 4422164a476SHuang Rui */ 4432164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 4442164a476SHuang Rui reg |= DWC3_GUSB3PIPECTL_SUSPHY; 4452164a476SHuang Rui 446b5a65c40SHuang Rui if (dwc->u2ss_inp3_quirk) 447b5a65c40SHuang Rui reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; 448b5a65c40SHuang Rui 449df31f5b3SHuang Rui if (dwc->req_p1p2p3_quirk) 450df31f5b3SHuang Rui reg |= DWC3_GUSB3PIPECTL_REQP1P2P3; 451df31f5b3SHuang Rui 452a2a1d0f5SHuang Rui if (dwc->del_p1p2p3_quirk) 453a2a1d0f5SHuang Rui reg |= DWC3_GUSB3PIPECTL_DEP1P2P3_EN; 454a2a1d0f5SHuang Rui 45541c06ffdSHuang Rui if (dwc->del_phy_power_chg_quirk) 45641c06ffdSHuang Rui reg |= DWC3_GUSB3PIPECTL_DEPOCHANGE; 45741c06ffdSHuang Rui 458fb67afcaSHuang Rui if (dwc->lfps_filter_quirk) 459fb67afcaSHuang Rui reg |= DWC3_GUSB3PIPECTL_LFPSFILT; 460fb67afcaSHuang Rui 46114f4ac53SHuang Rui if (dwc->rx_detect_poll_quirk) 46214f4ac53SHuang Rui reg |= DWC3_GUSB3PIPECTL_RX_DETOPOLL; 46314f4ac53SHuang Rui 4646b6a0c9aSHuang Rui if (dwc->tx_de_emphasis_quirk) 4656b6a0c9aSHuang Rui reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); 4666b6a0c9aSHuang Rui 467cd72f890SFelipe Balbi if (dwc->dis_u3_susphy_quirk) 46859acfa20SHuang Rui reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 46959acfa20SHuang Rui 470b5a65c40SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 471b5a65c40SHuang Rui 4722164a476SHuang Rui reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 4732164a476SHuang Rui 4743e10a2ceSHeikki Krogerus /* Select the HS PHY interface */ 4753e10a2ceSHeikki Krogerus switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) { 4763e10a2ceSHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_UTMI_ULPI: 47743cacb03SFelipe Balbi if (dwc->hsphy_interface && 47843cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "utmi", 4)) { 4793e10a2ceSHeikki Krogerus reg &= ~DWC3_GUSB2PHYCFG_ULPI_UTMI; 48088bc9d19SHeikki Krogerus break; 48143cacb03SFelipe Balbi } else if (dwc->hsphy_interface && 48243cacb03SFelipe Balbi !strncmp(dwc->hsphy_interface, "ulpi", 4)) { 4833e10a2ceSHeikki Krogerus reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI; 48488bc9d19SHeikki Krogerus dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 4853e10a2ceSHeikki Krogerus } else { 48688bc9d19SHeikki Krogerus /* Relying on default value. */ 48788bc9d19SHeikki Krogerus if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) 4883e10a2ceSHeikki Krogerus break; 4893e10a2ceSHeikki Krogerus } 4903e10a2ceSHeikki Krogerus /* FALLTHROUGH */ 49188bc9d19SHeikki Krogerus case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: 49288bc9d19SHeikki Krogerus /* Making sure the interface and PHY are operational */ 49388bc9d19SHeikki Krogerus ret = dwc3_soft_reset(dwc); 49488bc9d19SHeikki Krogerus if (ret) 49588bc9d19SHeikki Krogerus return ret; 49688bc9d19SHeikki Krogerus 49788bc9d19SHeikki Krogerus udelay(1); 49888bc9d19SHeikki Krogerus 49988bc9d19SHeikki Krogerus ret = dwc3_ulpi_init(dwc); 50088bc9d19SHeikki Krogerus if (ret) 50188bc9d19SHeikki Krogerus return ret; 50288bc9d19SHeikki Krogerus /* FALLTHROUGH */ 5033e10a2ceSHeikki Krogerus default: 5043e10a2ceSHeikki Krogerus break; 5053e10a2ceSHeikki Krogerus } 5063e10a2ceSHeikki Krogerus 5072164a476SHuang Rui /* 5082164a476SHuang Rui * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to 5092164a476SHuang Rui * '0' during coreConsultant configuration. So default value will 5102164a476SHuang Rui * be '0' when the core is reset. Application needs to set it to 5112164a476SHuang Rui * '1' after the core initialization is completed. 5122164a476SHuang Rui */ 5132164a476SHuang Rui if (dwc->revision > DWC3_REVISION_194A) 5142164a476SHuang Rui reg |= DWC3_GUSB2PHYCFG_SUSPHY; 5152164a476SHuang Rui 516cd72f890SFelipe Balbi if (dwc->dis_u2_susphy_quirk) 5170effe0a3SHuang Rui reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 5180effe0a3SHuang Rui 519ec791d14SJohn Youn if (dwc->dis_enblslpm_quirk) 520ec791d14SJohn Youn reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; 521ec791d14SJohn Youn 5222164a476SHuang Rui dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 52388bc9d19SHeikki Krogerus 52488bc9d19SHeikki Krogerus return 0; 525b5a65c40SHuang Rui } 526b5a65c40SHuang Rui 527b5a65c40SHuang Rui /** 52872246da4SFelipe Balbi * dwc3_core_init - Low-level initialization of DWC3 Core 52972246da4SFelipe Balbi * @dwc: Pointer to our controller context structure 53072246da4SFelipe Balbi * 53172246da4SFelipe Balbi * Returns 0 on success otherwise negative errno. 53272246da4SFelipe Balbi */ 53341ac7b3aSBill Pemberton static int dwc3_core_init(struct dwc3 *dwc) 53472246da4SFelipe Balbi { 5350ffcaf37SFelipe Balbi u32 hwparams4 = dwc->hwparams.hwparams4; 53672246da4SFelipe Balbi u32 reg; 53772246da4SFelipe Balbi int ret; 53872246da4SFelipe Balbi 5397650bd74SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); 5407650bd74SSebastian Andrzej Siewior /* This should read as U3 followed by revision number */ 541690fb371SJohn Youn if ((reg & DWC3_GSNPSID_MASK) == 0x55330000) { 542690fb371SJohn Youn /* Detected DWC_usb3 IP */ 543690fb371SJohn Youn dwc->revision = reg; 544690fb371SJohn Youn } else if ((reg & DWC3_GSNPSID_MASK) == 0x33310000) { 545690fb371SJohn Youn /* Detected DWC_usb31 IP */ 546690fb371SJohn Youn dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); 547690fb371SJohn Youn dwc->revision |= DWC3_REVISION_IS_DWC31; 548690fb371SJohn Youn } else { 5497650bd74SSebastian Andrzej Siewior dev_err(dwc->dev, "this is not a DesignWare USB3 DRD Core\n"); 5507650bd74SSebastian Andrzej Siewior ret = -ENODEV; 5517650bd74SSebastian Andrzej Siewior goto err0; 5527650bd74SSebastian Andrzej Siewior } 5537650bd74SSebastian Andrzej Siewior 554fa0ea13eSFelipe Balbi /* 555fa0ea13eSFelipe Balbi * Write Linux Version Code to our GUID register so it's easy to figure 556fa0ea13eSFelipe Balbi * out which kernel version a bug was found. 557fa0ea13eSFelipe Balbi */ 558fa0ea13eSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); 559fa0ea13eSFelipe Balbi 5600e1e5c47SPaul Zimmerman /* Handle USB2.0-only core configuration */ 5610e1e5c47SPaul Zimmerman if (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 5620e1e5c47SPaul Zimmerman DWC3_GHWPARAMS3_SSPHY_IFC_DIS) { 5630e1e5c47SPaul Zimmerman if (dwc->maximum_speed == USB_SPEED_SUPER) 5640e1e5c47SPaul Zimmerman dwc->maximum_speed = USB_SPEED_HIGH; 5650e1e5c47SPaul Zimmerman } 5660e1e5c47SPaul Zimmerman 56772246da4SFelipe Balbi /* issue device SoftReset too */ 568c5cc74e8SHeikki Krogerus ret = dwc3_soft_reset(dwc); 569c5cc74e8SHeikki Krogerus if (ret) 57072246da4SFelipe Balbi goto err0; 57172246da4SFelipe Balbi 57257303488SKishon Vijay Abraham I ret = dwc3_core_soft_reset(dwc); 57357303488SKishon Vijay Abraham I if (ret) 57457303488SKishon Vijay Abraham I goto err0; 57558a0f23fSPratyush Anand 5764878a028SSebastian Andrzej Siewior reg = dwc3_readl(dwc->regs, DWC3_GCTL); 5773e87c42aSPaul Zimmerman reg &= ~DWC3_GCTL_SCALEDOWN_MASK; 5784878a028SSebastian Andrzej Siewior 579164d7731SSebastian Andrzej Siewior switch (DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1)) { 5804878a028SSebastian Andrzej Siewior case DWC3_GHWPARAMS1_EN_PWROPT_CLK: 58132a4a135SFelipe Balbi /** 58232a4a135SFelipe Balbi * WORKAROUND: DWC3 revisions between 2.10a and 2.50a have an 58332a4a135SFelipe Balbi * issue which would cause xHCI compliance tests to fail. 58432a4a135SFelipe Balbi * 58532a4a135SFelipe Balbi * Because of that we cannot enable clock gating on such 58632a4a135SFelipe Balbi * configurations. 58732a4a135SFelipe Balbi * 58832a4a135SFelipe Balbi * Refers to: 58932a4a135SFelipe Balbi * 59032a4a135SFelipe Balbi * STAR#9000588375: Clock Gating, SOF Issues when ref_clk-Based 59132a4a135SFelipe Balbi * SOF/ITP Mode Used 59232a4a135SFelipe Balbi */ 59332a4a135SFelipe Balbi if ((dwc->dr_mode == USB_DR_MODE_HOST || 59432a4a135SFelipe Balbi dwc->dr_mode == USB_DR_MODE_OTG) && 59532a4a135SFelipe Balbi (dwc->revision >= DWC3_REVISION_210A && 59632a4a135SFelipe Balbi dwc->revision <= DWC3_REVISION_250A)) 59732a4a135SFelipe Balbi reg |= DWC3_GCTL_DSBLCLKGTNG | DWC3_GCTL_SOFITPSYNC; 59832a4a135SFelipe Balbi else 5994878a028SSebastian Andrzej Siewior reg &= ~DWC3_GCTL_DSBLCLKGTNG; 6004878a028SSebastian Andrzej Siewior break; 6010ffcaf37SFelipe Balbi case DWC3_GHWPARAMS1_EN_PWROPT_HIB: 6020ffcaf37SFelipe Balbi /* enable hibernation here */ 6030ffcaf37SFelipe Balbi dwc->nr_scratch = DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(hwparams4); 6042eac3992SHuang Rui 6052eac3992SHuang Rui /* 6062eac3992SHuang Rui * REVISIT Enabling this bit so that host-mode hibernation 6072eac3992SHuang Rui * will work. Device-mode hibernation is not yet implemented. 6082eac3992SHuang Rui */ 6092eac3992SHuang Rui reg |= DWC3_GCTL_GBLHIBERNATIONEN; 6100ffcaf37SFelipe Balbi break; 6114878a028SSebastian Andrzej Siewior default: 6121407bf13SFelipe Balbi dwc3_trace(trace_dwc3_core, "No power optimization available\n"); 6134878a028SSebastian Andrzej Siewior } 6144878a028SSebastian Andrzej Siewior 615946bd579SHuang Rui /* check if current dwc3 is on simulation board */ 616946bd579SHuang Rui if (dwc->hwparams.hwparams6 & DWC3_GHWPARAMS6_EN_FPGA) { 6171407bf13SFelipe Balbi dwc3_trace(trace_dwc3_core, 6181407bf13SFelipe Balbi "running on FPGA platform\n"); 619946bd579SHuang Rui dwc->is_fpga = true; 620946bd579SHuang Rui } 621946bd579SHuang Rui 6223b81221aSHuang Rui WARN_ONCE(dwc->disable_scramble_quirk && !dwc->is_fpga, 6233b81221aSHuang Rui "disable_scramble cannot be used on non-FPGA builds\n"); 6243b81221aSHuang Rui 6253b81221aSHuang Rui if (dwc->disable_scramble_quirk && dwc->is_fpga) 6263b81221aSHuang Rui reg |= DWC3_GCTL_DISSCRAMBLE; 6273b81221aSHuang Rui else 6283b81221aSHuang Rui reg &= ~DWC3_GCTL_DISSCRAMBLE; 6293b81221aSHuang Rui 6309a5b2f31SHuang Rui if (dwc->u2exit_lfps_quirk) 6319a5b2f31SHuang Rui reg |= DWC3_GCTL_U2EXIT_LFPS; 6329a5b2f31SHuang Rui 6334878a028SSebastian Andrzej Siewior /* 6344878a028SSebastian Andrzej Siewior * WORKAROUND: DWC3 revisions <1.90a have a bug 6351d046793SPaul Zimmerman * where the device can fail to connect at SuperSpeed 6364878a028SSebastian Andrzej Siewior * and falls back to high-speed mode which causes 6371d046793SPaul Zimmerman * the device to enter a Connect/Disconnect loop 6384878a028SSebastian Andrzej Siewior */ 6394878a028SSebastian Andrzej Siewior if (dwc->revision < DWC3_REVISION_190A) 6404878a028SSebastian Andrzej Siewior reg |= DWC3_GCTL_U2RSTECN; 6414878a028SSebastian Andrzej Siewior 642789451f6SFelipe Balbi dwc3_core_num_eps(dwc); 643789451f6SFelipe Balbi 6444878a028SSebastian Andrzej Siewior dwc3_writel(dwc->regs, DWC3_GCTL, reg); 6454878a028SSebastian Andrzej Siewior 6460ffcaf37SFelipe Balbi ret = dwc3_alloc_scratch_buffers(dwc); 6470ffcaf37SFelipe Balbi if (ret) 6480ffcaf37SFelipe Balbi goto err1; 6490ffcaf37SFelipe Balbi 6500ffcaf37SFelipe Balbi ret = dwc3_setup_scratch_buffers(dwc); 6510ffcaf37SFelipe Balbi if (ret) 6520ffcaf37SFelipe Balbi goto err2; 6530ffcaf37SFelipe Balbi 65472246da4SFelipe Balbi return 0; 65572246da4SFelipe Balbi 6560ffcaf37SFelipe Balbi err2: 6570ffcaf37SFelipe Balbi dwc3_free_scratch_buffers(dwc); 6580ffcaf37SFelipe Balbi 6590ffcaf37SFelipe Balbi err1: 6600ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 6610ffcaf37SFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 66257303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 66357303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 6640ffcaf37SFelipe Balbi 66572246da4SFelipe Balbi err0: 66672246da4SFelipe Balbi return ret; 66772246da4SFelipe Balbi } 66872246da4SFelipe Balbi 66972246da4SFelipe Balbi static void dwc3_core_exit(struct dwc3 *dwc) 67072246da4SFelipe Balbi { 6710ffcaf37SFelipe Balbi dwc3_free_scratch_buffers(dwc); 67201b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb2_phy); 67301b8daf7SVivek Gautam usb_phy_shutdown(dwc->usb3_phy); 67457303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 67557303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 67672246da4SFelipe Balbi } 67772246da4SFelipe Balbi 6783c9f94acSFelipe Balbi static int dwc3_core_get_phy(struct dwc3 *dwc) 67972246da4SFelipe Balbi { 6803c9f94acSFelipe Balbi struct device *dev = dwc->dev; 681941ea361SFelipe Balbi struct device_node *node = dev->of_node; 6823c9f94acSFelipe Balbi int ret; 68372246da4SFelipe Balbi 6845088b6f5SKishon Vijay Abraham I if (node) { 6855088b6f5SKishon Vijay Abraham I dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0); 6865088b6f5SKishon Vijay Abraham I dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1); 687bb674907SFelipe Balbi } else { 688bb674907SFelipe Balbi dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); 689bb674907SFelipe Balbi dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); 6905088b6f5SKishon Vijay Abraham I } 6915088b6f5SKishon Vijay Abraham I 692d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb2_phy)) { 693d105e7f8SFelipe Balbi ret = PTR_ERR(dwc->usb2_phy); 694122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 695122f06e6SKishon Vijay Abraham I dwc->usb2_phy = NULL; 696122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 697d105e7f8SFelipe Balbi return ret; 698122f06e6SKishon Vijay Abraham I } else { 69951e1e7bcSFelipe Balbi dev_err(dev, "no usb2 phy configured\n"); 700122f06e6SKishon Vijay Abraham I return ret; 701122f06e6SKishon Vijay Abraham I } 70251e1e7bcSFelipe Balbi } 70351e1e7bcSFelipe Balbi 704d105e7f8SFelipe Balbi if (IS_ERR(dwc->usb3_phy)) { 705315955d7SRuchika Kharwar ret = PTR_ERR(dwc->usb3_phy); 706122f06e6SKishon Vijay Abraham I if (ret == -ENXIO || ret == -ENODEV) { 707122f06e6SKishon Vijay Abraham I dwc->usb3_phy = NULL; 708122f06e6SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 709d105e7f8SFelipe Balbi return ret; 710122f06e6SKishon Vijay Abraham I } else { 71151e1e7bcSFelipe Balbi dev_err(dev, "no usb3 phy configured\n"); 712122f06e6SKishon Vijay Abraham I return ret; 713122f06e6SKishon Vijay Abraham I } 71451e1e7bcSFelipe Balbi } 71551e1e7bcSFelipe Balbi 71657303488SKishon Vijay Abraham I dwc->usb2_generic_phy = devm_phy_get(dev, "usb2-phy"); 71757303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb2_generic_phy)) { 71857303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb2_generic_phy); 71957303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 72057303488SKishon Vijay Abraham I dwc->usb2_generic_phy = NULL; 72157303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 72257303488SKishon Vijay Abraham I return ret; 72357303488SKishon Vijay Abraham I } else { 72457303488SKishon Vijay Abraham I dev_err(dev, "no usb2 phy configured\n"); 72557303488SKishon Vijay Abraham I return ret; 72657303488SKishon Vijay Abraham I } 72757303488SKishon Vijay Abraham I } 72857303488SKishon Vijay Abraham I 72957303488SKishon Vijay Abraham I dwc->usb3_generic_phy = devm_phy_get(dev, "usb3-phy"); 73057303488SKishon Vijay Abraham I if (IS_ERR(dwc->usb3_generic_phy)) { 73157303488SKishon Vijay Abraham I ret = PTR_ERR(dwc->usb3_generic_phy); 73257303488SKishon Vijay Abraham I if (ret == -ENOSYS || ret == -ENODEV) { 73357303488SKishon Vijay Abraham I dwc->usb3_generic_phy = NULL; 73457303488SKishon Vijay Abraham I } else if (ret == -EPROBE_DEFER) { 73557303488SKishon Vijay Abraham I return ret; 73657303488SKishon Vijay Abraham I } else { 73757303488SKishon Vijay Abraham I dev_err(dev, "no usb3 phy configured\n"); 73857303488SKishon Vijay Abraham I return ret; 73957303488SKishon Vijay Abraham I } 74057303488SKishon Vijay Abraham I } 74157303488SKishon Vijay Abraham I 7423c9f94acSFelipe Balbi return 0; 7433c9f94acSFelipe Balbi } 7443c9f94acSFelipe Balbi 7455f94adfeSFelipe Balbi static int dwc3_core_init_mode(struct dwc3 *dwc) 7465f94adfeSFelipe Balbi { 7475f94adfeSFelipe Balbi struct device *dev = dwc->dev; 7485f94adfeSFelipe Balbi int ret; 7495f94adfeSFelipe Balbi 7505f94adfeSFelipe Balbi switch (dwc->dr_mode) { 7515f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 7525f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE); 7535f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 7545f94adfeSFelipe Balbi if (ret) { 7555f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 7565f94adfeSFelipe Balbi return ret; 7575f94adfeSFelipe Balbi } 7585f94adfeSFelipe Balbi break; 7595f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 7605f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_HOST); 7615f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 7625f94adfeSFelipe Balbi if (ret) { 7635f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 7645f94adfeSFelipe Balbi return ret; 7655f94adfeSFelipe Balbi } 7665f94adfeSFelipe Balbi break; 7675f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 7685f94adfeSFelipe Balbi dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); 7695f94adfeSFelipe Balbi ret = dwc3_host_init(dwc); 7705f94adfeSFelipe Balbi if (ret) { 7715f94adfeSFelipe Balbi dev_err(dev, "failed to initialize host\n"); 7725f94adfeSFelipe Balbi return ret; 7735f94adfeSFelipe Balbi } 7745f94adfeSFelipe Balbi 7755f94adfeSFelipe Balbi ret = dwc3_gadget_init(dwc); 7765f94adfeSFelipe Balbi if (ret) { 7775f94adfeSFelipe Balbi dev_err(dev, "failed to initialize gadget\n"); 7785f94adfeSFelipe Balbi return ret; 7795f94adfeSFelipe Balbi } 7805f94adfeSFelipe Balbi break; 7815f94adfeSFelipe Balbi default: 7825f94adfeSFelipe Balbi dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); 7835f94adfeSFelipe Balbi return -EINVAL; 7845f94adfeSFelipe Balbi } 7855f94adfeSFelipe Balbi 7865f94adfeSFelipe Balbi return 0; 7875f94adfeSFelipe Balbi } 7885f94adfeSFelipe Balbi 7895f94adfeSFelipe Balbi static void dwc3_core_exit_mode(struct dwc3 *dwc) 7905f94adfeSFelipe Balbi { 7915f94adfeSFelipe Balbi switch (dwc->dr_mode) { 7925f94adfeSFelipe Balbi case USB_DR_MODE_PERIPHERAL: 7935f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 7945f94adfeSFelipe Balbi break; 7955f94adfeSFelipe Balbi case USB_DR_MODE_HOST: 7965f94adfeSFelipe Balbi dwc3_host_exit(dwc); 7975f94adfeSFelipe Balbi break; 7985f94adfeSFelipe Balbi case USB_DR_MODE_OTG: 7995f94adfeSFelipe Balbi dwc3_host_exit(dwc); 8005f94adfeSFelipe Balbi dwc3_gadget_exit(dwc); 8015f94adfeSFelipe Balbi break; 8025f94adfeSFelipe Balbi default: 8035f94adfeSFelipe Balbi /* do nothing */ 8045f94adfeSFelipe Balbi break; 8055f94adfeSFelipe Balbi } 8065f94adfeSFelipe Balbi } 8075f94adfeSFelipe Balbi 8083c9f94acSFelipe Balbi #define DWC3_ALIGN_MASK (16 - 1) 8093c9f94acSFelipe Balbi 8103c9f94acSFelipe Balbi static int dwc3_probe(struct platform_device *pdev) 8113c9f94acSFelipe Balbi { 8123c9f94acSFelipe Balbi struct device *dev = &pdev->dev; 8133c9f94acSFelipe Balbi struct dwc3_platform_data *pdata = dev_get_platdata(dev); 8143c9f94acSFelipe Balbi struct resource *res; 8153c9f94acSFelipe Balbi struct dwc3 *dwc; 81680caf7d2SHuang Rui u8 lpm_nyet_threshold; 8176b6a0c9aSHuang Rui u8 tx_de_emphasis; 818460d098cSHuang Rui u8 hird_threshold; 819db2be4e9SNikhil Badola u32 fladj = 0; 8203c9f94acSFelipe Balbi 821b09e99eeSAndy Shevchenko int ret; 8223c9f94acSFelipe Balbi 8233c9f94acSFelipe Balbi void __iomem *regs; 8243c9f94acSFelipe Balbi void *mem; 8253c9f94acSFelipe Balbi 8263c9f94acSFelipe Balbi mem = devm_kzalloc(dev, sizeof(*dwc) + DWC3_ALIGN_MASK, GFP_KERNEL); 827734d5a53SJingoo Han if (!mem) 8283c9f94acSFelipe Balbi return -ENOMEM; 829734d5a53SJingoo Han 8303c9f94acSFelipe Balbi dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1); 8313c9f94acSFelipe Balbi dwc->mem = mem; 8323c9f94acSFelipe Balbi dwc->dev = dev; 8333c9f94acSFelipe Balbi 8343c9f94acSFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 8353c9f94acSFelipe Balbi if (!res) { 8363c9f94acSFelipe Balbi dev_err(dev, "missing IRQ\n"); 8373c9f94acSFelipe Balbi return -ENODEV; 8383c9f94acSFelipe Balbi } 8393c9f94acSFelipe Balbi dwc->xhci_resources[1].start = res->start; 8403c9f94acSFelipe Balbi dwc->xhci_resources[1].end = res->end; 8413c9f94acSFelipe Balbi dwc->xhci_resources[1].flags = res->flags; 8423c9f94acSFelipe Balbi dwc->xhci_resources[1].name = res->name; 8433c9f94acSFelipe Balbi 8443c9f94acSFelipe Balbi res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 8453c9f94acSFelipe Balbi if (!res) { 8463c9f94acSFelipe Balbi dev_err(dev, "missing memory resource\n"); 8473c9f94acSFelipe Balbi return -ENODEV; 8483c9f94acSFelipe Balbi } 8493c9f94acSFelipe Balbi 850f32a5e23SVivek Gautam dwc->xhci_resources[0].start = res->start; 851f32a5e23SVivek Gautam dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + 852f32a5e23SVivek Gautam DWC3_XHCI_REGS_END; 853f32a5e23SVivek Gautam dwc->xhci_resources[0].flags = res->flags; 854f32a5e23SVivek Gautam dwc->xhci_resources[0].name = res->name; 855f32a5e23SVivek Gautam 856f32a5e23SVivek Gautam res->start += DWC3_GLOBALS_REGS_START; 857f32a5e23SVivek Gautam 858f32a5e23SVivek Gautam /* 859f32a5e23SVivek Gautam * Request memory region but exclude xHCI regs, 860f32a5e23SVivek Gautam * since it will be requested by the xhci-plat driver. 861f32a5e23SVivek Gautam */ 862f32a5e23SVivek Gautam regs = devm_ioremap_resource(dev, res); 8633da1f6eeSFelipe Balbi if (IS_ERR(regs)) { 8643da1f6eeSFelipe Balbi ret = PTR_ERR(regs); 8653da1f6eeSFelipe Balbi goto err0; 8663da1f6eeSFelipe Balbi } 867f32a5e23SVivek Gautam 868f32a5e23SVivek Gautam dwc->regs = regs; 869f32a5e23SVivek Gautam dwc->regs_size = resource_size(res); 870f32a5e23SVivek Gautam 87180caf7d2SHuang Rui /* default to highest possible threshold */ 87280caf7d2SHuang Rui lpm_nyet_threshold = 0xff; 87380caf7d2SHuang Rui 8746b6a0c9aSHuang Rui /* default to -3.5dB de-emphasis */ 8756b6a0c9aSHuang Rui tx_de_emphasis = 1; 8766b6a0c9aSHuang Rui 877460d098cSHuang Rui /* 878460d098cSHuang Rui * default to assert utmi_sleep_n and use maximum allowed HIRD 879460d098cSHuang Rui * threshold value of 0b1100 880460d098cSHuang Rui */ 881460d098cSHuang Rui hird_threshold = 12; 882460d098cSHuang Rui 88363863b98SHeikki Krogerus dwc->maximum_speed = usb_get_maximum_speed(dev); 88406e7114fSHeikki Krogerus dwc->dr_mode = usb_get_dr_mode(dev); 88563863b98SHeikki Krogerus 8863d128919SHeikki Krogerus dwc->has_lpm_erratum = device_property_read_bool(dev, 88780caf7d2SHuang Rui "snps,has-lpm-erratum"); 8883d128919SHeikki Krogerus device_property_read_u8(dev, "snps,lpm-nyet-threshold", 88980caf7d2SHuang Rui &lpm_nyet_threshold); 8903d128919SHeikki Krogerus dwc->is_utmi_l1_suspend = device_property_read_bool(dev, 891460d098cSHuang Rui "snps,is-utmi-l1-suspend"); 8923d128919SHeikki Krogerus device_property_read_u8(dev, "snps,hird-threshold", 893460d098cSHuang Rui &hird_threshold); 8943d128919SHeikki Krogerus dwc->usb3_lpm_capable = device_property_read_bool(dev, 895eac68e8fSRobert Baldyga "snps,usb3_lpm_capable"); 8963c9f94acSFelipe Balbi 8973d128919SHeikki Krogerus dwc->needs_fifo_resize = device_property_read_bool(dev, 89880caf7d2SHuang Rui "tx-fifo-resize"); 8993b81221aSHuang Rui 9003d128919SHeikki Krogerus dwc->disable_scramble_quirk = device_property_read_bool(dev, 9013b81221aSHuang Rui "snps,disable_scramble_quirk"); 9023d128919SHeikki Krogerus dwc->u2exit_lfps_quirk = device_property_read_bool(dev, 9039a5b2f31SHuang Rui "snps,u2exit_lfps_quirk"); 9043d128919SHeikki Krogerus dwc->u2ss_inp3_quirk = device_property_read_bool(dev, 905b5a65c40SHuang Rui "snps,u2ss_inp3_quirk"); 9063d128919SHeikki Krogerus dwc->req_p1p2p3_quirk = device_property_read_bool(dev, 907df31f5b3SHuang Rui "snps,req_p1p2p3_quirk"); 9083d128919SHeikki Krogerus dwc->del_p1p2p3_quirk = device_property_read_bool(dev, 909a2a1d0f5SHuang Rui "snps,del_p1p2p3_quirk"); 9103d128919SHeikki Krogerus dwc->del_phy_power_chg_quirk = device_property_read_bool(dev, 91141c06ffdSHuang Rui "snps,del_phy_power_chg_quirk"); 9123d128919SHeikki Krogerus dwc->lfps_filter_quirk = device_property_read_bool(dev, 913fb67afcaSHuang Rui "snps,lfps_filter_quirk"); 9143d128919SHeikki Krogerus dwc->rx_detect_poll_quirk = device_property_read_bool(dev, 91514f4ac53SHuang Rui "snps,rx_detect_poll_quirk"); 9163d128919SHeikki Krogerus dwc->dis_u3_susphy_quirk = device_property_read_bool(dev, 91759acfa20SHuang Rui "snps,dis_u3_susphy_quirk"); 9183d128919SHeikki Krogerus dwc->dis_u2_susphy_quirk = device_property_read_bool(dev, 9190effe0a3SHuang Rui "snps,dis_u2_susphy_quirk"); 920ec791d14SJohn Youn dwc->dis_enblslpm_quirk = device_property_read_bool(dev, 921ec791d14SJohn Youn "snps,dis_enblslpm_quirk"); 9226b6a0c9aSHuang Rui 9233d128919SHeikki Krogerus dwc->tx_de_emphasis_quirk = device_property_read_bool(dev, 9246b6a0c9aSHuang Rui "snps,tx_de_emphasis_quirk"); 9253d128919SHeikki Krogerus device_property_read_u8(dev, "snps,tx_de_emphasis", 9266b6a0c9aSHuang Rui &tx_de_emphasis); 9273d128919SHeikki Krogerus device_property_read_string(dev, "snps,hsphy_interface", 9283e10a2ceSHeikki Krogerus &dwc->hsphy_interface); 9293d128919SHeikki Krogerus device_property_read_u32(dev, "snps,quirk-frame-length-adjustment", 930db2be4e9SNikhil Badola &fladj); 9313d128919SHeikki Krogerus 9323d128919SHeikki Krogerus if (pdata) { 9333c9f94acSFelipe Balbi dwc->maximum_speed = pdata->maximum_speed; 93480caf7d2SHuang Rui dwc->has_lpm_erratum = pdata->has_lpm_erratum; 93580caf7d2SHuang Rui if (pdata->lpm_nyet_threshold) 93680caf7d2SHuang Rui lpm_nyet_threshold = pdata->lpm_nyet_threshold; 937460d098cSHuang Rui dwc->is_utmi_l1_suspend = pdata->is_utmi_l1_suspend; 938460d098cSHuang Rui if (pdata->hird_threshold) 939460d098cSHuang Rui hird_threshold = pdata->hird_threshold; 9403c9f94acSFelipe Balbi 9413c9f94acSFelipe Balbi dwc->needs_fifo_resize = pdata->tx_fifo_resize; 942eac68e8fSRobert Baldyga dwc->usb3_lpm_capable = pdata->usb3_lpm_capable; 9433c9f94acSFelipe Balbi dwc->dr_mode = pdata->dr_mode; 9443b81221aSHuang Rui 9453b81221aSHuang Rui dwc->disable_scramble_quirk = pdata->disable_scramble_quirk; 9469a5b2f31SHuang Rui dwc->u2exit_lfps_quirk = pdata->u2exit_lfps_quirk; 947b5a65c40SHuang Rui dwc->u2ss_inp3_quirk = pdata->u2ss_inp3_quirk; 948df31f5b3SHuang Rui dwc->req_p1p2p3_quirk = pdata->req_p1p2p3_quirk; 949a2a1d0f5SHuang Rui dwc->del_p1p2p3_quirk = pdata->del_p1p2p3_quirk; 95041c06ffdSHuang Rui dwc->del_phy_power_chg_quirk = pdata->del_phy_power_chg_quirk; 951fb67afcaSHuang Rui dwc->lfps_filter_quirk = pdata->lfps_filter_quirk; 95214f4ac53SHuang Rui dwc->rx_detect_poll_quirk = pdata->rx_detect_poll_quirk; 95359acfa20SHuang Rui dwc->dis_u3_susphy_quirk = pdata->dis_u3_susphy_quirk; 9540effe0a3SHuang Rui dwc->dis_u2_susphy_quirk = pdata->dis_u2_susphy_quirk; 955ec791d14SJohn Youn dwc->dis_enblslpm_quirk = pdata->dis_enblslpm_quirk; 9566b6a0c9aSHuang Rui 9576b6a0c9aSHuang Rui dwc->tx_de_emphasis_quirk = pdata->tx_de_emphasis_quirk; 9586b6a0c9aSHuang Rui if (pdata->tx_de_emphasis) 9596b6a0c9aSHuang Rui tx_de_emphasis = pdata->tx_de_emphasis; 9603e10a2ceSHeikki Krogerus 9613e10a2ceSHeikki Krogerus dwc->hsphy_interface = pdata->hsphy_interface; 962db2be4e9SNikhil Badola fladj = pdata->fladj_value; 9633c9f94acSFelipe Balbi } 9643c9f94acSFelipe Balbi 96580caf7d2SHuang Rui dwc->lpm_nyet_threshold = lpm_nyet_threshold; 9666b6a0c9aSHuang Rui dwc->tx_de_emphasis = tx_de_emphasis; 96780caf7d2SHuang Rui 968460d098cSHuang Rui dwc->hird_threshold = hird_threshold 969460d098cSHuang Rui | (dwc->is_utmi_l1_suspend << 4); 970460d098cSHuang Rui 9716c89cce0SHeikki Krogerus platform_set_drvdata(pdev, dwc); 9722917e718SHeikki Krogerus dwc3_cache_hwparams(dwc); 9736c89cce0SHeikki Krogerus 97488bc9d19SHeikki Krogerus ret = dwc3_phy_setup(dwc); 97588bc9d19SHeikki Krogerus if (ret) 97688bc9d19SHeikki Krogerus goto err0; 97745bb7de2SHeikki Krogerus 9783c9f94acSFelipe Balbi ret = dwc3_core_get_phy(dwc); 9793c9f94acSFelipe Balbi if (ret) 9803da1f6eeSFelipe Balbi goto err0; 9813c9f94acSFelipe Balbi 98272246da4SFelipe Balbi spin_lock_init(&dwc->lock); 98372246da4SFelipe Balbi 98419bacdc9SHeikki Krogerus if (!dev->dma_mask) { 985ddff14f1SKishon Vijay Abraham I dev->dma_mask = dev->parent->dma_mask; 986ddff14f1SKishon Vijay Abraham I dev->dma_parms = dev->parent->dma_parms; 987ddff14f1SKishon Vijay Abraham I dma_set_coherent_mask(dev, dev->parent->coherent_dma_mask); 98819bacdc9SHeikki Krogerus } 989ddff14f1SKishon Vijay Abraham I 990802ca850SChanho Park pm_runtime_enable(dev); 991802ca850SChanho Park pm_runtime_get_sync(dev); 992802ca850SChanho Park pm_runtime_forbid(dev); 99372246da4SFelipe Balbi 9943921426bSFelipe Balbi ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); 9953921426bSFelipe Balbi if (ret) { 9963921426bSFelipe Balbi dev_err(dwc->dev, "failed to allocate event buffers\n"); 9973921426bSFelipe Balbi ret = -ENOMEM; 9983da1f6eeSFelipe Balbi goto err1; 9993921426bSFelipe Balbi } 10003921426bSFelipe Balbi 100132a4a135SFelipe Balbi if (IS_ENABLED(CONFIG_USB_DWC3_HOST)) 100232a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_HOST; 100332a4a135SFelipe Balbi else if (IS_ENABLED(CONFIG_USB_DWC3_GADGET)) 100432a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_PERIPHERAL; 100532a4a135SFelipe Balbi 100632a4a135SFelipe Balbi if (dwc->dr_mode == USB_DR_MODE_UNKNOWN) 100732a4a135SFelipe Balbi dwc->dr_mode = USB_DR_MODE_OTG; 100832a4a135SFelipe Balbi 100972246da4SFelipe Balbi ret = dwc3_core_init(dwc); 101072246da4SFelipe Balbi if (ret) { 1011802ca850SChanho Park dev_err(dev, "failed to initialize core\n"); 10123da1f6eeSFelipe Balbi goto err1; 101372246da4SFelipe Balbi } 101472246da4SFelipe Balbi 10152c7f1bd9SJohn Youn /* default to superspeed if no maximum_speed passed */ 10162c7f1bd9SJohn Youn if (dwc->maximum_speed == USB_SPEED_UNKNOWN) { 10172c7f1bd9SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER; 10182c7f1bd9SJohn Youn 10192c7f1bd9SJohn Youn /* 10202c7f1bd9SJohn Youn * default to superspeed plus if we are capable. 10212c7f1bd9SJohn Youn */ 10222c7f1bd9SJohn Youn if (dwc3_is_usb31(dwc) && 10232c7f1bd9SJohn Youn (DWC3_GHWPARAMS3_SSPHY_IFC(dwc->hwparams.hwparams3) == 10242c7f1bd9SJohn Youn DWC3_GHWPARAMS3_SSPHY_IFC_GEN2)) 10252c7f1bd9SJohn Youn dwc->maximum_speed = USB_SPEED_SUPER_PLUS; 10262c7f1bd9SJohn Youn } 10272c7f1bd9SJohn Youn 1028db2be4e9SNikhil Badola /* Adjust Frame Length */ 1029db2be4e9SNikhil Badola dwc3_frame_length_adjustment(dwc, fladj); 1030db2be4e9SNikhil Badola 10313088f108SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 0); 10323088f108SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 0); 103357303488SKishon Vijay Abraham I ret = phy_power_on(dwc->usb2_generic_phy); 103457303488SKishon Vijay Abraham I if (ret < 0) 10353da1f6eeSFelipe Balbi goto err2; 103657303488SKishon Vijay Abraham I 103757303488SKishon Vijay Abraham I ret = phy_power_on(dwc->usb3_generic_phy); 103857303488SKishon Vijay Abraham I if (ret < 0) 10393da1f6eeSFelipe Balbi goto err3; 10403088f108SKishon Vijay Abraham I 1041f122d33eSFelipe Balbi ret = dwc3_event_buffers_setup(dwc); 1042f122d33eSFelipe Balbi if (ret) { 1043f122d33eSFelipe Balbi dev_err(dwc->dev, "failed to setup event buffers\n"); 10443da1f6eeSFelipe Balbi goto err4; 1045f122d33eSFelipe Balbi } 1046f122d33eSFelipe Balbi 10475f94adfeSFelipe Balbi ret = dwc3_core_init_mode(dwc); 10485f94adfeSFelipe Balbi if (ret) 10493da1f6eeSFelipe Balbi goto err5; 105072246da4SFelipe Balbi 105172246da4SFelipe Balbi ret = dwc3_debugfs_init(dwc); 105272246da4SFelipe Balbi if (ret) { 1053802ca850SChanho Park dev_err(dev, "failed to initialize debugfs\n"); 10543da1f6eeSFelipe Balbi goto err6; 105572246da4SFelipe Balbi } 105672246da4SFelipe Balbi 1057802ca850SChanho Park pm_runtime_allow(dev); 105872246da4SFelipe Balbi 105972246da4SFelipe Balbi return 0; 106072246da4SFelipe Balbi 10613da1f6eeSFelipe Balbi err6: 10625f94adfeSFelipe Balbi dwc3_core_exit_mode(dwc); 106372246da4SFelipe Balbi 10643da1f6eeSFelipe Balbi err5: 1065f122d33eSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 1066f122d33eSFelipe Balbi 10673da1f6eeSFelipe Balbi err4: 106857303488SKishon Vijay Abraham I phy_power_off(dwc->usb3_generic_phy); 106957303488SKishon Vijay Abraham I 10703da1f6eeSFelipe Balbi err3: 107157303488SKishon Vijay Abraham I phy_power_off(dwc->usb2_generic_phy); 107257303488SKishon Vijay Abraham I 10733da1f6eeSFelipe Balbi err2: 1074501fae51SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 1); 1075501fae51SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 1); 107672246da4SFelipe Balbi dwc3_core_exit(dwc); 107772246da4SFelipe Balbi 10783da1f6eeSFelipe Balbi err1: 10793921426bSFelipe Balbi dwc3_free_event_buffers(dwc); 108088bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 10813921426bSFelipe Balbi 10823da1f6eeSFelipe Balbi err0: 10833da1f6eeSFelipe Balbi /* 10843da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 10853da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 10863da1f6eeSFelipe Balbi * memory region the next time probe is called. 10873da1f6eeSFelipe Balbi */ 10883da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 10893da1f6eeSFelipe Balbi 109072246da4SFelipe Balbi return ret; 109172246da4SFelipe Balbi } 109272246da4SFelipe Balbi 1093fb4e98abSBill Pemberton static int dwc3_remove(struct platform_device *pdev) 109472246da4SFelipe Balbi { 109572246da4SFelipe Balbi struct dwc3 *dwc = platform_get_drvdata(pdev); 10963da1f6eeSFelipe Balbi struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 10973da1f6eeSFelipe Balbi 10983da1f6eeSFelipe Balbi /* 10993da1f6eeSFelipe Balbi * restore res->start back to its original value so that, in case the 11003da1f6eeSFelipe Balbi * probe is deferred, we don't end up getting error in request the 11013da1f6eeSFelipe Balbi * memory region the next time probe is called. 11023da1f6eeSFelipe Balbi */ 11033da1f6eeSFelipe Balbi res->start -= DWC3_GLOBALS_REGS_START; 110472246da4SFelipe Balbi 1105dc99f16fSFelipe Balbi dwc3_debugfs_exit(dwc); 1106dc99f16fSFelipe Balbi dwc3_core_exit_mode(dwc); 1107dc99f16fSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 1108dc99f16fSFelipe Balbi dwc3_free_event_buffers(dwc); 1109dc99f16fSFelipe Balbi 11108ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb2_phy, 1); 11118ba007a9SKishon Vijay Abraham I usb_phy_set_suspend(dwc->usb3_phy, 1); 111257303488SKishon Vijay Abraham I phy_power_off(dwc->usb2_generic_phy); 111357303488SKishon Vijay Abraham I phy_power_off(dwc->usb3_generic_phy); 11148ba007a9SKishon Vijay Abraham I 111572246da4SFelipe Balbi dwc3_core_exit(dwc); 111688bc9d19SHeikki Krogerus dwc3_ulpi_exit(dwc); 111772246da4SFelipe Balbi 11187415f17cSFelipe Balbi pm_runtime_put_sync(&pdev->dev); 11197415f17cSFelipe Balbi pm_runtime_disable(&pdev->dev); 11207415f17cSFelipe Balbi 112172246da4SFelipe Balbi return 0; 112272246da4SFelipe Balbi } 112372246da4SFelipe Balbi 11247415f17cSFelipe Balbi #ifdef CONFIG_PM_SLEEP 11257415f17cSFelipe Balbi static int dwc3_suspend(struct device *dev) 11267415f17cSFelipe Balbi { 11277415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 11287415f17cSFelipe Balbi unsigned long flags; 11297415f17cSFelipe Balbi 11307415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 11317415f17cSFelipe Balbi 1132a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 1133a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 1134a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 11357415f17cSFelipe Balbi dwc3_gadget_suspend(dwc); 11367415f17cSFelipe Balbi /* FALLTHROUGH */ 1137a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 11387415f17cSFelipe Balbi default: 11390b0231aaSFelipe Balbi dwc3_event_buffers_cleanup(dwc); 11407415f17cSFelipe Balbi break; 11417415f17cSFelipe Balbi } 11427415f17cSFelipe Balbi 11437415f17cSFelipe Balbi dwc->gctl = dwc3_readl(dwc->regs, DWC3_GCTL); 11447415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 11457415f17cSFelipe Balbi 11467415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb3_phy); 11477415f17cSFelipe Balbi usb_phy_shutdown(dwc->usb2_phy); 114857303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 114957303488SKishon Vijay Abraham I phy_exit(dwc->usb3_generic_phy); 11507415f17cSFelipe Balbi 11516344475fSSekhar Nori pinctrl_pm_select_sleep_state(dev); 11526344475fSSekhar Nori 11537415f17cSFelipe Balbi return 0; 11547415f17cSFelipe Balbi } 11557415f17cSFelipe Balbi 11567415f17cSFelipe Balbi static int dwc3_resume(struct device *dev) 11577415f17cSFelipe Balbi { 11587415f17cSFelipe Balbi struct dwc3 *dwc = dev_get_drvdata(dev); 11597415f17cSFelipe Balbi unsigned long flags; 116057303488SKishon Vijay Abraham I int ret; 11617415f17cSFelipe Balbi 11626344475fSSekhar Nori pinctrl_pm_select_default_state(dev); 11636344475fSSekhar Nori 11647415f17cSFelipe Balbi usb_phy_init(dwc->usb3_phy); 11657415f17cSFelipe Balbi usb_phy_init(dwc->usb2_phy); 116657303488SKishon Vijay Abraham I ret = phy_init(dwc->usb2_generic_phy); 116757303488SKishon Vijay Abraham I if (ret < 0) 116857303488SKishon Vijay Abraham I return ret; 116957303488SKishon Vijay Abraham I 117057303488SKishon Vijay Abraham I ret = phy_init(dwc->usb3_generic_phy); 117157303488SKishon Vijay Abraham I if (ret < 0) 117257303488SKishon Vijay Abraham I goto err_usb2phy_init; 11737415f17cSFelipe Balbi 11747415f17cSFelipe Balbi spin_lock_irqsave(&dwc->lock, flags); 11757415f17cSFelipe Balbi 11760b0231aaSFelipe Balbi dwc3_event_buffers_setup(dwc); 11777415f17cSFelipe Balbi dwc3_writel(dwc->regs, DWC3_GCTL, dwc->gctl); 11787415f17cSFelipe Balbi 1179a45c82b8SRuchika Kharwar switch (dwc->dr_mode) { 1180a45c82b8SRuchika Kharwar case USB_DR_MODE_PERIPHERAL: 1181a45c82b8SRuchika Kharwar case USB_DR_MODE_OTG: 11827415f17cSFelipe Balbi dwc3_gadget_resume(dwc); 11837415f17cSFelipe Balbi /* FALLTHROUGH */ 1184a45c82b8SRuchika Kharwar case USB_DR_MODE_HOST: 11857415f17cSFelipe Balbi default: 11867415f17cSFelipe Balbi /* do nothing */ 11877415f17cSFelipe Balbi break; 11887415f17cSFelipe Balbi } 11897415f17cSFelipe Balbi 11907415f17cSFelipe Balbi spin_unlock_irqrestore(&dwc->lock, flags); 11917415f17cSFelipe Balbi 11927415f17cSFelipe Balbi pm_runtime_disable(dev); 11937415f17cSFelipe Balbi pm_runtime_set_active(dev); 11947415f17cSFelipe Balbi pm_runtime_enable(dev); 11957415f17cSFelipe Balbi 11967415f17cSFelipe Balbi return 0; 119757303488SKishon Vijay Abraham I 119857303488SKishon Vijay Abraham I err_usb2phy_init: 119957303488SKishon Vijay Abraham I phy_exit(dwc->usb2_generic_phy); 120057303488SKishon Vijay Abraham I 120157303488SKishon Vijay Abraham I return ret; 12027415f17cSFelipe Balbi } 12037415f17cSFelipe Balbi 12047415f17cSFelipe Balbi static const struct dev_pm_ops dwc3_dev_pm_ops = { 12057415f17cSFelipe Balbi SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume) 12067415f17cSFelipe Balbi }; 12077415f17cSFelipe Balbi 12087415f17cSFelipe Balbi #define DWC3_PM_OPS &(dwc3_dev_pm_ops) 12097415f17cSFelipe Balbi #else 12107415f17cSFelipe Balbi #define DWC3_PM_OPS NULL 12117415f17cSFelipe Balbi #endif 12127415f17cSFelipe Balbi 12135088b6f5SKishon Vijay Abraham I #ifdef CONFIG_OF 12145088b6f5SKishon Vijay Abraham I static const struct of_device_id of_dwc3_match[] = { 12155088b6f5SKishon Vijay Abraham I { 121622a5aa17SFelipe Balbi .compatible = "snps,dwc3" 121722a5aa17SFelipe Balbi }, 121822a5aa17SFelipe Balbi { 12195088b6f5SKishon Vijay Abraham I .compatible = "synopsys,dwc3" 12205088b6f5SKishon Vijay Abraham I }, 12215088b6f5SKishon Vijay Abraham I { }, 12225088b6f5SKishon Vijay Abraham I }; 12235088b6f5SKishon Vijay Abraham I MODULE_DEVICE_TABLE(of, of_dwc3_match); 12245088b6f5SKishon Vijay Abraham I #endif 12255088b6f5SKishon Vijay Abraham I 1226404905a6SHeikki Krogerus #ifdef CONFIG_ACPI 1227404905a6SHeikki Krogerus 1228404905a6SHeikki Krogerus #define ACPI_ID_INTEL_BSW "808622B7" 1229404905a6SHeikki Krogerus 1230404905a6SHeikki Krogerus static const struct acpi_device_id dwc3_acpi_match[] = { 1231404905a6SHeikki Krogerus { ACPI_ID_INTEL_BSW, 0 }, 1232404905a6SHeikki Krogerus { }, 1233404905a6SHeikki Krogerus }; 1234404905a6SHeikki Krogerus MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match); 1235404905a6SHeikki Krogerus #endif 1236404905a6SHeikki Krogerus 123772246da4SFelipe Balbi static struct platform_driver dwc3_driver = { 123872246da4SFelipe Balbi .probe = dwc3_probe, 12397690417dSBill Pemberton .remove = dwc3_remove, 124072246da4SFelipe Balbi .driver = { 124172246da4SFelipe Balbi .name = "dwc3", 12425088b6f5SKishon Vijay Abraham I .of_match_table = of_match_ptr(of_dwc3_match), 1243404905a6SHeikki Krogerus .acpi_match_table = ACPI_PTR(dwc3_acpi_match), 12447415f17cSFelipe Balbi .pm = DWC3_PM_OPS, 124572246da4SFelipe Balbi }, 124672246da4SFelipe Balbi }; 124772246da4SFelipe Balbi 1248b1116dccSTobias Klauser module_platform_driver(dwc3_driver); 1249b1116dccSTobias Klauser 12507ae4fc4dSSebastian Andrzej Siewior MODULE_ALIAS("platform:dwc3"); 125172246da4SFelipe Balbi MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); 12525945f789SFelipe Balbi MODULE_LICENSE("GPL v2"); 125372246da4SFelipe Balbi MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver"); 1254