diff options
Diffstat (limited to 'drivers/usb/musb')
-rw-r--r-- | drivers/usb/musb/am35x.c | 3 | ||||
-rw-r--r-- | drivers/usb/musb/da8xx.c | 3 | ||||
-rw-r--r-- | drivers/usb/musb/davinci.c | 49 | ||||
-rw-r--r-- | drivers/usb/musb/musb_core.c | 838 | ||||
-rw-r--r-- | drivers/usb/musb/musb_core.h | 16 | ||||
-rw-r--r-- | drivers/usb/musb/musb_cppi41.c | 4 | ||||
-rw-r--r-- | drivers/usb/musb/musb_debug.h | 5 | ||||
-rw-r--r-- | drivers/usb/musb/musb_debugfs.c | 44 | ||||
-rw-r--r-- | drivers/usb/musb/musb_dma.h | 10 | ||||
-rw-r--r-- | drivers/usb/musb/musb_dsps.c | 39 | ||||
-rw-r--r-- | drivers/usb/musb/musb_gadget.c | 8 | ||||
-rw-r--r-- | drivers/usb/musb/musb_gadget.h | 10 | ||||
-rw-r--r-- | drivers/usb/musb/musb_host.c | 8 | ||||
-rw-r--r-- | drivers/usb/musb/musb_io.h | 6 | ||||
-rw-r--r-- | drivers/usb/musb/musb_regs.h | 55 | ||||
-rw-r--r-- | drivers/usb/musb/musb_virthub.c | 2 | ||||
-rw-r--r-- | drivers/usb/musb/musbhsdma.c | 74 | ||||
-rw-r--r-- | drivers/usb/musb/musbhsdma.h | 72 | ||||
-rw-r--r-- | drivers/usb/musb/omap2430.c | 100 | ||||
-rw-r--r-- | drivers/usb/musb/sunxi.c | 14 | ||||
-rw-r--r-- | drivers/usb/musb/ux500.c | 2 |
21 files changed, 599 insertions, 763 deletions
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index 0ad664efda6b..660641ab1545 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -201,7 +201,6 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) struct device *dev = musb->controller; struct musb_hdrc_platform_data *plat = dev_get_platdata(dev); struct omap_musb_board_data *data = plat->board_data; - struct usb_otg *otg = musb->xceiv->otg; unsigned long flags; irqreturn_t ret = IRQ_NONE; u32 epintr, usbintr; @@ -264,14 +263,12 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) WARNING("VBUS error workaround (delay coming)\n"); } else if (drvvbus) { MUSB_HST_MODE(musb); - otg->default_a = 1; musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; portstate(musb->port1_status |= USB_PORT_STAT_POWER); del_timer(&musb->dev_timer); } else { musb->is_active = 0; MUSB_DEV_MODE(musb); - otg->default_a = 0; musb->xceiv->otg->state = OTG_STATE_B_IDLE; portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); } diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index b8295ce7c4fe..1c023c0091c4 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -223,7 +223,6 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) { struct musb *musb = hci; void __iomem *reg_base = musb->ctrl_base; - struct usb_otg *otg = musb->xceiv->otg; unsigned long flags; irqreturn_t ret = IRQ_NONE; u32 status; @@ -280,7 +279,6 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) WARNING("VBUS error workaround (delay coming)\n"); } else if (drvvbus) { MUSB_HST_MODE(musb); - otg->default_a = 1; musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; portstate(musb->port1_status |= USB_PORT_STAT_POWER); del_timer(&musb->dev_timer); @@ -295,7 +293,6 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) */ musb->is_active = 0; MUSB_DEV_MODE(musb); - otg->default_a = 0; musb->xceiv->otg->state = OTG_STATE_B_IDLE; portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); } diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 2ad39dcd2f4c..fb6bbd254ab7 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -311,14 +311,12 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) WARNING("VBUS error workaround (delay coming)\n"); } else if (drvvbus) { MUSB_HST_MODE(musb); - otg->default_a = 1; musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; portstate(musb->port1_status |= USB_PORT_STAT_POWER); del_timer(&musb->dev_timer); } else { musb->is_active = 0; MUSB_DEV_MODE(musb); - otg->default_a = 0; musb->xceiv->otg->state = OTG_STATE_B_IDLE; portstate(musb->port1_status &= ~USB_PORT_STAT_POWER); } @@ -425,6 +423,9 @@ unregister: static int davinci_musb_exit(struct musb *musb) { + int maxdelay = 30; + u8 devctl, warn = 0; + del_timer_sync(&musb->dev_timer); /* force VBUS off */ @@ -438,31 +439,27 @@ static int davinci_musb_exit(struct musb *musb) davinci_musb_source_power(musb, 0 /*off*/, 1); - /* delay, to avoid problems with module reload */ - if (musb->xceiv->otg->default_a) { - int maxdelay = 30; - u8 devctl, warn = 0; + /* + * delay, to avoid problems with module reload. + * if there's no peripheral connected, this can take a + * long time to fall, especially on EVM with huge C133. + */ + do { + devctl = musb_readb(musb->mregs, MUSB_DEVCTL); + if (!(devctl & MUSB_DEVCTL_VBUS)) + break; + if ((devctl & MUSB_DEVCTL_VBUS) != warn) { + warn = devctl & MUSB_DEVCTL_VBUS; + dev_dbg(musb->controller, "VBUS %d\n", + warn >> MUSB_DEVCTL_VBUS_SHIFT); + } + msleep(1000); + maxdelay--; + } while (maxdelay > 0); - /* if there's no peripheral connected, this can take a - * long time to fall, especially on EVM with huge C133. - */ - do { - devctl = musb_readb(musb->mregs, MUSB_DEVCTL); - if (!(devctl & MUSB_DEVCTL_VBUS)) - break; - if ((devctl & MUSB_DEVCTL_VBUS) != warn) { - warn = devctl & MUSB_DEVCTL_VBUS; - dev_dbg(musb->controller, "VBUS %d\n", - warn >> MUSB_DEVCTL_VBUS_SHIFT); - } - msleep(1000); - maxdelay--; - } while (maxdelay > 0); - - /* in OTG mode, another host might be connected */ - if (devctl & MUSB_DEVCTL_VBUS) - dev_dbg(musb->controller, "VBUS off timeout (devctl %02x)\n", devctl); - } + /* in OTG mode, another host might be connected */ + if (devctl & MUSB_DEVCTL_VBUS) + dev_dbg(musb->controller, "VBUS off timeout (devctl %02x)\n", devctl); phy_off(); diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index fb5e4523dc28..b7d56272f9d1 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -274,20 +274,6 @@ static void musb_default_writew(void __iomem *addr, unsigned offset, u16 data) __raw_writew(data, addr + offset); } -static u32 musb_default_readl(const void __iomem *addr, unsigned offset) -{ - u32 data = __raw_readl(addr + offset); - - trace_musb_readl(__builtin_return_address(0), addr, offset, data); - return data; -} - -static void musb_default_writel(void __iomem *addr, unsigned offset, u32 data) -{ - trace_musb_writel(__builtin_return_address(0), addr, offset, data); - __raw_writel(data, addr + offset); -} - /* * Load an endpoint's FIFO */ @@ -390,10 +376,20 @@ EXPORT_SYMBOL_GPL(musb_readw); void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data); EXPORT_SYMBOL_GPL(musb_writew); -u32 (*musb_readl)(const void __iomem *addr, unsigned offset); +u32 musb_readl(const void __iomem *addr, unsigned offset) +{ + u32 data = __raw_readl(addr + offset); + + trace_musb_readl(__builtin_return_address(0), addr, offset, data); + return data; +} EXPORT_SYMBOL_GPL(musb_readl); -void (*musb_writel)(void __iomem *addr, unsigned offset, u32 data); +void musb_writel(void __iomem *addr, unsigned offset, u32 data) +{ + trace_musb_writel(__builtin_return_address(0), addr, offset, data); + __raw_writel(data, addr + offset); +} EXPORT_SYMBOL_GPL(musb_writel); #ifndef CONFIG_MUSB_PIO_ONLY @@ -527,6 +523,383 @@ void musb_hnp_stop(struct musb *musb) static void musb_recover_from_babble(struct musb *musb); +static void musb_handle_intr_resume(struct musb *musb, u8 devctl) +{ + musb_dbg(musb, "RESUME (%s)", + usb_otg_state_string(musb->xceiv->otg->state)); + + if (devctl & MUSB_DEVCTL_HM) { + switch (musb->xceiv->otg->state) { + case OTG_STATE_A_SUSPEND: + /* remote wakeup? */ + musb->port1_status |= + (USB_PORT_STAT_C_SUSPEND << 16) + | MUSB_PORT_STAT_RESUME; + musb->rh_timer = jiffies + + msecs_to_jiffies(USB_RESUME_TIMEOUT); + musb->xceiv->otg->state = OTG_STATE_A_HOST; + musb->is_active = 1; + musb_host_resume_root_hub(musb); + schedule_delayed_work(&musb->finish_resume_work, + msecs_to_jiffies(USB_RESUME_TIMEOUT)); + break; + case OTG_STATE_B_WAIT_ACON: + musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; + musb->is_active = 1; + MUSB_DEV_MODE(musb); + break; + default: + WARNING("bogus %s RESUME (%s)\n", + "host", + usb_otg_state_string(musb->xceiv->otg->state)); + } + } else { + switch (musb->xceiv->otg->state) { + case OTG_STATE_A_SUSPEND: + /* possibly DISCONNECT is upcoming */ + musb->xceiv->otg->state = OTG_STATE_A_HOST; + musb_host_resume_root_hub(musb); + break; + case OTG_STATE_B_WAIT_ACON: + case OTG_STATE_B_PERIPHERAL: + /* disconnect while suspended? we may + * not get a disconnect irq... + */ + if ((devctl & MUSB_DEVCTL_VBUS) + != (3 << MUSB_DEVCTL_VBUS_SHIFT) + ) { + musb->int_usb |= MUSB_INTR_DISCONNECT; + musb->int_usb &= ~MUSB_INTR_SUSPEND; + break; + } + musb_g_resume(musb); + break; + case OTG_STATE_B_IDLE: + musb->int_usb &= ~MUSB_INTR_SUSPEND; + break; + default: + WARNING("bogus %s RESUME (%s)\n", + "peripheral", + usb_otg_state_string(musb->xceiv->otg->state)); + } + } +} + +/* return IRQ_HANDLED to tell the caller to return immediately */ +static irqreturn_t musb_handle_intr_sessreq(struct musb *musb, u8 devctl) +{ + void __iomem *mbase = musb->mregs; + + if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS + && (devctl & MUSB_DEVCTL_BDEVICE)) { + musb_dbg(musb, "SessReq while on B state"); + return IRQ_HANDLED; + } + + musb_dbg(musb, "SESSION_REQUEST (%s)", + usb_otg_state_string(musb->xceiv->otg->state)); + + /* IRQ arrives from ID pin sense or (later, if VBUS power + * is removed) SRP. responses are time critical: + * - turn on VBUS (with silicon-specific mechanism) + * - go through A_WAIT_VRISE + * - ... to A_WAIT_BCON. + * a_wait_vrise_tmout triggers VBUS_ERROR transitions + */ + musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION); + musb->ep0_stage = MUSB_EP0_START; + musb->xceiv->otg->state = OTG_STATE_A_IDLE; + MUSB_HST_MODE(musb); + musb_platform_set_vbus(musb, 1); + + return IRQ_NONE; +} + +static void musb_handle_intr_vbuserr(struct musb *musb, u8 devctl) +{ + int ignore = 0; + + /* During connection as an A-Device, we may see a short + * current spikes causing voltage drop, because of cable + * and peripheral capacitance combined with vbus draw. + * (So: less common with truly self-powered devices, where + * vbus doesn't act like a power supply.) + * + * Such spikes are short; usually less than ~500 usec, max + * of ~2 msec. That is, they're not sustained overcurrent + * errors, though they're reported using VBUSERROR irqs. + * + * Workarounds: (a) hardware: use self powered devices. + * (b) software: ignore non-repeated VBUS errors. + * + * REVISIT: do delays from lots of DEBUG_KERNEL checks + * make trouble here, keeping VBUS < 4.4V ? + */ + switch (musb->xceiv->otg->state) { + case OTG_STATE_A_HOST: + /* recovery is dicey once we've gotten past the + * initial stages of enumeration, but if VBUS + * stayed ok at the other end of the link, and + * another reset is due (at least for high speed, + * to redo the chirp etc), it might work OK... + */ + case OTG_STATE_A_WAIT_BCON: + case OTG_STATE_A_WAIT_VRISE: + if (musb->vbuserr_retry) { + void __iomem *mbase = musb->mregs; + + musb->vbuserr_retry--; + ignore = 1; + devctl |= MUSB_DEVCTL_SESSION; + musb_writeb(mbase, MUSB_DEVCTL, devctl); + } else { + musb->port1_status |= + USB_PORT_STAT_OVERCURRENT + | (USB_PORT_STAT_C_OVERCURRENT << 16); + } + break; + default: + break; + } + + dev_printk(ignore ? KERN_DEBUG : KERN_ERR, musb->controller, + "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n", + usb_otg_state_string(musb->xceiv->otg->state), + devctl, + ({ char *s; + switch (devctl & MUSB_DEVCTL_VBUS) { + case 0 << MUSB_DEVCTL_VBUS_SHIFT: + s = "<SessEnd"; break; + case 1 << MUSB_DEVCTL_VBUS_SHIFT: + s = "<AValid"; break; + case 2 << MUSB_DEVCTL_VBUS_SHIFT: + s = "<VBusValid"; break; + /* case 3 << MUSB_DEVCTL_VBUS_SHIFT: */ + default: + s = "VALID"; break; + } s; }), + VBUSERR_RETRY_COUNT - musb->vbuserr_retry, + musb->port1_status); + + /* go through A_WAIT_VFALL then start a new session */ + if (!ignore) + musb_platform_set_vbus(musb, 0); +} + +static void musb_handle_intr_suspend(struct musb *musb, u8 devctl) +{ + musb_dbg(musb, "SUSPEND (%s) devctl %02x", + usb_otg_state_string(musb->xceiv->otg->state), devctl); + + switch (musb->xceiv->otg->state) { + case OTG_STATE_A_PERIPHERAL: + /* We also come here if the cable is removed, since + * this silicon doesn't report ID-no-longer-grounded. + * + * We depend on T(a_wait_bcon) to shut us down, and + * hope users don't do anything dicey during this + * undesired detour through A_WAIT_BCON. + */ + musb_hnp_stop(musb); + musb_host_resume_root_hub(musb); + musb_root_disconnect(musb); + musb_platform_try_idle(musb, jiffies + + msecs_to_jiffies(musb->a_wait_bcon + ? : OTG_TIME_A_WAIT_BCON)); + + break; + case OTG_STATE_B_IDLE: + if (!musb->is_active) + break; + /* fall through */ + case OTG_STATE_B_PERIPHERAL: + musb_g_suspend(musb); + musb->is_active = musb->g.b_hnp_enable; + if (musb->is_active) { + musb->xceiv->otg->state = OTG_STATE_B_WAIT_ACON; + musb_dbg(musb, "HNP: Setting timer for b_ase0_brst"); + mod_timer(&musb->otg_timer, jiffies + + msecs_to_jiffies( + OTG_TIME_B_ASE0_BRST)); + } + break; + case OTG_STATE_A_WAIT_BCON: + if (musb->a_wait_bcon != 0) + musb_platform_try_idle(musb, jiffies + + msecs_to_jiffies(musb->a_wait_bcon)); + break; + case OTG_STATE_A_HOST: + musb->xceiv->otg->state = OTG_STATE_A_SUSPEND; + musb->is_active = musb->hcd->self.b_hnp_enable; + break; + case OTG_STATE_B_HOST: + /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */ + musb_dbg(musb, "REVISIT: SUSPEND as B_HOST"); + break; + default: + /* "should not happen" */ + musb->is_active = 0; + break; + } +} + +static void musb_handle_intr_connect(struct musb *musb, u8 devctl, u8 int_usb) +{ + struct usb_hcd *hcd = musb->hcd; + + musb->is_active = 1; + musb->ep0_stage = MUSB_EP0_START; + + musb->intrtxe = musb->epmask; + musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe); + musb->intrrxe = musb->epmask & 0xfffe; + musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe); + musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7); + musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED + |USB_PORT_STAT_HIGH_SPEED + |USB_PORT_STAT_ENABLE + ); + musb->port1_status |= USB_PORT_STAT_CONNECTION + |(USB_PORT_STAT_C_CONNECTION << 16); + + /* high vs full speed is just a guess until after reset */ + if (devctl & MUSB_DEVCTL_LSDEV) + musb->port1_status |= USB_PORT_STAT_LOW_SPEED; + + /* indicate new connection to OTG machine */ + switch (musb->xceiv->otg->state) { + case OTG_STATE_B_PERIPHERAL: + if (int_usb & MUSB_INTR_SUSPEND) { + musb_dbg(musb, "HNP: SUSPEND+CONNECT, now b_host"); + int_usb &= ~MUSB_INTR_SUSPEND; + goto b_host; + } else + musb_dbg(musb, "CONNECT as b_peripheral???"); + break; + case OTG_STATE_B_WAIT_ACON: + musb_dbg(musb, "HNP: CONNECT, now b_host"); +b_host: + musb->xceiv->otg->state = OTG_STATE_B_HOST; + if (musb->hcd) + musb->hcd->self.is_b_host = 1; + del_timer(&musb->otg_timer); + break; + default: + if ((devctl & MUSB_DEVCTL_VBUS) + == (3 << MUSB_DEVCTL_VBUS_SHIFT)) { + musb->xceiv->otg->state = OTG_STATE_A_HOST; + if (hcd) + hcd->self.is_b_host = 0; + } + break; + } + + musb_host_poke_root_hub(musb); + + musb_dbg(musb, "CONNECT (%s) devctl %02x", + usb_otg_state_string(musb->xceiv->otg->state), devctl); +} + +static void musb_handle_intr_disconnect(struct musb *musb, u8 devctl) +{ + musb_dbg(musb, "DISCONNECT (%s) as %s, devctl %02x", + usb_otg_state_string(musb->xceiv->otg->state), + MUSB_MODE(musb), devctl); + + switch (musb->xceiv->otg->state) { + case OTG_STATE_A_HOST: + case OTG_STATE_A_SUSPEND: + musb_host_resume_root_hub(musb); + musb_root_disconnect(musb); + if (musb->a_wait_bcon != 0) + musb_platform_try_idle(musb, jiffies + + msecs_to_jiffies(musb->a_wait_bcon)); + break; + case OTG_STATE_B_HOST: + /* REVISIT this behaves for "real disconnect" + * cases; make sure the other transitions from + * from B_HOST act right too. The B_HOST code + * in hnp_stop() is currently not used... + */ + musb_root_disconnect(musb); + if (musb->hcd) + musb->hcd->self.is_b_host = 0; + musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; + MUSB_DEV_MODE(musb); + musb_g_disconnect(musb); + break; + case OTG_STATE_A_PERIPHERAL: + musb_hnp_stop(musb); + musb_root_disconnect(musb); + /* FALLTHROUGH */ + case OTG_STATE_B_WAIT_ACON: + /* FALLTHROUGH */ + case OTG_STATE_B_PERIPHERAL: + case OTG_STATE_B_IDLE: + musb_g_disconnect(musb); + break; + default: + WARNING("unhandled DISCONNECT transition (%s)\n", + usb_otg_state_string(musb->xceiv->otg->state)); + break; + } +} + +/* + * mentor saves a bit: bus reset and babble share the same irq. + * only host sees babble; only peripheral sees bus reset. + */ +static void musb_handle_intr_reset(struct musb *musb) +{ + if (is_host_active(musb)) { + /* + * When BABBLE happens what we can depends on which + * platform MUSB is running, because some platforms + * implemented proprietary means for 'recovering' from + * Babble conditions. One such platform is AM335x. In + * most cases, however, the only thing we can do is + * drop the session. + */ + dev_err(musb->controller, "Babble\n"); + musb_recover_from_babble(musb); + } else { + musb_dbg(musb, "BUS RESET as %s", + usb_otg_state_string(musb->xceiv->otg->state)); + switch (musb->xceiv->otg->state) { + case OTG_STATE_A_SUSPEND: + musb_g_reset(musb); + /* FALLTHROUGH */ + case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */ + /* never use invalid T(a_wait_bcon) */ + musb_dbg(musb, "HNP: in %s, %d msec timeout", + usb_otg_state_string(musb->xceiv->otg->state), + TA_WAIT_BCON(musb)); + mod_timer(&musb->otg_timer, jiffies + + msecs_to_jiffies(TA_WAIT_BCON(musb))); + break; + case OTG_STATE_A_PERIPHERAL: + del_timer(&musb->otg_timer); + musb_g_reset(musb); + break; + case OTG_STATE_B_WAIT_ACON: + musb_dbg(musb, "HNP: RESET (%s), to b_peripheral", + usb_otg_state_string(musb->xceiv->otg->state)); + musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; + musb_g_reset(musb); + break; + case OTG_STATE_B_IDLE: + musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; + /* FALLTHROUGH */ + case OTG_STATE_B_PERIPHERAL: + musb_g_reset(musb); + break; + default: + musb_dbg(musb, "Unhandled BUS RESET as %s", + usb_otg_state_string(musb->xceiv->otg->state)); + } + } +} + /* * Interrupt Service Routine to record USB "global" interrupts. * Since these do not happen often and signify things of @@ -551,379 +924,40 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, * spurious RESUME irqs happen too, paired with SUSPEND. */ if (int_usb & MUSB_INTR_RESUME) { + musb_handle_intr_resume(musb, devctl); handled = IRQ_HANDLED; - musb_dbg(musb, "RESUME (%s)", - usb_otg_state_string(musb->xceiv->otg->state)); - - if (devctl & MUSB_DEVCTL_HM) { - switch (musb->xceiv->otg->state) { - case OTG_STATE_A_SUSPEND: - /* remote wakeup? */ - musb->port1_status |= - (USB_PORT_STAT_C_SUSPEND << 16) - | MUSB_PORT_STAT_RESUME; - musb->rh_timer = jiffies - + msecs_to_jiffies(USB_RESUME_TIMEOUT); - musb->xceiv->otg->state = OTG_STATE_A_HOST; - musb->is_active = 1; - musb_host_resume_root_hub(musb); - schedule_delayed_work(&musb->finish_resume_work, - msecs_to_jiffies(USB_RESUME_TIMEOUT)); - break; - case OTG_STATE_B_WAIT_ACON: - musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; - musb->is_active = 1; - MUSB_DEV_MODE(musb); - break; - default: - WARNING("bogus %s RESUME (%s)\n", - "host", - usb_otg_state_string(musb->xceiv->otg->state)); - } - } else { - switch (musb->xceiv->otg->state) { - case OTG_STATE_A_SUSPEND: - /* possibly DISCONNECT is upcoming */ - musb->xceiv->otg->state = OTG_STATE_A_HOST; - musb_host_resume_root_hub(musb); - break; - case OTG_STATE_B_WAIT_ACON: - case OTG_STATE_B_PERIPHERAL: - /* disconnect while suspended? we may - * not get a disconnect irq... - */ - if ((devctl & MUSB_DEVCTL_VBUS) - != (3 << MUSB_DEVCTL_VBUS_SHIFT) - ) { - musb->int_usb |= MUSB_INTR_DISCONNECT; - musb->int_usb &= ~MUSB_INTR_SUSPEND; - break; - } - musb_g_resume(musb); - break; - case OTG_STATE_B_IDLE: - musb->int_usb &= ~MUSB_INTR_SUSPEND; - break; - default: - WARNING("bogus %s RESUME (%s)\n", - "peripheral", - usb_otg_state_string(musb->xceiv->otg->state)); - } - } } /* see manual for the order of the tests */ if (int_usb & MUSB_INTR_SESSREQ) { - void __iomem *mbase = musb->mregs; - - if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS - && (devctl & MUSB_DEVCTL_BDEVICE)) { - musb_dbg(musb, "SessReq while on B state"); + if (musb_handle_intr_sessreq(musb, devctl)) return IRQ_HANDLED; - } - - musb_dbg(musb, "SESSION_REQUEST (%s)", - usb_otg_state_string(musb->xceiv->otg->state)); - - /* IRQ arrives from ID pin sense or (later, if VBUS power - * is removed) SRP. responses are time critical: - * - turn on VBUS (with silicon-specific mechanism) - * - go through A_WAIT_VRISE - * - ... to A_WAIT_BCON. - * a_wait_vrise_tmout triggers VBUS_ERROR transitions - */ - musb_writeb(mbase, MUSB_DEVCTL, MUSB_DEVCTL_SESSION); - musb->ep0_stage = MUSB_EP0_START; - musb->xceiv->otg->state = OTG_STATE_A_IDLE; - MUSB_HST_MODE(musb); - musb_platform_set_vbus(musb, 1); - handled = IRQ_HANDLED; } if (int_usb & MUSB_INTR_VBUSERROR) { - int ignore = 0; - - /* During connection as an A-Device, we may see a short - * current spikes causing voltage drop, because of cable - * and peripheral capacitance combined with vbus draw. - * (So: less common with truly self-powered devices, where - * vbus doesn't act like a power supply.) - * - * Such spikes are short; usually less than ~500 usec, max - * of ~2 msec. That is, they're not sustained overcurrent - * errors, though they're reported using VBUSERROR irqs. - * - * Workarounds: (a) hardware: use self powered devices. - * (b) software: ignore non-repeated VBUS errors. - * - * REVISIT: do delays from lots of DEBUG_KERNEL checks - * make trouble here, keeping VBUS < 4.4V ? - */ - switch (musb->xceiv->otg->state) { - case OTG_STATE_A_HOST: - /* recovery is dicey once we've gotten past the - * initial stages of enumeration, but if VBUS - * stayed ok at the other end of the link, and - * another reset is due (at least for high speed, - * to redo the chirp etc), it might work OK... - */ - case OTG_STATE_A_WAIT_BCON: - case OTG_STATE_A_WAIT_VRISE: - if (musb->vbuserr_retry) { - void __iomem *mbase = musb->mregs; - - musb->vbuserr_retry--; - ignore = 1; - devctl |= MUSB_DEVCTL_SESSION; - musb_writeb(mbase, MUSB_DEVCTL, devctl); - } else { - musb->port1_status |= - USB_PORT_STAT_OVERCURRENT - | (USB_PORT_STAT_C_OVERCURRENT << 16); - } - break; - default: - break; - } - - dev_printk(ignore ? KERN_DEBUG : KERN_ERR, musb->controller, - "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n", - usb_otg_state_string(musb->xceiv->otg->state), - devctl, - ({ char *s; - switch (devctl & MUSB_DEVCTL_VBUS) { - case 0 << MUSB_DEVCTL_VBUS_SHIFT: - s = "<SessEnd"; break; - case 1 << MUSB_DEVCTL_VBUS_SHIFT: - s = "<AValid"; break; - case 2 << MUSB_DEVCTL_VBUS_SHIFT: - s = "<VBusValid"; break; - /* case 3 << MUSB_DEVCTL_VBUS_SHIFT: */ - default: - s = "VALID"; break; - } s; }), - VBUSERR_RETRY_COUNT - musb->vbuserr_retry, - musb->port1_status); - - /* go through A_WAIT_VFALL then start a new session */ - if (!ignore) - musb_platform_set_vbus(musb, 0); + musb_handle_intr_vbuserr(musb, devctl); handled = IRQ_HANDLED; } if (int_usb & MUSB_INTR_SUSPEND) { - musb_dbg(musb, "SUSPEND (%s) devctl %02x", - usb_otg_state_string(musb->xceiv->otg->state), devctl); + musb_handle_intr_suspend(musb, devctl); handled = IRQ_HANDLED; - - switch (musb->xceiv->otg->state) { - case OTG_STATE_A_PERIPHERAL: - /* We also come here if the cable is removed, since - * this silicon doesn't report ID-no-longer-grounded. - * - * We depend on T(a_wait_bcon) to shut us down, and - * hope users don't do anything dicey during this - * undesired detour through A_WAIT_BCON. - */ - musb_hnp_stop(musb); - musb_host_resume_root_hub(musb); - musb_root_disconnect(musb); - musb_platform_try_idle(musb, jiffies - + msecs_to_jiffies(musb->a_wait_bcon - ? : OTG_TIME_A_WAIT_BCON)); - - break; - case OTG_STATE_B_IDLE: - if (!musb->is_active) - break; - /* fall through */ - case OTG_STATE_B_PERIPHERAL: - musb_g_suspend(musb); - musb->is_active = musb->g.b_hnp_enable; - if (musb->is_active) { - musb->xceiv->otg->state = OTG_STATE_B_WAIT_ACON; - musb_dbg(musb, "HNP: Setting timer for b_ase0_brst"); - mod_timer(&musb->otg_timer, jiffies - + msecs_to_jiffies( - OTG_TIME_B_ASE0_BRST)); - } - break; - case OTG_STATE_A_WAIT_BCON: - if (musb->a_wait_bcon != 0) - musb_platform_try_idle(musb, jiffies - + msecs_to_jiffies(musb->a_wait_bcon)); - break; - case OTG_STATE_A_HOST: - musb->xceiv->otg->state = OTG_STATE_A_SUSPEND; - musb->is_active = musb->hcd->self.b_hnp_enable; - break; - case OTG_STATE_B_HOST: - /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */ - musb_dbg(musb, "REVISIT: SUSPEND as B_HOST"); - break; - default: - /* "should not happen" */ - musb->is_active = 0; - break; - } } if (int_usb & MUSB_INTR_CONNECT) { - struct usb_hcd *hcd = musb->hcd; - + musb_handle_intr_connect(musb, devctl, int_usb); handled = IRQ_HANDLED; - musb->is_active = 1; - - musb->ep0_stage = MUSB_EP0_START; - - musb->intrtxe = musb->epmask; - musb_writew(musb->mregs, MUSB_INTRTXE, musb->intrtxe); - musb->intrrxe = musb->epmask & 0xfffe; - musb_writew(musb->mregs, MUSB_INTRRXE, musb->intrrxe); - musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7); - musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED - |USB_PORT_STAT_HIGH_SPEED - |USB_PORT_STAT_ENABLE - ); - musb->port1_status |= USB_PORT_STAT_CONNECTION - |(USB_PORT_STAT_C_CONNECTION << 16); - - /* high vs full speed is just a guess until after reset */ - if (devctl & MUSB_DEVCTL_LSDEV) - musb->port1_status |= USB_PORT_STAT_LOW_SPEED; - - /* indicate new connection to OTG machine */ - switch (musb->xceiv->otg->state) { - case OTG_STATE_B_PERIPHERAL: - if (int_usb & MUSB_INTR_SUSPEND) { - musb_dbg(musb, "HNP: SUSPEND+CONNECT, now b_host"); - int_usb &= ~MUSB_INTR_SUSPEND; - goto b_host; - } else - musb_dbg(musb, "CONNECT as b_peripheral???"); - break; - case OTG_STATE_B_WAIT_ACON: - musb_dbg(musb, "HNP: CONNECT, now b_host"); -b_host: - musb->xceiv->otg->state = OTG_STATE_B_HOST; - if (musb->hcd) - musb->hcd->self.is_b_host = 1; - del_timer(&musb->otg_timer); - break; - default: - if ((devctl & MUSB_DEVCTL_VBUS) - == (3 << MUSB_DEVCTL_VBUS_SHIFT)) { - musb->xceiv->otg->state = OTG_STATE_A_HOST; - if (hcd) - hcd->self.is_b_host = 0; - } - break; - } - - musb_host_poke_root_hub(musb); - - musb_dbg(musb, "CONNECT (%s) devctl %02x", - usb_otg_state_string(musb->xceiv->otg->state), devctl); } if (int_usb & MUSB_INTR_DISCONNECT) { - musb_dbg(musb, "DISCONNECT (%s) as %s, devctl %02x", - usb_otg_state_string(musb->xceiv->otg->state), - MUSB_MODE(musb), devctl); + musb_handle_intr_disconnect(musb, devctl); handled = IRQ_HANDLED; - - switch (musb->xceiv->otg->state) { - case OTG_STATE_A_HOST: - case OTG_STATE_A_SUSPEND: - musb_host_resume_root_hub(musb); - musb_root_disconnect(musb); - if (musb->a_wait_bcon != 0) - musb_platform_try_idle(musb, jiffies - + msecs_to_jiffies(musb->a_wait_bcon)); - break; - case OTG_STATE_B_HOST: - /* REVISIT this behaves for "real disconnect" - * cases; make sure the other transitions from - * from B_HOST act right too. The B_HOST code - * in hnp_stop() is currently not used... - */ - musb_root_disconnect(musb); - if (musb->hcd) - musb->hcd->self.is_b_host = 0; - musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; - MUSB_DEV_MODE(musb); - musb_g_disconnect(musb); - break; - case OTG_STATE_A_PERIPHERAL: - musb_hnp_stop(musb); - musb_root_disconnect(musb); - /* FALLTHROUGH */ - case OTG_STATE_B_WAIT_ACON: - /* FALLTHROUGH */ - case OTG_STATE_B_PERIPHERAL: - case OTG_STATE_B_IDLE: - musb_g_disconnect(musb); - break; - default: - WARNING("unhandled DISCONNECT transition (%s)\n", - usb_otg_state_string(musb->xceiv->otg->state)); - break; - } } - /* mentor saves a bit: bus reset and babble share the same irq. - * only host sees babble; only peripheral sees bus reset. - */ if (int_usb & MUSB_INTR_RESET) { + musb_handle_intr_reset(musb); handled = IRQ_HANDLED; - if (is_host_active(musb)) { - /* - * When BABBLE happens what we can depends on which - * platform MUSB is running, because some platforms - * implemented proprietary means for 'recovering' from - * Babble conditions. One such platform is AM335x. In - * most cases, however, the only thing we can do is - * drop the session. - */ - dev_err(musb->controller, "Babble\n"); - musb_recover_from_babble(musb); - } else { - musb_dbg(musb, "BUS RESET as %s", - usb_otg_state_string(musb->xceiv->otg->state)); - switch (musb->xceiv->otg->state) { - case OTG_STATE_A_SUSPEND: - musb_g_reset(musb); - /* FALLTHROUGH */ - case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */ - /* never use invalid T(a_wait_bcon) */ - musb_dbg(musb, "HNP: in %s, %d msec timeout", - usb_otg_state_string(musb->xceiv->otg->state), - TA_WAIT_BCON(musb)); - mod_timer(&musb->otg_timer, jiffies - + msecs_to_jiffies(TA_WAIT_BCON(musb))); - break; - case OTG_STATE_A_PERIPHERAL: - del_timer(&musb->otg_timer); - musb_g_reset(musb); - break; - case OTG_STATE_B_WAIT_ACON: - musb_dbg(musb, "HNP: RESET (%s), to b_peripheral", - usb_otg_state_string(musb->xceiv->otg->state)); - musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; - musb_g_reset(musb); - break; - case OTG_STATE_B_IDLE: - musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; - /* FALLTHROUGH */ - case OTG_STATE_B_PERIPHERAL: - musb_g_reset(musb); - break; - default: - musb_dbg(musb, "Unhandled BUS RESET as %s", - usb_otg_state_string(musb->xceiv->otg->state)); - } - } } #if 0 @@ -1042,7 +1076,7 @@ void musb_start(struct musb *musb) * (b) vbus present/connect IRQ, peripheral mode; * (c) peripheral initiates, using SRP */ - if (musb->port_mode != MUSB_PORT_MODE_HOST && + if (musb->port_mode != MUSB_HOST && musb->xceiv->otg->state != OTG_STATE_A_WAIT_BCON && (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) { musb->is_active = 1; @@ -1244,25 +1278,25 @@ fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep, /* REVISIT error check: be sure ep0 can both rx and tx ... */ switch (cfg->style) { case FIFO_TX: - musb_write_txfifosz(mbase, c_size); - musb_write_txfifoadd(mbase, c_off); + musb_writeb(mbase, MUSB_TXFIFOSZ, c_size); + musb_writew(mbase, MUSB_TXFIFOADD, c_off); hw_ep->tx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); hw_ep->max_packet_sz_tx = maxpacket; break; case FIFO_RX: - musb_write_rxfifosz(mbase, c_size); - musb_write_rxfifoadd(mbase, c_off); + musb_writeb(mbase, MUSB_RXFIFOSZ, c_size); + musb_writew(mbase, MUSB_RXFIFOADD, c_off); hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); hw_ep->max_packet_sz_rx = maxpacket; break; case FIFO_RXTX: - musb_write_txfifosz(mbase, c_size); - musb_write_txfifoadd(mbase, c_off); + musb_writeb(mbase, MUSB_TXFIFOSZ, c_size); + musb_writew(mbase, MUSB_TXFIFOADD, c_off); hw_ep->rx_double_buffered = !!(c_size & MUSB_FIFOSZ_DPB); hw_ep->max_packet_sz_rx = maxpacket; - musb_write_rxfifosz(mbase, c_size); - musb_write_rxfifoadd(mbase, c_off); + musb_writeb(mbase, MUSB_RXFIFOSZ, c_size); + musb_writew(mbase, MUSB_RXFIFOADD, c_off); hw_ep->tx_double_buffered = hw_ep->rx_double_buffered; hw_ep->max_packet_sz_tx = maxpacket; @@ -1470,7 +1504,7 @@ static int musb_core_init(u16 musb_type, struct musb *musb) } /* log release info */ - musb->hwvers = musb_read_hwvers(mbase); + musb->hwvers = musb_readw(mbase, MUSB_HWVERS); pr_debug("%s: %sHDRC RTL version %d.%d%s\n", musb_driver_name, type, MUSB_HWVERS_MAJOR(musb->hwvers), MUSB_HWVERS_MINOR(musb->hwvers), @@ -1497,7 +1531,7 @@ static int musb_core_init(u16 musb_type, struct musb *musb) hw_ep->fifo = musb->io.fifo_offset(i) + mbase; #if IS_ENABLED(CONFIG_USB_MUSB_TUSB6010) - if (musb->io.quirks & MUSB_IN_TUSB) { + if (musb->ops->quirks & MUSB_IN_TUSB) { hw_ep->fifo_async = musb->async + 0x400 + musb->io.fifo_offset(i); hw_ep->fifo_sync = musb->sync + 0x400 + @@ -2158,8 +2192,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) musb_writeb = musb_default_writeb; musb_readw = musb_default_readw; musb_writew = musb_default_writew; - musb_readl = musb_default_readl; - musb_writel = musb_default_writel; /* The musb_platform_init() call: * - adjusts musb->mregs @@ -2182,11 +2214,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) goto fail2; } - if (musb->ops->quirks) - musb->io.quirks = musb->ops->quirks; /* Most devices use indexed offset or flat offset */ - if (musb->io.quirks & MUSB_INDEXED_EP) { + if (musb->ops->quirks & MUSB_INDEXED_EP) { musb->io.ep_offset = musb_indexed_ep_offset; musb->io.ep_select = musb_indexed_ep_select; } else { @@ -2194,7 +2224,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) musb->io.ep_select = musb_flat_ep_select; } - if (musb->io.quirks & MUSB_G_NO_SKB_RESERVE) + if (musb->ops->quirks & MUSB_G_NO_SKB_RESERVE) musb->g.quirk_avoids_skb_reserve = 1; /* At least tusb6010 has its own offsets */ @@ -2226,10 +2256,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) musb_readw = musb->ops->readw; if (musb->ops->writew) musb_writew = musb->ops->writew; - if (musb->ops->readl) - musb_readl = musb->ops->readl; - if (musb->ops->writel) - musb_writel = musb->ops->writel; #ifndef CONFIG_MUSB_PIO_ONLY if (!musb->ops->dma_init || !musb->ops->dma_exit) { @@ -2321,33 +2347,28 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) /* program PHY to use external vBus if required */ if (plat->extvbus) { - u8 busctl = musb_read_ulpi_buscontrol(musb->mregs); + u8 busctl = musb_readb(musb->mregs, MUSB_ULPI_BUSCONTROL); busctl |= MUSB_ULPI_USE_EXTVBUS; - musb_write_ulpi_buscontrol(musb->mregs, busctl); + musb_writeb(musb->mregs, MUSB_ULPI_BUSCONTROL, busctl); } - if (musb->xceiv->otg->default_a) { - MUSB_HST_MODE(musb); - musb->xceiv->otg->state = OTG_STATE_A_IDLE; - } else { - MUSB_DEV_MODE(musb); - musb->xceiv->otg->state = OTG_STATE_B_IDLE; - } + MUSB_DEV_MODE(musb); + musb->xceiv->otg->state = OTG_STATE_B_IDLE; switch (musb->port_mode) { - case MUSB_PORT_MODE_HOST: + case MUSB_HOST: status = musb_host_setup(musb, plat->power); if (status < 0) goto fail3; status = musb_platform_set_mode(musb, MUSB_HOST); break; - case MUSB_PORT_MODE_GADGET: + case MUSB_PERIPHERAL: status = musb_gadget_setup(musb); if (status < 0) goto fail3; status = musb_platform_set_mode(musb, MUSB_PERIPHERAL); break; - case MUSB_PORT_MODE_DUAL_ROLE: + case MUSB_OTG: status = musb_host_setup(musb, plat->power); if (status < 0) goto fail3; @@ -2366,9 +2387,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) if (status < 0) goto fail3; - status = musb_init_debugfs(musb); - if (status < 0) - goto fail4; + musb_init_debugfs(musb); status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group); if (status) @@ -2383,7 +2402,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) fail5: musb_exit_debugfs(musb); -fail4: musb_gadget_cleanup(musb); musb_host_cleanup(musb); @@ -2492,7 +2510,7 @@ static void musb_save_context(struct musb *musb) musb->context.frame = musb_readw(musb_base, MUSB_FRAME); musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE); - musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs); + musb->context.busctl = musb_readb(musb_base, MUSB_ULPI_BUSCONTROL); musb->context.power = musb_readb(musb_base, MUSB_POWER); musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE); musb->context.index = musb_readb(musb_base, MUSB_INDEX); @@ -2521,13 +2539,13 @@ static void musb_save_context(struct musb *musb) if (musb->dyn_fifo) { musb->context.index_regs[i].txfifoadd = - musb_read_txfifoadd(musb_base); + musb_readw(musb_base, MUSB_TXFIFOADD); musb->context.index_regs[i].rxfifoadd = - musb_read_rxfifoadd(musb_base); + musb_readw(musb_base, MUSB_RXFIFOADD); musb->context.index_regs[i].txfifosz = - musb_read_txfifosz(musb_base); + musb_readb(musb_base, MUSB_TXFIFOSZ); musb->context.index_regs[i].rxfifosz = - musb_read_rxfifosz(musb_base); + musb_readb(musb_base, MUSB_RXFIFOSZ); } musb->context.index_regs[i].txtype = @@ -2564,7 +2582,7 @@ static void musb_restore_context(struct musb *musb) musb_writew(musb_base, MUSB_FRAME, musb->context.frame); musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode); - musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl); + musb_writeb(musb_base, MUSB_ULPI_BUSCONTROL, musb->context.busctl); /* Don't affect SUSPENDM/RESUME bits in POWER reg */ power = musb_readb(musb_base, MUSB_POWER); @@ -2601,13 +2619,13 @@ static void musb_restore_context(struct musb *musb) musb->context.index_regs[i].rxcsr); if (musb->dyn_fifo) { - musb_write_txfifosz(musb_base, + musb_writeb(musb_base, MUSB_TXFIFOSZ, musb->context.index_regs[i].txfifosz); - musb_write_rxfifosz(musb_base, + musb_writeb(musb_base, MUSB_RXFIFOSZ, musb->context.index_regs[i].rxfifosz); - musb_write_txfifoadd(musb_base, + musb_writew(musb_base, MUSB_TXFIFOADD, musb->context.index_regs[i].txfifoadd); - musb_write_rxfifoadd(musb_base, + musb_writew(musb_base, MUSB_RXFIFOADD, musb->context.index_regs[i].rxfifoadd); } @@ -2657,7 +2675,7 @@ static int musb_suspend(struct device *dev) ; musb->flush_irq_work = false; - if (!(musb->io.quirks & MUSB_PRESERVE_SESSION)) + if (!(musb->ops->quirks & MUSB_PRESERVE_SESSION)) musb_writeb(musb->mregs, MUSB_DEVCTL, 0); WARN_ON(!list_empty(&musb->pending_list)); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 8a74cb2907f8..04203b7126d5 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -53,12 +53,6 @@ struct musb_ep; #define is_peripheral_active(m) (!(m)->is_host) #define is_host_active(m) ((m)->is_host) -enum { - MUSB_PORT_MODE_HOST = 1, - MUSB_PORT_MODE_GADGET, - MUSB_PORT_MODE_DUAL_ROLE, -}; - /****************************** CONSTANTS ********************************/ #ifndef MUSB_C_NUM_EPS @@ -127,8 +121,6 @@ struct musb_io; * @writeb: write 8 bits * @readw: read 16 bits * @writew: write 16 bits - * @readl: read 32 bits - * @writel: write 32 bits * @read_fifo: reads the fifo * @write_fifo: writes to fifo * @dma_init: platform specific dma init function @@ -140,7 +132,6 @@ struct musb_io; * @recover: platform-specific babble recovery * @vbus_status: returns vbus status if possible * @set_vbus: forces vbus status - * @adjust_channel_params: pre check for standard dma channel_program func * @pre_root_reset_end: called before the root usb port reset flag gets cleared * @post_root_reset_end: called after the root usb port reset flag gets cleared * @phy_callback: optional callback function for the phy to call @@ -174,8 +165,6 @@ struct musb_platform_ops { void (*writeb)(void __iomem *addr, unsigned offset, u8 data); u16 (*readw)(const void __iomem *addr, unsigned offset); void (*writew)(void __iomem *addr, unsigned offset, u16 data); - u32 (*readl)(const void __iomem *addr, unsigned offset); - void (*writel)(void __iomem *addr, unsigned offset, u32 data); void (*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf); void (*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf); struct dma_controller * @@ -188,9 +177,6 @@ struct musb_platform_ops { int (*vbus_status)(struct musb *musb); void (*set_vbus)(struct musb *musb, int on); - int (*adjust_channel_params)(struct dma_channel *channel, - u16 packet_sz, u8 *mode, - dma_addr_t *dma_addr, u32 *len); void (*pre_root_reset_end)(struct musb *musb); void (*post_root_reset_end)(struct musb *musb); int (*phy_callback)(enum musb_vbus_id_status status); @@ -359,7 +345,7 @@ struct musb { u8 min_power; /* vbus for periph, in mA/2 */ - int port_mode; /* MUSB_PORT_MODE_* */ + enum musb_mode port_mode; bool session; unsigned long quirk_retries; bool is_host; diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c index d0dd4f470bbe..7fbb8a307145 100644 --- a/drivers/usb/musb/musb_cppi41.c +++ b/drivers/usb/musb/musb_cppi41.c @@ -614,7 +614,7 @@ static int cppi41_dma_channel_abort(struct dma_channel *channel) } /* DA8xx Advisory 2.3.27: wait 250 ms before to start the teardown */ - if (musb->io.quirks & MUSB_DA8XX) + if (musb->ops->quirks & MUSB_DA8XX) mdelay(250); tdbit = 1 << cppi41_channel->port_num; @@ -773,7 +773,7 @@ cppi41_dma_controller_create(struct musb *musb, void __iomem *base) controller->controller.is_compatible = cppi41_is_compatible; controller->controller.musb = musb; - if (musb->io.quirks & MUSB_DA8XX) { + if (musb->ops->quirks & MUSB_DA8XX) { controller->tdown_reg = DA8XX_USB_TEARDOWN; controller->autoreq_reg = DA8XX_USB_AUTOREQ; controller->set_dma_mode = da8xx_set_dma_mode; diff --git a/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h index 5e0f079dde21..c444a80fe1da 100644 --- a/drivers/usb/musb/musb_debug.h +++ b/drivers/usb/musb/musb_debug.h @@ -20,12 +20,11 @@ void musb_dbg(struct musb *musb, const char *fmt, ...); #ifdef CONFIG_DEBUG_FS -int musb_init_debugfs(struct musb *musb); +void musb_init_debugfs(struct musb *musb); void musb_exit_debugfs(struct musb *musb); #else -static inline int musb_init_debugfs(struct musb *musb) +static inline void musb_init_debugfs(struct musb *musb) { - return 0; } static inline void musb_exit_debugfs(struct musb *musb) { diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c index e2050cac3eae..f42858e2b54c 100644 --- a/drivers/usb/musb/musb_debugfs.c +++ b/drivers/usb/musb/musb_debugfs.c @@ -321,48 +321,18 @@ static const struct file_operations musb_softconnect_fops = { .release = single_release, }; -int musb_init_debugfs(struct musb *musb) +void musb_init_debugfs(struct musb *musb) { - struct dentry *root; - struct dentry *file; - int ret; + struct dentry *root; root = debugfs_create_dir(dev_name(musb->controller), NULL); - if (!root) { - ret = -ENOMEM; - goto err0; - } - - file = debugfs_create_file("regdump", S_IRUGO, root, musb, - &musb_regdump_fops); - if (!file) { - ret = -ENOMEM; - goto err1; - } - - file = debugfs_create_file("testmode", S_IRUGO | S_IWUSR, - root, musb, &musb_test_mode_fops); - if (!file) { - ret = -ENOMEM; - goto err1; - } - - file = debugfs_create_file("softconnect", S_IRUGO | S_IWUSR, - root, musb, &musb_softconnect_fops); - if (!file) { - ret = -ENOMEM; - goto err1; - } - musb->debugfs_root = root; - return 0; - -err1: - debugfs_remove_recursive(root); - -err0: - return ret; + debugfs_create_file("regdump", S_IRUGO, root, musb, &musb_regdump_fops); + debugfs_create_file("testmode", S_IRUGO | S_IWUSR, root, musb, + &musb_test_mode_fops); + debugfs_create_file("softconnect", S_IRUGO | S_IWUSR, root, musb, + &musb_softconnect_fops); } void /* __init_or_exit */ musb_exit_debugfs(struct musb *musb) diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h index 0fc8cd0c2a5c..8f60271c0a9d 100644 --- a/drivers/usb/musb/musb_dma.h +++ b/drivers/usb/musb/musb_dma.h @@ -44,31 +44,31 @@ struct musb_hw_ep; #endif #ifdef CONFIG_USB_UX500_DMA -#define musb_dma_ux500(musb) (musb->io.quirks & MUSB_DMA_UX500) +#define musb_dma_ux500(musb) (musb->ops->quirks & MUSB_DMA_UX500) #else #define musb_dma_ux500(musb) 0 #endif #ifdef CONFIG_USB_TI_CPPI41_DMA -#define musb_dma_cppi41(musb) (musb->io.quirks & MUSB_DMA_CPPI41) +#define musb_dma_cppi41(musb) (musb->ops->quirks & MUSB_DMA_CPPI41) #else #define musb_dma_cppi41(musb) 0 #endif #ifdef CONFIG_USB_TI_CPPI_DMA -#define musb_dma_cppi(musb) (musb->io.quirks & MUSB_DMA_CPPI) +#define musb_dma_cppi(musb) (musb->ops->quirks & MUSB_DMA_CPPI) #else #define musb_dma_cppi(musb) 0 #endif #ifdef CONFIG_USB_TUSB_OMAP_DMA -#define tusb_dma_omap(musb) (musb->io.quirks & MUSB_DMA_TUSB_OMAP) +#define tusb_dma_omap(musb) (musb->ops->quirks & MUSB_DMA_TUSB_OMAP) #else #define tusb_dma_omap(musb) 0 #endif #ifdef CONFIG_USB_INVENTRA_DMA -#define musb_dma_inventra(musb) (musb->io.quirks & MUSB_DMA_INVENTRA) +#define musb_dma_inventra(musb) (musb->ops->quirks & MUSB_DMA_INVENTRA) #else #define musb_dma_inventra(musb) 0 #endif diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 6a60bc0490c5..fb871eabcc10 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -183,7 +183,7 @@ static void dsps_musb_enable(struct musb *musb) musb_writel(reg_base, wrp->coreintr_set, coremask); /* start polling for ID change in dual-role idle mode */ if (musb->xceiv->otg->state == OTG_STATE_B_IDLE && - musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) + musb->port_mode == MUSB_OTG) dsps_mod_timer(glue, -1); } @@ -231,7 +231,7 @@ static int dsps_check_status(struct musb *musb, void *unused) break; case OTG_STATE_A_WAIT_BCON: /* keep VBUS on for host-only mode */ - if (musb->port_mode == MUSB_PORT_MODE_HOST) { + if (musb->port_mode == MUSB_HOST) { dsps_mod_timer_optional(glue); break; } @@ -360,13 +360,11 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) WARNING("VBUS error workaround (delay coming)\n"); } else if (drvvbus) { MUSB_HST_MODE(musb); - musb->xceiv->otg->default_a = 1; musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; dsps_mod_timer_optional(glue); } else { musb->is_active = 0; MUSB_DEV_MODE(musb); - musb->xceiv->otg->default_a = 0; musb->xceiv->otg->state = OTG_STATE_B_IDLE; } @@ -401,24 +399,17 @@ out: static int dsps_musb_dbg_init(struct musb *musb, struct dsps_glue *glue) { struct dentry *root; - struct dentry *file; char buf[128]; sprintf(buf, "%s.dsps", dev_name(musb->controller)); root = debugfs_create_dir(buf, NULL); - if (!root) - return -ENOMEM; glue->dbgfs_root = root; glue->regset.regs = dsps_musb_regs; glue->regset.nregs = ARRAY_SIZE(dsps_musb_regs); glue->regset.base = musb->ctrl_base; - file = debugfs_create_regset32("regdump", S_IRUGO, root, &glue->regset); - if (!file) { - debugfs_remove_recursive(root); - return -ENOMEM; - } + debugfs_create_regset32("regdump", S_IRUGO, root, &glue->regset); return 0; } @@ -729,25 +720,6 @@ static int get_int_prop(struct device_node *dn, const char *s) return val; } -static int get_musb_port_mode(struct device *dev) -{ - enum usb_dr_mode mode; - - mode = usb_get_dr_mode(dev); - switch (mode) { - case USB_DR_MODE_HOST: - return MUSB_PORT_MODE_HOST; - - case USB_DR_MODE_PERIPHERAL: - return MUSB_PORT_MODE_GADGET; - - case USB_DR_MODE_UNKNOWN: - case USB_DR_MODE_OTG: - default: - return MUSB_PORT_MODE_DUAL_ROLE; - } -} - static int dsps_create_musb_pdev(struct dsps_glue *glue, struct platform_device *parent) { @@ -786,6 +758,7 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue, musb->dev.parent = dev; musb->dev.dma_mask = &musb_dmamask; musb->dev.coherent_dma_mask = musb_dmamask; + device_set_of_node_from_dev(&musb->dev, &parent->dev); glue->musb = musb; @@ -807,7 +780,7 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue, config->num_eps = get_int_prop(dn, "mentor,num-eps"); config->ram_bits = get_int_prop(dn, "mentor,ram-bits"); config->host_port_deassert_reset_at_resume = 1; - pdata.mode = get_musb_port_mode(dev); + pdata.mode = musb_get_mode(dev); /* DT keeps this entry in mA, musb expects it as per USB spec */ pdata.power = get_int_prop(dn, "mentor,power") / 2; @@ -1047,7 +1020,7 @@ static int dsps_resume(struct device *dev) musb_writel(mbase, wrp->tx_mode, glue->context.tx_mode); musb_writel(mbase, wrp->rx_mode, glue->context.rx_mode); if (musb->xceiv->otg->state == OTG_STATE_B_IDLE && - musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) + musb->port_mode == MUSB_OTG) dsps_mod_timer(glue, -1); pm_runtime_put(dev); diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 71c5835ea9cd..eae8b1b1b45b 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1794,16 +1794,12 @@ int musb_gadget_setup(struct musb *musb) musb->g.speed = USB_SPEED_UNKNOWN; MUSB_DEV_MODE(musb); - musb->xceiv->otg->default_a = 0; musb->xceiv->otg->state = OTG_STATE_B_IDLE; /* this "gadget" abstracts/virtualizes the controller */ musb->g.name = musb_driver_name; -#if IS_ENABLED(CONFIG_USB_MUSB_DUAL_ROLE) - musb->g.is_otg = 1; -#elif IS_ENABLED(CONFIG_USB_MUSB_GADGET) + /* don't support otg protocols */ musb->g.is_otg = 0; -#endif INIT_DELAYED_WORK(&musb->gadget_work, musb_gadget_work); musb_g_init_endpoints(musb); @@ -1823,7 +1819,7 @@ err: void musb_gadget_cleanup(struct musb *musb) { - if (musb->port_mode == MUSB_PORT_MODE_HOST) + if (musb->port_mode == MUSB_HOST) return; cancel_delayed_work_sync(&musb->gadget_work); diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h index 9c34aca06db6..d02663660813 100644 --- a/drivers/usb/musb/musb_gadget.h +++ b/drivers/usb/musb/musb_gadget.h @@ -60,10 +60,7 @@ struct musb_request { enum buffer_map_state map_state; }; -static inline struct musb_request *to_musb_request(struct usb_request *req) -{ - return req ? container_of(req, struct musb_request, request) : NULL; -} +#define to_musb_request(r) container_of((r), struct musb_request, request) extern struct usb_request * musb_alloc_request(struct usb_ep *ep, gfp_t gfp_flags); @@ -99,10 +96,7 @@ struct musb_ep { u8 hb_mult; }; -static inline struct musb_ep *to_musb_ep(struct usb_ep *ep) -{ - return ep ? container_of(ep, struct musb_ep, end_point) : NULL; -} +#define to_musb_ep(ep) container_of((ep), struct musb_ep, end_point) static inline struct musb_request *next_request(struct musb_ep *ep) { diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 15a42cee0a9c..8000c7c02f79 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -2735,7 +2735,7 @@ int musb_host_alloc(struct musb *musb) void musb_host_cleanup(struct musb *musb) { - if (musb->port_mode == MUSB_PORT_MODE_GADGET) + if (musb->port_mode == MUSB_PERIPHERAL) return; usb_remove_hcd(musb->hcd); } @@ -2750,13 +2750,13 @@ int musb_host_setup(struct musb *musb, int power_budget) int ret; struct usb_hcd *hcd = musb->hcd; - if (musb->port_mode == MUSB_PORT_MODE_HOST) { + if (musb->port_mode == MUSB_HOST) { MUSB_HST_MODE(musb); - musb->xceiv->otg->default_a = 1; musb->xceiv->otg->state = OTG_STATE_A_IDLE; } otg_set_host(musb->xceiv->otg, &hcd->self); - hcd->self.otg_port = 1; + /* don't support otg protocols */ + hcd->self.otg_port = 0; musb->xceiv->otg->host = &hcd->self; hcd->power_budget = 2 * (power_budget ? : 250); hcd->skip_phy_initialization = 1; diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h index b7025b2e6e00..8058a58092cf 100644 --- a/drivers/usb/musb/musb_io.h +++ b/drivers/usb/musb/musb_io.h @@ -16,7 +16,6 @@ /** * struct musb_io - IO functions for MUSB - * @quirks: platform specific flags * @ep_offset: platform specific function to get end point offset * @ep_select: platform specific function to select end point * @fifo_offset: platform specific function to get fifo offset @@ -25,7 +24,6 @@ * @busctl_offset: platform specific function to get busctl offset */ struct musb_io { - u32 quirks; u32 (*ep_offset)(u8 epnum, u16 offset); void (*ep_select)(void __iomem *mbase, u8 epnum); u32 (*fifo_offset)(u8 epnum); @@ -39,7 +37,7 @@ extern u8 (*musb_readb)(const void __iomem *addr, unsigned offset); extern void (*musb_writeb)(void __iomem *addr, unsigned offset, u8 data); extern u16 (*musb_readw)(const void __iomem *addr, unsigned offset); extern void (*musb_writew)(void __iomem *addr, unsigned offset, u16 data); -extern u32 (*musb_readl)(const void __iomem *addr, unsigned offset); -extern void (*musb_writel)(void __iomem *addr, unsigned offset, u32 data); +extern u32 musb_readl(const void __iomem *addr, unsigned offset); +extern void musb_writel(void __iomem *addr, unsigned offset, u32 data); #endif diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index 88466622c89f..5cd7264fc2cb 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h @@ -273,67 +273,12 @@ #define MUSB_RXHUBADDR 0x06 #define MUSB_RXHUBPORT 0x07 -static inline void musb_write_txfifosz(void __iomem *mbase, u8 c_size) -{ - musb_writeb(mbase, MUSB_TXFIFOSZ, c_size); -} - -static inline void musb_write_txfifoadd(void __iomem *mbase, u16 c_off) -{ - musb_writew(mbase, MUSB_TXFIFOADD, c_off); -} - -static inline void musb_write_rxfifosz(void __iomem *mbase, u8 c_size) -{ - musb_writeb(mbase, MUSB_RXFIFOSZ, c_size); -} - -static inline void musb_write_rxfifoadd(void __iomem *mbase, u16 c_off) -{ - musb_writew(mbase, MUSB_RXFIFOADD, c_off); -} - -static inline void musb_write_ulpi_buscontrol(void __iomem *mbase, u8 val) -{ - musb_writeb(mbase, MUSB_ULPI_BUSCONTROL, val); -} - -static inline u8 musb_read_txfifosz(void __iomem *mbase) -{ - return musb_readb(mbase, MUSB_TXFIFOSZ); -} - -static inline u16 musb_read_txfifoadd(void __iomem *mbase) -{ - return musb_readw(mbase, MUSB_TXFIFOADD); -} - -static inline u8 musb_read_rxfifosz(void __iomem *mbase) -{ - return musb_readb(mbase, MUSB_RXFIFOSZ); -} - -static inline u16 musb_read_rxfifoadd(void __iomem *mbase) -{ - return musb_readw(mbase, MUSB_RXFIFOADD); -} - -static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase) -{ - return musb_readb(mbase, MUSB_ULPI_BUSCONTROL); -} - static inline u8 musb_read_configdata(void __iomem *mbase) { musb_writeb(mbase, MUSB_INDEX, 0); return musb_readb(mbase, 0x10 + MUSB_CONFIGDATA); } -static inline u16 musb_read_hwvers(void __iomem *mbase) -{ - return musb_readw(mbase, MUSB_HWVERS); -} - static inline void musb_write_rxfunaddr(struct musb *musb, u8 epnum, u8 qh_addr_reg) { diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index 2f8dd9826e94..a84ec27c4c12 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -254,7 +254,7 @@ static int musb_has_gadget(struct musb *musb) #ifdef CONFIG_USB_MUSB_HOST return 1; #else - return musb->port_mode == MUSB_PORT_MODE_HOST; + return musb->port_mode == MUSB_HOST; #endif } diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 4389fc3422bd..a688f7f87829 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -10,7 +10,71 @@ #include <linux/platform_device.h> #include <linux/slab.h> #include "musb_core.h" -#include "musbhsdma.h" + +#define MUSB_HSDMA_BASE 0x200 +#define MUSB_HSDMA_INTR (MUSB_HSDMA_BASE + 0) +#define MUSB_HSDMA_CONTROL 0x4 +#define MUSB_HSDMA_ADDRESS 0x8 +#define MUSB_HSDMA_COUNT 0xc + +#define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset) \ + (MUSB_HSDMA_BASE + (_bchannel << 4) + _offset) + +#define musb_read_hsdma_addr(mbase, bchannel) \ + musb_readl(mbase, \ + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS)) + +#define musb_write_hsdma_addr(mbase, bchannel, addr) \ + musb_writel(mbase, \ + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), \ + addr) + +#define musb_read_hsdma_count(mbase, bchannel) \ + musb_readl(mbase, \ + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT)) + +#define musb_write_hsdma_count(mbase, bchannel, len) \ + musb_writel(mbase, \ + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), \ + len) +/* control register (16-bit): */ +#define MUSB_HSDMA_ENABLE_SHIFT 0 +#define MUSB_HSDMA_TRANSMIT_SHIFT 1 +#define MUSB_HSDMA_MODE1_SHIFT 2 +#define MUSB_HSDMA_IRQENABLE_SHIFT 3 +#define MUSB_HSDMA_ENDPOINT_SHIFT 4 +#define MUSB_HSDMA_BUSERROR_SHIFT 8 +#define MUSB_HSDMA_BURSTMODE_SHIFT 9 +#define MUSB_HSDMA_BURSTMODE (3 << MUSB_HSDMA_BURSTMODE_SHIFT) +#define MUSB_HSDMA_BURSTMODE_UNSPEC 0 +#define MUSB_HSDMA_BURSTMODE_INCR4 1 +#define MUSB_HSDMA_BURSTMODE_INCR8 2 +#define MUSB_HSDMA_BURSTMODE_INCR16 3 + +#define MUSB_HSDMA_CHANNELS 8 + +struct musb_dma_controller; + +struct musb_dma_channel { + struct dma_channel channel; + struct musb_dma_controller *controller; + u32 start_addr; + u32 len; + u16 max_packet_sz; + u8 idx; + u8 epnum; + u8 transmit; +}; + +struct musb_dma_controller { + struct dma_controller controller; + struct musb_dma_channel channel[MUSB_HSDMA_CHANNELS]; + void *private_data; + void __iomem *base; + u8 channel_count; + u8 used_channels; + int irq; +}; static void dma_channel_release(struct dma_channel *channel); @@ -135,14 +199,6 @@ static int dma_channel_program(struct dma_channel *channel, BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN || channel->status == MUSB_DMA_STATUS_BUSY); - /* Let targets check/tweak the arguments */ - if (musb->ops->adjust_channel_params) { - int ret = musb->ops->adjust_channel_params(channel, - packet_sz, &mode, &dma_addr, &len); - if (ret) - return ret; - } - /* * The DMA engine in RTL1.8 and above cannot handle * DMA addresses that are not aligned to a 4 byte boundary. diff --git a/drivers/usb/musb/musbhsdma.h b/drivers/usb/musb/musbhsdma.h deleted file mode 100644 index 93665135aff1..000000000000 --- a/drivers/usb/musb/musbhsdma.h +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * MUSB OTG driver - support for Mentor's DMA controller - * - * Copyright 2005 Mentor Graphics Corporation - * Copyright (C) 2005-2007 by Texas Instruments - */ - -#define MUSB_HSDMA_BASE 0x200 -#define MUSB_HSDMA_INTR (MUSB_HSDMA_BASE + 0) -#define MUSB_HSDMA_CONTROL 0x4 -#define MUSB_HSDMA_ADDRESS 0x8 -#define MUSB_HSDMA_COUNT 0xc - -#define MUSB_HSDMA_CHANNEL_OFFSET(_bchannel, _offset) \ - (MUSB_HSDMA_BASE + (_bchannel << 4) + _offset) - -#define musb_read_hsdma_addr(mbase, bchannel) \ - musb_readl(mbase, \ - MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS)) - -#define musb_write_hsdma_addr(mbase, bchannel, addr) \ - musb_writel(mbase, \ - MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), \ - addr) - -#define musb_read_hsdma_count(mbase, bchannel) \ - musb_readl(mbase, \ - MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT)) - -#define musb_write_hsdma_count(mbase, bchannel, len) \ - musb_writel(mbase, \ - MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), \ - len) -/* control register (16-bit): */ -#define MUSB_HSDMA_ENABLE_SHIFT 0 -#define MUSB_HSDMA_TRANSMIT_SHIFT 1 -#define MUSB_HSDMA_MODE1_SHIFT 2 -#define MUSB_HSDMA_IRQENABLE_SHIFT 3 -#define MUSB_HSDMA_ENDPOINT_SHIFT 4 -#define MUSB_HSDMA_BUSERROR_SHIFT 8 -#define MUSB_HSDMA_BURSTMODE_SHIFT 9 -#define MUSB_HSDMA_BURSTMODE (3 << MUSB_HSDMA_BURSTMODE_SHIFT) -#define MUSB_HSDMA_BURSTMODE_UNSPEC 0 -#define MUSB_HSDMA_BURSTMODE_INCR4 1 -#define MUSB_HSDMA_BURSTMODE_INCR8 2 -#define MUSB_HSDMA_BURSTMODE_INCR16 3 - -#define MUSB_HSDMA_CHANNELS 8 - -struct musb_dma_controller; - -struct musb_dma_channel { - struct dma_channel channel; - struct musb_dma_controller *controller; - u32 start_addr; - u32 len; - u16 max_packet_sz; - u8 idx; - u8 epnum; - u8 transmit; -}; - -struct musb_dma_controller { - struct dma_controller controller; - struct musb_dma_channel channel[MUSB_HSDMA_CHANNELS]; - void *private_data; - void __iomem *base; - u8 channel_count; - u8 used_channels; - int irq; -}; diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 5d705930ef47..b1dd81fb5f55 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -77,7 +77,6 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) otg_set_vbus(otg, 1); } else { musb->is_active = 1; - otg->default_a = 1; musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; devctl |= MUSB_DEVCTL_SESSION; MUSB_HST_MODE(musb); @@ -89,7 +88,6 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) * jumping right to B_IDLE... */ - otg->default_a = 0; musb->xceiv->otg->state = OTG_STATE_B_IDLE; devctl &= ~MUSB_DEVCTL_SESSION; @@ -148,14 +146,12 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) struct musb_hdrc_platform_data *pdata = dev_get_platdata(musb->controller); struct omap_musb_board_data *data = pdata->board_data; - struct usb_otg *otg = musb->xceiv->otg; pm_runtime_get_sync(musb->controller); switch (glue->status) { case MUSB_ID_GROUND: dev_dbg(musb->controller, "ID GND\n"); - otg->default_a = true; musb->xceiv->otg->state = OTG_STATE_A_IDLE; musb->xceiv->last_event = USB_EVENT_ID; if (musb->gadget_driver) { @@ -168,7 +164,6 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) case MUSB_VBUS_VALID: dev_dbg(musb->controller, "VBUS Connect\n"); - otg->default_a = false; musb->xceiv->otg->state = OTG_STATE_B_IDLE; musb->xceiv->last_event = USB_EVENT_VBUS; omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE); @@ -239,21 +234,15 @@ static int omap2430_musb_init(struct musb *musb) * up through ULPI. TWL4030-family PMICs include one, * which needs a driver, drivers aren't always needed. */ - if (dev->parent->of_node) { - musb->phy = devm_phy_get(dev->parent, "usb2-phy"); - - /* We can't totally remove musb->xceiv as of now because - * musb core uses xceiv.state and xceiv.otg. Once we have - * a separate state machine to handle otg, these can be moved - * out of xceiv and then we can start using the generic PHY - * framework - */ - musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, - "usb-phy", 0); - } else { - musb->xceiv = devm_usb_get_phy_dev(dev, 0); - musb->phy = devm_phy_get(dev, "usb"); - } + musb->phy = devm_phy_get(dev->parent, "usb2-phy"); + + /* We can't totally remove musb->xceiv as of now because + * musb core uses xceiv.state and xceiv.otg. Once we have + * a separate state machine to handle otg, these can be moved + * out of xceiv and then we can start using the generic PHY + * framework + */ + musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, "usb-phy", 0); if (IS_ERR(musb->xceiv)) { status = PTR_ERR(musb->xceiv); @@ -391,8 +380,13 @@ static int omap2430_probe(struct platform_device *pdev) struct omap2430_glue *glue; struct device_node *np = pdev->dev.of_node; struct musb_hdrc_config *config; + struct device_node *control_node; + struct platform_device *control_pdev; int ret = -ENOMEM, val; + if (!np) + return -ENODEV; + glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); if (!glue) goto err0; @@ -412,47 +406,43 @@ static int omap2430_probe(struct platform_device *pdev) glue->status = MUSB_UNKNOWN; glue->control_otghs = ERR_PTR(-ENODEV); - if (np) { - struct device_node *control_node; - struct platform_device *control_pdev; + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + goto err2; - pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - goto err2; + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + goto err2; - data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); - if (!data) - goto err2; + config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL); + if (!config) + goto err2; - config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL); - if (!config) + of_property_read_u32(np, "mode", (u32 *)&pdata->mode); + of_property_read_u32(np, "interface-type", + (u32 *)&data->interface_type); + of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps); + of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits); + of_property_read_u32(np, "power", (u32 *)&pdata->power); + + ret = of_property_read_u32(np, "multipoint", &val); + if (!ret && val) + config->multipoint = true; + + pdata->board_data = data; + pdata->config = config; + + control_node = of_parse_phandle(np, "ctrl-module", 0); + if (control_node) { + control_pdev = of_find_device_by_node(control_node); + if (!control_pdev) { + dev_err(&pdev->dev, "Failed to get control device\n"); + ret = -EINVAL; goto err2; - - of_property_read_u32(np, "mode", (u32 *)&pdata->mode); - of_property_read_u32(np, "interface-type", - (u32 *)&data->interface_type); - of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps); - of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits); - of_property_read_u32(np, "power", (u32 *)&pdata->power); - - ret = of_property_read_u32(np, "multipoint", &val); - if (!ret && val) - config->multipoint = true; - - pdata->board_data = data; - pdata->config = config; - - control_node = of_parse_phandle(np, "ctrl-module", 0); - if (control_node) { - control_pdev = of_find_device_by_node(control_node); - if (!control_pdev) { - dev_err(&pdev->dev, "Failed to get control device\n"); - ret = -EINVAL; - goto err2; - } - glue->control_otghs = &control_pdev->dev; } + glue->control_otghs = &control_pdev->dev; } + pdata->platform_ops = &omap2430_ops; platform_set_drvdata(pdev, glue); diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c index 2d201219ecff..832a41f9ee7d 100644 --- a/drivers/usb/musb/sunxi.c +++ b/drivers/usb/musb/sunxi.c @@ -105,13 +105,11 @@ static void sunxi_musb_work(struct work_struct *work) devctl = readb(musb->mregs + SUNXI_MUSB_DEVCTL); if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) { set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags); - musb->xceiv->otg->default_a = 1; musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; MUSB_HST_MODE(musb); devctl |= MUSB_DEVCTL_SESSION; } else { clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags); - musb->xceiv->otg->default_a = 0; musb->xceiv->otg->state = OTG_STATE_B_IDLE; MUSB_DEV_MODE(musb); devctl &= ~MUSB_DEVCTL_SESSION; @@ -347,7 +345,7 @@ static int sunxi_musb_set_mode(struct musb *musb, u8 mode) if (glue->phy_mode == new_mode) return 0; - if (musb->port_mode != MUSB_PORT_MODE_DUAL_ROLE) { + if (musb->port_mode != MUSB_OTG) { dev_err(musb->controller->parent, "Error changing modes is only supported in dual role mode\n"); return -EINVAL; @@ -651,10 +649,8 @@ static const struct musb_hdrc_config sunxi_musb_hdrc_config = { .fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg), .multipoint = true, .dyn_fifo = true, - .soft_con = true, .num_eps = SUNXI_MUSB_MAX_EP_NUM, .ram_bits = SUNXI_MUSB_RAM_BITS, - .dma = 0, }; static struct musb_hdrc_config sunxi_musb_hdrc_config_h3 = { @@ -662,10 +658,8 @@ static struct musb_hdrc_config sunxi_musb_hdrc_config_h3 = { .fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg_h3), .multipoint = true, .dyn_fifo = true, - .soft_con = true, .num_eps = SUNXI_MUSB_MAX_EP_NUM_H3, .ram_bits = SUNXI_MUSB_RAM_BITS, - .dma = 0, }; @@ -690,19 +684,19 @@ static int sunxi_musb_probe(struct platform_device *pdev) switch (usb_get_dr_mode(&pdev->dev)) { #if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_HOST case USB_DR_MODE_HOST: - pdata.mode = MUSB_PORT_MODE_HOST; + pdata.mode = MUSB_HOST; glue->phy_mode = PHY_MODE_USB_HOST; break; #endif #if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_GADGET case USB_DR_MODE_PERIPHERAL: - pdata.mode = MUSB_PORT_MODE_GADGET; + pdata.mode = MUSB_PERIPHERAL; glue->phy_mode = PHY_MODE_USB_DEVICE; break; #endif #ifdef CONFIG_USB_MUSB_DUAL_ROLE case USB_DR_MODE_OTG: - pdata.mode = MUSB_PORT_MODE_DUAL_ROLE; + pdata.mode = MUSB_OTG; glue->phy_mode = PHY_MODE_USB_OTG; break; #endif diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index 27b4a77a9e23..73538d1d0524 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -62,7 +62,6 @@ static void ux500_musb_set_vbus(struct musb *musb, int is_on) } else { musb->is_active = 1; - musb->xceiv->otg->default_a = 1; musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; devctl |= MUSB_DEVCTL_SESSION; MUSB_HST_MODE(musb); @@ -73,7 +72,6 @@ static void ux500_musb_set_vbus(struct musb *musb, int is_on) /* NOTE: we're skipping A_WAIT_VFALL -> A_IDLE and jumping * right to B_IDLE... */ - musb->xceiv->otg->default_a = 0; devctl &= ~MUSB_DEVCTL_SESSION; MUSB_DEV_MODE(musb); } |