/*-------------------------------------------------------------------------*/
#ifndef CONFIG_BLACKFIN
-static int musb_ulpi_read(struct otg_transceiver *otg, u32 offset)
+static int musb_ulpi_read(struct otg_transceiver *otg, u32 reg)
{
void __iomem *addr = otg->io_priv;
int i = 0;
* ULPICarKitControlDisableUTMI after clearing POWER_SUSPENDM.
*/
- musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset);
+ musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)reg);
musb_writeb(addr, MUSB_ULPI_REG_CONTROL,
MUSB_ULPI_REG_REQ | MUSB_ULPI_RDN_WR);
return ret;
}
-static int musb_ulpi_write(struct otg_transceiver *otg,
- u32 offset, u32 data)
+static int musb_ulpi_write(struct otg_transceiver *otg, u32 val, u32 reg)
{
void __iomem *addr = otg->io_priv;
int i = 0;
power &= ~MUSB_POWER_SUSPENDM;
musb_writeb(addr, MUSB_POWER, power);
- musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)offset);
- musb_writeb(addr, MUSB_ULPI_REG_DATA, (u8)data);
+ musb_writeb(addr, MUSB_ULPI_REG_ADDR, (u8)reg);
+ musb_writeb(addr, MUSB_ULPI_REG_DATA, (u8)val);
musb_writeb(addr, MUSB_ULPI_REG_CONTROL, MUSB_ULPI_REG_REQ);
while (!(musb_readb(addr, MUSB_ULPI_REG_CONTROL)
if (power & MUSB_POWER_SUSPENDM) {
/* spurious */
- musb->int_usb &= ~MUSB_INTR_SUSPEND;
- dev_dbg(musb->controller, "Spurious SUSPENDM\n");
+ int_usb &= ~MUSB_INTR_SUSPEND;
+ dev_err(musb->controller, "Spurious SUSPENDM\n");
break;
}
if ((devctl & MUSB_DEVCTL_VBUS)
!= (3 << MUSB_DEVCTL_VBUS_SHIFT)
) {
- musb->int_usb |= MUSB_INTR_DISCONNECT;
- musb->int_usb &= ~MUSB_INTR_SUSPEND;
+ if (!(int_usb & MUSB_INTR_DISCONNECT))
+ dev_err(musb->controller,
+ "disconnect while suspended?\n");
+ int_usb |= MUSB_INTR_DISCONNECT;
+ int_usb &= ~MUSB_INTR_SUSPEND;
break;
}
musb_g_resume(musb);
break;
case OTG_STATE_B_IDLE:
- musb->int_usb &= ~MUSB_INTR_SUSPEND;
+ if (int_usb & MUSB_INTR_SUSPEND)
+ dev_err(musb->controller,
+ "bogus suspend+resume?\n");
+ int_usb &= ~MUSB_INTR_SUSPEND;
break;
default:
WARNING("bogus %s RESUME (%s)\n",
break;
}
- dev_dbg(musb->controller, "VBUS_ERROR in %s (%02x, %s), retry #%d, port1 %08x\n",
+ dev_printk(ignore ? KERN_DEBUG : KERN_ERR, musb->controller,
+ "VBUS_ERROR in %s (%02x, %02x, %s), retry #%d, port1 %08x\n",
otg_state_string(musb->xceiv->state),
- devctl,
+ devctl, power,
({ char *s;
switch (devctl & MUSB_DEVCTL_VBUS) {
case 0 << MUSB_DEVCTL_VBUS_SHIFT:
switch (musb->xceiv->state) {
case OTG_STATE_B_PERIPHERAL:
if (int_usb & MUSB_INTR_SUSPEND) {
- dev_dbg(musb->controller, "HNP: SUSPEND+CONNECT, now b_host\n");
+ dev_err(musb->controller, "HNP: SUSPEND+CONNECT, now b_host\n");
int_usb &= ~MUSB_INTR_SUSPEND;
goto b_host;
} else
*/
if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS)
musb->is_active = 1;
- else
- devctl |= MUSB_DEVCTL_SESSION;
+ //else
+ // devctl |= MUSB_DEVCTL_SESSION;
} else if (is_host_enabled(musb)) {
/* assume ID pin is hard-wired to ground */
unsigned long flags;
irqreturn_t retval = IRQ_NONE;
struct musb *musb = __hci;
+ int i;
spin_lock_irqsave(&musb->lock, flags);
- musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
- musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
- musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
+ for (i = 0; i < 8; i++) {
+ musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
+ /* SOF is not enabled, but status is still often set */
+ musb->int_usb &= ~MUSB_INTR_SOF;
+ musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
+ musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
- if (musb->int_usb || musb->int_tx || musb->int_rx)
- retval = musb_interrupt(musb);
+ if (musb->int_usb || musb->int_tx || musb->int_rx)
+ retval = musb_interrupt(musb);
+ else
+ break;
+ }
spin_unlock_irqrestore(&musb->lock, flags);
(devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral",
musb->int_usb, musb->int_tx, musb->int_rx);
- /* the core can interrupt us for multiple reasons; docs have
- * a generic interrupt flowchart to follow
+ /**
+ * According to Mentor Graphics' documentation, flowchart on page 98,
+ * IRQ should be handled as follows:
+ *
+ * . Resume IRQ
+ * . Session Request IRQ
+ * . VBUS Error IRQ
+ * . Suspend IRQ
+ * . Connect IRQ
+ * . Disconnect IRQ
+ * . Reset/Babble IRQ
+ * . SOF IRQ (we're not using this one)
+ * . Endpoint 0 IRQ
+ * . TX Endpoints
+ * . RX Endpoints
+ *
+ * We will be following that flowchart in order to avoid any problems
+ * that might arise with internal Finite State Machine.
*/
+
if (musb->int_usb)
retval |= musb_stage0_irq(musb, musb->int_usb,
devctl, power);
- /* "stage 1" is handling endpoint irqs */
-
- /* handle endpoint 0 first */
if (musb->int_tx & 1) {
if (devctl & MUSB_DEVCTL_HM)
retval |= musb_h_ep0_irq(musb);
retval |= musb_g_ep0_irq(musb);
}
- /* RX on endpoints 1-15 */
- reg = musb->int_rx >> 1;
+ reg = musb->int_tx >> 1;
ep_num = 1;
while (reg) {
if (reg & 1) {
- /* musb_ep_select(musb->mregs, ep_num); */
- /* REVISIT just retval = ep->rx_irq(...) */
retval = IRQ_HANDLED;
if (devctl & MUSB_DEVCTL_HM) {
if (is_host_capable())
- musb_host_rx(musb, ep_num);
+ musb_host_tx(musb, ep_num);
} else {
if (is_peripheral_capable())
- musb_g_rx(musb, ep_num);
+ musb_g_tx(musb, ep_num);
}
}
-
reg >>= 1;
ep_num++;
}
- /* TX on endpoints 1-15 */
- reg = musb->int_tx >> 1;
+ reg = musb->int_rx >> 1;
ep_num = 1;
while (reg) {
if (reg & 1) {
- /* musb_ep_select(musb->mregs, ep_num); */
- /* REVISIT just retval |= ep->tx_irq(...) */
retval = IRQ_HANDLED;
if (devctl & MUSB_DEVCTL_HM) {
if (is_host_capable())
- musb_host_tx(musb, ep_num);
+ musb_host_rx(musb, ep_num);
} else {
if (is_peripheral_capable())
- musb_g_tx(musb, ep_num);
+ musb_g_rx(musb, ep_num);
}
}
+
reg >>= 1;
ep_num++;
}
if (musb_ulpi_access.write == NULL)
return;
+ pm_runtime_get_sync(musb->controller);
+
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
/*
//if (ret)
// dev_err(musb->controller, "VBUS workaround error\n");
}
+
+ pm_runtime_put(musb->controller);
}
/* --------------------------------------------------------------------------
dma_controller_destroy(c);
}
- kfree(musb);
+ usb_put_hcd(musb_to_hcd(musb));
}
/*
? 'B' : 'A'));
} else /* peripheral is enabled */ {
- MUSB_DEV_MODE(musb);
- musb->xceiv->default_a = 0;
- musb->xceiv->state = OTG_STATE_B_IDLE;
+ if (musb->xceiv->default_a) {
+ MUSB_HST_MODE(musb);
+ musb->xceiv->state = OTG_STATE_A_IDLE;
+ } else {
+ MUSB_DEV_MODE(musb);
+ musb->xceiv->state = OTG_STATE_B_IDLE;
+ }
status = musb_gadget_setup(musb);
spin_lock_irqsave(&musb->lock, flags);
- if (is_peripheral_active(musb)) {
+ {
/* FIXME force disconnect unless we know USB will wake
* the system up quickly enough to respond ...
*/
pm_usage_count);
ret = -EBUSY;
}
- } else if (is_host_active(musb)) {
- /* we know all the children are suspended; sometimes
- * they will even be wakeup-enabled.
- */
}
spin_unlock_irqrestore(&musb->lock, flags);
if (usb_disabled())
return 0;
- pr_info("%s: version " MUSB_VERSION ", "
- "?dma?"
- ", "
- "otg (peripheral+host)",
+ pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n",
musb_driver_name);
return platform_driver_probe(&musb_driver, musb_probe);
}