diff options
Diffstat (limited to 'drivers/usb/musb')
-rw-r--r-- | drivers/usb/musb/Kconfig | 4 | ||||
-rw-r--r-- | drivers/usb/musb/cppi_dma.h | 4 | ||||
-rw-r--r-- | drivers/usb/musb/davinci.c | 20 | ||||
-rw-r--r-- | drivers/usb/musb/musb_core.c | 47 | ||||
-rw-r--r-- | drivers/usb/musb/musb_debug.h | 4 | ||||
-rw-r--r-- | drivers/usb/musb/musb_gadget_ep0.c | 24 | ||||
-rw-r--r-- | drivers/usb/musb/musb_host.c | 178 | ||||
-rw-r--r-- | drivers/usb/musb/musb_host.h | 1 | ||||
-rw-r--r-- | drivers/usb/musb/musb_io.h | 4 | ||||
-rw-r--r-- | drivers/usb/musb/musbhsdma.c | 306 | ||||
-rw-r--r-- | drivers/usb/musb/omap2430.c | 2 | ||||
-rw-r--r-- | drivers/usb/musb/tusb6010.c | 2 |
12 files changed, 326 insertions, 270 deletions
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 58b2b8fc943..4b9542bbb35 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -33,10 +33,6 @@ config USB_MUSB_SOC default y if ARCH_DAVINCI default y if ARCH_OMAP2430 default y if ARCH_OMAP34XX - help - Use a static <asm/arch/hdrc_cnf.h> file to describe how the - controller is configured (endpoints, mechanisms, etc) on the - current iteration of a given system-on-chip. comment "DaVinci 644x USB support" depends on USB_MUSB_HDRC && ARCH_DAVINCI diff --git a/drivers/usb/musb/cppi_dma.h b/drivers/usb/musb/cppi_dma.h index fc5216b5d2c..729b4071787 100644 --- a/drivers/usb/musb/cppi_dma.h +++ b/drivers/usb/musb/cppi_dma.h @@ -119,8 +119,8 @@ struct cppi { void __iomem *mregs; /* Mentor regs */ void __iomem *tibase; /* TI/CPPI regs */ - struct cppi_channel tx[MUSB_C_NUM_EPT - 1]; - struct cppi_channel rx[MUSB_C_NUM_EPR - 1]; + struct cppi_channel tx[4]; + struct cppi_channel rx[4]; struct dma_pool *pool; diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 75baf181a8c..dfb3bcbe00f 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -30,6 +30,7 @@ #include <linux/delay.h> #include <linux/clk.h> #include <linux/io.h> +#include <linux/gpio.h> #include <asm/arch/hardware.h> #include <asm/arch/memory.h> @@ -39,7 +40,7 @@ #include "musb_core.h" #ifdef CONFIG_MACH_DAVINCI_EVM -#include <asm/arch/i2c-client.h> +#define GPIO_nVBUS_DRV 87 #endif #include "davinci.h" @@ -138,7 +139,6 @@ static int vbus_state = -1; /* VBUS SWITCHING IS BOARD-SPECIFIC */ #ifdef CONFIG_MACH_DAVINCI_EVM -#ifndef CONFIG_MACH_DAVINCI_EVM_OTG /* I2C operations are always synchronous, and require a task context. * With unloaded systems, using the shared workqueue seems to suffice @@ -146,12 +146,11 @@ static int vbus_state = -1; */ static void evm_deferred_drvvbus(struct work_struct *ignored) { - davinci_i2c_expander_op(0x3a, USB_DRVVBUS, vbus_state); + gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); vbus_state = !vbus_state; } static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); -#endif /* modified board */ #endif /* EVM */ static void davinci_source_power(struct musb *musb, int is_on, int immediate) @@ -165,21 +164,10 @@ static void davinci_source_power(struct musb *musb, int is_on, int immediate) #ifdef CONFIG_MACH_DAVINCI_EVM if (machine_is_davinci_evm()) { -#ifdef CONFIG_MACH_DAVINCI_EVM_OTG - /* modified EVM board switching VBUS with GPIO(6) not I2C - * NOTE: PINMUX0.RGB888 (bit23) must be clear - */ - if (is_on) - gpio_set(GPIO(6)); - else - gpio_clear(GPIO(6)); - immediate = 1; -#else if (immediate) - davinci_i2c_expander_op(0x3a, USB_DRVVBUS, !is_on); + gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); else schedule_work(&evm_vbus_work); -#endif } #endif if (immediate) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 128e949db47..5280dba9b1f 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -82,9 +82,9 @@ /* * This gets many kinds of configuration information: * - Kconfig for everything user-configurable - * - <asm/arch/hdrc_cnf.h> 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. */ @@ -114,8 +114,8 @@ -unsigned debug; -module_param(debug, uint, S_IRUGO | S_IWUSR); +unsigned musb_debug; +module_param(musb_debug, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug message level. Default = 0"); #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia" @@ -974,9 +974,9 @@ static void musb_shutdown(struct platform_device *pdev) /* * 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. We use normal - * idioms to so both modes are compile-tested, but dead code elimination - * leaves only the relevant one in the object file. + * 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. * * We don't currently use dynamic fifo setup capability to do anything * more than selecting one of a bunch of predefined configurations. @@ -1806,6 +1806,7 @@ allocate_instance(struct device *dev, 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++) { @@ -2054,15 +2055,6 @@ bad_config: } - return 0; - -fail: - if (musb->clock) - clk_put(musb->clock); - device_init_wakeup(dev, 0); - musb_free(musb); - return status; - #ifdef CONFIG_SYSFS status = device_create_file(dev, &dev_attr_mode); status = device_create_file(dev, &dev_attr_vbus); @@ -2071,12 +2063,31 @@ fail: #endif /* CONFIG_USB_GADGET_MUSB_HDRC */ status = 0; #endif + if (status) + goto fail2; - return status; + return 0; 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); - goto fail; +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; + } /*-------------------------------------------------------------------------*/ @@ -2237,7 +2248,7 @@ static int __init musb_init(void) "host" #endif ", debug=%d\n", - musb_driver_name, debug); + musb_driver_name, musb_debug); return platform_driver_probe(&musb_driver, musb_probe); } diff --git a/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h index 4d2794441b1..9fc1db44c72 100644 --- a/drivers/usb/musb/musb_debug.h +++ b/drivers/usb/musb/musb_debug.h @@ -48,11 +48,11 @@ __func__, __LINE__ , ## args); \ } } while (0) -extern unsigned debug; +extern unsigned musb_debug; static inline int _dbg_level(unsigned l) { - return debug >= l; + return musb_debug >= l; } #define DBG(level, fmt, args...) xprintk(level, KERN_DEBUG, fmt, ## args) diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index a57652fff39..3f5e30ddfa2 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -437,7 +437,7 @@ static void ep0_rxstate(struct musb *musb) { void __iomem *regs = musb->control_ep->regs; struct usb_request *req; - u16 tmp; + u16 count, csr; req = next_ep0_request(musb); @@ -449,35 +449,35 @@ static void ep0_rxstate(struct musb *musb) unsigned len = req->length - req->actual; /* read the buffer */ - tmp = musb_readb(regs, MUSB_COUNT0); - if (tmp > len) { + count = musb_readb(regs, MUSB_COUNT0); + if (count > len) { req->status = -EOVERFLOW; - tmp = len; + count = len; } - musb_read_fifo(&musb->endpoints[0], tmp, buf); - req->actual += tmp; - tmp = MUSB_CSR0_P_SVDRXPKTRDY; - if (tmp < 64 || req->actual == req->length) { + musb_read_fifo(&musb->endpoints[0], count, buf); + req->actual += count; + csr = MUSB_CSR0_P_SVDRXPKTRDY; + if (count < 64 || req->actual == req->length) { musb->ep0_state = MUSB_EP0_STAGE_STATUSIN; - tmp |= MUSB_CSR0_P_DATAEND; + csr |= MUSB_CSR0_P_DATAEND; } else req = NULL; } else - tmp = MUSB_CSR0_P_SVDRXPKTRDY | MUSB_CSR0_P_SENDSTALL; + csr = MUSB_CSR0_P_SVDRXPKTRDY | MUSB_CSR0_P_SENDSTALL; /* Completion handler may choose to stall, e.g. because the * message just received holds invalid data. */ if (req) { - musb->ackpend = tmp; + musb->ackpend = csr; musb_g_ep0_giveback(musb, req); if (!musb->ackpend) return; musb->ackpend = 0; } musb_ep_select(musb->mregs, 0); - musb_writew(regs, MUSB_CSR0, tmp); + musb_writew(regs, MUSB_CSR0, csr); } /* diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 8b4be012669..cc64462d4c4 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -108,7 +108,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum, /* * Clear TX fifo. Needed to avoid BABBLE errors. */ -static inline void musb_h_tx_flush_fifo(struct musb_hw_ep *ep) +static void musb_h_tx_flush_fifo(struct musb_hw_ep *ep) { void __iomem *epio = ep->regs; u16 csr; @@ -291,6 +291,7 @@ __acquires(musb->lock) urb->actual_length, urb->transfer_buffer_length ); + usb_hcd_unlink_urb_from_ep(musb_to_hcd(musb), urb); spin_unlock(&musb->lock); usb_hcd_giveback_urb(musb_to_hcd(musb), urb, status); spin_lock(&musb->lock); @@ -353,8 +354,6 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) break; } - usb_hcd_unlink_urb_from_ep(musb_to_hcd(musb), urb); - qh->is_ready = 0; __musb_giveback(musb, urb, status); qh->is_ready = ready; @@ -379,6 +378,19 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) switch (qh->type) { + case USB_ENDPOINT_XFER_CONTROL: + case USB_ENDPOINT_XFER_BULK: + /* fifo policy for these lists, except that NAKing + * should rotate a qh to the end (for fairness). + */ + if (qh->mux == 1) { + head = qh->ring.prev; + list_del(&qh->ring); + kfree(qh); + qh = first_qh(head); + break; + } + case USB_ENDPOINT_XFER_ISOC: case USB_ENDPOINT_XFER_INT: /* this is where periodic bandwidth should be @@ -389,17 +401,6 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) kfree(qh); qh = NULL; break; - - case USB_ENDPOINT_XFER_CONTROL: - case USB_ENDPOINT_XFER_BULK: - /* fifo policy for these lists, except that NAKing - * should rotate a qh to the end (for fairness). - */ - head = qh->ring.prev; - list_del(&qh->ring); - kfree(qh); - qh = first_qh(head); - break; } } return qh; @@ -436,7 +437,7 @@ musb_advance_schedule(struct musb *musb, struct urb *urb, } } -static inline u16 musb_h_flush_rxfifo(struct musb_hw_ep *hw_ep, u16 csr) +static u16 musb_h_flush_rxfifo(struct musb_hw_ep *hw_ep, u16 csr) { /* we don't want fifo to fill itself again; * ignore dma (various models), @@ -1005,7 +1006,7 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb) /* * Handle default endpoint interrupt as host. Only called in IRQ time - * from the LinuxIsr() interrupt service routine. + * from musb_interrupt(). * * called with controller irqlocked */ @@ -1508,10 +1509,29 @@ void musb_host_rx(struct musb *musb, u8 epnum) musb_writew(hw_ep->regs, MUSB_RXCSR, val); #ifdef CONFIG_USB_INVENTRA_DMA + if (usb_pipeisoc(pipe)) { + struct usb_iso_packet_descriptor *d; + + d = urb->iso_frame_desc + qh->iso_idx; + d->actual_length = xfer_len; + + /* even if there was an error, we did the dma + * for iso_frame_desc->length + */ + if (d->status != EILSEQ && d->status != -EOVERFLOW) + d->status = 0; + + if (++qh->iso_idx >= urb->number_of_packets) + done = true; + else + done = false; + + } else { /* done if urb buffer is full or short packet is recd */ done = (urb->actual_length + xfer_len >= urb->transfer_buffer_length || dma->actual_len < qh->maxpacket); + } /* send IN token for next packet, without AUTOREQ */ if (!done) { @@ -1548,7 +1568,8 @@ void musb_host_rx(struct musb *musb, u8 epnum) if (dma) { struct dma_controller *c; u16 rx_count; - int ret; + int ret, length; + dma_addr_t buf; rx_count = musb_readw(epio, MUSB_RXCOUNT); @@ -1561,6 +1582,35 @@ void musb_host_rx(struct musb *musb, u8 epnum) c = musb->dma_controller; + if (usb_pipeisoc(pipe)) { + int status = 0; + struct usb_iso_packet_descriptor *d; + + d = urb->iso_frame_desc + qh->iso_idx; + + if (iso_err) { + status = -EILSEQ; + urb->error_count++; + } + if (rx_count > d->length) { + if (status == 0) { + status = -EOVERFLOW; + urb->error_count++; + } + DBG(2, "** OVERFLOW %d into %d\n",\ + rx_count, d->length); + + length = d->length; + } else + length = rx_count; + d->status = status; + buf = urb->transfer_dma + d->offset; + } else { + length = rx_count; + buf = urb->transfer_dma + + urb->actual_length; + } + dma->desired_mode = 0; #ifdef USE_MODE1 /* because of the issue below, mode 1 will @@ -1572,6 +1622,12 @@ void musb_host_rx(struct musb *musb, u8 epnum) urb->actual_length) > qh->maxpacket) dma->desired_mode = 1; + if (rx_count < hw_ep->max_packet_sz_rx) { + length = rx_count; + dma->bDesiredMode = 0; + } else { + length = urb->transfer_buffer_length; + } #endif /* Disadvantage of using mode 1: @@ -1609,12 +1665,7 @@ void musb_host_rx(struct musb *musb, u8 epnum) */ ret = c->channel_program( dma, qh->maxpacket, - dma->desired_mode, - urb->transfer_dma - + urb->actual_length, - (dma->desired_mode == 0) - ? rx_count - : urb->transfer_buffer_length); + dma->desired_mode, buf, length); if (!ret) { c->channel_release(dma); @@ -1632,19 +1683,6 @@ void musb_host_rx(struct musb *musb, u8 epnum) } } - if (dma && usb_pipeisoc(pipe)) { - struct usb_iso_packet_descriptor *d; - int iso_stat = status; - - d = urb->iso_frame_desc + qh->iso_idx; - d->actual_length += xfer_len; - if (iso_err) { - iso_stat = -EILSEQ; - urb->error_count++; - } - d->status = iso_stat; - } - finish: urb->actual_length += xfer_len; qh->offset += xfer_len; @@ -1672,22 +1710,9 @@ static int musb_schedule( struct list_head *head = NULL; /* use fixed hardware for control and bulk */ - switch (qh->type) { - case USB_ENDPOINT_XFER_CONTROL: + if (qh->type == USB_ENDPOINT_XFER_CONTROL) { head = &musb->control; hw_ep = musb->control_ep; - break; - case USB_ENDPOINT_XFER_BULK: - hw_ep = musb->bulk_ep; - if (is_in) - head = &musb->in_bulk; - else - head = &musb->out_bulk; - break; - } - if (head) { - idle = list_empty(head); - list_add_tail(&qh->ring, head); goto success; } @@ -1726,19 +1751,34 @@ static int musb_schedule( else diff = hw_ep->max_packet_sz_tx - qh->maxpacket; - if (diff > 0 && best_diff > diff) { + if (diff >= 0 && best_diff > diff) { best_diff = diff; best_end = epnum; } } - if (best_end < 0) + /* use bulk reserved ep1 if no other ep is free */ + if (best_end < 0 && qh->type == USB_ENDPOINT_XFER_BULK) { + hw_ep = musb->bulk_ep; + if (is_in) + head = &musb->in_bulk; + else + head = &musb->out_bulk; + goto success; + } else if (best_end < 0) { return -ENOSPC; + } idle = 1; + qh->mux = 0; hw_ep = musb->endpoints + best_end; musb->periodic[best_end] = qh; DBG(4, "qh %p periodic slot %d\n", qh, best_end); success: + if (head) { + idle = list_empty(head); + list_add_tail(&qh->ring, head); + qh->mux = 1; + } qh->hw_ep = hw_ep; qh->hep->hcpriv = qh; if (idle) @@ -1791,7 +1831,9 @@ static int musb_urb_enqueue( */ qh = kzalloc(sizeof *qh, mem_flags); if (!qh) { + spin_lock_irqsave(&musb->lock, flags); usb_hcd_unlink_urb_from_ep(hcd, urb); + spin_unlock_irqrestore(&musb->lock, flags); return -ENOMEM; } @@ -1873,7 +1915,11 @@ static int musb_urb_enqueue( /* set up tt info if needed */ if (urb->dev->tt) { qh->h_port_reg = (u8) urb->dev->ttport; - qh->h_addr_reg |= 0x80; + if (urb->dev->tt->hub) + qh->h_addr_reg = + (u8) urb->dev->tt->hub->devnum; + if (urb->dev->tt->multi) + qh->h_addr_reg |= 0x80; } } } @@ -1903,7 +1949,9 @@ static int musb_urb_enqueue( done: if (ret != 0) { + spin_lock_irqsave(&musb->lock, flags); usb_hcd_unlink_urb_from_ep(hcd, urb); + spin_unlock_irqrestore(&musb->lock, flags); kfree(qh); } return ret; @@ -2008,11 +2056,13 @@ static int musb_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) sched = &musb->control; break; case USB_ENDPOINT_XFER_BULK: - if (usb_pipein(urb->pipe)) - sched = &musb->in_bulk; - else - sched = &musb->out_bulk; - break; + if (qh->mux == 1) { + if (usb_pipein(urb->pipe)) + sched = &musb->in_bulk; + else + sched = &musb->out_bulk; + break; + } default: /* REVISIT when we get a schedule tree, periodic * transfers won't always be at the head of a @@ -2060,11 +2110,13 @@ musb_h_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) sched = &musb->control; break; case USB_ENDPOINT_XFER_BULK: - if (is_in) - sched = &musb->in_bulk; - else - sched = &musb->out_bulk; - break; + if (qh->mux == 1) { + if (is_in) + sched = &musb->in_bulk; + else + sched = &musb->out_bulk; + break; + } default: /* REVISIT when we get a schedule tree, periodic transfers * won't always be at the head of a singleton queue... diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h index 77bcdb9d5b3..0b7fbcd2196 100644 --- a/drivers/usb/musb/musb_host.h +++ b/drivers/usb/musb/musb_host.h @@ -53,6 +53,7 @@ struct musb_qh { struct list_head ring; /* of musb_qh */ /* struct musb_qh *next; */ /* for periodic tree */ + u8 mux; /* qh multiplexed to hw_ep */ unsigned offset; /* in urb->transfer_buffer */ unsigned segsize; /* current xfer fragment */ diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h index 6bbedae83af..223f0a51409 100644 --- a/drivers/usb/musb/musb_io.h +++ b/drivers/usb/musb/musb_io.h @@ -37,7 +37,9 @@ #include <linux/io.h> -#ifndef CONFIG_ARM +#if !defined(CONFIG_ARM) && !defined(CONFIG_SUPERH) \ + && !defined(CONFIG_AVR32) && !defined(CONFIG_PPC32) \ + && !defined(CONFIG_PPC64) static inline void readsl(const void __iomem *addr, void *buf, int len) { insl((unsigned long)addr, buf, len); } static inline void readsw(const void __iomem *addr, void *buf, int len) diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 9ba8fb7fcd2..8c734ef2c1e 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -45,8 +45,8 @@ #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_HSDMA_CHANNEL_OFFSET(_bchannel, _offset) \ + (MUSB_HSDMA_BASE + (_bchannel << 4) + _offset) /* control register (16-bit): */ #define MUSB_HSDMA_ENABLE_SHIFT 0 @@ -67,23 +67,23 @@ struct musb_dma_controller; struct musb_dma_channel { - struct dma_channel Channel; + struct dma_channel channel; struct musb_dma_controller *controller; - u32 dwStartAddress; + u32 start_addr; u32 len; - u16 wMaxPacketSize; - u8 bIndex; + u16 max_packet_sz; + u8 idx; u8 epnum; u8 transmit; }; struct musb_dma_controller { - struct dma_controller Controller; - struct musb_dma_channel aChannel[MUSB_HSDMA_CHANNELS]; - void *pDmaPrivate; - void __iomem *pCoreBase; - u8 bChannelCount; - u8 bmUsedChannels; + struct dma_controller controller; + struct musb_dma_channel channel[MUSB_HSDMA_CHANNELS]; + void *private_data; + void __iomem *base; + u8 channel_count; + u8 used_channels; u8 irq; }; @@ -93,91 +93,91 @@ static int dma_controller_start(struct dma_controller *c) return 0; } -static void dma_channel_release(struct dma_channel *pChannel); +static void dma_channel_release(struct dma_channel *channel); static int dma_controller_stop(struct dma_controller *c) { - struct musb_dma_controller *controller = - container_of(c, struct musb_dma_controller, Controller); - struct musb *musb = (struct musb *) controller->pDmaPrivate; - struct dma_channel *pChannel; - u8 bBit; + struct musb_dma_controller *controller = container_of(c, + struct musb_dma_controller, controller); + struct musb *musb = controller->private_data; + struct dma_channel *channel; + u8 bit; - if (controller->bmUsedChannels != 0) { + if (controller->used_channels != 0) { dev_err(musb->controller, "Stopping DMA controller while channel active\n"); - for (bBit = 0; bBit < MUSB_HSDMA_CHANNELS; bBit++) { - if (controller->bmUsedChannels & (1 << bBit)) { - pChannel = &controller->aChannel[bBit].Channel; - dma_channel_release(pChannel); + for (bit = 0; bit < MUSB_HSDMA_CHANNELS; bit++) { + if (controller->used_channels & (1 << bit)) { + channel = &controller->channel[bit].channel; + dma_channel_release(channel); - if (!controller->bmUsedChannels) + if (!controller->used_channels) break; } } } + return 0; } static struct dma_channel *dma_channel_allocate(struct dma_controller *c, struct musb_hw_ep *hw_ep, u8 transmit) { - u8 bBit; - struct dma_channel *pChannel = NULL; - struct musb_dma_channel *pImplChannel = NULL; - struct musb_dma_controller *controller = - container_of(c, struct musb_dma_controller, Controller); - - for (bBit = 0; bBit < MUSB_HSDMA_CHANNELS; bBit++) { - if (!(controller->bmUsedChannels & (1 << bBit))) { - controller->bmUsedChannels |= (1 << bBit); - pImplChannel = &(controller->aChannel[bBit]); - pImplChannel->controller = controller; - pImplChannel->bIndex = bBit; - pImplChannel->epnum = hw_ep->epnum; - pImplChannel->transmit = transmit; - pChannel = &(pImplChannel->Channel); - pChannel->private_data = pImplChannel; - pChannel->status = MUSB_DMA_STATUS_FREE; - pChannel->max_len = 0x10000; + struct musb_dma_controller *controller = container_of(c, + struct musb_dma_controller, controller); + struct musb_dma_channel *musb_channel = NULL; + struct dma_channel *channel = NULL; + u8 bit; + + for (bit = 0; bit < MUSB_HSDMA_CHANNELS; bit++) { + if (!(controller->used_channels & (1 << bit))) { + controller->used_channels |= (1 << bit); + musb_channel = &(controller->channel[bit]); + musb_channel->controller = controller; + musb_channel->idx = bit; + musb_channel->epnum = hw_ep->epnum; + musb_channel->transmit = transmit; + channel = &(musb_channel->channel); + channel->private_data = musb_channel; + channel->status = MUSB_DMA_STATUS_FREE; + channel->max_len = 0x10000; /* Tx => mode 1; Rx => mode 0 */ - pChannel->desired_mode = transmit; - pChannel->actual_len = 0; + channel->desired_mode = transmit; + channel->actual_len = 0; break; } } - return pChannel; + + return channel; } -static void dma_channel_release(struct dma_channel *pChannel) +static void dma_channel_release(struct dma_channel *channel) { - struct musb_dma_channel *pImplChannel = - (struct musb_dma_channel *) pChannel->private_data; + struct musb_dma_channel *musb_channel = channel->private_data; - pChannel->actual_len = 0; - pImplChannel->dwStartAddress = 0; - pImplChannel->len = 0; + channel->actual_len = 0; + musb_channel->start_addr = 0; + musb_channel->len = 0; - pImplChannel->controller->bmUsedChannels &= - ~(1 << pImplChannel->bIndex); + musb_channel->controller->used_channels &= + ~(1 << musb_channel->idx); - pChannel->status = MUSB_DMA_STATUS_UNKNOWN; + channel->status = MUSB_DMA_STATUS_UNKNOWN; } -static void configure_channel(struct dma_channel *pChannel, +static void configure_channel(struct dma_channel *channel, u16 packet_sz, u8 mode, dma_addr_t dma_addr, u32 len) { - struct musb_dma_channel *pImplChannel = - (struct musb_dma_channel *) pChannel->private_data; - struct musb_dma_controller *controller = pImplChannel->controller; - void __iomem *mbase = controller->pCoreBase; - u8 bChannel = pImplChannel->bIndex; + struct musb_dma_channel *musb_channel = channel->private_data; + struct musb_dma_controller *controller = musb_channel->controller; + void __iomem *mbase = controller->base; + u8 bchannel = musb_channel->idx; u16 csr = 0; DBG(4, "%p, pkt_sz %d, addr 0x%x, len %d, mode %d\n", - pChannel, packet_sz, dma_addr, len, mode); + channel, packet_sz, dma_addr, len, mode); if (mode) { csr |= 1 << MUSB_HSDMA_MODE1_SHIFT; @@ -195,180 +195,183 @@ static void configure_channel(struct dma_channel *pChannel, } } - csr |= (pImplChannel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT) + csr |= (musb_channel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT) | (1 << MUSB_HSDMA_ENABLE_SHIFT) | (1 << MUSB_HSDMA_IRQENABLE_SHIFT) - | (pImplChannel->transmit + | (musb_channel->transmit ? (1 << MUSB_HSDMA_TRANSMIT_SHIFT) : 0); /* address/count */ musb_writel(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_ADDRESS), + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), dma_addr); musb_writel(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_COUNT), + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), len); /* control (this should start things) */ musb_writew(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_CONTROL), + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL), csr); } -static int dma_channel_program(struct dma_channel *pChannel, +static int dma_channel_program(struct dma_channel *channel, u16 packet_sz, u8 mode, dma_addr_t dma_addr, u32 len) { - struct musb_dma_channel *pImplChannel = - (struct musb_dma_channel *) pChannel->private_data; + struct musb_dma_channel *musb_channel = channel->private_data; DBG(2, "ep%d-%s pkt_sz %d, dma_addr 0x%x length %d, mode %d\n", - pImplChannel->epnum, - pImplChannel->transmit ? "Tx" : "Rx", + musb_channel->epnum, + musb_channel->transmit ? "Tx" : "Rx", packet_sz, dma_addr, len, mode); - BUG_ON(pChannel->status == MUSB_DMA_STATUS_UNKNOWN || - pChannel->status == MUSB_DMA_STATUS_BUSY); + BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN || + channel->status == MUSB_DMA_STATUS_BUSY); - pChannel->actual_len = 0; - pImplChannel->dwStartAddress = dma_addr; - pImplChannel->len = len; - pImplChannel->wMaxPacketSize = packet_sz; - pChannel->status = MUSB_DMA_STATUS_BUSY; + channel->actual_len = 0; + musb_channel->start_addr = dma_addr; + musb_channel->len = len; + musb_channel->max_packet_sz = packet_sz; + channel->status = MUSB_DMA_STATUS_BUSY; if ((mode == 1) && (len >= packet_sz)) - configure_channel(pChannel, packet_sz, 1, dma_addr, len); + configure_channel(channel, packet_sz, 1, dma_addr, len); else - configure_channel(pChannel, packet_sz, 0, dma_addr, len); + configure_channel(channel, packet_sz, 0, dma_addr, len); return true; } -static int dma_channel_abort(struct dma_channel *pChannel) +static int dma_channel_abort(struct dma_channel *channel) { - struct musb_dma_channel *pImplChannel = - (struct musb_dma_channel *) pChannel->private_data; - u8 bChannel = pImplChannel->bIndex; - void __iomem *mbase = pImplChannel->controller->pCoreBase; + struct musb_dma_channel *musb_channel = channel->private_data; + void __iomem *mbase = musb_channel->controller->base; + + u8 bchannel = musb_channel->idx; u16 csr; - if (pChannel->status == MUSB_DMA_STATUS_BUSY) { - if (pImplChannel->transmit) { + if (channel->status == MUSB_DMA_STATUS_BUSY) { + if (musb_channel->transmit) { csr = musb_readw(mbase, - MUSB_EP_OFFSET(pImplChannel->epnum, + MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR)); csr &= ~(MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB | MUSB_TXCSR_DMAMODE); musb_writew(mbase, - MUSB_EP_OFFSET(pImplChannel->epnum, - MUSB_TXCSR), + MUSB_EP_OFFSET(musb_channel->epnum, MUSB_TXCSR), csr); } else { csr = musb_readw(mbase, - MUSB_EP_OFFSET(pImplChannel->epnum, + MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR)); csr &= ~(MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAENAB | MUSB_RXCSR_DMAMODE); musb_writew(mbase, - MUSB_EP_OFFSET(pImplChannel->epnum, - MUSB_RXCSR), + MUSB_EP_OFFSET(musb_channel->epnum, MUSB_RXCSR), csr); } musb_writew(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_CONTROL), + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL), 0); musb_writel(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_ADDRESS), + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_ADDRESS), 0); musb_writel(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bChannel, MUSB_HSDMA_COUNT), + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_COUNT), 0); - pChannel->status = MUSB_DMA_STATUS_FREE; + channel->status = MUSB_DMA_STATUS_FREE; } + return 0; } static irqreturn_t dma_controller_irq(int irq, void *private_data) { - struct musb_dma_controller *controller = - (struct musb_dma_controller *)private_data; - struct musb_dma_channel *pImplChannel; - struct musb *musb = controller->pDmaPrivate; - void __iomem *mbase = controller->pCoreBase; - struct dma_channel *pChannel; - u8 bChannel; - u16 csr; - u32 dwAddress; - u8 int_hsdma; + struct musb_dma_controller *controller = private_data; + struct musb *musb = controller->private_data; + struct musb_dma_channel *musb_channel; + struct dma_channel *channel; + + void __iomem *mbase = controller->base; + irqreturn_t retval = IRQ_NONE; + unsigned long flags; + u8 bchannel; + u8 int_hsdma; + + u32 addr; + u16 csr; + spin_lock_irqsave(&musb->lock, flags); int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR); if (!int_hsdma) goto done; - for (bChannel = 0; bChannel < MUSB_HSDMA_CHANNELS; bChannel++) { - if (int_hsdma & (1 << bChannel)) { - pImplChannel = (struct musb_dma_channel *) - &(controller->aChannel[bChannel]); - pChannel = &pImplChannel->Channel; + for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) { + if (int_hsdma & (1 << bchannel)) { + musb_channel = (struct musb_dma_channel *) + &(controller->channel[bchannel]); + channel = &musb_channel->channel; csr = musb_readw(mbase, - MUSB_HSDMA_CHANNEL_OFFSET(bChannel, + MUSB_HSDMA_CHANNEL_OFFSET(bchannel, MUSB_HSDMA_CONTROL)); - if (csr & (1 << MUSB_HSDMA_BUSERROR_SHIFT)) - pImplChannel->Channel.status = + if (csr & (1 << MUSB_HSDMA_BUSERROR_SHIFT)) { + musb_channel->channel.status = MUSB_DMA_STATUS_BUS_ABORT; - else { + } else { u8 devctl; - dwAddress = musb_readl(mbase, + addr = musb_readl(mbase, MUSB_HSDMA_CHANNEL_OFFSET( - bChannel, + bchannel, MUSB_HSDMA_ADDRESS)); - pChannel->actual_len = dwAddress - - pImplChannel->dwStartAddress; + channel->actual_len = addr + - musb_channel->start_addr; DBG(2, "ch %p, 0x%x -> 0x%x (%d / %d) %s\n", - pChannel, pImplChannel->dwStartAddress, - dwAddress, pChannel->actual_len, - pImplChannel->len, - (pChannel->actual_len - < pImplChannel->len) ? + channel, musb_channel->start_addr, + addr, channel->actual_len, + musb_channel->len, + (channel->actual_len + < musb_channel->len) ? "=> reconfig 0" : "=> complete"); devctl = musb_readb(mbase, MUSB_DEVCTL); - pChannel->status = MUSB_DMA_STATUS_FREE; + channel->status = MUSB_DMA_STATUS_FREE; /* completed */ if ((devctl & MUSB_DEVCTL_HM) - && (pImplChannel->transmit) - && ((pChannel->desired_mode == 0) - || (pChannel->actual_len & - (pImplChannel->wMaxPacketSize - 1))) + && (musb_channel->transmit) + && ((channel->desired_mode == 0) + || (channel->actual_len & + (musb_channel->max_packet_sz - 1))) ) { /* Send out the packet */ musb_ep_select(mbase, - pImplChannel->epnum); + musb_channel->epnum); musb_writew(mbase, MUSB_EP_OFFSET( - pImplChannel->epnum, + musb_channel->epnum, MUSB_TXCSR), MUSB_TXCSR_TXPKTRDY); - } else + } else { musb_dma_completion( musb, - pImplChannel->epnum, - pImplChannel->transmit); + musb_channel->epnum, + musb_channel->transmit); + } } } } @@ -380,9 +383,9 @@ done: void dma_controller_destroy(struct dma_controller *c) { - struct musb_dma_controller *controller; + struct musb_dma_controller *controller = container_of(c, + struct musb_dma_controller, controller); - controller = container_of(c, struct musb_dma_controller, Controller); if (!controller) return; @@ -393,7 +396,7 @@ void dma_controller_destroy(struct dma_controller *c) } struct dma_controller *__init -dma_controller_create(struct musb *musb, void __iomem *pCoreBase) +dma_controller_create(struct musb *musb, void __iomem *base) { struct musb_dma_controller *controller; struct device *dev = musb->controller; @@ -405,29 +408,30 @@ dma_controller_create(struct musb *musb, void __iomem *pCoreBase) return NULL; } - controller = kzalloc(sizeof(struct musb_dma_controller), GFP_KERNEL); + controller = kzalloc(sizeof(*controller), GFP_KERNEL); if (!controller) return NULL; - controller->bChannelCount = MUSB_HSDMA_CHANNELS; - controller->pDmaPrivate = musb; - controller->pCoreBase = pCoreBase; + controller->channel_count = MUSB_HSDMA_CHANNELS; + controller->private_data = musb; + controller->base = base; - controller->Controller.start = dma_controller_start; - controller->Controller.stop = dma_controller_stop; - controller->Controller.channel_alloc = dma_channel_allocate; - controller->Controller.channel_release = dma_channel_release; - controller->Controller.channel_program = dma_channel_program; - controller->Controller.channel_abort = dma_channel_abort; + controller->controller.start = dma_controller_start; + controller->controller.stop = dma_controller_stop; + controller->controller.channel_alloc = dma_channel_allocate; + controller->controller.channel_release = dma_channel_release; + controller->controller.channel_program = dma_channel_program; + controller->controller.channel_abort = dma_channel_abort; if (request_irq(irq, dma_controller_irq, IRQF_DISABLED, - musb->controller->bus_id, &controller->Controller)) { + musb->controller->bus_id, &controller->controller)) { dev_err(dev, "request_irq %d failed!\n", irq); - dma_controller_destroy(&controller->Controller); + dma_controller_destroy(&controller->controller); + return NULL; } controller->irq = irq; - return &controller->Controller; + return &controller->controller; } diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 9d2dcb121c5..ce6c162920f 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -53,7 +53,9 @@ static void musb_do_idle(unsigned long _musb) { struct musb *musb = (void *)_musb; unsigned long flags; +#ifdef CONFIG_USB_MUSB_HDRC_HCD u8 power; +#endif u8 devctl; devctl = musb_readb(musb->mregs, MUSB_DEVCTL); diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index b73b036f3d7..ee8fca92a4a 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -605,7 +605,7 @@ void musb_platform_set_mode(struct musb *musb, u8 musb_mode) if (musb->board_mode != MUSB_OTG) { ERR("Changing mode currently only supported in OTG mode\n"); - return; + return -EINVAL; } otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); |