static void otg_timer(unsigned long _musb) { struct musb *musb = (void *)_musb; void __iomem *mregs = musb->mregs; struct device *dev = musb->controller; struct dsps_glue *glue = dev_get_drvdata(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; u8 devctl; unsigned long flags; int skip_session = 0; /* * We poll because DSPS IP's won't expose several OTG-critical * status change events (from the transceiver) otherwise. */ devctl = dsps_readb(mregs, MUSB_DEVCTL); dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl, usb_otg_state_string(musb->xceiv->otg->state)); spin_lock_irqsave(&musb->lock, flags); switch (musb->xceiv->otg->state) { case OTG_STATE_A_WAIT_BCON: dsps_writeb(musb->mregs, MUSB_DEVCTL, 0); skip_session = 1; /* fall */ case OTG_STATE_A_IDLE: case OTG_STATE_B_IDLE: if (devctl & MUSB_DEVCTL_BDEVICE) { musb->xceiv->otg->state = OTG_STATE_B_IDLE; MUSB_DEV_MODE(musb); } else { musb->xceiv->otg->state = OTG_STATE_A_IDLE; MUSB_HST_MODE(musb); } if (!(devctl & MUSB_DEVCTL_SESSION) && !skip_session) dsps_writeb(mregs, MUSB_DEVCTL, MUSB_DEVCTL_SESSION); mod_timer(&glue->timer, jiffies + msecs_to_jiffies(wrp->poll_timeout)); break; case OTG_STATE_A_WAIT_VFALL: musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; dsps_writel(musb->ctrl_base, wrp->coreintr_set, MUSB_INTR_VBUSERROR << wrp->usb_shift); break; default: break; } spin_unlock_irqrestore(&musb->lock, flags); }
static int dsps_musb_init(struct musb *musb) { struct device *dev = musb->controller; struct dsps_glue *glue = dev_get_drvdata(dev->parent); struct platform_device *parent = to_platform_device(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; void __iomem *reg_base; struct resource *r; u32 rev, val; int ret; r = platform_get_resource_byname(parent, IORESOURCE_MEM, "control"); reg_base = devm_ioremap_resource(dev, r); if (IS_ERR(reg_base)) return PTR_ERR(reg_base); musb->ctrl_base = reg_base; /* NOP driver needs change if supporting dual instance */ musb->xceiv = devm_usb_get_phy_by_phandle(dev, "phys", 0); if (IS_ERR(musb->xceiv)) return PTR_ERR(musb->xceiv); /* Returns zero if e.g. not clocked */ rev = dsps_readl(reg_base, wrp->revision); if (!rev) return -ENODEV; usb_phy_init(musb->xceiv); setup_timer(&glue->timer, otg_timer, (unsigned long) musb); /* Reset the musb */ dsps_writel(reg_base, wrp->control, (1 << wrp->reset)); musb->isr = dsps_interrupt; /* reset the otgdisable bit, needed for host mode to work */ val = dsps_readl(reg_base, wrp->phy_utmi); val &= ~(1 << wrp->otg_disable); dsps_writel(musb->ctrl_base, wrp->phy_utmi, val); /* * Check whether the dsps version has babble control enabled. * In latest silicon revision the babble control logic is enabled. * If MUSB_BABBLE_CTL returns 0x4 then we have the babble control * logic enabled. */ val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); if (val == MUSB_BABBLE_RCV_DISABLE) { glue->sw_babble_enabled = true; val |= MUSB_BABBLE_SW_SESSION_CTRL; dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val); } ret = dsps_musb_dbg_init(musb, glue); if (ret) return ret; return 0; }
static void otg_timer(unsigned long _musb) { struct musb *musb = (void *)_musb; void __iomem *mregs = musb->mregs; struct device *dev = musb->controller; struct platform_device *pdev = to_platform_device(dev); struct dsps_glue *glue = dev_get_drvdata(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; u8 devctl; unsigned long flags; /* * We poll because DSPS IP's won't expose several OTG-critical * status change events (from the transceiver) otherwise. */ devctl = dsps_readb(mregs, MUSB_DEVCTL); dev_dbg(musb->controller, "Poll devctl %02x (%s)\n", devctl, otg_state_string(musb->xceiv->state)); spin_lock_irqsave(&musb->lock, flags); switch (musb->xceiv->state) { case OTG_STATE_A_WAIT_BCON: /* * We need to avoid stopping the session in host mode, * otherwise we don't see any newly connected devices */ if (!is_host_active(musb)) { devctl &= ~MUSB_DEVCTL_SESSION; dsps_writeb(musb->mregs, MUSB_DEVCTL, devctl); } devctl = dsps_readb(musb->mregs, MUSB_DEVCTL); if (devctl & MUSB_DEVCTL_BDEVICE) { musb->xceiv->state = OTG_STATE_B_IDLE; MUSB_DEV_MODE(musb); } else { musb->xceiv->state = OTG_STATE_A_IDLE; MUSB_HST_MODE(musb); } break; case OTG_STATE_A_WAIT_VFALL: musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; dsps_writel(musb->ctrl_base, wrp->coreintr_set, MUSB_INTR_VBUSERROR << wrp->usb_shift); break; case OTG_STATE_B_IDLE: devctl = dsps_readb(mregs, MUSB_DEVCTL); if (devctl & MUSB_DEVCTL_BDEVICE) mod_timer(&glue->timer[pdev->id], jiffies + wrp->poll_seconds * HZ); else musb->xceiv->state = OTG_STATE_A_IDLE; break; default: break; } spin_unlock_irqrestore(&musb->lock, flags); }
/** * dsps_musb_disable - disable HDRC and flush interrupts */ static void dsps_musb_disable(struct musb *musb) { struct device *dev = musb->controller; struct platform_device *pdev = to_platform_device(dev->parent); struct dsps_glue *glue = platform_get_drvdata(pdev); const struct dsps_musb_wrapper *wrp = glue->wrp; void __iomem *reg_base = musb->ctrl_base; dsps_writel(reg_base, wrp->coreintr_clear, wrp->usb_bitmap); dsps_writel(reg_base, wrp->epintr_clear, wrp->txep_bitmap | wrp->rxep_bitmap); dsps_writeb(musb->mregs, MUSB_DEVCTL, 0); }
/** * dsps_musb_disable - disable HDRC and flush interrupts */ static void dsps_musb_disable(struct musb *musb) { struct device_d *dev = musb->controller; struct device_d *pdev = dev; struct dsps_glue *glue = pdev->priv; const struct dsps_musb_wrapper *wrp = glue->wrp; void __iomem *reg_base = musb->ctrl_base; dsps_writel(reg_base, wrp->coreintr_clear, wrp->usb_bitmap); dsps_writel(reg_base, wrp->epintr_clear, wrp->txep_bitmap | wrp->rxep_bitmap); dsps_writeb(musb->mregs, MUSB_DEVCTL, 0); }
static bool sw_babble_control(struct musb *musb) { u8 babble_ctl; bool session_restart = false; babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); dev_dbg(musb->controller, "babble: MUSB_BABBLE_CTL value %x\n", babble_ctl); /* * check line monitor flag to check whether babble is * due to noise */ dev_dbg(musb->controller, "STUCK_J is %s\n", babble_ctl & MUSB_BABBLE_STUCK_J ? "set" : "reset"); if (babble_ctl & MUSB_BABBLE_STUCK_J) { int timeout = 10; /* * babble is due to noise, then set transmit idle (d7 bit) * to resume normal operation */ babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); babble_ctl |= MUSB_BABBLE_FORCE_TXIDLE; dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, babble_ctl); /* wait till line monitor flag cleared */ dev_dbg(musb->controller, "Set TXIDLE, wait J to clear\n"); do { babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); udelay(1); } while ((babble_ctl & MUSB_BABBLE_STUCK_J) && timeout--); /* check whether stuck_at_j bit cleared */ if (babble_ctl & MUSB_BABBLE_STUCK_J) { /* * real babble condition has occurred * restart the controller to start the * session again */ dev_dbg(musb->controller, "J not cleared, misc (%x)\n", babble_ctl); session_restart = true; } } else { session_restart = true; } return session_restart; }