19ecb8875SAjay Kumar Gupta /* 29ecb8875SAjay Kumar Gupta * Texas Instruments DSPS platforms "glue layer" 39ecb8875SAjay Kumar Gupta * 49ecb8875SAjay Kumar Gupta * Copyright (C) 2012, by Texas Instruments 59ecb8875SAjay Kumar Gupta * 69ecb8875SAjay Kumar Gupta * Based on the am35x "glue layer" code. 79ecb8875SAjay Kumar Gupta * 89ecb8875SAjay Kumar Gupta * This file is part of the Inventra Controller Driver for Linux. 99ecb8875SAjay Kumar Gupta * 109ecb8875SAjay Kumar Gupta * The Inventra Controller Driver for Linux is free software; you 119ecb8875SAjay Kumar Gupta * can redistribute it and/or modify it under the terms of the GNU 129ecb8875SAjay Kumar Gupta * General Public License version 2 as published by the Free Software 139ecb8875SAjay Kumar Gupta * Foundation. 149ecb8875SAjay Kumar Gupta * 159ecb8875SAjay Kumar Gupta * The Inventra Controller Driver for Linux is distributed in 169ecb8875SAjay Kumar Gupta * the hope that it will be useful, but WITHOUT ANY WARRANTY; 179ecb8875SAjay Kumar Gupta * without even the implied warranty of MERCHANTABILITY or 189ecb8875SAjay Kumar Gupta * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 199ecb8875SAjay Kumar Gupta * License for more details. 209ecb8875SAjay Kumar Gupta * 219ecb8875SAjay Kumar Gupta * You should have received a copy of the GNU General Public License 229ecb8875SAjay Kumar Gupta * along with The Inventra Controller Driver for Linux ; if not, 239ecb8875SAjay Kumar Gupta * write to the Free Software Foundation, Inc., 59 Temple Place, 249ecb8875SAjay Kumar Gupta * Suite 330, Boston, MA 02111-1307 USA 259ecb8875SAjay Kumar Gupta * 269ecb8875SAjay Kumar Gupta * musb_dsps.c will be a common file for all the TI DSPS platforms 279ecb8875SAjay Kumar Gupta * such as dm64x, dm36x, dm35x, da8x, am35x and ti81x. 289ecb8875SAjay Kumar Gupta * For now only ti81x is using this and in future davinci.c, am35x.c 299ecb8875SAjay Kumar Gupta * da8xx.c would be merged to this file after testing. 309ecb8875SAjay Kumar Gupta */ 319ecb8875SAjay Kumar Gupta 329ecb8875SAjay Kumar Gupta #include <linux/io.h> 33ded017eeSKishon Vijay Abraham I #include <linux/err.h> 349ecb8875SAjay Kumar Gupta #include <linux/platform_device.h> 359ecb8875SAjay Kumar Gupta #include <linux/dma-mapping.h> 369ecb8875SAjay Kumar Gupta #include <linux/pm_runtime.h> 379ecb8875SAjay Kumar Gupta #include <linux/module.h> 38d7078df6SFelipe Balbi #include <linux/usb/usb_phy_generic.h> 39e8c4a7acSFelipe Balbi #include <linux/platform_data/usb-omap.h> 400f53e481SFelipe Balbi #include <linux/sizes.h> 419ecb8875SAjay Kumar Gupta 429ecb8875SAjay Kumar Gupta #include <linux/of.h> 439ecb8875SAjay Kumar Gupta #include <linux/of_device.h> 449ecb8875SAjay Kumar Gupta #include <linux/of_address.h> 4597238b35SSebastian Andrzej Siewior #include <linux/of_irq.h> 46c031a7d4SSebastian Andrzej Siewior #include <linux/usb/of.h> 479ecb8875SAjay Kumar Gupta 4840f099e3SMarkus Pargmann #include <linux/debugfs.h> 4940f099e3SMarkus Pargmann 509ecb8875SAjay Kumar Gupta #include "musb_core.h" 519ecb8875SAjay Kumar Gupta 5265145677SAjay Kumar Gupta static const struct of_device_id musb_dsps_of_match[]; 5365145677SAjay Kumar Gupta 549ecb8875SAjay Kumar Gupta /** 559ecb8875SAjay Kumar Gupta * DSPS musb wrapper register offset. 569ecb8875SAjay Kumar Gupta * FIXME: This should be expanded to have all the wrapper registers from TI DSPS 579ecb8875SAjay Kumar Gupta * musb ips. 589ecb8875SAjay Kumar Gupta */ 599ecb8875SAjay Kumar Gupta struct dsps_musb_wrapper { 609ecb8875SAjay Kumar Gupta u16 revision; 619ecb8875SAjay Kumar Gupta u16 control; 629ecb8875SAjay Kumar Gupta u16 status; 639ecb8875SAjay Kumar Gupta u16 epintr_set; 649ecb8875SAjay Kumar Gupta u16 epintr_clear; 659ecb8875SAjay Kumar Gupta u16 epintr_status; 669ecb8875SAjay Kumar Gupta u16 coreintr_set; 679ecb8875SAjay Kumar Gupta u16 coreintr_clear; 689ecb8875SAjay Kumar Gupta u16 coreintr_status; 699ecb8875SAjay Kumar Gupta u16 phy_utmi; 709ecb8875SAjay Kumar Gupta u16 mode; 71b991f9b7SDaniel Mack u16 tx_mode; 72b991f9b7SDaniel Mack u16 rx_mode; 739ecb8875SAjay Kumar Gupta 749ecb8875SAjay Kumar Gupta /* bit positions for control */ 759ecb8875SAjay Kumar Gupta unsigned reset:5; 769ecb8875SAjay Kumar Gupta 779ecb8875SAjay Kumar Gupta /* bit positions for interrupt */ 789ecb8875SAjay Kumar Gupta unsigned usb_shift:5; 799ecb8875SAjay Kumar Gupta u32 usb_mask; 809ecb8875SAjay Kumar Gupta u32 usb_bitmap; 819ecb8875SAjay Kumar Gupta unsigned drvvbus:5; 829ecb8875SAjay Kumar Gupta 839ecb8875SAjay Kumar Gupta unsigned txep_shift:5; 849ecb8875SAjay Kumar Gupta u32 txep_mask; 859ecb8875SAjay Kumar Gupta u32 txep_bitmap; 869ecb8875SAjay Kumar Gupta 879ecb8875SAjay Kumar Gupta unsigned rxep_shift:5; 889ecb8875SAjay Kumar Gupta u32 rxep_mask; 899ecb8875SAjay Kumar Gupta u32 rxep_bitmap; 909ecb8875SAjay Kumar Gupta 919ecb8875SAjay Kumar Gupta /* bit positions for phy_utmi */ 929ecb8875SAjay Kumar Gupta unsigned otg_disable:5; 939ecb8875SAjay Kumar Gupta 949ecb8875SAjay Kumar Gupta /* bit positions for mode */ 959ecb8875SAjay Kumar Gupta unsigned iddig:5; 96943c1397SFelipe Balbi unsigned iddig_mux:5; 979ecb8875SAjay Kumar Gupta /* miscellaneous stuff */ 989e204d88SFelipe Balbi unsigned poll_timeout; 999ecb8875SAjay Kumar Gupta }; 1009ecb8875SAjay Kumar Gupta 101869c5978SDaniel Mack /* 102869c5978SDaniel Mack * register shadow for suspend 103869c5978SDaniel Mack */ 104869c5978SDaniel Mack struct dsps_context { 105869c5978SDaniel Mack u32 control; 106869c5978SDaniel Mack u32 epintr; 107869c5978SDaniel Mack u32 coreintr; 108869c5978SDaniel Mack u32 phy_utmi; 109869c5978SDaniel Mack u32 mode; 110869c5978SDaniel Mack u32 tx_mode; 111869c5978SDaniel Mack u32 rx_mode; 112869c5978SDaniel Mack }; 113869c5978SDaniel Mack 1149ecb8875SAjay Kumar Gupta /** 1159ecb8875SAjay Kumar Gupta * DSPS glue structure. 1169ecb8875SAjay Kumar Gupta */ 1179ecb8875SAjay Kumar Gupta struct dsps_glue { 1189ecb8875SAjay Kumar Gupta struct device *dev; 11997238b35SSebastian Andrzej Siewior struct platform_device *musb; /* child musb pdev */ 1209ecb8875SAjay Kumar Gupta const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ 121369469a9STony Lindgren int vbus_irq; /* optional vbus irq */ 12297238b35SSebastian Andrzej Siewior struct timer_list timer; /* otg_workaround timer */ 12397238b35SSebastian Andrzej Siewior unsigned long last_timer; /* last timer data for each instance */ 124371254ceSGeorge Cherian bool sw_babble_enabled; 12525534828SAlexandre Bailon void __iomem *usbss_base; 126869c5978SDaniel Mack 127869c5978SDaniel Mack struct dsps_context context; 12840f099e3SMarkus Pargmann struct debugfs_regset32 regset; 12940f099e3SMarkus Pargmann struct dentry *dbgfs_root; 13040f099e3SMarkus Pargmann }; 13140f099e3SMarkus Pargmann 13240f099e3SMarkus Pargmann static const struct debugfs_reg32 dsps_musb_regs[] = { 13340f099e3SMarkus Pargmann { "revision", 0x00 }, 13440f099e3SMarkus Pargmann { "control", 0x14 }, 13540f099e3SMarkus Pargmann { "status", 0x18 }, 13640f099e3SMarkus Pargmann { "eoi", 0x24 }, 13740f099e3SMarkus Pargmann { "intr0_stat", 0x30 }, 13840f099e3SMarkus Pargmann { "intr1_stat", 0x34 }, 13940f099e3SMarkus Pargmann { "intr0_set", 0x38 }, 14040f099e3SMarkus Pargmann { "intr1_set", 0x3c }, 14140f099e3SMarkus Pargmann { "txmode", 0x70 }, 14240f099e3SMarkus Pargmann { "rxmode", 0x74 }, 14340f099e3SMarkus Pargmann { "autoreq", 0xd0 }, 14440f099e3SMarkus Pargmann { "srpfixtime", 0xd4 }, 14540f099e3SMarkus Pargmann { "tdown", 0xd8 }, 14640f099e3SMarkus Pargmann { "phy_utmi", 0xe0 }, 14740f099e3SMarkus Pargmann { "mode", 0xe8 }, 1489ecb8875SAjay Kumar Gupta }; 1499ecb8875SAjay Kumar Gupta 150369469a9STony Lindgren static void dsps_mod_timer(struct dsps_glue *glue, int wait_ms) 151369469a9STony Lindgren { 152369469a9STony Lindgren int wait; 153369469a9STony Lindgren 154369469a9STony Lindgren if (wait_ms < 0) 155369469a9STony Lindgren wait = msecs_to_jiffies(glue->wrp->poll_timeout); 156369469a9STony Lindgren else 157369469a9STony Lindgren wait = msecs_to_jiffies(wait_ms); 158369469a9STony Lindgren 159369469a9STony Lindgren mod_timer(&glue->timer, jiffies + wait); 160369469a9STony Lindgren } 161369469a9STony Lindgren 162369469a9STony Lindgren /* 163369469a9STony Lindgren * If no vbus irq from the PMIC is configured, we need to poll VBUS status. 164369469a9STony Lindgren */ 165369469a9STony Lindgren static void dsps_mod_timer_optional(struct dsps_glue *glue) 166369469a9STony Lindgren { 167369469a9STony Lindgren if (glue->vbus_irq) 168369469a9STony Lindgren return; 169369469a9STony Lindgren 170369469a9STony Lindgren dsps_mod_timer(glue, -1); 171369469a9STony Lindgren } 172369469a9STony Lindgren 17325534828SAlexandre Bailon /* USBSS / USB AM335x */ 17425534828SAlexandre Bailon #define USBSS_IRQ_STATUS 0x28 17525534828SAlexandre Bailon #define USBSS_IRQ_ENABLER 0x2c 17625534828SAlexandre Bailon #define USBSS_IRQ_CLEARR 0x30 17725534828SAlexandre Bailon 17825534828SAlexandre Bailon #define USBSS_IRQ_PD_COMP (1 << 2) 17925534828SAlexandre Bailon 1809ecb8875SAjay Kumar Gupta /** 1819ecb8875SAjay Kumar Gupta * dsps_musb_enable - enable interrupts 1829ecb8875SAjay Kumar Gupta */ 1839ecb8875SAjay Kumar Gupta static void dsps_musb_enable(struct musb *musb) 1849ecb8875SAjay Kumar Gupta { 1859ecb8875SAjay Kumar Gupta struct device *dev = musb->controller; 1869ecb8875SAjay Kumar Gupta struct platform_device *pdev = to_platform_device(dev->parent); 1879ecb8875SAjay Kumar Gupta struct dsps_glue *glue = platform_get_drvdata(pdev); 1889ecb8875SAjay Kumar Gupta const struct dsps_musb_wrapper *wrp = glue->wrp; 1899ecb8875SAjay Kumar Gupta void __iomem *reg_base = musb->ctrl_base; 1909ecb8875SAjay Kumar Gupta u32 epmask, coremask; 1919ecb8875SAjay Kumar Gupta 1929ecb8875SAjay Kumar Gupta /* Workaround: setup IRQs through both register sets. */ 1939ecb8875SAjay Kumar Gupta epmask = ((musb->epmask & wrp->txep_mask) << wrp->txep_shift) | 1949ecb8875SAjay Kumar Gupta ((musb->epmask & wrp->rxep_mask) << wrp->rxep_shift); 1959ecb8875SAjay Kumar Gupta coremask = (wrp->usb_bitmap & ~MUSB_INTR_SOF); 1969ecb8875SAjay Kumar Gupta 197086b2882SBin Liu musb_writel(reg_base, wrp->epintr_set, epmask); 198086b2882SBin Liu musb_writel(reg_base, wrp->coreintr_set, coremask); 199b8239dccSBin Liu /* start polling for ID change in dual-role idle mode */ 200b8239dccSBin Liu if (musb->xceiv->otg->state == OTG_STATE_B_IDLE && 201b8239dccSBin Liu musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) 202369469a9STony Lindgren dsps_mod_timer(glue, -1); 2039ecb8875SAjay Kumar Gupta } 2049ecb8875SAjay Kumar Gupta 2059ecb8875SAjay Kumar Gupta /** 2069ecb8875SAjay Kumar Gupta * dsps_musb_disable - disable HDRC and flush interrupts 2079ecb8875SAjay Kumar Gupta */ 2089ecb8875SAjay Kumar Gupta static void dsps_musb_disable(struct musb *musb) 2099ecb8875SAjay Kumar Gupta { 2109ecb8875SAjay Kumar Gupta struct device *dev = musb->controller; 2119ecb8875SAjay Kumar Gupta struct platform_device *pdev = to_platform_device(dev->parent); 2129ecb8875SAjay Kumar Gupta struct dsps_glue *glue = platform_get_drvdata(pdev); 2139ecb8875SAjay Kumar Gupta const struct dsps_musb_wrapper *wrp = glue->wrp; 2149ecb8875SAjay Kumar Gupta void __iomem *reg_base = musb->ctrl_base; 2159ecb8875SAjay Kumar Gupta 216086b2882SBin Liu musb_writel(reg_base, wrp->coreintr_clear, wrp->usb_bitmap); 217086b2882SBin Liu musb_writel(reg_base, wrp->epintr_clear, 2189ecb8875SAjay Kumar Gupta wrp->txep_bitmap | wrp->rxep_bitmap); 219ea2f35c0STony Lindgren del_timer_sync(&glue->timer); 2209ecb8875SAjay Kumar Gupta } 2219ecb8875SAjay Kumar Gupta 222ea2f35c0STony Lindgren /* Caller must take musb->lock */ 223ea2f35c0STony Lindgren static int dsps_check_status(struct musb *musb, void *unused) 2249ecb8875SAjay Kumar Gupta { 2259ecb8875SAjay Kumar Gupta void __iomem *mregs = musb->mregs; 2269ecb8875SAjay Kumar Gupta struct device *dev = musb->controller; 227db4a9320SB, Ravi struct dsps_glue *glue = dev_get_drvdata(dev->parent); 2289ecb8875SAjay Kumar Gupta const struct dsps_musb_wrapper *wrp = glue->wrp; 2299ecb8875SAjay Kumar Gupta u8 devctl; 2300f901c98SSebastian Andrzej Siewior int skip_session = 0; 2319ecb8875SAjay Kumar Gupta 232369469a9STony Lindgren if (glue->vbus_irq) 233369469a9STony Lindgren del_timer(&glue->timer); 234369469a9STony Lindgren 2359ecb8875SAjay Kumar Gupta /* 2369ecb8875SAjay Kumar Gupta * We poll because DSPS IP's won't expose several OTG-critical 2379ecb8875SAjay Kumar Gupta * status change events (from the transceiver) otherwise. 2389ecb8875SAjay Kumar Gupta */ 239086b2882SBin Liu devctl = musb_readb(mregs, MUSB_DEVCTL); 2409ecb8875SAjay Kumar Gupta dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl, 241e47d9254SAntoine Tenart usb_otg_state_string(musb->xceiv->otg->state)); 2429ecb8875SAjay Kumar Gupta 243e47d9254SAntoine Tenart switch (musb->xceiv->otg->state) { 2442f3fd2c5STony Lindgren case OTG_STATE_A_WAIT_VRISE: 245369469a9STony Lindgren dsps_mod_timer_optional(glue); 2462f3fd2c5STony Lindgren break; 2479ecb8875SAjay Kumar Gupta case OTG_STATE_A_WAIT_BCON: 248b3addcf0SBin Liu /* keep VBUS on for host-only mode */ 249b3addcf0SBin Liu if (musb->port_mode == MUSB_PORT_MODE_HOST) { 250b3addcf0SBin Liu dsps_mod_timer_optional(glue); 251b3addcf0SBin Liu break; 252b3addcf0SBin Liu } 253086b2882SBin Liu musb_writeb(musb->mregs, MUSB_DEVCTL, 0); 2540f901c98SSebastian Andrzej Siewior skip_session = 1; 2550f901c98SSebastian Andrzej Siewior /* fall */ 2569ecb8875SAjay Kumar Gupta 2570f901c98SSebastian Andrzej Siewior case OTG_STATE_A_IDLE: 2580f901c98SSebastian Andrzej Siewior case OTG_STATE_B_IDLE: 259369469a9STony Lindgren if (!glue->vbus_irq) { 2609ecb8875SAjay Kumar Gupta if (devctl & MUSB_DEVCTL_BDEVICE) { 261e47d9254SAntoine Tenart musb->xceiv->otg->state = OTG_STATE_B_IDLE; 2629ecb8875SAjay Kumar Gupta MUSB_DEV_MODE(musb); 2639ecb8875SAjay Kumar Gupta } else { 264e47d9254SAntoine Tenart musb->xceiv->otg->state = OTG_STATE_A_IDLE; 2659ecb8875SAjay Kumar Gupta MUSB_HST_MODE(musb); 2669ecb8875SAjay Kumar Gupta } 2670f901c98SSebastian Andrzej Siewior if (!(devctl & MUSB_DEVCTL_SESSION) && !skip_session) 268369469a9STony Lindgren musb_writeb(mregs, MUSB_DEVCTL, 269369469a9STony Lindgren MUSB_DEVCTL_SESSION); 270369469a9STony Lindgren } 271369469a9STony Lindgren dsps_mod_timer_optional(glue); 2729ecb8875SAjay Kumar Gupta break; 2739ecb8875SAjay Kumar Gupta case OTG_STATE_A_WAIT_VFALL: 274e47d9254SAntoine Tenart musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; 275086b2882SBin Liu musb_writel(musb->ctrl_base, wrp->coreintr_set, 2769ecb8875SAjay Kumar Gupta MUSB_INTR_VBUSERROR << wrp->usb_shift); 2779ecb8875SAjay Kumar Gupta break; 2789ecb8875SAjay Kumar Gupta default: 2799ecb8875SAjay Kumar Gupta break; 2809ecb8875SAjay Kumar Gupta } 28165b3f50eSTony Lindgren 282ea2f35c0STony Lindgren return 0; 283ea2f35c0STony Lindgren } 284ea2f35c0STony Lindgren 285*05678497SKees Cook static void otg_timer(struct timer_list *t) 286ea2f35c0STony Lindgren { 287*05678497SKees Cook struct dsps_glue *glue = from_timer(glue, t, timer); 288*05678497SKees Cook struct musb *musb = platform_get_drvdata(glue->musb); 289ea2f35c0STony Lindgren struct device *dev = musb->controller; 290ea2f35c0STony Lindgren unsigned long flags; 291ea2f35c0STony Lindgren int err; 292ea2f35c0STony Lindgren 293ea2f35c0STony Lindgren err = pm_runtime_get(dev); 294ea2f35c0STony Lindgren if ((err != -EINPROGRESS) && err < 0) { 295ea2f35c0STony Lindgren dev_err(dev, "Poll could not pm_runtime_get: %i\n", err); 296ea2f35c0STony Lindgren pm_runtime_put_noidle(dev); 297ea2f35c0STony Lindgren 298ea2f35c0STony Lindgren return; 299ea2f35c0STony Lindgren } 300ea2f35c0STony Lindgren 301ea2f35c0STony Lindgren spin_lock_irqsave(&musb->lock, flags); 302ea2f35c0STony Lindgren err = musb_queue_resume_work(musb, dsps_check_status, NULL); 303ea2f35c0STony Lindgren if (err < 0) 304ea2f35c0STony Lindgren dev_err(dev, "%s resume work: %i\n", __func__, err); 305ea2f35c0STony Lindgren spin_unlock_irqrestore(&musb->lock, flags); 30665b3f50eSTony Lindgren pm_runtime_mark_last_busy(dev); 30765b3f50eSTony Lindgren pm_runtime_put_autosuspend(dev); 3089ecb8875SAjay Kumar Gupta } 3099ecb8875SAjay Kumar Gupta 3104ab53a69SWei Yongjun static void dsps_musb_clear_ep_rxintr(struct musb *musb, int epnum) 311c48400baSBin Liu { 312c48400baSBin Liu u32 epintr; 313c48400baSBin Liu struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent); 314c48400baSBin Liu const struct dsps_musb_wrapper *wrp = glue->wrp; 315c48400baSBin Liu 316c48400baSBin Liu /* musb->lock might already been held */ 317c48400baSBin Liu epintr = (1 << epnum) << wrp->rxep_shift; 318c48400baSBin Liu musb_writel(musb->ctrl_base, wrp->epintr_status, epintr); 319c48400baSBin Liu } 320c48400baSBin Liu 3219ecb8875SAjay Kumar Gupta static irqreturn_t dsps_interrupt(int irq, void *hci) 3229ecb8875SAjay Kumar Gupta { 3239ecb8875SAjay Kumar Gupta struct musb *musb = hci; 3249ecb8875SAjay Kumar Gupta void __iomem *reg_base = musb->ctrl_base; 3259ecb8875SAjay Kumar Gupta struct device *dev = musb->controller; 326db4a9320SB, Ravi struct dsps_glue *glue = dev_get_drvdata(dev->parent); 3279ecb8875SAjay Kumar Gupta const struct dsps_musb_wrapper *wrp = glue->wrp; 3289ecb8875SAjay Kumar Gupta unsigned long flags; 3299ecb8875SAjay Kumar Gupta irqreturn_t ret = IRQ_NONE; 3309ecb8875SAjay Kumar Gupta u32 epintr, usbintr; 3319ecb8875SAjay Kumar Gupta 3329ecb8875SAjay Kumar Gupta spin_lock_irqsave(&musb->lock, flags); 3339ecb8875SAjay Kumar Gupta 3349ecb8875SAjay Kumar Gupta /* Get endpoint interrupts */ 335086b2882SBin Liu epintr = musb_readl(reg_base, wrp->epintr_status); 3369ecb8875SAjay Kumar Gupta musb->int_rx = (epintr & wrp->rxep_bitmap) >> wrp->rxep_shift; 3379ecb8875SAjay Kumar Gupta musb->int_tx = (epintr & wrp->txep_bitmap) >> wrp->txep_shift; 3389ecb8875SAjay Kumar Gupta 3399ecb8875SAjay Kumar Gupta if (epintr) 340086b2882SBin Liu musb_writel(reg_base, wrp->epintr_status, epintr); 3419ecb8875SAjay Kumar Gupta 3429ecb8875SAjay Kumar Gupta /* Get usb core interrupts */ 343086b2882SBin Liu usbintr = musb_readl(reg_base, wrp->coreintr_status); 3449ecb8875SAjay Kumar Gupta if (!usbintr && !epintr) 3459be73baeSSebastian Andrzej Siewior goto out; 3469ecb8875SAjay Kumar Gupta 3479ecb8875SAjay Kumar Gupta musb->int_usb = (usbintr & wrp->usb_bitmap) >> wrp->usb_shift; 3489ecb8875SAjay Kumar Gupta if (usbintr) 349086b2882SBin Liu musb_writel(reg_base, wrp->coreintr_status, usbintr); 3509ecb8875SAjay Kumar Gupta 3519ecb8875SAjay Kumar Gupta dev_dbg(musb->controller, "usbintr (%x) epintr(%x)\n", 3529ecb8875SAjay Kumar Gupta usbintr, epintr); 3531d57de30SDaniel Mack 3549ecb8875SAjay Kumar Gupta if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) { 355086b2882SBin Liu int drvvbus = musb_readl(reg_base, wrp->status); 3569ecb8875SAjay Kumar Gupta void __iomem *mregs = musb->mregs; 357086b2882SBin Liu u8 devctl = musb_readb(mregs, MUSB_DEVCTL); 3589ecb8875SAjay Kumar Gupta int err; 3599ecb8875SAjay Kumar Gupta 360032ec49fSFelipe Balbi err = musb->int_usb & MUSB_INTR_VBUSERROR; 3619ecb8875SAjay Kumar Gupta if (err) { 3629ecb8875SAjay Kumar Gupta /* 3639ecb8875SAjay Kumar Gupta * The Mentor core doesn't debounce VBUS as needed 3649ecb8875SAjay Kumar Gupta * to cope with device connect current spikes. This 3659ecb8875SAjay Kumar Gupta * means it's not uncommon for bus-powered devices 3669ecb8875SAjay Kumar Gupta * to get VBUS errors during enumeration. 3679ecb8875SAjay Kumar Gupta * 3689ecb8875SAjay Kumar Gupta * This is a workaround, but newer RTL from Mentor 3699ecb8875SAjay Kumar Gupta * seems to allow a better one: "re"-starting sessions 3709ecb8875SAjay Kumar Gupta * without waiting for VBUS to stop registering in 3719ecb8875SAjay Kumar Gupta * devctl. 3729ecb8875SAjay Kumar Gupta */ 3739ecb8875SAjay Kumar Gupta musb->int_usb &= ~MUSB_INTR_VBUSERROR; 374e47d9254SAntoine Tenart musb->xceiv->otg->state = OTG_STATE_A_WAIT_VFALL; 375369469a9STony Lindgren dsps_mod_timer_optional(glue); 3769ecb8875SAjay Kumar Gupta WARNING("VBUS error workaround (delay coming)\n"); 377032ec49fSFelipe Balbi } else if (drvvbus) { 3789ecb8875SAjay Kumar Gupta MUSB_HST_MODE(musb); 3799ecb8875SAjay Kumar Gupta musb->xceiv->otg->default_a = 1; 380e47d9254SAntoine Tenart musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; 381369469a9STony Lindgren dsps_mod_timer_optional(glue); 3829ecb8875SAjay Kumar Gupta } else { 3839ecb8875SAjay Kumar Gupta musb->is_active = 0; 3849ecb8875SAjay Kumar Gupta MUSB_DEV_MODE(musb); 3859ecb8875SAjay Kumar Gupta musb->xceiv->otg->default_a = 0; 386e47d9254SAntoine Tenart musb->xceiv->otg->state = OTG_STATE_B_IDLE; 3879ecb8875SAjay Kumar Gupta } 3889ecb8875SAjay Kumar Gupta 3899ecb8875SAjay Kumar Gupta /* NOTE: this must complete power-on within 100 ms. */ 3909ecb8875SAjay Kumar Gupta dev_dbg(musb->controller, "VBUS %s (%s)%s, devctl %02x\n", 3919ecb8875SAjay Kumar Gupta drvvbus ? "on" : "off", 392e47d9254SAntoine Tenart usb_otg_state_string(musb->xceiv->otg->state), 3939ecb8875SAjay Kumar Gupta err ? " ERROR" : "", 3949ecb8875SAjay Kumar Gupta devctl); 3959ecb8875SAjay Kumar Gupta ret = IRQ_HANDLED; 3969ecb8875SAjay Kumar Gupta } 3979ecb8875SAjay Kumar Gupta 3989ecb8875SAjay Kumar Gupta if (musb->int_tx || musb->int_rx || musb->int_usb) 3999ecb8875SAjay Kumar Gupta ret |= musb_interrupt(musb); 4009ecb8875SAjay Kumar Gupta 4012f3fd2c5STony Lindgren /* Poll for ID change and connect */ 4022f3fd2c5STony Lindgren switch (musb->xceiv->otg->state) { 4032f3fd2c5STony Lindgren case OTG_STATE_B_IDLE: 4042f3fd2c5STony Lindgren case OTG_STATE_A_WAIT_BCON: 405369469a9STony Lindgren dsps_mod_timer_optional(glue); 4062f3fd2c5STony Lindgren break; 4072f3fd2c5STony Lindgren default: 4082f3fd2c5STony Lindgren break; 4092f3fd2c5STony Lindgren } 4102f3fd2c5STony Lindgren 4119be73baeSSebastian Andrzej Siewior out: 4129ecb8875SAjay Kumar Gupta spin_unlock_irqrestore(&musb->lock, flags); 4139ecb8875SAjay Kumar Gupta 4149ecb8875SAjay Kumar Gupta return ret; 4159ecb8875SAjay Kumar Gupta } 4169ecb8875SAjay Kumar Gupta 41740f099e3SMarkus Pargmann static int dsps_musb_dbg_init(struct musb *musb, struct dsps_glue *glue) 41840f099e3SMarkus Pargmann { 41940f099e3SMarkus Pargmann struct dentry *root; 42040f099e3SMarkus Pargmann struct dentry *file; 42140f099e3SMarkus Pargmann char buf[128]; 42240f099e3SMarkus Pargmann 42340f099e3SMarkus Pargmann sprintf(buf, "%s.dsps", dev_name(musb->controller)); 42440f099e3SMarkus Pargmann root = debugfs_create_dir(buf, NULL); 42540f099e3SMarkus Pargmann if (!root) 42640f099e3SMarkus Pargmann return -ENOMEM; 42740f099e3SMarkus Pargmann glue->dbgfs_root = root; 42840f099e3SMarkus Pargmann 42940f099e3SMarkus Pargmann glue->regset.regs = dsps_musb_regs; 43040f099e3SMarkus Pargmann glue->regset.nregs = ARRAY_SIZE(dsps_musb_regs); 43140f099e3SMarkus Pargmann glue->regset.base = musb->ctrl_base; 43240f099e3SMarkus Pargmann 43340f099e3SMarkus Pargmann file = debugfs_create_regset32("regdump", S_IRUGO, root, &glue->regset); 43440f099e3SMarkus Pargmann if (!file) { 43540f099e3SMarkus Pargmann debugfs_remove_recursive(root); 43640f099e3SMarkus Pargmann return -ENOMEM; 43740f099e3SMarkus Pargmann } 43840f099e3SMarkus Pargmann return 0; 43940f099e3SMarkus Pargmann } 44040f099e3SMarkus Pargmann 4419ecb8875SAjay Kumar Gupta static int dsps_musb_init(struct musb *musb) 4429ecb8875SAjay Kumar Gupta { 4439ecb8875SAjay Kumar Gupta struct device *dev = musb->controller; 444db4a9320SB, Ravi struct dsps_glue *glue = dev_get_drvdata(dev->parent); 44597238b35SSebastian Andrzej Siewior struct platform_device *parent = to_platform_device(dev->parent); 4469ecb8875SAjay Kumar Gupta const struct dsps_musb_wrapper *wrp = glue->wrp; 44797238b35SSebastian Andrzej Siewior void __iomem *reg_base; 44897238b35SSebastian Andrzej Siewior struct resource *r; 4499ecb8875SAjay Kumar Gupta u32 rev, val; 45040f099e3SMarkus Pargmann int ret; 4519ecb8875SAjay Kumar Gupta 45297238b35SSebastian Andrzej Siewior r = platform_get_resource_byname(parent, IORESOURCE_MEM, "control"); 45397238b35SSebastian Andrzej Siewior reg_base = devm_ioremap_resource(dev, r); 45451ef74f6SJulia Lawall if (IS_ERR(reg_base)) 45551ef74f6SJulia Lawall return PTR_ERR(reg_base); 45697238b35SSebastian Andrzej Siewior musb->ctrl_base = reg_base; 4579ecb8875SAjay Kumar Gupta 458d7554226SAfzal Mohammed /* NOP driver needs change if supporting dual instance */ 459983f3cabSFelipe Balbi musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, "phys", 0); 46097238b35SSebastian Andrzej Siewior if (IS_ERR(musb->xceiv)) 46197238b35SSebastian Andrzej Siewior return PTR_ERR(musb->xceiv); 4629ecb8875SAjay Kumar Gupta 463bb90600dSTony Lindgren musb->phy = devm_phy_get(dev->parent, "usb2-phy"); 464bb90600dSTony Lindgren 4659ecb8875SAjay Kumar Gupta /* Returns zero if e.g. not clocked */ 466086b2882SBin Liu rev = musb_readl(reg_base, wrp->revision); 46797238b35SSebastian Andrzej Siewior if (!rev) 46897238b35SSebastian Andrzej Siewior return -ENODEV; 4699ecb8875SAjay Kumar Gupta 4707557a57fSSebastian Andrzej Siewior usb_phy_init(musb->xceiv); 471bb90600dSTony Lindgren if (IS_ERR(musb->phy)) { 472bb90600dSTony Lindgren musb->phy = NULL; 473bb90600dSTony Lindgren } else { 474bb90600dSTony Lindgren ret = phy_init(musb->phy); 475bb90600dSTony Lindgren if (ret < 0) 476bb90600dSTony Lindgren return ret; 477bb90600dSTony Lindgren ret = phy_power_on(musb->phy); 478bb90600dSTony Lindgren if (ret) { 479bb90600dSTony Lindgren phy_exit(musb->phy); 480bb90600dSTony Lindgren return ret; 481bb90600dSTony Lindgren } 482bb90600dSTony Lindgren } 483bb90600dSTony Lindgren 484*05678497SKees Cook timer_setup(&glue->timer, otg_timer, 0); 4859ecb8875SAjay Kumar Gupta 4869ecb8875SAjay Kumar Gupta /* Reset the musb */ 487086b2882SBin Liu musb_writel(reg_base, wrp->control, (1 << wrp->reset)); 4889ecb8875SAjay Kumar Gupta 4899ecb8875SAjay Kumar Gupta musb->isr = dsps_interrupt; 4909ecb8875SAjay Kumar Gupta 4919ecb8875SAjay Kumar Gupta /* reset the otgdisable bit, needed for host mode to work */ 492086b2882SBin Liu val = musb_readl(reg_base, wrp->phy_utmi); 4939ecb8875SAjay Kumar Gupta val &= ~(1 << wrp->otg_disable); 494086b2882SBin Liu musb_writel(musb->ctrl_base, wrp->phy_utmi, val); 4959ecb8875SAjay Kumar Gupta 496371254ceSGeorge Cherian /* 497371254ceSGeorge Cherian * Check whether the dsps version has babble control enabled. 498371254ceSGeorge Cherian * In latest silicon revision the babble control logic is enabled. 499371254ceSGeorge Cherian * If MUSB_BABBLE_CTL returns 0x4 then we have the babble control 500371254ceSGeorge Cherian * logic enabled. 501371254ceSGeorge Cherian */ 502086b2882SBin Liu val = musb_readb(musb->mregs, MUSB_BABBLE_CTL); 503f860f0b1SFelipe Balbi if (val & MUSB_BABBLE_RCV_DISABLE) { 504371254ceSGeorge Cherian glue->sw_babble_enabled = true; 505371254ceSGeorge Cherian val |= MUSB_BABBLE_SW_SESSION_CTRL; 506086b2882SBin Liu musb_writeb(musb->mregs, MUSB_BABBLE_CTL, val); 507371254ceSGeorge Cherian } 508371254ceSGeorge Cherian 509369469a9STony Lindgren dsps_mod_timer(glue, -1); 5102f3fd2c5STony Lindgren 511e94a7369SSaurabh Karajgaonkar return dsps_musb_dbg_init(musb, glue); 5129ecb8875SAjay Kumar Gupta } 5139ecb8875SAjay Kumar Gupta 5149ecb8875SAjay Kumar Gupta static int dsps_musb_exit(struct musb *musb) 5159ecb8875SAjay Kumar Gupta { 5169ecb8875SAjay Kumar Gupta struct device *dev = musb->controller; 517db4a9320SB, Ravi struct dsps_glue *glue = dev_get_drvdata(dev->parent); 5189ecb8875SAjay Kumar Gupta 51997238b35SSebastian Andrzej Siewior del_timer_sync(&glue->timer); 5207557a57fSSebastian Andrzej Siewior usb_phy_shutdown(musb->xceiv); 521bb90600dSTony Lindgren phy_power_off(musb->phy); 522bb90600dSTony Lindgren phy_exit(musb->phy); 5230fca91b8SDaniel Mack debugfs_remove_recursive(glue->dbgfs_root); 5240fca91b8SDaniel Mack 5259ecb8875SAjay Kumar Gupta return 0; 5269ecb8875SAjay Kumar Gupta } 5279ecb8875SAjay Kumar Gupta 528943c1397SFelipe Balbi static int dsps_musb_set_mode(struct musb *musb, u8 mode) 529943c1397SFelipe Balbi { 530943c1397SFelipe Balbi struct device *dev = musb->controller; 531943c1397SFelipe Balbi struct dsps_glue *glue = dev_get_drvdata(dev->parent); 532943c1397SFelipe Balbi const struct dsps_musb_wrapper *wrp = glue->wrp; 533943c1397SFelipe Balbi void __iomem *ctrl_base = musb->ctrl_base; 534943c1397SFelipe Balbi u32 reg; 535943c1397SFelipe Balbi 536086b2882SBin Liu reg = musb_readl(ctrl_base, wrp->mode); 537943c1397SFelipe Balbi 538943c1397SFelipe Balbi switch (mode) { 539943c1397SFelipe Balbi case MUSB_HOST: 540943c1397SFelipe Balbi reg &= ~(1 << wrp->iddig); 541943c1397SFelipe Balbi 542943c1397SFelipe Balbi /* 543943c1397SFelipe Balbi * if we're setting mode to host-only or device-only, we're 544943c1397SFelipe Balbi * going to ignore whatever the PHY sends us and just force 545943c1397SFelipe Balbi * ID pin status by SW 546943c1397SFelipe Balbi */ 547943c1397SFelipe Balbi reg |= (1 << wrp->iddig_mux); 548943c1397SFelipe Balbi 549086b2882SBin Liu musb_writel(ctrl_base, wrp->mode, reg); 550086b2882SBin Liu musb_writel(ctrl_base, wrp->phy_utmi, 0x02); 551943c1397SFelipe Balbi break; 552943c1397SFelipe Balbi case MUSB_PERIPHERAL: 553943c1397SFelipe Balbi reg |= (1 << wrp->iddig); 554943c1397SFelipe Balbi 555943c1397SFelipe Balbi /* 556943c1397SFelipe Balbi * if we're setting mode to host-only or device-only, we're 557943c1397SFelipe Balbi * going to ignore whatever the PHY sends us and just force 558943c1397SFelipe Balbi * ID pin status by SW 559943c1397SFelipe Balbi */ 560943c1397SFelipe Balbi reg |= (1 << wrp->iddig_mux); 561943c1397SFelipe Balbi 562086b2882SBin Liu musb_writel(ctrl_base, wrp->mode, reg); 563943c1397SFelipe Balbi break; 564943c1397SFelipe Balbi case MUSB_OTG: 565086b2882SBin Liu musb_writel(ctrl_base, wrp->phy_utmi, 0x02); 566943c1397SFelipe Balbi break; 567943c1397SFelipe Balbi default: 568943c1397SFelipe Balbi dev_err(glue->dev, "unsupported mode %d\n", mode); 569943c1397SFelipe Balbi return -EINVAL; 570943c1397SFelipe Balbi } 571943c1397SFelipe Balbi 572943c1397SFelipe Balbi return 0; 573943c1397SFelipe Balbi } 574943c1397SFelipe Balbi 5753709ffcaSFelipe Balbi static bool dsps_sw_babble_control(struct musb *musb) 576371254ceSGeorge Cherian { 577371254ceSGeorge Cherian u8 babble_ctl; 578371254ceSGeorge Cherian bool session_restart = false; 579371254ceSGeorge Cherian 580086b2882SBin Liu babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL); 581371254ceSGeorge Cherian dev_dbg(musb->controller, "babble: MUSB_BABBLE_CTL value %x\n", 582371254ceSGeorge Cherian babble_ctl); 583371254ceSGeorge Cherian /* 584371254ceSGeorge Cherian * check line monitor flag to check whether babble is 585371254ceSGeorge Cherian * due to noise 586371254ceSGeorge Cherian */ 587371254ceSGeorge Cherian dev_dbg(musb->controller, "STUCK_J is %s\n", 588371254ceSGeorge Cherian babble_ctl & MUSB_BABBLE_STUCK_J ? "set" : "reset"); 589371254ceSGeorge Cherian 590371254ceSGeorge Cherian if (babble_ctl & MUSB_BABBLE_STUCK_J) { 591371254ceSGeorge Cherian int timeout = 10; 592371254ceSGeorge Cherian 593371254ceSGeorge Cherian /* 594371254ceSGeorge Cherian * babble is due to noise, then set transmit idle (d7 bit) 595371254ceSGeorge Cherian * to resume normal operation 596371254ceSGeorge Cherian */ 597086b2882SBin Liu babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL); 598371254ceSGeorge Cherian babble_ctl |= MUSB_BABBLE_FORCE_TXIDLE; 599086b2882SBin Liu musb_writeb(musb->mregs, MUSB_BABBLE_CTL, babble_ctl); 600371254ceSGeorge Cherian 601371254ceSGeorge Cherian /* wait till line monitor flag cleared */ 602371254ceSGeorge Cherian dev_dbg(musb->controller, "Set TXIDLE, wait J to clear\n"); 603371254ceSGeorge Cherian do { 604086b2882SBin Liu babble_ctl = musb_readb(musb->mregs, MUSB_BABBLE_CTL); 605371254ceSGeorge Cherian udelay(1); 606371254ceSGeorge Cherian } while ((babble_ctl & MUSB_BABBLE_STUCK_J) && timeout--); 607371254ceSGeorge Cherian 608371254ceSGeorge Cherian /* check whether stuck_at_j bit cleared */ 609371254ceSGeorge Cherian if (babble_ctl & MUSB_BABBLE_STUCK_J) { 610371254ceSGeorge Cherian /* 611371254ceSGeorge Cherian * real babble condition has occurred 612371254ceSGeorge Cherian * restart the controller to start the 613371254ceSGeorge Cherian * session again 614371254ceSGeorge Cherian */ 615371254ceSGeorge Cherian dev_dbg(musb->controller, "J not cleared, misc (%x)\n", 616371254ceSGeorge Cherian babble_ctl); 617371254ceSGeorge Cherian session_restart = true; 618371254ceSGeorge Cherian } 619371254ceSGeorge Cherian } else { 620371254ceSGeorge Cherian session_restart = true; 621371254ceSGeorge Cherian } 622371254ceSGeorge Cherian 623371254ceSGeorge Cherian return session_restart; 624371254ceSGeorge Cherian } 625371254ceSGeorge Cherian 626b28a6432SFelipe Balbi static int dsps_musb_recover(struct musb *musb) 6271d57de30SDaniel Mack { 6281d57de30SDaniel Mack struct device *dev = musb->controller; 6291d57de30SDaniel Mack struct dsps_glue *glue = dev_get_drvdata(dev->parent); 630011d0dd5SFelipe Balbi int session_restart = 0; 6311d57de30SDaniel Mack 632371254ceSGeorge Cherian if (glue->sw_babble_enabled) 6333709ffcaSFelipe Balbi session_restart = dsps_sw_babble_control(musb); 634011d0dd5SFelipe Balbi else 635371254ceSGeorge Cherian session_restart = 1; 63656700178SGeorge Cherian 637d0cddae7SFelipe Balbi return session_restart ? 0 : -EPIPE; 6381d57de30SDaniel Mack } 6391d57de30SDaniel Mack 6403e457371STony Lindgren /* Similar to am35x, dm81xx support only 32-bit read operation */ 6413e457371STony Lindgren static void dsps_read_fifo32(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) 6423e457371STony Lindgren { 6433e457371STony Lindgren void __iomem *fifo = hw_ep->fifo; 6443e457371STony Lindgren 6453e457371STony Lindgren if (len >= 4) { 646d30323f8STony Lindgren ioread32_rep(fifo, dst, len >> 2); 6473e457371STony Lindgren dst += len & ~0x03; 6483e457371STony Lindgren len &= 0x03; 6493e457371STony Lindgren } 6503e457371STony Lindgren 6513e457371STony Lindgren /* Read any remaining 1 to 3 bytes */ 6523e457371STony Lindgren if (len > 0) { 6533e457371STony Lindgren u32 val = musb_readl(fifo, 0); 6543e457371STony Lindgren memcpy(dst, &val, len); 6553e457371STony Lindgren } 6563e457371STony Lindgren } 6573e457371STony Lindgren 65825534828SAlexandre Bailon #ifdef CONFIG_USB_TI_CPPI41_DMA 65925534828SAlexandre Bailon static void dsps_dma_controller_callback(struct dma_controller *c) 66025534828SAlexandre Bailon { 66125534828SAlexandre Bailon struct musb *musb = c->musb; 66225534828SAlexandre Bailon struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent); 66325534828SAlexandre Bailon void __iomem *usbss_base = glue->usbss_base; 66425534828SAlexandre Bailon u32 status; 66525534828SAlexandre Bailon 66625534828SAlexandre Bailon status = musb_readl(usbss_base, USBSS_IRQ_STATUS); 66725534828SAlexandre Bailon if (status & USBSS_IRQ_PD_COMP) 66825534828SAlexandre Bailon musb_writel(usbss_base, USBSS_IRQ_STATUS, USBSS_IRQ_PD_COMP); 66925534828SAlexandre Bailon } 67025534828SAlexandre Bailon 67125534828SAlexandre Bailon static struct dma_controller * 67225534828SAlexandre Bailon dsps_dma_controller_create(struct musb *musb, void __iomem *base) 67325534828SAlexandre Bailon { 67425534828SAlexandre Bailon struct dma_controller *controller; 67525534828SAlexandre Bailon struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent); 67625534828SAlexandre Bailon void __iomem *usbss_base = glue->usbss_base; 67725534828SAlexandre Bailon 67825534828SAlexandre Bailon controller = cppi41_dma_controller_create(musb, base); 67925534828SAlexandre Bailon if (IS_ERR_OR_NULL(controller)) 68025534828SAlexandre Bailon return controller; 68125534828SAlexandre Bailon 68225534828SAlexandre Bailon musb_writel(usbss_base, USBSS_IRQ_ENABLER, USBSS_IRQ_PD_COMP); 68325534828SAlexandre Bailon controller->dma_callback = dsps_dma_controller_callback; 68425534828SAlexandre Bailon 68525534828SAlexandre Bailon return controller; 68625534828SAlexandre Bailon } 68725534828SAlexandre Bailon 68825534828SAlexandre Bailon static void dsps_dma_controller_destroy(struct dma_controller *c) 68925534828SAlexandre Bailon { 69025534828SAlexandre Bailon struct musb *musb = c->musb; 69125534828SAlexandre Bailon struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent); 69225534828SAlexandre Bailon void __iomem *usbss_base = glue->usbss_base; 69325534828SAlexandre Bailon 69425534828SAlexandre Bailon musb_writel(usbss_base, USBSS_IRQ_CLEARR, USBSS_IRQ_PD_COMP); 69525534828SAlexandre Bailon cppi41_dma_controller_destroy(c); 69625534828SAlexandre Bailon } 69725534828SAlexandre Bailon 69825534828SAlexandre Bailon #ifdef CONFIG_PM_SLEEP 69925534828SAlexandre Bailon static void dsps_dma_controller_suspend(struct dsps_glue *glue) 70025534828SAlexandre Bailon { 70125534828SAlexandre Bailon void __iomem *usbss_base = glue->usbss_base; 70225534828SAlexandre Bailon 70325534828SAlexandre Bailon musb_writel(usbss_base, USBSS_IRQ_CLEARR, USBSS_IRQ_PD_COMP); 70425534828SAlexandre Bailon } 70525534828SAlexandre Bailon 70625534828SAlexandre Bailon static void dsps_dma_controller_resume(struct dsps_glue *glue) 70725534828SAlexandre Bailon { 70825534828SAlexandre Bailon void __iomem *usbss_base = glue->usbss_base; 70925534828SAlexandre Bailon 71025534828SAlexandre Bailon musb_writel(usbss_base, USBSS_IRQ_ENABLER, USBSS_IRQ_PD_COMP); 71125534828SAlexandre Bailon } 71225534828SAlexandre Bailon #endif 71325534828SAlexandre Bailon #else /* CONFIG_USB_TI_CPPI41_DMA */ 71425534828SAlexandre Bailon #ifdef CONFIG_PM_SLEEP 71525534828SAlexandre Bailon static void dsps_dma_controller_suspend(struct dsps_glue *glue) {} 71625534828SAlexandre Bailon static void dsps_dma_controller_resume(struct dsps_glue *glue) {} 71725534828SAlexandre Bailon #endif 71825534828SAlexandre Bailon #endif /* CONFIG_USB_TI_CPPI41_DMA */ 71925534828SAlexandre Bailon 7209ecb8875SAjay Kumar Gupta static struct musb_platform_ops dsps_ops = { 721f8e9f34fSTony Lindgren .quirks = MUSB_DMA_CPPI41 | MUSB_INDEXED_EP, 7229ecb8875SAjay Kumar Gupta .init = dsps_musb_init, 7239ecb8875SAjay Kumar Gupta .exit = dsps_musb_exit, 7249ecb8875SAjay Kumar Gupta 7257f6283edSTony Lindgren #ifdef CONFIG_USB_TI_CPPI41_DMA 72625534828SAlexandre Bailon .dma_init = dsps_dma_controller_create, 72725534828SAlexandre Bailon .dma_exit = dsps_dma_controller_destroy, 7287f6283edSTony Lindgren #endif 7299ecb8875SAjay Kumar Gupta .enable = dsps_musb_enable, 7309ecb8875SAjay Kumar Gupta .disable = dsps_musb_disable, 7319ecb8875SAjay Kumar Gupta 732943c1397SFelipe Balbi .set_mode = dsps_musb_set_mode, 733b28a6432SFelipe Balbi .recover = dsps_musb_recover, 734c48400baSBin Liu .clear_ep_rxintr = dsps_musb_clear_ep_rxintr, 7359ecb8875SAjay Kumar Gupta }; 7369ecb8875SAjay Kumar Gupta 7379ecb8875SAjay Kumar Gupta static u64 musb_dmamask = DMA_BIT_MASK(32); 7389ecb8875SAjay Kumar Gupta 73997238b35SSebastian Andrzej Siewior static int get_int_prop(struct device_node *dn, const char *s) 7409ecb8875SAjay Kumar Gupta { 74197238b35SSebastian Andrzej Siewior int ret; 74297238b35SSebastian Andrzej Siewior u32 val; 74397238b35SSebastian Andrzej Siewior 74497238b35SSebastian Andrzej Siewior ret = of_property_read_u32(dn, s, &val); 74597238b35SSebastian Andrzej Siewior if (ret) 74697238b35SSebastian Andrzej Siewior return 0; 74797238b35SSebastian Andrzej Siewior return val; 74897238b35SSebastian Andrzej Siewior } 74997238b35SSebastian Andrzej Siewior 750c031a7d4SSebastian Andrzej Siewior static int get_musb_port_mode(struct device *dev) 751c031a7d4SSebastian Andrzej Siewior { 752c031a7d4SSebastian Andrzej Siewior enum usb_dr_mode mode; 753c031a7d4SSebastian Andrzej Siewior 75406e7114fSHeikki Krogerus mode = usb_get_dr_mode(dev); 755c031a7d4SSebastian Andrzej Siewior switch (mode) { 756c031a7d4SSebastian Andrzej Siewior case USB_DR_MODE_HOST: 757c031a7d4SSebastian Andrzej Siewior return MUSB_PORT_MODE_HOST; 758c031a7d4SSebastian Andrzej Siewior 759c031a7d4SSebastian Andrzej Siewior case USB_DR_MODE_PERIPHERAL: 760c031a7d4SSebastian Andrzej Siewior return MUSB_PORT_MODE_GADGET; 761c031a7d4SSebastian Andrzej Siewior 762c031a7d4SSebastian Andrzej Siewior case USB_DR_MODE_UNKNOWN: 763c031a7d4SSebastian Andrzej Siewior case USB_DR_MODE_OTG: 764c031a7d4SSebastian Andrzej Siewior default: 765c031a7d4SSebastian Andrzej Siewior return MUSB_PORT_MODE_DUAL_ROLE; 7662b84f92bSJoe Perches } 767c031a7d4SSebastian Andrzej Siewior } 768c031a7d4SSebastian Andrzej Siewior 76997238b35SSebastian Andrzej Siewior static int dsps_create_musb_pdev(struct dsps_glue *glue, 77097238b35SSebastian Andrzej Siewior struct platform_device *parent) 77197238b35SSebastian Andrzej Siewior { 77297238b35SSebastian Andrzej Siewior struct musb_hdrc_platform_data pdata; 77397238b35SSebastian Andrzej Siewior struct resource resources[2]; 774c031a7d4SSebastian Andrzej Siewior struct resource *res; 77597238b35SSebastian Andrzej Siewior struct device *dev = &parent->dev; 77665145677SAjay Kumar Gupta struct musb_hdrc_config *config; 7779ecb8875SAjay Kumar Gupta struct platform_device *musb; 77897238b35SSebastian Andrzej Siewior struct device_node *dn = parent->dev.of_node; 779606bf4d5STony Lindgren int ret, val; 7809ecb8875SAjay Kumar Gupta 78197238b35SSebastian Andrzej Siewior memset(resources, 0, sizeof(resources)); 782c031a7d4SSebastian Andrzej Siewior res = platform_get_resource_byname(parent, IORESOURCE_MEM, "mc"); 783c031a7d4SSebastian Andrzej Siewior if (!res) { 78497238b35SSebastian Andrzej Siewior dev_err(dev, "failed to get memory.\n"); 785c031a7d4SSebastian Andrzej Siewior return -EINVAL; 7869ecb8875SAjay Kumar Gupta } 787c031a7d4SSebastian Andrzej Siewior resources[0] = *res; 78897238b35SSebastian Andrzej Siewior 789c031a7d4SSebastian Andrzej Siewior res = platform_get_resource_byname(parent, IORESOURCE_IRQ, "mc"); 790c031a7d4SSebastian Andrzej Siewior if (!res) { 79197238b35SSebastian Andrzej Siewior dev_err(dev, "failed to get irq.\n"); 792c031a7d4SSebastian Andrzej Siewior return -EINVAL; 79397238b35SSebastian Andrzej Siewior } 794c031a7d4SSebastian Andrzej Siewior resources[1] = *res; 7959ecb8875SAjay Kumar Gupta 79665b3d52dSB, Ravi /* allocate the child platform device */ 79745abfa68SBin Liu musb = platform_device_alloc("musb-hdrc", 79845abfa68SBin Liu (resources[0].start & 0xFFF) == 0x400 ? 0 : 1); 79965b3d52dSB, Ravi if (!musb) { 80065b3d52dSB, Ravi dev_err(dev, "failed to allocate musb device\n"); 80197238b35SSebastian Andrzej Siewior return -ENOMEM; 80265b3d52dSB, Ravi } 8039ecb8875SAjay Kumar Gupta 8049ecb8875SAjay Kumar Gupta musb->dev.parent = dev; 8059ecb8875SAjay Kumar Gupta musb->dev.dma_mask = &musb_dmamask; 8069ecb8875SAjay Kumar Gupta musb->dev.coherent_dma_mask = musb_dmamask; 8079ecb8875SAjay Kumar Gupta 80897238b35SSebastian Andrzej Siewior glue->musb = musb; 8099ecb8875SAjay Kumar Gupta 81097238b35SSebastian Andrzej Siewior ret = platform_device_add_resources(musb, resources, 81197238b35SSebastian Andrzej Siewior ARRAY_SIZE(resources)); 8129ecb8875SAjay Kumar Gupta if (ret) { 8139ecb8875SAjay Kumar Gupta dev_err(dev, "failed to add resources\n"); 81497238b35SSebastian Andrzej Siewior goto err; 8159ecb8875SAjay Kumar Gupta } 8169ecb8875SAjay Kumar Gupta 81797238b35SSebastian Andrzej Siewior config = devm_kzalloc(&parent->dev, sizeof(*config), GFP_KERNEL); 81865145677SAjay Kumar Gupta if (!config) { 819b25e5f1cSWei Yongjun ret = -ENOMEM; 82097238b35SSebastian Andrzej Siewior goto err; 82165145677SAjay Kumar Gupta } 82297238b35SSebastian Andrzej Siewior pdata.config = config; 82397238b35SSebastian Andrzej Siewior pdata.platform_ops = &dsps_ops; 82465145677SAjay Kumar Gupta 825c031a7d4SSebastian Andrzej Siewior config->num_eps = get_int_prop(dn, "mentor,num-eps"); 826c031a7d4SSebastian Andrzej Siewior config->ram_bits = get_int_prop(dn, "mentor,ram-bits"); 827869c5978SDaniel Mack config->host_port_deassert_reset_at_resume = 1; 828c031a7d4SSebastian Andrzej Siewior pdata.mode = get_musb_port_mode(dev); 829c031a7d4SSebastian Andrzej Siewior /* DT keeps this entry in mA, musb expects it as per USB spec */ 830c031a7d4SSebastian Andrzej Siewior pdata.power = get_int_prop(dn, "mentor,power") / 2; 831606bf4d5STony Lindgren 832606bf4d5STony Lindgren ret = of_property_read_u32(dn, "mentor,multipoint", &val); 833606bf4d5STony Lindgren if (!ret && val) 834606bf4d5STony Lindgren config->multipoint = true; 83565145677SAjay Kumar Gupta 83663863b98SHeikki Krogerus config->maximum_speed = usb_get_maximum_speed(&parent->dev); 83741932b9bSBin Liu switch (config->maximum_speed) { 83841932b9bSBin Liu case USB_SPEED_LOW: 83941932b9bSBin Liu case USB_SPEED_FULL: 84041932b9bSBin Liu break; 84141932b9bSBin Liu case USB_SPEED_SUPER: 84241932b9bSBin Liu dev_warn(dev, "ignore incorrect maximum_speed " 84341932b9bSBin Liu "(super-speed) setting in dts"); 84441932b9bSBin Liu /* fall through */ 84541932b9bSBin Liu default: 84641932b9bSBin Liu config->maximum_speed = USB_SPEED_HIGH; 84741932b9bSBin Liu } 84841932b9bSBin Liu 84997238b35SSebastian Andrzej Siewior ret = platform_device_add_data(musb, &pdata, sizeof(pdata)); 8509ecb8875SAjay Kumar Gupta if (ret) { 8519ecb8875SAjay Kumar Gupta dev_err(dev, "failed to add platform_data\n"); 85297238b35SSebastian Andrzej Siewior goto err; 8539ecb8875SAjay Kumar Gupta } 8549ecb8875SAjay Kumar Gupta 8559ecb8875SAjay Kumar Gupta ret = platform_device_add(musb); 8569ecb8875SAjay Kumar Gupta if (ret) { 8579ecb8875SAjay Kumar Gupta dev_err(dev, "failed to register musb device\n"); 85897238b35SSebastian Andrzej Siewior goto err; 8599ecb8875SAjay Kumar Gupta } 8609ecb8875SAjay Kumar Gupta return 0; 8619ecb8875SAjay Kumar Gupta 86297238b35SSebastian Andrzej Siewior err: 8639ecb8875SAjay Kumar Gupta platform_device_put(musb); 8649ecb8875SAjay Kumar Gupta return ret; 8659ecb8875SAjay Kumar Gupta } 8669ecb8875SAjay Kumar Gupta 867369469a9STony Lindgren static irqreturn_t dsps_vbus_threaded_irq(int irq, void *priv) 868369469a9STony Lindgren { 869369469a9STony Lindgren struct dsps_glue *glue = priv; 870369469a9STony Lindgren struct musb *musb = platform_get_drvdata(glue->musb); 871369469a9STony Lindgren 872369469a9STony Lindgren if (!musb) 873369469a9STony Lindgren return IRQ_NONE; 874369469a9STony Lindgren 875369469a9STony Lindgren dev_dbg(glue->dev, "VBUS interrupt\n"); 876369469a9STony Lindgren dsps_mod_timer(glue, 0); 877369469a9STony Lindgren 878369469a9STony Lindgren return IRQ_HANDLED; 879369469a9STony Lindgren } 880369469a9STony Lindgren 881369469a9STony Lindgren static int dsps_setup_optional_vbus_irq(struct platform_device *pdev, 882369469a9STony Lindgren struct dsps_glue *glue) 883369469a9STony Lindgren { 884369469a9STony Lindgren int error; 885369469a9STony Lindgren 886369469a9STony Lindgren glue->vbus_irq = platform_get_irq_byname(pdev, "vbus"); 887369469a9STony Lindgren if (glue->vbus_irq == -EPROBE_DEFER) 888369469a9STony Lindgren return -EPROBE_DEFER; 889369469a9STony Lindgren 890369469a9STony Lindgren if (glue->vbus_irq <= 0) { 891369469a9STony Lindgren glue->vbus_irq = 0; 892369469a9STony Lindgren return 0; 893369469a9STony Lindgren } 894369469a9STony Lindgren 895369469a9STony Lindgren error = devm_request_threaded_irq(glue->dev, glue->vbus_irq, 896369469a9STony Lindgren NULL, dsps_vbus_threaded_irq, 897369469a9STony Lindgren IRQF_ONESHOT, 898369469a9STony Lindgren "vbus", glue); 899369469a9STony Lindgren if (error) { 900369469a9STony Lindgren glue->vbus_irq = 0; 901369469a9STony Lindgren return error; 902369469a9STony Lindgren } 903369469a9STony Lindgren dev_dbg(glue->dev, "VBUS irq %i configured\n", glue->vbus_irq); 904369469a9STony Lindgren 905369469a9STony Lindgren return 0; 906369469a9STony Lindgren } 907369469a9STony Lindgren 90841ac7b3aSBill Pemberton static int dsps_probe(struct platform_device *pdev) 9099ecb8875SAjay Kumar Gupta { 91065145677SAjay Kumar Gupta const struct of_device_id *match; 91165145677SAjay Kumar Gupta const struct dsps_musb_wrapper *wrp; 9129ecb8875SAjay Kumar Gupta struct dsps_glue *glue; 91397238b35SSebastian Andrzej Siewior int ret; 9149ecb8875SAjay Kumar Gupta 9154fc4b274SSebastian Andrzej Siewior if (!strcmp(pdev->name, "musb-hdrc")) 9164fc4b274SSebastian Andrzej Siewior return -ENODEV; 9174fc4b274SSebastian Andrzej Siewior 918cc506036SFelipe Balbi match = of_match_node(musb_dsps_of_match, pdev->dev.of_node); 91965145677SAjay Kumar Gupta if (!match) { 92065145677SAjay Kumar Gupta dev_err(&pdev->dev, "fail to get matching of_match struct\n"); 92197238b35SSebastian Andrzej Siewior return -EINVAL; 92265145677SAjay Kumar Gupta } 92365145677SAjay Kumar Gupta wrp = match->data; 9249ecb8875SAjay Kumar Gupta 9253e457371STony Lindgren if (of_device_is_compatible(pdev->dev.of_node, "ti,musb-dm816")) 9263e457371STony Lindgren dsps_ops.read_fifo = dsps_read_fifo32; 9273e457371STony Lindgren 9289ecb8875SAjay Kumar Gupta /* allocate glue */ 929de9db572SMarkus Pargmann glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); 9300816ea2fSPeter Chen if (!glue) 93197238b35SSebastian Andrzej Siewior return -ENOMEM; 9329ecb8875SAjay Kumar Gupta 9339ecb8875SAjay Kumar Gupta glue->dev = &pdev->dev; 93497238b35SSebastian Andrzej Siewior glue->wrp = wrp; 93525534828SAlexandre Bailon glue->usbss_base = of_iomap(pdev->dev.parent->of_node, 0); 93625534828SAlexandre Bailon if (!glue->usbss_base) 93725534828SAlexandre Bailon return -ENXIO; 9389ecb8875SAjay Kumar Gupta 939369469a9STony Lindgren if (usb_get_dr_mode(&pdev->dev) == USB_DR_MODE_PERIPHERAL) { 940369469a9STony Lindgren ret = dsps_setup_optional_vbus_irq(pdev, glue); 941369469a9STony Lindgren if (ret) 9426b7ad496SBin Liu goto err_iounmap; 943369469a9STony Lindgren } 944369469a9STony Lindgren 9459ecb8875SAjay Kumar Gupta platform_set_drvdata(pdev, glue); 9469ecb8875SAjay Kumar Gupta pm_runtime_enable(&pdev->dev); 94797238b35SSebastian Andrzej Siewior ret = dsps_create_musb_pdev(glue, pdev); 94897238b35SSebastian Andrzej Siewior if (ret) 94924752917STony Lindgren goto err; 95065b3f50eSTony Lindgren 9519ecb8875SAjay Kumar Gupta return 0; 9529ecb8875SAjay Kumar Gupta 95324752917STony Lindgren err: 9540e38c4edSAjay Kumar Gupta pm_runtime_disable(&pdev->dev); 9556b7ad496SBin Liu err_iounmap: 9566b7ad496SBin Liu iounmap(glue->usbss_base); 9579ecb8875SAjay Kumar Gupta return ret; 9589ecb8875SAjay Kumar Gupta } 95997238b35SSebastian Andrzej Siewior 960fb4e98abSBill Pemberton static int dsps_remove(struct platform_device *pdev) 9619ecb8875SAjay Kumar Gupta { 9629ecb8875SAjay Kumar Gupta struct dsps_glue *glue = platform_get_drvdata(pdev); 9639ecb8875SAjay Kumar Gupta 96497238b35SSebastian Andrzej Siewior platform_device_unregister(glue->musb); 9659ecb8875SAjay Kumar Gupta 9669ecb8875SAjay Kumar Gupta pm_runtime_disable(&pdev->dev); 9676b7ad496SBin Liu iounmap(glue->usbss_base); 96840f099e3SMarkus Pargmann 9699ecb8875SAjay Kumar Gupta return 0; 9709ecb8875SAjay Kumar Gupta } 9719ecb8875SAjay Kumar Gupta 972fa7b4ca5SSebastian Andrzej Siewior static const struct dsps_musb_wrapper am33xx_driver_data = { 9739ecb8875SAjay Kumar Gupta .revision = 0x00, 9749ecb8875SAjay Kumar Gupta .control = 0x14, 9759ecb8875SAjay Kumar Gupta .status = 0x18, 9769ecb8875SAjay Kumar Gupta .epintr_set = 0x38, 9779ecb8875SAjay Kumar Gupta .epintr_clear = 0x40, 9789ecb8875SAjay Kumar Gupta .epintr_status = 0x30, 9799ecb8875SAjay Kumar Gupta .coreintr_set = 0x3c, 9809ecb8875SAjay Kumar Gupta .coreintr_clear = 0x44, 9819ecb8875SAjay Kumar Gupta .coreintr_status = 0x34, 9829ecb8875SAjay Kumar Gupta .phy_utmi = 0xe0, 9839ecb8875SAjay Kumar Gupta .mode = 0xe8, 984b991f9b7SDaniel Mack .tx_mode = 0x70, 985b991f9b7SDaniel Mack .rx_mode = 0x74, 9869ecb8875SAjay Kumar Gupta .reset = 0, 9879ecb8875SAjay Kumar Gupta .otg_disable = 21, 9889ecb8875SAjay Kumar Gupta .iddig = 8, 989943c1397SFelipe Balbi .iddig_mux = 7, 9909ecb8875SAjay Kumar Gupta .usb_shift = 0, 9919ecb8875SAjay Kumar Gupta .usb_mask = 0x1ff, 9929ecb8875SAjay Kumar Gupta .usb_bitmap = (0x1ff << 0), 9939ecb8875SAjay Kumar Gupta .drvvbus = 8, 9949ecb8875SAjay Kumar Gupta .txep_shift = 0, 9959ecb8875SAjay Kumar Gupta .txep_mask = 0xffff, 9969ecb8875SAjay Kumar Gupta .txep_bitmap = (0xffff << 0), 9979ecb8875SAjay Kumar Gupta .rxep_shift = 16, 9989ecb8875SAjay Kumar Gupta .rxep_mask = 0xfffe, 9999ecb8875SAjay Kumar Gupta .rxep_bitmap = (0xfffe << 16), 10009e204d88SFelipe Balbi .poll_timeout = 2000, /* ms */ 10019ecb8875SAjay Kumar Gupta }; 10029ecb8875SAjay Kumar Gupta 10032f82686eSBill Pemberton static const struct of_device_id musb_dsps_of_match[] = { 100465145677SAjay Kumar Gupta { .compatible = "ti,musb-am33xx", 10053e457371STony Lindgren .data = &am33xx_driver_data, }, 10063e457371STony Lindgren { .compatible = "ti,musb-dm816", 10073e457371STony Lindgren .data = &am33xx_driver_data, }, 10089ecb8875SAjay Kumar Gupta { }, 10099ecb8875SAjay Kumar Gupta }; 10109ecb8875SAjay Kumar Gupta MODULE_DEVICE_TABLE(of, musb_dsps_of_match); 10119ecb8875SAjay Kumar Gupta 10125b783983SWolfram Sang #ifdef CONFIG_PM_SLEEP 1013869c5978SDaniel Mack static int dsps_suspend(struct device *dev) 1014869c5978SDaniel Mack { 1015869c5978SDaniel Mack struct dsps_glue *glue = dev_get_drvdata(dev); 1016869c5978SDaniel Mack const struct dsps_musb_wrapper *wrp = glue->wrp; 1017869c5978SDaniel Mack struct musb *musb = platform_get_drvdata(glue->musb); 1018f042e9cbSSebastian Andrzej Siewior void __iomem *mbase; 1019706d61b2SJohan Hovold int ret; 1020f042e9cbSSebastian Andrzej Siewior 1021f042e9cbSSebastian Andrzej Siewior if (!musb) 1022f042e9cbSSebastian Andrzej Siewior /* This can happen if the musb device is in -EPROBE_DEFER */ 1023f042e9cbSSebastian Andrzej Siewior return 0; 1024f042e9cbSSebastian Andrzej Siewior 1025706d61b2SJohan Hovold ret = pm_runtime_get_sync(dev); 1026706d61b2SJohan Hovold if (ret < 0) { 1027706d61b2SJohan Hovold pm_runtime_put_noidle(dev); 1028706d61b2SJohan Hovold return ret; 1029706d61b2SJohan Hovold } 1030706d61b2SJohan Hovold 1031706d61b2SJohan Hovold del_timer_sync(&glue->timer); 1032706d61b2SJohan Hovold 1033f042e9cbSSebastian Andrzej Siewior mbase = musb->ctrl_base; 1034086b2882SBin Liu glue->context.control = musb_readl(mbase, wrp->control); 1035086b2882SBin Liu glue->context.epintr = musb_readl(mbase, wrp->epintr_set); 1036086b2882SBin Liu glue->context.coreintr = musb_readl(mbase, wrp->coreintr_set); 1037086b2882SBin Liu glue->context.phy_utmi = musb_readl(mbase, wrp->phy_utmi); 1038086b2882SBin Liu glue->context.mode = musb_readl(mbase, wrp->mode); 1039086b2882SBin Liu glue->context.tx_mode = musb_readl(mbase, wrp->tx_mode); 1040086b2882SBin Liu glue->context.rx_mode = musb_readl(mbase, wrp->rx_mode); 1041869c5978SDaniel Mack 104225534828SAlexandre Bailon dsps_dma_controller_suspend(glue); 104325534828SAlexandre Bailon 1044869c5978SDaniel Mack return 0; 1045869c5978SDaniel Mack } 1046869c5978SDaniel Mack 1047869c5978SDaniel Mack static int dsps_resume(struct device *dev) 1048869c5978SDaniel Mack { 1049869c5978SDaniel Mack struct dsps_glue *glue = dev_get_drvdata(dev); 1050869c5978SDaniel Mack const struct dsps_musb_wrapper *wrp = glue->wrp; 1051869c5978SDaniel Mack struct musb *musb = platform_get_drvdata(glue->musb); 1052f042e9cbSSebastian Andrzej Siewior void __iomem *mbase; 1053869c5978SDaniel Mack 1054f042e9cbSSebastian Andrzej Siewior if (!musb) 1055f042e9cbSSebastian Andrzej Siewior return 0; 1056f042e9cbSSebastian Andrzej Siewior 105725534828SAlexandre Bailon dsps_dma_controller_resume(glue); 105825534828SAlexandre Bailon 1059f042e9cbSSebastian Andrzej Siewior mbase = musb->ctrl_base; 1060086b2882SBin Liu musb_writel(mbase, wrp->control, glue->context.control); 1061086b2882SBin Liu musb_writel(mbase, wrp->epintr_set, glue->context.epintr); 1062086b2882SBin Liu musb_writel(mbase, wrp->coreintr_set, glue->context.coreintr); 1063086b2882SBin Liu musb_writel(mbase, wrp->phy_utmi, glue->context.phy_utmi); 1064086b2882SBin Liu musb_writel(mbase, wrp->mode, glue->context.mode); 1065086b2882SBin Liu musb_writel(mbase, wrp->tx_mode, glue->context.tx_mode); 1066086b2882SBin Liu musb_writel(mbase, wrp->rx_mode, glue->context.rx_mode); 1067e47d9254SAntoine Tenart if (musb->xceiv->otg->state == OTG_STATE_B_IDLE && 106853185b3aSSebastian Andrzej Siewior musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) 1069369469a9STony Lindgren dsps_mod_timer(glue, -1); 1070869c5978SDaniel Mack 1071706d61b2SJohan Hovold pm_runtime_put(dev); 1072706d61b2SJohan Hovold 1073869c5978SDaniel Mack return 0; 1074869c5978SDaniel Mack } 1075869c5978SDaniel Mack #endif 1076869c5978SDaniel Mack 1077869c5978SDaniel Mack static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume); 1078869c5978SDaniel Mack 10799ecb8875SAjay Kumar Gupta static struct platform_driver dsps_usbss_driver = { 10809ecb8875SAjay Kumar Gupta .probe = dsps_probe, 10817690417dSBill Pemberton .remove = dsps_remove, 10829ecb8875SAjay Kumar Gupta .driver = { 10839ecb8875SAjay Kumar Gupta .name = "musb-dsps", 1084869c5978SDaniel Mack .pm = &dsps_pm_ops, 1085b432cb83SSachin Kamat .of_match_table = musb_dsps_of_match, 10869ecb8875SAjay Kumar Gupta }, 10879ecb8875SAjay Kumar Gupta }; 10889ecb8875SAjay Kumar Gupta 10899ecb8875SAjay Kumar Gupta MODULE_DESCRIPTION("TI DSPS MUSB Glue Layer"); 10909ecb8875SAjay Kumar Gupta MODULE_AUTHOR("Ravi B <ravibabu@ti.com>"); 10919ecb8875SAjay Kumar Gupta MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>"); 10929ecb8875SAjay Kumar Gupta MODULE_LICENSE("GPL v2"); 10939ecb8875SAjay Kumar Gupta 109497238b35SSebastian Andrzej Siewior module_platform_driver(dsps_usbss_driver); 1095