diff --git a/arch/arm/mach-bcm2708/Kconfig b/arch/arm/mach-bcm2708/Kconfig index 1dfd0a41658446..eae398f934a85d 100644 --- a/arch/arm/mach-bcm2708/Kconfig +++ b/arch/arm/mach-bcm2708/Kconfig @@ -13,10 +13,17 @@ config BCM2708_GPIO bool "BCM2708 gpio support" depends on MACH_BCM2708 select ARCH_REQUIRE_GPIOLIB - default y + default n help Include support for the Broadcom(R) BCM2708 gpio. +config BCM2708_RPI2C + bool "I2C Sniffing support on Raspbery Pi" + depends on MACH_BCM2708 + default y + help + Include support for the I2C sniffer (slave mode) on Raspbery Pi. + config BCM2708_VCMEM bool "Videocore Memory" depends on MACH_BCM2708 diff --git a/arch/arm/mach-bcm2708/Makefile b/arch/arm/mach-bcm2708/Makefile index b180e068fff045..afba3bee02b1de 100644 --- a/arch/arm/mach-bcm2708/Makefile +++ b/arch/arm/mach-bcm2708/Makefile @@ -2,10 +2,10 @@ # Makefile for the linux kernel. # -obj-$(CONFIG_MACH_BCM2708) += clock.o bcm2708.o armctrl.o vcio.o power.o dma.o delay.o +obj-$(CONFIG_MACH_BCM2708) += clock.o bcm2708.o armctrl.o vcio.o power.o dma.o obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o +obj-$(CONFIG_BCM2708_RPI2C) += rpi2c.o +rpi2c-objs := rpi2c_fiq.o rpi2c_linux.o obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o - obj-$(CONFIG_BCM2708_DMAER) += dmaer_master.o dmaer_master-objs := dmaer.o vc_support.o - diff --git a/arch/arm/mach-bcm2708/armctrl.c b/arch/arm/mach-bcm2708/armctrl.c index f22fbba2bf49e0..274aa30d6d8281 100644 --- a/arch/arm/mach-bcm2708/armctrl.c +++ b/arch/arm/mach-bcm2708/armctrl.c @@ -46,41 +46,36 @@ static unsigned int remap_irqs[(INTERRUPT_ARASANSDIO + 1) - INTERRUPT_JPEG] = { static void armctrl_mask_irq(struct irq_data *d) { static const unsigned int disables[4] = { - IO_ADDRESS(ARM_IRQ_DIBL1), - IO_ADDRESS(ARM_IRQ_DIBL2), - IO_ADDRESS(ARM_IRQ_DIBL3), + ARM_IRQ_DIBL1, + ARM_IRQ_DIBL2, + ARM_IRQ_DIBL3, 0 }; - if(d->irq >= FIQ_START) - { - writel(0, __io(IO_ADDRESS(ARM_IRQ_FAST))); - } - else - { + if (d->irq >= FIQ_START) { + writel(0, __io_address(ARM_IRQ_FAST)); + } else { unsigned int data = (unsigned int)irq_get_chip_data(d->irq); - writel(1 << (data & 0x1f), __io(disables[(data >> 5) & 0x3])); + writel(1 << (data & 0x1f), __io_address(disables[(data >> 5) & 0x3])); } } static void armctrl_unmask_irq(struct irq_data *d) { static const unsigned int enables[4] = { - IO_ADDRESS(ARM_IRQ_ENBL1), - IO_ADDRESS(ARM_IRQ_ENBL2), - IO_ADDRESS(ARM_IRQ_ENBL3), + ARM_IRQ_ENBL1, + ARM_IRQ_ENBL2, + ARM_IRQ_ENBL3, 0 }; - if(d->irq >= FIQ_START) - { - unsigned int data = (unsigned int)irq_get_chip_data(d->irq) - FIQ_START; - writel(0x80 | data, __io(IO_ADDRESS(ARM_IRQ_FAST))); - } - else - { - unsigned int data = (unsigned int)irq_get_chip_data(d->irq); - writel(1 << (data & 0x1f), __io(enables[(data >> 5) & 0x3])); + if (d->irq >= FIQ_START) { + unsigned int data = + (unsigned int)irq_get_chip_data(d->irq) - FIQ_START; + writel(0x80 | data, __io_address(ARM_IRQ_FAST)); + } else { + unsigned int data = (unsigned int)irq_get_chip_data(d->irq); + writel(1 << (data & 0x1f), __io_address(enables[(data >> 5) & 0x3])); } } @@ -100,17 +95,16 @@ static void armctrl_unmask_irq(struct irq_data *d) * @soft_int: Save for VIC_INT_SOFT. * @protect: Save for VIC_PROTECT. */ - struct armctrl_info { - void __iomem *base; - int irq; - u32 resume_sources; - u32 resume_irqs; - u32 int_select; - u32 int_enable; - u32 soft_int; - u32 protect; - } armctrl; - +struct armctrl_info { + void __iomem *base; + int irq; + u32 resume_sources; + u32 resume_irqs; + u32 int_select; + u32 int_enable; + u32 soft_int; + u32 protect; +} armctrl; static int armctrl_suspend(void) { @@ -122,7 +116,6 @@ static void armctrl_resume(void) return; } - /** * armctrl_pm_register - Register a VIC for later power management control * @base: The base address of the VIC. @@ -159,19 +152,19 @@ static int armctrl_set_wake(struct irq_data *d, unsigned int on) } #else -static inline void armctrl_pm_register(void __iomem *base, unsigned int irq, +static inline void armctrl_pm_register(void __iomem * base, unsigned int irq, u32 arg1) { } + #define armctrl_suspend NULL #define armctrl_resume NULL #define armctrl_set_wake NULL #endif /* CONFIG_PM */ - static struct syscore_ops armctrl_syscore_ops = { .suspend = armctrl_suspend, - .resume = armctrl_resume, + .resume = armctrl_resume, }; /** @@ -189,7 +182,6 @@ static int __init armctrl_syscore_init(void) late_initcall(armctrl_syscore_init); - static struct irq_chip armctrl_chip = { .name = "ARMCTRL", .irq_ack = armctrl_mask_irq, diff --git a/arch/arm/mach-bcm2708/bcm2708.c b/arch/arm/mach-bcm2708/bcm2708.c index 9a5632f6b8a4c7..5662c1a52f8703 100644 --- a/arch/arm/mach-bcm2708/bcm2708.c +++ b/arch/arm/mach-bcm2708/bcm2708.c @@ -108,13 +108,6 @@ static struct map_desc bcm2708_io_desc[] __initdata = { .pfn = __phys_to_pfn(UART1_BASE), .length = SZ_4K, .type = MT_DEVICE}, -#ifdef CONFIG_MMC_BCM2708 /* broadcom legacy SD */ - { - .virtual = IO_ADDRESS(MMCI0_BASE), - .pfn = __phys_to_pfn(MMCI0_BASE), - .length = SZ_4K, - .type = MT_DEVICE}, -#endif { .virtual = IO_ADDRESS(DMA_BASE), .pfn = __phys_to_pfn(DMA_BASE), @@ -161,14 +154,10 @@ static inline uint32_t timer_read(void) return readl(__io_address(ST_BASE + 0x04)); } -#ifdef ARCH_HAS_READ_CURRENT_TIMER -int read_current_timer(unsigned long *timer_val) +static unsigned long bcm2708_read_current_timer(void) { - *timer_val = timer_read(); - return 0; + return timer_read(); } -EXPORT_SYMBOL(read_current_timer); -#endif static u32 notrace bcm2708_read_sched_clock(void) { @@ -235,12 +224,6 @@ static struct clk_lookup lookups[] = { { /* USB */ .dev_id = "bcm2708_usb", .clk = &osc_clk, -#ifdef CONFIG_MMC_BCM2708 - }, - { /* MCI */ - .dev_id = "bcm2708_mci.0", - .clk = &sdhost_clk, -#endif }, { /* SPI */ .dev_id = "bcm2708_spi.0", .clk = &sdhost_clk, @@ -277,31 +260,6 @@ static struct platform_device bcm2708_dmaman_device = { .num_resources = ARRAY_SIZE(bcm2708_dmaman_resources), }; -#ifdef CONFIG_MMC_BCM2708 -static struct resource bcm2708_mci_resources[] = { - { - .start = MMCI0_BASE, - .end = MMCI0_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - { - .start = IRQ_SDIO, - .end = IRQ_SDIO, - .flags = IORESOURCE_IRQ, - } -}; - -static struct platform_device bcm2708_mci_device = { - .name = "bcm2708_mci", - .id = 0, /* first bcm2708_mci */ - .resource = bcm2708_mci_resources, - .num_resources = ARRAY_SIZE(bcm2708_mci_resources), - .dev = { - .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON), - }, -}; -#endif /* CONFIG_MMC_BCM2708 */ - #if defined(CONFIG_W1_MASTER_GPIO) || defined(CONFIG_W1_MASTER_GPIO_MODULE) static struct w1_gpio_platform_data w1_gpio_pdata = { .pin = W1_GPIO, @@ -516,6 +474,7 @@ struct platform_device bcm2708_powerman_device = { .coherent_dma_mask = 0xffffffffUL}, }; + static struct platform_device bcm2708_alsa_devices[] = { [0] = { .name = "bcm2835_AUD0", @@ -579,6 +538,7 @@ static struct resource bcm2708_spi_resources[] = { } }; + static struct platform_device bcm2708_spi_device = { .name = "bcm2708_spi", .id = 0, @@ -588,6 +548,7 @@ static struct platform_device bcm2708_spi_device = { #ifdef CONFIG_BCM2708_SPIDEV static struct spi_board_info bcm2708_spi_devices[] = { +#ifdef CONFIG_SPI_SPIDEV { .modalias = "spidev", .max_speed_hz = 500000, @@ -601,6 +562,7 @@ static struct spi_board_info bcm2708_spi_devices[] = { .chip_select = 1, .mode = SPI_MODE_0, } +#endif }; #endif @@ -700,13 +662,13 @@ static void bcm2708_restart(char mode, const char *cmd) writel(pm_rsts, __io_address(PM_RSTS)); /* Setup watchdog for reset */ - pm_rstc = readl(IO_ADDRESS(PM_RSTC)); + pm_rstc = readl(__io_address(PM_RSTC)); pm_wdog = PM_PASSWORD | (timeout & PM_WDOG_TIME_SET); // watchdog timer = timer clock / 16; need password (31:16) + value (11:0) pm_rstc = PM_PASSWORD | (pm_rstc & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET; - writel(pm_wdog, IO_ADDRESS(PM_WDOG)); - writel(pm_rstc, IO_ADDRESS(PM_RSTC)); + writel(pm_wdog, __io_address(PM_WDOG)); + writel(pm_rstc, __io_address(PM_RSTC)); } /* We can't really power off, but if we do the normal reset scheme, and indicate to bootcode.bin not to reboot, then most of the chip will be powered off */ @@ -753,9 +715,6 @@ void __init bcm2708_init(void) platform_device_register(&w1_device); #endif bcm_register_device(&bcm2708_systemtimer_device); -#ifdef CONFIG_MMC_BCM2708 - bcm_register_device(&bcm2708_mci_device); -#endif bcm_register_device(&bcm2708_fb_device); if (!fiq_fix_enable) { @@ -793,8 +752,6 @@ void __init bcm2708_init(void) #endif } -#define TIMER_PERIOD DIV_ROUND_CLOSEST(STC_FREQ_HZ, HZ) - static void timer_set_mode(enum clock_event_mode mode, struct clock_event_device *clk) { @@ -856,6 +813,12 @@ static struct irqaction bcm2708_timer_irq = { /* * Set up timer interrupt, and return the current time in seconds. */ + +static struct delay_timer bcm2708_delay_timer = { + .read_current_timer = bcm2708_read_current_timer, + .freq = STC_FREQ_HZ, +}; + static void __init bcm2708_timer_init(void) { /* init high res timer */ @@ -881,11 +844,9 @@ static void __init bcm2708_timer_init(void) timer0_clockevent.cpumask = cpumask_of(0); clockevents_register_device(&timer0_clockevent); -} -struct sys_timer bcm2708_timer = { - .init = bcm2708_timer_init, -}; + register_current_timer_delay(&bcm2708_delay_timer); +} #if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) #include @@ -922,38 +883,6 @@ static inline void bcm2708_init_led(void) } #endif -/* The assembly versions in delay.S don't account for core freq changing in cpufreq driver */ -/* Use 1MHz system timer for busy waiting */ -static void bcm2708_udelay(unsigned long usecs) -{ - unsigned long start = timer_read(); - unsigned long now; - do { - now = timer_read(); - } while ((long)(now - start) <= usecs); -} - - -static void bcm2708_const_udelay(unsigned long scaled_usecs) -{ - /* want /107374, this is about 3% bigger. We know usecs is less than 2000, so shouldn't overflow */ - const unsigned long usecs = scaled_usecs * 10 >> 20; - unsigned long start = timer_read(); - unsigned long now; - do { - now = timer_read(); - } while ((long)(now - start) <= usecs); -} - -extern void bcm2708_delay(unsigned long cycles); - -struct arm_delay_ops arm_delay_ops = { - .delay = bcm2708_delay, - .const_udelay = bcm2708_const_udelay, - .udelay = bcm2708_udelay, -}; - - void __init bcm2708_init_early(void) { /* @@ -975,7 +904,7 @@ MACHINE_START(BCM2708, "BCM2708") /* Maintainer: Broadcom Europe Ltd. */ .map_io = bcm2708_map_io, .init_irq = bcm2708_init_irq, - .timer =&bcm2708_timer, + .init_time = bcm2708_timer_init, .init_machine = bcm2708_init, .init_early = bcm2708_init_early, .reserve = board_reserve, diff --git a/arch/arm/mach-bcm2708/bcm2708_gpio.c b/arch/arm/mach-bcm2708/bcm2708_gpio.c index 2d87250783e92a..d0339eb5fdcfa5 100644 --- a/arch/arm/mach-bcm2708/bcm2708_gpio.c +++ b/arch/arm/mach-bcm2708/bcm2708_gpio.c @@ -16,10 +16,10 @@ #include #include #include +#include #include #include #include -#include #define BCM_GPIO_DRIVER_NAME "bcm2708_gpio" #define DRIVER_NAME BCM_GPIO_DRIVER_NAME @@ -70,7 +70,7 @@ static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset, unsigned gpio_field_offset = (offset - 10 * gpio_bank) * 3; //printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set_function %p (%d,%d)\n", gc, offset, function); - if (offset >= BCM_NR_GPIOS) + if (offset >= ARCH_NR_GPIOS) return -EINVAL; spin_lock_irqsave(&lock, flags); @@ -108,7 +108,7 @@ static int bcm2708_gpio_get(struct gpio_chip *gc, unsigned offset) unsigned gpio_field_offset = (offset - 32 * gpio_bank); unsigned lev; - if (offset >= BCM_NR_GPIOS) + if (offset >= ARCH_NR_GPIOS) return 0; lev = readl(gpio->base + GPIOLEV(gpio_bank)); //printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_get %p (%d)=%d\n", gc, offset, 0x1 & (lev>>gpio_field_offset)); @@ -121,7 +121,7 @@ static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value) unsigned gpio_bank = offset / 32; unsigned gpio_field_offset = (offset - 32 * gpio_bank); //printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set %p (%d=%d)\n", gc, offset, value); - if (offset >= BCM_NR_GPIOS) + if (offset >= ARCH_NR_GPIOS) return; if (value) writel(1 << gpio_field_offset, gpio->base + GPIOSET(gpio_bank)); @@ -135,8 +135,6 @@ static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value) #if BCM_GPIO_USE_IRQ -#define IRQ_TO_GPIO(x) irq_to_gpio(x) - static int bcm2708_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) { return gpio_to_irq(gpio); @@ -151,15 +149,15 @@ static int bcm2708_gpio_irq_set_type(struct irq_data *d, unsigned type) return -EINVAL; if (type & IRQ_TYPE_EDGE_RISING) { - gpio->rising |= (1 << IRQ_TO_GPIO(irq)); + gpio->rising |= (1 << irq_to_gpio(irq)); } else { - gpio->rising &= ~(1 << IRQ_TO_GPIO(irq)); + gpio->rising &= ~(1 << irq_to_gpio(irq)); } if (type & IRQ_TYPE_EDGE_FALLING) { - gpio->falling |= (1 << IRQ_TO_GPIO(irq)); + gpio->falling |= (1 << irq_to_gpio(irq)); } else { - gpio->falling &= ~(1 << IRQ_TO_GPIO(irq)); + gpio->falling &= ~(1 << irq_to_gpio(irq)); } return 0; } @@ -168,7 +166,7 @@ static void bcm2708_gpio_irq_mask(struct irq_data *d) { unsigned irq = d->irq; struct bcm2708_gpio *gpio = irq_get_chip_data(irq); - unsigned gn = IRQ_TO_GPIO(irq); + unsigned gn = irq_to_gpio(irq); unsigned gb = gn / 32; unsigned long rising = readl(gpio->base + GPIOREN(gb)); unsigned long falling = readl(gpio->base + GPIOFEN(gb)); @@ -183,7 +181,7 @@ static void bcm2708_gpio_irq_unmask(struct irq_data *d) { unsigned irq = d->irq; struct bcm2708_gpio *gpio = irq_get_chip_data(irq); - unsigned gn = IRQ_TO_GPIO(irq); + unsigned gn = irq_to_gpio(irq); unsigned gb = gn / 32; unsigned long rising = readl(gpio->base + GPIOREN(gb)); unsigned long falling = readl(gpio->base + GPIOFEN(gb)); @@ -282,7 +280,7 @@ static int bcm2708_gpio_probe(struct platform_device *dev) ucb->gc.label = "bcm2708_gpio"; ucb->gc.base = 0; - ucb->gc.ngpio = BCM_NR_GPIOS; + ucb->gc.ngpio = ARCH_NR_GPIOS; ucb->gc.owner = THIS_MODULE; ucb->gc.direction_input = bcm2708_gpio_dir_in; diff --git a/arch/arm/mach-bcm2708/dmaer.c b/arch/arm/mach-bcm2708/dmaer.c index 9063874e23358a..d1bc0fa5c13429 100755 --- a/arch/arm/mach-bcm2708/dmaer.c +++ b/arch/arm/mach-bcm2708/dmaer.c @@ -645,7 +645,7 @@ static int Mmap(struct file *pFile, struct vm_area_struct *pVma) pVmaList->m_pPageTail = pPages; pVma->vm_ops = &g_vmOps4k; - pVma->vm_flags |= VM_RESERVED; + pVma->vm_flags |= VM_IO; VmaOpen4k(pVma); diff --git a/arch/arm/mach-bcm2708/include/mach/gpio.h b/arch/arm/mach-bcm2708/include/mach/gpio.h index 0b82f26c44d60d..f600bc77ad4052 100644 --- a/arch/arm/mach-bcm2708/include/mach/gpio.h +++ b/arch/arm/mach-bcm2708/include/mach/gpio.h @@ -9,40 +9,10 @@ #ifndef __ASM_ARCH_GPIO_H #define __ASM_ARCH_GPIO_H -#define BCM_NR_GPIOS 54 // number of gpio lines +#define ARCH_NR_GPIOS 54 // number of gpio lines -#include -#include -#include - -#ifdef CONFIG_GPIOLIB - -static inline int gpio_get_value(unsigned gpio) -{ - return __gpio_get_value(gpio); -} - -static inline void gpio_set_value(unsigned gpio, int value) -{ - __gpio_set_value(gpio, value); -} - -static inline int gpio_cansleep(unsigned gpio) -{ - return __gpio_cansleep(gpio); -} - - -static inline unsigned irq_to_gpio(unsigned irq) { - return (irq-GPIO_IRQ_START); -} - -static inline unsigned gpio_to_irq(unsigned gpio) { - return GPIO_IRQ_START+gpio; -} -#define gpio_to_irq gpio_to_irq - -#endif /* CONFIG_GPIOLIB */ +#define gpio_to_irq(x) ((x) + GPIO_IRQ_START) +#define irq_to_gpio(x) ((x) - GPIO_IRQ_START) #endif diff --git a/arch/arm/mach-bcm2708/include/mach/io.h b/arch/arm/mach-bcm2708/include/mach/io.h index e8c7fca17261b0..e6eb84d71006db 100644 --- a/arch/arm/mach-bcm2708/include/mach/io.h +++ b/arch/arm/mach-bcm2708/include/mach/io.h @@ -23,6 +23,5 @@ #define IO_SPACE_LIMIT 0xffffffff #define __io(a) __typesafe_io(a) -#define __mem_pci(a) (a) #endif diff --git a/arch/arm/mach-bcm2708/include/mach/platform.h b/arch/arm/mach-bcm2708/include/mach/platform.h index e063a1ec36d92e..992a630c4829fe 100644 --- a/arch/arm/mach-bcm2708/include/mach/platform.h +++ b/arch/arm/mach-bcm2708/include/mach/platform.h @@ -25,7 +25,7 @@ /* macros to get at IO space when running virtually */ #define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000) -#define __io_address(a) __io(IO_ADDRESS(a)) +#define __io_address(n) IOMEM(IO_ADDRESS(n)) /* diff --git a/arch/arm/mach-bcm2708/include/mach/uncompress.h b/arch/arm/mach-bcm2708/include/mach/uncompress.h index 5c43412b44a57a..6ff8f94630287f 100644 --- a/arch/arm/mach-bcm2708/include/mach/uncompress.h +++ b/arch/arm/mach-bcm2708/include/mach/uncompress.h @@ -25,12 +25,12 @@ #define UART_BAUD 115200 -#define BCM2708_UART_DR UART0_BASE + UART01x_DR -#define BCM2708_UART_FR UART0_BASE + UART01x_FR -#define BCM2708_UART_IBRD UART0_BASE + UART011_IBRD -#define BCM2708_UART_FBRD UART0_BASE + UART011_FBRD -#define BCM2708_UART_LCRH UART0_BASE + UART011_LCRH -#define BCM2708_UART_CR UART0_BASE + UART011_CR +#define BCM2708_UART_DR __io(UART0_BASE + UART01x_DR) +#define BCM2708_UART_FR __io(UART0_BASE + UART01x_FR) +#define BCM2708_UART_IBRD __io(UART0_BASE + UART011_IBRD) +#define BCM2708_UART_FBRD __io(UART0_BASE + UART011_FBRD) +#define BCM2708_UART_LCRH __io(UART0_BASE + UART011_LCRH) +#define BCM2708_UART_CR __io(UART0_BASE + UART011_CR) /* * This does not append a newline diff --git a/drivers/i2c/busses/i2c-bcm2708.c b/drivers/i2c/busses/i2c-bcm2708.c index b2b3fbacdb3b3c..012f337b0601aa 100644 --- a/drivers/i2c/busses/i2c-bcm2708.c +++ b/drivers/i2c/busses/i2c-bcm2708.c @@ -71,7 +71,10 @@ #define DRV_NAME "bcm2708_i2c" static unsigned int baudrate = CONFIG_I2C_BCM2708_BAUDRATE; +static unsigned int clkt = 0x0; // Disable Clock stretching timeout by default module_param(baudrate, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); +module_param(clkt, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + MODULE_PARM_DESC(baudrate, "The I2C baudrate"); @@ -108,6 +111,7 @@ static void bcm2708_i2c_init_pinmode(int id) BUG_ON(id != 0 && id != 1); /* BSC0 is on GPIO 0 & 1, BSC1 is on GPIO 2 & 3 */ for (pin = id*2+0; pin <= id*2+1; pin++) { +printk("bcm2708_i2c_init_pinmode(%d,%d)\n", id, pin); INP_GPIO(pin); /* set mode to GPIO input first */ SET_GPIO_ALT(pin, 0); /* set mode to ALT 0 */ } @@ -131,6 +135,7 @@ static inline void bcm2708_wr(struct bcm2708_i2c *bi, unsigned reg, u32 val) static inline void bcm2708_bsc_reset(struct bcm2708_i2c *bi) { bcm2708_wr(bi, BSC_C, 0); + bcm2708_wr(bi, BSC_CLKT, clkt); bcm2708_wr(bi, BSC_S, BSC_S_CLKT | BSC_S_ERR | BSC_S_DONE); } @@ -260,7 +265,7 @@ static struct i2c_algorithm bcm2708_i2c_algorithm = { .functionality = bcm2708_i2c_functionality, }; -static int __devinit bcm2708_i2c_probe(struct platform_device *pdev) +static int bcm2708_i2c_probe(struct platform_device *pdev) { struct resource *regs; int irq, err = -ENOMEM; @@ -358,7 +363,7 @@ static int __devinit bcm2708_i2c_probe(struct platform_device *pdev) return err; } -static int __devexit bcm2708_i2c_remove(struct platform_device *pdev) +static int bcm2708_i2c_remove(struct platform_device *pdev) { struct bcm2708_i2c *bi = platform_get_drvdata(pdev); @@ -380,7 +385,7 @@ static struct platform_driver bcm2708_i2c_driver = { .owner = THIS_MODULE, }, .probe = bcm2708_i2c_probe, - .remove = __devexit_p(bcm2708_i2c_remove), + .remove = bcm2708_i2c_remove, }; // module_platform_driver(bcm2708_i2c_driver); diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index b257ac258bbc1e..dc69918171d5f7 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -18,8 +18,8 @@ config USB_C67X00_HCD module will be called c67x00. config USB_XHCI_HCD - tristate "xHCI HCD (USB 3.0) support (EXPERIMENTAL)" - depends on USB && USB_ARCH_HAS_XHCI && EXPERIMENTAL + tristate "xHCI HCD (USB 3.0) support" + depends on USB && USB_ARCH_HAS_XHCI ---help--- The eXtensible Host Controller Interface (xHCI) is standard for USB 3.0 "SuperSpeed" host controller hardware. @@ -95,6 +95,11 @@ config USB_EHCI_TT_NEWSCHED If unsure, say Y. +config USB_EHCI_PCI + tristate + depends on USB_EHCI_HCD && PCI + default y + config USB_EHCI_HCD_PMC_MSP tristate "EHCI support for on-chip PMC MSP71xx USB controller" depends on USB_EHCI_HCD && MSP_HAS_USB @@ -143,7 +148,7 @@ config USB_EHCI_FSL Variation of ARC USB block used in some Freescale chips. config USB_EHCI_MXC - bool "Support for Freescale i.MX on-chip EHCI USB controller" + tristate "Support for Freescale i.MX on-chip EHCI USB controller" depends on USB_EHCI_HCD && ARCH_MXC select USB_EHCI_ROOT_HUB_TT ---help--- @@ -215,9 +220,13 @@ config USB_W90X900_EHCI Enables support for the W90X900 USB controller config USB_CNS3XXX_EHCI - bool "Cavium CNS3XXX EHCI Module" + bool "Cavium CNS3XXX EHCI Module (DEPRECATED)" depends on USB_EHCI_HCD && ARCH_CNS3XXX + select USB_EHCI_HCD_PLATFORM ---help--- + This option is deprecated now and the driver was removed, use + USB_EHCI_HCD_PLATFORM instead. + Enable support for the CNS3XXX SOC's on-chip EHCI controller. It is needed for high-speed (480Mbit/sec) USB 2.0 device support. @@ -237,7 +246,7 @@ config USB_EHCI_ATH79 config USB_OXU210HP_HCD tristate "OXU210HP HCD support" - depends on USB + depends on USB && GENERIC_HARDIRQS ---help--- The OXU210HP is an USB host/OTG/device controller. Enable this option if your board has this chip. If unsure, say N. @@ -262,7 +271,7 @@ config USB_ISP116X_HCD config USB_ISP1760_HCD tristate "ISP 1760 HCD support" - depends on USB && EXPERIMENTAL + depends on USB ---help--- The ISP1760 chip is a USB 2.0 host controller. @@ -292,7 +301,7 @@ config USB_OHCI_HCD depends on USB && USB_ARCH_HAS_OHCI select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 select USB_OTG_UTILS if ARCH_OMAP - select USB_ISP1301 if ARCH_LPC32XX || ARCH_PNX4008 + depends on USB_ISP1301 || !ARCH_LPC32XX ---help--- The Open Host Controller Interface (OHCI) is a standard for accessing USB 1.1 host controller hardware. It does more in hardware than Intel's @@ -333,16 +342,6 @@ config USB_OHCI_ATH79 Enables support for the built-in OHCI controller present on the Atheros AR71XX/AR7240 SoCs. -config USB_OHCI_HCD_PPC_SOC - bool "OHCI support for on-chip PPC USB controller" - depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx) - default y - select USB_OHCI_BIG_ENDIAN_DESC - select USB_OHCI_BIG_ENDIAN_MMIO - ---help--- - Enables support for the USB controller on the MPC52xx or - STB03xxx processor chip. If unsure, say Y. - config USB_OHCI_HCD_PPC_OF_BE bool "OHCI support for OF platform bus (big endian)" depends on USB_OHCI_HCD && PPC_OF @@ -376,7 +375,7 @@ config USB_OHCI_HCD_PCI config USB_OHCI_HCD_SSB bool "OHCI support for Broadcom SSB OHCI core (DEPRECATED)" - depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD) && EXPERIMENTAL + depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD) select USB_HCD_SSB select USB_OHCI_HCD_PLATFORM default n @@ -393,9 +392,13 @@ config USB_OHCI_HCD_SSB If unsure, say N. config USB_OHCI_SH - bool "OHCI support for SuperH USB controller" + bool "OHCI support for SuperH USB controller (DEPRECATED)" depends on USB_OHCI_HCD && SUPERH + select USB_OHCI_HCD_PLATFORM ---help--- + This option is deprecated now and the driver was removed, use + USB_OHCI_HCD_PLATFORM instead. + Enables support for the on-chip OHCI controller on the SuperH. If you use the PCI OHCI controller, this option is not necessary. @@ -406,29 +409,33 @@ config USB_OHCI_EXYNOS Enable support for the Samsung Exynos SOC's on-chip OHCI controller. config USB_CNS3XXX_OHCI - bool "Cavium CNS3XXX OHCI Module" + bool "Cavium CNS3XXX OHCI Module (DEPRECATED)" depends on USB_OHCI_HCD && ARCH_CNS3XXX + select USB_OHCI_HCD_PLATFORM ---help--- + This option is deprecated now and the driver was removed, use + USB_OHCI_HCD_PLATFORM instead. + Enable support for the CNS3XXX SOC's on-chip OHCI controller. It is needed for low-speed USB 1.0 device support. config USB_OHCI_HCD_PLATFORM bool "Generic OHCI driver for a platform device" - depends on USB_OHCI_HCD && EXPERIMENTAL + depends on USB_OHCI_HCD default n ---help--- Adds an OHCI host driver for a generic platform device, which - provieds a memory space and an irq. + provides a memory space and an irq. If unsure, say N. config USB_EHCI_HCD_PLATFORM - bool "Generic EHCI driver for a platform device" - depends on USB_EHCI_HCD && EXPERIMENTAL + tristate "Generic EHCI driver for a platform device" + depends on USB_EHCI_HCD default n ---help--- Adds an EHCI host driver for a generic platform device, which - provieds a memory space and an irq. + provides a memory space and an irq. If unsure, say N. @@ -450,7 +457,7 @@ config USB_OHCI_LITTLE_ENDIAN config USB_UHCI_HCD tristate "UHCI HCD (most Intel and VIA) support" - depends on USB && (PCI || SPARC_LEON) + depends on USB && (PCI || SPARC_LEON || ARCH_VT8500) ---help--- The Universal Host Controller Interface is a standard by Intel for accessing the USB hardware in the PC (which is also called the USB @@ -468,7 +475,15 @@ config USB_UHCI_HCD config USB_UHCI_SUPPORT_NON_PCI_HC bool depends on USB_UHCI_HCD - default y if SPARC_LEON + default y if (SPARC_LEON || ARCH_VT8500) + +config USB_UHCI_PLATFORM + bool "Generic UHCI Platform Driver support" + depends on USB_UHCI_SUPPORT_NON_PCI_HC + default y if ARCH_VT8500 + ---help--- + Enable support for generic UHCI platform devices that require no + additional configuration. config USB_UHCI_BIG_ENDIAN_MMIO bool @@ -583,8 +598,7 @@ config USB_RENESAS_USBHS_HCD module will be called renesas-usbhs. config USB_WHCI_HCD - tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)" - depends on EXPERIMENTAL + tristate "Wireless USB Host Controller Interface (WHCI) driver" depends on PCI && USB && UWB select USB_WUSB select UWB_WHCI @@ -596,8 +610,7 @@ config USB_WHCI_HCD will be called "whci-hcd". config USB_HWA_HCD - tristate "Host Wire Adapter (HWA) driver (EXPERIMENTAL)" - depends on EXPERIMENTAL + tristate "Host Wire Adapter (HWA) driver" depends on USB && UWB select USB_WUSB select UWB_HWA @@ -661,7 +674,7 @@ config USB_OCTEON2_COMMON config USB_HCD_BCMA tristate "BCMA usb host driver" - depends on BCMA && EXPERIMENTAL + depends on BCMA select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD help @@ -673,7 +686,7 @@ config USB_HCD_BCMA config USB_HCD_SSB tristate "SSB usb host driver" - depends on SSB && EXPERIMENTAL + depends on SSB select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD help diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index f7676841fa4944..653e2589b48f92 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -24,6 +24,10 @@ obj-$(CONFIG_USB_WHCI_HCD) += whci/ obj-$(CONFIG_PCI) += pci-quirks.o obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o +obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o +obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o +obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o + obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o @@ -42,6 +46,5 @@ obj-$(CONFIG_USB_DWCOTG) += dwc_otg/ dwc_common_port/ obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o -obj-$(CONFIG_MIPS_ALCHEMY) += alchemy-common.o obj-$(CONFIG_USB_HCD_BCMA) += bcma-hcd.o obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c index 443da21d73ca10..df13d425e9c5fd 100644 --- a/drivers/usb/host/bcma-hcd.c +++ b/drivers/usb/host/bcma-hcd.c @@ -54,7 +54,7 @@ static int bcma_wait_bits(struct bcma_device *dev, u16 reg, u32 bitmask, return -ETIMEDOUT; } -static void __devinit bcma_hcd_4716wa(struct bcma_device *dev) +static void bcma_hcd_4716wa(struct bcma_device *dev) { #ifdef CONFIG_BCMA_DRIVER_MIPS /* Work around for 4716 failures. */ @@ -88,7 +88,7 @@ static void __devinit bcma_hcd_4716wa(struct bcma_device *dev) } /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */ -static void __devinit bcma_hcd_init_chip(struct bcma_device *dev) +static void bcma_hcd_init_chip(struct bcma_device *dev) { u32 tmp; @@ -165,8 +165,7 @@ static const struct usb_ehci_pdata ehci_pdata = { static const struct usb_ohci_pdata ohci_pdata = { }; -static struct platform_device * __devinit -bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr) +static struct platform_device *bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr) { struct platform_device *hci_dev; struct resource hci_res[2]; @@ -212,7 +211,7 @@ bcma_hcd_create_pdev(struct bcma_device *dev, bool ohci, u32 addr) return ERR_PTR(ret); } -static int __devinit bcma_hcd_probe(struct bcma_device *dev) +static int bcma_hcd_probe(struct bcma_device *dev) { int err; u16 chipid_top; @@ -266,7 +265,7 @@ static int __devinit bcma_hcd_probe(struct bcma_device *dev) return err; } -static void __devexit bcma_hcd_remove(struct bcma_device *dev) +static void bcma_hcd_remove(struct bcma_device *dev) { struct bcma_hcd_device *usb_dev = bcma_get_drvdata(dev); struct platform_device *ohci_dev = usb_dev->ohci_dev; @@ -306,7 +305,7 @@ static int bcma_hcd_resume(struct bcma_device *dev) #define bcma_hcd_resume NULL #endif /* CONFIG_PM */ -static const struct bcma_device_id bcma_hcd_table[] __devinitconst = { +static const struct bcma_device_id bcma_hcd_table[] = { BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS), BCMA_CORETABLE_END }; @@ -316,7 +315,7 @@ static struct bcma_driver bcma_hcd_driver = { .name = KBUILD_MODNAME, .id_table = bcma_hcd_table, .probe = bcma_hcd_probe, - .remove = __devexit_p(bcma_hcd_remove), + .remove = bcma_hcd_remove, .shutdown = bcma_hcd_shutdown, .suspend = bcma_hcd_suspend, .resume = bcma_hcd_resume, diff --git a/drivers/usb/host/dwc_common_port/changes.txt b/drivers/usb/host/dwc_common_port/changes.txt index 6740702d07375a..f6839f92c2760d 100644 --- a/drivers/usb/host/dwc_common_port/changes.txt +++ b/drivers/usb/host/dwc_common_port/changes.txt @@ -1,174 +1,174 @@ - -dwc_read_reg32() and friends now take an additional parameter, a pointer to an -IO context struct. The IO context struct should live in an os-dependent struct -in your driver. As an example, the dwc_usb3 driver has an os-dependent struct -named 'os_dep' embedded in the main device struct. So there these calls look -like this: - - dwc_read_reg32(&usb3_dev->os_dep.ioctx, &pcd->dev_global_regs->dcfg); - - dwc_write_reg32(&usb3_dev->os_dep.ioctx, - &pcd->dev_global_regs->dcfg, 0); - -Note that for the existing Linux driver ports, it is not necessary to actually -define the 'ioctx' member in the os-dependent struct. Since Linux does not -require an IO context, its macros for dwc_read_reg32() and friends do not -use the context pointer, so it is optimized away by the compiler. But it is -necessary to add the pointer parameter to all of the call sites, to be ready -for any future ports (such as FreeBSD) which do require an IO context. - - -Similarly, dwc_alloc(), dwc_alloc_atomic(), dwc_strdup(), and dwc_free() now -take an additional parameter, a pointer to a memory context. Examples: - - addr = dwc_alloc(&usb3_dev->os_dep.memctx, size); - - dwc_free(&usb3_dev->os_dep.memctx, addr); - -Again, for the Linux ports, it is not necessary to actually define the memctx -member, but it is necessary to add the pointer parameter to all of the call -sites. - - -Same for dwc_dma_alloc() and dwc_dma_free(). Examples: - - virt_addr = dwc_dma_alloc(&usb3_dev->os_dep.dmactx, size, &phys_addr); - - dwc_dma_free(&usb3_dev->os_dep.dmactx, size, virt_addr, phys_addr); - - -Same for dwc_mutex_alloc() and dwc_mutex_free(). Examples: - - mutex = dwc_mutex_alloc(&usb3_dev->os_dep.mtxctx); - - dwc_mutex_free(&usb3_dev->os_dep.mtxctx, mutex); - - -Same for dwc_spinlock_alloc() and dwc_spinlock_free(). Examples: - - lock = dwc_spinlock_alloc(&usb3_dev->osdep.splctx); - - dwc_spinlock_free(&usb3_dev->osdep.splctx, lock); - - -Same for dwc_timer_alloc(). Example: - - timer = dwc_timer_alloc(&usb3_dev->os_dep.tmrctx, "dwc_usb3_tmr1", - cb_func, cb_data); - - -Same for dwc_waitq_alloc(). Example: - - waitq = dwc_waitq_alloc(&usb3_dev->os_dep.wtqctx); - - -Same for dwc_thread_run(). Example: - - thread = dwc_thread_run(&usb3_dev->os_dep.thdctx, func, - "dwc_usb3_thd1", data); - - -Same for dwc_workq_alloc(). Example: - - workq = dwc_workq_alloc(&usb3_dev->osdep.wkqctx, "dwc_usb3_wkq1"); - - -Same for dwc_task_alloc(). Example: - - task = dwc_task_alloc(&usb3_dev->os_dep.tskctx, "dwc_usb3_tsk1", - cb_func, cb_data); - - -In addition to the context pointer additions, a few core functions have had -other changes made to their parameters: - -The 'flags' parameter to dwc_spinlock_irqsave() and dwc_spinunlock_irqrestore() -has been changed from a uint64_t to a dwc_irqflags_t. - -dwc_thread_should_stop() now takes a 'dwc_thread_t *' parameter, because the -FreeBSD equivalent of that function requires it. - -And, in addition to the context pointer, dwc_task_alloc() also adds a -'char *name' parameter, to be consistent with dwc_thread_run() and -dwc_workq_alloc(), and because the FreeBSD equivalent of that function -requires a unique name. - - -Here is a complete list of the core functions that now take a pointer to a -context as their first parameter: - - dwc_read_reg32 - dwc_read_reg64 - dwc_write_reg32 - dwc_write_reg64 - dwc_modify_reg32 - dwc_modify_reg64 - dwc_alloc - dwc_alloc_atomic - dwc_strdup - dwc_free - dwc_dma_alloc - dwc_dma_free - dwc_mutex_alloc - dwc_mutex_free - dwc_spinlock_alloc - dwc_spinlock_free - dwc_timer_alloc - dwc_waitq_alloc - dwc_thread_run - dwc_workq_alloc - dwc_task_alloc Also adds a 'char *name' as its 2nd parameter - -And here are the core functions that have other changes to their parameters: - - dwc_spinlock_irqsave 'flags' param is now a 'dwc_irqflags_t *' - dwc_spinunlock_irqrestore 'flags' param is now a 'dwc_irqflags_t' - dwc_thread_should_stop Adds a 'dwc_thread_t *' parameter - - - -The changes to the core functions also require some of the other library -functions to change: - - dwc_cc_if_alloc() and dwc_cc_if_free() now take a 'void *memctx' - (for memory allocation) as the 1st param and a 'void *mtxctx' - (for mutex allocation) as the 2nd param. - - dwc_cc_clear(), dwc_cc_add(), dwc_cc_change(), dwc_cc_remove(), - dwc_cc_data_for_save(), and dwc_cc_restore_from_data() now take a - 'void *memctx' as the 1st param. - - dwc_dh_modpow(), dwc_dh_pk(), and dwc_dh_derive_keys() now take a - 'void *memctx' as the 1st param. - - dwc_modpow() now takes a 'void *memctx' as the 1st param. - - dwc_alloc_notification_manager() now takes a 'void *memctx' as the - 1st param and a 'void *wkqctx' (for work queue allocation) as the 2nd - param, and also now returns an integer value that is non-zero if - allocation of its data structures or work queue fails. - - dwc_register_notifier() now takes a 'void *memctx' as the 1st param. - - dwc_memory_debug_start() now takes a 'void *mem_ctx' as the first - param, and also now returns an integer value that is non-zero if - allocation of its data structures fails. - - - -Other miscellaneous changes: - -The DEBUG_MEMORY and DEBUG_REGS #define's have been renamed to -DWC_DEBUG_MEMORY and DWC_DEBUG_REGS. - -The following #define's have been added to allow selectively compiling library -features: - - DWC_CCLIB - DWC_CRYPTOLIB - DWC_NOTIFYLIB - DWC_UTFLIB - -A DWC_LIBMODULE #define has also been added. If this is not defined, then the -module code in dwc_common_linux.c is not compiled in. This allows linking the -library code directly into a driver module, instead of as a standalone module. + +dwc_read_reg32() and friends now take an additional parameter, a pointer to an +IO context struct. The IO context struct should live in an os-dependent struct +in your driver. As an example, the dwc_usb3 driver has an os-dependent struct +named 'os_dep' embedded in the main device struct. So there these calls look +like this: + + dwc_read_reg32(&usb3_dev->os_dep.ioctx, &pcd->dev_global_regs->dcfg); + + dwc_write_reg32(&usb3_dev->os_dep.ioctx, + &pcd->dev_global_regs->dcfg, 0); + +Note that for the existing Linux driver ports, it is not necessary to actually +define the 'ioctx' member in the os-dependent struct. Since Linux does not +require an IO context, its macros for dwc_read_reg32() and friends do not +use the context pointer, so it is optimized away by the compiler. But it is +necessary to add the pointer parameter to all of the call sites, to be ready +for any future ports (such as FreeBSD) which do require an IO context. + + +Similarly, dwc_alloc(), dwc_alloc_atomic(), dwc_strdup(), and dwc_free() now +take an additional parameter, a pointer to a memory context. Examples: + + addr = dwc_alloc(&usb3_dev->os_dep.memctx, size); + + dwc_free(&usb3_dev->os_dep.memctx, addr); + +Again, for the Linux ports, it is not necessary to actually define the memctx +member, but it is necessary to add the pointer parameter to all of the call +sites. + + +Same for dwc_dma_alloc() and dwc_dma_free(). Examples: + + virt_addr = dwc_dma_alloc(&usb3_dev->os_dep.dmactx, size, &phys_addr); + + dwc_dma_free(&usb3_dev->os_dep.dmactx, size, virt_addr, phys_addr); + + +Same for dwc_mutex_alloc() and dwc_mutex_free(). Examples: + + mutex = dwc_mutex_alloc(&usb3_dev->os_dep.mtxctx); + + dwc_mutex_free(&usb3_dev->os_dep.mtxctx, mutex); + + +Same for dwc_spinlock_alloc() and dwc_spinlock_free(). Examples: + + lock = dwc_spinlock_alloc(&usb3_dev->osdep.splctx); + + dwc_spinlock_free(&usb3_dev->osdep.splctx, lock); + + +Same for dwc_timer_alloc(). Example: + + timer = dwc_timer_alloc(&usb3_dev->os_dep.tmrctx, "dwc_usb3_tmr1", + cb_func, cb_data); + + +Same for dwc_waitq_alloc(). Example: + + waitq = dwc_waitq_alloc(&usb3_dev->os_dep.wtqctx); + + +Same for dwc_thread_run(). Example: + + thread = dwc_thread_run(&usb3_dev->os_dep.thdctx, func, + "dwc_usb3_thd1", data); + + +Same for dwc_workq_alloc(). Example: + + workq = dwc_workq_alloc(&usb3_dev->osdep.wkqctx, "dwc_usb3_wkq1"); + + +Same for dwc_task_alloc(). Example: + + task = dwc_task_alloc(&usb3_dev->os_dep.tskctx, "dwc_usb3_tsk1", + cb_func, cb_data); + + +In addition to the context pointer additions, a few core functions have had +other changes made to their parameters: + +The 'flags' parameter to dwc_spinlock_irqsave() and dwc_spinunlock_irqrestore() +has been changed from a uint64_t to a dwc_irqflags_t. + +dwc_thread_should_stop() now takes a 'dwc_thread_t *' parameter, because the +FreeBSD equivalent of that function requires it. + +And, in addition to the context pointer, dwc_task_alloc() also adds a +'char *name' parameter, to be consistent with dwc_thread_run() and +dwc_workq_alloc(), and because the FreeBSD equivalent of that function +requires a unique name. + + +Here is a complete list of the core functions that now take a pointer to a +context as their first parameter: + + dwc_read_reg32 + dwc_read_reg64 + dwc_write_reg32 + dwc_write_reg64 + dwc_modify_reg32 + dwc_modify_reg64 + dwc_alloc + dwc_alloc_atomic + dwc_strdup + dwc_free + dwc_dma_alloc + dwc_dma_free + dwc_mutex_alloc + dwc_mutex_free + dwc_spinlock_alloc + dwc_spinlock_free + dwc_timer_alloc + dwc_waitq_alloc + dwc_thread_run + dwc_workq_alloc + dwc_task_alloc Also adds a 'char *name' as its 2nd parameter + +And here are the core functions that have other changes to their parameters: + + dwc_spinlock_irqsave 'flags' param is now a 'dwc_irqflags_t *' + dwc_spinunlock_irqrestore 'flags' param is now a 'dwc_irqflags_t' + dwc_thread_should_stop Adds a 'dwc_thread_t *' parameter + + + +The changes to the core functions also require some of the other library +functions to change: + + dwc_cc_if_alloc() and dwc_cc_if_free() now take a 'void *memctx' + (for memory allocation) as the 1st param and a 'void *mtxctx' + (for mutex allocation) as the 2nd param. + + dwc_cc_clear(), dwc_cc_add(), dwc_cc_change(), dwc_cc_remove(), + dwc_cc_data_for_save(), and dwc_cc_restore_from_data() now take a + 'void *memctx' as the 1st param. + + dwc_dh_modpow(), dwc_dh_pk(), and dwc_dh_derive_keys() now take a + 'void *memctx' as the 1st param. + + dwc_modpow() now takes a 'void *memctx' as the 1st param. + + dwc_alloc_notification_manager() now takes a 'void *memctx' as the + 1st param and a 'void *wkqctx' (for work queue allocation) as the 2nd + param, and also now returns an integer value that is non-zero if + allocation of its data structures or work queue fails. + + dwc_register_notifier() now takes a 'void *memctx' as the 1st param. + + dwc_memory_debug_start() now takes a 'void *mem_ctx' as the first + param, and also now returns an integer value that is non-zero if + allocation of its data structures fails. + + + +Other miscellaneous changes: + +The DEBUG_MEMORY and DEBUG_REGS #define's have been renamed to +DWC_DEBUG_MEMORY and DWC_DEBUG_REGS. + +The following #define's have been added to allow selectively compiling library +features: + + DWC_CCLIB + DWC_CRYPTOLIB + DWC_NOTIFYLIB + DWC_UTFLIB + +A DWC_LIBMODULE #define has also been added. If this is not defined, then the +module code in dwc_common_linux.c is not compiled in. This allows linking the +library code directly into a driver module, instead of as a standalone module. diff --git a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c index b5a007d163ddc9..813168d7ef91af 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c +++ b/drivers/usb/host/dwc_otg/dwc_otg_cil_intr.c @@ -1350,7 +1350,9 @@ static inline uint32_t dwc_otg_read_common_intr(dwc_otg_core_if_t * core_if, gin // Re-enable the saved interrupts local_irq_save(flags); +#ifdef DWC_FIQ local_fiq_disable(); +#endif gintmsk.d32 |= gintmsk_common.d32; gintsts_saved.d32 &= ~gintmsk_common.d32; reenable_gintmsk->d32 = gintmsk.d32; diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c index b3e19444b9aca7..cfd3ab66417c0c 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c @@ -501,7 +501,6 @@ int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd, dwc_otg_transaction_type_e tr_type; dwc_otg_qtd_t *qtd; gintmsk_data_t intr_mask = {.d32 = 0 }; - hprt0_data_t hprt0 = { .d32 = 0 }; #ifdef DEBUG /* integrity checks (Broadcom) */ if (NULL == hcd->core_if) { @@ -516,16 +515,6 @@ int dwc_otg_hcd_urb_enqueue(dwc_otg_hcd_t * hcd, return -DWC_E_NO_DEVICE; } - /* Some core configurations cannot support LS traffic on a FS root port */ - if ((hcd->fops->speed(hcd, dwc_otg_urb->priv) == USB_SPEED_LOW) && - (hcd->core_if->hwcfg2.b.fs_phy_type == 1) && - (hcd->core_if->hwcfg2.b.hs_phy_type == 1)) { - hprt0.d32 = DWC_READ_REG32(hcd->core_if->host_if->hprt0); - if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_FULL_SPEED) { - return -DWC_E_NO_DEVICE; - } - } - qtd = dwc_otg_hcd_qtd_create(dwc_otg_urb, atomic_alloc); if (qtd == NULL) { DWC_ERROR("DWC OTG HCD URB Enqueue failed creating QTD\n"); @@ -758,9 +747,7 @@ static void completion_tasklet_func(void *ptr) DWC_FREE(item); usb_hcd_giveback_urb(hcd->priv, urb, urb->status); - fiq_print(FIQDBG_PORTHUB, "COMPLETE"); - DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags); } DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags); @@ -1345,13 +1332,14 @@ int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh) if(hcd->hub_port[hub_addr] & (1 << port_addr)) { fiq_print(FIQDBG_PORTHUB, "H%dP%d:S%02d", hub_addr, port_addr, qh->skip_count); - qh->skip_count++; if(qh->skip_count > 40000) { printk_once(KERN_ERR "Error: Having to skip port allocation"); +#ifdef DWC_FIQ local_fiq_disable(); +#endif BUG(); return 0; } @@ -1362,7 +1350,7 @@ int dwc_otg_hcd_allocate_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh) qh->skip_count = 0; hcd->hub_port[hub_addr] |= 1 << port_addr; fiq_print(FIQDBG_PORTHUB, "H%dP%d:A %d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num); -#ifdef FIQ_DEBUG +#if defined(DWC_FIQ) && defined(FIQ_DEBUG) hcd->hub_port_alloc[hub_addr * 16 + port_addr] = dwc_otg_hcd_get_frame_number(hcd); #endif return 0; @@ -1382,7 +1370,6 @@ void dwc_otg_hcd_release_port(dwc_otg_hcd_t * hcd, dwc_otg_qh_t *qh) hcd->hub_port_alloc[hub_addr * 16 + port_addr] = -1; #endif fiq_print(FIQDBG_PORTHUB, "H%dP%d:RO%d", hub_addr, port_addr, DWC_CIRCLEQ_FIRST(&qh->qtd_list)->urb->pipe_info.ep_num); - } diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c index 57092d2f2e879e..980e2ad523c6f6 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c @@ -38,8 +38,9 @@ #include #include +#ifdef DWC_FIQ #include - +#endif extern bool microframe_schedule; @@ -54,8 +55,13 @@ extern bool microframe_schedule; void * dummy_send; mphi_regs_t c_mphi_regs; volatile void *dwc_regs_base; -int fiq_done, int_done; +#ifdef DWC_FIQ +int fiq_done; +#endif +int int_done; +gintsts_data_t gintsts; +gintmsk_data_t gintmsk; gintsts_data_t gintsts_saved = {.d32 = 0}; hcint_data_t hcint_saved[MAX_EPS_CHANNELS]; hcintmsk_data_t hcintmsk_saved[MAX_EPS_CHANNELS]; @@ -74,6 +80,7 @@ int complete_sched[MAX_EPS_CHANNELS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, int split_start_frame[MAX_EPS_CHANNELS]; int queued_port[MAX_EPS_CHANNELS]; +#ifdef DWC_FIQ #ifdef FIQ_DEBUG char buffer[1000*16]; int wptr; @@ -101,6 +108,7 @@ void notrace _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...) } #endif + void notrace fiq_queue_request(int channel, int odd_frame) { hcchar_data_t hcchar = { .d32 = FIQ_READ(dwc_regs_base + 0x500 + (channel * 0x20) + 0x0) }; @@ -351,13 +359,13 @@ int notrace fiq_hcintr_handle(int channel, hfnum_data_t hfnum) return hcint_saved[channel].d32 == 0; } -gintsts_data_t gintsts; -gintmsk_data_t gintmsk; // triggered: The set of interrupts that were triggered // handled: The set of interrupts that have been handled (no IRQ is // required) // keep: The set of interrupts we want to keep unmasked even though we // want to trigger an IRQ to handle it (SOF and HCINTR) +//gintsts_data_t gintsts; +//gintmsk_data_t gintmsk; gintsts_data_t triggered, handled, keep; hfnum_data_t hfnum; @@ -489,6 +497,7 @@ void __attribute__ ((naked)) notrace dwc_otg_hcd_handle_fiq(void) "subs pc, lr, #4;" ); } +#endif //DWC_FIQ /** This function handles interrupts for the HCD. */ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) @@ -516,11 +525,15 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd) DWC_SPINLOCK(dwc_otg_hcd->lock); /* Check if HOST Mode */ if (dwc_otg_is_host_mode(core_if)) { +#ifdef DWC_FIQ local_fiq_disable(); +#endif gintmsk.d32 |= gintsts_saved.d32; gintsts.d32 |= gintsts_saved.d32; gintsts_saved.d32 = 0; +#ifdef DWC_FIQ local_fiq_enable(); +#endif if (!gintsts.d32) { goto exit_handler_routine; } @@ -742,9 +755,10 @@ int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd) } /* Clear interrupt */ - gintsts.b.sofintr = 1; - DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); - + if (!fiq_fix_enable) { + gintsts.b.sofintr = 1; + DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32); + } return 1; } @@ -1325,7 +1339,7 @@ static void release_channel(dwc_otg_hcd_t * hcd, int free_qtd; dwc_irqflags_t flags; dwc_spinlock_t *channel_lock = hcd->channel_lock; -#ifdef FIQ_DEBUG +#if defined(DWC_FIQ) && defined(FIQ_DEBUG) int endp = qtd->urb ? qtd->urb->pipe_info.ep_num : 0; #endif int hog_port = 0; @@ -1416,7 +1430,9 @@ static void release_channel(dwc_otg_hcd_t * hcd, DWC_SPINLOCK_IRQSAVE(channel_lock, &flags); hcd->available_host_channels++; +#ifdef DWC_FIQ fiq_print(FIQDBG_PORTHUB, "AHC = %d ", hcd->available_host_channels); +#endif DWC_SPINUNLOCK_IRQRESTORE(channel_lock, flags); } @@ -1857,7 +1873,8 @@ static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd, */ switch(dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) { case UE_BULK: - case UE_CONTROL: + //case UE_INTERRUPT: + //case UE_CONTROL: if (nak_holdoff_enable) hc->qh->nak_frame = dwc_otg_hcd_get_frame_number(hcd); } diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c index 2449ee02f26879..83d895b6ebcba2 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c +++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c @@ -51,7 +51,9 @@ #include #include #include +#ifdef DWC_FIQ #include +#endif #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) #include <../drivers/usb/core/hcd.h> @@ -392,6 +394,7 @@ static struct dwc_otg_hcd_function_ops hcd_fops = { .get_b_hnp_enable = _get_b_hnp_enable, }; +#ifdef DWC_FIQ static struct fiq_handler fh = { .name = "usb_fiq", }; @@ -400,6 +403,7 @@ struct fiq_stack_s { uint8_t stack[2048]; int magic2; } fiq_stack; +#endif extern mphi_regs_t c_mphi_regs; /** @@ -433,11 +437,12 @@ int hcd_init(dwc_bus_dev_t *_dev) pci_set_consistent_dma_mask(_dev, dmamask); #endif +#ifdef DWC_FIQ if (fiq_fix_enable) { // Set up fiq claim_fiq(&fh); - set_fiq_handler(__FIQ_Branch, 8); + set_fiq_handler(__FIQ_Branch, 4); memset(®s,0,sizeof(regs)); regs.ARM_r8 = (long)dwc_otg_hcd_handle_fiq; regs.ARM_r9 = (long)0; @@ -446,7 +451,7 @@ int hcd_init(dwc_bus_dev_t *_dev) fiq_stack.magic1 = 0xdeadbeef; fiq_stack.magic2 = 0xaa995566; } - +#endif /* * Allocate memory for the base HCD plus the DWC OTG HCD. * Initialize the base HCD. @@ -465,7 +470,7 @@ int hcd_init(dwc_bus_dev_t *_dev) } hcd->regs = otg_dev->os_dep.base; - +#ifdef DWC_FIQ if (fiq_fix_enable) { volatile extern void *dwc_regs_base; @@ -490,6 +495,7 @@ int hcd_init(dwc_bus_dev_t *_dev) // Enable FIQ interrupt from USB peripheral enable_fiq(INTERRUPT_VC_USB); } +#endif /* Initialize the DWC OTG HCD. */ dwc_otg_hcd = dwc_otg_hcd_alloc_hcd(); if (!dwc_otg_hcd) { diff --git a/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h index ca173797aac43f..fef86463da4a14 100755 --- a/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h +++ b/drivers/usb/host/dwc_otg/dwc_otg_mphi_fix.h @@ -37,7 +37,7 @@ typedef enum { } FIQDBG_T; void _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...); -#ifdef FIQ_DEBUG +#if defined(DWC_FIQ) && defined(FIQ_DEBUG) #define fiq_print _fiq_print #else #define fiq_print(x, y, ...) diff --git a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c index 903e6706ed50eb..a591d897cedbbf 100644 --- a/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c +++ b/drivers/usb/host/dwc_otg/dwc_otg_pcd_linux.c @@ -1284,12 +1284,8 @@ void pcd_remove(dwc_bus_dev_t *_dev) * @param driver The driver being registered * @param bind The bind function of gadget driver */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) -int usb_gadget_register_driver(struct usb_gadget_driver *driver) -#else -int usb_gadget_probe_driver(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) -#endif + +int usb_gadget_probe_driver(struct usb_gadget_driver *driver) { int retval; @@ -1297,11 +1293,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, driver->driver.name); if (!driver || driver->max_speed == USB_SPEED_UNKNOWN || -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) !driver->bind || -#else - !bind || -#endif !driver->unbind || !driver->disconnect || !driver->setup) { DWC_DEBUGPL(DBG_PCDV, "EINVAL\n"); return -EINVAL; @@ -1320,11 +1312,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, gadget_wrapper->gadget.dev.driver = &driver->driver; DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) - retval = driver->bind(&gadget_wrapper->gadget); -#else - retval = bind(&gadget_wrapper->gadget); -#endif + retval = driver->bind(&gadget_wrapper->gadget, gadget_wrapper->driver); if (retval) { DWC_ERROR("bind to driver %s --> error %d\n", driver->driver.name, retval); @@ -1336,11 +1324,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, driver->driver.name); return 0; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) -EXPORT_SYMBOL(usb_gadget_register_driver); -#else EXPORT_SYMBOL(usb_gadget_probe_driver); -#endif /** * This function unregisters a gadget driver diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index a47e2cffaaf84a..f3beac4d06b81f 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -53,18 +53,11 @@ static void atmel_stop_ehci(struct platform_device *pdev) static int ehci_atmel_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; /* registers start at offset 0x0 */ ehci->caps = hcd->regs; - retval = ehci_setup(hcd); - if (retval) - return retval; - - ehci_port_power(ehci, 0); - - return retval; + return ehci_setup(hcd); } static const struct hc_driver ehci_atmel_hc_driver = { @@ -104,7 +97,7 @@ static const struct hc_driver ehci_atmel_hc_driver = { static u64 at91_ehci_dma_mask = DMA_BIT_MASK(32); -static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev) +static int ehci_atmel_drv_probe(struct platform_device *pdev) { struct usb_hcd *hcd; const struct hc_driver *driver = &ehci_atmel_hc_driver; @@ -150,31 +143,23 @@ static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, - driver->description)) { - dev_dbg(&pdev->dev, "controller already in use\n"); - retval = -EBUSY; + hcd->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hcd->regs)) { + retval = PTR_ERR(hcd->regs); goto fail_request_resource; } - hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); - if (hcd->regs == NULL) { - dev_dbg(&pdev->dev, "error mapping memory\n"); - retval = -EFAULT; - goto fail_ioremap; - } - - iclk = clk_get(&pdev->dev, "ehci_clk"); + iclk = devm_clk_get(&pdev->dev, "ehci_clk"); if (IS_ERR(iclk)) { dev_err(&pdev->dev, "Error getting interface clock\n"); retval = -ENOENT; - goto fail_get_iclk; + goto fail_request_resource; } - fclk = clk_get(&pdev->dev, "uhpck"); + fclk = devm_clk_get(&pdev->dev, "uhpck"); if (IS_ERR(fclk)) { dev_err(&pdev->dev, "Error getting function clock\n"); retval = -ENOENT; - goto fail_get_fclk; + goto fail_request_resource; } atmel_start_ehci(pdev); @@ -187,13 +172,6 @@ static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev) fail_add_hcd: atmel_stop_ehci(pdev); - clk_put(fclk); -fail_get_fclk: - clk_put(iclk); -fail_get_iclk: - iounmap(hcd->regs); -fail_ioremap: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); fail_request_resource: usb_put_hcd(hcd); fail_create_hcd: @@ -203,19 +181,15 @@ static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev) return retval; } -static int __devexit ehci_atmel_drv_remove(struct platform_device *pdev) +static int ehci_atmel_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); ehci_shutdown(hcd); usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); atmel_stop_ehci(pdev); - clk_put(fclk); - clk_put(iclk); fclk = iclk = NULL; return 0; @@ -232,7 +206,7 @@ MODULE_DEVICE_TABLE(of, atmel_ehci_dt_ids); static struct platform_driver ehci_atmel_driver = { .probe = ehci_atmel_drv_probe, - .remove = __devexit_p(ehci_atmel_drv_remove), + .remove = ehci_atmel_drv_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = "atmel-ehci", diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index f0c00de035efff..70b496dc18a008 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -18,21 +18,6 @@ /* this file is part of ehci-hcd.c */ -#define ehci_dbg(ehci, fmt, args...) \ - dev_dbg (ehci_to_hcd(ehci)->self.controller , fmt , ## args ) -#define ehci_err(ehci, fmt, args...) \ - dev_err (ehci_to_hcd(ehci)->self.controller , fmt , ## args ) -#define ehci_info(ehci, fmt, args...) \ - dev_info (ehci_to_hcd(ehci)->self.controller , fmt , ## args ) -#define ehci_warn(ehci, fmt, args...) \ - dev_warn (ehci_to_hcd(ehci)->self.controller , fmt , ## args ) - -#ifdef VERBOSE_DEBUG -# define ehci_vdbg ehci_dbg -#else - static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {} -#endif - #ifdef DEBUG /* check the values in the HCSPARAMS register @@ -352,11 +337,6 @@ static int debug_async_open(struct inode *, struct file *); static int debug_periodic_open(struct inode *, struct file *); static int debug_registers_open(struct inode *, struct file *); static int debug_async_open(struct inode *, struct file *); -static ssize_t debug_lpm_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos); -static ssize_t debug_lpm_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos); -static int debug_lpm_close(struct inode *inode, struct file *file); static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*); static int debug_close(struct inode *, struct file *); @@ -382,14 +362,6 @@ static const struct file_operations debug_registers_fops = { .release = debug_close, .llseek = default_llseek, }; -static const struct file_operations debug_lpm_fops = { - .owner = THIS_MODULE, - .open = simple_open, - .read = debug_lpm_read, - .write = debug_lpm_write, - .release = debug_lpm_close, - .llseek = noop_llseek, -}; static struct dentry *ehci_debug_root; @@ -653,10 +625,8 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) seen [seen_count++].qh = p.qh; } else temp = 0; - if (p.qh) { - tag = Q_NEXT_TYPE(ehci, hw->hw_next); - p = p.qh->qh_next; - } + tag = Q_NEXT_TYPE(ehci, hw->hw_next); + p = p.qh->qh_next; break; case Q_TYPE_FSTN: temp = scnprintf (next, size, @@ -973,86 +943,6 @@ static int debug_registers_open(struct inode *inode, struct file *file) return file->private_data ? 0 : -ENOMEM; } -static int debug_lpm_close(struct inode *inode, struct file *file) -{ - return 0; -} - -static ssize_t debug_lpm_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - /* TODO: show lpm stats */ - return 0; -} - -static ssize_t debug_lpm_write(struct file *file, const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct usb_hcd *hcd; - struct ehci_hcd *ehci; - char buf[50]; - size_t len; - u32 temp; - unsigned long port; - u32 __iomem *portsc ; - u32 params; - - hcd = bus_to_hcd(file->private_data); - ehci = hcd_to_ehci(hcd); - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - buf[len] = '\0'; - if (len > 0 && buf[len - 1] == '\n') - buf[len - 1] = '\0'; - - if (strncmp(buf, "enable", 5) == 0) { - if (strict_strtoul(buf + 7, 10, &port)) - return -EINVAL; - params = ehci_readl(ehci, &ehci->caps->hcs_params); - if (port > HCS_N_PORTS(params)) { - ehci_dbg(ehci, "ERR: LPM on bad port %lu\n", port); - return -ENODEV; - } - portsc = &ehci->regs->port_status[port-1]; - temp = ehci_readl(ehci, portsc); - if (!(temp & PORT_DEV_ADDR)) { - ehci_dbg(ehci, "LPM: no device attached\n"); - return -ENODEV; - } - temp |= PORT_LPM; - ehci_writel(ehci, temp, portsc); - printk(KERN_INFO "force enable LPM for port %lu\n", port); - } else if (strncmp(buf, "hird=", 5) == 0) { - unsigned long hird; - if (strict_strtoul(buf + 5, 16, &hird)) - return -EINVAL; - printk(KERN_INFO "setting hird %s %lu\n", buf + 6, hird); - ehci->command = (ehci->command & ~CMD_HIRD) | (hird << 24); - ehci_writel(ehci, ehci->command, &ehci->regs->command); - } else if (strncmp(buf, "disable", 7) == 0) { - if (strict_strtoul(buf + 8, 10, &port)) - return -EINVAL; - params = ehci_readl(ehci, &ehci->caps->hcs_params); - if (port > HCS_N_PORTS(params)) { - ehci_dbg(ehci, "ERR: LPM off bad port %lu\n", port); - return -ENODEV; - } - portsc = &ehci->regs->port_status[port-1]; - temp = ehci_readl(ehci, portsc); - if (!(temp & PORT_DEV_ADDR)) { - ehci_dbg(ehci, "ERR: no device attached\n"); - return -ENODEV; - } - temp &= ~PORT_LPM; - ehci_writel(ehci, temp, portsc); - printk(KERN_INFO "disabled LPM for port %lu\n", port); - } else - return -EOPNOTSUPP; - return count; -} - static inline void create_debug_files (struct ehci_hcd *ehci) { struct usb_bus *bus = &ehci_to_hcd(ehci)->self; @@ -1073,10 +963,6 @@ static inline void create_debug_files (struct ehci_hcd *ehci) &debug_registers_fops)) goto file_error; - if (!debugfs_create_file("lpm", S_IRUGO|S_IWUSR, ehci->debug_dir, bus, - &debug_lpm_fops)) - goto file_error; - return; file_error: diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index b7451b29c5acba..d81d2fcbff1894 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -210,11 +210,11 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd, usb_put_hcd(hcd); } -static void ehci_fsl_setup_phy(struct usb_hcd *hcd, +static int ehci_fsl_setup_phy(struct usb_hcd *hcd, enum fsl_usb2_phy_modes phy_mode, unsigned int port_offset) { - u32 portsc, temp; + u32 portsc; struct ehci_hcd *ehci = hcd_to_ehci(hcd); void __iomem *non_ehci = hcd->regs; struct device *dev = hcd->self.controller; @@ -222,7 +222,7 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd, if (pdata->controller_ver < 0) { dev_warn(hcd->self.controller, "Could not get controller version\n"); - return; + return -ENODEV; } portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]); @@ -230,11 +230,17 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd, switch (phy_mode) { case FSL_USB2_PHY_ULPI: - if (pdata->controller_ver) { + if (pdata->have_sysif_regs && pdata->controller_ver) { /* controller version 1.6 or above */ - temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); - out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | - USB_CTRL_USB_EN | ULPI_PHY_CLK_SEL); + setbits32(non_ehci + FSL_SOC_USB_CTRL, + ULPI_PHY_CLK_SEL); + /* + * Due to controller issue of PHY_CLK_VALID in ULPI + * mode, we set USB_CTRL_USB_EN before checking + * PHY_CLK_VALID, otherwise PHY_CLK_VALID doesn't work. + */ + clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL, + UTMI_PHY_EN, USB_CTRL_USB_EN); } portsc |= PORT_PTS_ULPI; break; @@ -245,11 +251,9 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd, portsc |= PORT_PTS_PTW; /* fall through */ case FSL_USB2_PHY_UTMI: - if (pdata->controller_ver) { + if (pdata->have_sysif_regs && pdata->controller_ver) { /* controller version 1.6 or above */ - temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); - out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | - UTMI_PHY_EN | USB_CTRL_USB_EN); + setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN); mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to become stable - 10ms*/ } @@ -262,23 +266,34 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd, case FSL_USB2_PHY_NONE: break; } + + if (pdata->have_sysif_regs && pdata->controller_ver && + (phy_mode == FSL_USB2_PHY_ULPI)) { + /* check PHY_CLK_VALID to get phy clk valid */ + if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) & + PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) { + printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n"); + return -EINVAL; + } + } + ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); + + if (phy_mode != FSL_USB2_PHY_ULPI && pdata->have_sysif_regs) + setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN); + + return 0; } -static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) +static int ehci_fsl_usb_setup(struct ehci_hcd *ehci) { struct usb_hcd *hcd = ehci_to_hcd(ehci); struct fsl_usb2_platform_data *pdata; void __iomem *non_ehci = hcd->regs; - u32 temp; pdata = hcd->self.controller->platform_data; - /* Enable PHY interface in the control reg. */ if (pdata->have_sysif_regs) { - temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); - out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004); - /* * Turn on cache snooping hardware, since some PowerPC platforms * wholly rely on hardware to deal with cache coherent @@ -293,7 +308,8 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) if ((pdata->operating_mode == FSL_USB2_DR_HOST) || (pdata->operating_mode == FSL_USB2_DR_OTG)) - ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0); + if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0)) + return -EINVAL; if (pdata->operating_mode == FSL_USB2_MPH_HOST) { unsigned int chip, rev, svr; @@ -307,9 +323,12 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) ehci->has_fsl_port_bug = 1; if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) - ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0); + if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0)) + return -EINVAL; + if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) - ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1); + if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1)) + return -EINVAL; } if (pdata->have_sysif_regs) { @@ -322,13 +341,15 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) #endif out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); } + + return 0; } /* called after powerup, by probe or system-pm "wakeup" */ static int ehci_fsl_reinit(struct ehci_hcd *ehci) { - ehci_fsl_usb_setup(ehci); - ehci_port_power(ehci, 0); + if (ehci_fsl_usb_setup(ehci)) + return -EINVAL; return 0; } diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h index 88403684d10b4a..dbd292e9f0a7d5 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -61,4 +61,5 @@ #define PLL_RESET (1<<8) #define UTMI_PHY_EN (1<<9) #define ULPI_PHY_CLK_SEL (1<<10) +#define PHY_CLK_VALID (1<<17) #endif /* _EHCI_FSL_H */ diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c index 22ca45c079a422..5d75de9729b668 100644 --- a/drivers/usb/host/ehci-grlib.c +++ b/drivers/usb/host/ehci-grlib.c @@ -25,7 +25,7 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - +#include #include #include @@ -34,22 +34,6 @@ #define GRUSBHC_HCIVERSION 0x0100 /* Known value of cap. reg. HCIVERSION */ -/* called during probe() after chip reset completes */ -static int ehci_grlib_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; - - retval = ehci_setup(hcd); - if (retval) - return retval; - - ehci_port_power(ehci, 1); - - return retval; -} - - static const struct hc_driver ehci_grlib_hc_driver = { .description = hcd_name, .product_desc = "GRLIB GRUSBHC EHCI", @@ -64,7 +48,7 @@ static const struct hc_driver ehci_grlib_hc_driver = { /* * basic lifecycle operations */ - .reset = ehci_grlib_setup, + .reset = ehci_setup, .start = ehci_run, .stop = ehci_stop, .shutdown = ehci_shutdown, @@ -98,7 +82,7 @@ static const struct hc_driver ehci_grlib_hc_driver = { }; -static int __devinit ehci_hcd_grlib_probe(struct platform_device *op) +static int ehci_hcd_grlib_probe(struct platform_device *op) { struct device_node *dn = op->dev.of_node; struct usb_hcd *hcd; @@ -127,12 +111,6 @@ static int __devinit ehci_hcd_grlib_probe(struct platform_device *op) hcd->rsrc_start = res.start; hcd->rsrc_len = resource_size(&res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__); - rv = -EBUSY; - goto err_rmr; - } - irq = irq_of_parse_and_map(dn, 0); if (irq == NO_IRQ) { printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__); @@ -140,10 +118,9 @@ static int __devinit ehci_hcd_grlib_probe(struct platform_device *op) goto err_irq; } - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - printk(KERN_ERR "%s: ioremap failed\n", __FILE__); - rv = -ENOMEM; + hcd->regs = devm_ioremap_resource(&op->dev, &res); + if (IS_ERR(hcd->regs)) { + rv = PTR_ERR(hcd->regs); goto err_ioremap; } @@ -161,17 +138,13 @@ static int __devinit ehci_hcd_grlib_probe(struct platform_device *op) rv = usb_add_hcd(hcd, irq, 0); if (rv) - goto err_ehci; + goto err_ioremap; return 0; -err_ehci: - iounmap(hcd->regs); err_ioremap: irq_dispose_mapping(irq); err_irq: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err_rmr: usb_put_hcd(hcd); return rv; @@ -188,9 +161,7 @@ static int ehci_hcd_grlib_remove(struct platform_device *op) usb_remove_hcd(hcd); - iounmap(hcd->regs); irq_dispose_mapping(hcd->irq); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index b05c6865b610d6..83b5a1725924b9 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include @@ -75,10 +74,6 @@ static const char hcd_name [] = "ehci_hcd"; #undef VERBOSE_DEBUG #undef EHCI_URB_TRACE -#ifdef DEBUG -#define EHCI_STATS -#endif - /* magic numbers that can affect system performance */ #define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ #define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ @@ -108,19 +103,39 @@ static bool ignore_oc = 0; module_param (ignore_oc, bool, S_IRUGO); MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); -/* for link power management(LPM) feature */ -static unsigned int hird; -module_param(hird, int, S_IRUGO); -MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us"); - #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) /*-------------------------------------------------------------------------*/ #include "ehci.h" -#include "ehci-dbg.c" #include "pci-quirks.h" +/* + * The MosChip MCS9990 controller updates its microframe counter + * a little before the frame counter, and occasionally we will read + * the invalid intermediate value. Avoid problems by checking the + * microframe number (the low-order 3 bits); if they are 0 then + * re-read the register to get the correct value. + */ +static unsigned ehci_moschip_read_frame_index(struct ehci_hcd *ehci) +{ + unsigned uf; + + uf = ehci_readl(ehci, &ehci->regs->frame_index); + if (unlikely((uf & 7) == 0)) + uf = ehci_readl(ehci, &ehci->regs->frame_index); + return uf; +} + +static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci) +{ + if (ehci->frame_index_bug) + return ehci_moschip_read_frame_index(ehci); + return ehci_readl(ehci, &ehci->regs->frame_index); +} + +#include "ehci-dbg.c" + /*-------------------------------------------------------------------------*/ /* @@ -228,7 +243,7 @@ static int ehci_reset (struct ehci_hcd *ehci) /* If the EHCI debug controller is active, special care must be * taken before and after a host controller reset */ - if (ehci->debug && !dbgp_reset_prep()) + if (ehci->debug && !dbgp_reset_prep(ehci_to_hcd(ehci))) ehci->debug = NULL; command |= CMD_RESET; @@ -251,7 +266,7 @@ static int ehci_reset (struct ehci_hcd *ehci) tdi_reset (ehci); if (ehci->debug) - dbgp_external_startup(); + dbgp_external_startup(ehci_to_hcd(ehci)); ehci->port_c_suspend = ehci->suspended_ports = ehci->resuming_ports = 0; @@ -287,13 +302,13 @@ static void ehci_quiesce (struct ehci_hcd *ehci) static void end_unlink_async(struct ehci_hcd *ehci); static void unlink_empty_async(struct ehci_hcd *ehci); +static void unlink_empty_async_suspended(struct ehci_hcd *ehci); static void ehci_work(struct ehci_hcd *ehci); static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); #include "ehci-timer.c" #include "ehci-hub.c" -#include "ehci-lpm.c" #include "ehci-mem.c" #include "ehci-q.c" #include "ehci-sched.c" @@ -353,24 +368,6 @@ static void ehci_shutdown(struct usb_hcd *hcd) hrtimer_cancel(&ehci->hrtimer); } -static void ehci_port_power (struct ehci_hcd *ehci, int is_on) -{ - unsigned port; - - if (!HCS_PPC (ehci->hcs_params)) - return; - - ehci_dbg (ehci, "...power%s ports...\n", is_on ? "up" : "down"); - for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) - (void) ehci_hub_control(ehci_to_hcd(ehci), - is_on ? SetPortFeature : ClearPortFeature, - USB_PORT_FEAT_POWER, - port--, NULL, 0); - /* Flush those writes */ - ehci_readl(ehci, &ehci->regs->command); - msleep(20); -} - /*-------------------------------------------------------------------------*/ /* @@ -503,7 +500,7 @@ static int ehci_init(struct usb_hcd *hcd) /* controllers may cache some of the periodic schedule ... */ if (HCC_ISOC_CACHE(hcc_params)) // full frame cache - ehci->i_thresh = 2 + 8; + ehci->i_thresh = 0; else // N microframes cached ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); @@ -555,17 +552,6 @@ static int ehci_init(struct usb_hcd *hcd) temp &= ~(3 << 2); temp |= (EHCI_TUNE_FLS << 2); } - if (HCC_LPM(hcc_params)) { - /* support link power management EHCI 1.1 addendum */ - ehci_dbg(ehci, "support lpm\n"); - ehci->has_lpm = 1; - if (hird > 0xf) { - ehci_dbg(ehci, "hird %d invalid, use default 0", - hird); - hird = 0; - } - temp |= hird << 24; - } ehci->command = temp; /* Accept arbitrarily long scatter-gather lists */ @@ -660,7 +646,7 @@ static int ehci_run (struct usb_hcd *hcd) return 0; } -static int ehci_setup(struct usb_hcd *hcd) +int ehci_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval; @@ -684,13 +670,11 @@ static int ehci_setup(struct usb_hcd *hcd) if (retval) return retval; - if (ehci_is_TDI(ehci)) - tdi_reset(ehci); - ehci_reset(ehci); return 0; } +EXPORT_SYMBOL_GPL(ehci_setup); /*-------------------------------------------------------------------------*/ @@ -762,11 +746,9 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* guard against (alleged) silicon errata */ if (cmd & CMD_IAAD) ehci_dbg(ehci, "IAA with IAAD still set?\n"); - if (ehci->async_iaa) { + if (ehci->async_iaa) COUNT(ehci->stats.iaa); - end_unlink_async(ehci); - } else - ehci_dbg(ehci, "IAA with nothing unlinked?\n"); + end_unlink_async(ehci); } /* remote wakeup [4.3.1] */ @@ -811,6 +793,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) ehci->reset_done[i] = jiffies + msecs_to_jiffies(25); set_bit(i, &ehci->resuming_ports); ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); + usb_hcd_start_port_resume(&hcd->self, i); mod_timer(&hcd->rh_timer, ehci->reset_done[i]); } } @@ -1096,7 +1079,7 @@ static int ehci_get_frame (struct usb_hcd *hcd) /* These routines handle the generic parts of controller suspend/resume */ -static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup) +int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); @@ -1119,9 +1102,10 @@ static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup) return 0; } +EXPORT_SYMBOL_GPL(ehci_suspend); /* Returns 0 if power was preserved, 1 if power was lost */ -static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated) +int ehci_resume(struct usb_hcd *hcd, bool hibernated) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); @@ -1177,53 +1161,93 @@ static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated) ehci->rh_state = EHCI_RH_SUSPENDED; spin_unlock_irq(&ehci->lock); - /* here we "know" root ports should always stay powered */ - ehci_port_power(ehci, 1); - return 1; } +EXPORT_SYMBOL_GPL(ehci_resume); #endif /*-------------------------------------------------------------------------*/ /* - * The EHCI in ChipIdea HDRC cannot be a separate module or device, - * because its registers (and irq) are shared between host/gadget/otg - * functions and in order to facilitate role switching we cannot - * give the ehci driver exclusive access to those. + * Generic structure: This gets copied for platform drivers so that + * individual entries can be overridden as needed. */ -#ifndef CHIPIDEA_EHCI + +static const struct hc_driver ehci_hc_driver = { + .description = hcd_name, + .product_desc = "EHCI Host Controller", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* + * generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_MEMORY | HCD_USB2, + + /* + * basic lifecycle operations + */ + .reset = ehci_setup, + .start = ehci_run, + .stop = ehci_stop, + .shutdown = ehci_shutdown, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ehci_urb_enqueue, + .urb_dequeue = ehci_urb_dequeue, + .endpoint_disable = ehci_endpoint_disable, + .endpoint_reset = ehci_endpoint_reset, + .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, + + /* + * scheduling support + */ + .get_frame_number = ehci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, + .bus_suspend = ehci_bus_suspend, + .bus_resume = ehci_bus_resume, + .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, +}; + +void ehci_init_driver(struct hc_driver *drv, + const struct ehci_driver_overrides *over) +{ + /* Copy the generic table to drv and then apply the overrides */ + *drv = ehci_hc_driver; + + if (over) { + drv->hcd_priv_size += over->extra_priv_size; + if (over->reset) + drv->reset = over->reset; + } +} +EXPORT_SYMBOL_GPL(ehci_init_driver); + +/*-------------------------------------------------------------------------*/ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_AUTHOR (DRIVER_AUTHOR); MODULE_LICENSE ("GPL"); -#ifdef CONFIG_PCI -#include "ehci-pci.c" -#define PCI_DRIVER ehci_pci_driver -#endif - #ifdef CONFIG_USB_EHCI_FSL #include "ehci-fsl.c" #define PLATFORM_DRIVER ehci_fsl_driver #endif -#ifdef CONFIG_USB_EHCI_MXC -#include "ehci-mxc.c" -#define PLATFORM_DRIVER ehci_mxc_driver -#endif - #ifdef CONFIG_USB_EHCI_SH #include "ehci-sh.c" #define PLATFORM_DRIVER ehci_hcd_sh_driver #endif -#ifdef CONFIG_MIPS_ALCHEMY -#include "ehci-au1xxx.c" -#define PLATFORM_DRIVER ehci_hcd_au1xxx_driver -#endif - #ifdef CONFIG_USB_EHCI_HCD_OMAP #include "ehci-omap.c" #define PLATFORM_DRIVER ehci_hcd_omap_driver @@ -1249,11 +1273,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_orion_driver #endif -#ifdef CONFIG_ARCH_IXP4XX -#include "ehci-ixp4xx.c" -#define PLATFORM_DRIVER ixp4xx_ehci_driver -#endif - #ifdef CONFIG_USB_W90X900_EHCI #include "ehci-w90x900.c" #define PLATFORM_DRIVER ehci_hcd_w90x900_driver @@ -1269,11 +1288,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_octeon_driver #endif -#ifdef CONFIG_USB_CNS3XXX_EHCI -#include "ehci-cns3xxx.c" -#define PLATFORM_DRIVER cns3xxx_ehci_driver -#endif - #ifdef CONFIG_ARCH_VT8500 #include "ehci-vt8500.c" #define PLATFORM_DRIVER vt8500_ehci_driver @@ -1314,34 +1328,24 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_grlib_driver #endif -#ifdef CONFIG_CPU_XLR -#include "ehci-xls.c" -#define PLATFORM_DRIVER ehci_xls_driver -#endif - #ifdef CONFIG_USB_EHCI_MV #include "ehci-mv.c" #define PLATFORM_DRIVER ehci_mv_driver #endif -#ifdef CONFIG_MACH_LOONGSON1 -#include "ehci-ls1x.c" -#define PLATFORM_DRIVER ehci_ls1x_driver -#endif - #ifdef CONFIG_MIPS_SEAD3 #include "ehci-sead3.c" #define PLATFORM_DRIVER ehci_hcd_sead3_driver #endif -#ifdef CONFIG_USB_EHCI_HCD_PLATFORM -#include "ehci-platform.c" -#define PLATFORM_DRIVER ehci_platform_driver -#endif - -#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ - !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ - !defined(XILINX_OF_PLATFORM_DRIVER) +#if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \ + !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \ + !IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \ + !IS_ENABLED(CONFIG_USB_EHCI_MXC) && \ + !defined(PLATFORM_DRIVER) && \ + !defined(PS3_SYSTEM_BUS_DRIVER) && \ + !defined(OF_PLATFORM_DRIVER) && \ + !defined(XILINX_OF_PLATFORM_DRIVER) #error "missing bus glue for ehci-hcd" #endif @@ -1378,12 +1382,6 @@ static int __init ehci_hcd_init(void) goto clean0; #endif -#ifdef PCI_DRIVER - retval = pci_register_driver(&PCI_DRIVER); - if (retval < 0) - goto clean1; -#endif - #ifdef PS3_SYSTEM_BUS_DRIVER retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER); if (retval < 0) @@ -1415,10 +1413,6 @@ static int __init ehci_hcd_init(void) ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); clean2: #endif -#ifdef PCI_DRIVER - pci_unregister_driver(&PCI_DRIVER); -clean1: -#endif #ifdef PLATFORM_DRIVER platform_driver_unregister(&PLATFORM_DRIVER); clean0: @@ -1444,9 +1438,6 @@ static void __exit ehci_hcd_cleanup(void) #ifdef PLATFORM_DRIVER platform_driver_unregister(&PLATFORM_DRIVER); #endif -#ifdef PCI_DRIVER - pci_unregister_driver(&PCI_DRIVER); -#endif #ifdef PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); #endif @@ -1456,5 +1447,3 @@ static void __exit ehci_hcd_cleanup(void) clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); } module_exit(ehci_hcd_cleanup); - -#endif /* CHIPIDEA_EHCI */ diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index c7880223738a69..7d06e77f6c4fa0 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -56,6 +56,19 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci) if (!ehci->owned_ports) return; + /* Make sure the ports are powered */ + port = HCS_N_PORTS(ehci->hcs_params); + while (port--) { + if (test_bit(port, &ehci->owned_ports)) { + reg = &ehci->regs->port_status[port]; + status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; + if (!(status & PORT_POWER)) { + status |= PORT_POWER; + ehci_writel(ehci, status, reg); + } + } + } + /* Give the connections some time to appear */ msleep(20); @@ -315,7 +328,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) ehci->rh_state = EHCI_RH_SUSPENDED; end_unlink_async(ehci); - unlink_empty_async(ehci); + unlink_empty_async_suspended(ehci); ehci_handle_intr_unlinks(ehci); end_free_itds(ehci); @@ -353,10 +366,10 @@ static int ehci_bus_resume (struct usb_hcd *hcd) goto shutdown; if (unlikely(ehci->debug)) { - if (!dbgp_reset_prep()) + if (!dbgp_reset_prep(hcd)) ehci->debug = NULL; else - dbgp_external_startup(); + dbgp_external_startup(hcd); } /* Ideally and we've got a real resume here, and no port's power @@ -384,11 +397,24 @@ static int ehci_bus_resume (struct usb_hcd *hcd) ehci_writel(ehci, ehci->command, &ehci->regs->command); ehci->rh_state = EHCI_RH_RUNNING; - /* Some controller/firmware combinations need a delay during which - * they set up the port statuses. See Bugzilla #8190. */ - spin_unlock_irq(&ehci->lock); - msleep(8); - spin_lock_irq(&ehci->lock); + /* + * According to Bugzilla #8190, the port status for some controllers + * will be wrong without a delay. At their wrong status, the port + * is enabled, but not suspended neither resumed. + */ + i = HCS_N_PORTS(ehci->hcs_params); + while (i--) { + temp = ehci_readl(ehci, &ehci->regs->port_status[i]); + if ((temp & PORT_PE) && + !(temp & (PORT_SUSPEND | PORT_RESUME))) { + ehci_dbg(ehci, "Port status(0x%x) is wrong\n", temp); + spin_unlock_irq(&ehci->lock); + msleep(8); + spin_lock_irq(&ehci->lock); + break; + } + } + if (ehci->shutdown) goto shutdown; @@ -623,7 +649,11 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) status = STS_PCD; } } - /* FIXME autosuspend idle root hubs */ + + /* If a resume is in progress, make sure it can finish */ + if (ehci->resuming_ports) + mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(25)); + spin_unlock_irqrestore (&ehci->lock, flags); return status ? retval : 0; } @@ -764,11 +794,6 @@ static int ehci_hub_control ( status_reg); break; case USB_PORT_FEAT_C_CONNECTION: - if (ehci->has_lpm) { - /* clear PORTSC bits on disconnect */ - temp &= ~PORT_LPM; - temp &= ~PORT_DEV_ADDR; - } ehci_writel(ehci, temp | PORT_CSC, status_reg); break; case USB_PORT_FEAT_C_OVER_CURRENT: @@ -830,6 +855,7 @@ static int ehci_hub_control ( /* resume signaling for 20 msec */ ehci->reset_done[wIndex] = jiffies + msecs_to_jiffies(20); + usb_hcd_start_port_resume(&hcd->self, wIndex); /* check the port again */ mod_timer(&ehci_to_hcd(ehci)->rh_timer, ehci->reset_done[wIndex]); @@ -841,6 +867,7 @@ static int ehci_hub_control ( clear_bit(wIndex, &ehci->suspended_ports); set_bit(wIndex, &ehci->port_c_suspend); ehci->reset_done[wIndex] = 0; + usb_hcd_end_port_resume(&hcd->self, wIndex); /* stop resume signaling */ temp = ehci_readl(ehci, status_reg); @@ -929,6 +956,7 @@ static int ehci_hub_control ( ehci->reset_done[wIndex] = 0; if (temp & PORT_PE) set_bit(wIndex, &ehci->port_c_suspend); + usb_hcd_end_port_resume(&hcd->self, wIndex); } if (temp & PORT_OC) @@ -1088,8 +1116,7 @@ static int ehci_hub_control ( return retval; } -static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd, - int portnum) +static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); @@ -1098,8 +1125,7 @@ static void __maybe_unused ehci_relinquish_port(struct usb_hcd *hcd, set_owner(ehci, --portnum, PORT_OWNER); } -static int __maybe_unused ehci_port_handed_over(struct usb_hcd *hcd, - int portnum) +static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); u32 __iomem *reg; diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 17dd9e94001ec6..88a49c87e74848 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -53,7 +53,6 @@ static int ehci_msm_reset(struct usb_hcd *hcd) /* Disable streaming mode and select host mode */ writel(0x13, USB_USBMODE); - ehci_port_power(ehci, 1); return 0; } @@ -133,7 +132,7 @@ static int ehci_msm_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_ioremap(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENOMEM; @@ -145,17 +144,17 @@ static int ehci_msm_probe(struct platform_device *pdev) * powering up VBUS, mapping of registers address space and power * management. */ - phy = usb_get_phy(USB_PHY_TYPE_USB2); + phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(phy)) { dev_err(&pdev->dev, "unable to find transceiver\n"); ret = -ENODEV; - goto unmap; + goto put_hcd; } ret = otg_set_host(phy->otg, &hcd->self); if (ret < 0) { dev_err(&pdev->dev, "unable to register with transceiver\n"); - goto put_transceiver; + goto put_hcd; } device_init_wakeup(&pdev->dev, 1); @@ -168,17 +167,13 @@ static int ehci_msm_probe(struct platform_device *pdev) return 0; -put_transceiver: - usb_put_phy(phy); -unmap: - iounmap(hcd->regs); put_hcd: usb_put_hcd(hcd); return ret; } -static int __devexit ehci_msm_remove(struct platform_device *pdev) +static int ehci_msm_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); @@ -187,7 +182,6 @@ static int __devexit ehci_msm_remove(struct platform_device *pdev) pm_runtime_set_suspended(&pdev->dev); otg_set_host(phy->otg, NULL); - usb_put_phy(phy); usb_put_hcd(hcd); @@ -226,7 +220,7 @@ static const struct dev_pm_ops ehci_msm_dev_pm_ops = { static struct platform_driver ehci_msm_driver = { .probe = ehci_msm_probe, - .remove = __devexit_p(ehci_msm_remove), + .remove = ehci_msm_remove, .driver = { .name = "msm_hsusb_host", .pm = &ehci_msm_dev_pm_ops, diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index f6df1ccc961775..3065809546b159 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -43,7 +43,7 @@ static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv) unsigned int i; for (i = 0; i < ehci_mv->clknum; i++) - clk_enable(ehci_mv->clk[i]); + clk_prepare_enable(ehci_mv->clk[i]); } static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv) @@ -51,7 +51,7 @@ static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv) unsigned int i; for (i = 0; i < ehci_mv->clknum; i++) - clk_disable(ehci_mv->clk[i]); + clk_disable_unprepare(ehci_mv->clk[i]); } static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv) @@ -161,7 +161,7 @@ static int mv_ehci_probe(struct platform_device *pdev) return -ENOMEM; size = sizeof(*ehci_mv) + sizeof(struct clk *) * pdata->clknum; - ehci_mv = kzalloc(size, GFP_KERNEL); + ehci_mv = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); if (ehci_mv == NULL) { dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n"); retval = -ENOMEM; @@ -175,12 +175,12 @@ static int mv_ehci_probe(struct platform_device *pdev) ehci_mv->clknum = pdata->clknum; for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) { ehci_mv->clk[clk_i] = - clk_get(&pdev->dev, pdata->clkname[clk_i]); + devm_clk_get(&pdev->dev, pdata->clkname[clk_i]); if (IS_ERR(ehci_mv->clk[clk_i])) { dev_err(&pdev->dev, "error get clck \"%s\"\n", pdata->clkname[clk_i]); retval = PTR_ERR(ehci_mv->clk[clk_i]); - goto err_put_clk; + goto err_clear_drvdata; } } @@ -188,34 +188,36 @@ static int mv_ehci_probe(struct platform_device *pdev) if (r == NULL) { dev_err(&pdev->dev, "no phy I/O memory resource defined\n"); retval = -ENODEV; - goto err_put_clk; + goto err_clear_drvdata; } - ehci_mv->phy_regs = ioremap(r->start, resource_size(r)); + ehci_mv->phy_regs = devm_ioremap(&pdev->dev, r->start, + resource_size(r)); if (ehci_mv->phy_regs == 0) { dev_err(&pdev->dev, "failed to map phy I/O memory\n"); retval = -EFAULT; - goto err_put_clk; + goto err_clear_drvdata; } r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "capregs"); if (!r) { dev_err(&pdev->dev, "no I/O memory resource defined\n"); retval = -ENODEV; - goto err_iounmap_phyreg; + goto err_clear_drvdata; } - ehci_mv->cap_regs = ioremap(r->start, resource_size(r)); + ehci_mv->cap_regs = devm_ioremap(&pdev->dev, r->start, + resource_size(r)); if (ehci_mv->cap_regs == NULL) { dev_err(&pdev->dev, "failed to map I/O memory\n"); retval = -EFAULT; - goto err_iounmap_phyreg; + goto err_clear_drvdata; } retval = mv_ehci_enable(ehci_mv); if (retval) { dev_err(&pdev->dev, "init phy error %d\n", retval); - goto err_iounmap_capreg; + goto err_clear_drvdata; } offset = readl(ehci_mv->cap_regs) & CAPLENGTH_MASK; @@ -239,7 +241,7 @@ static int mv_ehci_probe(struct platform_device *pdev) ehci_mv->mode = pdata->mode; if (ehci_mv->mode == MV_USB_MODE_OTG) { #ifdef CONFIG_USB_OTG_UTILS - ehci_mv->otg = usb_get_phy(USB_PHY_TYPE_USB2); + ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(ehci_mv->otg)) { dev_err(&pdev->dev, "unable to find transceiver\n"); @@ -252,7 +254,7 @@ static int mv_ehci_probe(struct platform_device *pdev) dev_err(&pdev->dev, "unable to register with transceiver\n"); retval = -ENODEV; - goto err_put_transceiver; + goto err_disable_clk; } /* otg will enable clock before use as host */ mv_ehci_disable(ehci_mv); @@ -286,22 +288,10 @@ static int mv_ehci_probe(struct platform_device *pdev) err_set_vbus: if (pdata->set_vbus) pdata->set_vbus(0); -#ifdef CONFIG_USB_OTG_UTILS -err_put_transceiver: - if (!IS_ERR_OR_NULL(ehci_mv->otg)) - usb_put_phy(ehci_mv->otg); -#endif err_disable_clk: mv_ehci_disable(ehci_mv); -err_iounmap_capreg: - iounmap(ehci_mv->cap_regs); -err_iounmap_phyreg: - iounmap(ehci_mv->phy_regs); -err_put_clk: - for (clk_i--; clk_i >= 0; clk_i--) - clk_put(ehci_mv->clk[clk_i]); +err_clear_drvdata: platform_set_drvdata(pdev, NULL); - kfree(ehci_mv); err_put_hcd: usb_put_hcd(hcd); @@ -312,15 +302,12 @@ static int mv_ehci_remove(struct platform_device *pdev) { struct ehci_hcd_mv *ehci_mv = platform_get_drvdata(pdev); struct usb_hcd *hcd = ehci_mv->hcd; - int clk_i; if (hcd->rh_registered) usb_remove_hcd(hcd); - if (!IS_ERR_OR_NULL(ehci_mv->otg)) { + if (!IS_ERR_OR_NULL(ehci_mv->otg)) otg_set_host(ehci_mv->otg->otg, NULL); - usb_put_phy(ehci_mv->otg); - } if (ehci_mv->mode == MV_USB_MODE_HOST) { if (ehci_mv->pdata->set_vbus) @@ -329,15 +316,8 @@ static int mv_ehci_remove(struct platform_device *pdev) mv_ehci_disable(ehci_mv); } - iounmap(ehci_mv->cap_regs); - iounmap(ehci_mv->phy_regs); - - for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) - clk_put(ehci_mv->clk[clk_i]); - platform_set_drvdata(pdev, NULL); - kfree(ehci_mv); usb_put_hcd(hcd); return 0; diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index 34201372c85f57..e9301fb97eaa32 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -17,84 +17,38 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include #include #include #include #include #include #include +#include +#include -#include -#include +#include #include +#include "ehci.h" + +#define DRIVER_DESC "Freescale On-Chip EHCI Host driver" + +static const char hcd_name[] = "ehci-mxc"; + #define ULPI_VIEWPORT_OFFSET 0x170 struct ehci_mxc_priv { struct clk *usbclk, *ahbclk, *phyclk; - struct usb_hcd *hcd; }; -/* called during probe() after chip reset completes */ -static int ehci_mxc_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; +static struct hc_driver __read_mostly ehci_mxc_hc_driver; - hcd->has_tt = 1; - - retval = ehci_setup(hcd); - if (retval) - return retval; - - ehci_port_power(ehci, 0); - return 0; -} - -static const struct hc_driver ehci_mxc_hc_driver = { - .description = hcd_name, - .product_desc = "Freescale On-Chip EHCI Host Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_USB2 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .reset = ehci_mxc_setup, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, +static const struct ehci_driver_overrides ehci_mxc_overrides __initdata = { + .extra_priv_size = sizeof(struct ehci_mxc_priv), }; static int ehci_mxc_drv_probe(struct platform_device *pdev) @@ -103,7 +57,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) struct usb_hcd *hcd; struct resource *res; int irq, ret; - unsigned int flags; struct ehci_mxc_priv *priv; struct device *dev = &pdev->dev; struct ehci_hcd *ehci; @@ -121,44 +74,35 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) if (!hcd) return -ENOMEM; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - ret = -ENOMEM; - goto err_alloc; - } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "Found HC with no register addr. Check setup!\n"); ret = -ENODEV; - goto err_get_resource; + goto err_alloc; } hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - dev_dbg(dev, "controller already in use\n"); - ret = -EBUSY; - goto err_request_mem; + hcd->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hcd->regs)) { + ret = PTR_ERR(hcd->regs); + goto err_alloc; } - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - dev_err(dev, "error mapping memory\n"); - ret = -EFAULT; - goto err_ioremap; - } + hcd->has_tt = 1; + ehci = hcd_to_ehci(hcd); + priv = (struct ehci_mxc_priv *) ehci->priv; /* enable clocks */ - priv->usbclk = clk_get(dev, "ipg"); + priv->usbclk = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(priv->usbclk)) { ret = PTR_ERR(priv->usbclk); - goto err_clk; + goto err_alloc; } clk_prepare_enable(priv->usbclk); - priv->ahbclk = clk_get(dev, "ahb"); + priv->ahbclk = devm_clk_get(&pdev->dev, "ahb"); if (IS_ERR(priv->ahbclk)) { ret = PTR_ERR(priv->ahbclk); goto err_clk_ahb; @@ -166,7 +110,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) clk_prepare_enable(priv->ahbclk); /* "dr" device has its own clock on i.MX51 */ - priv->phyclk = clk_get(dev, "phy"); + priv->phyclk = devm_clk_get(&pdev->dev, "phy"); if (IS_ERR(priv->phyclk)) priv->phyclk = NULL; if (priv->phyclk) @@ -184,8 +128,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) mdelay(10); } - ehci = hcd_to_ehci(hcd); - /* EHCI registers start at offset 0x100 */ ehci->caps = hcd->regs + 0x100; ehci->regs = hcd->regs + 0x100 + @@ -213,55 +155,24 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) } } - priv->hcd = hcd; - platform_set_drvdata(pdev, priv); + platform_set_drvdata(pdev, hcd); ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) goto err_add; - if (pdata->otg) { - /* - * efikamx and efikasb have some hardware bug which is - * preventing usb to work unless CHRGVBUS is set. - * It's in violation of USB specs - */ - if (machine_is_mx51_efikamx() || machine_is_mx51_efikasb()) { - flags = usb_phy_io_read(pdata->otg, - ULPI_OTG_CTRL); - flags |= ULPI_OTG_CTRL_CHRGVBUS; - ret = usb_phy_io_write(pdata->otg, flags, - ULPI_OTG_CTRL); - if (ret) { - dev_err(dev, "unable to set CHRVBUS\n"); - goto err_add; - } - } - } - return 0; err_add: if (pdata && pdata->exit) pdata->exit(pdev); err_init: - if (priv->phyclk) { + if (priv->phyclk) clk_disable_unprepare(priv->phyclk); - clk_put(priv->phyclk); - } clk_disable_unprepare(priv->ahbclk); - clk_put(priv->ahbclk); err_clk_ahb: clk_disable_unprepare(priv->usbclk); - clk_put(priv->usbclk); -err_clk: - iounmap(hcd->regs); -err_ioremap: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err_request_mem: -err_get_resource: - kfree(priv); err_alloc: usb_put_hcd(hcd); return ret; @@ -270,8 +181,11 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) { struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data; - struct ehci_mxc_priv *priv = platform_get_drvdata(pdev); - struct usb_hcd *hcd = priv->hcd; + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + struct ehci_mxc_priv *priv = (struct ehci_mxc_priv *) ehci->priv; + + usb_remove_hcd(hcd); if (pdata && pdata->exit) pdata->exit(pdev); @@ -279,31 +193,20 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) if (pdata->otg) usb_phy_shutdown(pdata->otg); - usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); - platform_set_drvdata(pdev, NULL); - clk_disable_unprepare(priv->usbclk); - clk_put(priv->usbclk); clk_disable_unprepare(priv->ahbclk); - clk_put(priv->ahbclk); - if (priv->phyclk) { + if (priv->phyclk) clk_disable_unprepare(priv->phyclk); - clk_put(priv->phyclk); - } - - kfree(priv); + usb_put_hcd(hcd); + platform_set_drvdata(pdev, NULL); return 0; } static void ehci_mxc_drv_shutdown(struct platform_device *pdev) { - struct ehci_mxc_priv *priv = platform_get_drvdata(pdev); - struct usb_hcd *hcd = priv->hcd; + struct usb_hcd *hcd = platform_get_drvdata(pdev); if (hcd->driver->shutdown) hcd->driver->shutdown(hcd); @@ -313,9 +216,31 @@ MODULE_ALIAS("platform:mxc-ehci"); static struct platform_driver ehci_mxc_driver = { .probe = ehci_mxc_drv_probe, - .remove = __exit_p(ehci_mxc_drv_remove), + .remove = ehci_mxc_drv_remove, .shutdown = ehci_mxc_drv_shutdown, .driver = { .name = "mxc-ehci", }, }; + +static int __init ehci_mxc_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + + ehci_init_driver(&ehci_mxc_hc_driver, &ehci_mxc_overrides); + return platform_driver_register(&ehci_mxc_driver); +} +module_init(ehci_mxc_init); + +static void __exit ehci_mxc_cleanup(void) +{ + platform_driver_unregister(&ehci_mxc_driver); +} +module_exit(ehci_mxc_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Sascha Hauer"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c index ba26957abf4620..a89750fff4ff09 100644 --- a/drivers/usb/host/ehci-octeon.c +++ b/drivers/usb/host/ehci-octeon.c @@ -159,9 +159,6 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev) platform_set_drvdata(pdev, hcd); - /* root ports should always stay powered */ - ehci_port_power(ehci, 1); - return 0; err3: ehci_octeon_stop(); diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index d7fe287d067803..0555ee42d7cb18 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -39,12 +39,13 @@ #include #include #include -#include #include #include #include #include +#include + /* EHCI Register Set */ #define EHCI_INSNREG04 (0xA0) #define EHCI_INSNREG04_DISABLE_UNSUSPEND (1 << 5) @@ -106,7 +107,7 @@ static int omap_ehci_init(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); int rc; - struct ehci_hcd_omap_platform_data *pdata; + struct usbhs_omap_platform_data *pdata; pdata = hcd->self.controller->platform_data; @@ -146,14 +147,11 @@ static int omap_ehci_init(struct usb_hcd *hcd) gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1); } - /* root ports should always stay powered */ - ehci_port_power(ehci, 1); - return rc; } static void disable_put_regulator( - struct ehci_hcd_omap_platform_data *pdata) + struct usbhs_omap_platform_data *pdata) { int i; @@ -178,7 +176,7 @@ static void disable_put_regulator( static int ehci_hcd_omap_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct ehci_hcd_omap_platform_data *pdata = dev->platform_data; + struct usbhs_omap_platform_data *pdata = dev->platform_data; struct resource *res; struct usb_hcd *hcd; void __iomem *regs; @@ -290,7 +288,6 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct usb_hcd *hcd = dev_get_drvdata(dev); - struct ehci_hcd_omap_platform_data *pdata = dev->platform_data; usb_remove_hcd(hcd); disable_put_regulator(dev->platform_data); @@ -300,13 +297,6 @@ static int ehci_hcd_omap_remove(struct platform_device *pdev) pm_runtime_put_sync(dev); pm_runtime_disable(dev); - if (pdata->phy_reset) { - if (gpio_is_valid(pdata->reset_gpio_port[0])) - gpio_free(pdata->reset_gpio_port[0]); - - if (gpio_is_valid(pdata->reset_gpio_port[1])) - gpio_free(pdata->reset_gpio_port[1]); - } return 0; } @@ -374,7 +364,7 @@ static const struct hc_driver ehci_omap_hc_driver = { .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; -MODULE_ALIAS("platform:omap-ehci"); +MODULE_ALIAS("platform:ehci-omap"); MODULE_AUTHOR("Texas Instruments, Inc."); MODULE_AUTHOR("Felipe Balbi "); diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index 8892d3642cefcc..914a3ecfb5d361 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c @@ -13,7 +13,10 @@ #include #include #include -#include +#include +#include +#include +#include #define rdl(off) __raw_readl(hcd->regs + (off)) #define wrl(off, val) __raw_writel((val), hcd->regs + (off)) @@ -101,20 +104,6 @@ static void orion_usb_phy_v1_setup(struct usb_hcd *hcd) wrl(USB_MODE, 0x13); } -static int ehci_orion_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; - - retval = ehci_setup(hcd); - if (retval) - return retval; - - ehci_port_power(ehci, 0); - - return retval; -} - static const struct hc_driver ehci_orion_hc_driver = { .description = hcd_name, .product_desc = "Marvell Orion EHCI", @@ -129,7 +118,7 @@ static const struct hc_driver ehci_orion_hc_driver = { /* * basic lifecycle operations */ - .reset = ehci_orion_setup, + .reset = ehci_setup, .start = ehci_run, .stop = ehci_stop, .shutdown = ehci_shutdown, @@ -160,7 +149,7 @@ static const struct hc_driver ehci_orion_hc_driver = { .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; -static void __init +static void ehci_orion_conf_mbus_windows(struct usb_hcd *hcd, const struct mbus_dram_target_info *dram) { @@ -181,7 +170,9 @@ ehci_orion_conf_mbus_windows(struct usb_hcd *hcd, } } -static int __devinit ehci_orion_drv_probe(struct platform_device *pdev) +static u64 ehci_orion_dma_mask = DMA_BIT_MASK(32); + +static int ehci_orion_drv_probe(struct platform_device *pdev) { struct orion_ehci_data *pd = pdev->dev.platform_data; const struct mbus_dram_target_info *dram; @@ -191,13 +182,17 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev) struct clk *clk; void __iomem *regs; int irq, err; + enum orion_ehci_phy_ver phy_version; if (usb_disabled()) return -ENODEV; pr_debug("Initializing Orion-SoC USB Host Controller\n"); - irq = platform_get_irq(pdev, 0); + if (pdev->dev.of_node) + irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + else + irq = platform_get_irq(pdev, 0); if (irq <= 0) { dev_err(&pdev->dev, "Found HC with no IRQ. Check %s setup!\n", @@ -215,6 +210,14 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev) goto err1; } + /* + * Right now device-tree probed devices don't get dma_mask + * set. Since shared usb code relies on it, set it here for + * now. Once we have dma capability bindings this can go away. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &ehci_orion_dma_mask; + if (!request_mem_region(res->start, resource_size(res), ehci_orion_hc_driver.description)) { dev_dbg(&pdev->dev, "controller already in use\n"); @@ -262,7 +265,12 @@ static int __devinit ehci_orion_drv_probe(struct platform_device *pdev) /* * setup Orion USB controller. */ - switch (pd->phy_version) { + if (pdev->dev.of_node) + phy_version = EHCI_PHY_NA; + else + phy_version = pd->phy_version; + + switch (phy_version) { case EHCI_PHY_NA: /* dont change USB phy settings */ break; case EHCI_PHY_ORION: @@ -317,9 +325,19 @@ static int __exit ehci_orion_drv_remove(struct platform_device *pdev) MODULE_ALIAS("platform:orion-ehci"); +static const struct of_device_id ehci_orion_dt_ids[] = { + { .compatible = "marvell,orion-ehci", }, + {}, +}; +MODULE_DEVICE_TABLE(of, ehci_orion_dt_ids); + static struct platform_driver ehci_orion_driver = { .probe = ehci_orion_drv_probe, .remove = __exit_p(ehci_orion_drv_remove), .shutdown = usb_hcd_platform_shutdown, - .driver.name = "orion-ehci", + .driver = { + .name = "orion-ehci", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(ehci_orion_dt_ids), + }, }; diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 2cb7d370c4eff9..170b9399e09f34 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -18,9 +18,18 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#ifndef CONFIG_PCI -#error "This file is PCI bus glue. CONFIG_PCI must be defined." -#endif +#include +#include +#include +#include +#include + +#include "ehci.h" +#include "pci-quirks.h" + +#define DRIVER_DESC "EHCI PCI platform driver" + +static const char hcd_name[] = "ehci-pci"; /* defined here to avoid adding to pci_ids.h for single instance use */ #define PCI_DEVICE_ID_INTEL_CE4100_USB 0x2e70 @@ -103,7 +112,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) } break; case PCI_VENDOR_ID_INTEL: - ehci->fs_i_thresh = 1; if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB) hcd->has_tt = 1; break; @@ -192,6 +200,26 @@ static int ehci_pci_setup(struct usb_hcd *hcd) break; } + /* optional debug port, normally in the first BAR */ + temp = pci_find_capability(pdev, PCI_CAP_ID_DBG); + if (temp) { + pci_read_config_dword(pdev, temp, &temp); + temp >>= 16; + if (((temp >> 13) & 7) == 1) { + u32 hcs_params = ehci_readl(ehci, + &ehci->caps->hcs_params); + + temp &= 0x1fff; + ehci->debug = hcd->regs + temp; + temp = ehci_readl(ehci, &ehci->debug->control); + ehci_info(ehci, "debug port %d%s\n", + HCS_DEBUG_PORT(hcs_params), + (temp & DBGP_ENABLED) ? " IN USE" : ""); + if (!(temp & DBGP_ENABLED)) + ehci->debug = NULL; + } + } + retval = ehci_setup(hcd); if (retval) return retval; @@ -203,11 +231,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) break; case PCI_VENDOR_ID_INTEL: ehci->need_io_watchdog = 0; - if (pdev->device == 0x0806 || pdev->device == 0x0811 - || pdev->device == 0x0829) { - ehci_info(ehci, "disable lpm for langwell/penwell\n"); - ehci->has_lpm = 0; - } break; case PCI_VENDOR_ID_NVIDIA: switch (pdev->device) { @@ -217,8 +240,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) * devices with PPCD enabled. */ case 0x0d9d: - ehci_info(ehci, "disable lpm/ppcd for nvidia mcp89"); - ehci->has_lpm = 0; + ehci_info(ehci, "disable ppcd for nvidia mcp89\n"); ehci->has_ppcd = 0; ehci->command &= ~CMD_PPCEE; break; @@ -226,25 +248,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) break; } - /* optional debug port, normally in the first BAR */ - temp = pci_find_capability(pdev, 0x0a); - if (temp) { - pci_read_config_dword(pdev, temp, &temp); - temp >>= 16; - if ((temp & (3 << 13)) == (1 << 13)) { - temp &= 0x1fff; - ehci->debug = hcd->regs + temp; - temp = ehci_readl(ehci, &ehci->debug->control); - ehci_info(ehci, "debug port %d%s\n", - HCS_DEBUG_PORT(ehci->hcs_params), - (temp & DBGP_ENABLED) - ? " IN USE" - : ""); - if (!(temp & DBGP_ENABLED)) - ehci->debug = NULL; - } - } - /* at least the Genesys GL880S needs fixup here */ temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); temp &= 0x0f; @@ -304,7 +307,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) ehci_warn(ehci, "selective suspend/wakeup unavailable\n"); #endif - ehci_port_power(ehci, 1); retval = ehci_pci_reinit(ehci, pdev); done: return retval; @@ -323,18 +325,14 @@ static int ehci_pci_setup(struct usb_hcd *hcd) * Also they depend on separate root hub suspend/resume. */ -static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) -{ - return ehci_suspend(hcd, do_wakeup); -} - static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev) { return pdev->class == PCI_CLASS_SERIAL_USB_EHCI && pdev->vendor == PCI_VENDOR_ID_INTEL && (pdev->device == 0x1E26 || pdev->device == 0x8C2D || - pdev->device == 0x8C26); + pdev->device == 0x8C26 || + pdev->device == 0x9C26); } static void ehci_enable_xhci_companion(void) @@ -378,76 +376,17 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) (void) ehci_pci_reinit(ehci, pdev); return 0; } -#endif -static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int rc = 0; - - if (!udev->parent) /* udev is root hub itself, impossible */ - rc = -1; - /* we only support lpm device connected to root hub yet */ - if (ehci->has_lpm && !udev->parent->parent) { - rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum); - if (!rc) - rc = ehci_lpm_check(ehci, udev->portnum); - } - return rc; -} +#else -static const struct hc_driver ehci_pci_hc_driver = { - .description = hcd_name, - .product_desc = "EHCI Host Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), +#define ehci_suspend NULL +#define ehci_pci_resume NULL +#endif /* CONFIG_PM */ - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, +static struct hc_driver __read_mostly ehci_pci_hc_driver; - /* - * basic lifecycle operations - */ +static const struct ehci_driver_overrides pci_overrides __initdata = { .reset = ehci_pci_setup, - .start = ehci_run, -#ifdef CONFIG_PM - .pci_suspend = ehci_pci_suspend, - .pci_resume = ehci_pci_resume, -#endif - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - /* - * call back when device connected and addressed - */ - .update_device = ehci_update_device, - - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; /*-------------------------------------------------------------------------*/ @@ -480,3 +419,31 @@ static struct pci_driver ehci_pci_driver = { }, #endif }; + +static int __init ehci_pci_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + + ehci_init_driver(&ehci_pci_hc_driver, &pci_overrides); + + /* Entries for the PCI suspend/resume callbacks are special */ + ehci_pci_hc_driver.pci_suspend = ehci_suspend; + ehci_pci_hc_driver.pci_resume = ehci_pci_resume; + + return pci_register_driver(&ehci_pci_driver); +} +module_init(ehci_pci_init); + +static void __exit ehci_pci_cleanup(void) +{ + pci_unregister_driver(&ehci_pci_driver); +} +module_exit(ehci_pci_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("David Brownell"); +MODULE_AUTHOR("Alan Stern"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index 4b1d896d5a2214..ca7506390542bf 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -18,9 +18,22 @@ * * Licensed under the GNU/GPL. See COPYING for details. */ +#include +#include +#include +#include +#include #include +#include +#include #include +#include "ehci.h" + +#define DRIVER_DESC "EHCI generic platform driver" + +static const char hcd_name[] = "ehci-platform"; + static int ehci_platform_reset(struct usb_hcd *hcd) { struct platform_device *pdev = to_platform_device(hcd->self.controller); @@ -38,113 +51,94 @@ static int ehci_platform_reset(struct usb_hcd *hcd) if (retval) return retval; - if (pdata->port_power_on) - ehci_port_power(ehci, 1); - if (pdata->port_power_off) - ehci_port_power(ehci, 0); - + if (pdata->no_io_watchdog) + ehci->need_io_watchdog = 0; return 0; } -static const struct hc_driver ehci_platform_hc_driver = { - .description = hcd_name, - .product_desc = "Generic Platform EHCI Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), - - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, - - .reset = ehci_platform_reset, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - - .get_frame_number = ehci_get_frame, +static struct hc_driver __read_mostly ehci_platform_hc_driver; - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, -#if defined(CONFIG_PM) - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, -#endif - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, +static const struct ehci_driver_overrides platform_overrides __initdata = { + .reset = ehci_platform_reset, }; -static int __devinit ehci_platform_probe(struct platform_device *dev) +static int ehci_platform_probe(struct platform_device *dev) { struct usb_hcd *hcd; struct resource *res_mem; + struct usb_ehci_pdata *pdata = dev->dev.platform_data; int irq; int err = -ENOMEM; - BUG_ON(!dev->dev.platform_data); + if (!pdata) { + WARN_ON(1); + return -ENODEV; + } if (usb_disabled()) return -ENODEV; irq = platform_get_irq(dev, 0); if (irq < 0) { - pr_err("no irq provided"); + dev_err(&dev->dev, "no irq provided"); return irq; } res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res_mem) { - pr_err("no memory recourse provided"); + dev_err(&dev->dev, "no memory resource provided"); return -ENXIO; } + if (pdata->power_on) { + err = pdata->power_on(dev); + if (err < 0) + return err; + } + hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev, dev_name(&dev->dev)); - if (!hcd) - return -ENOMEM; + if (!hcd) { + err = -ENOMEM; + goto err_power; + } hcd->rsrc_start = res_mem->start; hcd->rsrc_len = resource_size(res_mem); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - pr_err("controller already in use"); - err = -EBUSY; + hcd->regs = devm_ioremap_resource(&dev->dev, res_mem); + if (IS_ERR(hcd->regs)) { + err = PTR_ERR(hcd->regs); goto err_put_hcd; } - - hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) - goto err_release_region; err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) - goto err_iounmap; + goto err_put_hcd; platform_set_drvdata(dev, hcd); return err; -err_iounmap: - iounmap(hcd->regs); -err_release_region: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err_put_hcd: usb_put_hcd(hcd); +err_power: + if (pdata->power_off) + pdata->power_off(dev); + return err; } -static int __devexit ehci_platform_remove(struct platform_device *dev) +static int ehci_platform_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); + struct usb_ehci_pdata *pdata = dev->dev.platform_data; usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); platform_set_drvdata(dev, NULL); + if (pdata->power_off) + pdata->power_off(dev); + return 0; } @@ -153,14 +147,32 @@ static int __devexit ehci_platform_remove(struct platform_device *dev) static int ehci_platform_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); + struct usb_ehci_pdata *pdata = dev->platform_data; + struct platform_device *pdev = + container_of(dev, struct platform_device, dev); bool do_wakeup = device_may_wakeup(dev); + int ret; + + ret = ehci_suspend(hcd, do_wakeup); + + if (pdata->power_suspend) + pdata->power_suspend(pdev); - return ehci_suspend(hcd, do_wakeup); + return ret; } static int ehci_platform_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); + struct usb_ehci_pdata *pdata = dev->platform_data; + struct platform_device *pdev = + container_of(dev, struct platform_device, dev); + + if (pdata->power_on) { + int err = pdata->power_on(pdev); + if (err < 0) + return err; + } ehci_resume(hcd, false); return 0; @@ -185,7 +197,7 @@ static const struct dev_pm_ops ehci_platform_pm_ops = { static struct platform_driver ehci_platform_driver = { .id_table = ehci_platform_table, .probe = ehci_platform_probe, - .remove = __devexit_p(ehci_platform_remove), + .remove = ehci_platform_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .owner = THIS_MODULE, @@ -193,3 +205,26 @@ static struct platform_driver ehci_platform_driver = { .pm = &ehci_platform_pm_ops, } }; + +static int __init ehci_platform_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + + ehci_init_driver(&ehci_platform_hc_driver, &platform_overrides); + return platform_driver_register(&ehci_platform_driver); +} +module_init(ehci_platform_init); + +static void __exit ehci_platform_cleanup(void) +{ + platform_driver_unregister(&ehci_platform_driver); +} +module_exit(ehci_platform_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Hauke Mehrtens"); +MODULE_AUTHOR("Alan Stern"); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c index 087aee2a904f0f..363890ee41d2bc 100644 --- a/drivers/usb/host/ehci-pmcmsp.c +++ b/drivers/usb/host/ehci-pmcmsp.c @@ -90,7 +90,6 @@ static int ehci_msp_setup(struct usb_hcd *hcd) return retval; usb_hcd_tdi_set_mode(ehci); - ehci_port_power(ehci, 0); return retval; } diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index bbbe89dfd886b8..56dc732bf4511e 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -12,6 +12,7 @@ * This file is licenced under the GPL. */ +#include #include #include @@ -71,7 +72,7 @@ static const struct hc_driver ehci_ppc_of_hc_driver = { * Fix: Enable Break Memory Transfer (BMT) in INSNREG3 */ #define PPC440EPX_EHCI0_INSREG_BMT (0x1 << 0) -static int __devinit +static int ppc44x_enable_bmt(struct device_node *dn) { __iomem u32 *insreg_virt; @@ -87,7 +88,7 @@ ppc44x_enable_bmt(struct device_node *dn) } -static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op) +static int ehci_hcd_ppc_of_probe(struct platform_device *op) { struct device_node *dn = op->dev.of_node; struct usb_hcd *hcd; @@ -114,12 +115,6 @@ static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op) hcd->rsrc_start = res.start; hcd->rsrc_len = resource_size(&res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__); - rv = -EBUSY; - goto err_rmr; - } - irq = irq_of_parse_and_map(dn, 0); if (irq == NO_IRQ) { printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__); @@ -127,10 +122,9 @@ static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op) goto err_irq; } - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - printk(KERN_ERR "%s: ioremap failed\n", __FILE__); - rv = -ENOMEM; + hcd->regs = devm_ioremap_resource(&op->dev, &res); + if (IS_ERR(hcd->regs)) { + rv = PTR_ERR(hcd->regs); goto err_ioremap; } @@ -139,8 +133,10 @@ static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op) if (np != NULL) { /* claim we really affected by usb23 erratum */ if (!of_address_to_resource(np, 0, &res)) - ehci->ohci_hcctrl_reg = ioremap(res.start + - OHCI_HCCTRL_OFFSET, OHCI_HCCTRL_LEN); + ehci->ohci_hcctrl_reg = + devm_ioremap(&op->dev, + res.start + OHCI_HCCTRL_OFFSET, + OHCI_HCCTRL_LEN); else pr_debug("%s: no ohci offset in fdt\n", __FILE__); if (!ehci->ohci_hcctrl_reg) { @@ -169,19 +165,13 @@ static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op) rv = usb_add_hcd(hcd, irq, 0); if (rv) - goto err_ehci; + goto err_ioremap; return 0; -err_ehci: - if (ehci->has_amcc_usb23) - iounmap(ehci->ohci_hcctrl_reg); - iounmap(hcd->regs); err_ioremap: irq_dispose_mapping(irq); err_irq: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err_rmr: usb_put_hcd(hcd); return rv; @@ -202,9 +192,7 @@ static int ehci_hcd_ppc_of_remove(struct platform_device *op) usb_remove_hcd(hcd); - iounmap(hcd->regs); irq_dispose_mapping(hcd->irq); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); /* use request_mem_region to test if the ohci driver is loaded. if so * ensure the ohci core is operational. @@ -222,8 +210,6 @@ static int ehci_hcd_ppc_of_remove(struct platform_device *op) pr_debug("%s: no ohci offset in fdt\n", __FILE__); of_node_put(np); } - - iounmap(ehci->ohci_hcctrl_reg); } usb_put_hcd(hcd); diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index 45a356e9f138a4..df5925a4f0dba9 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c @@ -93,7 +93,7 @@ static const struct hc_driver ps3_ehci_hc_driver = { .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; -static int __devinit ps3_ehci_probe(struct ps3_system_bus_device *dev) +static int ps3_ehci_probe(struct ps3_system_bus_device *dev) { int result; struct usb_hcd *hcd; diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 3d989028c8365e..23d13690428591 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -135,7 +135,7 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) * qtd is updated in qh_completions(). Update the QH * overlay here. */ - if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) { + if (qh->hw->hw_token & ACTIVE_BIT(ehci)) { qh->hw->hw_qtd_next = qtd->hw_next; qtd = NULL; } @@ -449,11 +449,19 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) else if (last_status == -EINPROGRESS && !urb->unlinked) continue; - /* qh unlinked; token in overlay may be most current */ - if (state == QH_STATE_IDLE - && cpu_to_hc32(ehci, qtd->qtd_dma) - == hw->hw_current) { + /* + * If this was the active qtd when the qh was unlinked + * and the overlay's token is active, then the overlay + * hasn't been written back to the qtd yet so use its + * token instead of the qtd's. After the qtd is + * processed and removed, the overlay won't be valid + * any more. + */ + if (state == QH_STATE_IDLE && + qh->qtd_list.next == &qtd->qtd_list && + (hw->hw_token & ACTIVE_BIT(ehci))) { token = hc32_to_cpu(ehci, hw->hw_token); + hw->hw_token &= ~ACTIVE_BIT(ehci); /* An unlink may leave an incomplete * async transaction in the TT buffer. @@ -1170,7 +1178,7 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh) struct ehci_qh *prev; /* Add to the end of the list of QHs waiting for the next IAAD */ - qh->qh_state = QH_STATE_UNLINK; + qh->qh_state = QH_STATE_UNLINK_WAIT; if (ehci->async_unlink) ehci->async_unlink_last->unlink_next = qh; else @@ -1197,17 +1205,36 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested) if (ehci->async_iaa || ehci->async_unlinking) return; - /* Do all the waiting QHs at once */ - ehci->async_iaa = ehci->async_unlink; - ehci->async_unlink = NULL; - /* If the controller isn't running, we don't have to wait for it */ if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) { + + /* Do all the waiting QHs */ + ehci->async_iaa = ehci->async_unlink; + ehci->async_unlink = NULL; + if (!nested) /* Avoid recursion */ end_unlink_async(ehci); /* Otherwise start a new IAA cycle */ } else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) { + struct ehci_qh *qh; + + /* Do only the first waiting QH (nVidia bug?) */ + qh = ehci->async_unlink; + + /* + * Intel (?) bug: The HC can write back the overlay region + * even after the IAA interrupt occurs. In self-defense, + * always go through two IAA cycles for each QH. + */ + if (qh->qh_state == QH_STATE_UNLINK_WAIT) { + qh->qh_state = QH_STATE_UNLINK; + } else { + ehci->async_iaa = qh; + ehci->async_unlink = qh->unlink_next; + qh->unlink_next = NULL; + } + /* Make sure the unlinks are all visible to the hardware */ wmb(); @@ -1255,39 +1282,53 @@ static void end_unlink_async(struct ehci_hcd *ehci) } } +static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh); + static void unlink_empty_async(struct ehci_hcd *ehci) { - struct ehci_qh *qh, *next; - bool stopped = (ehci->rh_state < EHCI_RH_RUNNING); + struct ehci_qh *qh; + struct ehci_qh *qh_to_unlink = NULL; bool check_unlinks_later = false; + int count = 0; - /* Unlink all the async QHs that have been empty for a timer cycle */ - next = ehci->async->qh_next.qh; - while (next) { - qh = next; - next = qh->qh_next.qh; - + /* Find the last async QH which has been empty for a timer cycle */ + for (qh = ehci->async->qh_next.qh; qh; qh = qh->qh_next.qh) { if (list_empty(&qh->qtd_list) && qh->qh_state == QH_STATE_LINKED) { - if (!stopped && qh->unlink_cycle == - ehci->async_unlink_cycle) + ++count; + if (qh->unlink_cycle == ehci->async_unlink_cycle) check_unlinks_later = true; else - single_unlink_async(ehci, qh); + qh_to_unlink = qh; } } - /* Start a new IAA cycle if any QHs are waiting for it */ - if (ehci->async_unlink) - start_iaa_cycle(ehci, false); + /* If nothing else is being unlinked, unlink the last empty QH */ + if (!ehci->async_iaa && !ehci->async_unlink && qh_to_unlink) { + start_unlink_async(ehci, qh_to_unlink); + --count; + } - /* QHs that haven't been empty for long enough will be handled later */ - if (check_unlinks_later) { + /* Other QHs will be handled later */ + if (count > 0) { ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true); ++ehci->async_unlink_cycle; } } +/* The root hub is suspended; unlink all the async QHs */ +static void unlink_empty_async_suspended(struct ehci_hcd *ehci) +{ + struct ehci_qh *qh; + + while (ehci->async->qh_next.qh) { + qh = ehci->async->qh_next.qh; + WARN_ON(!list_empty(&qh->qtd_list)); + single_unlink_async(ehci, qh); + } + start_iaa_cycle(ehci, false); +} + /* makes sure the async qh will become idle */ /* caller must own ehci->lock */ diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index 9d8f1dd57cb36a..20ebf6a8b7f473 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c @@ -16,7 +16,9 @@ #include #include #include -#include +#include +#include +#include #include #define EHCI_INSNREG00(base) (base + 0x90) @@ -32,6 +34,9 @@ struct s5p_ehci_hcd { struct device *dev; struct usb_hcd *hcd; struct clk *clk; + struct usb_phy *phy; + struct usb_otg *otg; + struct s5p_ehci_platdata *pdata; }; static const struct hc_driver s5p_ehci_hc_driver = { @@ -65,6 +70,26 @@ static const struct hc_driver s5p_ehci_hc_driver = { .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; +static void s5p_ehci_phy_enable(struct s5p_ehci_hcd *s5p_ehci) +{ + struct platform_device *pdev = to_platform_device(s5p_ehci->dev); + + if (s5p_ehci->phy) + usb_phy_init(s5p_ehci->phy); + else if (s5p_ehci->pdata->phy_init) + s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST); +} + +static void s5p_ehci_phy_disable(struct s5p_ehci_hcd *s5p_ehci) +{ + struct platform_device *pdev = to_platform_device(s5p_ehci->dev); + + if (s5p_ehci->phy) + usb_phy_shutdown(s5p_ehci->phy); + else if (s5p_ehci->pdata->phy_exit) + s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST); +} + static void s5p_setup_vbus_gpio(struct platform_device *pdev) { int err; @@ -85,22 +110,17 @@ static void s5p_setup_vbus_gpio(struct platform_device *pdev) static u64 ehci_s5p_dma_mask = DMA_BIT_MASK(32); -static int __devinit s5p_ehci_probe(struct platform_device *pdev) +static int s5p_ehci_probe(struct platform_device *pdev) { - struct s5p_ehci_platdata *pdata; + struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; struct s5p_ehci_hcd *s5p_ehci; struct usb_hcd *hcd; struct ehci_hcd *ehci; struct resource *res; + struct usb_phy *phy; int irq; int err; - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(&pdev->dev, "No platform data defined\n"); - return -EINVAL; - } - /* * Right now device-tree probed devices don't get dma_mask set. * Since shared usb code relies on it, set it here for now. @@ -118,6 +138,20 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) if (!s5p_ehci) return -ENOMEM; + phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); + if (IS_ERR_OR_NULL(phy)) { + /* Fallback to pdata */ + if (!pdata) { + dev_warn(&pdev->dev, "no platform data or transceiver defined\n"); + return -EPROBE_DEFER; + } else { + s5p_ehci->pdata = pdata; + } + } else { + s5p_ehci->phy = phy; + s5p_ehci->otg = phy->otg; + } + s5p_ehci->dev = &pdev->dev; hcd = usb_create_hcd(&s5p_ehci_hc_driver, &pdev->dev, @@ -128,7 +162,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) } s5p_ehci->hcd = hcd; - s5p_ehci->clk = clk_get(&pdev->dev, "usbhost"); + s5p_ehci->clk = devm_clk_get(&pdev->dev, "usbhost"); if (IS_ERR(s5p_ehci->clk)) { dev_err(&pdev->dev, "Failed to get usbhost clock\n"); @@ -136,9 +170,9 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) goto fail_clk; } - err = clk_enable(s5p_ehci->clk); + err = clk_prepare_enable(s5p_ehci->clk); if (err) - goto fail_clken; + goto fail_clk; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -163,8 +197,10 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) goto fail_io; } - if (pdata->phy_init) - pdata->phy_init(pdev, S5P_USB_PHY_HOST); + if (s5p_ehci->otg) + s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self); + + s5p_ehci_phy_enable(s5p_ehci); ehci = hcd_to_ehci(hcd); ehci->caps = hcd->regs; @@ -175,35 +211,35 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) { dev_err(&pdev->dev, "Failed to add USB HCD\n"); - goto fail_io; + goto fail_add_hcd; } platform_set_drvdata(pdev, s5p_ehci); return 0; +fail_add_hcd: + s5p_ehci_phy_disable(s5p_ehci); fail_io: - clk_disable(s5p_ehci->clk); -fail_clken: - clk_put(s5p_ehci->clk); + clk_disable_unprepare(s5p_ehci->clk); fail_clk: usb_put_hcd(hcd); return err; } -static int __devexit s5p_ehci_remove(struct platform_device *pdev) +static int s5p_ehci_remove(struct platform_device *pdev) { - struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev); struct usb_hcd *hcd = s5p_ehci->hcd; usb_remove_hcd(hcd); - if (pdata && pdata->phy_exit) - pdata->phy_exit(pdev, S5P_USB_PHY_HOST); + if (s5p_ehci->otg) + s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self); + + s5p_ehci_phy_disable(s5p_ehci); - clk_disable(s5p_ehci->clk); - clk_put(s5p_ehci->clk); + clk_disable_unprepare(s5p_ehci->clk); usb_put_hcd(hcd); @@ -225,16 +261,16 @@ static int s5p_ehci_suspend(struct device *dev) struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev); struct usb_hcd *hcd = s5p_ehci->hcd; bool do_wakeup = device_may_wakeup(dev); - struct platform_device *pdev = to_platform_device(dev); - struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; int rc; rc = ehci_suspend(hcd, do_wakeup); - if (pdata && pdata->phy_exit) - pdata->phy_exit(pdev, S5P_USB_PHY_HOST); + if (s5p_ehci->otg) + s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self); - clk_disable(s5p_ehci->clk); + s5p_ehci_phy_disable(s5p_ehci); + + clk_disable_unprepare(s5p_ehci->clk); return rc; } @@ -243,13 +279,13 @@ static int s5p_ehci_resume(struct device *dev) { struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev); struct usb_hcd *hcd = s5p_ehci->hcd; - struct platform_device *pdev = to_platform_device(dev); - struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; - clk_enable(s5p_ehci->clk); + clk_prepare_enable(s5p_ehci->clk); + + if (s5p_ehci->otg) + s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self); - if (pdata && pdata->phy_init) - pdata->phy_init(pdev, S5P_USB_PHY_HOST); + s5p_ehci_phy_enable(s5p_ehci); /* DMA burst Enable */ writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); @@ -269,7 +305,7 @@ static const struct dev_pm_ops s5p_ehci_pm_ops = { #ifdef CONFIG_OF static const struct of_device_id exynos_ehci_match[] = { - { .compatible = "samsung,exynos-ehci" }, + { .compatible = "samsung,exynos4210-ehci" }, {}, }; MODULE_DEVICE_TABLE(of, exynos_ehci_match); @@ -277,7 +313,7 @@ MODULE_DEVICE_TABLE(of, exynos_ehci_match); static struct platform_driver s5p_ehci_driver = { .probe = s5p_ehci_probe, - .remove = __devexit_p(s5p_ehci_remove), + .remove = s5p_ehci_remove, .shutdown = s5p_ehci_shutdown, .driver = { .name = "s5p-ehci", diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 528a54068a460f..5a00ef3a7bbacb 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -36,29 +36,6 @@ static int ehci_get_frame (struct usb_hcd *hcd); -#ifdef CONFIG_PCI - -static unsigned ehci_read_frame_index(struct ehci_hcd *ehci) -{ - unsigned uf; - - /* - * The MosChip MCS9990 controller updates its microframe counter - * a little before the frame counter, and occasionally we will read - * the invalid intermediate value. Avoid problems by checking the - * microframe number (the low-order 3 bits); if they are 0 then - * re-read the register to get the correct value. - */ - uf = ehci_readl(ehci, &ehci->regs->frame_index); - if (unlikely(ehci->frame_index_bug && ((uf & 7) == 0))) - uf = ehci_readl(ehci, &ehci->regs->frame_index); - return uf; -} - -#endif - -/*-------------------------------------------------------------------------*/ - /* * periodic_next_shadow - return "next" pointer on shadow list * @periodic: host pointer to qh/itd/sitd @@ -1237,6 +1214,7 @@ itd_urb_transaction ( memset (itd, 0, sizeof *itd); itd->itd_dma = itd_dma; + itd->frame = 9999; /* an invalid value */ list_add (&itd->itd_list, &sched->td_list); } spin_unlock_irqrestore (&ehci->lock, flags); @@ -1361,7 +1339,7 @@ sitd_slot_ok ( * given EHCI_TUNE_FLS and the slop). Or, write a smarter scheduler! */ -#define SCHEDULE_SLOP 80 /* microframes */ +#define SCHEDULING_DELAY 40 /* microframes */ static int iso_stream_schedule ( @@ -1370,7 +1348,7 @@ iso_stream_schedule ( struct ehci_iso_stream *stream ) { - u32 now, next, start, period, span; + u32 now, base, next, start, period, span; int status; unsigned mod = ehci->periodic_size << 3; struct ehci_iso_sched *sched = urb->hcpriv; @@ -1382,62 +1360,72 @@ iso_stream_schedule ( span <<= 3; } - if (span > mod - SCHEDULE_SLOP) { - ehci_dbg (ehci, "iso request %p too long\n", urb); - status = -EFBIG; - goto fail; - } - now = ehci_read_frame_index(ehci) & (mod - 1); /* Typical case: reuse current schedule, stream is still active. * Hopefully there are no gaps from the host falling behind - * (irq delays etc), but if there are we'll take the next - * slot in the schedule, implicitly assuming URB_ISO_ASAP. + * (irq delays etc). If there are, the behavior depends on + * whether URB_ISO_ASAP is set. */ if (likely (!list_empty (&stream->td_list))) { - u32 excess; - /* For high speed devices, allow scheduling within the - * isochronous scheduling threshold. For full speed devices - * and Intel PCI-based controllers, don't (work around for - * Intel ICH9 bug). - */ - if (!stream->highspeed && ehci->fs_i_thresh) - next = now + ehci->i_thresh; + /* Take the isochronous scheduling threshold into account */ + if (ehci->i_thresh) + next = now + ehci->i_thresh; /* uframe cache */ else - next = now; + next = (now + 2 + 7) & ~0x07; /* full frame cache */ - /* Fell behind (by up to twice the slop amount)? - * We decide based on the time of the last currently-scheduled - * slot, not the time of the next available slot. + /* + * Use ehci->last_iso_frame as the base. There can't be any + * TDs scheduled for earlier than that. */ - excess = (stream->next_uframe - period - next) & (mod - 1); - if (excess >= mod - 2 * SCHEDULE_SLOP) - start = next + excess - mod + period * - DIV_ROUND_UP(mod - excess, period); - else - start = next + excess + period; - if (start - now >= mod) { - ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n", - urb, start - now - period, period, - mod); - status = -EFBIG; + base = ehci->last_iso_frame << 3; + next = (next - base) & (mod - 1); + start = (stream->next_uframe - base) & (mod - 1); + + /* Is the schedule already full? */ + if (unlikely(start < period)) { + ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n", + urb, stream->next_uframe, base, + period, mod); + status = -ENOSPC; goto fail; } + + /* Behind the scheduling threshold? */ + if (unlikely(start < next)) { + + /* USB_ISO_ASAP: Round up to the first available slot */ + if (urb->transfer_flags & URB_ISO_ASAP) + start += (next - start + period - 1) & -period; + + /* + * Not ASAP: Use the next slot in the stream. If + * the entire URB falls before the threshold, fail. + */ + else if (start + span - period < next) { + ehci_dbg(ehci, "iso urb late %p (%u+%u < %u)\n", + urb, start + base, + span - period, next + base); + status = -EXDEV; + goto fail; + } + } + + start += base; } /* need to schedule; when's the next (u)frame we could start? * this is bigger than ehci->i_thresh allows; scheduling itself - * isn't free, the slop should handle reasonably slow cpus. it + * isn't free, the delay should handle reasonably slow cpus. it * can also help high bandwidth if the dma and irq loads don't * jump until after the queue is primed. */ else { int done = 0; - start = SCHEDULE_SLOP + (now & ~0x07); - /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ + base = now & ~0x07; + start = base + SCHEDULING_DELAY; /* find a uframe slot with enough bandwidth. * Early uframes are more precious because full-speed @@ -1464,19 +1452,16 @@ iso_stream_schedule ( /* no room in the schedule */ if (!done) { - ehci_dbg(ehci, "iso resched full %p (now %d max %d)\n", - urb, now, now + mod); + ehci_dbg(ehci, "iso sched full %p", urb); status = -ENOSPC; goto fail; } } /* Tried to schedule too far into the future? */ - if (unlikely(start - now + span - period - >= mod - 2 * SCHEDULE_SLOP)) { - ehci_dbg(ehci, "request %p would overflow (%d+%d >= %d)\n", - urb, start - now, span - period, - mod - 2 * SCHEDULE_SLOP); + if (unlikely(start - base + span - period >= mod)) { + ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n", + urb, start - base, span - period, mod); status = -EFBIG; goto fail; } @@ -1490,7 +1475,7 @@ iso_stream_schedule ( /* Make sure scan_isoc() sees these */ if (ehci->isoc_count == 0) - ehci->next_frame = now >> 3; + ehci->last_iso_frame = now >> 3; return 0; fail: @@ -1708,7 +1693,7 @@ static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd) urb->actual_length += desc->actual_length; } else { /* URB was too late */ - desc->status = -EXDEV; + urb->error_count++; } } @@ -1931,6 +1916,7 @@ sitd_urb_transaction ( memset (sitd, 0, sizeof *sitd); sitd->sitd_dma = sitd_dma; + sitd->frame = 9999; /* an invalid value */ list_add (&sitd->sitd_list, &iso_sched->td_list); } @@ -2081,7 +2067,7 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd) t = hc32_to_cpup(ehci, &sitd->hw_results); /* report transfer status */ - if (t & SITD_ERRS) { + if (unlikely(t & SITD_ERRS)) { urb->error_count++; if (t & SITD_STS_DBE) desc->status = usb_pipein (urb->pipe) @@ -2091,6 +2077,9 @@ static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd) desc->status = -EOVERFLOW; else /* XACT, MMF, etc */ desc->status = -EPROTO; + } else if (unlikely(t & SITD_STS_ACTIVE)) { + /* URB was too late */ + urb->error_count++; } else { desc->status = 0; desc->actual_length = desc->length - SITD_LENGTH(t); @@ -2220,12 +2209,12 @@ static void scan_isoc(struct ehci_hcd *ehci) now_frame = (uf >> 3) & fmask; live = true; } else { - now_frame = (ehci->next_frame - 1) & fmask; + now_frame = (ehci->last_iso_frame - 1) & fmask; live = false; } ehci->now_frame = now_frame; - frame = ehci->next_frame; + frame = ehci->last_iso_frame; for (;;) { union ehci_shadow q, *q_p; __hc32 type, *hw_p; @@ -2334,7 +2323,9 @@ static void scan_isoc(struct ehci_hcd *ehci) /* Stop when we have reached the current frame */ if (frame == now_frame) break; + + /* The last frame may still have active siTDs */ + ehci->last_iso_frame = frame; frame = (frame + 1) & fmask; } - ehci->next_frame = now_frame; } diff --git a/drivers/usb/host/ehci-sead3.c b/drivers/usb/host/ehci-sead3.c index 0c9e43cfaff547..f55477c5a1be00 100644 --- a/drivers/usb/host/ehci-sead3.c +++ b/drivers/usb/host/ehci-sead3.c @@ -19,6 +19,7 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include static int ehci_sead3_setup(struct usb_hcd *hcd) @@ -112,19 +113,12 @@ static int ehci_hcd_sead3_drv_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - pr_debug("request_mem_region failed"); - ret = -EBUSY; + hcd->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hcd->regs)) { + ret = PTR_ERR(hcd->regs); goto err1; } - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - pr_debug("ioremap failed"); - ret = -ENOMEM; - goto err2; - } - /* Root hub has integrated TT. */ hcd->has_tt = 1; @@ -135,9 +129,6 @@ static int ehci_hcd_sead3_drv_probe(struct platform_device *pdev) return ret; } - iounmap(hcd->regs); -err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err1: usb_put_hcd(hcd); return ret; @@ -148,8 +139,6 @@ static int ehci_hcd_sead3_drv_remove(struct platform_device *pdev) struct usb_hcd *hcd = platform_get_drvdata(pdev); usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); platform_set_drvdata(pdev, NULL); diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index b3f1e3650da0a4..3565a300f40134 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c @@ -21,17 +21,10 @@ struct ehci_sh_priv { static int ehci_sh_reset(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int ret; ehci->caps = hcd->regs; - ret = ehci_setup(hcd); - if (unlikely(ret)) - return ret; - - ehci_port_power(ehci, 0); - - return ret; + return ehci_setup(hcd); } static const struct hc_driver ehci_sh_hc_driver = { @@ -125,33 +118,26 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, - driver->description)) { - dev_dbg(&pdev->dev, "controller already in use\n"); - ret = -EBUSY; + hcd->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hcd->regs)) { + ret = PTR_ERR(hcd->regs); goto fail_request_resource; } - hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); - if (hcd->regs == NULL) { - dev_dbg(&pdev->dev, "error mapping memory\n"); - ret = -ENXIO; - goto fail_ioremap; - } - - priv = kmalloc(sizeof(struct ehci_sh_priv), GFP_KERNEL); + priv = devm_kzalloc(&pdev->dev, sizeof(struct ehci_sh_priv), + GFP_KERNEL); if (!priv) { dev_dbg(&pdev->dev, "error allocating priv data\n"); ret = -ENOMEM; - goto fail_alloc; + goto fail_request_resource; } /* These are optional, we don't care if they fail */ - priv->fclk = clk_get(&pdev->dev, "usb_fck"); + priv->fclk = devm_clk_get(&pdev->dev, "usb_fck"); if (IS_ERR(priv->fclk)) priv->fclk = NULL; - priv->iclk = clk_get(&pdev->dev, "usb_ick"); + priv->iclk = devm_clk_get(&pdev->dev, "usb_ick"); if (IS_ERR(priv->iclk)) priv->iclk = NULL; @@ -176,14 +162,6 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev) clk_disable(priv->iclk); clk_disable(priv->fclk); - clk_put(priv->iclk); - clk_put(priv->fclk); - - kfree(priv); -fail_alloc: - iounmap(hcd->regs); -fail_ioremap: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); fail_request_resource: usb_put_hcd(hcd); fail_create_hcd: @@ -198,19 +176,12 @@ static int __exit ehci_hcd_sh_remove(struct platform_device *pdev) struct usb_hcd *hcd = priv->hcd; usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); platform_set_drvdata(pdev, NULL); clk_disable(priv->fclk); clk_disable(priv->iclk); - clk_put(priv->fclk); - clk_put(priv->iclk); - - kfree(priv); - return 0; } diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c index c718a065e154d6..466c1bb5b96728 100644 --- a/drivers/usb/host/ehci-spear.c +++ b/drivers/usb/host/ehci-spear.c @@ -37,18 +37,11 @@ static void spear_stop_ehci(struct spear_ehci *ehci) static int ehci_spear_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval = 0; /* registers start at offset 0x0 */ ehci->caps = hcd->regs; - retval = ehci_setup(hcd); - if (retval) - return retval; - - ehci_port_power(ehci, 0); - - return retval; + return ehci_setup(hcd); } static const struct hc_driver ehci_spear_hc_driver = { @@ -116,8 +109,6 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev) struct clk *usbh_clk; const struct hc_driver *driver = &ehci_spear_hc_driver; int irq, retval; - char clk_name[20] = "usbh_clk"; - static int instance = -1; if (usb_disabled()) return -ENODEV; @@ -125,7 +116,7 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) { retval = irq; - goto fail_irq_get; + goto fail; } /* @@ -136,47 +127,38 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev) if (!pdev->dev.dma_mask) pdev->dev.dma_mask = &spear_ehci_dma_mask; - /* - * Increment the device instance, when probing via device-tree - */ - if (pdev->id < 0) - instance++; - else - instance = pdev->id; - sprintf(clk_name, "usbh.%01d_clk", instance); - - usbh_clk = clk_get(NULL, clk_name); + usbh_clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(usbh_clk)) { dev_err(&pdev->dev, "Error getting interface clock\n"); retval = PTR_ERR(usbh_clk); - goto fail_get_usbh_clk; + goto fail; } hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { retval = -ENOMEM; - goto fail_create_hcd; + goto fail; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { retval = -ENODEV; - goto fail_request_resource; + goto err_put_hcd; } hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, + if (!devm_request_mem_region(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len, driver->description)) { retval = -EBUSY; - goto fail_request_resource; + goto err_put_hcd; } - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_ioremap(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len); if (hcd->regs == NULL) { dev_dbg(&pdev->dev, "error mapping memory\n"); retval = -ENOMEM; - goto fail_ioremap; + goto err_put_hcd; } ehci = (struct spear_ehci *)hcd_to_ehci(hcd); @@ -185,21 +167,15 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev) spear_start_ehci(ehci); retval = usb_add_hcd(hcd, irq, IRQF_SHARED); if (retval) - goto fail_add_hcd; + goto err_stop_ehci; return retval; -fail_add_hcd: +err_stop_ehci: spear_stop_ehci(ehci); - iounmap(hcd->regs); -fail_ioremap: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -fail_request_resource: +err_put_hcd: usb_put_hcd(hcd); -fail_create_hcd: - clk_put(usbh_clk); -fail_get_usbh_clk: -fail_irq_get: +fail: dev_err(&pdev->dev, "init fail, %d\n", retval); return retval ; @@ -218,17 +194,12 @@ static int spear_ehci_hcd_drv_remove(struct platform_device *pdev) if (ehci_p->clk) spear_stop_ehci(ehci_p); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); - if (ehci_p->clk) - clk_put(ehci_p->clk); - return 0; } -static struct of_device_id spear_ehci_id_table[] __devinitdata = { +static struct of_device_id spear_ehci_id_table[] = { { .compatible = "st,spear600-ehci", }, { }, }; diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 26dedb30ad0be7..568aecc7075b4d 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -2,7 +2,7 @@ * EHCI-compliant USB host controller driver for NVIDIA Tegra SoCs * * Copyright (C) 2010 Google, Inc. - * Copyright (C) 2009 NVIDIA Corporation + * Copyright (C) 2009 - 2013 NVIDIA Corporation * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -26,9 +26,17 @@ #include #include #include +#include +#include -#include -#include +#define TEGRA_USB_BASE 0xC5000000 +#define TEGRA_USB2_BASE 0xC5004000 +#define TEGRA_USB3_BASE 0xC5008000 + +/* PORTSC registers */ +#define TEGRA_USB_PORTSC1 0x184 +#define TEGRA_USB_PORTSC1_PTS(x) (((x) & 0x3) << 30) +#define TEGRA_USB_PORTSC1_PHCD (1 << 23) #define TEGRA_USB_DMA_ALIGN 32 @@ -36,10 +44,10 @@ struct tegra_ehci_hcd { struct ehci_hcd *ehci; struct tegra_usb_phy *phy; struct clk *clk; - struct clk *emc_clk; struct usb_phy *transceiver; int host_resumed; int port_resuming; + bool needs_double_reset; enum tegra_usb_phy_port_speed port_speed; }; @@ -47,9 +55,8 @@ static void tegra_ehci_power_up(struct usb_hcd *hcd) { struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); - clk_prepare_enable(tegra->emc_clk); clk_prepare_enable(tegra->clk); - tegra_usb_phy_power_on(tegra->phy); + usb_phy_set_suspend(hcd->phy, 0); tegra->host_resumed = 1; } @@ -58,9 +65,8 @@ static void tegra_ehci_power_down(struct usb_hcd *hcd) struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); tegra->host_resumed = 0; - tegra_usb_phy_power_off(tegra->phy); + usb_phy_set_suspend(hcd->phy, 1); clk_disable_unprepare(tegra->clk); - clk_disable_unprepare(tegra->emc_clk); } static int tegra_ehci_internal_port_reset( @@ -153,7 +159,7 @@ static int tegra_ehci_hub_control( if (tegra->port_resuming && !(temp & PORT_SUSPEND)) { /* Resume completed, re-enable disconnect detection */ tegra->port_resuming = 0; - tegra_usb_phy_postresume(tegra->phy); + tegra_usb_phy_postresume(hcd->phy); } } @@ -181,7 +187,7 @@ static int tegra_ehci_hub_control( } /* For USB1 port we need to issue Port Reset twice internally */ - if (tegra->phy->instance == 0 && + if (tegra->needs_double_reset && (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_RESET)) { spin_unlock_irqrestore(&ehci->lock, flags); return tegra_ehci_internal_port_reset(ehci, status_reg); @@ -206,7 +212,7 @@ static int tegra_ehci_hub_control( goto done; /* Disable disconnect detection during port resume */ - tegra_usb_phy_preresume(tegra->phy); + tegra_usb_phy_preresume(hcd->phy); ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25); @@ -277,7 +283,6 @@ static void tegra_ehci_shutdown(struct usb_hcd *hcd) static int tegra_ehci_setup(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; /* EHCI registers start at offset 0x100 */ ehci->caps = hcd->regs + 0x100; @@ -285,12 +290,7 @@ static int tegra_ehci_setup(struct usb_hcd *hcd) /* switch to host mode */ hcd->has_tt = 1; - retval = ehci_setup(hcd); - if (retval) - return retval; - - ehci_port_power(ehci, 1); - return retval; + return ehci_setup(hcd); } struct dma_aligned_buffer { @@ -476,7 +476,7 @@ static int controller_resume(struct device *dev) } /* Force the phy to keep data lines in suspend state */ - tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed); + tegra_ehci_phy_restore_start(hcd->phy, tegra->port_speed); /* Enable host mode */ tdi_reset(ehci); @@ -543,17 +543,17 @@ static int controller_resume(struct device *dev) } } - tegra_ehci_phy_restore_end(tegra->phy); + tegra_ehci_phy_restore_end(hcd->phy); goto done; restart: if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH) - tegra_ehci_phy_restore_end(tegra->phy); + tegra_ehci_phy_restore_end(hcd->phy); tegra_ehci_restart(hcd); done: - tegra_usb_phy_preresume(tegra->phy); + tegra_usb_phy_preresume(hcd->phy); tegra->port_resuming = 1; return 0; } @@ -607,6 +607,37 @@ static const struct dev_pm_ops tegra_ehci_pm_ops = { #endif +/* Bits of PORTSC1, which will get cleared by writing 1 into them */ +#define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) + +void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val) +{ + unsigned long val; + struct usb_hcd *hcd = bus_to_hcd(x->otg->host); + void __iomem *base = hcd->regs; + + val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS; + val &= ~TEGRA_USB_PORTSC1_PTS(3); + val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3); + writel(val, base + TEGRA_USB_PORTSC1); +} +EXPORT_SYMBOL_GPL(tegra_ehci_set_pts); + +void tegra_ehci_set_phcd(struct usb_phy *x, bool enable) +{ + unsigned long val; + struct usb_hcd *hcd = bus_to_hcd(x->otg->host); + void __iomem *base = hcd->regs; + + val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS; + if (enable) + val |= TEGRA_USB_PORTSC1_PHCD; + else + val &= ~TEGRA_USB_PORTSC1_PHCD; + writel(val, base + TEGRA_USB_PORTSC1); +} +EXPORT_SYMBOL_GPL(tegra_ehci_set_phcd); + static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32); static int tegra_ehci_probe(struct platform_device *pdev) @@ -618,6 +649,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) int err = 0; int irq; int instance = pdev->id; + struct usb_phy *u_phy; pdata = pdev->dev.platform_data; if (!pdata) { @@ -634,7 +666,8 @@ static int tegra_ehci_probe(struct platform_device *pdev) setup_vbus_gpio(pdev, pdata); - tegra = kzalloc(sizeof(struct tegra_ehci_hcd), GFP_KERNEL); + tegra = devm_kzalloc(&pdev->dev, sizeof(struct tegra_ehci_hcd), + GFP_KERNEL); if (!tegra) return -ENOMEM; @@ -642,13 +675,12 @@ static int tegra_ehci_probe(struct platform_device *pdev) dev_name(&pdev->dev)); if (!hcd) { dev_err(&pdev->dev, "Unable to create HCD\n"); - err = -ENOMEM; - goto fail_hcd; + return -ENOMEM; } platform_set_drvdata(pdev, tegra); - tegra->clk = clk_get(&pdev->dev, NULL); + tegra->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(tegra->clk)) { dev_err(&pdev->dev, "Can't get ehci clock\n"); err = PTR_ERR(tegra->clk); @@ -657,17 +689,10 @@ static int tegra_ehci_probe(struct platform_device *pdev) err = clk_prepare_enable(tegra->clk); if (err) - goto fail_clken; - - tegra->emc_clk = clk_get(&pdev->dev, "emc"); - if (IS_ERR(tegra->emc_clk)) { - dev_err(&pdev->dev, "Can't get emc clock\n"); - err = PTR_ERR(tegra->emc_clk); - goto fail_emc_clk; - } + goto fail_clk; - clk_prepare_enable(tegra->emc_clk); - clk_set_rate(tegra->emc_clk, 400000000); + tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node, + "nvidia,needs-double-reset"); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -677,7 +702,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) } hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - hcd->regs = ioremap(res->start, resource_size(res)); + hcd->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!hcd->regs) { dev_err(&pdev->dev, "Failed to remap I/O memory\n"); err = -ENOMEM; @@ -702,7 +727,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) default: err = -ENODEV; dev_err(&pdev->dev, "unknown usb instance\n"); - goto fail_phy; + goto fail_io; } } @@ -712,10 +737,22 @@ static int tegra_ehci_probe(struct platform_device *pdev) if (IS_ERR(tegra->phy)) { dev_err(&pdev->dev, "Failed to open USB phy\n"); err = -ENXIO; - goto fail_phy; + goto fail_io; + } + + hcd->phy = u_phy = &tegra->phy->u_phy; + usb_phy_init(hcd->phy); + + u_phy->otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg), + GFP_KERNEL); + if (!u_phy->otg) { + dev_err(&pdev->dev, "Failed to alloc memory for otg\n"); + err = -ENOMEM; + goto fail_io; } + u_phy->otg->host = hcd_to_bus(hcd); - err = tegra_usb_phy_power_on(tegra->phy); + err = usb_phy_set_suspend(hcd->phy, 0); if (err) { dev_err(&pdev->dev, "Failed to power on the phy\n"); goto fail; @@ -733,7 +770,8 @@ static int tegra_ehci_probe(struct platform_device *pdev) #ifdef CONFIG_USB_OTG_UTILS if (pdata->operating_mode == TEGRA_USB_OTG) { - tegra->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); + tegra->transceiver = + devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); if (!IS_ERR_OR_NULL(tegra->transceiver)) otg_set_host(tegra->transceiver->otg, &hcd->self); } @@ -757,25 +795,14 @@ static int tegra_ehci_probe(struct platform_device *pdev) fail: #ifdef CONFIG_USB_OTG_UTILS - if (!IS_ERR_OR_NULL(tegra->transceiver)) { + if (!IS_ERR_OR_NULL(tegra->transceiver)) otg_set_host(tegra->transceiver->otg, NULL); - usb_put_phy(tegra->transceiver); - } #endif - tegra_usb_phy_close(tegra->phy); -fail_phy: - iounmap(hcd->regs); + usb_phy_shutdown(hcd->phy); fail_io: - clk_disable_unprepare(tegra->emc_clk); - clk_put(tegra->emc_clk); -fail_emc_clk: clk_disable_unprepare(tegra->clk); -fail_clken: - clk_put(tegra->clk); fail_clk: usb_put_hcd(hcd); -fail_hcd: - kfree(tegra); return err; } @@ -784,34 +811,21 @@ static int tegra_ehci_remove(struct platform_device *pdev) struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); - if (tegra == NULL || hcd == NULL) - return -EINVAL; - pm_runtime_get_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); #ifdef CONFIG_USB_OTG_UTILS - if (!IS_ERR_OR_NULL(tegra->transceiver)) { + if (!IS_ERR_OR_NULL(tegra->transceiver)) otg_set_host(tegra->transceiver->otg, NULL); - usb_put_phy(tegra->transceiver); - } #endif + usb_phy_shutdown(hcd->phy); usb_remove_hcd(hcd); - - tegra_usb_phy_close(tegra->phy); - iounmap(hcd->regs); - usb_put_hcd(hcd); clk_disable_unprepare(tegra->clk); - clk_put(tegra->clk); - - clk_disable_unprepare(tegra->emc_clk); - clk_put(tegra->emc_clk); - kfree(tegra); return 0; } @@ -824,7 +838,7 @@ static void tegra_ehci_hcd_shutdown(struct platform_device *pdev) hcd->driver->shutdown(hcd); } -static struct of_device_id tegra_ehci_of_match[] __devinitdata = { +static struct of_device_id tegra_ehci_of_match[] = { { .compatible = "nvidia,tegra20-ehci", }, { }, }; diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c index 20dbdcbe9b0fc1..c3fa1305f830bf 100644 --- a/drivers/usb/host/ehci-timer.c +++ b/drivers/usb/host/ehci-timer.c @@ -304,7 +304,7 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci) * (a) SMP races against real IAA firing and retriggering, and * (b) clean HC shutdown, when IAA watchdog was pending. */ - if (ehci->async_iaa) { + if (1) { u32 cmd, status; /* If we get here, IAA is *REALLY* late. It's barely diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c index 4d147c4e33f534..7ecf709610ba8e 100644 --- a/drivers/usb/host/ehci-vt8500.c +++ b/drivers/usb/host/ehci-vt8500.c @@ -16,24 +16,10 @@ * */ +#include +#include #include -static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int rc = 0; - - if (!udev->parent) /* udev is root hub itself, impossible */ - rc = -1; - /* we only support lpm device connected to root hub yet */ - if (ehci->has_lpm && !udev->parent->parent) { - rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum); - if (!rc) - rc = ehci_lpm_check(ehci, udev->portnum); - } - return rc; -} - static const struct hc_driver vt8500_ehci_hc_driver = { .description = hcd_name, .product_desc = "VT8500 EHCI", @@ -76,14 +62,11 @@ static const struct hc_driver vt8500_ehci_hc_driver = { .relinquish_port = ehci_relinquish_port, .port_handed_over = ehci_port_handed_over, - /* - * call back when device connected and addressed - */ - .update_device = ehci_update_device, - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; +static u64 vt8500_ehci_dma_mask = DMA_BIT_MASK(32); + static int vt8500_ehci_drv_probe(struct platform_device *pdev) { struct usb_hcd *hcd; @@ -94,6 +77,14 @@ static int vt8500_ehci_drv_probe(struct platform_device *pdev) if (usb_disabled()) return -ENODEV; + /* + * Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we have dma capability bindings this can go away. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &vt8500_ehci_dma_mask; + if (pdev->resource[1].flags != IORESOURCE_IRQ) { pr_debug("resource[1] is not IORESOURCE_IRQ"); return -ENOMEM; @@ -106,19 +97,12 @@ static int vt8500_ehci_drv_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - pr_debug("request_mem_region failed"); - ret = -EBUSY; + hcd->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hcd->regs)) { + ret = PTR_ERR(hcd->regs); goto err1; } - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - pr_debug("ioremap failed"); - ret = -ENOMEM; - goto err2; - } - ehci = hcd_to_ehci(hcd); ehci->caps = hcd->regs; @@ -129,9 +113,6 @@ static int vt8500_ehci_drv_probe(struct platform_device *pdev) return ret; } - iounmap(hcd->regs); -err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err1: usb_put_hcd(hcd); return ret; @@ -142,14 +123,18 @@ static int vt8500_ehci_drv_remove(struct platform_device *pdev) struct usb_hcd *hcd = platform_get_drvdata(pdev); usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); platform_set_drvdata(pdev, NULL); return 0; } +static const struct of_device_id vt8500_ehci_ids[] = { + { .compatible = "via,vt8500-ehci", }, + { .compatible = "wm,prizm-ehci", }, + {} +}; + static struct platform_driver vt8500_ehci_driver = { .probe = vt8500_ehci_drv_probe, .remove = vt8500_ehci_drv_remove, @@ -157,7 +142,9 @@ static struct platform_driver vt8500_ehci_driver = { .driver = { .name = "vt8500-ehci", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(vt8500_ehci_ids), } }; MODULE_ALIAS("platform:vt8500-ehci"); +MODULE_DEVICE_TABLE(of, vt8500_ehci_ids); diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c index ec598082c14b09..59e0e24c753feb 100644 --- a/drivers/usb/host/ehci-w90x900.c +++ b/drivers/usb/host/ehci-w90x900.c @@ -13,12 +13,12 @@ #include -/*ebable phy0 and phy1 for w90p910*/ +/* enable phy0 and phy1 for w90p910 */ #define ENPHY (0x01<<8) #define PHY0_CTR (0xA4) #define PHY1_CTR (0xA8) -static int __devinit usb_w90x900_probe(const struct hc_driver *driver, +static int usb_w90x900_probe(const struct hc_driver *driver, struct platform_device *pdev) { struct usb_hcd *hcd; @@ -147,7 +147,7 @@ static const struct hc_driver ehci_w90x900_hc_driver = { .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; -static int __devinit ehci_w90x900_probe(struct platform_device *pdev) +static int ehci_w90x900_probe(struct platform_device *pdev) { if (usb_disabled()) return -ENODEV; @@ -155,7 +155,7 @@ static int __devinit ehci_w90x900_probe(struct platform_device *pdev) return usb_w90x900_probe(&ehci_w90x900_hc_driver, pdev); } -static int __devexit ehci_w90x900_remove(struct platform_device *pdev) +static int ehci_w90x900_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); @@ -166,7 +166,7 @@ static int __devexit ehci_w90x900_remove(struct platform_device *pdev) static struct platform_driver ehci_hcd_w90x900_driver = { .probe = ehci_w90x900_probe, - .remove = __devexit_p(ehci_w90x900_remove), + .remove = ehci_w90x900_remove, .driver = { .name = "w90x900-ehci", .owner = THIS_MODULE, diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index 39f24fa37ebe9f..d845e3bcfaffb1 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c @@ -25,6 +25,7 @@ * */ +#include #include #include @@ -125,7 +126,7 @@ static const struct hc_driver ehci_xilinx_of_hc_driver = { * as HS only or HS/FS only, it checks the configuration in the device tree * entry, and sets an appropriate value for hcd->has_tt. */ -static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op) +static int ehci_hcd_xilinx_of_probe(struct platform_device *op) { struct device_node *dn = op->dev.of_node; struct usb_hcd *hcd; @@ -152,12 +153,6 @@ static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op) hcd->rsrc_start = res.start; hcd->rsrc_len = resource_size(&res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__); - rv = -EBUSY; - goto err_rmr; - } - irq = irq_of_parse_and_map(dn, 0); if (!irq) { printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__); @@ -165,11 +160,10 @@ static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op) goto err_irq; } - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - printk(KERN_ERR "%s: ioremap failed\n", __FILE__); - rv = -ENOMEM; - goto err_ioremap; + hcd->regs = devm_ioremap_resource(&op->dev, &res); + if (IS_ERR(hcd->regs)) { + rv = PTR_ERR(hcd->regs); + goto err_irq; } ehci = hcd_to_ehci(hcd); @@ -200,12 +194,7 @@ static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op) if (rv == 0) return 0; - iounmap(hcd->regs); - -err_ioremap: err_irq: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err_rmr: usb_put_hcd(hcd); return rv; @@ -227,9 +216,6 @@ static int ehci_hcd_xilinx_of_remove(struct platform_device *op) usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); return 0; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index da07d98f7d1de7..36c3a82105953b 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -38,6 +38,10 @@ typedef __u16 __bitwise __hc16; #endif /* statistics can be kept for tuning/monitoring */ +#ifdef DEBUG +#define EHCI_STATS +#endif + struct ehci_stats { /* irq usage */ unsigned long normal; @@ -143,7 +147,7 @@ struct ehci_hcd { /* one per controller */ struct ehci_qh *intr_unlink_last; unsigned intr_unlink_cycle; unsigned now_frame; /* frame from HC hardware */ - unsigned next_frame; /* scan periodic, start here */ + unsigned last_iso_frame; /* last frame scanned for iso */ unsigned intr_count; /* intr activity count */ unsigned isoc_count; /* isoc activity count */ unsigned periodic_count; /* periodic activity count */ @@ -193,7 +197,6 @@ struct ehci_hcd { /* one per controller */ unsigned has_amcc_usb23:1; unsigned need_io_watchdog:1; unsigned amd_pll_fix:1; - unsigned fs_i_thresh:1; /* Intel iso scheduling */ unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/ unsigned has_synopsys_hc_bug:1; /* Synopsys HC */ unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */ @@ -207,7 +210,6 @@ struct ehci_hcd { /* one per controller */ #define OHCI_HCCTRL_LEN 0x4 __hc32 *ohci_hcctrl_reg; unsigned has_hostpc:1; - unsigned has_lpm:1; /* support link power management */ unsigned has_ppcd:1; /* support per-port change bits */ u8 sbrn; /* packed release number */ @@ -223,6 +225,9 @@ struct ehci_hcd { /* one per controller */ #ifdef DEBUG struct dentry *debug_dir; #endif + + /* platform-specific data -- must come last */ + unsigned long priv[0] __aligned(sizeof(s64)); }; /* convert between an HCD pointer and the corresponding EHCI_HCD */ @@ -762,26 +767,41 @@ static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) /*-------------------------------------------------------------------------*/ -#ifdef CONFIG_PCI - -/* For working around the MosChip frame-index-register bug */ -static unsigned ehci_read_frame_index(struct ehci_hcd *ehci); - +#define ehci_dbg(ehci, fmt, args...) \ + dev_dbg(ehci_to_hcd(ehci)->self.controller , fmt , ## args) +#define ehci_err(ehci, fmt, args...) \ + dev_err(ehci_to_hcd(ehci)->self.controller , fmt , ## args) +#define ehci_info(ehci, fmt, args...) \ + dev_info(ehci_to_hcd(ehci)->self.controller , fmt , ## args) +#define ehci_warn(ehci, fmt, args...) \ + dev_warn(ehci_to_hcd(ehci)->self.controller , fmt , ## args) + +#ifdef VERBOSE_DEBUG +# define ehci_vdbg ehci_dbg #else - -static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci) -{ - return ehci_readl(ehci, &ehci->regs->frame_index); -} - + static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {} #endif -/*-------------------------------------------------------------------------*/ - #ifndef DEBUG #define STUB_DEBUG_FILES #endif /* DEBUG */ /*-------------------------------------------------------------------------*/ +/* Declarations of things exported for use by ehci platform drivers */ + +struct ehci_driver_overrides { + size_t extra_priv_size; + int (*reset)(struct usb_hcd *hcd); +}; + +extern void ehci_init_driver(struct hc_driver *drv, + const struct ehci_driver_overrides *over); +extern int ehci_setup(struct usb_hcd *hcd); + +#ifdef CONFIG_PM +extern int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup); +extern int ehci_resume(struct usb_hcd *hcd, bool hibernated); +#endif /* CONFIG_PM */ + #endif /* __LINUX_EHCI_HCD_H */ diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index 7da1a26bed2e65..0b46542591fff6 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c @@ -561,7 +561,7 @@ static const struct hc_driver fhci_driver = { .hub_control = fhci_hub_control, }; -static int __devinit of_fhci_probe(struct platform_device *ofdev) +static int of_fhci_probe(struct platform_device *ofdev) { struct device *dev = &ofdev->dev; struct device_node *node = dev->of_node; @@ -780,7 +780,7 @@ static int __devinit of_fhci_probe(struct platform_device *ofdev) return ret; } -static int __devexit fhci_remove(struct device *dev) +static int fhci_remove(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct fhci_hcd *fhci = hcd_to_fhci(hcd); @@ -803,7 +803,7 @@ static int __devexit fhci_remove(struct device *dev) return 0; } -static int __devexit of_fhci_remove(struct platform_device *ofdev) +static int of_fhci_remove(struct platform_device *ofdev) { return fhci_remove(&ofdev->dev); } @@ -821,7 +821,7 @@ static struct platform_driver of_fhci_driver = { .of_match_table = of_fhci_match, }, .probe = of_fhci_probe, - .remove = __devexit_p(of_fhci_remove), + .remove = of_fhci_remove, }; module_platform_driver(of_fhci_driver); diff --git a/drivers/usb/host/fhci-sched.c b/drivers/usb/host/fhci-sched.c index 2dc8a40e39d76e..8f18538e0ff752 100644 --- a/drivers/usb/host/fhci-sched.c +++ b/drivers/usb/host/fhci-sched.c @@ -261,8 +261,7 @@ static void move_head_to_tail(struct list_head *list) struct list_head *node = list->next; if (!list_empty(list)) { - list_del(node); - list_add_tail(node, list); + list_move_tail(node, list); } } diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 22ff6b3a676f40..11e0b79ff9d52a 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -24,7 +24,7 @@ struct fsl_usb2_dev_data { enum fsl_usb2_operating_modes op_mode; /* operating mode */ }; -struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = { +struct fsl_usb2_dev_data dr_mode_data[] = { { .dr_mode = "host", .drivers = { "fsl-ehci", NULL, NULL, }, @@ -42,7 +42,7 @@ struct fsl_usb2_dev_data dr_mode_data[] __devinitdata = { }, }; -struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np) +struct fsl_usb2_dev_data *get_dr_mode_data(struct device_node *np) { const unsigned char *prop; int i; @@ -59,7 +59,7 @@ struct fsl_usb2_dev_data * __devinit get_dr_mode_data(struct device_node *np) return &dr_mode_data[0]; /* mode not specified, use host */ } -static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type) +static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type) { if (!phy_type) return FSL_USB2_PHY_NONE; @@ -75,7 +75,7 @@ static enum fsl_usb2_phy_modes __devinit determine_usb_phy(const char *phy_type) return FSL_USB2_PHY_NONE; } -struct platform_device * __devinit fsl_usb2_device_register( +struct platform_device *fsl_usb2_device_register( struct platform_device *ofdev, struct fsl_usb2_platform_data *pdata, const char *name, int id) @@ -133,6 +133,8 @@ static int usb_get_ver_info(struct device_node *np) ver = FSL_USB_VER_1_6; else if (of_device_is_compatible(np, "fsl-usb2-dr-v2.2")) ver = FSL_USB_VER_2_2; + else if (of_device_is_compatible(np, "fsl-usb2-dr-v2.4")) + ver = FSL_USB_VER_2_4; else /* for previous controller versions */ ver = FSL_USB_VER_OLD; @@ -140,6 +142,9 @@ static int usb_get_ver_info(struct device_node *np) return ver; } + if (of_device_is_compatible(np, "fsl,mpc5121-usb2-dr")) + return FSL_USB_VER_OLD; + if (of_device_is_compatible(np, "fsl-usb2-mph")) { if (of_device_is_compatible(np, "fsl-usb2-mph-v1.6")) ver = FSL_USB_VER_1_6; @@ -152,7 +157,7 @@ static int usb_get_ver_info(struct device_node *np) return ver; } -static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev) +static int fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev) { struct device_node *np = ofdev->dev.of_node; struct platform_device *usb_dev; @@ -222,13 +227,13 @@ static int __devinit fsl_usb2_mph_dr_of_probe(struct platform_device *ofdev) return 0; } -static int __devexit __unregister_subdev(struct device *dev, void *d) +static int __unregister_subdev(struct device *dev, void *d) { platform_device_unregister(to_platform_device(dev)); return 0; } -static int __devexit fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev) +static int fsl_usb2_mph_dr_of_remove(struct platform_device *ofdev) { device_for_each_child(&ofdev->dev, NULL, __unregister_subdev); return 0; @@ -334,7 +339,7 @@ static struct platform_driver fsl_usb2_mph_dr_driver = { .of_match_table = fsl_usb2_mph_dr_of_match, }, .probe = fsl_usb2_mph_dr_of_probe, - .remove = __devexit_p(fsl_usb2_mph_dr_of_remove), + .remove = fsl_usb2_mph_dr_of_remove, }; module_platform_driver(fsl_usb2_mph_dr_driver); diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index f19e2690c232d5..f0ebe8e7c58b4d 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c @@ -58,6 +58,7 @@ #include #include #include +#include #include "imx21-hcd.h" @@ -1680,7 +1681,7 @@ static int imx21_hc_reset(struct usb_hcd *hcd) return 0; } -static int __devinit imx21_hc_start(struct usb_hcd *hcd) +static int imx21_hc_start(struct usb_hcd *hcd) { struct imx21 *imx21 = hcd_to_imx21(hcd); unsigned long flags; diff --git a/drivers/usb/host/imx21-hcd.h b/drivers/usb/host/imx21-hcd.h index 87b29fd971b409..c005770a73e97e 100644 --- a/drivers/usb/host/imx21-hcd.h +++ b/drivers/usb/host/imx21-hcd.h @@ -24,7 +24,7 @@ #ifndef __LINUX_IMX21_HCD_H__ #define __LINUX_IMX21_HCD_H__ -#include +#include #define NUM_ISO_ETDS 2 #define USB_NUM_ETD 32 diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 9e65e3091c8a12..b64e661618bb88 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -1557,7 +1557,7 @@ static int isp116x_remove(struct platform_device *pdev) return 0; } -static int __devinit isp116x_probe(struct platform_device *pdev) +static int isp116x_probe(struct platform_device *pdev) { struct usb_hcd *hcd; struct isp116x *isp116x; diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index 256326322cfd8b..974480c516fabc 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c @@ -2645,7 +2645,7 @@ static struct hc_driver isp1362_hc_driver = { /*-------------------------------------------------------------------------*/ -static int __devexit isp1362_remove(struct platform_device *pdev) +static int isp1362_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); @@ -2680,7 +2680,7 @@ static int __devexit isp1362_remove(struct platform_device *pdev) return 0; } -static int __devinit isp1362_probe(struct platform_device *pdev) +static int isp1362_probe(struct platform_device *pdev) { struct usb_hcd *hcd; struct isp1362_hcd *isp1362_hcd; @@ -2856,7 +2856,7 @@ static int isp1362_resume(struct platform_device *pdev) static struct platform_driver isp1362_driver = { .probe = isp1362_probe, - .remove = __devexit_p(isp1362_remove), + .remove = isp1362_remove, .suspend = isp1362_suspend, .resume = isp1362_resume, diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index a35bbddf89685a..125e261f5bfca1 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -932,7 +932,7 @@ static void enqueue_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh) } } -void schedule_ptds(struct usb_hcd *hcd) +static void schedule_ptds(struct usb_hcd *hcd) { struct isp1760_hcd *priv; struct isp1760_qh *qh, *qh_next; @@ -1285,7 +1285,7 @@ static irqreturn_t isp1760_irq(struct usb_hcd *hcd) #define SLOT_CHECK_PERIOD 200 static struct timer_list errata2_timer; -void errata2_function(unsigned long data) +static void errata2_function(unsigned long data) { struct usb_hcd *hcd = (struct usb_hcd *) data; struct isp1760_hcd *priv = hcd_to_priv(hcd); diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index fff114fd546155..bbb791bd7617d6 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -43,7 +43,6 @@ static int of_isp1760_probe(struct platform_device *dev) struct device_node *dp = dev->dev.of_node; struct resource *res; struct resource memory; - struct of_irq oirq; int virq; resource_size_t res_len; int ret; @@ -69,14 +68,12 @@ static int of_isp1760_probe(struct platform_device *dev) goto free_data; } - if (of_irq_map_one(dp, 0, &oirq)) { + virq = irq_of_parse_and_map(dp, 0); + if (!virq) { ret = -ENODEV; goto release_reg; } - virq = irq_create_of_mapping(oirq.controller, oirq.specifier, - oirq.size); - if (of_device_is_compatible(dp, "nxp,usb-isp1761")) devflags |= ISP1760_FLAG_ISP1761; @@ -175,7 +172,7 @@ static struct platform_driver isp1760_of_driver = { #endif #ifdef CONFIG_PCI -static int __devinit isp1761_pci_probe(struct pci_dev *dev, +static int isp1761_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { u8 latency, limit; @@ -349,7 +346,7 @@ static struct pci_driver isp1761_pci_driver = { }; #endif -static int __devinit isp1760_plat_probe(struct platform_device *pdev) +static int isp1760_plat_probe(struct platform_device *pdev) { int ret = 0; struct usb_hcd *hcd; @@ -416,7 +413,7 @@ static int __devinit isp1760_plat_probe(struct platform_device *pdev) return ret; } -static int __devexit isp1760_plat_remove(struct platform_device *pdev) +static int isp1760_plat_remove(struct platform_device *pdev) { struct resource *mem_res; resource_size_t mem_size; @@ -435,7 +432,7 @@ static int __devexit isp1760_plat_remove(struct platform_device *pdev) static struct platform_driver isp1760_plat_driver = { .probe = isp1760_plat_probe, - .remove = __devexit_p(isp1760_plat_remove), + .remove = isp1760_plat_remove, .driver = { .name = "isp1760", }, diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 0bf72f943b00d3..a0cb44f0e72420 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -16,11 +16,11 @@ #include #include #include +#include #include #include -#include #include #ifndef CONFIG_ARCH_AT91 @@ -94,7 +94,7 @@ static void at91_stop_hc(struct platform_device *pdev) /*-------------------------------------------------------------------------*/ -static void __devexit usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); +static void usb_hcd_at91_remove (struct usb_hcd *, struct platform_device *); /* configure so an HC device and id are always provided */ /* always called with process context; sleeping is OK */ @@ -108,7 +108,7 @@ static void __devexit usb_hcd_at91_remove (struct usb_hcd *, struct platform_dev * then invokes the start() method for the HCD associated with it * through the hotplug entry's driver_data. */ -static int __devinit usb_hcd_at91_probe(const struct hc_driver *driver, +static int usb_hcd_at91_probe(const struct hc_driver *driver, struct platform_device *pdev) { int retval; @@ -203,7 +203,7 @@ static int __devinit usb_hcd_at91_probe(const struct hc_driver *driver, * context, "rmmod" or something similar. * */ -static void __devexit usb_hcd_at91_remove(struct usb_hcd *hcd, +static void usb_hcd_at91_remove(struct usb_hcd *hcd, struct platform_device *pdev) { usb_remove_hcd(hcd); @@ -222,7 +222,7 @@ static void __devexit usb_hcd_at91_remove(struct usb_hcd *hcd, /*-------------------------------------------------------------------------*/ -static int __devinit +static int ohci_at91_reset (struct usb_hcd *hcd) { struct at91_usbh_data *board = hcd->self.controller->platform_data; @@ -236,7 +236,7 @@ ohci_at91_reset (struct usb_hcd *hcd) return 0; } -static int __devinit +static int ohci_at91_start (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); @@ -506,7 +506,7 @@ MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids); static u64 at91_ohci_dma_mask = DMA_BIT_MASK(32); -static int __devinit ohci_at91_of_init(struct platform_device *pdev) +static int ohci_at91_of_init(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; int i, gpio; @@ -548,7 +548,7 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev) return 0; } #else -static int __devinit ohci_at91_of_init(struct platform_device *pdev) +static int ohci_at91_of_init(struct platform_device *pdev) { return 0; } @@ -556,7 +556,7 @@ static int __devinit ohci_at91_of_init(struct platform_device *pdev) /*-------------------------------------------------------------------------*/ -static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev) +static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) { struct at91_usbh_data *pdata; int i; @@ -641,7 +641,7 @@ static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev) return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev); } -static int __devexit ohci_hcd_at91_drv_remove(struct platform_device *pdev) +static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) { struct at91_usbh_data *pdata = pdev->dev.platform_data; int i; @@ -705,7 +705,7 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev) if (!clocked) at91_start_clock(); - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } #else @@ -717,7 +717,7 @@ MODULE_ALIAS("platform:at91_ohci"); static struct platform_driver ohci_hcd_at91_driver = { .probe = ohci_hcd_at91_drv_probe, - .remove = __devexit_p(ohci_hcd_at91_drv_remove), + .remove = ohci_hcd_at91_drv_remove, .shutdown = usb_hcd_platform_shutdown, .suspend = ohci_hcd_at91_drv_suspend, .resume = ohci_hcd_at91_drv_resume, diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c index 269b1e0f769197..0b815a856811ed 100644 --- a/drivers/usb/host/ohci-da8xx.c +++ b/drivers/usb/host/ohci-da8xx.c @@ -17,7 +17,7 @@ #include #include -#include +#include #ifndef CONFIG_ARCH_DAVINCI_DA8XX #error "This file is DA8xx bus glue. Define CONFIG_ARCH_DAVINCI_DA8XX." diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index dbfbd1dfd2e2f7..8704e9fa5a8041 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -107,7 +107,7 @@ static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd, usb_put_hcd(hcd); } -static int __devinit ohci_ep93xx_start(struct usb_hcd *hcd) +static int ohci_ep93xx_start(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); int ret; @@ -194,7 +194,7 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev) ep93xx_start_hc(&pdev->dev); - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } #endif diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c index fc3091bd2379fb..e3b7e85120e444 100644 --- a/drivers/usb/host/ohci-exynos.c +++ b/drivers/usb/host/ohci-exynos.c @@ -14,15 +14,45 @@ #include #include #include -#include +#include +#include +#include #include struct exynos_ohci_hcd { struct device *dev; struct usb_hcd *hcd; struct clk *clk; + struct usb_phy *phy; + struct usb_otg *otg; + struct exynos4_ohci_platdata *pdata; }; +static void exynos_ohci_phy_enable(struct exynos_ohci_hcd *exynos_ohci) +{ + struct platform_device *pdev = to_platform_device(exynos_ohci->dev); + + if (exynos_ohci->phy) + usb_phy_init(exynos_ohci->phy); + else if (exynos_ohci->pdata->phy_init) + exynos_ohci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST); +} + +static void exynos_ohci_phy_disable(struct exynos_ohci_hcd *exynos_ohci) +{ + struct platform_device *pdev = to_platform_device(exynos_ohci->dev); + + if (exynos_ohci->phy) + usb_phy_shutdown(exynos_ohci->phy); + else if (exynos_ohci->pdata->phy_exit) + exynos_ohci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST); +} + +static int ohci_exynos_reset(struct usb_hcd *hcd) +{ + return ohci_init(hcd_to_ohci(hcd)); +} + static int ohci_exynos_start(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); @@ -30,10 +60,6 @@ static int ohci_exynos_start(struct usb_hcd *hcd) ohci_dbg(ohci, "ohci_exynos_start, ohci:%p", ohci); - ret = ohci_init(ohci); - if (ret < 0) - return ret; - ret = ohci_run(ohci); if (ret < 0) { dev_err(hcd->self.controller, "can't start %s\n", @@ -53,6 +79,7 @@ static const struct hc_driver exynos_ohci_hc_driver = { .irq = ohci_irq, .flags = HCD_MEMORY|HCD_USB11, + .reset = ohci_exynos_reset, .start = ohci_exynos_start, .stop = ohci_stop, .shutdown = ohci_shutdown, @@ -74,22 +101,17 @@ static const struct hc_driver exynos_ohci_hc_driver = { static u64 ohci_exynos_dma_mask = DMA_BIT_MASK(32); -static int __devinit exynos_ohci_probe(struct platform_device *pdev) +static int exynos_ohci_probe(struct platform_device *pdev) { - struct exynos4_ohci_platdata *pdata; + struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; struct exynos_ohci_hcd *exynos_ohci; struct usb_hcd *hcd; struct ohci_hcd *ohci; struct resource *res; + struct usb_phy *phy; int irq; int err; - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(&pdev->dev, "No platform data defined\n"); - return -EINVAL; - } - /* * Right now device-tree probed devices don't get dma_mask set. * Since shared usb code relies on it, set it here for now. @@ -105,6 +127,20 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) if (!exynos_ohci) return -ENOMEM; + phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); + if (IS_ERR_OR_NULL(phy)) { + /* Fallback to pdata */ + if (!pdata) { + dev_warn(&pdev->dev, "no platform data or transceiver defined\n"); + return -EPROBE_DEFER; + } else { + exynos_ohci->pdata = pdata; + } + } else { + exynos_ohci->phy = phy; + exynos_ohci->otg = phy->otg; + } + exynos_ohci->dev = &pdev->dev; hcd = usb_create_hcd(&exynos_ohci_hc_driver, &pdev->dev, @@ -115,7 +151,7 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) } exynos_ohci->hcd = hcd; - exynos_ohci->clk = clk_get(&pdev->dev, "usbhost"); + exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost"); if (IS_ERR(exynos_ohci->clk)) { dev_err(&pdev->dev, "Failed to get usbhost clock\n"); @@ -123,9 +159,9 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) goto fail_clk; } - err = clk_enable(exynos_ohci->clk); + err = clk_prepare_enable(exynos_ohci->clk); if (err) - goto fail_clken; + goto fail_clk; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -150,8 +186,11 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) goto fail_io; } - if (pdata->phy_init) - pdata->phy_init(pdev, S5P_USB_PHY_HOST); + if (exynos_ohci->otg) + exynos_ohci->otg->set_host(exynos_ohci->otg, + &exynos_ohci->hcd->self); + + exynos_ohci_phy_enable(exynos_ohci); ohci = hcd_to_ohci(hcd); ohci_hcd_init(ohci); @@ -159,35 +198,36 @@ static int __devinit exynos_ohci_probe(struct platform_device *pdev) err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) { dev_err(&pdev->dev, "Failed to add USB HCD\n"); - goto fail_io; + goto fail_add_hcd; } platform_set_drvdata(pdev, exynos_ohci); return 0; +fail_add_hcd: + exynos_ohci_phy_disable(exynos_ohci); fail_io: - clk_disable(exynos_ohci->clk); -fail_clken: - clk_put(exynos_ohci->clk); + clk_disable_unprepare(exynos_ohci->clk); fail_clk: usb_put_hcd(hcd); return err; } -static int __devexit exynos_ohci_remove(struct platform_device *pdev) +static int exynos_ohci_remove(struct platform_device *pdev) { - struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev); struct usb_hcd *hcd = exynos_ohci->hcd; usb_remove_hcd(hcd); - if (pdata && pdata->phy_exit) - pdata->phy_exit(pdev, S5P_USB_PHY_HOST); + if (exynos_ohci->otg) + exynos_ohci->otg->set_host(exynos_ohci->otg, + &exynos_ohci->hcd->self); + + exynos_ohci_phy_disable(exynos_ohci); - clk_disable(exynos_ohci->clk); - clk_put(exynos_ohci->clk); + clk_disable_unprepare(exynos_ohci->clk); usb_put_hcd(hcd); @@ -209,8 +249,6 @@ static int exynos_ohci_suspend(struct device *dev) struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev); struct usb_hcd *hcd = exynos_ohci->hcd; struct ohci_hcd *ohci = hcd_to_ohci(hcd); - struct platform_device *pdev = to_platform_device(dev); - struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; unsigned long flags; int rc = 0; @@ -229,10 +267,13 @@ static int exynos_ohci_suspend(struct device *dev) clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - if (pdata && pdata->phy_exit) - pdata->phy_exit(pdev, S5P_USB_PHY_HOST); + if (exynos_ohci->otg) + exynos_ohci->otg->set_host(exynos_ohci->otg, + &exynos_ohci->hcd->self); + + exynos_ohci_phy_disable(exynos_ohci); - clk_disable(exynos_ohci->clk); + clk_disable_unprepare(exynos_ohci->clk); fail: spin_unlock_irqrestore(&ohci->lock, flags); @@ -244,18 +285,16 @@ static int exynos_ohci_resume(struct device *dev) { struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev); struct usb_hcd *hcd = exynos_ohci->hcd; - struct platform_device *pdev = to_platform_device(dev); - struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; - clk_enable(exynos_ohci->clk); + clk_prepare_enable(exynos_ohci->clk); - if (pdata && pdata->phy_init) - pdata->phy_init(pdev, S5P_USB_PHY_HOST); + if (exynos_ohci->otg) + exynos_ohci->otg->set_host(exynos_ohci->otg, + &exynos_ohci->hcd->self); - /* Mark hardware accessible again as we are out of D3 state by now */ - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + exynos_ohci_phy_enable(exynos_ohci); - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } @@ -271,7 +310,7 @@ static const struct dev_pm_ops exynos_ohci_pm_ops = { #ifdef CONFIG_OF static const struct of_device_id exynos_ohci_match[] = { - { .compatible = "samsung,exynos-ohci" }, + { .compatible = "samsung,exynos4210-ohci" }, {}, }; MODULE_DEVICE_TABLE(of, exynos_ohci_match); @@ -279,7 +318,7 @@ MODULE_DEVICE_TABLE(of, exynos_ohci_match); static struct platform_driver exynos_ohci_driver = { .probe = exynos_ohci_probe, - .remove = __devexit_p(exynos_ohci_remove), + .remove = exynos_ohci_remove, .shutdown = exynos_ohci_shutdown, .driver = { .name = "exynos-ohci", diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 2b1e8d84c87387..007137fe14d274 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -231,13 +231,45 @@ static int ohci_urb_enqueue ( frame &= ~(ed->interval - 1); frame |= ed->branch; urb->start_frame = frame; + } + } else if (ed->type == PIPE_ISOCHRONOUS) { + u16 next = ohci_frame_no(ohci) + 1; + u16 frame = ed->last_iso + ed->interval; + + /* Behind the scheduling threshold? */ + if (unlikely(tick_before(frame, next))) { - /* yes, only URB_ISO_ASAP is supported, and - * urb->start_frame is never used as input. + /* USB_ISO_ASAP: Round up to the first available slot */ + if (urb->transfer_flags & URB_ISO_ASAP) { + frame += (next - frame + ed->interval - 1) & + -ed->interval; + + /* + * Not ASAP: Use the next slot in the stream. If + * the entire URB falls before the threshold, fail. */ + } else { + if (tick_before(frame + ed->interval * + (urb->number_of_packets - 1), next)) { + retval = -EXDEV; + usb_hcd_unlink_urb_from_ep(hcd, urb); + goto fail; + } + + /* + * Some OHCI hardware doesn't handle late TDs + * correctly. After retiring them it proceeds + * to the next ED instead of the next TD. + * Therefore we have to omit the late TDs + * entirely. + */ + urb_priv->td_cnt = DIV_ROUND_UP( + (u16) (next - frame), + ed->interval); + } } - } else if (ed->type == PIPE_ISOCHRONOUS) - urb->start_frame = ed->last_iso + ed->interval; + urb->start_frame = frame; + } /* fill the TDs and link them to the ed; and * enable that part of the schedule, if needed @@ -893,7 +925,7 @@ static void ohci_stop (struct usb_hcd *hcd) ohci_dump (ohci, 1); if (quirk_nec(ohci)) - flush_work_sync(&ohci->nec_work); + flush_work(&ohci->nec_work); ohci_usb_reset (ohci); ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); @@ -983,6 +1015,79 @@ static int ohci_restart (struct ohci_hcd *ohci) #endif +#ifdef CONFIG_PM + +static int __maybe_unused ohci_suspend(struct usb_hcd *hcd, bool do_wakeup) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + unsigned long flags; + + /* Disable irq emission and mark HW unaccessible. Use + * the spinlock to properly synchronize with possible pending + * RH suspend or resume activity. + */ + spin_lock_irqsave (&ohci->lock, flags); + ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); + (void)ohci_readl(ohci, &ohci->regs->intrdisable); + + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + spin_unlock_irqrestore (&ohci->lock, flags); + + return 0; +} + + +static int __maybe_unused ohci_resume(struct usb_hcd *hcd, bool hibernated) +{ + struct ohci_hcd *ohci = hcd_to_ohci(hcd); + int port; + bool need_reinit = false; + + set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); + + /* Make sure resume from hibernation re-enumerates everything */ + if (hibernated) + ohci_usb_reset(ohci); + + /* See if the controller is already running or has been reset */ + ohci->hc_control = ohci_readl(ohci, &ohci->regs->control); + if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { + need_reinit = true; + } else { + switch (ohci->hc_control & OHCI_CTRL_HCFS) { + case OHCI_USB_OPER: + case OHCI_USB_RESET: + need_reinit = true; + } + } + + /* If needed, reinitialize and suspend the root hub */ + if (need_reinit) { + spin_lock_irq(&ohci->lock); + ohci_rh_resume(ohci); + ohci_rh_suspend(ohci, 0); + spin_unlock_irq(&ohci->lock); + } + + /* Normally just turn on port power and enable interrupts */ + else { + ohci_dbg(ohci, "powerup ports\n"); + for (port = 0; port < ohci->num_ports; port++) + ohci_writel(ohci, RH_PS_PPS, + &ohci->regs->roothub.portstatus[port]); + + ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable); + ohci_readl(ohci, &ohci->regs->intrenable); + msleep(20); + } + + usb_hcd_resume_root_hub(hcd); + + return 0; +} + +#endif + /*-------------------------------------------------------------------------*/ MODULE_AUTHOR (DRIVER_AUTHOR); @@ -1029,27 +1134,12 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ohci_hcd_ep93xx_driver #endif -#ifdef CONFIG_MIPS_ALCHEMY -#include "ohci-au1xxx.c" -#define PLATFORM_DRIVER ohci_hcd_au1xxx_driver -#endif - -#ifdef CONFIG_PNX8550 -#include "ohci-pnx8550.c" -#define PLATFORM_DRIVER ohci_hcd_pnx8550_driver -#endif - -#ifdef CONFIG_USB_OHCI_HCD_PPC_SOC -#include "ohci-ppc-soc.c" -#define PLATFORM_DRIVER ohci_hcd_ppc_soc_driver -#endif - #ifdef CONFIG_ARCH_AT91 #include "ohci-at91.c" #define PLATFORM_DRIVER ohci_hcd_at91_driver #endif -#if defined(CONFIG_ARCH_PNX4008) || defined(CONFIG_ARCH_LPC32XX) +#ifdef CONFIG_ARCH_LPC32XX #include "ohci-nxp.c" #define PLATFORM_DRIVER usb_hcd_nxp_driver #endif @@ -1059,11 +1149,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ohci_hcd_da8xx_driver #endif -#ifdef CONFIG_USB_OHCI_SH -#include "ohci-sh.c" -#define PLATFORM_DRIVER ohci_hcd_sh_driver -#endif - #ifdef CONFIG_USB_OHCI_HCD_PPC_OF #include "ohci-ppc-of.c" @@ -1105,16 +1190,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ohci_hcd_tilegx_driver #endif -#ifdef CONFIG_USB_CNS3XXX_OHCI -#include "ohci-cns3xxx.c" -#define PLATFORM_DRIVER ohci_hcd_cns3xxx_driver -#endif - -#ifdef CONFIG_CPU_XLR -#include "ohci-xls.c" -#define PLATFORM_DRIVER ohci_xls_driver -#endif - #ifdef CONFIG_USB_OHCI_HCD_PLATFORM #include "ohci-platform.c" #define PLATFORM_DRIVER ohci_platform_driver diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 2f3619eefefa9b..db09dae7b557a1 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -316,48 +316,6 @@ static int ohci_bus_resume (struct usb_hcd *hcd) return rc; } -/* Carry out the final steps of resuming the controller device */ -static void __maybe_unused ohci_finish_controller_resume(struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci(hcd); - int port; - bool need_reinit = false; - - /* See if the controller is already running or has been reset */ - ohci->hc_control = ohci_readl(ohci, &ohci->regs->control); - if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { - need_reinit = true; - } else { - switch (ohci->hc_control & OHCI_CTRL_HCFS) { - case OHCI_USB_OPER: - case OHCI_USB_RESET: - need_reinit = true; - } - } - - /* If needed, reinitialize and suspend the root hub */ - if (need_reinit) { - spin_lock_irq(&ohci->lock); - ohci_rh_resume(ohci); - ohci_rh_suspend(ohci, 0); - spin_unlock_irq(&ohci->lock); - } - - /* Normally just turn on port power and enable interrupts */ - else { - ohci_dbg(ohci, "powerup ports\n"); - for (port = 0; port < ohci->num_ports; port++) - ohci_writel(ohci, RH_PS_PPS, - &ohci->regs->roothub.portstatus[port]); - - ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrenable); - ohci_readl(ohci, &ohci->regs->intrenable); - msleep(20); - } - - usb_hcd_resume_root_hub(hcd); -} - /* Carry out polling-, autostop-, and autoresume-related state changes */ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, int any_connected, int rhsc_status) diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c index 931d588c3fb57c..8062bb9dea16ea 100644 --- a/drivers/usb/host/ohci-jz4740.c +++ b/drivers/usb/host/ohci-jz4740.c @@ -145,7 +145,7 @@ static const struct hc_driver ohci_jz4740_hc_driver = { }; -static __devinit int jz4740_ohci_probe(struct platform_device *pdev) +static int jz4740_ohci_probe(struct platform_device *pdev) { int ret; struct usb_hcd *hcd; @@ -239,7 +239,7 @@ static __devinit int jz4740_ohci_probe(struct platform_device *pdev) return ret; } -static __devexit int jz4740_ohci_remove(struct platform_device *pdev) +static int jz4740_ohci_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd); @@ -266,7 +266,7 @@ static __devexit int jz4740_ohci_remove(struct platform_device *pdev) static struct platform_driver ohci_hcd_jz4740_driver = { .probe = jz4740_ohci_probe, - .remove = __devexit_p(jz4740_ohci_remove), + .remove = jz4740_ohci_remove, .driver = { .name = "jz4740-ohci", .owner = THIS_MODULE, diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c index a446386bf77920..f4988fbe78e799 100644 --- a/drivers/usb/host/ohci-nxp.c +++ b/drivers/usb/host/ohci-nxp.c @@ -2,7 +2,6 @@ * driver for NXP USB Host devices * * Currently supported OHCI host devices: - * - Philips PNX4008 * - NXP LPC32xx * * Authors: Dmitry Chigirev @@ -66,38 +65,6 @@ static struct clk *usb_pll_clk; static struct clk *usb_dev_clk; static struct clk *usb_otg_clk; -static void isp1301_configure_pnx4008(void) -{ - /* PNX4008 only supports DAT_SE0 USB mode */ - /* PNX4008 R2A requires setting the MAX603 to output 3.6V */ - /* Power up externel charge-pump */ - - i2c_smbus_write_byte_data(isp1301_i2c_client, - ISP1301_I2C_MODE_CONTROL_1, MC1_DAT_SE0 | MC1_SPEED_REG); - i2c_smbus_write_byte_data(isp1301_i2c_client, - ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR, - ~(MC1_DAT_SE0 | MC1_SPEED_REG)); - i2c_smbus_write_byte_data(isp1301_i2c_client, - ISP1301_I2C_MODE_CONTROL_2, - MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL); - i2c_smbus_write_byte_data(isp1301_i2c_client, - ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR, - ~(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL)); - i2c_smbus_write_byte_data(isp1301_i2c_client, - ISP1301_I2C_OTG_CONTROL_1, OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN); - i2c_smbus_write_byte_data(isp1301_i2c_client, - ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR, - ~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN)); - i2c_smbus_write_byte_data(isp1301_i2c_client, - ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR, 0xFF); - i2c_smbus_write_byte_data(isp1301_i2c_client, - ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR, - 0xFF); - i2c_smbus_write_byte_data(isp1301_i2c_client, - ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR, - 0xFF); -} - static void isp1301_configure_lpc32xx(void) { /* LPC32XX only supports DAT_SE0 USB mode */ @@ -149,10 +116,7 @@ static void isp1301_configure_lpc32xx(void) static void isp1301_configure(void) { - if (machine_is_pnx4008()) - isp1301_configure_pnx4008(); - else - isp1301_configure_lpc32xx(); + isp1301_configure_lpc32xx(); } static inline void isp1301_vbus_on(void) @@ -183,7 +147,7 @@ static void nxp_stop_hc(void) __raw_writel(tmp, USB_OTG_STAT_CONTROL); } -static int __devinit ohci_nxp_start(struct usb_hcd *hcd) +static int ohci_nxp_start(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); int ret; @@ -241,48 +205,7 @@ static const struct hc_driver ohci_nxp_hc_driver = { .start_port_reset = ohci_start_port_reset, }; -static void nxp_set_usb_bits(void) -{ - if (machine_is_pnx4008()) { - start_int_set_falling_edge(SE_USB_OTG_ATX_INT_N); - start_int_ack(SE_USB_OTG_ATX_INT_N); - start_int_umask(SE_USB_OTG_ATX_INT_N); - - start_int_set_rising_edge(SE_USB_OTG_TIMER_INT); - start_int_ack(SE_USB_OTG_TIMER_INT); - start_int_umask(SE_USB_OTG_TIMER_INT); - - start_int_set_rising_edge(SE_USB_I2C_INT); - start_int_ack(SE_USB_I2C_INT); - start_int_umask(SE_USB_I2C_INT); - - start_int_set_rising_edge(SE_USB_INT); - start_int_ack(SE_USB_INT); - start_int_umask(SE_USB_INT); - - start_int_set_rising_edge(SE_USB_NEED_CLK_INT); - start_int_ack(SE_USB_NEED_CLK_INT); - start_int_umask(SE_USB_NEED_CLK_INT); - - start_int_set_rising_edge(SE_USB_AHB_NEED_CLK_INT); - start_int_ack(SE_USB_AHB_NEED_CLK_INT); - start_int_umask(SE_USB_AHB_NEED_CLK_INT); - } -} - -static void nxp_unset_usb_bits(void) -{ - if (machine_is_pnx4008()) { - start_int_mask(SE_USB_OTG_ATX_INT_N); - start_int_mask(SE_USB_OTG_TIMER_INT); - start_int_mask(SE_USB_I2C_INT); - start_int_mask(SE_USB_INT); - start_int_mask(SE_USB_NEED_CLK_INT); - start_int_mask(SE_USB_AHB_NEED_CLK_INT); - } -} - -static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev) +static int usb_hcd_nxp_probe(struct platform_device *pdev) { struct usb_hcd *hcd = 0; struct ohci_hcd *ohci; @@ -355,7 +278,7 @@ static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev) usb_otg_clk = clk_get(&pdev->dev, "ck_usb_otg"); if (IS_ERR(usb_otg_clk)) { dev_err(&pdev->dev, "failed to acquire USB DEV Clock\n"); - ret = PTR_ERR(usb_dev_clk); + ret = PTR_ERR(usb_otg_clk); goto out6; } @@ -376,9 +299,6 @@ static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev) goto out8; } - /* Set all USB bits in the Start Enable register */ - nxp_set_usb_bits(); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "Failed to get MEM resource\n"); @@ -386,10 +306,9 @@ static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev) goto out8; } - hcd->regs = devm_request_and_ioremap(&pdev->dev, res); - if (!hcd->regs) { - dev_err(&pdev->dev, "Failed to devm_request_and_ioremap\n"); - ret = -ENOMEM; + hcd->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hcd->regs)) { + ret = PTR_ERR(hcd->regs); goto out8; } hcd->rsrc_start = res->start; @@ -413,7 +332,6 @@ static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev) nxp_stop_hc(); out8: - nxp_unset_usb_bits(); usb_put_hcd(hcd); out7: clk_disable(usb_otg_clk); @@ -441,7 +359,6 @@ static int usb_hcd_nxp_remove(struct platform_device *pdev) nxp_stop_hc(); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); - nxp_unset_usb_bits(); clk_disable(usb_pll_clk); clk_put(usb_pll_clk); clk_disable(usb_dev_clk); diff --git a/drivers/usb/host/ohci-octeon.c b/drivers/usb/host/ohci-octeon.c index d469bf9b9e5400..d44430d009f89c 100644 --- a/drivers/usb/host/ohci-octeon.c +++ b/drivers/usb/host/ohci-octeon.c @@ -42,7 +42,7 @@ static void ohci_octeon_hw_stop(void) octeon2_usb_clocks_stop(); } -static int __devinit ohci_octeon_start(struct usb_hcd *hcd) +static int ohci_octeon_start(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); int ret; diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index f8b2d91851f7cb..b1d32fb4a7ae60 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -24,8 +24,7 @@ #include #include -#include -#include +#include #include #include @@ -93,14 +92,14 @@ static int omap_ohci_transceiver_power(int on) { if (on) { if (machine_is_omap_innovator() && cpu_is_omap1510()) - fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL) + __raw_writeb(__raw_readb(INNOVATOR_FPGA_CAM_USB_CONTROL) | ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), INNOVATOR_FPGA_CAM_USB_CONTROL); else if (machine_is_omap_osk()) tps65010_set_gpio_out_value(GPIO1, LOW); } else { if (machine_is_omap_innovator() && cpu_is_omap1510()) - fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL) + __raw_writeb(__raw_readb(INNOVATOR_FPGA_CAM_USB_CONTROL) & ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), INNOVATOR_FPGA_CAM_USB_CONTROL); else if (machine_is_omap_osk()) @@ -530,7 +529,7 @@ static int ohci_omap_resume(struct platform_device *dev) ohci->next_statechange = jiffies; omap_ohci_clock_power(1); - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c index 1b8133b6e451a7..eb35d96302373c 100644 --- a/drivers/usb/host/ohci-omap3.c +++ b/drivers/usb/host/ohci-omap3.c @@ -30,7 +30,6 @@ */ #include -#include #include /*-------------------------------------------------------------------------*/ @@ -125,7 +124,7 @@ static const struct hc_driver ohci_omap3_hc_driver = { * then invokes the start() method for the HCD associated with it * through the hotplug entry's driver_data. */ -static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev) +static int ohci_hcd_omap3_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct usb_hcd *hcd = NULL; @@ -209,7 +208,7 @@ static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev) * the HCD's stop() method. It is always called from a thread * context, normally "rmmod", "apmd", or something similar. */ -static int __devexit ohci_hcd_omap3_remove(struct platform_device *pdev) +static int ohci_hcd_omap3_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct usb_hcd *hcd = dev_get_drvdata(dev); @@ -232,7 +231,7 @@ static void ohci_hcd_omap3_shutdown(struct platform_device *pdev) static struct platform_driver ohci_hcd_omap3_driver = { .probe = ohci_hcd_omap3_probe, - .remove = __devexit_p(ohci_hcd_omap3_remove), + .remove = ohci_hcd_omap3_remove, .shutdown = ohci_hcd_omap3_shutdown, .driver = { .name = "ohci-omap3", diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 1843bb68ac7cee..951514ef446dfa 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -270,7 +270,7 @@ static int ohci_pci_reset (struct usb_hcd *hcd) } -static int __devinit ohci_pci_start (struct usb_hcd *hcd) +static int ohci_pci_start (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); int ret; @@ -296,49 +296,6 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd) return ret; } -#ifdef CONFIG_PM - -static int ohci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - unsigned long flags; - int rc = 0; - - /* Root hub was already suspended. Disable irq emission and - * mark HW unaccessible, bail out if RH has been resumed. Use - * the spinlock to properly synchronize with possible pending - * RH suspend or resume activity. - */ - spin_lock_irqsave (&ohci->lock, flags); - if (ohci->rh_state != OHCI_RH_SUSPENDED) { - rc = -EINVAL; - goto bail; - } - ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); - (void)ohci_readl(ohci, &ohci->regs->intrdisable); - - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - bail: - spin_unlock_irqrestore (&ohci->lock, flags); - - return rc; -} - - -static int ohci_pci_resume(struct usb_hcd *hcd, bool hibernated) -{ - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - - /* Make sure resume from hibernation re-enumerates everything */ - if (hibernated) - ohci_usb_reset(hcd_to_ohci(hcd)); - - ohci_finish_controller_resume(hcd); - return 0; -} - -#endif /* CONFIG_PM */ - /*-------------------------------------------------------------------------*/ @@ -362,8 +319,8 @@ static const struct hc_driver ohci_pci_hc_driver = { .shutdown = ohci_shutdown, #ifdef CONFIG_PM - .pci_suspend = ohci_pci_suspend, - .pci_resume = ohci_pci_resume, + .pci_suspend = ohci_suspend, + .pci_resume = ohci_resume, #endif /* diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index 670c7059c9ae3a..c3e7287f792170 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c @@ -13,6 +13,7 @@ * * Licensed under the GNU/GPL. See COPYING for details. */ +#include #include #include @@ -31,6 +32,10 @@ static int ohci_platform_reset(struct usb_hcd *hcd) ohci->flags |= OHCI_QUIRK_FRAME_NO; ohci_hcd_init(ohci); + + if (pdata->num_ports) + ohci->num_ports = pdata->num_ports; + err = ohci_init(ohci); return err; @@ -79,74 +84,84 @@ static const struct hc_driver ohci_platform_hc_driver = { .start_port_reset = ohci_start_port_reset, }; -static int __devinit ohci_platform_probe(struct platform_device *dev) +static int ohci_platform_probe(struct platform_device *dev) { struct usb_hcd *hcd; struct resource *res_mem; + struct usb_ohci_pdata *pdata = dev->dev.platform_data; int irq; int err = -ENOMEM; - BUG_ON(!dev->dev.platform_data); + if (!pdata) { + WARN_ON(1); + return -ENODEV; + } if (usb_disabled()) return -ENODEV; irq = platform_get_irq(dev, 0); if (irq < 0) { - pr_err("no irq provided"); + dev_err(&dev->dev, "no irq provided"); return irq; } res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res_mem) { - pr_err("no memory recourse provided"); + dev_err(&dev->dev, "no memory resource provided"); return -ENXIO; } + if (pdata->power_on) { + err = pdata->power_on(dev); + if (err < 0) + return err; + } + hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev, dev_name(&dev->dev)); - if (!hcd) - return -ENOMEM; + if (!hcd) { + err = -ENOMEM; + goto err_power; + } hcd->rsrc_start = res_mem->start; hcd->rsrc_len = resource_size(res_mem); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - pr_err("controller already in use"); - err = -EBUSY; + hcd->regs = devm_ioremap_resource(&dev->dev, res_mem); + if (IS_ERR(hcd->regs)) { + err = PTR_ERR(hcd->regs); goto err_put_hcd; } - - hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) - goto err_release_region; err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) - goto err_iounmap; + goto err_put_hcd; platform_set_drvdata(dev, hcd); return err; -err_iounmap: - iounmap(hcd->regs); -err_release_region: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err_put_hcd: usb_put_hcd(hcd); +err_power: + if (pdata->power_off) + pdata->power_off(dev); + return err; } -static int __devexit ohci_platform_remove(struct platform_device *dev) +static int ohci_platform_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); + struct usb_ohci_pdata *pdata = dev->dev.platform_data; usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); platform_set_drvdata(dev, NULL); + if (pdata->power_off) + pdata->power_off(dev); + return 0; } @@ -154,14 +169,30 @@ static int __devexit ohci_platform_remove(struct platform_device *dev) static int ohci_platform_suspend(struct device *dev) { + struct usb_ohci_pdata *pdata = dev->platform_data; + struct platform_device *pdev = + container_of(dev, struct platform_device, dev); + + if (pdata->power_suspend) + pdata->power_suspend(pdev); + return 0; } static int ohci_platform_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); + struct usb_ohci_pdata *pdata = dev->platform_data; + struct platform_device *pdev = + container_of(dev, struct platform_device, dev); + + if (pdata->power_on) { + int err = pdata->power_on(pdev); + if (err < 0) + return err; + } - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } @@ -184,7 +215,7 @@ static const struct dev_pm_ops ohci_platform_pm_ops = { static struct platform_driver ohci_platform_driver = { .id_table = ohci_platform_table, .probe = ohci_platform_probe, - .remove = __devexit_p(ohci_platform_remove), + .remove = ohci_platform_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .owner = THIS_MODULE, diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index e27d5ae2b9ebf1..64c2ed9ff95e80 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c @@ -19,7 +19,7 @@ #include -static int __devinit +static int ohci_ppc_of_start(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); @@ -81,7 +81,7 @@ static const struct hc_driver ohci_ppc_of_hc_driver = { }; -static int __devinit ohci_hcd_ppc_of_probe(struct platform_device *op) +static int ohci_hcd_ppc_of_probe(struct platform_device *op) { struct device_node *dn = op->dev.of_node; struct usb_hcd *hcd; diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c index 2ee1d8d713d23d..7d35cd9e286271 100644 --- a/drivers/usb/host/ohci-ps3.c +++ b/drivers/usb/host/ohci-ps3.c @@ -30,7 +30,7 @@ static int ps3_ohci_hc_reset(struct usb_hcd *hcd) return ohci_init(ohci); } -static int __devinit ps3_ohci_hc_start(struct usb_hcd *hcd) +static int ps3_ohci_hc_start(struct usb_hcd *hcd) { int result; struct ohci_hcd *ohci = hcd_to_ohci(hcd); @@ -76,7 +76,7 @@ static const struct hc_driver ps3_ohci_hc_driver = { #endif }; -static int __devinit ps3_ohci_probe(struct ps3_system_bus_device *dev) +static int ps3_ohci_probe(struct ps3_system_bus_device *dev) { int result; struct usb_hcd *hcd; diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index e1a3cc6d28dcc0..efe71f3ca47720 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -23,9 +23,11 @@ #include #include #include +#include +#include #include -#include -#include +#include +#include /* * UHC: USB Host Controller (OHCI-like) register definitions @@ -272,6 +274,67 @@ static void pxa27x_stop_hc(struct pxa27x_ohci *ohci, struct device *dev) clk_disable_unprepare(ohci->clk); } +#ifdef CONFIG_OF +static const struct of_device_id pxa_ohci_dt_ids[] = { + { .compatible = "marvell,pxa-ohci" }, + { } +}; + +MODULE_DEVICE_TABLE(of, pxa_ohci_dt_ids); + +static u64 pxa_ohci_dma_mask = DMA_BIT_MASK(32); + +static int ohci_pxa_of_init(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct pxaohci_platform_data *pdata; + u32 tmp; + + if (!np) + return 0; + + /* Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we have dma capability bindings this can go away. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &pxa_ohci_dma_mask; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + if (of_get_property(np, "marvell,enable-port1", NULL)) + pdata->flags |= ENABLE_PORT1; + if (of_get_property(np, "marvell,enable-port2", NULL)) + pdata->flags |= ENABLE_PORT2; + if (of_get_property(np, "marvell,enable-port3", NULL)) + pdata->flags |= ENABLE_PORT3; + if (of_get_property(np, "marvell,port-sense-low", NULL)) + pdata->flags |= POWER_SENSE_LOW; + if (of_get_property(np, "marvell,power-control-low", NULL)) + pdata->flags |= POWER_CONTROL_LOW; + if (of_get_property(np, "marvell,no-oc-protection", NULL)) + pdata->flags |= NO_OC_PROTECTION; + if (of_get_property(np, "marvell,oc-mode-perport", NULL)) + pdata->flags |= OC_MODE_PERPORT; + if (!of_property_read_u32(np, "marvell,power-on-delay", &tmp)) + pdata->power_on_delay = tmp; + if (!of_property_read_u32(np, "marvell,port-mode", &tmp)) + pdata->port_mode = tmp; + if (!of_property_read_u32(np, "marvell,power-budget", &tmp)) + pdata->power_budget = tmp; + + pdev->dev.platform_data = pdata; + + return 0; +} +#else +static int ohci_pxa_of_init(struct platform_device *pdev) +{ + return 0; +} +#endif /*-------------------------------------------------------------------------*/ @@ -297,6 +360,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device struct resource *r; struct clk *usb_clk; + retval = ohci_pxa_of_init(pdev); + if (retval) + return retval; + inf = pdev->dev.platform_data; if (!inf) @@ -404,7 +471,7 @@ void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev) /*-------------------------------------------------------------------------*/ -static int __devinit +static int ohci_pxa27x_start (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); @@ -524,7 +591,7 @@ static int ohci_hcd_pxa27x_drv_resume(struct device *dev) /* Select Power Management Mode */ pxa27x_ohci_select_pmm(ohci, inf->port_mode); - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } @@ -544,6 +611,7 @@ static struct platform_driver ohci_hcd_pxa27x_driver = { .driver = { .name = "pxa27x-ohci", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(pxa_ohci_dt_ids), #ifdef CONFIG_PM .pm = &ohci_hcd_pxa27x_pm_ops, #endif diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index 9d00d4721bca6f..88731b7c5f4290 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -44,6 +44,7 @@ __acquires(ohci->lock) // ASSERT (urb->hcpriv != 0); urb_free_priv (ohci, urb->hcpriv); + urb->hcpriv = NULL; if (likely(status == -EINPROGRESS)) status = 0; @@ -596,7 +597,6 @@ static void td_submit_urb ( urb_priv->ed->hwHeadP &= ~cpu_to_hc32 (ohci, ED_C); } - urb_priv->td_cnt = 0; list_add (&urb_priv->pending, &ohci->pending); if (data_len) @@ -672,7 +672,8 @@ static void td_submit_urb ( * we could often reduce the number of TDs here. */ case PIPE_ISOCHRONOUS: - for (cnt = 0; cnt < urb->number_of_packets; cnt++) { + for (cnt = urb_priv->td_cnt; cnt < urb->number_of_packets; + cnt++) { int frame = urb->start_frame; // FIXME scheduling should handle frame counter diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 664c869eb096bf..e125770b893c39 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -21,7 +21,7 @@ #include #include -#include +#include #define valid_port(idx) ((idx) == 1 || (idx) == 2) @@ -323,8 +323,6 @@ usb_hcd_s3c2410_remove(struct usb_hcd *hcd, struct platform_device *dev) { usb_remove_hcd(hcd); s3c2410_stop_hc(dev); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); } @@ -353,35 +351,28 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, hcd->rsrc_start = dev->resource[0].start; hcd->rsrc_len = resource_size(&dev->resource[0]); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - dev_err(&dev->dev, "request_mem_region failed\n"); - retval = -EBUSY; + hcd->regs = devm_ioremap_resource(&dev->dev, &dev->resource[0]); + if (IS_ERR(hcd->regs)) { + retval = PTR_ERR(hcd->regs); goto err_put; } - clk = clk_get(&dev->dev, "usb-host"); + clk = devm_clk_get(&dev->dev, "usb-host"); if (IS_ERR(clk)) { dev_err(&dev->dev, "cannot get usb-host clock\n"); retval = PTR_ERR(clk); - goto err_mem; + goto err_put; } - usb_clk = clk_get(&dev->dev, "usb-bus-host"); + usb_clk = devm_clk_get(&dev->dev, "usb-bus-host"); if (IS_ERR(usb_clk)) { dev_err(&dev->dev, "cannot get usb-bus-host clock\n"); retval = PTR_ERR(usb_clk); - goto err_clk; + goto err_put; } s3c2410_start_hc(dev, hcd); - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - dev_err(&dev->dev, "ioremap failed\n"); - retval = -ENOMEM; - goto err_ioremap; - } - ohci_hcd_init(hcd_to_ohci(hcd)); retval = usb_add_hcd(hcd, dev->resource[1].start, 0); @@ -392,14 +383,6 @@ static int usb_hcd_s3c2410_probe(const struct hc_driver *driver, err_ioremap: s3c2410_stop_hc(dev); - iounmap(hcd->regs); - clk_put(usb_clk); - - err_clk: - clk_put(clk); - - err_mem: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err_put: usb_put_hcd(hcd); @@ -474,12 +457,12 @@ static const struct hc_driver ohci_s3c2410_hc_driver = { /* device driver */ -static int __devinit ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev) +static int ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev) { return usb_hcd_s3c2410_probe(&ohci_s3c2410_hc_driver, pdev); } -static int __devexit ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev) +static int ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); @@ -524,8 +507,7 @@ static int ohci_hcd_s3c2410_drv_resume(struct device *dev) s3c2410_start_hc(pdev, hcd); - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } @@ -541,7 +523,7 @@ static const struct dev_pm_ops ohci_hcd_s3c2410_pm_ops = { static struct platform_driver ohci_hcd_s3c2410_driver = { .probe = ohci_hcd_s3c2410_drv_probe, - .remove = __devexit_p(ohci_hcd_s3c2410_drv_remove), + .remove = ohci_hcd_s3c2410_drv_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .owner = THIS_MODULE, diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c index b6cc925209246f..17b2a7dad77b81 100644 --- a/drivers/usb/host/ohci-sa1111.c +++ b/drivers/usb/host/ohci-sa1111.c @@ -63,7 +63,7 @@ static int ohci_sa1111_reset(struct usb_hcd *hcd) return ohci_init(ohci); } -static int __devinit ohci_sa1111_start(struct usb_hcd *hcd) +static int ohci_sa1111_start(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); int ret; diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c index 5596ac2ba1ca55..3b5b908fd47b29 100644 --- a/drivers/usb/host/ohci-sm501.c +++ b/drivers/usb/host/ohci-sm501.c @@ -238,7 +238,7 @@ static int ohci_sm501_resume(struct platform_device *pdev) ohci->next_statechange = jiffies; sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1); - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } #else diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c index fc7305ee3c9cd4..9020bf0e2eca13 100644 --- a/drivers/usb/host/ohci-spear.c +++ b/drivers/usb/host/ohci-spear.c @@ -33,7 +33,7 @@ static void spear_stop_ohci(struct spear_ohci *ohci) clk_disable_unprepare(ohci->clk); } -static int __devinit ohci_spear_start(struct usb_hcd *hcd) +static int ohci_spear_start(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); int ret; @@ -101,13 +101,11 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) struct spear_ohci *ohci_p; struct resource *res; int retval, irq; - char clk_name[20] = "usbh_clk"; - static int instance = -1; irq = platform_get_irq(pdev, 0); if (irq < 0) { retval = irq; - goto fail_irq_get; + goto fail; } /* @@ -118,47 +116,39 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) if (!pdev->dev.dma_mask) pdev->dev.dma_mask = &spear_ohci_dma_mask; - /* - * Increment the device instance, when probing via device-tree - */ - if (pdev->id < 0) - instance++; - else - instance = pdev->id; - sprintf(clk_name, "usbh.%01d_clk", instance); - - usbh_clk = clk_get(NULL, clk_name); + usbh_clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(usbh_clk)) { dev_err(&pdev->dev, "Error getting interface clock\n"); retval = PTR_ERR(usbh_clk); - goto fail_get_usbh_clk; + goto fail; } hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { retval = -ENOMEM; - goto fail_create_hcd; + goto fail; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { retval = -ENODEV; - goto fail_request_resource; + goto err_put_hcd; } hcd->rsrc_start = pdev->resource[0].start; hcd->rsrc_len = resource_size(res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { + if (!devm_request_mem_region(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len, + hcd_name)) { dev_dbg(&pdev->dev, "request_mem_region failed\n"); retval = -EBUSY; - goto fail_request_resource; + goto err_put_hcd; } - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_ioremap(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { dev_dbg(&pdev->dev, "ioremap failed\n"); retval = -ENOMEM; - goto fail_ioremap; + goto err_put_hcd; } ohci_p = (struct spear_ohci *)hcd_to_ohci(hcd); @@ -171,15 +161,9 @@ static int spear_ohci_hcd_drv_probe(struct platform_device *pdev) return retval; spear_stop_ohci(ohci_p); - iounmap(hcd->regs); -fail_ioremap: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -fail_request_resource: +err_put_hcd: usb_put_hcd(hcd); -fail_create_hcd: - clk_put(usbh_clk); -fail_get_usbh_clk: -fail_irq_get: +fail: dev_err(&pdev->dev, "init fail, %d\n", retval); return retval; @@ -194,12 +178,8 @@ static int spear_ohci_hcd_drv_remove(struct platform_device *pdev) if (ohci_p->clk) spear_stop_ohci(ohci_p); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); - if (ohci_p->clk) - clk_put(ohci_p->clk); platform_set_drvdata(pdev, NULL); return 0; } @@ -231,12 +211,12 @@ static int spear_ohci_hcd_drv_resume(struct platform_device *dev) ohci->next_statechange = jiffies; spear_start_ohci(ohci_p); - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } #endif -static struct of_device_id spear_ohci_id_table[] __devinitdata = { +static struct of_device_id spear_ohci_id_table[] = { { .compatible = "st,spear600-ohci", }, { }, }; diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c index 60c2b0722f2e16..5e3a6deb62b1e7 100644 --- a/drivers/usb/host/ohci-tmio.c +++ b/drivers/usb/host/ohci-tmio.c @@ -128,7 +128,8 @@ static void tmio_start_hc(struct platform_device *dev) tmio_iowrite8(2, tmio->ccr + CCR_INTC); dev_info(&dev->dev, "revision %d @ 0x%08llx, irq %d\n", - tmio_ioread8(tmio->ccr + CCR_REVID), hcd->rsrc_start, hcd->irq); + tmio_ioread8(tmio->ccr + CCR_REVID), + (u64) hcd->rsrc_start, hcd->irq); } static int ohci_tmio_start(struct usb_hcd *hcd) @@ -184,7 +185,7 @@ static const struct hc_driver ohci_tmio_hc_driver = { /*-------------------------------------------------------------------------*/ static struct platform_driver ohci_hcd_tmio_driver; -static int __devinit ohci_hcd_tmio_drv_probe(struct platform_device *dev) +static int ohci_hcd_tmio_drv_probe(struct platform_device *dev) { const struct mfd_cell *cell = mfd_get_cell(dev); struct resource *regs = platform_get_resource(dev, IORESOURCE_MEM, 0); @@ -271,7 +272,7 @@ static int __devinit ohci_hcd_tmio_drv_probe(struct platform_device *dev) return ret; } -static int __devexit ohci_hcd_tmio_drv_remove(struct platform_device *dev) +static int ohci_hcd_tmio_drv_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct tmio_hcd *tmio = hcd_to_tmio(hcd); @@ -352,7 +353,7 @@ static int ohci_hcd_tmio_drv_resume(struct platform_device *dev) spin_unlock_irqrestore(&tmio->lock, flags); - ohci_finish_controller_resume(hcd); + ohci_resume(hcd, false); return 0; } @@ -363,7 +364,7 @@ static int ohci_hcd_tmio_drv_resume(struct platform_device *dev) static struct platform_driver ohci_hcd_tmio_driver = { .probe = ohci_hcd_tmio_drv_probe, - .remove = __devexit_p(ohci_hcd_tmio_drv_remove), + .remove = ohci_hcd_tmio_drv_remove, .shutdown = usb_hcd_platform_shutdown, .suspend = ohci_hcd_tmio_drv_suspend, .resume = ohci_hcd_tmio_drv_resume, diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 39f9e4a9a2d3f0..4c338ec03a07d1 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -443,7 +443,7 @@ static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask) #define pio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_IO) #define mmio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_MEMORY) -static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev) +static void quirk_usb_handoff_uhci(struct pci_dev *pdev) { unsigned long base = 0; int i; @@ -461,12 +461,12 @@ static void __devinit quirk_usb_handoff_uhci(struct pci_dev *pdev) uhci_check_and_reset_hc(pdev, base); } -static int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx) +static int mmio_resource_enabled(struct pci_dev *pdev, int idx) { return pci_resource_start(pdev, idx) && mmio_enabled(pdev); } -static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) +static void quirk_usb_handoff_ohci(struct pci_dev *pdev) { void __iomem *base; u32 control; @@ -533,7 +533,7 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) iounmap(base); } -static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = { +static const struct dmi_system_id ehci_dmi_nohandoff_table[] = { { /* Pegatron Lucid (ExoPC) */ .matches = { @@ -558,7 +558,7 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = { { } }; -static void __devinit ehci_bios_handoff(struct pci_dev *pdev, +static void ehci_bios_handoff(struct pci_dev *pdev, void __iomem *op_reg_base, u32 cap, u8 offset) { @@ -626,7 +626,7 @@ static void __devinit ehci_bios_handoff(struct pci_dev *pdev, writel(0, op_reg_base + EHCI_CONFIGFLAG); } -static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) +static void quirk_usb_disable_ehci(struct pci_dev *pdev) { void __iomem *base, *op_reg_base; u32 hcc_params, cap, val; @@ -723,6 +723,7 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done, } #define PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI 0x8C31 +#define PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI 0x9C31 bool usb_is_intel_ppt_switchable_xhci(struct pci_dev *pdev) { @@ -736,7 +737,8 @@ bool usb_is_intel_lpt_switchable_xhci(struct pci_dev *pdev) { return pdev->class == PCI_CLASS_SERIAL_USB_XHCI && pdev->vendor == PCI_VENDOR_ID_INTEL && - pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI; + (pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI); } bool usb_is_intel_switchable_xhci(struct pci_dev *pdev) @@ -778,6 +780,7 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) "defaulting to EHCI.\n"); dev_warn(&xhci_pdev->dev, "USB 3.0 devices will work at USB 2.0 speeds.\n"); + usb_disable_xhci_ports(xhci_pdev); return; } @@ -841,7 +844,7 @@ EXPORT_SYMBOL_GPL(usb_disable_xhci_ports); * and then waits 5 seconds for the BIOS to hand over control. * If we timeout, assume the BIOS is broken and take control anyway. */ -static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) +static void quirk_usb_handoff_xhci(struct pci_dev *pdev) { void __iomem *base; int ext_cap_offset; @@ -941,7 +944,7 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) iounmap(base); } -static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) +static void quirk_usb_early_handoff(struct pci_dev *pdev) { /* Skip Netlogic mips SoC's internal PCI USB controller. * This device does not need/support EHCI/OHCI handoff diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 4c634eb56358a1..a6fd8f5371dfd9 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2029,18 +2029,15 @@ static int r8a66597_get_frame(struct usb_hcd *hcd) static void collect_usb_address_map(struct usb_device *udev, unsigned long *map) { int chix; + struct usb_device *childdev; if (udev->state == USB_STATE_CONFIGURED && udev->parent && udev->parent->devnum > 1 && udev->parent->descriptor.bDeviceClass == USB_CLASS_HUB) map[udev->devnum/32] |= (1 << (udev->devnum % 32)); - for (chix = 0; chix < udev->maxchild; chix++) { - struct usb_device *childdev = udev->children[chix]; - - if (childdev) - collect_usb_address_map(childdev, map); - } + usb_hub_for_each_child(udev, chix, childdev) + collect_usb_address_map(childdev, map); } /* this function must be called with interrupt disabled */ @@ -2394,7 +2391,7 @@ static const struct dev_pm_ops r8a66597_dev_pm_ops = { #define R8A66597_DEV_PM_OPS NULL #endif -static int __devexit r8a66597_remove(struct platform_device *pdev) +static int r8a66597_remove(struct platform_device *pdev) { struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev); struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597); @@ -2408,7 +2405,7 @@ static int __devexit r8a66597_remove(struct platform_device *pdev) return 0; } -static int __devinit r8a66597_probe(struct platform_device *pdev) +static int r8a66597_probe(struct platform_device *pdev) { char clk_name[8]; struct resource *res = NULL, *ires; @@ -2535,7 +2532,7 @@ static int __devinit r8a66597_probe(struct platform_device *pdev) static struct platform_driver r8a66597_driver = { .probe = r8a66597_probe, - .remove = __devexit_p(r8a66597_remove), + .remove = r8a66597_remove, .driver = { .name = (char *) hcd_name, .owner = THIS_MODULE, diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 91ce1c02e6173d..d62f0404baaa63 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -156,7 +156,7 @@ static void setup_packet( writeb(SL_SETUP /* | ep->epnum */, data_reg); writeb(usb_pipedevice(urb->pipe), data_reg); - /* always OUT/data0 */ ; + /* always OUT/data0 */ sl811_write(sl811, bank + SL11H_HOSTCTLREG, control | SL11H_HCTLMASK_OUT); ep->length = 0; @@ -1595,7 +1595,7 @@ static struct hc_driver sl811h_hc_driver = { /*-------------------------------------------------------------------------*/ -static int __devexit +static int sl811h_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); @@ -1618,7 +1618,7 @@ sl811h_remove(struct platform_device *dev) return 0; } -static int __devinit +static int sl811h_probe(struct platform_device *dev) { struct usb_hcd *hcd; @@ -1808,7 +1808,7 @@ sl811h_resume(struct platform_device *dev) /* this driver is exported so sl811_cs can depend on it */ struct platform_driver sl811h_driver = { .probe = sl811h_probe, - .remove = __devexit_p(sl811h_remove), + .remove = sl811h_remove, .suspend = sl811h_suspend, .resume = sl811h_resume, diff --git a/drivers/usb/host/ssb-hcd.c b/drivers/usb/host/ssb-hcd.c index c2a29faba076d9..74af2c6287d267 100644 --- a/drivers/usb/host/ssb-hcd.c +++ b/drivers/usb/host/ssb-hcd.c @@ -39,7 +39,7 @@ struct ssb_hcd_device { u32 enable_flags; }; -static void __devinit ssb_hcd_5354wa(struct ssb_device *dev) +static void ssb_hcd_5354wa(struct ssb_device *dev) { #ifdef CONFIG_SSB_DRIVER_MIPS /* Work around for 5354 failures */ @@ -53,7 +53,7 @@ static void __devinit ssb_hcd_5354wa(struct ssb_device *dev) #endif } -static void __devinit ssb_hcd_usb20wa(struct ssb_device *dev) +static void ssb_hcd_usb20wa(struct ssb_device *dev) { if (dev->id.coreid == SSB_DEV_USB20_HOST) { /* @@ -80,7 +80,7 @@ static void __devinit ssb_hcd_usb20wa(struct ssb_device *dev) } /* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */ -static u32 __devinit ssb_hcd_init_chip(struct ssb_device *dev) +static u32 ssb_hcd_init_chip(struct ssb_device *dev) { u32 flags = 0; @@ -101,8 +101,7 @@ static const struct usb_ehci_pdata ehci_pdata = { static const struct usb_ohci_pdata ohci_pdata = { }; -static struct platform_device * __devinit -ssb_hcd_create_pdev(struct ssb_device *dev, bool ohci, u32 addr, u32 len) +static struct platform_device *ssb_hcd_create_pdev(struct ssb_device *dev, bool ohci, u32 addr, u32 len) { struct platform_device *hci_dev; struct resource hci_res[2]; @@ -148,7 +147,7 @@ ssb_hcd_create_pdev(struct ssb_device *dev, bool ohci, u32 addr, u32 len) return ERR_PTR(ret); } -static int __devinit ssb_hcd_probe(struct ssb_device *dev, +static int ssb_hcd_probe(struct ssb_device *dev, const struct ssb_device_id *id) { int err, tmp; @@ -207,7 +206,7 @@ static int __devinit ssb_hcd_probe(struct ssb_device *dev, return err; } -static void __devexit ssb_hcd_remove(struct ssb_device *dev) +static void ssb_hcd_remove(struct ssb_device *dev) { struct ssb_hcd_device *usb_dev = ssb_get_drvdata(dev); struct platform_device *ohci_dev = usb_dev->ohci_dev; @@ -221,7 +220,7 @@ static void __devexit ssb_hcd_remove(struct ssb_device *dev) ssb_device_disable(dev, 0); } -static void __devexit ssb_hcd_shutdown(struct ssb_device *dev) +static void ssb_hcd_shutdown(struct ssb_device *dev) { ssb_device_disable(dev, 0); } @@ -249,7 +248,7 @@ static int ssb_hcd_resume(struct ssb_device *dev) #define ssb_hcd_resume NULL #endif /* CONFIG_PM */ -static const struct ssb_device_id ssb_hcd_table[] __devinitconst = { +static const struct ssb_device_id ssb_hcd_table[] = { SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV), SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV), SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV), @@ -261,7 +260,7 @@ static struct ssb_driver ssb_hcd_driver = { .name = KBUILD_MODNAME, .id_table = ssb_hcd_table, .probe = ssb_hcd_probe, - .remove = __devexit_p(ssb_hcd_remove), + .remove = ssb_hcd_remove, .shutdown = ssb_hcd_shutdown, .suspend = ssb_hcd_suspend, .resume = ssb_hcd_resume, diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index dbbd1ba2522412..5efdffe3236572 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -2990,7 +2990,7 @@ static struct hc_driver u132_hc_driver = { * synchronously - but instead should immediately stop activity to the * device and asynchronously call usb_remove_hcd() */ -static int __devexit u132_remove(struct platform_device *pdev) +static int u132_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); if (hcd) { @@ -3084,7 +3084,7 @@ static void u132_initialise(struct u132 *u132, struct platform_device *pdev) mutex_unlock(&u132->sw_lock); } -static int __devinit u132_probe(struct platform_device *pdev) +static int u132_probe(struct platform_device *pdev) { struct usb_hcd *hcd; int retval; @@ -3212,7 +3212,7 @@ static int u132_resume(struct platform_device *pdev) */ static struct platform_driver u132_platform_driver = { .probe = u132_probe, - .remove = __devexit_p(u132_remove), + .remove = u132_remove, .suspend = u132_suspend, .resume = u132_resume, .driver = { diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index fc0b0daac93d25..45573754652534 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -16,6 +16,8 @@ #include "uhci-hcd.h" +#define EXTRA_SPACE 1024 + static struct dentry *uhci_debugfs_root; #ifdef DEBUG @@ -44,10 +46,6 @@ static int uhci_show_td(struct uhci_hcd *uhci, struct uhci_td *td, char *buf, char *spid; u32 status, token; - /* Try to make sure there's enough memory */ - if (len < 160) - return 0; - status = td_status(uhci, td); out += sprintf(out, "%*s[%p] link (%08x) ", space, "", td, hc32_to_cpu(uhci, td->link)); @@ -64,6 +62,8 @@ static int uhci_show_td(struct uhci_hcd *uhci, struct uhci_td *td, char *buf, (status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "", (status & TD_CTRL_BITSTUFF) ? "BitStuff " : "", status & 0x7ff); + if (out - buf > len) + goto done; token = td_token(uhci, td); switch (uhci_packetid(token)) { @@ -90,6 +90,9 @@ static int uhci_show_td(struct uhci_hcd *uhci, struct uhci_td *td, char *buf, spid); out += sprintf(out, "(buf=%08x)\n", hc32_to_cpu(uhci, td->buffer)); +done: + if (out - buf > len) + out += sprintf(out, " ...\n"); return out - buf; } @@ -101,8 +104,6 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, int i, nactive, ninactive; char *ptype; - if (len < 200) - return 0; out += sprintf(out, "urb_priv [%p] ", urbp); out += sprintf(out, "urb [%p] ", urbp->urb); @@ -110,6 +111,8 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe)); out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe), (usb_pipein(urbp->urb->pipe) ? "IN" : "OUT")); + if (out - buf > len) + goto done; switch (usb_pipetype(urbp->urb->pipe)) { case PIPE_ISOCHRONOUS: ptype = "ISO"; break; @@ -128,6 +131,9 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked); out += sprintf(out, "\n"); + if (out - buf > len) + goto done; + i = nactive = ninactive = 0; list_for_each_entry(td, &urbp->td_list, list) { if (urbp->qh->type != USB_ENDPOINT_XFER_ISOC && @@ -135,6 +141,8 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, out += sprintf(out, "%*s%d: ", space + 2, "", i); out += uhci_show_td(uhci, td, out, len - (out - buf), 0); + if (out - buf > len) + goto tail; } else { if (td_status(uhci, td) & TD_CTRL_ACTIVE) ++nactive; @@ -143,10 +151,13 @@ static int uhci_show_urbp(struct uhci_hcd *uhci, struct urb_priv *urbp, } } if (nactive + ninactive > 0) - out += sprintf(out, "%*s[skipped %d inactive and %d active " - "TDs]\n", + out += sprintf(out, + "%*s[skipped %d inactive and %d active TDs]\n", space, "", ninactive, nactive); - +done: + if (out - buf > len) + out += sprintf(out, " ...\n"); +tail: return out - buf; } @@ -158,10 +169,6 @@ static int uhci_show_qh(struct uhci_hcd *uhci, __hc32 element = qh_element(qh); char *qtype; - /* Try to make sure there's enough memory */ - if (len < 80 * 7) - return 0; - switch (qh->type) { case USB_ENDPOINT_XFER_ISOC: qtype = "ISO"; break; case USB_ENDPOINT_XFER_INT: qtype = "INT"; break; @@ -175,13 +182,15 @@ static int uhci_show_qh(struct uhci_hcd *uhci, hc32_to_cpu(uhci, qh->link), hc32_to_cpu(uhci, element)); if (qh->type == USB_ENDPOINT_XFER_ISOC) - out += sprintf(out, "%*s period %d phase %d load %d us, " - "frame %x desc [%p]\n", + out += sprintf(out, + "%*s period %d phase %d load %d us, frame %x desc [%p]\n", space, "", qh->period, qh->phase, qh->load, qh->iso_frame, qh->iso_packet_desc); else if (qh->type == USB_ENDPOINT_XFER_INT) out += sprintf(out, "%*s period %d phase %d load %d us\n", space, "", qh->period, qh->phase, qh->load); + if (out - buf > len) + goto done; if (element & UHCI_PTR_QH(uhci)) out += sprintf(out, "%*s Element points to QH (bug?)\n", space, ""); @@ -195,11 +204,17 @@ static int uhci_show_qh(struct uhci_hcd *uhci, if (!(element & ~(UHCI_PTR_QH(uhci) | UHCI_PTR_DEPTH(uhci)))) out += sprintf(out, "%*s Element is NULL (bug?)\n", space, ""); + if (out - buf > len) + goto done; + if (list_empty(&qh->queue)) { out += sprintf(out, "%*s queue is empty\n", space, ""); - if (qh == uhci->skel_async_qh) + if (qh == uhci->skel_async_qh) { out += uhci_show_td(uhci, uhci->term_td, out, len - (out - buf), 0); + if (out - buf > len) + goto tail; + } } else { struct urb_priv *urbp = list_entry(qh->queue.next, struct urb_priv, node); @@ -211,9 +226,12 @@ static int uhci_show_qh(struct uhci_hcd *uhci, space, ""); i = nurbs = 0; list_for_each_entry(urbp, &qh->queue, node) { - if (++i <= 10) + if (++i <= 10) { out += uhci_show_urbp(uhci, urbp, out, len - (out - buf), space + 2); + if (out - buf > len) + goto tail; + } else ++nurbs; } @@ -222,24 +240,27 @@ static int uhci_show_qh(struct uhci_hcd *uhci, space, "", nurbs); } + if (out - buf > len) + goto done; + if (qh->dummy_td) { out += sprintf(out, "%*s Dummy TD\n", space, ""); out += uhci_show_td(uhci, qh->dummy_td, out, len - (out - buf), 0); + if (out - buf > len) + goto tail; } +done: + if (out - buf > len) + out += sprintf(out, " ...\n"); +tail: return out - buf; } -static int uhci_show_sc(int port, unsigned short status, char *buf, int len) +static int uhci_show_sc(int port, unsigned short status, char *buf) { - char *out = buf; - - /* Try to make sure there's enough memory */ - if (len < 160) - return 0; - - out += sprintf(out, " stat%d = %04x %s%s%s%s%s%s%s%s%s%s\n", + return sprintf(buf, " stat%d = %04x %s%s%s%s%s%s%s%s%s%s\n", port, status, (status & USBPORTSC_SUSP) ? " Suspend" : "", @@ -252,19 +273,12 @@ static int uhci_show_sc(int port, unsigned short status, char *buf, int len) (status & USBPORTSC_PE) ? " Enabled" : "", (status & USBPORTSC_CSC) ? " ConnectChange" : "", (status & USBPORTSC_CCS) ? " Connected" : ""); - - return out - buf; } -static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf, int len) +static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf) { - char *out = buf; char *rh_state; - /* Try to make sure there's enough memory */ - if (len < 60) - return 0; - switch (uhci->rh_state) { case UHCI_RH_RESET: rh_state = "reset"; break; @@ -283,9 +297,8 @@ static int uhci_show_root_hub_state(struct uhci_hcd *uhci, char *buf, int len) default: rh_state = "?"; break; } - out += sprintf(out, "Root-hub state: %s FSBR: %d\n", + return sprintf(buf, "Root-hub state: %s FSBR: %d\n", rh_state, uhci->fsbr_is_on); - return out - buf; } static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) @@ -296,9 +309,6 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) unsigned char sof; unsigned short portsc1, portsc2; - /* Try to make sure there's enough memory */ - if (len < 80 * 9) - return 0; usbcmd = uhci_readw(uhci, 0); usbstat = uhci_readw(uhci, 2); @@ -319,6 +329,8 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) (usbcmd & USBCMD_GRESET) ? "GRESET " : "", (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "", (usbcmd & USBCMD_RS) ? "RS " : ""); + if (out - buf > len) + goto done; out += sprintf(out, " usbstat = %04x %s%s%s%s%s%s\n", usbstat, @@ -328,19 +340,33 @@ static int uhci_show_status(struct uhci_hcd *uhci, char *buf, int len) (usbstat & USBSTS_RD) ? "ResumeDetect " : "", (usbstat & USBSTS_ERROR) ? "USBError " : "", (usbstat & USBSTS_USBINT) ? "USBINT " : ""); + if (out - buf > len) + goto done; out += sprintf(out, " usbint = %04x\n", usbint); out += sprintf(out, " usbfrnum = (%d)%03x\n", (usbfrnum >> 10) & 1, 0xfff & (4*(unsigned int)usbfrnum)); out += sprintf(out, " flbaseadd = %08x\n", flbaseadd); out += sprintf(out, " sof = %02x\n", sof); - out += uhci_show_sc(1, portsc1, out, len - (out - buf)); - out += uhci_show_sc(2, portsc2, out, len - (out - buf)); - out += sprintf(out, "Most recent frame: %x (%d) " - "Last ISO frame: %x (%d)\n", + if (out - buf > len) + goto done; + + out += uhci_show_sc(1, portsc1, out); + if (out - buf > len) + goto done; + + out += uhci_show_sc(2, portsc2, out); + if (out - buf > len) + goto done; + + out += sprintf(out, + "Most recent frame: %x (%d) Last ISO frame: %x (%d)\n", uhci->frame_number, uhci->frame_number & 1023, uhci->last_iso_frame, uhci->last_iso_frame & 1023); +done: + if (out - buf > len) + out += sprintf(out, " ...\n"); return out - buf; } @@ -360,9 +386,13 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) "int8", "int4", "int2", "async", "term" }; - out += uhci_show_root_hub_state(uhci, out, len - (out - buf)); + out += uhci_show_root_hub_state(uhci, out); + if (out - buf > len) + goto done; out += sprintf(out, "HC status\n"); out += uhci_show_status(uhci, out, len - (out - buf)); + if (out - buf > len) + goto tail; out += sprintf(out, "Periodic load table\n"); for (i = 0; i < MAX_PHASE; ++i) { @@ -375,7 +405,7 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) uhci_to_hcd(uhci)->self.bandwidth_int_reqs, uhci_to_hcd(uhci)->self.bandwidth_isoc_reqs); if (debug <= 1) - return out - buf; + goto tail; out += sprintf(out, "Frame List\n"); nframes = 10; @@ -383,6 +413,8 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) for (i = 0; i < UHCI_NUMFRAMES; ++i) { __hc32 qh_dma; + if (out - buf > len) + goto done; j = 0; td = uhci->frame_cpu[i]; link = uhci->frame[i]; @@ -401,15 +433,20 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) td = list_entry(tmp, struct uhci_td, fl_list); tmp = tmp->next; if (link != LINK_TO_TD(uhci, td)) { - if (nframes > 0) - out += sprintf(out, " link does " - "not match list entry!\n"); - else + if (nframes > 0) { + out += sprintf(out, + " link does not match list entry!\n"); + if (out - buf > len) + goto done; + } else ++nerrs; } - if (nframes > 0) + if (nframes > 0) { out += uhci_show_td(uhci, td, out, len - (out - buf), 4); + if (out - buf > len) + goto tail; + } link = td->link; } while (tmp != head); @@ -423,9 +460,11 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) i, hc32_to_cpu(uhci, link)); j = 1; } - out += sprintf(out, " link does not match " - "QH (%08x)!\n", + out += sprintf(out, + " link does not match QH (%08x)!\n", hc32_to_cpu(uhci, qh_dma)); + if (out - buf > len) + goto done; } else ++nerrs; } @@ -436,18 +475,27 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) out += sprintf(out, "Skeleton QHs\n"); + if (out - buf > len) + goto done; + fsbr_link = 0; for (i = 0; i < UHCI_NUM_SKELQH; ++i) { int cnt = 0; qh = uhci->skelqh[i]; - out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); \ + out += sprintf(out, "- skel_%s_qh\n", qh_names[i]); out += uhci_show_qh(uhci, qh, out, len - (out - buf), 4); + if (out - buf > len) + goto tail; /* Last QH is the Terminating QH, it's different */ if (i == SKEL_TERM) { - if (qh_element(qh) != LINK_TO_TD(uhci, uhci->term_td)) - out += sprintf(out, " skel_term_qh element is not set to term_td!\n"); + if (qh_element(qh) != LINK_TO_TD(uhci, uhci->term_td)) { + out += sprintf(out, + " skel_term_qh element is not set to term_td!\n"); + if (out - buf > len) + goto done; + } link = fsbr_link; if (!link) link = LINK_TO_QH(uhci, uhci->skel_term_qh); @@ -460,9 +508,12 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) while (tmp != head) { qh = list_entry(tmp, struct uhci_qh, node); tmp = tmp->next; - if (++cnt <= 10) + if (++cnt <= 10) { out += uhci_show_qh(uhci, qh, out, len - (out - buf), 4); + if (out - buf > len) + goto tail; + } if (!fsbr_link && qh->skel >= SKEL_FSBR) fsbr_link = LINK_TO_QH(uhci, qh); } @@ -480,9 +531,17 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len) link = LINK_TO_QH(uhci, uhci->skel_term_qh); check_qh_link: if (qh->link != link) - out += sprintf(out, " last QH not linked to next skeleton!\n"); + out += sprintf(out, + " last QH not linked to next skeleton!\n"); + + if (out - buf > len) + goto done; } +done: + if (out - buf > len) + out += sprintf(out, " ...\n"); +tail: return out - buf; } @@ -514,7 +573,8 @@ static int uhci_debug_open(struct inode *inode, struct file *file) up->size = 0; spin_lock_irqsave(&uhci->lock, flags); if (uhci->is_initialized) - up->size = uhci_sprint_schedule(uhci, up->data, MAX_OUTPUT); + up->size = uhci_sprint_schedule(uhci, up->data, + MAX_OUTPUT - EXTRA_SPACE); spin_unlock_irqrestore(&uhci->lock, flags); file->private_data = up; @@ -529,7 +589,9 @@ static loff_t uhci_debug_lseek(struct file *file, loff_t off, int whence) up = file->private_data; - /* XXX: atomic 64bit seek access, but that needs to be fixed in the VFS */ + /* + * XXX: atomic 64bit seek access, but that needs to be fixed in the VFS + */ switch (whence) { case 0: new = off; diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c index f7a62138e3e0d3..511bfc46dd7829 100644 --- a/drivers/usb/host/uhci-grlib.c +++ b/drivers/usb/host/uhci-grlib.c @@ -85,7 +85,7 @@ static const struct hc_driver uhci_grlib_hc_driver = { }; -static int __devinit uhci_hcd_grlib_probe(struct platform_device *op) +static int uhci_hcd_grlib_probe(struct platform_device *op) { struct device_node *dn = op->dev.of_node; struct usb_hcd *hcd; diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index e4db350602b8ea..4a86b63745b872 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -447,23 +447,25 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) return IRQ_NONE; uhci_writew(uhci, status, USBSTS); /* Clear it */ + spin_lock(&uhci->lock); + if (unlikely(!uhci->is_initialized)) /* not yet configured */ + goto done; + if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { if (status & USBSTS_HSE) - dev_err(uhci_dev(uhci), "host system error, " - "PCI problems?\n"); + dev_err(uhci_dev(uhci), + "host system error, PCI problems?\n"); if (status & USBSTS_HCPE) - dev_err(uhci_dev(uhci), "host controller process " - "error, something bad happened!\n"); + dev_err(uhci_dev(uhci), + "host controller process error, something bad happened!\n"); if (status & USBSTS_HCH) { - spin_lock(&uhci->lock); if (uhci->rh_state >= UHCI_RH_RUNNING) { dev_err(uhci_dev(uhci), - "host controller halted, " - "very bad!\n"); + "host controller halted, very bad!\n"); if (debug > 1 && errbuf) { /* Print the schedule for debugging */ - uhci_sprint_schedule(uhci, - errbuf, ERRBUF_LEN); + uhci_sprint_schedule(uhci, errbuf, + ERRBUF_LEN - EXTRA_SPACE); lprintk(errbuf); } uhci_hc_died(uhci); @@ -473,15 +475,15 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) * pending unlinks */ mod_timer(&hcd->rh_timer, jiffies); } - spin_unlock(&uhci->lock); } } - if (status & USBSTS_RD) + if (status & USBSTS_RD) { + spin_unlock(&uhci->lock); usb_hcd_poll_rh_status(hcd); - else { - spin_lock(&uhci->lock); + } else { uhci_scan_schedule(uhci); + done: spin_unlock(&uhci->lock); } @@ -589,8 +591,8 @@ static int uhci_start(struct usb_hcd *hcd) UHCI_NUMFRAMES * sizeof(*uhci->frame), &uhci->frame_dma_handle, 0); if (!uhci->frame) { - dev_err(uhci_dev(uhci), "unable to allocate " - "consistent memory for frame list\n"); + dev_err(uhci_dev(uhci), + "unable to allocate consistent memory for frame list\n"); goto err_alloc_frame; } memset(uhci->frame, 0, UHCI_NUMFRAMES * sizeof(*uhci->frame)); @@ -598,8 +600,8 @@ static int uhci_start(struct usb_hcd *hcd) uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu), GFP_KERNEL); if (!uhci->frame_cpu) { - dev_err(uhci_dev(uhci), "unable to allocate " - "memory for frame pointers\n"); + dev_err(uhci_dev(uhci), + "unable to allocate memory for frame pointers\n"); goto err_alloc_frame_cpu; } @@ -662,9 +664,9 @@ static int uhci_start(struct usb_hcd *hcd) */ mb(); + spin_lock_irq(&uhci->lock); configure_hc(uhci); uhci->is_initialized = 1; - spin_lock_irq(&uhci->lock); start_rh(uhci); spin_unlock_irq(&uhci->lock); return 0; @@ -734,8 +736,8 @@ static int uhci_rh_suspend(struct usb_hcd *hcd) */ else if (hcd->self.root_hub->do_remote_wakeup && uhci->resuming_ports) { - dev_dbg(uhci_dev(uhci), "suspend failed because a port " - "is resuming\n"); + dev_dbg(uhci_dev(uhci), + "suspend failed because a port is resuming\n"); rc = -EBUSY; } else suspend_rh(uhci, UHCI_RH_SUSPENDED); @@ -826,8 +828,8 @@ static int uhci_count_ports(struct usb_hcd *hcd) /* Anything greater than 7 is weird so we'll ignore it. */ if (port > UHCI_RH_MAXCHILD) { - dev_info(uhci_dev(uhci), "port count misdetected? " - "forcing to 2 ports\n"); + dev_info(uhci_dev(uhci), + "port count misdetected? forcing to 2 ports\n"); port = 2; } @@ -846,6 +848,11 @@ static const char hcd_name[] = "uhci_hcd"; #define PLATFORM_DRIVER uhci_grlib_driver #endif +#ifdef CONFIG_USB_UHCI_PLATFORM +#include "uhci-platform.c" +#define PLATFORM_DRIVER uhci_platform_driver +#endif + #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) #error "missing bus glue for uhci-hcd" #endif diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 7af2b705204748..6f986d82472d7d 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -212,10 +212,6 @@ struct uhci_qh { #define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */ #define TD_CTRL_ACTLEN_MASK 0x7FF /* actual length, encoded as n - 1 */ -#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \ - TD_CTRL_BABBLE | TD_CTRL_CRCTIME | \ - TD_CTRL_BITSTUFF) - #define uhci_maxerr(err) ((err) << TD_CTRL_C_ERR_SHIFT) #define uhci_status_bits(ctrl_sts) ((ctrl_sts) & 0xF60000) #define uhci_actual_length(ctrl_sts) (((ctrl_sts) + 1) & \ diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 768d54295a2074..9189bc984c98ce 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -21,8 +21,8 @@ static const __u8 root_hub_hub_des[] = 0x00, /* (per-port OC, no power switching) */ 0x01, /* __u8 bPwrOn2pwrGood; 2ms */ 0x00, /* __u8 bHubContrCurrent; 0 mA */ - 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */ - 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ + 0x00, /* __u8 DeviceRemovable; *** 7 Ports max */ + 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max */ }; #define UHCI_RH_MAXCHILD 7 @@ -116,6 +116,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, } } clear_bit(port, &uhci->resuming_ports); + usb_hcd_end_port_resume(&uhci_to_hcd(uhci)->self, port); } /* Wait for the UHCI controller in HP's iLO2 server management chip. @@ -167,6 +168,8 @@ static void uhci_check_ports(struct uhci_hcd *uhci) set_bit(port, &uhci->resuming_ports); uhci->ports_timeout = jiffies + msecs_to_jiffies(25); + usb_hcd_start_port_resume( + &uhci_to_hcd(uhci)->self, port); /* Make sure we see the port again * after the resuming period is over. */ @@ -222,7 +225,8 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) /* auto-stop if nothing connected for 1 second */ if (any_ports_active(uhci)) uhci->rh_state = UHCI_RH_RUNNING; - else if (time_after_eq(jiffies, uhci->auto_stop_time)) + else if (time_after_eq(jiffies, uhci->auto_stop_time) && + !uhci->wait_for_hp) suspend_rh(uhci, UHCI_RH_AUTO_STOPPED); break; diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index d2c6f5ac4626af..041c6ddb695c8e 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -1200,7 +1200,7 @@ static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb) if (debug > 1 && errbuf) { /* Print the chain for debugging */ uhci_show_qh(uhci, urbp->qh, errbuf, - ERRBUF_LEN, 0); + ERRBUF_LEN - EXTRA_SPACE, 0); lprintk(errbuf); } } @@ -1256,7 +1256,8 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, struct uhci_qh *qh) { struct uhci_td *td = NULL; /* Since urb->number_of_packets > 0 */ - int i, frame; + int i; + unsigned frame, next; unsigned long destination, status; struct urb_priv *urbp = (struct urb_priv *) urb->hcpriv; @@ -1265,37 +1266,29 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, urb->number_of_packets >= UHCI_NUMFRAMES) return -EFBIG; + uhci_get_current_frame_number(uhci); + /* Check the period and figure out the starting frame number */ if (!qh->bandwidth_reserved) { qh->period = urb->interval; - if (urb->transfer_flags & URB_ISO_ASAP) { - qh->phase = -1; /* Find the best phase */ - i = uhci_check_bandwidth(uhci, qh); - if (i) - return i; - - /* Allow a little time to allocate the TDs */ - uhci_get_current_frame_number(uhci); - frame = uhci->frame_number + 10; - - /* Move forward to the first frame having the - * correct phase */ - urb->start_frame = frame + ((qh->phase - frame) & - (qh->period - 1)); - } else { - i = urb->start_frame - uhci->last_iso_frame; - if (i <= 0 || i >= UHCI_NUMFRAMES) - return -EINVAL; - qh->phase = urb->start_frame & (qh->period - 1); - i = uhci_check_bandwidth(uhci, qh); - if (i) - return i; - } + qh->phase = -1; /* Find the best phase */ + i = uhci_check_bandwidth(uhci, qh); + if (i) + return i; + + /* Allow a little time to allocate the TDs */ + next = uhci->frame_number + 10; + frame = qh->phase; + + /* Round up to the first available slot */ + frame += (next - frame + qh->period - 1) & -qh->period; } else if (qh->period != urb->interval) { return -EINVAL; /* Can't change the period */ } else { + next = uhci->frame_number + 1; + /* Find the next unused frame */ if (list_empty(&qh->queue)) { frame = qh->iso_frame; @@ -1308,25 +1301,31 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, lurb->number_of_packets * lurb->interval; } - if (urb->transfer_flags & URB_ISO_ASAP) { - /* Skip some frames if necessary to insure - * the start frame is in the future. + + /* Fell behind? */ + if (uhci_frame_before_eq(frame, next)) { + + /* USB_ISO_ASAP: Round up to the first available slot */ + if (urb->transfer_flags & URB_ISO_ASAP) + frame += (next - frame + qh->period - 1) & + -qh->period; + + /* + * Not ASAP: Use the next slot in the stream. If + * the entire URB falls before the threshold, fail. */ - uhci_get_current_frame_number(uhci); - if (uhci_frame_before_eq(frame, uhci->frame_number)) { - frame = uhci->frame_number + 1; - frame += ((qh->phase - frame) & - (qh->period - 1)); - } - } /* Otherwise pick up where the last URB leaves off */ - urb->start_frame = frame; + else if (!uhci_frame_before_eq(next, + frame + (urb->number_of_packets - 1) * + qh->period)) + return -EXDEV; + } } /* Make sure we won't have to go too far into the future */ if (uhci_frame_before_eq(uhci->last_iso_frame + UHCI_NUMFRAMES, - urb->start_frame + urb->number_of_packets * - urb->interval)) + frame + urb->number_of_packets * urb->interval)) return -EFBIG; + urb->start_frame = frame; status = TD_CTRL_ACTIVE | TD_CTRL_IOS; destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe); diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c index 1e141f755b26dd..c3a647816af0b7 100644 --- a/drivers/usb/host/whci/hcd.c +++ b/drivers/usb/host/whci/hcd.c @@ -238,16 +238,16 @@ static struct hc_driver whc_hc_driver = { static int whc_probe(struct umc_dev *umc) { - int ret = -ENOMEM; + int ret; struct usb_hcd *usb_hcd; - struct wusbhc *wusbhc = NULL; - struct whc *whc = NULL; + struct wusbhc *wusbhc; + struct whc *whc; struct device *dev = &umc->dev; usb_hcd = usb_create_hcd(&whc_hc_driver, dev, "whci"); if (usb_hcd == NULL) { dev_err(dev, "unable to create hcd\n"); - goto error; + return -ENOMEM; } usb_hcd->wireless = 1; diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index 76083ae9213800..dc31c425ce0179 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c @@ -436,7 +436,7 @@ static int qset_add_urb_sg(struct whc *whc, struct whc_qset *qset, struct urb *u int i; int ntds = 0; struct whc_std *std = NULL; - struct whc_page_list_entry *entry; + struct whc_page_list_entry *new_pl_virt; dma_addr_t prev_end = 0; size_t pl_len; int p = 0; @@ -508,12 +508,15 @@ static int qset_add_urb_sg(struct whc *whc, struct whc_qset *qset, struct urb *u pl_len = std->num_pointers * sizeof(struct whc_page_list_entry); - std->pl_virt = krealloc(std->pl_virt, pl_len, mem_flags); - if (std->pl_virt == NULL) { + new_pl_virt = krealloc(std->pl_virt, pl_len, mem_flags); + if (new_pl_virt == NULL) { + kfree(std->pl_virt); + std->pl_virt = NULL; return -ENOMEM; } + std->pl_virt = new_pl_virt; - for (;p < std->num_pointers; p++, entry++) { + for (;p < std->num_pointers; p++) { std->pl_virt[p].buf_ptr = cpu_to_le64(dma_addr); dma_addr = (dma_addr + WHCI_PAGE_SIZE) & ~(WHCI_PAGE_SIZE-1); } diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 4b436f5a41711b..5f3a7c74aa8d39 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -544,7 +544,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci, int i; /* Fields are 32 bits wide, DMA addresses are in bytes */ int field_size = 32 / 8; - struct xhci_slot_ctx *slot_ctx; dma_addr_t dma = ctx->dma; int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); @@ -570,7 +569,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci, dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma); } - slot_ctx = xhci_get_slot_ctx(xhci, ctx); xhci_dbg_slot_ctx(xhci, ctx); xhci_dbg_ep_ctx(xhci, ctx, last_ep); } diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index d5eb357aa5c42c..68914429482f30 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -29,7 +29,7 @@ #define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \ PORT_RC | PORT_PLC | PORT_PE) -/* usb 1.1 root hub device descriptor */ +/* USB 3.0 BOS descriptor and a capability descriptor, combined */ static u8 usb_bos_descriptor [] = { USB_DT_BOS_SIZE, /* __u8 bLength, 5 bytes */ USB_DT_BOS, /* __u8 bDescriptorType */ @@ -151,9 +151,8 @@ static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, if (portsc & PORT_DEV_REMOVE) port_removable |= 1 << (i + 1); } - memset(&desc->u.ss.DeviceRemovable, - (__force __u16) cpu_to_le16(port_removable), - sizeof(__u16)); + + desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable); } static void xhci_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci, @@ -422,7 +421,7 @@ void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, xhci_writel(xhci, temp, port_array[port_id]); } -void xhci_set_remote_wake_mask(struct xhci_hcd *xhci, +static void xhci_set_remote_wake_mask(struct xhci_hcd *xhci, __le32 __iomem **port_array, int port_id, u16 wake_mask) { u32 temp; @@ -762,12 +761,39 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, break; case USB_PORT_FEAT_LINK_STATE: temp = xhci_readl(xhci, port_array[wIndex]); + + /* Disable port */ + if (link_state == USB_SS_PORT_LS_SS_DISABLED) { + xhci_dbg(xhci, "Disable port %d\n", wIndex); + temp = xhci_port_state_to_neutral(temp); + /* + * Clear all change bits, so that we get a new + * connection event. + */ + temp |= PORT_CSC | PORT_PEC | PORT_WRC | + PORT_OCC | PORT_RC | PORT_PLC | + PORT_CEC; + xhci_writel(xhci, temp | PORT_PE, + port_array[wIndex]); + temp = xhci_readl(xhci, port_array[wIndex]); + break; + } + + /* Put link in RxDetect (enable port) */ + if (link_state == USB_SS_PORT_LS_RX_DETECT) { + xhci_dbg(xhci, "Enable port %d\n", wIndex); + xhci_set_link_state(xhci, port_array, wIndex, + link_state); + temp = xhci_readl(xhci, port_array[wIndex]); + break; + } + /* Software should not attempt to set - * port link state above '5' (Rx.Detect) and the port + * port link state above '3' (U3) and the port * must be enabled. */ if ((temp & PORT_PE) == 0 || - (link_state > USB_SS_PORT_LS_RX_DETECT)) { + (link_state > USB_SS_PORT_LS_U3)) { xhci_warn(xhci, "Cannot set link state.\n"); goto error; } @@ -808,6 +834,14 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = xhci_readl(xhci, port_array[wIndex]); xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n", wIndex, temp); + + spin_unlock_irqrestore(&xhci->lock, flags); + temp = usb_acpi_power_manageable(hcd->self.root_hub, + wIndex); + if (temp) + usb_acpi_set_power_state(hcd->self.root_hub, + wIndex, true); + spin_lock_irqsave(&xhci->lock, flags); break; case USB_PORT_FEAT_RESET: temp = (temp | PORT_RESET); @@ -907,6 +941,18 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, xhci_disable_port(hcd, xhci, wIndex, port_array[wIndex], temp); break; + case USB_PORT_FEAT_POWER: + xhci_writel(xhci, temp & ~PORT_POWER, + port_array[wIndex]); + + spin_unlock_irqrestore(&xhci->lock, flags); + temp = usb_acpi_power_manageable(hcd->self.root_hub, + wIndex); + if (temp) + usb_acpi_set_power_state(hcd->self.root_hub, + wIndex, false); + spin_lock_irqsave(&xhci->lock, flags); + break; default: goto error; } @@ -938,6 +984,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) int max_ports; __le32 __iomem **port_array; struct xhci_bus_state *bus_state; + bool reset_change = false; max_ports = xhci_get_ports(hcd, &port_array); bus_state = &xhci->bus_state[hcd_index(hcd)]; @@ -969,6 +1016,12 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) buf[(i + 1) / 8] |= 1 << (i + 1) % 8; status = 1; } + if ((temp & PORT_RC)) + reset_change = true; + } + if (!status && !reset_change) { + xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); } spin_unlock_irqrestore(&xhci->lock, flags); return status ? retval : 0; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 487bc083dead0a..7e702f0de00e3d 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -205,7 +205,12 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci, next = xhci_segment_alloc(xhci, cycle_state, flags); if (!next) { - xhci_free_segments_for_ring(xhci, *first); + prev = *first; + while (prev) { + next = prev->next; + xhci_segment_free(xhci, prev); + prev = next; + } return -ENOMEM; } xhci_link_segments(xhci, prev, next, type); @@ -258,7 +263,7 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, return ring; fail: - xhci_ring_free(xhci, ring); + kfree(ring); return NULL; } @@ -364,6 +369,10 @@ static struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci ctx->size += CTX_SIZE(xhci->hcc_params); ctx->bytes = dma_pool_alloc(xhci->device_pool, flags, &ctx->dma); + if (!ctx->bytes) { + kfree(ctx); + return NULL; + } memset(ctx->bytes, 0, ctx->size); return ctx; } @@ -1017,44 +1026,24 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, * is attached to (or the roothub port its ancestor hub is attached to). All we * know is the index of that port under either the USB 2.0 or the USB 3.0 * roothub, but that doesn't give us the real index into the HW port status - * registers. Scan through the xHCI roothub port array, looking for the Nth - * entry of the correct port speed. Return the port number of that entry. + * registers. Call xhci_find_raw_port_number() to get real index. */ static u32 xhci_find_real_port_number(struct xhci_hcd *xhci, struct usb_device *udev) { struct usb_device *top_dev; - unsigned int num_similar_speed_ports; - unsigned int faked_port_num; - int i; + struct usb_hcd *hcd; + + if (udev->speed == USB_SPEED_SUPER) + hcd = xhci->shared_hcd; + else + hcd = xhci->main_hcd; for (top_dev = udev; top_dev->parent && top_dev->parent->parent; top_dev = top_dev->parent) /* Found device below root hub */; - faked_port_num = top_dev->portnum; - for (i = 0, num_similar_speed_ports = 0; - i < HCS_MAX_PORTS(xhci->hcs_params1); i++) { - u8 port_speed = xhci->port_array[i]; - /* - * Skip ports that don't have known speeds, or have duplicate - * Extended Capabilities port speed entries. - */ - if (port_speed == 0 || port_speed == DUPLICATE_ENTRY) - continue; - - /* - * USB 3.0 ports are always under a USB 3.0 hub. USB 2.0 and - * 1.1 ports are under the USB 2.0 hub. If the port speed - * matches the device speed, it's a similar speed port. - */ - if ((port_speed == 0x03) == (udev->speed == USB_SPEED_SUPER)) - num_similar_speed_ports++; - if (num_similar_speed_ports == faked_port_num) - /* Roothub ports are numbered from 1 to N */ - return i+1; - } - return 0; + return xhci_find_raw_port_number(hcd, top_dev->portnum); } /* Setup an xHCI virtual device for a Set Address command */ @@ -1245,6 +1234,8 @@ static unsigned int xhci_microframes_to_exponent(struct usb_device *udev, static unsigned int xhci_parse_microframe_interval(struct usb_device *udev, struct usb_host_endpoint *ep) { + if (ep->desc.bInterval == 0) + return 0; return xhci_microframes_to_exponent(udev, ep, ep->desc.bInterval, 0, 15); } @@ -1436,15 +1427,17 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, ep_ctx->ep_info2 |= cpu_to_le32(xhci_get_endpoint_type(udev, ep)); /* Set the max packet size and max burst */ + max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); + max_burst = 0; switch (udev->speed) { case USB_SPEED_SUPER: - max_packet = usb_endpoint_maxp(&ep->desc); - ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet)); /* dig out max burst from ep companion desc */ - max_packet = ep->ss_ep_comp.bMaxBurst; - ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_packet)); + max_burst = ep->ss_ep_comp.bMaxBurst; break; case USB_SPEED_HIGH: + /* Some devices get this wrong */ + if (usb_endpoint_xfer_bulk(&ep->desc)) + max_packet = 512; /* bits 11:12 specify the number of additional transaction * opportunities per microframe (USB 2.0, section 9.6.6) */ @@ -1452,17 +1445,16 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, usb_endpoint_xfer_int(&ep->desc)) { max_burst = (usb_endpoint_maxp(&ep->desc) & 0x1800) >> 11; - ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_burst)); } - /* Fall through */ + break; case USB_SPEED_FULL: case USB_SPEED_LOW: - max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); - ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet)); break; default: BUG(); } + ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet) | + MAX_BURST(max_burst)); max_esit_payload = xhci_get_max_esit_payload(xhci, udev, ep); ep_ctx->tx_info = cpu_to_le32(MAX_ESIT_PAYLOAD_FOR_EP(max_esit_payload)); @@ -1839,6 +1831,9 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) } spin_unlock_irqrestore(&xhci->lock, flags); + if (!xhci->rh_bw) + goto no_bw; + num_ports = HCS_MAX_PORTS(xhci->hcs_params1); for (i = 0; i < num_ports; i++) { struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table; @@ -1857,6 +1852,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) } } +no_bw: xhci->num_usb2_ports = 0; xhci->num_usb3_ports = 0; xhci->num_active_eps = 0; @@ -2268,6 +2264,9 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) u32 page_size, temp; int i; + INIT_LIST_HEAD(&xhci->lpm_failed_devs); + INIT_LIST_HEAD(&xhci->cancel_cmd_list); + page_size = xhci_readl(xhci, &xhci->op_regs->page_size); xhci_dbg(xhci, "Supported page size register = 0x%x\n", page_size); for (i = 0; i < 16; i++) { @@ -2346,7 +2345,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci->cmd_ring = xhci_ring_alloc(xhci, 1, 1, TYPE_COMMAND, flags); if (!xhci->cmd_ring) goto fail; - INIT_LIST_HEAD(&xhci->cancel_cmd_list); xhci_dbg(xhci, "Allocated command ring at %p\n", xhci->cmd_ring); xhci_dbg(xhci, "First segment DMA is 0x%llx\n", (unsigned long long)xhci->cmd_ring->first_seg->dma); @@ -2457,8 +2455,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) if (xhci_setup_port_arrays(xhci, flags)) goto fail; - INIT_LIST_HEAD(&xhci->lpm_failed_devs); - /* Enable USB 3.0 device notifications for function remote wake, which * is necessary for allowing USB 3.0 devices to do remote wakeup from * U3 (device suspend). diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index dcb72f724d0ef7..cc24e39b97d5b8 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -221,15 +221,16 @@ static void xhci_pci_remove(struct pci_dev *dev) static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); - int retval = 0; - - if (hcd->state != HC_STATE_SUSPENDED || - xhci->shared_hcd->state != HC_STATE_SUSPENDED) - return -EINVAL; + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - retval = xhci_suspend(xhci); + /* + * Systems with the TI redriver that loses port status change events + * need to have the registers polled during D3, so avoid D3cold. + */ + if (xhci_compliance_mode_recovery_timer_quirk_check()) + pdev->no_d3cold = true; - return retval; + return xhci_suspend(xhci); } static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated) @@ -320,6 +321,7 @@ static const struct hc_driver xhci_pci_hc_driver = { .set_usb2_hw_lpm = xhci_set_usb2_hardware_lpm, .enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout, .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout, + .find_raw_port_number = xhci_find_raw_port_number, }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index df90fe51b4aa2d..93ad67eca0535f 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -179,6 +179,7 @@ static int xhci_plat_remove(struct platform_device *dev) usb_remove_hcd(hcd); iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); kfree(xhci); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 4f1e265223dd4d..1969c001b3f9a8 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -318,7 +318,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci) * seconds), then it should assume that the there are * larger problems with the xHC and assert HCRST. */ - ret = handshake(xhci, &xhci->op_regs->cmd_ring, + ret = xhci_handshake(xhci, &xhci->op_regs->cmd_ring, CMD_RING_RUNNING, 0, 5 * 1000 * 1000); if (ret < 0) { xhci_err(xhci, "Stopped the command ring failed, " @@ -1599,14 +1599,20 @@ static void handle_port_status(struct xhci_hcd *xhci, max_ports = HCS_MAX_PORTS(xhci->hcs_params1); if ((port_id <= 0) || (port_id > max_ports)) { xhci_warn(xhci, "Invalid port id %d\n", port_id); - bogus_port_status = true; - goto cleanup; + inc_deq(xhci, xhci->event_ring); + return; } /* Figure out which usb_hcd this port is attached to: * is it a USB 3.0 port or a USB 2.0/1.1 port? */ major_revision = xhci->port_array[port_id - 1]; + + /* Find the right roothub. */ + hcd = xhci_to_hcd(xhci); + if ((major_revision == 0x03) != (hcd->speed == HCD_USB3)) + hcd = xhci->shared_hcd; + if (major_revision == 0) { xhci_warn(xhci, "Event for port %u not in " "Extended Capabilities, ignoring.\n", @@ -1629,10 +1635,6 @@ static void handle_port_status(struct xhci_hcd *xhci, * into the index into the ports on the correct split roothub, and the * correct bus_state structure. */ - /* Find the right roothub. */ - hcd = xhci_to_hcd(xhci); - if ((major_revision == 0x03) != (hcd->speed == HCD_USB3)) - hcd = xhci->shared_hcd; bus_state = &xhci->bus_state[hcd_index(hcd)]; if (hcd->speed == HCD_USB3) port_array = xhci->usb3_ports; @@ -1698,7 +1700,7 @@ static void handle_port_status(struct xhci_hcd *xhci, faked_port_index + 1); if (slot_id && xhci->devs[slot_id]) xhci_ring_device(xhci, slot_id); - if (bus_state->port_remote_wakeup && (1 << faked_port_index)) { + if (bus_state->port_remote_wakeup & (1 << faked_port_index)) { bus_state->port_remote_wakeup &= ~(1 << faked_port_index); xhci_test_and_clear_bit(xhci, port_array, @@ -1725,6 +1727,15 @@ static void handle_port_status(struct xhci_hcd *xhci, if (bogus_port_status) return; + /* + * xHCI port-status-change events occur when the "or" of all the + * status-change bits in the portsc register changes from 0 to 1. + * New status changes won't cause an event if any other change + * bits are still set. When an event occurs, switch over to + * polling to avoid losing status changes. + */ + xhci_dbg(xhci, "%s: starting port polling.\n", __func__); + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); spin_unlock(&xhci->lock); /* Pass this up to the core */ usb_hcd_poll_rh_status(hcd); @@ -2018,8 +2029,8 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, if (event_trb != ep_ring->dequeue && event_trb != td->last_trb) td->urb->actual_length = - td->urb->transfer_buffer_length - - TRB_LEN(le32_to_cpu(event->transfer_len)); + td->urb->transfer_buffer_length - + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); else td->urb->actual_length = 0; @@ -2051,7 +2062,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, /* Maybe the event was for the data stage? */ td->urb->actual_length = td->urb->transfer_buffer_length - - TRB_LEN(le32_to_cpu(event->transfer_len)); + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); xhci_dbg(xhci, "Waiting for status " "stage event\n"); return 0; @@ -2087,7 +2098,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, /* handle completion code */ switch (trb_comp_code) { case COMP_SUCCESS: - if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) { + if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) { frame->status = 0; break; } @@ -2132,7 +2143,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])); } len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - - TRB_LEN(le32_to_cpu(event->transfer_len)); + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); if (trb_comp_code != COMP_STOP_INVAL) { frame->actual_length = len; @@ -2190,7 +2201,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, case COMP_SUCCESS: /* Double check that the HW transferred everything. */ if (event_trb != td->last_trb || - TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { xhci_warn(xhci, "WARN Successful completion " "on short TX\n"); if (td->urb->transfer_flags & URB_SHORT_NOT_OK) @@ -2218,18 +2229,18 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, "%d bytes untransferred\n", td->urb->ep->desc.bEndpointAddress, td->urb->transfer_buffer_length, - TRB_LEN(le32_to_cpu(event->transfer_len))); + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len))); /* Fast path - was this the last TRB in the TD for this URB? */ if (event_trb == td->last_trb) { - if (TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { + if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { td->urb->actual_length = td->urb->transfer_buffer_length - - TRB_LEN(le32_to_cpu(event->transfer_len)); + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); if (td->urb->transfer_buffer_length < td->urb->actual_length) { xhci_warn(xhci, "HC gave bad length " "of %d bytes left\n", - TRB_LEN(le32_to_cpu(event->transfer_len))); + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len))); td->urb->actual_length = 0; if (td->urb->transfer_flags & URB_SHORT_NOT_OK) *status = -EREMOTEIO; @@ -2271,7 +2282,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, if (trb_comp_code != COMP_STOP_INVAL) td->urb->actual_length += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - - TRB_LEN(le32_to_cpu(event->transfer_len)); + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); } return finish_td(xhci, td, event_trb, event, ep, status, false); @@ -2284,6 +2295,8 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, */ static int handle_tx_event(struct xhci_hcd *xhci, struct xhci_transfer_event *event) + __releases(&xhci->lock) + __acquires(&xhci->lock) { struct xhci_virt_device *xdev; struct xhci_virt_ep *ep; @@ -2357,7 +2370,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, * transfer type */ case COMP_SUCCESS: - if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) + if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) break; if (xhci->quirks & XHCI_TRUST_TX_LENGTH) trb_comp_code = COMP_SHORT_TX; @@ -2450,14 +2463,21 @@ static int handle_tx_event(struct xhci_hcd *xhci, * TD list. */ if (list_empty(&ep_ring->td_list)) { - xhci_warn(xhci, "WARN Event TRB for slot %d ep %d " - "with no TDs queued?\n", - TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), - ep_index); - xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", - (le32_to_cpu(event->flags) & - TRB_TYPE_BITMASK)>>10); - xhci_print_trb_offsets(xhci, (union xhci_trb *) event); + /* + * A stopped endpoint may generate an extra completion + * event if the device was suspended. Don't print + * warnings. + */ + if (!(trb_comp_code == COMP_STOP || + trb_comp_code == COMP_STOP_INVAL)) { + xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n", + TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), + ep_index); + xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", + (le32_to_cpu(event->flags) & + TRB_TYPE_BITMASK)>>10); + xhci_print_trb_offsets(xhci, (union xhci_trb *) event); + } if (ep->skip) { ep->skip = false; xhci_dbg(xhci, "td_list is empty while skip " @@ -2578,6 +2598,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, (trb_comp_code != COMP_STALL && trb_comp_code != COMP_BABBLE)) xhci_urb_free_priv(xhci, urb_priv); + else + kfree(urb_priv); usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb); if ((urb->actual_length != urb->transfer_buffer_length && @@ -2695,13 +2717,11 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); u32 status; - union xhci_trb *trb; u64 temp_64; union xhci_trb *event_ring_deq; dma_addr_t deq; spin_lock(&xhci->lock); - trb = xhci->event_ring->dequeue; /* Check if the xHC generated the interrupt, or the irq is shared */ status = xhci_readl(xhci, &xhci->op_regs->status); if (status == 0xffffffff) @@ -2861,7 +2881,7 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, xhci_err(xhci, "Ring expansion failed\n"); return -ENOMEM; } - }; + } if (enqueue_is_link_trb(ep_ring)) { struct xhci_ring *ring = ep_ring; @@ -3069,11 +3089,11 @@ static u32 xhci_td_remainder(unsigned int remainder) } /* - * For xHCI 1.0 host controllers, TD size is the number of packets remaining in - * the TD (*not* including this TRB). + * For xHCI 1.0 host controllers, TD size is the number of max packet sized + * packets remaining in the TD (*not* including this TRB). * * Total TD packet count = total_packet_count = - * roundup(TD size in bytes / wMaxPacketSize) + * DIV_ROUND_UP(TD size in bytes / wMaxPacketSize) * * Packets transferred up to and including this TRB = packets_transferred = * rounddown(total bytes transferred including this TRB / wMaxPacketSize) @@ -3081,24 +3101,27 @@ static u32 xhci_td_remainder(unsigned int remainder) * TD size = total_packet_count - packets_transferred * * It must fit in bits 21:17, so it can't be bigger than 31. + * The last TRB in a TD must have the TD size set to zero. */ - static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len, - unsigned int total_packet_count, struct urb *urb) + unsigned int total_packet_count, struct urb *urb, + unsigned int num_trbs_left) { int packets_transferred; /* One TRB with a zero-length data packet. */ - if (running_total == 0 && trb_buff_len == 0) + if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0)) return 0; /* All the TRB queueing functions don't count the current TRB in * running_total. */ packets_transferred = (running_total + trb_buff_len) / - usb_endpoint_maxp(&urb->ep->desc); + GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); - return xhci_td_remainder(total_packet_count - packets_transferred); + if ((total_packet_count - packets_transferred) > 31) + return 31 << 17; + return (total_packet_count - packets_transferred) << 17; } static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, @@ -3125,7 +3148,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, num_trbs = count_sg_trbs_needed(xhci, urb); num_sgs = urb->num_mapped_sgs; - total_packet_count = roundup(urb->transfer_buffer_length, + total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length, usb_endpoint_maxp(&urb->ep->desc)); trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id], @@ -3208,7 +3231,8 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, running_total); } else { remainder = xhci_v1_0_td_remainder(running_total, - trb_buff_len, total_packet_count, urb); + trb_buff_len, total_packet_count, urb, + num_trbs - 1); } length_field = TRB_LEN(trb_buff_len) | remainder | @@ -3316,7 +3340,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, start_cycle = ep_ring->cycle_state; running_total = 0; - total_packet_count = roundup(urb->transfer_buffer_length, + total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length, usb_endpoint_maxp(&urb->ep->desc)); /* How much data is in the first TRB? */ addr = (u64) urb->transfer_dma; @@ -3362,7 +3386,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, running_total); } else { remainder = xhci_v1_0_td_remainder(running_total, - trb_buff_len, total_packet_count, urb); + trb_buff_len, total_packet_count, urb, + num_trbs - 1); } length_field = TRB_LEN(trb_buff_len) | remainder | @@ -3625,8 +3650,9 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, addr = start_addr + urb->iso_frame_desc[i].offset; td_len = urb->iso_frame_desc[i].length; td_remain_len = td_len; - total_packet_count = roundup(td_len, - usb_endpoint_maxp(&urb->ep->desc)); + total_packet_count = DIV_ROUND_UP(td_len, + GET_MAX_PACKET( + usb_endpoint_maxp(&urb->ep->desc))); /* A zero-length transfer still involves at least one packet. */ if (total_packet_count == 0) total_packet_count++; @@ -3648,9 +3674,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, td = urb_priv->td[i]; for (j = 0; j < trbs_per_td; j++) { u32 remainder = 0; - field = TRB_TBC(burst_count) | TRB_TLBPC(residue); + field = 0; if (first_trb) { + field = TRB_TBC(burst_count) | + TRB_TLBPC(residue); /* Queue the isoc TRB */ field |= TRB_TYPE(TRB_ISOC); /* Assume URB_ISO_ASAP is set */ @@ -3704,7 +3732,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, } else { remainder = xhci_v1_0_td_remainder( running_total, trb_buff_len, - total_packet_count, urb); + total_packet_count, urb, + (trbs_per_td - j - 1)); } length_field = TRB_LEN(trb_buff_len) | remainder | diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index a6e910b2bc04b8..82b08091be6c9d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -40,7 +40,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB"); /* TODO: copied from ehci-hcd.c - can this be refactored? */ /* - * handshake - spin reading hc until handshake completes or fails + * xhci_handshake - spin reading hc until handshake completes or fails * @ptr: address of hc register to be read * @mask: bits to look at in result of read * @done: value of those bits when handshake succeeds @@ -52,7 +52,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB"); * handshake done). There are two failure modes: "usec" have passed (major * hardware flakeout), or the register reads as all-ones (hardware removed). */ -int handshake(struct xhci_hcd *xhci, void __iomem *ptr, +int xhci_handshake(struct xhci_hcd *xhci, void __iomem *ptr, u32 mask, u32 done, int usec) { u32 result; @@ -103,7 +103,7 @@ int xhci_halt(struct xhci_hcd *xhci) xhci_dbg(xhci, "// Halt the HC\n"); xhci_quiesce(xhci); - ret = handshake(xhci, &xhci->op_regs->status, + ret = xhci_handshake(xhci, &xhci->op_regs->status, STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); if (!ret) { xhci->xhc_state |= XHCI_STATE_HALTED; @@ -132,7 +132,7 @@ static int xhci_start(struct xhci_hcd *xhci) * Wait for the HCHalted Status bit to be 0 to indicate the host is * running. */ - ret = handshake(xhci, &xhci->op_regs->status, + ret = xhci_handshake(xhci, &xhci->op_regs->status, STS_HALT, 0, XHCI_MAX_HALT_USEC); if (ret == -ETIMEDOUT) xhci_err(xhci, "Host took too long to start, " @@ -167,7 +167,7 @@ int xhci_reset(struct xhci_hcd *xhci) command |= CMD_RESET; xhci_writel(xhci, command, &xhci->op_regs->command); - ret = handshake(xhci, &xhci->op_regs->command, + ret = xhci_handshake(xhci, &xhci->op_regs->command, CMD_RESET, 0, 10 * 1000 * 1000); if (ret) return ret; @@ -177,7 +177,7 @@ int xhci_reset(struct xhci_hcd *xhci) * xHCI cannot write to any doorbells or operational registers other * than status until the "Controller Not Ready" flag is cleared. */ - ret = handshake(xhci, &xhci->op_regs->status, + ret = xhci_handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 10 * 1000 * 1000); for (i = 0; i < 2; ++i) { @@ -350,7 +350,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd) * generate interrupts. Don't even try to enable MSI. */ if (xhci->quirks & XHCI_BROKEN_MSI) - return 0; + goto legacy_irq; /* unregister the legacy interrupt */ if (hcd->irq) @@ -371,6 +371,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd) return -EINVAL; } + legacy_irq: /* fall back to legacy interrupt*/ ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED, hcd->irq_descr, hcd); @@ -465,7 +466,7 @@ static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci) * Systems: * Vendor: Hewlett-Packard -> System Models: Z420, Z620 and Z820 */ -static bool compliance_mode_recovery_timer_quirk_check(void) +bool xhci_compliance_mode_recovery_timer_quirk_check(void) { const char *dmi_product_name, *dmi_sys_vendor; @@ -480,7 +481,7 @@ static bool compliance_mode_recovery_timer_quirk_check(void) if (strstr(dmi_product_name, "Z420") || strstr(dmi_product_name, "Z620") || strstr(dmi_product_name, "Z820") || - strstr(dmi_product_name, "Z1")) + strstr(dmi_product_name, "Z1 Workstation")) return true; return false; @@ -516,7 +517,7 @@ int xhci_init(struct usb_hcd *hcd) xhci_dbg(xhci, "Finished xhci_init\n"); /* Initializing Compliance Mode Recovery Data If Needed */ - if (compliance_mode_recovery_timer_quirk_check()) { + if (xhci_compliance_mode_recovery_timer_quirk_check()) { xhci->quirks |= XHCI_COMP_MODE_QUIRK; compliance_mode_recovery_timer_init(xhci); } @@ -880,6 +881,15 @@ int xhci_suspend(struct xhci_hcd *xhci) struct usb_hcd *hcd = xhci_to_hcd(xhci); u32 command; + if (hcd->state != HC_STATE_SUSPENDED || + xhci->shared_hcd->state != HC_STATE_SUSPENDED) + return -EINVAL; + + /* Don't poll the roothubs on bus suspend. */ + xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); + del_timer_sync(&hcd->rh_timer); + spin_lock_irq(&xhci->lock); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); @@ -890,7 +900,7 @@ int xhci_suspend(struct xhci_hcd *xhci) command = xhci_readl(xhci, &xhci->op_regs->command); command &= ~CMD_RUN; xhci_writel(xhci, command, &xhci->op_regs->command); - if (handshake(xhci, &xhci->op_regs->status, + if (xhci_handshake(xhci, &xhci->op_regs->status, STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) { xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n"); spin_unlock_irq(&xhci->lock); @@ -905,7 +915,8 @@ int xhci_suspend(struct xhci_hcd *xhci) command = xhci_readl(xhci, &xhci->op_regs->command); command |= CMD_CSS; xhci_writel(xhci, command, &xhci->op_regs->command); - if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10 * 1000)) { + if (xhci_handshake(xhci, &xhci->op_regs->status, + STS_SAVE, 0, 10 * 1000)) { xhci_warn(xhci, "WARN: xHC save state timeout\n"); spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; @@ -941,6 +952,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) struct usb_hcd *hcd = xhci_to_hcd(xhci); struct usb_hcd *secondary_hcd; int retval = 0; + bool comp_timer_running = false; /* Wait a bit if either of the roothubs need to settle from the * transition into bus suspend. @@ -967,7 +979,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) command = xhci_readl(xhci, &xhci->op_regs->command); command |= CMD_CRS; xhci_writel(xhci, command, &xhci->op_regs->command); - if (handshake(xhci, &xhci->op_regs->status, + if (xhci_handshake(xhci, &xhci->op_regs->status, STS_RESTORE, 0, 10 * 1000)) { xhci_warn(xhci, "WARN: xHC restore state timeout\n"); spin_unlock_irq(&xhci->lock); @@ -978,6 +990,13 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) /* If restore operation fails, re-initialize the HC during resume */ if ((temp & STS_SRE) || hibernated) { + + if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && + !(xhci_all_ports_seen_u0(xhci))) { + del_timer_sync(&xhci->comp_mode_recovery_timer); + xhci_dbg(xhci, "Compliance Mode Recovery Timer deleted!\n"); + } + /* Let the USB core know _both_ roothubs lost power. */ usb_root_hub_lost_power(xhci->main_hcd->self.root_hub); usb_root_hub_lost_power(xhci->shared_hcd->self.root_hub); @@ -1020,6 +1039,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) retval = xhci_init(hcd->primary_hcd); if (retval) return retval; + comp_timer_running = true; + xhci_dbg(xhci, "Start the primary HCD\n"); retval = xhci_run(hcd->primary_hcd); if (!retval) { @@ -1035,7 +1056,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) command = xhci_readl(xhci, &xhci->op_regs->command); command |= CMD_RUN; xhci_writel(xhci, command, &xhci->op_regs->command); - handshake(xhci, &xhci->op_regs->status, STS_HALT, + xhci_handshake(xhci, &xhci->op_regs->status, STS_HALT, 0, 250 * 1000); /* step 5: walk topology and initialize portsc, @@ -1061,9 +1082,14 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) * to suffer the Compliance Mode issue again. It doesn't matter if * ports have entered previously to U0 before system's suspension. */ - if (xhci->quirks & XHCI_COMP_MODE_QUIRK) + if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && !comp_timer_running) compliance_mode_recovery_timer_init(xhci); + /* Re-enable port polling. */ + xhci_dbg(xhci, "%s: starting port polling.\n", __func__); + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); + usb_hcd_poll_rh_status(hcd); + return retval; } #endif /* CONFIG_PM */ @@ -1627,7 +1653,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct xhci_hcd *xhci; struct xhci_container_ctx *in_ctx, *out_ctx; unsigned int ep_index; - struct xhci_ep_ctx *ep_ctx; struct xhci_slot_ctx *slot_ctx; struct xhci_input_control_ctx *ctrl_ctx; u32 added_ctxs; @@ -1663,7 +1688,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, out_ctx = virt_dev->out_ctx; ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); ep_index = xhci_get_endpoint_index(&ep->desc); - ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); /* If this endpoint is already in use, and the upper layers are trying * to add it again without dropping it, reject the addition. @@ -1817,6 +1841,8 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci, case COMP_EBADSLT: dev_warn(&udev->dev, "WARN: slot not enabled for" "evaluate context command.\n"); + ret = -EINVAL; + break; case COMP_CTX_STATE: dev_warn(&udev->dev, "WARN: invalid context state for " "evaluate context command.\n"); @@ -1953,7 +1979,7 @@ static void xhci_finish_resource_reservation(struct xhci_hcd *xhci, xhci->num_active_eps); } -unsigned int xhci_get_block_size(struct usb_device *udev) +static unsigned int xhci_get_block_size(struct usb_device *udev) { switch (udev->speed) { case USB_SPEED_LOW: @@ -1971,7 +1997,8 @@ unsigned int xhci_get_block_size(struct usb_device *udev) } } -unsigned int xhci_get_largest_overhead(struct xhci_interval_bw *interval_bw) +static unsigned int +xhci_get_largest_overhead(struct xhci_interval_bw *interval_bw) { if (interval_bw->overhead[LS_OVERHEAD_TYPE]) return LS_OVERHEAD; @@ -2253,7 +2280,7 @@ static bool xhci_is_async_ep(unsigned int ep_type) static bool xhci_is_sync_in_ep(unsigned int ep_type) { - return (ep_type == ISOC_IN_EP || ep_type != INT_IN_EP); + return (ep_type == ISOC_IN_EP || ep_type == INT_IN_EP); } static unsigned int xhci_get_ss_bw_consumed(struct xhci_bw_info *ep_bw) @@ -3762,6 +3789,28 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) return 0; } +/* + * Transfer the port index into real index in the HW port status + * registers. Caculate offset between the port's PORTSC register + * and port status base. Divide the number of per port register + * to get the real index. The raw port number bases 1. + */ +int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + __le32 __iomem *base_addr = &xhci->op_regs->port_status_base; + __le32 __iomem *addr; + int raw_port; + + if (hcd->speed != HCD_USB3) + addr = xhci->usb2_ports[port1 - 1]; + else + addr = xhci->usb3_ports[port1 - 1]; + + raw_port = (addr - base_addr)/NUM_PORT_REGS + 1; + return raw_port; +} + #ifdef CONFIG_USB_SUSPEND /* BESL to HIRD Encoding array for USB2 LPM */ @@ -3873,7 +3922,8 @@ static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd, spin_lock_irqsave(&xhci->lock, flags); /* Check L1 Status */ - ret = handshake(xhci, pm_addr, PORT_L1S_MASK, PORT_L1S_SUCCESS, 125); + ret = xhci_handshake(xhci, pm_addr, + PORT_L1S_MASK, PORT_L1S_SUCCESS, 125); if (ret != -ETIMEDOUT) { /* enter L1 successfully */ temp = xhci_readl(xhci, addr); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 53df4e70ca074c..bde9f22ccd857c 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -206,8 +206,8 @@ struct xhci_op_regs { /* bits 12:31 are reserved (and should be preserved on writes). */ /* IMAN - Interrupt Management Register */ -#define IMAN_IP (1 << 1) -#define IMAN_IE (1 << 0) +#define IMAN_IE (1 << 1) +#define IMAN_IP (1 << 0) /* USBSTS - USB status - status bitmasks */ /* HC not running - set to 1 when run/stop bit is cleared. */ @@ -972,6 +972,10 @@ struct xhci_transfer_event { __le32 flags; }; +/* Transfer event TRB length bit mask */ +/* bits 0:23 */ +#define EVENT_TRB_LEN(p) ((p) & 0xffffff) + /** Transfer Event bit fields **/ #define TRB_TO_EP_ID(p) (((p) >> 16) & 0x1f) @@ -1720,7 +1724,7 @@ static inline void xhci_unregister_plat(void) /* xHCI host controller glue */ typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *); -int handshake(struct xhci_hcd *xhci, void __iomem *ptr, +int xhci_handshake(struct xhci_hcd *xhci, void __iomem *ptr, u32 mask, u32 done, int usec); void xhci_quiesce(struct xhci_hcd *xhci); int xhci_halt(struct xhci_hcd *xhci); @@ -1829,6 +1833,7 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength); int xhci_hub_status_data(struct usb_hcd *hcd, char *buf); +int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1); #ifdef CONFIG_PM int xhci_bus_suspend(struct usb_hcd *hcd); @@ -1848,4 +1853,7 @@ struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_hcd *xhci, struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx); struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int ep_index); +/* xHCI quirks */ +bool xhci_compliance_mode_recovery_timer_quirk_check(void); + #endif /* __LINUX_XHCI_HCD_H */