diff options
Diffstat (limited to 'drivers/usb/musb')
-rw-r--r-- | drivers/usb/musb/Kconfig | 61 | ||||
-rw-r--r-- | drivers/usb/musb/Makefile | 26 | ||||
-rw-r--r-- | drivers/usb/musb/musb_core.c | 8 | ||||
-rw-r--r-- | drivers/usb/musb/musb_core.h | 4 | ||||
-rw-r--r-- | drivers/usb/musb/musb_debug.h | 4 | ||||
-rw-r--r-- | drivers/usb/musb/musb_debugfs.c | 8 | ||||
-rw-r--r-- | drivers/usb/musb/musb_gadget.c | 6 | ||||
-rw-r--r-- | drivers/usb/musb/musb_gadget_ep0.c | 1 | ||||
-rw-r--r-- | drivers/usb/musb/musb_io.h | 2 | ||||
-rw-r--r-- | drivers/usb/musb/omap2430.c | 61 | ||||
-rw-r--r-- | drivers/usb/musb/tusb6010.c | 1 | ||||
-rw-r--r-- | drivers/usb/musb/ux500_dma.c | 39 |
12 files changed, 87 insertions, 134 deletions
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 07a03460a59..f70cab3beee 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -5,14 +5,13 @@ # (M)HDRC = (Multipoint) Highspeed Dual-Role Controller config USB_MUSB_HDRC + tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' depends on USB && USB_GADGET - depends on (ARM || (BF54x && !BF544) || (BF52x && !BF522 && !BF523)) select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN) select TWL4030_USB if MACH_OMAP_3430SDP select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA select USB_OTG_UTILS select USB_GADGET_DUALSPEED - tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' help Say Y here if your system has a dual role high speed USB controller based on the Mentor Graphics silicon IP. Then @@ -31,9 +30,10 @@ config USB_MUSB_HDRC To compile this driver as a module, choose M here; the module will be called "musb-hdrc". +if USB_MUSB_HDRC + choice prompt "Platform Glue Layer" - depends on USB_MUSB_HDRC config USB_MUSB_DAVINCI tristate "DaVinci" @@ -45,7 +45,6 @@ config USB_MUSB_DA8XX config USB_MUSB_TUSB6010 tristate "TUSB6010" - depends on ARCH_OMAP config USB_MUSB_OMAP2PLUS tristate "OMAP2430 and onwards" @@ -65,46 +64,54 @@ config USB_MUSB_UX500 endchoice -config MUSB_PIO_ONLY - bool 'Disable DMA (always use PIO)' - depends on USB_MUSB_HDRC - default USB_MUSB_TUSB6010 || USB_MUSB_DA8XX || USB_MUSB_AM35X +choice + prompt 'MUSB DMA mode' + default USB_UX500_DMA if USB_MUSB_UX500 + default USB_INVENTRA_DMA if USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN + default USB_TI_CPPI_DMA if USB_MUSB_DAVINCI + default USB_TUSB_OMAP_DMA if USB_MUSB_TUSB6010 + default MUSB_PIO_ONLY if USB_MUSB_TUSB6010 || USB_MUSB_DA8XX || USB_MUSB_AM35X help - All data is copied between memory and FIFO by the CPU. - DMA controllers are ignored. - - Do not select 'n' here unless DMA support for your SOC or board - is unavailable (or unstable). When DMA is enabled at compile time, - you can still disable it at run time using the "use_dma=n" module - parameter. + Unfortunately, only one option can be enabled here. Ideally one + should be able to build all these drivers into one kernel to + allow using DMA on multiplatform kernels. config USB_UX500_DMA - bool - depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY - default USB_MUSB_UX500 + bool 'ST Ericsson U8500 and U5500' + depends on USB_MUSB_UX500 help Enable DMA transfers on UX500 platforms. config USB_INVENTRA_DMA - bool - depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY - default USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN + bool 'Inventra' + depends on USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN help Enable DMA transfers using Mentor's engine. config USB_TI_CPPI_DMA - bool - depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY - default USB_MUSB_DAVINCI + bool 'TI CPPI (Davinci)' + depends on USB_MUSB_DAVINCI help Enable DMA transfers when TI CPPI DMA is available. config USB_TUSB_OMAP_DMA - bool - depends on USB_MUSB_HDRC && !MUSB_PIO_ONLY + bool 'TUSB 6010' depends on USB_MUSB_TUSB6010 depends on ARCH_OMAP - default y help Enable DMA transfers on TUSB 6010 when OMAP DMA is available. +config MUSB_PIO_ONLY + bool 'Disable DMA (always use PIO)' + help + All data is copied between memory and FIFO by the CPU. + DMA controllers are ignored. + + Do not choose this unless DMA support for your SOC or board + is unavailable (or unstable). When DMA is enabled at compile time, + you can still disable it at run time using the "use_dma=n" module + parameter. + +endchoice + +endif # USB_MUSB_HDRC diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index d8fd9d092de..88bfb9dee4b 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -24,25 +24,7 @@ obj-$(CONFIG_USB_MUSB_UX500) += ux500.o # PIO only, or DMA (several potential schemes). # though PIO is always there to back up DMA, and for ep0 -ifneq ($(CONFIG_MUSB_PIO_ONLY),y) - - ifeq ($(CONFIG_USB_INVENTRA_DMA),y) - musb_hdrc-y += musbhsdma.o - - else - ifeq ($(CONFIG_USB_TI_CPPI_DMA),y) - musb_hdrc-y += cppi_dma.o - - else - ifeq ($(CONFIG_USB_TUSB_OMAP_DMA),y) - musb_hdrc-y += tusb6010_omap.o - - else - ifeq ($(CONFIG_USB_UX500_DMA),y) - musb_hdrc-y += ux500_dma.o - - endif - endif - endif - endif -endif +musb_hdrc-$(CONFIG_USB_INVENTRA_DMA) += musbhsdma.o +musb_hdrc-$(CONFIG_USB_TI_CPPI_DMA) += cppi_dma.o +musb_hdrc-$(CONFIG_USB_TUSB_OMAP_DMA) += tusb6010_omap.o +musb_hdrc-$(CONFIG_USB_UX500_DMA) += ux500_dma.o diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index b63ab157010..f6ff7923048 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -661,7 +661,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, handled = IRQ_HANDLED; musb->is_active = 1; - set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); musb->ep0_stage = MUSB_EP0_START; @@ -1432,7 +1431,7 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb) struct musb_hw_ep *hw_ep = musb->endpoints + i; hw_ep->fifo = MUSB_FIFO_OFFSET(i) + mbase; -#ifdef CONFIG_USB_MUSB_TUSB6010 +#if defined(CONFIG_USB_MUSB_TUSB6010) || defined (CONFIG_USB_MUSB_TUSB6010_MODULE) hw_ep->fifo_async = musb->async + 0x400 + MUSB_FIFO_OFFSET(i); hw_ep->fifo_sync = musb->sync + 0x400 + MUSB_FIFO_OFFSET(i); hw_ep->fifo_sync_va = @@ -1631,6 +1630,7 @@ void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit) } } } +EXPORT_SYMBOL_GPL(musb_dma_completion); #else #define use_dma 0 @@ -2012,8 +2012,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) if (status < 0) goto fail3; - pm_runtime_put(musb->controller); - status = musb_init_debugfs(musb); if (status < 0) goto fail4; @@ -2158,6 +2156,7 @@ static void musb_save_context(struct musb *musb) if (!epio) continue; + musb_writeb(musb_base, MUSB_INDEX, i); musb->context.index_regs[i].txmaxp = musb_readw(epio, MUSB_TXMAXP); musb->context.index_regs[i].txcsr = @@ -2233,6 +2232,7 @@ static void musb_restore_context(struct musb *musb) if (!epio) continue; + musb_writeb(musb_base, MUSB_INDEX, i); musb_writew(epio, MUSB_TXMAXP, musb->context.index_regs[i].txmaxp); musb_writew(epio, MUSB_TXCSR, diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index b3c065ab9db..3d28fb8a2dc 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -40,7 +40,6 @@ #include <linux/interrupt.h> #include <linux/errno.h> #include <linux/timer.h> -#include <linux/clk.h> #include <linux/device.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> @@ -311,6 +310,7 @@ struct musb_context_registers { u8 index, testmode; u8 devctl, busctl, misc; + u32 otg_interfsel; struct musb_csr_regs index_regs[MUSB_C_NUM_EPS]; }; @@ -327,6 +327,7 @@ struct musb { irqreturn_t (*isr)(int, void *); struct work_struct irq_work; + struct work_struct otg_notifier_work; u16 hwvers; /* this hub status bit is reserved by USB 2.0 and not seen by usbcore */ @@ -372,6 +373,7 @@ struct musb { u16 int_tx; struct otg_transceiver *xceiv; + u8 xceiv_event; int nIrq; unsigned irq_wake:1; diff --git a/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h index 742eada5002..27ba8f79946 100644 --- a/drivers/usb/musb/musb_debug.h +++ b/drivers/usb/musb/musb_debug.h @@ -43,8 +43,8 @@ #define ERR(fmt, args...) yprintk(KERN_ERR, fmt, ## args) #ifdef CONFIG_DEBUG_FS -extern int musb_init_debugfs(struct musb *musb); -extern void musb_exit_debugfs(struct musb *musb); +int musb_init_debugfs(struct musb *musb); +void musb_exit_debugfs(struct musb *musb); #else static inline int musb_init_debugfs(struct musb *musb) { diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c index 61f4ee466df..13d9af9bf92 100644 --- a/drivers/usb/musb/musb_debugfs.c +++ b/drivers/usb/musb/musb_debugfs.c @@ -33,11 +33,7 @@ #include <linux/module.h> #include <linux/kernel.h> -#include <linux/sched.h> #include <linux/init.h> -#include <linux/list.h> -#include <linux/platform_device.h> -#include <linux/io.h> #include <linux/debugfs.h> #include <linux/seq_file.h> @@ -46,10 +42,6 @@ #include "musb_core.h" #include "musb_debug.h" -#ifdef CONFIG_ARCH_DAVINCI -#include "davinci.h" -#endif - struct musb_register_map { char *name; unsigned offset; diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 922148ff8d2..ac3d2eec20f 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -40,8 +40,6 @@ #include <linux/smp.h> #include <linux/spinlock.h> #include <linux/delay.h> -#include <linux/moduleparam.h> -#include <linux/stat.h> #include <linux/dma-mapping.h> #include <linux/slab.h> @@ -1844,7 +1842,7 @@ int __init musb_gadget_setup(struct musb *musb) */ musb->g.ops = &musb_gadget_operations; - musb->g.is_dualspeed = 1; + musb->g.max_speed = USB_SPEED_HIGH; musb->g.speed = USB_SPEED_UNKNOWN; /* this "gadget" abstracts/virtualizes the controller */ @@ -1903,7 +1901,7 @@ static int musb_gadget_start(struct usb_gadget *g, unsigned long flags; int retval = -EINVAL; - if (driver->speed < USB_SPEED_HIGH) + if (driver->max_speed < USB_SPEED_HIGH) goto err0; pm_runtime_get_sync(musb->controller); diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index 6a0d0467ec7..e40d7647caf 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -37,7 +37,6 @@ #include <linux/list.h> #include <linux/timer.h> #include <linux/spinlock.h> -#include <linux/init.h> #include <linux/device.h> #include <linux/interrupt.h> diff --git a/drivers/usb/musb/musb_io.h b/drivers/usb/musb/musb_io.h index 03c6ccdbb3b..e61aa95f2d2 100644 --- a/drivers/usb/musb/musb_io.h +++ b/drivers/usb/musb/musb_io.h @@ -74,7 +74,7 @@ static inline void musb_writel(void __iomem *addr, unsigned offset, u32 data) { __raw_writel(data, addr + offset); } -#ifdef CONFIG_USB_MUSB_TUSB6010 +#if defined(CONFIG_USB_MUSB_TUSB6010) || defined (CONFIG_USB_MUSB_TUSB6010_MODULE) /* * TUSB6010 doesn't allow 8-bit access; 16-bit access is the minimum. diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index ba85f273e48..c27bbbf32b5 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -29,7 +29,6 @@ #include <linux/sched.h> #include <linux/init.h> #include <linux/list.h> -#include <linux/clk.h> #include <linux/io.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> @@ -228,21 +227,25 @@ static int musb_otg_notifications(struct notifier_block *nb, unsigned long event, void *unused) { struct musb *musb = container_of(nb, struct musb, nb); + + musb->xceiv_event = event; + schedule_work(&musb->otg_notifier_work); + + return 0; +} + +static void musb_otg_notifier_work(struct work_struct *data_notifier_work) +{ + struct musb *musb = container_of(data_notifier_work, struct musb, otg_notifier_work); struct device *dev = musb->controller; struct musb_hdrc_platform_data *pdata = dev->platform_data; struct omap_musb_board_data *data = pdata->board_data; - switch (event) { + switch (musb->xceiv_event) { case USB_EVENT_ID: dev_dbg(musb->controller, "ID GND\n"); - if (is_otg_enabled(musb)) { - if (musb->gadget_driver) { - pm_runtime_get_sync(musb->controller); - otg_init(musb->xceiv); - omap2430_musb_set_vbus(musb, 1); - } - } else { + if (!is_otg_enabled(musb) || musb->gadget_driver) { pm_runtime_get_sync(musb->controller); otg_init(musb->xceiv); omap2430_musb_set_vbus(musb, 1); @@ -274,10 +277,7 @@ static int musb_otg_notifications(struct notifier_block *nb, break; default: dev_dbg(musb->controller, "ID float\n"); - return NOTIFY_DONE; } - - return NOTIFY_OK; } static int omap2430_musb_init(struct musb *musb) @@ -297,6 +297,8 @@ static int omap2430_musb_init(struct musb *musb) return -ENODEV; } + INIT_WORK(&musb->otg_notifier_work, musb_otg_notifier_work); + status = pm_runtime_get_sync(dev); if (status < 0) { dev_err(dev, "pm_runtime_get_sync FAILED"); @@ -334,7 +336,6 @@ static int omap2430_musb_init(struct musb *musb) return 0; err1: - pm_runtime_disable(dev); return status; } @@ -350,20 +351,19 @@ static void omap2430_musb_enable(struct musb *musb) case USB_EVENT_ID: otg_init(musb->xceiv); - if (data->interface_type == MUSB_INTERFACE_UTMI) { - devctl = musb_readb(musb->mregs, MUSB_DEVCTL); - /* start the session */ - devctl |= MUSB_DEVCTL_SESSION; - musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); - while (musb_readb(musb->mregs, MUSB_DEVCTL) & - MUSB_DEVCTL_BDEVICE) { - cpu_relax(); - - if (time_after(jiffies, timeout)) { - dev_err(musb->controller, - "configured as A device timeout"); - break; - } + if (data->interface_type != MUSB_INTERFACE_UTMI) + break; + devctl = musb_readb(musb->mregs, MUSB_DEVCTL); + /* start the session */ + devctl |= MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + while (musb_readb(musb->mregs, MUSB_DEVCTL) & + MUSB_DEVCTL_BDEVICE) { + cpu_relax(); + + if (time_after(jiffies, timeout)) { + dev_err(dev, "configured as A device timeout"); + break; } } break; @@ -478,7 +478,6 @@ static int __exit omap2430_remove(struct platform_device *pdev) platform_device_del(glue->musb); platform_device_put(glue->musb); pm_runtime_put(&pdev->dev); - pm_runtime_disable(&pdev->dev); kfree(glue); return 0; @@ -491,6 +490,9 @@ static int omap2430_runtime_suspend(struct device *dev) struct omap2430_glue *glue = dev_get_drvdata(dev); struct musb *musb = glue_to_musb(glue); + musb->context.otg_interfsel = musb_readl(musb->mregs, + OTG_INTERFSEL); + omap2430_low_level_exit(musb); otg_set_suspend(musb->xceiv, 1); @@ -503,6 +505,9 @@ static int omap2430_runtime_resume(struct device *dev) struct musb *musb = glue_to_musb(glue); omap2430_low_level_init(musb); + musb_writel(musb->mregs, OTG_INTERFSEL, + musb->context.otg_interfsel); + otg_set_suspend(musb->xceiv, 0); return 0; diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index ec1480191f7..1f405616e6c 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -56,6 +56,7 @@ u8 tusb_get_revision(struct musb *musb) return rev; } +EXPORT_SYMBOL_GPL(tusb_get_revision); static int tusb_print_revision(struct musb *musb) { diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index ef4333f4bbe..a163632877a 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c @@ -37,7 +37,6 @@ struct ux500_dma_channel { struct dma_channel channel; struct ux500_dma_controller *controller; struct musb_hw_ep *hw_ep; - struct work_struct channel_work; struct dma_chan *dma_chan; unsigned int cur_len; dma_cookie_t cookie; @@ -56,31 +55,11 @@ struct ux500_dma_controller { dma_addr_t phy_base; }; -/* Work function invoked from DMA callback to handle tx transfers. */ -static void ux500_tx_work(struct work_struct *data) -{ - struct ux500_dma_channel *ux500_channel = container_of(data, - struct ux500_dma_channel, channel_work); - struct musb_hw_ep *hw_ep = ux500_channel->hw_ep; - struct musb *musb = hw_ep->musb; - unsigned long flags; - - dev_dbg(musb->controller, "DMA tx transfer done on hw_ep=%d\n", - hw_ep->epnum); - - spin_lock_irqsave(&musb->lock, flags); - ux500_channel->channel.actual_len = ux500_channel->cur_len; - ux500_channel->channel.status = MUSB_DMA_STATUS_FREE; - musb_dma_completion(musb, hw_ep->epnum, - ux500_channel->is_tx); - spin_unlock_irqrestore(&musb->lock, flags); -} - /* Work function invoked from DMA callback to handle rx transfers. */ -static void ux500_rx_work(struct work_struct *data) +void ux500_dma_callback(void *private_data) { - struct ux500_dma_channel *ux500_channel = container_of(data, - struct ux500_dma_channel, channel_work); + struct dma_channel *channel = private_data; + struct ux500_dma_channel *ux500_channel = channel->private_data; struct musb_hw_ep *hw_ep = ux500_channel->hw_ep; struct musb *musb = hw_ep->musb; unsigned long flags; @@ -94,14 +73,7 @@ static void ux500_rx_work(struct work_struct *data) musb_dma_completion(musb, hw_ep->epnum, ux500_channel->is_tx); spin_unlock_irqrestore(&musb->lock, flags); -} - -void ux500_dma_callback(void *private_data) -{ - struct dma_channel *channel = (struct dma_channel *)private_data; - struct ux500_dma_channel *ux500_channel = channel->private_data; - schedule_work(&ux500_channel->channel_work); } static bool ux500_configure_channel(struct dma_channel *channel, @@ -330,7 +302,6 @@ static int ux500_dma_controller_start(struct dma_controller *c) void **param_array; struct ux500_dma_channel *channel_array; u32 ch_count; - void (*musb_channel_work)(struct work_struct *); dma_cap_mask_t mask; if ((data->num_rx_channels > UX500_MUSB_DMA_NUM_RX_CHANNELS) || @@ -347,7 +318,6 @@ static int ux500_dma_controller_start(struct dma_controller *c) channel_array = controller->rx_channel; ch_count = data->num_rx_channels; param_array = data->dma_rx_param_array; - musb_channel_work = ux500_rx_work; for (dir = 0; dir < 2; dir++) { for (ch_num = 0; ch_num < ch_count; ch_num++) { @@ -374,15 +344,12 @@ static int ux500_dma_controller_start(struct dma_controller *c) return -EBUSY; } - INIT_WORK(&ux500_channel->channel_work, - musb_channel_work); } /* Prepare the loop for TX channels */ channel_array = controller->tx_channel; ch_count = data->num_tx_channels; param_array = data->dma_tx_param_array; - musb_channel_work = ux500_tx_work; is_tx = 1; } |