--- zzzz-none-000/linux-2.6.28.10/drivers/usb/musb/musb_core.c 2009-05-02 18:54:43.000000000 +0000 +++ puma5-6360-529/linux-2.6.28.10/drivers/usb/musb/musb_core.c 2011-03-08 12:52:02.000000000 +0000 @@ -82,9 +82,9 @@ /* * This gets many kinds of configuration information: * - Kconfig for everything user-configurable + * - for SOC or family details * - platform_device for addressing, irq, and platform_data * - platform_data is mostly for board-specific informarion - * (plus recentrly, SOC or family details) * * Most of the conditional compilation will (someday) vanish. */ @@ -100,13 +100,23 @@ #include #ifdef CONFIG_ARM -#include -#include +#include +#include #include #endif #include "musb_core.h" +#ifdef CONFIG_ARCH_PUMA5 +#include "puma5.h" +#include "cppi41_dma.h" +#if defined(CONFIG_ARM_AVALANCHE_PPD) && defined(CONFIG_USB_PPD_SUPPORT) +#include +extern Int32 ti_ppd_config_pid_range(TI_PP_PID_RANGE *pid_range); +#include +static TI_PP_PID_RANGE pid_range_usb; +#endif +#endif #ifdef CONFIG_ARCH_DAVINCI #include "davinci.h" @@ -114,14 +124,23 @@ -unsigned musb_debug; -module_param(musb_debug, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug message level. Default = 0"); +#if MUSB_DEBUG > 0 +unsigned debug = MUSB_DEBUG; +module_param(debug, uint, 0); +MODULE_PARM_DESC(debug, "initial debug message level"); + +#define MUSB_VERSION_SUFFIX "/dbg" +#endif #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia" #define DRIVER_DESC "Inventra Dual-Role USB Controller Driver" -#define MUSB_VERSION "6.0" +#define MUSB_VERSION_BASE "6.0" + +#ifndef MUSB_VERSION_SUFFIX +#define MUSB_VERSION_SUFFIX "" +#endif +#define MUSB_VERSION MUSB_VERSION_BASE MUSB_VERSION_SUFFIX #define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION @@ -149,6 +168,126 @@ /*-------------------------------------------------------------------------*/ #ifndef CONFIG_USB_TUSB6010 + +static void musb_fifo_io(u8 * fifo, u8 * buf, u16 len, char is_read) +{ + u16 index = 0; +// char size = ((unsigned long)buf & 0x04) ? 4 : +// ((unsigned long)buf & 0x02) ? 2 : 1; +/* AVM/BC Fix*/ + char size = ((unsigned long)buf & 0x01) ? 1 : + ((unsigned long)buf & 0x02) ? 2 : 4; +#ifndef CONFIG_CPU_LITTLE_ENDIAN + u32 *pTemp = (u32 *) buf; + u16 *pTmp16 = (u16 *) buf; +#endif +/* AVM/BC Fix*/ + if (len == 0) { + return; + } + size = (len >= size) ? size : (len >= (size >> 1)) ? (size >> 1) : 1; + if (size == 1) { + if (is_read) + readsb(fifo, (void *__iomem)buf, len); + else + writesb(fifo, (void *__iomem)buf, len); + return; + } +#ifndef CONFIG_CPU_LITTLE_ENDIAN + while (len >= size) { + switch (size) { + case 4: + if (is_read) + *pTemp = cpu_to_le32(*(u32 *) fifo); + else + *(u32 *) fifo = cpu_to_le32(*pTemp); + pTemp++; + break; + case 2: + if (is_read) + *pTmp16 = cpu_to_le16(*(u16 *) fifo); + else + *(u16 *) fifo = cpu_to_le16(*pTmp16); + pTmp16++; + break; + } + len -= size; + index += size; + } +#else + switch (size) { + case 4: + if (is_read) + readsl(fifo, buf, len >> 2); + else + writesl(fifo, (void *__iomem)(buf), len >> 2); + index += len & ~0x03; + break; + case 2: + if (is_read) + readsw(fifo, buf, len >> 1); + else + writesw(fifo, (void *__iomem)(buf), len >> 1); + index += len & ~0x01; + break; + } +#endif + if (len & 0x02) { + if (is_read) + *(u16 *) & buf[index] = + cpu_to_le16(musb_readw(fifo, 0)); + else + musb_writew(fifo, 0, + cpu_to_le16(*(u16 *) & buf[index])); + index += 2; + } + if (len & 0x01) { + if (is_read) + buf[index] = musb_readb(fifo, 0); + else + musb_writeb(fifo, 0, buf[index]); + } +} +void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 wCount, const u8 * pSource) +{ + void __iomem *fifo = hw_ep->fifo; + prefetch((u8 *) pSource); + DBG(4, "%cX ep%d fifo %p count %d buf %p\n", + 'T', hw_ep->epnum, fifo, wCount, pSource); + /* we can't assume unaligned reads work */ + if (likely((0x01 & (unsigned long)pSource) == 0)) { + /* best case is 32bit-aligned source address */ + if ((0x02 & (unsigned long)pSource) == 0) { + musb_fifo_io(fifo, (u8 *) pSource, wCount, 0); + } else { + musb_fifo_io(fifo, (u8 *) pSource, wCount, 0); + } + } else { + musb_fifo_io(fifo, (u8 *) pSource, wCount, 0); + } +} + +void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 wCount, u8 * pDest) +{ + void __iomem *fifo = hw_ep->fifo; + DBG(4, "%cX ep%d fifo %p count %d buf %p\n", + 'R', hw_ep->epnum, fifo, wCount, pDest); + + /* we can't assume unaligned writes work */ + if (likely((0x01 & (unsigned long)pDest) == 0)) { + /* best case is 32bit-aligned destination address */ + if ((0x02 & (unsigned long)pDest) == 0) { + musb_fifo_io(fifo, pDest, wCount, 1); + } else { + musb_fifo_io(fifo, pDest, wCount, 1); + } + } else { + musb_fifo_io(fifo, pDest, wCount, 1); + } +} + + +#else /* * Load an endpoint's FIFO */ @@ -233,7 +372,7 @@ /*-------------------------------------------------------------------------*/ /* for high speed test mode; see USB 2.0 spec 7.1.20 */ -static const u8 musb_test_packet[53] = { +const u8 musb_test_packet[53] = { /* implicit SYNC then DATA0 to start */ /* JKJKJKJK x9 */ @@ -257,7 +396,7 @@ void __iomem *regs = musb->endpoints[0].regs; musb_ep_select(musb->mregs, 0); - musb_write_fifo(musb->control_ep, + musb_write_fifo(musb->endpoints, sizeof(musb_test_packet), musb_test_packet); musb_writew(regs, MUSB_CSR0, MUSB_CSR0_TXPKTRDY); } @@ -366,6 +505,54 @@ #endif +void musb_fifo_check_tasklet(unsigned long data) +{ + struct musb *musb = (struct musb *)data; + u8 epnum = 1, sch_tsklt = 0; + struct musb_hw_ep *hw_ep = NULL; + unsigned long flags; + u16 csr; + void __iomem *epio = hw_ep->regs; + void __iomem *mbase = musb->mregs; + + do { + hw_ep = musb->endpoints + epnum; + epio = hw_ep->regs; + spin_lock_irqsave(&musb->lock, flags); + musb_ep_select(mbase, epnum); + if (hw_ep->fifo_flush_check) { + csr = musb_readw(epio, MUSB_TXCSR); + if ((csr & MUSB_TXCSR_FIFONOTEMPTY) || + (csr & MUSB_TXCSR_TXPKTRDY)) { + sch_tsklt = 1; + DBG(6, "Rescheduling %d\n", + hw_ep->epnum); + } else { + hw_ep->fifo_flush_check = 0; + musb->fifo_check_complete(hw_ep); + DBG(6, "Completed Tasklet %d\n", + hw_ep->epnum); + } + } + + spin_unlock_irqrestore(&musb->lock, flags); + /* REVISIT: we should check TX eps only */ + epnum++; + } while (epnum < MUSB_C_NUM_EPS); + + if (sch_tsklt) + tasklet_schedule(&musb->fifo_check); +} +#if 1 +#ifdef CONFIG_MUSB_SCHEDULE_INTR_EP +int use_intr_sched = 1; +#endif + +int is_intr_sched(void) +{ + return use_intr_sched; +} +#endif /* * Interrupt Service Routine to record USB "global" interrupts. * Since these do not happen often and signify things of @@ -530,6 +717,8 @@ ignore = 1; devctl |= MUSB_DEVCTL_SESSION; musb_writeb(mbase, MUSB_DEVCTL, devctl); + /* 20110107 AVM/WK FIX for BABBLE Error Recovery */ + musb_root_disconnect(musb); } else { musb->port1_status |= (1 << USB_PORT_FEAT_OVER_CURRENT) @@ -600,6 +789,8 @@ MUSB_HST_MODE(musb); + musb->fifo_check_complete = musb_h_fifo_check_complete; + /* indicate new connection to OTG machine */ switch (musb->xceiv.state) { case OTG_STATE_B_PERIPHERAL: @@ -652,10 +843,6 @@ switch (musb->xceiv.state) { #ifdef CONFIG_USB_OTG case OTG_STATE_A_SUSPEND: - /* We need to ignore disconnect on suspend - * otherwise tusb 2.0 won't reconnect after a - * power cycle, which breaks otg compliance. - */ musb->ignore_disconnect = 1; musb_g_reset(musb); /* FALLTHROUGH */ @@ -670,7 +857,7 @@ musb_hnp_stop(musb); break; case OTG_STATE_B_WAIT_ACON: - DBG(1, "HNP: RESET (%s), to b_peripheral\n", + DBG(1, "HNP: RESET (%s), back to b_peripheral\n", otg_state_string(musb)); musb->xceiv.state = OTG_STATE_B_PERIPHERAL; musb_g_reset(musb); @@ -723,38 +910,46 @@ * endpoints, relies on TX/RX interval registers, and isn't claimed * to support ISO transfers yet. */ + if (int_usb & MUSB_INTR_SOF) { + void __iomem *mbase = musb->mregs; + struct musb_hw_ep *ep; + u8 epnum; + u16 frame; + + DBG(6, "START_OF_FRAME\n"); + handled = IRQ_HANDLED; + + /* start any periodic Tx transfers waiting for current frame */ + frame = musb_readw(mbase, MUSB_FRAME); + ep = musb->endpoints; + for (epnum = 1; (epnum < musb->nr_endpoints) + && (musb->epmask >= (1 << epnum)); + epnum++, ep++) { + /* + * FIXME handle framecounter wraps (12 bits) + * eliminate duplicated StartUrb logic + */ + if (ep->dwWaitFrame >= frame) { + ep->dwWaitFrame = 0; + printk("SOF --> periodic TX%s on %d\n", + ep->tx_channel ? " DMA" : "", + epnum); + if (!ep->tx_channel) + musb_h_tx_start(musb, epnum); + else + cppi_hostdma_start(musb, epnum); + } + } /* end of for loop */ + } +#endif if (int_usb & MUSB_INTR_SOF) { - void __iomem *mbase = musb->mregs; - struct musb_hw_ep *ep; - u8 epnum; - u16 frame; - - DBG(6, "START_OF_FRAME\n"); - handled = IRQ_HANDLED; - - /* start any periodic Tx transfers waiting for current frame */ - frame = musb_readw(mbase, MUSB_FRAME); - ep = musb->endpoints; - for (epnum = 1; (epnum < musb->nr_endpoints) - && (musb->epmask >= (1 << epnum)); - epnum++, ep++) { - /* - * FIXME handle framecounter wraps (12 bits) - * eliminate duplicated StartUrb logic - */ - if (ep->dwWaitFrame >= frame) { - ep->dwWaitFrame = 0; - pr_debug("SOF --> periodic TX%s on %d\n", - ep->tx_channel ? " DMA" : "", - epnum); - if (!ep->tx_channel) - musb_h_tx_start(musb, epnum); - else - cppi_hostdma_start(musb, epnum); - } - } /* end of for loop */ - } + DBG(5, "START_OF_FRAME\n"); + handled = IRQ_HANDLED; +#ifdef CONFIG_USB_MUSB_HDRC_HCD + if (is_intr_sched() && musb->intr_ep) + musb_host_intr_schedule(musb); #endif + } if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) { DBG(1, "DISCONNECT (%s) as %s, devctl %02x\n", @@ -876,7 +1071,7 @@ | MUSB_POWER_SOFTCONN | MUSB_POWER_HSENAB /* ENSUSPEND wedges tusb */ - /* | MUSB_POWER_ENSUSPEND */ + | MUSB_POWER_ENSUSPEND ); musb->is_active = 0; @@ -974,13 +1169,14 @@ /* * The silicon either has hard-wired endpoint configurations, or else * "dynamic fifo" sizing. The driver has support for both, though at this - * writing only the dynamic sizing is very well tested. Since we switched - * away from compile-time hardware parameters, we can no longer rely on - * dead code elimination to leave only the relevant one in the object file. + * writing only the dynamic sizing is very well tested. We use normal + * idioms to so both modes are compile-tested, but dead code elimination + * leaves only the relevant one in the object file. * * We don't currently use dynamic fifo setup capability to do anything * more than selecting one of a bunch of predefined configurations. */ + #if defined(CONFIG_USB_TUSB6010) || \ defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX) static ushort __initdata fifo_mode = 4; @@ -992,7 +1188,6 @@ module_param(fifo_mode, ushort, 0); MODULE_PARM_DESC(fifo_mode, "initial endpoint configuration"); - enum fifo_style { FIFO_RXTX, FIFO_TX, FIFO_RX } __attribute__ ((packed)); enum buf_mode { BUF_SINGLE, BUF_DOUBLE } __attribute__ ((packed)); @@ -1025,15 +1220,16 @@ { .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, }, { .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, }, }; - /* mode 2 - fits in 4KB */ static struct fifo_cfg __initdata mode_2_cfg[] = { { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, }, { .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, }, -{ .hw_ep_num = 3, .style = FIFO_RXTX, .maxpacket = 256, }, -{ .hw_ep_num = 4, .style = FIFO_RXTX, .maxpacket = 256, }, +{ .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, }, +{ .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, }, +{ .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, }, +{ .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 256, }, }; /* mode 3 - fits in 4KB */ @@ -1103,7 +1299,7 @@ c_size = size - 3; if (cfg->mode == BUF_DOUBLE) { if ((offset + (maxpacket << 1)) > - (1 << (musb->config->ram_bits + 2))) + (1 << (musb->config->ram_bits + 2))) return -EMSGSIZE; c_size |= MUSB_FIFOSZ_DPB; } else { @@ -1116,10 +1312,17 @@ #ifdef CONFIG_USB_MUSB_HDRC_HCD /* EP0 reserved endpoint for control, bidirectional; - * EP1 reserved for bulk, two unidirection halves. + * EP2 reserved for isoc, two unidirection halves. */ - if (hw_ep->epnum == 1) - musb->bulk_ep = hw_ep; +#ifdef CONFIG_MUSB_RESERVE_ISO_EP + if ((hw_ep->epnum == RESERVE_EP) && (cfg->style == FIFO_RX)) + musb->iso_ep = hw_ep; +#endif + +#ifdef CONFIG_MUSB_SCHEDULE_INTR_EP + if ((hw_ep->epnum == RESERVE_EP) && (cfg->style == FIFO_RX)) + musb->intr_ep = hw_ep; +#endif /* REVISIT error check: be sure ep0 can both rx and tx ... */ #endif switch (cfg->style) { @@ -1203,7 +1406,7 @@ /* assert(offset > 0) */ /* NOTE: for RTL versions >= 1.400 EPINFO and RAMINFO would - * be better than static musb->config->num_eps and DYN_FIFO_SIZE... + * be better than static musb->config->num_eps and DYN_FIFO_SIZE... */ for (i = 0; i < n; i++) { @@ -1223,18 +1426,10 @@ epn++; musb->nr_endpoints = max(epn, musb->nr_endpoints); } - printk(KERN_DEBUG "%s: %d/%d max ep, %d/%d memory\n", musb_driver_name, n + 1, musb->config->num_eps * 2 - 1, - offset, (1 << (musb->config->ram_bits + 2))); - -#ifdef CONFIG_USB_MUSB_HDRC_HCD - if (!musb->bulk_ep) { - pr_debug("%s: missing bulk\n", musb_driver_name); - return -EINVAL; - } -#endif + offset, (1 << (musb->config->ram_bits + 2))); return 0; } @@ -1250,6 +1445,10 @@ struct musb_hw_ep *hw_ep; void *mbase = musb->mregs; +#ifdef CONFIG_USB_MUSB_HDRC_HCD + u8 bulk_ep_found = 0; +#endif + DBG(2, "<== static silicon ep config\n"); /* FIXME pick up ep0 maxpacket size */ @@ -1290,19 +1489,11 @@ /* REVISIT: this algorithm is lazy, we should at least * try to pick a double buffered endpoint. */ - if (musb->bulk_ep) - continue; - musb->bulk_ep = hw_ep; + if (bulk_ep_found == 0) + bulk_ep_found = 1; #endif } -#ifdef CONFIG_USB_MUSB_HDRC_HCD - if (!musb->bulk_ep) { - pr_debug("%s: missing bulk\n", musb_driver_name); - return -EINVAL; - } -#endif - return 0; } @@ -1367,9 +1558,9 @@ (data >> 16) & 0xff, (data >> 24) & 0xff); /* FIXME ID2 and ID3 are unused */ data = musb_readl(mbase, 0x408); - printk(KERN_DEBUG "ID2=%lx\n", (long unsigned)data); + printk("ID2=%lx\n", (long unsigned)data); data = musb_readl(mbase, 0x40c); - printk(KERN_DEBUG "ID3=%lx\n", (long unsigned)data); + printk("ID3=%lx\n", (long unsigned)data); reg = musb_readb(mbase, 0x400); musb_type = ('M' == reg) ? MUSB_CONTROLLER_MHDRC : MUSB_CONTROLLER_HDRC; #else @@ -1445,6 +1636,9 @@ hw_ep->regs = MUSB_EP_OFFSET(i, 0) + mbase; #ifdef CONFIG_USB_MUSB_HDRC_HCD + /* init qh_list */ + INIT_LIST_HEAD(&hw_ep->in_list); + INIT_LIST_HEAD(&hw_ep->out_list); hw_ep->target_regs = MUSB_BUSCTL_OFFSET(i, 0) + mbase; hw_ep->rx_reinit = 1; hw_ep->tx_reinit = 1; @@ -1479,6 +1673,7 @@ #if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430) +//static irqreturn_t generic_interrupt(int irq, void *__hci, struct pt_regs *r) static irqreturn_t generic_interrupt(int irq, void *__hci) { unsigned long flags; @@ -1490,6 +1685,7 @@ 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); +// musb->int_regs = r; if (musb->int_usb || musb->int_tx || musb->int_rx) retval = musb_interrupt(musb); @@ -1542,7 +1738,9 @@ /* handle endpoint 0 first */ if (musb->int_tx & 1) { if (devctl & MUSB_DEVCTL_HM) + { retval |= musb_h_ep0_irq(musb); + } else retval |= musb_g_ep0_irq(musb); } @@ -1556,8 +1754,9 @@ /* REVISIT just retval = ep->rx_irq(...) */ retval = IRQ_HANDLED; if (devctl & MUSB_DEVCTL_HM) { - if (is_host_capable()) + if (is_host_capable()){ musb_host_rx(musb, ep_num); + } } else { if (is_peripheral_capable()) musb_g_rx(musb, ep_num); @@ -1598,7 +1797,9 @@ #ifndef CONFIG_MUSB_PIO_ONLY -static int __initdata use_dma = 1; +/* == 20110308 AVM/WK DMA Default changed to DMA off ==*/ +static int __initdata use_dma = 0; +//static int __initdata use_dma = 1; /* "modprobe ... use_dma=0" etc */ module_param(use_dma, bool, 0); @@ -1756,8 +1957,10 @@ #endif /* sysfs */ /* Only used to provide driver mode change events */ +//static void musb_irq_work(void *data) static void musb_irq_work(struct work_struct *data) { +// struct musb *musb = (struct musb *)data; struct musb *musb = container_of(data, struct musb, irq_work); static int old_state; @@ -1773,7 +1976,7 @@ static struct musb *__init allocate_instance(struct device *dev, - struct musb_hdrc_config *config, void __iomem *mbase) + struct musb_hdrc_config *config, void __iomem *mbase) { struct musb *musb; struct musb_hw_ep *ep; @@ -1787,9 +1990,8 @@ /* usbcore sets dev->driver_data to hcd, and sometimes uses that... */ musb = hcd_to_musb(hcd); - INIT_LIST_HEAD(&musb->control); - INIT_LIST_HEAD(&musb->in_bulk); - INIT_LIST_HEAD(&musb->out_bulk); + musb->hold = 0; + musb->hold_count = 0; hcd->uses_new_polling = 1; @@ -1806,7 +2008,6 @@ musb->ctrl_base = mbase; musb->nIrq = -ENODEV; musb->config = config; - BUG_ON(musb->config->num_eps > MUSB_C_NUM_EPS); for (epnum = 0, ep = musb->endpoints; epnum < musb->config->num_eps; epnum++, ep++) { @@ -1815,6 +2016,9 @@ ep->epnum = epnum; } +#ifdef CONFIG_USB_MUSB_OTG + otg_set_transceiver(&musb->xceiv); +#endif musb->controller = dev; return musb; } @@ -1839,7 +2043,10 @@ #endif if (musb->nIrq >= 0) { + if (musb->irq_wake) { disable_irq_wake(musb->nIrq); + musb->irq_wake = 0; + } free_irq(musb->nIrq, musb); } if (is_dma_capable() && musb->dma_controller) { @@ -1858,6 +2065,9 @@ clk_put(musb->clock); } + tasklet_disable(&musb->fifo_check); + tasklet_kill(&musb->fifo_check); + #ifdef CONFIG_USB_MUSB_OTG put_device(musb->xceiv.dev); #endif @@ -1914,7 +2124,6 @@ dev_err(dev, "incompatible Kconfig role setting\n"); return -EINVAL; } - /* allocate */ musb = allocate_instance(dev, plat->config, ctrl); if (!musb) @@ -1981,6 +2190,7 @@ goto fail2; /* Init IRQ workqueue before request_irq */ +// INIT_WORK(&musb->irq_work, musb_irq_work, musb); INIT_WORK(&musb->irq_work, musb_irq_work); /* attach to the IRQ */ @@ -1991,8 +2201,17 @@ } musb->nIrq = nIrq; /* FIXME this handles wakeup irqs wrong */ - if (enable_irq_wake(nIrq) == 0) +/* AVM/WK patch from OMAP */ + if (enable_irq_wake(nIrq) == 0) { + musb->irq_wake = 1; device_init_wakeup(dev, 1); + } + + /* Initialize the tasklet to check for FIFO status on completion of + * a request + */ + tasklet_init(&musb->fifo_check, musb_fifo_check_tasklet, + (unsigned long)musb); pr_info("%s: USB %s mode controller at %p using %s, IRQ %d\n", musb_driver_name, @@ -2006,7 +2225,6 @@ (is_dma_capable() && musb->dma_controller) ? "DMA" : "PIO", musb->nIrq); - #ifdef CONFIG_USB_MUSB_HDRC_HCD /* host side needs more setup, except for no-host modes */ if (musb->board_mode != MUSB_PERIPHERAL) { @@ -2029,8 +2247,6 @@ musb->xceiv.state = OTG_STATE_A_IDLE; status = usb_add_hcd(musb_to_hcd(musb), -1, 0); - if (status) - goto fail; DBG(1, "%s mode, status %d, devctl %02x %c\n", "HOST", status, @@ -2045,8 +2261,6 @@ musb->xceiv.state = OTG_STATE_B_IDLE; status = musb_gadget_setup(musb); - if (status) - goto fail; DBG(1, "%s mode, status %d, dev%02x\n", is_otg_enabled(musb) ? "OTG" : "PERIPHERAL", @@ -2055,6 +2269,41 @@ } + if (status == 0) + musb_debug_create("driver/musb_hdrc", musb); + else { +fail: + if (musb->clock) + clk_put(musb->clock); + device_init_wakeup(dev, 0); + musb_free(musb); + return status; + } + +#if defined(CONFIG_ARM_AVALANCHE_PPD) && defined(CONFIG_USB_PPD_SUPPORT) +{ + int retVal; +#define TI_PP_PID_TYPE_USBRNDIS 3 +#define TI_PP_PID_TYPE_USBCDC 4 + /* Install usb PID */ + pid_range_usb.type = TI_PP_PID_TYPE_USBRNDIS ; + pid_range_usb.port_num = CPPI41_SRCPORT_USBEP0; + pid_range_usb.count = PP_USB_PID_COUNT; + pid_range_usb.base_index = PP_USB_PID_BASE; + +#ifdef CONFIG_TI_PACKET_PROCESSOR + retVal = ti_ppm_config_pid_range (&pid_range_usb); +#else + retVal = ti_ppd_config_pid_range (&pid_range_usb); +#endif + if( retVal < 0 ) + { + printk("%s: config_pid_range failed with error code %d.\n", + __FUNCTION__, retVal); + } +} +#endif /* CONFIG_ARM_AVALANCHE_PPD */ + #ifdef CONFIG_SYSFS status = device_create_file(dev, &dev_attr_mode); status = device_create_file(dev, &dev_attr_vbus); @@ -2063,31 +2312,12 @@ #endif /* CONFIG_USB_GADGET_MUSB_HDRC */ status = 0; #endif - if (status) - goto fail2; - return 0; + return status; fail2: -#ifdef CONFIG_SYSFS - device_remove_file(musb->controller, &dev_attr_mode); - device_remove_file(musb->controller, &dev_attr_vbus); -#ifdef CONFIG_USB_MUSB_OTG - device_remove_file(musb->controller, &dev_attr_srp); -#endif -#endif musb_platform_exit(musb); -fail: - dev_err(musb->controller, - "musb_init_controller failed with status %d\n", status); - - if (musb->clock) - clk_put(musb->clock); - device_init_wakeup(dev, 0); - musb_free(musb); - - return status; - + goto fail; } /*-------------------------------------------------------------------------*/ @@ -2102,21 +2332,38 @@ static int __init musb_probe(struct platform_device *pdev) { - struct device *dev = &pdev->dev; - int irq = platform_get_irq(pdev, 0); + struct device *dev;// = &pdev->dev; + int irq;// = platform_get_irq(pdev, 0); struct resource *iomem; +#ifdef CONFIG_ARCH_PUMA5 + struct resource *gpio; +#endif void __iomem *base; + dev = &pdev->dev; + irq = platform_get_irq(pdev, 0); + iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!iomem || irq == 0) return -ENODEV; +/* AVM/WK Patch */ +#ifdef CONFIG_ARCH_PUMA5 + gpio = platform_get_resource(pdev, IORESOURCE_IO, 0); + if (!gpio) + return -ENODEV; + + if(request_resource(&gpio_resource, gpio)) { + return -ENODEV; + } +#endif base = ioremap(iomem->start, iomem->end - iomem->start + 1); + base = (void *)iomem->start; + if (!base) { dev_err(dev, "ioremap failed\n"); return -ENOMEM; } - #ifndef CONFIG_MUSB_PIO_ONLY /* clobbered by use_dma=n */ orig_dma_mask = dev->dma_mask; @@ -2127,20 +2374,30 @@ static int __devexit musb_remove(struct platform_device *pdev) { struct musb *musb = dev_to_musb(&pdev->dev); - void __iomem *ctrl_base = musb->ctrl_base; + /* void __iomem *ctrl_base = musb->ctrl_base;*/ + //unsigned long flags; /* this gets called on rmmod. * - Host mode: host may still be active * - Peripheral mode: peripheral is deactivated (or never-activated) * - OTG mode: both roles are deactivated (or never-activated) */ +#ifndef CONFIG_PM musb_shutdown(pdev); +#else + spin_lock_irqsave(&musb->lock, flags); + musb_platform_disable(musb); + musb_generic_disable(musb); + spin_unlock_irqrestore(&musb->lock, flags); +#endif + + musb_debug_delete("driver/musb_hdrc", musb); #ifdef CONFIG_USB_MUSB_HDRC_HCD if (musb->board_mode == MUSB_HOST) usb_remove_hcd(musb_to_hcd(musb)); #endif musb_free(musb); - iounmap(ctrl_base); +// iounmap(ctrl_base); device_init_wakeup(&pdev->dev, 0); #ifndef CONFIG_MUSB_PIO_ONLY pdev->dev.dma_mask = orig_dma_mask; @@ -2148,6 +2405,23 @@ return 0; } +void musb_pullup(struct musb *musb, int is_on) +{ + u8 power; + + power = musb_readb(musb->mregs, MUSB_DEVCTL); + if (is_on) + power |= MUSB_POWER_SOFTCONN; + else + power &= ~MUSB_POWER_SOFTCONN; + + /* FIXME if on, HdrcStart; if off, HdrcStop */ + +/* DBG(3, "gadget %s D+ pullup %s\n", + musb->pGadgetDriver->function, is_on ? "on" : "off"); */ + musb_writeb(musb->mregs, MUSB_DEVCTL, power); +} + #ifdef CONFIG_PM static int musb_suspend(struct platform_device *pdev, pm_message_t message) @@ -2155,8 +2429,10 @@ unsigned long flags; struct musb *musb = dev_to_musb(&pdev->dev); +#ifndef CONFIG_ARCH_PUMA5 if (!musb->clock) return 0; +#endif spin_lock_irqsave(&musb->lock, flags); @@ -2164,16 +2440,22 @@ /* FIXME force disconnect unless we know USB will wake * the system up quickly enough to respond ... */ +#ifdef CONFIG_ARCH_PUMA5 + puma5_usb_power_down(musb); + printk("suspend: usb power down\n"); +#endif } else if (is_host_active(musb)) { /* we know all the children are suspended; sometimes * they will even be wakeup-enabled. */ } +#ifndef CONFIG_ARCH_PUMA5 if (musb->set_clock) musb->set_clock(musb->clock, 0); else clk_disable(musb->clock); +#endif spin_unlock_irqrestore(&musb->lock, flags); return 0; } @@ -2183,20 +2465,32 @@ unsigned long flags; struct musb *musb = dev_to_musb(&pdev->dev); +#ifndef CONFIG_ARCH_PUMA5 if (!musb->clock) return 0; +#endif spin_lock_irqsave(&musb->lock, flags); +#ifndef CONFIG_ARCH_PUMA5 if (musb->set_clock) musb->set_clock(musb->clock, 1); else clk_enable(musb->clock); +#endif /* for static cmos like DaVinci, register values were preserved * unless for some reason the whole soc powered down and we're * not treating that as a whole-system restart (e.g. swsusp) */ + + if (is_peripheral_active(musb)) { +#ifdef CONFIG_ARCH_PUMA5 + printk("resume: usb power up\n"); + puma5_usb_power_up(musb); +#endif + } + spin_unlock_irqrestore(&musb->lock, flags); return 0; } @@ -2212,6 +2506,7 @@ .bus = &platform_bus_type, .owner = THIS_MODULE, }, + .probe = musb_probe, .remove = __devexit_p(musb_remove), .shutdown = musb_shutdown, .suspend = musb_suspend, @@ -2219,9 +2514,15 @@ }; /*-------------------------------------------------------------------------*/ +#ifdef CONFIG_ARCH_PUMA5 +extern struct platform_device usb_device; + static void musb_release (struct device *dev) + {} +#endif static int __init musb_init(void) { + int retval; #ifdef CONFIG_USB_MUSB_HDRC_HCD if (usb_disabled()) return 0; @@ -2239,6 +2540,7 @@ #else "?dma?" #endif + ", use_dma=%u" ", " #ifdef CONFIG_USB_MUSB_OTG "otg (peripheral+host)" @@ -2248,17 +2550,25 @@ "host" #endif ", debug=%d\n", - musb_driver_name, musb_debug); - return platform_driver_probe(&musb_driver, musb_probe); -} + musb_driver_name, + use_dma, + debug); -/* make us init after usbcore and before usb - * gadget and host-side drivers start to register - */ -subsys_initcall(musb_init); +#ifdef CONFIG_ARCH_PUMA5 + platform_device_register(&usb_device); + usb_device.dev.release = musb_release; +#endif + + retval = platform_driver_register(&musb_driver); + return retval; +} +module_init(musb_init); static void __exit musb_cleanup(void) { +#ifdef CONFIG_ARCH_PUMA5 + platform_device_unregister(&usb_device); +#endif platform_driver_unregister(&musb_driver); } module_exit(musb_cleanup);