提交 c44dead7 编写于 作者: L Linus Torvalds

Merge branch 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (205 commits)
  USB: EHCI: Remove SPARC_LEON {read,write}_be definitions from ehci.h
  USB: UHCI: Support big endian GRUSBHC HC
  sparc: add {read,write}*_be routines
  USB: UHCI: Add support for big endian descriptors
  USB: UHCI: Use ACCESS_ONCE rather than using a full compiler barrier
  USB: UHCI: Add support for big endian mmio
  usb-storage: Correct adjust_quirks to include latest flags
  usb/isp1760: Fix possible unlink problems
  usb/isp1760: Move function isp1760_endpoint_disable() within file.
  USB: remove remaining usages of hcd->state from usbcore and fix regression
  usb: musb: ux500: add configuration and build options for ux500 dma
  usb: musb: ux500: add dma glue layer for ux500
  usb: musb: ux500: add dma name for ux500
  usb: musb: ux500: add ux500 specific code for gadget side
  usb: musb: fix compile error
  usb-storage: fix up the unusual_realtek device list
  USB: gadget: f_audio: Fix invalid dereference of initdata
  EHCI: don't rescan interrupt QHs needlessly
  OHCI: fix regression caused by nVidia shutdown workaround
  USB: OTG: msm: Free VCCCX regulator even if we can't set the voltage
  ...
无相关合并请求
......@@ -2585,6 +2585,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
bytes of sense data);
c = FIX_CAPACITY (decrease the reported
device capacity by one sector);
d = NO_READ_DISC_INFO (don't use
READ_DISC_INFO command);
e = NO_READ_CAPACITY_16 (don't use
READ_CAPACITY_16 command);
h = CAPACITY_HEURISTICS (decrease the
reported device capacity by one
sector if the number is odd);
......
......@@ -95,9 +95,11 @@ pre_reset
int (*pre_reset)(struct usb_interface *intf);
Another driver or user space is triggering a reset on the device which
contains the interface passed as an argument. Cease IO and save any
device state you need to restore.
A driver or user space is triggering a reset on the device which
contains the interface passed as an argument. Cease IO, wait for all
outstanding URBs to complete, and save any device state you need to
restore. No more URBs may be submitted until the post_reset method
is called.
If you need to allocate memory here, use GFP_NOIO or GFP_ATOMIC, if you
are in atomic context.
......
......@@ -90,10 +90,10 @@ ServiceBinary=%12%\USBSER.sys
[SourceDisksFiles]
[SourceDisksNames]
[DeviceList]
%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_0525&PID_A4AB&MI_02
%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02
[DeviceList.NTamd64]
%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_0525&PID_A4AB&MI_02
%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02
;------------------------------------------------------------------------------
......
......@@ -18,15 +18,15 @@ DriverVer = 06/21/2006,6.0.6000.16384
; Decoration for x86 architecture
[LinuxDevices.NTx86]
%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_0525&PID_a4ab&MI_00
%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_1d6b&PID_0104&MI_00
; Decoration for x64 architecture
[LinuxDevices.NTamd64]
%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_0525&PID_a4ab&MI_00
%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_1d6b&PID_0104&MI_00
; Decoration for ia64 architecture
[LinuxDevices.NTia64]
%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_0525&PID_a4ab&MI_00
%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_1d6b&PID_0104&MI_00
;@@@ This is the common setting for setup
[ControlFlags]
......
......@@ -4253,7 +4253,7 @@ F: include/linux/isicom.h
MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
M: Felipe Balbi <balbi@ti.com>
L: linux-usb@vger.kernel.org
T: git git://gitorious.org/usb/usb.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
S: Maintained
F: drivers/usb/musb/
......@@ -4588,6 +4588,7 @@ M: Felipe Balbi <balbi@ti.com>
M: David Brownell <dbrownell@users.sourceforge.net>
L: linux-usb@vger.kernel.org
L: linux-omap@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
S: Maintained
F: drivers/usb/*/*omap*
F: arch/arm/*omap*/usb*
......
......@@ -170,6 +170,7 @@ config MACH_NURI
select S3C_DEV_HSMMC3
select S3C_DEV_I2C1
select S3C_DEV_I2C5
select S5P_DEV_USB_EHCI
select EXYNOS4_SETUP_I2C1
select EXYNOS4_SETUP_I2C5
select EXYNOS4_SETUP_SDHCI
......
......@@ -54,3 +54,5 @@ obj-$(CONFIG_EXYNOS4_SETUP_I2C7) += setup-i2c7.o
obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD) += setup-keypad.o
obj-$(CONFIG_EXYNOS4_SETUP_SDHCI) += setup-sdhci.o
obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO) += setup-sdhci-gpio.o
obj-$(CONFIG_USB_SUPPORT) += usb-phy.o
......@@ -97,7 +97,12 @@ static struct map_desc exynos4_iodesc[] __initdata = {
.pfn = __phys_to_pfn(EXYNOS4_PA_SROMC),
.length = SZ_4K,
.type = MT_DEVICE,
},
}, {
.virtual = (unsigned long)S5P_VA_USB_HSPHY,
.pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
.length = SZ_4K,
.type = MT_DEVICE,
}
};
static void exynos4_idle(void)
......
......@@ -101,6 +101,9 @@
#define EXYNOS4_PA_SROMC 0x12570000
#define EXYNOS4_PA_EHCI 0x12580000
#define EXYNOS4_PA_HSPHY 0x125B0000
#define EXYNOS4_PA_UART 0x13800000
#define EXYNOS4_PA_IIC(x) (0x13860000 + ((x) * 0x10000))
......@@ -143,6 +146,7 @@
#define S5P_PA_SROMC EXYNOS4_PA_SROMC
#define S5P_PA_SYSCON EXYNOS4_PA_SYSCON
#define S5P_PA_TIMER EXYNOS4_PA_TIMER
#define S5P_PA_EHCI EXYNOS4_PA_EHCI
#define SAMSUNG_PA_KEYPAD EXYNOS4_PA_KEYPAD
......
......@@ -33,6 +33,9 @@
#define S5P_EINT_WAKEUP_MASK S5P_PMUREG(0x0604)
#define S5P_WAKEUP_MASK S5P_PMUREG(0x0608)
#define S5P_USBHOST_PHY_CONTROL S5P_PMUREG(0x0708)
#define S5P_USBHOST_PHY_ENABLE (1 << 0)
#define S5P_MIPI_DPHY_CONTROL(n) S5P_PMUREG(0x0710 + (n) * 4)
#define S5P_MIPI_DPHY_ENABLE (1 << 0)
#define S5P_MIPI_DPHY_SRESETN (1 << 1)
......
/*
* Copyright (C) 2011 Samsung Electronics Co.Ltd
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
*
* 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
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __PLAT_S5P_REGS_USB_PHY_H
#define __PLAT_S5P_REGS_USB_PHY_H
#define EXYNOS4_HSOTG_PHYREG(x) ((x) + S5P_VA_USB_HSPHY)
#define EXYNOS4_PHYPWR EXYNOS4_HSOTG_PHYREG(0x00)
#define PHY1_HSIC_NORMAL_MASK (0xf << 9)
#define PHY1_HSIC1_SLEEP (1 << 12)
#define PHY1_HSIC1_FORCE_SUSPEND (1 << 11)
#define PHY1_HSIC0_SLEEP (1 << 10)
#define PHY1_HSIC0_FORCE_SUSPEND (1 << 9)
#define PHY1_STD_NORMAL_MASK (0x7 << 6)
#define PHY1_STD_SLEEP (1 << 8)
#define PHY1_STD_ANALOG_POWERDOWN (1 << 7)
#define PHY1_STD_FORCE_SUSPEND (1 << 6)
#define PHY0_NORMAL_MASK (0x39 << 0)
#define PHY0_SLEEP (1 << 5)
#define PHY0_OTG_DISABLE (1 << 4)
#define PHY0_ANALOG_POWERDOWN (1 << 3)
#define PHY0_FORCE_SUSPEND (1 << 0)
#define EXYNOS4_PHYCLK EXYNOS4_HSOTG_PHYREG(0x04)
#define PHY1_COMMON_ON_N (1 << 7)
#define PHY0_COMMON_ON_N (1 << 4)
#define PHY0_ID_PULLUP (1 << 2)
#define CLKSEL_MASK (0x3 << 0)
#define CLKSEL_SHIFT (0)
#define CLKSEL_48M (0x0 << 0)
#define CLKSEL_12M (0x2 << 0)
#define CLKSEL_24M (0x3 << 0)
#define EXYNOS4_RSTCON EXYNOS4_HSOTG_PHYREG(0x08)
#define HOST_LINK_PORT_SWRST_MASK (0xf << 6)
#define HOST_LINK_PORT2_SWRST (1 << 9)
#define HOST_LINK_PORT1_SWRST (1 << 8)
#define HOST_LINK_PORT0_SWRST (1 << 7)
#define HOST_LINK_ALL_SWRST (1 << 6)
#define PHY1_SWRST_MASK (0x7 << 3)
#define PHY1_HSIC_SWRST (1 << 5)
#define PHY1_STD_SWRST (1 << 4)
#define PHY1_ALL_SWRST (1 << 3)
#define PHY0_SWRST_MASK (0x7 << 0)
#define PHY0_PHYLINK_SWRST (1 << 2)
#define PHY0_HLINK_SWRST (1 << 1)
#define PHY0_SWRST (1 << 0)
#define EXYNOS4_PHY1CON EXYNOS4_HSOTG_PHYREG(0x34)
#define FPENABLEN (1 << 0)
#endif /* __PLAT_S5P_REGS_USB_PHY_H */
......@@ -30,6 +30,8 @@
#include <plat/cpu.h>
#include <plat/devs.h>
#include <plat/sdhci.h>
#include <plat/ehci.h>
#include <plat/clock.h>
#include <mach/map.h>
......@@ -262,6 +264,16 @@ static struct i2c_board_info i2c5_devs[] __initdata = {
/* max8997, To be updated */
};
/* USB EHCI */
static struct s5p_ehci_platdata nuri_ehci_pdata;
static void __init nuri_ehci_init(void)
{
struct s5p_ehci_platdata *pdata = &nuri_ehci_pdata;
s5p_ehci_set_platdata(pdata);
}
static struct platform_device *nuri_devices[] __initdata = {
/* Samsung Platform Devices */
&emmc_fixed_voltage,
......@@ -270,6 +282,7 @@ static struct platform_device *nuri_devices[] __initdata = {
&s3c_device_hsmmc3,
&s3c_device_wdt,
&s3c_device_timer[0],
&s5p_device_ehci,
/* NURI Devices */
&nuri_gpio_keys,
......@@ -291,6 +304,9 @@ static void __init nuri_machine_init(void)
i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
nuri_ehci_init();
clk_xusbxti.rate = 24000000;
/* Last */
platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
}
......
/*
* Copyright (C) 2011 Samsung Electronics Co.Ltd
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
*
* 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
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <mach/regs-pmu.h>
#include <mach/regs-usb-phy.h>
#include <plat/cpu.h>
#include <plat/usb-phy.h>
static int exynos4_usb_phy1_init(struct platform_device *pdev)
{
struct clk *otg_clk;
struct clk *xusbxti_clk;
u32 phyclk;
u32 rstcon;
int err;
otg_clk = clk_get(&pdev->dev, "otg");
if (IS_ERR(otg_clk)) {
dev_err(&pdev->dev, "Failed to get otg clock\n");
return PTR_ERR(otg_clk);
}
err = clk_enable(otg_clk);
if (err) {
clk_put(otg_clk);
return err;
}
writel(readl(S5P_USBHOST_PHY_CONTROL) | S5P_USBHOST_PHY_ENABLE,
S5P_USBHOST_PHY_CONTROL);
/* set clock frequency for PLL */
phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK;
xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
switch (clk_get_rate(xusbxti_clk)) {
case 12 * MHZ:
phyclk |= CLKSEL_12M;
break;
case 24 * MHZ:
phyclk |= CLKSEL_24M;
break;
default:
case 48 * MHZ:
/* default reference clock */
break;
}
clk_put(xusbxti_clk);
}
writel(phyclk, EXYNOS4_PHYCLK);
/* floating prevention logic: disable */
writel((readl(EXYNOS4_PHY1CON) | FPENABLEN), EXYNOS4_PHY1CON);
/* set to normal HSIC 0 and 1 of PHY1 */
writel((readl(EXYNOS4_PHYPWR) & ~PHY1_HSIC_NORMAL_MASK),
EXYNOS4_PHYPWR);
/* set to normal standard USB of PHY1 */
writel((readl(EXYNOS4_PHYPWR) & ~PHY1_STD_NORMAL_MASK), EXYNOS4_PHYPWR);
/* reset all ports of both PHY and Link */
rstcon = readl(EXYNOS4_RSTCON) | HOST_LINK_PORT_SWRST_MASK |
PHY1_SWRST_MASK;
writel(rstcon, EXYNOS4_RSTCON);
udelay(10);
rstcon &= ~(HOST_LINK_PORT_SWRST_MASK | PHY1_SWRST_MASK);
writel(rstcon, EXYNOS4_RSTCON);
udelay(50);
clk_disable(otg_clk);
clk_put(otg_clk);
return 0;
}
static int exynos4_usb_phy1_exit(struct platform_device *pdev)
{
struct clk *otg_clk;
int err;
otg_clk = clk_get(&pdev->dev, "otg");
if (IS_ERR(otg_clk)) {
dev_err(&pdev->dev, "Failed to get otg clock\n");
return PTR_ERR(otg_clk);
}
err = clk_enable(otg_clk);
if (err) {
clk_put(otg_clk);
return err;
}
writel((readl(EXYNOS4_PHYPWR) | PHY1_STD_ANALOG_POWERDOWN),
EXYNOS4_PHYPWR);
writel(readl(S5P_USBHOST_PHY_CONTROL) & ~S5P_USBHOST_PHY_ENABLE,
S5P_USBHOST_PHY_CONTROL);
clk_disable(otg_clk);
clk_put(otg_clk);
return 0;
}
int s5p_usb_phy_init(struct platform_device *pdev, int type)
{
if (type == S5P_USB_PHY_HOST)
return exynos4_usb_phy1_init(pdev);
return -EINVAL;
}
int s5p_usb_phy_exit(struct platform_device *pdev, int type)
{
if (type == S5P_USB_PHY_HOST)
return exynos4_usb_phy1_exit(pdev);
return -EINVAL;
}
......@@ -21,6 +21,10 @@
/* USB host controller */
#define S3C2410_PA_USBHOST (0x49000000)
/* S3C2416/S3C2443/S3C2450 High-Speed USB Gadget */
#define S3C2416_PA_HSUDC (0x49800000)
#define S3C2416_SZ_HSUDC (SZ_4K)
/* DMA controller */
#define S3C2410_PA_DMA (0x4B000000)
#define S3C24XX_SZ_DMA SZ_1M
......
......@@ -37,6 +37,10 @@
#define S3C2443_SYSID S3C2443_CLKREG(0x5C)
#define S3C2443_PWRCFG S3C2443_CLKREG(0x60)
#define S3C2443_RSTCON S3C2443_CLKREG(0x64)
#define S3C2443_PHYCTRL S3C2443_CLKREG(0x80)
#define S3C2443_PHYPWR S3C2443_CLKREG(0x84)
#define S3C2443_URSTCON S3C2443_CLKREG(0x88)
#define S3C2443_UCLKCON S3C2443_CLKREG(0x8C)
#define S3C2443_SWRST_RESET (0x533c2443)
......@@ -121,6 +125,27 @@
#define S3C2443_PWRCFG_SLEEP (1<<15)
#define S3C2443_PWRCFG_USBPHY (1 << 4)
#define S3C2443_URSTCON_FUNCRST (1 << 2)
#define S3C2443_URSTCON_PHYRST (1 << 0)
#define S3C2443_PHYCTRL_CLKSEL (1 << 3)
#define S3C2443_PHYCTRL_EXTCLK (1 << 2)
#define S3C2443_PHYCTRL_PLLSEL (1 << 1)
#define S3C2443_PHYCTRL_DSPORT (1 << 0)
#define S3C2443_PHYPWR_COMMON_ON (1 << 31)
#define S3C2443_PHYPWR_ANALOG_PD (1 << 4)
#define S3C2443_PHYPWR_PLL_REFCLK (1 << 3)
#define S3C2443_PHYPWR_XO_ON (1 << 2)
#define S3C2443_PHYPWR_PLL_PWRDN (1 << 1)
#define S3C2443_PHYPWR_FSUSPEND (1 << 0)
#define S3C2443_UCLKCON_DETECT_VBUS (1 << 31)
#define S3C2443_UCLKCON_FUNC_CLKEN (1 << 2)
#define S3C2443_UCLKCON_TCLKEN (1 << 0)
#include <asm/div64.h>
static inline unsigned int
......
......@@ -23,6 +23,7 @@
#include <linux/mtd/partitions.h>
#include <linux/gpio.h>
#include <linux/fb.h>
#include <linux/delay.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
......@@ -35,6 +36,7 @@
#include <plat/regs-serial.h>
#include <mach/regs-gpio.h>
#include <mach/regs-lcd.h>
#include <mach/regs-s3c2443-clock.h>
#include <mach/idle.h>
#include <mach/leds-gpio.h>
......@@ -47,6 +49,7 @@
#include <plat/cpu.h>
#include <plat/nand.h>
#include <plat/sdhci.h>
#include <plat/udc.h>
#include <plat/regs-fb-v4.h>
#include <plat/fb.h>
......@@ -121,6 +124,27 @@ static struct s3c2410_uartcfg smdk2416_uartcfgs[] __initdata = {
}
};
void smdk2416_hsudc_gpio_init(void)
{
s3c_gpio_setpull(S3C2410_GPH(14), S3C_GPIO_PULL_UP);
s3c_gpio_setpull(S3C2410_GPF(2), S3C_GPIO_PULL_NONE);
s3c_gpio_cfgpin(S3C2410_GPH(14), S3C_GPIO_SFN(1));
s3c2410_modify_misccr(S3C2416_MISCCR_SEL_SUSPND, 0);
}
void smdk2416_hsudc_gpio_uninit(void)
{
s3c2410_modify_misccr(S3C2416_MISCCR_SEL_SUSPND, 1);
s3c_gpio_setpull(S3C2410_GPH(14), S3C_GPIO_PULL_NONE);
s3c_gpio_cfgpin(S3C2410_GPH(14), S3C_GPIO_SFN(0));
}
struct s3c24xx_hsudc_platdata smdk2416_hsudc_platdata = {
.epnum = 9,
.gpio_init = smdk2416_hsudc_gpio_init,
.gpio_uninit = smdk2416_hsudc_gpio_uninit,
};
struct s3c_fb_pd_win smdk2416_fb_win[] = {
[0] = {
/* think this is the same as the smdk6410 */
......@@ -186,6 +210,7 @@ static struct platform_device *smdk2416_devices[] __initdata = {
&s3c_device_i2c0,
&s3c_device_hsmmc0,
&s3c_device_hsmmc1,
&s3c_device_usb_hsudc,
};
static void __init smdk2416_map_io(void)
......@@ -203,6 +228,8 @@ static void __init smdk2416_machine_init(void)
s3c_sdhci0_set_platdata(&smdk2416_hsmmc0_pdata);
s3c_sdhci1_set_platdata(&smdk2416_hsmmc1_pdata);
s3c24xx_hsudc_set_platdata(&smdk2416_hsudc_platdata);
gpio_request(S3C2410_GPB(4), "USBHost Power");
gpio_direction_output(S3C2410_GPB(4), 1);
......
......@@ -22,6 +22,7 @@
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/dma-mapping.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
......@@ -233,6 +234,46 @@ void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *pd)
}
}
/* USB High Speed 2.0 Device (Gadget) */
static struct resource s3c_hsudc_resource[] = {
[0] = {
.start = S3C2416_PA_HSUDC,
.end = S3C2416_PA_HSUDC + S3C2416_SZ_HSUDC - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_USBD,
.end = IRQ_USBD,
.flags = IORESOURCE_IRQ,
}
};
static u64 s3c_hsudc_dmamask = DMA_BIT_MASK(32);
struct platform_device s3c_device_usb_hsudc = {
.name = "s3c-hsudc",
.id = -1,
.num_resources = ARRAY_SIZE(s3c_hsudc_resource),
.resource = s3c_hsudc_resource,
.dev = {
.dma_mask = &s3c_hsudc_dmamask,
.coherent_dma_mask = DMA_BIT_MASK(32),
},
};
void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd)
{
struct s3c24xx_hsudc_platdata *npd;
npd = kmalloc(sizeof(*npd), GFP_KERNEL);
if (npd) {
memcpy(npd, pd, sizeof(*npd));
s3c_device_usb_hsudc.dev.platform_data = npd;
} else {
printk(KERN_ERR "no memory for udc platform data\n");
}
}
/* IIS */
static struct resource s3c_iis_resource[] = {
......
......@@ -37,4 +37,21 @@ struct s3c2410_udc_mach_info {
extern void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *);
/**
* s3c24xx_hsudc_platdata - Platform data for USB High-Speed gadget controller.
* @epnum: Number of endpoints to be instantiated by the controller driver.
* @gpio_init: Platform specific USB related GPIO initialization.
* @gpio_uninit: Platform specific USB releted GPIO uninitialzation.
*
* Representation of platform data for the S3C24XX USB 2.0 High Speed gadget
* controllers.
*/
struct s3c24xx_hsudc_platdata {
unsigned int epnum;
void (*gpio_init)(void);
void (*gpio_uninit)(void);
};
extern void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd);
#endif /* __ASM_ARM_ARCH_UDC_H */
......@@ -85,6 +85,11 @@ config S5P_DEV_CSIS1
help
Compile in platform device definitions for MIPI-CSIS channel 1
config S5P_DEV_USB_EHCI
bool
help
Compile in platform device definition for USB EHCI
config S5P_SETUP_MIPIPHY
bool
help
......
......@@ -33,4 +33,5 @@ obj-$(CONFIG_S5P_DEV_FIMC3) += dev-fimc3.o
obj-$(CONFIG_S5P_DEV_ONENAND) += dev-onenand.o
obj-$(CONFIG_S5P_DEV_CSIS0) += dev-csis0.o
obj-$(CONFIG_S5P_DEV_CSIS1) += dev-csis1.o
obj-$(CONFIG_S5P_DEV_USB_EHCI) += dev-ehci.o
obj-$(CONFIG_S5P_SETUP_MIPIPHY) += setup-mipiphy.o
/*
* Copyright (C) 2011 Samsung Electronics Co.Ltd
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
*
* 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
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/platform_device.h>
#include <mach/irqs.h>
#include <mach/map.h>
#include <plat/devs.h>
#include <plat/ehci.h>
#include <plat/usb-phy.h>
/* USB EHCI Host Controller registration */
static struct resource s5p_ehci_resource[] = {
[0] = {
.start = S5P_PA_EHCI,
.end = S5P_PA_EHCI + SZ_256 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_USB_HOST,
.end = IRQ_USB_HOST,
.flags = IORESOURCE_IRQ,
}
};
static u64 s5p_device_ehci_dmamask = 0xffffffffUL;
struct platform_device s5p_device_ehci = {
.name = "s5p-ehci",
.id = -1,
.num_resources = ARRAY_SIZE(s5p_ehci_resource),
.resource = s5p_ehci_resource,
.dev = {
.dma_mask = &s5p_device_ehci_dmamask,
.coherent_dma_mask = 0xffffffffUL
}
};
void __init s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd)
{
struct s5p_ehci_platdata *npd;
npd = s3c_set_platdata(pd, sizeof(struct s5p_ehci_platdata),
&s5p_device_ehci);
if (!npd->phy_init)
npd->phy_init = s5p_usb_phy_init;
if (!npd->phy_exit)
npd->phy_exit = s5p_usb_phy_exit;
}
/*
* Copyright (C) 2011 Samsung Electronics Co.Ltd
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
*
* 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
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __PLAT_S5P_EHCI_H
#define __PLAT_S5P_EHCI_H
struct s5p_ehci_platdata {
int (*phy_init)(struct platform_device *pdev, int type);
int (*phy_exit)(struct platform_device *pdev, int type);
};
extern void s5p_ehci_set_platdata(struct s5p_ehci_platdata *pd);
#endif /* __PLAT_S5P_EHCI_H */
......@@ -39,7 +39,7 @@
#define S5P_VA_TWD S5P_VA_COREPERI(0x600)
#define S5P_VA_GIC_DIST S5P_VA_COREPERI(0x1000)
#define S3C_VA_USB_HSPHY S3C_ADDR(0x02900000)
#define S5P_VA_USB_HSPHY S3C_ADDR(0x02900000)
#define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000))
#define VA_VIC0 VA_VIC(0)
......
/*
* Copyright (C) 2011 Samsung Electronics Co.Ltd
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
*
* 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
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __PLAT_S5P_USB_PHY_H
#define __PLAT_S5P_USB_PHY_H
enum s5p_usb_phy_type {
S5P_USB_PHY_DEVICE,
S5P_USB_PHY_HOST,
};
extern int s5p_usb_phy_init(struct platform_device *pdev, int type);
extern int s5p_usb_phy_exit(struct platform_device *pdev, int type);
#endif /* __PLAT_S5P_REGS_USB_PHY_H */
......@@ -88,6 +88,7 @@ extern struct platform_device s3c64xx_device_onenand1;
extern struct platform_device s5p_device_onenand;
extern struct platform_device s3c_device_usbgadget;
extern struct platform_device s3c_device_usb_hsudc;
extern struct platform_device s3c_device_usb_hsotg;
extern struct platform_device s5pv210_device_ac97;
......@@ -142,6 +143,8 @@ extern struct platform_device s5p_device_fimc3;
extern struct platform_device s5p_device_mipi_csis0;
extern struct platform_device s5p_device_mipi_csis1;
extern struct platform_device s5p_device_ehci;
extern struct platform_device exynos4_device_sysmmu;
/* s3c2440 specific devices */
......
......@@ -26,12 +26,17 @@ config ATH79_MACH_PB44
endmenu
config SOC_AR71XX
select USB_ARCH_HAS_EHCI
select USB_ARCH_HAS_OHCI
def_bool n
config SOC_AR724X
select USB_ARCH_HAS_EHCI
select USB_ARCH_HAS_OHCI
def_bool n
config SOC_AR913X
select USB_ARCH_HAS_EHCI
def_bool n
config ATH79_DEV_AR913X_WMAC
......
......@@ -64,11 +64,10 @@ obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/
obj-$(CONFIG_PARIDE) += block/paride/
obj-$(CONFIG_TC) += tc/
obj-$(CONFIG_UWB) += uwb/
obj-$(CONFIG_USB_OTG_UTILS) += usb/otg/
obj-$(CONFIG_USB_OTG_UTILS) += usb/
obj-$(CONFIG_USB) += usb/
obj-$(CONFIG_USB_MUSB_HDRC) += usb/musb/
obj-$(CONFIG_PCI) += usb/
obj-$(CONFIG_USB_GADGET) += usb/gadget/
obj-$(CONFIG_USB_GADGET) += usb/
obj-$(CONFIG_SERIO) += input/serio/
obj-$(CONFIG_GAMEPORT) += input/gameport/
obj-$(CONFIG_INPUT) += input/
......
......@@ -1775,19 +1775,37 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_KYE, 0x0058) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYVOLTAGE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYCURRENT) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTIME) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MICROCASSYPH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIC) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIB) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOTOR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOSTANALYSER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOSTANALYSER2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_ABSESP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_AUTODATABUS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MCT) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) },
......
......@@ -380,19 +380,38 @@
#define USB_VENDOR_ID_LD 0x0f11
#define USB_DEVICE_ID_LD_CASSY 0x1000
#define USB_DEVICE_ID_LD_CASSY2 0x1001
#define USB_DEVICE_ID_LD_POCKETCASSY 0x1010
#define USB_DEVICE_ID_LD_POCKETCASSY2 0x1011
#define USB_DEVICE_ID_LD_MOBILECASSY 0x1020
#define USB_DEVICE_ID_LD_MOBILECASSY2 0x1021
#define USB_DEVICE_ID_LD_MICROCASSYVOLTAGE 0x1031
#define USB_DEVICE_ID_LD_MICROCASSYCURRENT 0x1032
#define USB_DEVICE_ID_LD_MICROCASSYTIME 0x1033
#define USB_DEVICE_ID_LD_MICROCASSYTEMPERATURE 0x1035
#define USB_DEVICE_ID_LD_MICROCASSYPH 0x1038
#define USB_DEVICE_ID_LD_JWM 0x1080
#define USB_DEVICE_ID_LD_DMMP 0x1081
#define USB_DEVICE_ID_LD_UMIP 0x1090
#define USB_DEVICE_ID_LD_XRAY1 0x1100
#define USB_DEVICE_ID_LD_UMIC 0x10A0
#define USB_DEVICE_ID_LD_UMIB 0x10B0
#define USB_DEVICE_ID_LD_XRAY 0x1100
#define USB_DEVICE_ID_LD_XRAY2 0x1101
#define USB_DEVICE_ID_LD_XRAYCT 0x1110
#define USB_DEVICE_ID_LD_VIDEOCOM 0x1200
#define USB_DEVICE_ID_LD_MOTOR 0x1210
#define USB_DEVICE_ID_LD_COM3LAB 0x2000
#define USB_DEVICE_ID_LD_TELEPORT 0x2010
#define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020
#define USB_DEVICE_ID_LD_POWERCONTROL 0x2030
#define USB_DEVICE_ID_LD_MACHINETEST 0x2040
#define USB_DEVICE_ID_LD_MOSTANALYSER 0x2050
#define USB_DEVICE_ID_LD_MOSTANALYSER2 0x2051
#define USB_DEVICE_ID_LD_ABSESP 0x2060
#define USB_DEVICE_ID_LD_AUTODATABUS 0x2070
#define USB_DEVICE_ID_LD_MCT 0x2080
#define USB_DEVICE_ID_LD_HYBRID 0x2090
#define USB_DEVICE_ID_LD_HEATCONTROL 0x20A0
#define USB_VENDOR_ID_LOGITECH 0x046d
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
......
......@@ -65,8 +65,10 @@ config USB_ARCH_HAS_EHCI
default y if ARCH_CNS3XXX
default y if ARCH_VT8500
default y if PLAT_SPEAR
default y if PLAT_S5P
default y if ARCH_MSM
default y if MICROBLAZE
default y if SPARC_LEON
default PCI
# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
......@@ -116,6 +118,8 @@ source "drivers/usb/host/Kconfig"
source "drivers/usb/musb/Kconfig"
source "drivers/usb/renesas_usbhs/Kconfig"
source "drivers/usb/class/Kconfig"
source "drivers/usb/storage/Kconfig"
......
......@@ -22,6 +22,7 @@ obj-$(CONFIG_USB_R8A66597_HCD) += host/
obj-$(CONFIG_USB_HWA_HCD) += host/
obj-$(CONFIG_USB_ISP1760_HCD) += host/
obj-$(CONFIG_USB_IMX21_HCD) += host/
obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/
obj-$(CONFIG_USB_C67X00_HCD) += c67x00/
......@@ -45,3 +46,8 @@ obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/
obj-$(CONFIG_USB_ATM) += atm/
obj-$(CONFIG_USB_SPEEDTOUCH) += atm/
obj-$(CONFIG_USB_MUSB_HDRC) += musb/
obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs/
obj-$(CONFIG_USB_OTG_UTILS) += otg/
obj-$(CONFIG_USB_GADGET) += gadget/
此差异已折叠。
......@@ -72,16 +72,10 @@ struct acm_wb {
};
struct acm_rb {
struct list_head list;
int size;
unsigned char *base;
dma_addr_t dma;
};
struct acm_ru {
struct list_head list;
struct acm_rb *buffer;
struct urb *urb;
int index;
struct acm *instance;
};
......@@ -97,35 +91,30 @@ struct acm {
unsigned int country_code_size; /* size of this buffer */
unsigned int country_rel_date; /* release date of version */
struct acm_wb wb[ACM_NW];
struct acm_ru ru[ACM_NR];
struct acm_rb rb[ACM_NR];
unsigned long read_urbs_free;
struct urb *read_urbs[ACM_NR];
struct acm_rb read_buffers[ACM_NR];
int rx_buflimit;
int rx_endpoint;
spinlock_t read_lock;
struct list_head spare_read_urbs;
struct list_head spare_read_bufs;
struct list_head filled_read_bufs;
int write_used; /* number of non-empty write buffers */
int processing;
int transmitting;
spinlock_t write_lock;
struct mutex mutex;
struct usb_cdc_line_coding line; /* bits, stop, parity */
struct work_struct work; /* work queue entry for line discipline waking up */
wait_queue_head_t drain_wait; /* close processing */
struct tasklet_struct urb_task; /* rx processing */
spinlock_t throttle_lock; /* synchronize throtteling and read callback */
unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
unsigned int ctrlout; /* output control lines (DTR, RTS) */
unsigned int writesize; /* max packet size for the output bulk endpoint */
unsigned int readsize,ctrlsize; /* buffer sizes for freeing */
unsigned int minor; /* acm minor number */
unsigned char throttle; /* throttled by tty layer */
unsigned char clocal; /* termios CLOCAL */
unsigned int ctrl_caps; /* control capabilities from the class specific header */
unsigned int susp_count; /* number of suspended interfaces */
unsigned int combined_interfaces:1; /* control and data collapsed */
unsigned int is_int_ep:1; /* interrupt endpoints contrary to spec used */
unsigned int throttled:1; /* actually throttled */
unsigned int throttle_req:1; /* throttle requested */
u8 bInterval;
struct acm_wb *delayed_wb; /* write queued for a device about to be woken */
};
......@@ -137,3 +126,4 @@ struct acm {
#define SINGLE_RX_URB 2
#define NO_CAP_LINE 4
#define NOT_A_MODEM 8
#define NO_DATA_INTERFACE 16
......@@ -542,6 +542,8 @@ static int wdm_open(struct inode *inode, struct file *file)
mutex_lock(&desc->lock);
if (!desc->count++) {
desc->werr = 0;
desc->rerr = 0;
rv = usb_submit_urb(desc->validity, GFP_KERNEL);
if (rv < 0) {
desc->count--;
......@@ -853,6 +855,18 @@ static int wdm_pre_reset(struct usb_interface *intf)
struct wdm_device *desc = usb_get_intfdata(intf);
mutex_lock(&desc->lock);
kill_urbs(desc);
/*
* we notify everybody using poll of
* an exceptional situation
* must be done before recovery lest a spontaneous
* message from the device is lost
*/
spin_lock_irq(&desc->iuspin);
desc->rerr = -EINTR;
spin_unlock_irq(&desc->iuspin);
wake_up_all(&desc->wait);
return 0;
}
......
......@@ -129,7 +129,7 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
max_tx = ep->desc.wMaxPacketSize * (desc->bMaxBurst + 1);
else
max_tx = 999999;
if (desc->wBytesPerInterval > max_tx) {
if (le16_to_cpu(desc->wBytesPerInterval) > max_tx) {
dev_warn(ddev, "%s endpoint with wBytesPerInterval of %d in "
"config %d interface %d altsetting %d ep %d: "
"setting to %d\n",
......
......@@ -64,49 +64,49 @@
/* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */
#define ALLOW_SERIAL_NUMBER
static const char *format_topo =
static const char format_topo[] =
/* T: Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=dddd MxCh=dd */
"\nT: Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%-4s MxCh=%2d\n";
static const char *format_string_manufacturer =
static const char format_string_manufacturer[] =
/* S: Manufacturer=xxxx */
"S: Manufacturer=%.100s\n";
static const char *format_string_product =
static const char format_string_product[] =
/* S: Product=xxxx */
"S: Product=%.100s\n";
#ifdef ALLOW_SERIAL_NUMBER
static const char *format_string_serialnumber =
static const char format_string_serialnumber[] =
/* S: SerialNumber=xxxx */
"S: SerialNumber=%.100s\n";
#endif
static const char *format_bandwidth =
static const char format_bandwidth[] =
/* B: Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
"B: Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n";
static const char *format_device1 =
static const char format_device1[] =
/* D: Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */
"D: Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n";
static const char *format_device2 =
static const char format_device2[] =
/* P: Vendor=xxxx ProdID=xxxx Rev=xx.xx */
"P: Vendor=%04x ProdID=%04x Rev=%2x.%02x\n";
static const char *format_config =
static const char format_config[] =
/* C: #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
"C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
static const char *format_iad =
static const char format_iad[] =
/* A: FirstIf#=dd IfCount=dd Cls=xx(sssss) Sub=xx Prot=xx */
"A: FirstIf#=%2d IfCount=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x\n";
static const char *format_iface =
static const char format_iface[] =
/* I: If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/
"I:%c If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
static const char *format_endpt =
static const char format_endpt[] =
/* E: Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=D?s */
"E: Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%d%cs\n";
......
......@@ -236,13 +236,6 @@ EXPORT_SYMBOL_GPL(usb_register_dev);
void usb_deregister_dev(struct usb_interface *intf,
struct usb_class_driver *class_driver)
{
int minor_base = class_driver->minor_base;
char name[20];
#ifdef CONFIG_USB_DYNAMIC_MINORS
minor_base = 0;
#endif
if (intf->minor == -1)
return;
......@@ -252,7 +245,6 @@ void usb_deregister_dev(struct usb_interface *intf,
usb_minors[intf->minor] = NULL;
up_write(&minor_rwsem);
snprintf(name, sizeof(name), class_driver->name, intf->minor - minor_base);
device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor));
intf->usb_dev = NULL;
intf->minor = -1;
......
......@@ -986,7 +986,7 @@ static int register_root_hub(struct usb_hcd *hcd)
spin_unlock_irq (&hcd_root_hub_lock);
/* Did the HC die before the root hub was registered? */
if (HCD_DEAD(hcd) || hcd->state == HC_STATE_HALT)
if (HCD_DEAD(hcd))
usb_hc_died (hcd); /* This time clean up */
}
......@@ -2128,9 +2128,6 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
if (hcd->shared_hcd)
set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
if (unlikely(hcd->state == HC_STATE_HALT))
usb_hc_died(hcd);
rc = IRQ_HANDLED;
}
......@@ -2407,6 +2404,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
rhdev->speed = USB_SPEED_SUPER;
break;
default:
retval = -EINVAL;
goto err_set_rh_speed;
}
......
......@@ -379,15 +379,6 @@ static int hub_port_status(struct usb_hub *hub, int port1,
*status = le16_to_cpu(hub->status->port.wPortStatus);
*change = le16_to_cpu(hub->status->port.wPortChange);
if ((hub->hdev->parent != NULL) &&
hub_is_superspeed(hub->hdev)) {
/* Translate the USB 3 port status */
u16 tmp = *status & USB_SS_PORT_STAT_MASK;
if (*status & USB_SS_PORT_STAT_POWER)
tmp |= USB_PORT_STAT_POWER;
*status = tmp;
}
ret = 0;
}
mutex_unlock(&hub->status_mutex);
......@@ -2160,11 +2151,76 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
return status;
}
/* Warm reset a USB3 protocol port */
static int hub_port_warm_reset(struct usb_hub *hub, int port)
{
int ret;
u16 portstatus, portchange;
if (!hub_is_superspeed(hub->hdev)) {
dev_err(hub->intfdev, "only USB3 hub support warm reset\n");
return -EINVAL;
}
/* Warm reset the port */
ret = set_port_feature(hub->hdev,
port, USB_PORT_FEAT_BH_PORT_RESET);
if (ret) {
dev_err(hub->intfdev, "cannot warm reset port %d\n", port);
return ret;
}
msleep(20);
ret = hub_port_status(hub, port, &portstatus, &portchange);
if (portchange & USB_PORT_STAT_C_RESET)
clear_port_feature(hub->hdev, port, USB_PORT_FEAT_C_RESET);
if (portchange & USB_PORT_STAT_C_BH_RESET)
clear_port_feature(hub->hdev, port,
USB_PORT_FEAT_C_BH_PORT_RESET);
if (portchange & USB_PORT_STAT_C_LINK_STATE)
clear_port_feature(hub->hdev, port,
USB_PORT_FEAT_C_PORT_LINK_STATE);
return ret;
}
/* Check if a port is power on */
static int port_is_power_on(struct usb_hub *hub, unsigned portstatus)
{
int ret = 0;
if (hub_is_superspeed(hub->hdev)) {
if (portstatus & USB_SS_PORT_STAT_POWER)
ret = 1;
} else {
if (portstatus & USB_PORT_STAT_POWER)
ret = 1;
}
return ret;
}
#ifdef CONFIG_PM
#define MASK_BITS (USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION | \
USB_PORT_STAT_SUSPEND)
#define WANT_BITS (USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION)
/* Check if a port is suspended(USB2.0 port) or in U3 state(USB3.0 port) */
static int port_is_suspended(struct usb_hub *hub, unsigned portstatus)
{
int ret = 0;
if (hub_is_superspeed(hub->hdev)) {
if ((portstatus & USB_PORT_STAT_LINK_STATE)
== USB_SS_PORT_LS_U3)
ret = 1;
} else {
if (portstatus & USB_PORT_STAT_SUSPEND)
ret = 1;
}
return ret;
}
/* Determine whether the device on a port is ready for a normal resume,
* is ready for a reset-resume, or should be disconnected.
......@@ -2174,7 +2230,9 @@ static int check_port_resume_type(struct usb_device *udev,
int status, unsigned portchange, unsigned portstatus)
{
/* Is the device still present? */
if (status || (portstatus & MASK_BITS) != WANT_BITS) {
if (status || port_is_suspended(hub, portstatus) ||
!port_is_power_on(hub, portstatus) ||
!(portstatus & USB_PORT_STAT_CONNECTION)) {
if (status >= 0)
status = -ENODEV;
}
......@@ -2285,14 +2343,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
}
/* see 7.1.7.6 */
/* Clear PORT_POWER if it's a USB3.0 device connected to USB 3.0
* external hub.
* FIXME: this is a temporary workaround to make the system able
* to suspend/resume.
*/
if ((hub->hdev->parent != NULL) && hub_is_superspeed(hub->hdev))
status = clear_port_feature(hub->hdev, port1,
USB_PORT_FEAT_POWER);
if (hub_is_superspeed(hub->hdev))
status = set_port_feature(hub->hdev,
port1 | (USB_SS_PORT_LS_U3 << 3),
USB_PORT_FEAT_LINK_STATE);
else
status = set_port_feature(hub->hdev, port1,
USB_PORT_FEAT_SUSPEND);
......@@ -2439,7 +2493,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
/* Skip the initial Clear-Suspend step for a remote wakeup */
status = hub_port_status(hub, port1, &portstatus, &portchange);
if (status == 0 && !(portstatus & USB_PORT_STAT_SUSPEND))
if (status == 0 && !port_is_suspended(hub, portstatus))
goto SuspendCleared;
// dev_dbg(hub->intfdev, "resume port %d\n", port1);
......@@ -2447,8 +2501,13 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
set_bit(port1, hub->busy_bits);
/* see 7.1.7.7; affects power usage, but not budgeting */
status = clear_port_feature(hub->hdev,
port1, USB_PORT_FEAT_SUSPEND);
if (hub_is_superspeed(hub->hdev))
status = set_port_feature(hub->hdev,
port1 | (USB_SS_PORT_LS_U0 << 3),
USB_PORT_FEAT_LINK_STATE);
else
status = clear_port_feature(hub->hdev,
port1, USB_PORT_FEAT_SUSPEND);
if (status) {
dev_dbg(hub->intfdev, "can't resume port %d, status %d\n",
port1, status);
......@@ -2470,9 +2529,15 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
SuspendCleared:
if (status == 0) {
if (portchange & USB_PORT_STAT_C_SUSPEND)
clear_port_feature(hub->hdev, port1,
USB_PORT_FEAT_C_SUSPEND);
if (hub_is_superspeed(hub->hdev)) {
if (portchange & USB_PORT_STAT_C_LINK_STATE)
clear_port_feature(hub->hdev, port1,
USB_PORT_FEAT_C_PORT_LINK_STATE);
} else {
if (portchange & USB_PORT_STAT_C_SUSPEND)
clear_port_feature(hub->hdev, port1,
USB_PORT_FEAT_C_SUSPEND);
}
}
clear_bit(port1, hub->busy_bits);
......@@ -3147,7 +3212,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
/* maybe switch power back on (e.g. root hub was reset) */
if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
&& !(portstatus & USB_PORT_STAT_POWER))
&& !port_is_power_on(hub, portstatus))
set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
if (portstatus & USB_PORT_STAT_ENABLE)
......@@ -3490,6 +3555,16 @@ static void hub_events(void)
USB_PORT_FEAT_C_PORT_CONFIG_ERROR);
}
/* Warm reset a USB3 protocol port if it's in
* SS.Inactive state.
*/
if (hub_is_superspeed(hub->hdev) &&
(portstatus & USB_PORT_STAT_LINK_STATE)
== USB_SS_PORT_LS_SS_INACTIVE) {
dev_dbg(hub_dev, "warm reset port %d\n", i);
hub_port_warm_reset(hub, i);
}
if (connect_change)
hub_port_connect_change(hub, i,
portstatus, portchange);
......
......@@ -842,22 +842,19 @@ const struct attribute_group *usb_interface_groups[] = {
NULL
};
int usb_create_sysfs_intf_files(struct usb_interface *intf)
void usb_create_sysfs_intf_files(struct usb_interface *intf)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_host_interface *alt = intf->cur_altsetting;
int retval;
if (intf->sysfs_files_created || intf->unregistering)
return 0;
return;
if (alt->string == NULL &&
!(udev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
if (!alt->string && !(udev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS))
alt->string = usb_cache_string(udev, alt->desc.iInterface);
if (alt->string)
retval = device_create_file(&intf->dev, &dev_attr_interface);
if (alt->string && device_create_file(&intf->dev, &dev_attr_interface))
; /* We don't actually care if the function fails. */
intf->sysfs_files_created = 1;
return 0;
}
void usb_remove_sysfs_intf_files(struct usb_interface *intf)
......
......@@ -953,8 +953,7 @@ static int usb_bus_notify(struct notifier_block *nb, unsigned long action,
if (dev->type == &usb_device_type)
(void) usb_create_sysfs_dev_files(to_usb_device(dev));
else if (dev->type == &usb_if_device_type)
(void) usb_create_sysfs_intf_files(
to_usb_interface(dev));
usb_create_sysfs_intf_files(to_usb_interface(dev));
break;
case BUS_NOTIFY_DEL_DEVICE:
......
......@@ -4,7 +4,7 @@
extern int usb_create_sysfs_dev_files(struct usb_device *dev);
extern void usb_remove_sysfs_dev_files(struct usb_device *dev);
extern int usb_create_sysfs_intf_files(struct usb_interface *intf);
extern void usb_create_sysfs_intf_files(struct usb_interface *intf);
extern void usb_remove_sysfs_intf_files(struct usb_interface *intf);
extern int usb_create_ep_devs(struct device *parent,
struct usb_host_endpoint *endpoint,
......
......@@ -102,6 +102,9 @@ static struct kgdb_io kgdbdbgp_io_ops;
#define dbgp_kgdb_mode (0)
#endif
/* Local version of HC_LENGTH macro as ehci struct is not available here */
#define EARLY_HC_LENGTH(p) (0x00ff & (p)) /* bits 7 : 0 */
/*
* USB Packet IDs (PIDs)
*/
......@@ -892,7 +895,7 @@ int __init early_dbgp_init(char *s)
dbgp_printk("ehci_bar: %p\n", ehci_bar);
ehci_caps = ehci_bar;
ehci_regs = ehci_bar + HC_LENGTH(readl(&ehci_caps->hc_capbase));
ehci_regs = ehci_bar + EARLY_HC_LENGTH(readl(&ehci_caps->hc_capbase));
ehci_debug = ehci_bar + offset;
ehci_dev.bus = bus;
ehci_dev.slot = slot;
......
......@@ -260,6 +260,24 @@ config USB_R8A66597
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_RENESAS_USBHS
boolean "Renesas USBHS"
depends on USB_RENESAS_USBHS
select USB_GADGET_DUALSPEED
help
Renesas USBHS is a discrete USB host and peripheral controller
chip that supports both full and high speed USB 2.0 data transfers.
platform is able to configure endpoint (pipe) style
Say "y" to enable the gadget specific portion of the USBHS driver.
config USB_RENESAS_USBHS_UDC
tristate
depends on USB_GADGET_RENESAS_USBHS
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_PXA27X
boolean "PXA 27x"
depends on ARCH_PXA && (PXA27x || PXA3xx)
......@@ -338,6 +356,23 @@ config USB_S3C2410_DEBUG
boolean "S3C2410 udc debug messages"
depends on USB_GADGET_S3C2410
config USB_GADGET_S3C_HSUDC
boolean "S3C2416, S3C2443 and S3C2450 USB Device Controller"
depends on ARCH_S3C2410
select USB_GADGET_DUALSPEED
help
Samsung's S3C2416, S3C2443 and S3C2450 is an ARM9 based SoC
integrated with dual speed USB 2.0 device controller. It has
8 endpoints, as well as endpoint zero.
This driver has been tested on S3C2416 and S3C2450 processors.
config USB_S3C_HSUDC
tristate
depends on USB_GADGET_S3C_HSUDC
default USB_GADGET
select USB_GADGET_SELECTED
config USB_GADGET_PXA_U2O
boolean "PXA9xx Processor USB2.0 controller"
select USB_GADGET_DUALSPEED
......
......@@ -22,6 +22,7 @@ obj-$(CONFIG_USB_R8A66597) += r8a66597-udc.o
obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o
obj-$(CONFIG_USB_CI13XXX_PCI) += ci13xxx_pci.o
obj-$(CONFIG_USB_S3C_HSOTG) += s3c-hsotg.o
obj-$(CONFIG_USB_S3C_HSUDC) += s3c-hsudc.o
obj-$(CONFIG_USB_LANGWELL) += langwell_udc.o
obj-$(CONFIG_USB_EG20T) += pch_udc.o
obj-$(CONFIG_USB_PXA_U2O) += mv_udc.o
......
......@@ -1767,7 +1767,7 @@ static int __init at91udc_probe(struct platform_device *pdev)
}
/* newer chips have more FIFO memory than rm9200 */
if (cpu_is_at91sam9260()) {
if (cpu_is_at91sam9260() || cpu_is_at91sam9g20()) {
udc->ep[0].maxpacket = 64;
udc->ep[3].maxpacket = 64;
udc->ep[4].maxpacket = 512;
......
......@@ -310,7 +310,7 @@ static int hw_device_reset(struct ci13xxx *udc)
udc->udc_driver->notify_event(udc,
CI13XXX_CONTROLLER_RESET_EVENT);
if (udc->udc_driver->flags && CI13XXX_DISABLE_STREAMING)
if (udc->udc_driver->flags & CI13XXX_DISABLE_STREAMING)
hw_cwrite(CAP_USBMODE, USBMODE_SDIS, USBMODE_SDIS);
/* USBMODE should be configured step by step */
......@@ -1634,8 +1634,6 @@ static int _gadget_stop_activity(struct usb_gadget *gadget)
gadget_for_each_ep(ep, gadget) {
usb_ep_disable(ep);
}
usb_ep_disable(&udc->ep0out.ep);
usb_ep_disable(&udc->ep0in.ep);
if (udc->status != NULL) {
usb_ep_free_request(&udc->ep0in.ep, udc->status);
......@@ -1678,18 +1676,10 @@ __acquires(udc->lock)
if (retval)
goto done;
retval = usb_ep_enable(&udc->ep0out.ep, &ctrl_endpt_out_desc);
if (retval)
goto done;
udc->status = usb_ep_alloc_request(&udc->ep0in.ep, GFP_ATOMIC);
if (udc->status == NULL)
retval = -ENOMEM;
retval = usb_ep_enable(&udc->ep0in.ep, &ctrl_endpt_in_desc);
if (!retval) {
udc->status = usb_ep_alloc_request(&udc->ep0in.ep, GFP_ATOMIC);
if (udc->status == NULL) {
usb_ep_disable(&udc->ep0out.ep);
retval = -ENOMEM;
}
}
spin_lock(udc->lock);
done:
......@@ -1843,7 +1833,8 @@ __releases(mEp->lock)
__acquires(mEp->lock)
{
struct ci13xxx_req *mReq, *mReqTemp;
int retval;
struct ci13xxx_ep *mEpTemp = mEp;
int uninitialized_var(retval);
trace("%p", mEp);
......@@ -1859,12 +1850,15 @@ __acquires(mEp->lock)
dbg_done(_usb_addr(mEp), mReq->ptr->token, retval);
if (mReq->req.complete != NULL) {
spin_unlock(mEp->lock);
mReq->req.complete(&mEp->ep, &mReq->req);
if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) &&
mReq->req.length)
mEpTemp = &_udc->ep0in;
mReq->req.complete(&mEpTemp->ep, &mReq->req);
spin_lock(mEp->lock);
}
}
if (retval == EBUSY)
if (retval == -EBUSY)
retval = 0;
if (retval < 0)
dbg_event(_usb_addr(mEp), "DONE", retval);
......@@ -1894,7 +1888,7 @@ __acquires(udc->lock)
for (i = 0; i < hw_ep_max; i++) {
struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i];
int type, num, err = -EINVAL;
int type, num, dir, err = -EINVAL;
struct usb_ctrlrequest req;
if (mEp->desc == NULL)
......@@ -1952,7 +1946,10 @@ __acquires(udc->lock)
if (req.wLength != 0)
break;
num = le16_to_cpu(req.wIndex);
dir = num & USB_ENDPOINT_DIR_MASK;
num &= USB_ENDPOINT_NUMBER_MASK;
if (dir) /* TX */
num += hw_ep_max/2;
if (!udc->ci13xxx_ep[num].wedge) {
spin_unlock(udc->lock);
err = usb_ep_clear_halt(
......@@ -2001,7 +1998,10 @@ __acquires(udc->lock)
if (req.wLength != 0)
break;
num = le16_to_cpu(req.wIndex);
dir = num & USB_ENDPOINT_DIR_MASK;
num &= USB_ENDPOINT_NUMBER_MASK;
if (dir) /* TX */
num += hw_ep_max/2;
spin_unlock(udc->lock);
err = usb_ep_set_halt(&udc->ci13xxx_ep[num].ep);
......@@ -2110,7 +2110,12 @@ static int ep_enable(struct usb_ep *ep,
(mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT;
mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */
retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type);
/*
* Enable endpoints in the HW other than ep0 as ep0
* is always enabled
*/
if (mEp->num)
retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type);
spin_unlock_irqrestore(mEp->lock, flags);
return retval;
......@@ -2242,11 +2247,15 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req,
spin_lock_irqsave(mEp->lock, flags);
if (mEp->type == USB_ENDPOINT_XFER_CONTROL &&
!list_empty(&mEp->qh.queue)) {
_ep_nuke(mEp);
retval = -EOVERFLOW;
warn("endpoint ctrl %X nuked", _usb_addr(mEp));
if (mEp->type == USB_ENDPOINT_XFER_CONTROL) {
if (req->length)
mEp = (_udc->ep0_dir == RX) ?
&_udc->ep0out : &_udc->ep0in;
if (!list_empty(&mEp->qh.queue)) {
_ep_nuke(mEp);
retval = -EOVERFLOW;
warn("endpoint ctrl %X nuked", _usb_addr(mEp));
}
}
/* first nuke then test link, e.g. previous status has not sent */
......@@ -2497,6 +2506,15 @@ static int ci13xxx_wakeup(struct usb_gadget *_gadget)
return ret;
}
static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
{
struct ci13xxx *udc = container_of(_gadget, struct ci13xxx, gadget);
if (udc->transceiver)
return otg_set_power(udc->transceiver, mA);
return -ENOTSUPP;
}
/**
* Device operations part of the API to the USB controller hardware,
* which don't involve endpoints (or i/o)
......@@ -2505,6 +2523,7 @@ static int ci13xxx_wakeup(struct usb_gadget *_gadget)
static const struct usb_gadget_ops usb_gadget_ops = {
.vbus_session = ci13xxx_vbus_session,
.wakeup = ci13xxx_wakeup,
.vbus_draw = ci13xxx_vbus_draw,
};
/**
......@@ -2595,6 +2614,14 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
}
if (retval)
goto done;
spin_unlock_irqrestore(udc->lock, flags);
retval = usb_ep_enable(&udc->ep0out.ep, &ctrl_endpt_out_desc);
if (retval)
return retval;
retval = usb_ep_enable(&udc->ep0in.ep, &ctrl_endpt_in_desc);
if (retval)
return retval;
spin_lock_irqsave(udc->lock, flags);
udc->gadget.ep0 = &udc->ep0in.ep;
/* bind gadget */
......
......@@ -461,12 +461,23 @@ static int set_config(struct usb_composite_dev *cdev,
reset_config(cdev);
goto done;
}
if (result == USB_GADGET_DELAYED_STATUS) {
DBG(cdev,
"%s: interface %d (%s) requested delayed status\n",
__func__, tmp, f->name);
cdev->delayed_status++;
DBG(cdev, "delayed_status count %d\n",
cdev->delayed_status);
}
}
/* when we return, be sure our power usage is valid */
power = c->bMaxPower ? (2 * c->bMaxPower) : CONFIG_USB_GADGET_VBUS_DRAW;
done:
usb_gadget_vbus_draw(gadget, power);
if (result >= 0 && cdev->delayed_status)
result = USB_GADGET_DELAYED_STATUS;
return result;
}
......@@ -895,6 +906,14 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (w_value && !f->set_alt)
break;
value = f->set_alt(f, w_index, w_value);
if (value == USB_GADGET_DELAYED_STATUS) {
DBG(cdev,
"%s: interface %d (%s) requested delayed status\n",
__func__, intf, f->name);
cdev->delayed_status++;
DBG(cdev, "delayed_status count %d\n",
cdev->delayed_status);
}
break;
case USB_REQ_GET_INTERFACE:
if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
......@@ -958,7 +977,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
}
/* respond with data transfer before status phase? */
if (value >= 0) {
if (value >= 0 && value != USB_GADGET_DELAYED_STATUS) {
req->length = value;
req->zero = value < w_length;
value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
......@@ -967,6 +986,10 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
req->status = 0;
composite_setup_complete(gadget->ep0, req);
}
} else if (value == USB_GADGET_DELAYED_STATUS && w_length != 0) {
WARN(cdev,
"%s: Delayed status not supported for w_length != 0",
__func__);
}
done:
......@@ -1289,3 +1312,40 @@ void usb_composite_unregister(struct usb_composite_driver *driver)
return;
usb_gadget_unregister_driver(&composite_driver);
}
/**
* usb_composite_setup_continue() - Continue with the control transfer
* @cdev: the composite device who's control transfer was kept waiting
*
* This function must be called by the USB function driver to continue
* with the control transfer's data/status stage in case it had requested to
* delay the data/status stages. A USB function's setup handler (e.g. set_alt())
* can request the composite framework to delay the setup request's data/status
* stages by returning USB_GADGET_DELAYED_STATUS.
*/
void usb_composite_setup_continue(struct usb_composite_dev *cdev)
{
int value;
struct usb_request *req = cdev->req;
unsigned long flags;
DBG(cdev, "%s\n", __func__);
spin_lock_irqsave(&cdev->lock, flags);
if (cdev->delayed_status == 0) {
WARN(cdev, "%s: Unexpected call\n", __func__);
} else if (--cdev->delayed_status == 0) {
DBG(cdev, "%s: Completing delayed status\n", __func__);
req->length = 0;
value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
if (value < 0) {
DBG(cdev, "ep_queue --> %d\n", value);
req->status = 0;
composite_setup_complete(cdev->gadget->ep0, req);
}
}
spin_unlock_irqrestore(&cdev->lock, flags);
}
......@@ -261,8 +261,8 @@ static int __init dbgp_configure_endpoints(struct usb_gadget *gadget)
o_desc.wMaxPacketSize =
__constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
dbg_desc.bDebugInEndpoint = i_desc.bEndpointAddress & 0x7f;
dbg_desc.bDebugOutEndpoint = o_desc.bEndpointAddress & 0x7f;
dbg_desc.bDebugInEndpoint = i_desc.bEndpointAddress;
dbg_desc.bDebugOutEndpoint = o_desc.bEndpointAddress;
#ifdef CONFIG_USB_G_DBGP_SERIAL
dbgp.serial->in = dbgp.i_ep;
......@@ -312,6 +312,7 @@ static int __init dbgp_bind(struct usb_gadget *gadget)
dbgp.req->length = DBGP_REQ_EP0_LEN;
gadget->ep0->driver_data = gadget;
device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
#ifdef CONFIG_USB_G_DBGP_SERIAL
dbgp.serial = kzalloc(sizeof(struct gserial), GFP_KERNEL);
......@@ -350,9 +351,9 @@ static int dbgp_setup(struct usb_gadget *gadget,
u8 request = ctrl->bRequest;
u16 value = le16_to_cpu(ctrl->wValue);
u16 length = le16_to_cpu(ctrl->wLength);
int err = 0;
void *data;
u16 len;
int err = -EOPNOTSUPP;
void *data = NULL;
u16 len = 0;
gadget->ep0->driver_data = gadget;
......@@ -371,10 +372,9 @@ static int dbgp_setup(struct usb_gadget *gadget,
default:
goto fail;
}
err = 0;
} else if (request == USB_REQ_SET_FEATURE &&
value == USB_DEVICE_DEBUG_MODE) {
len = 0;
data = NULL;
dev_dbg(&dbgp.gadget->dev, "setup: feat debug\n");
#ifdef CONFIG_USB_G_DBGP_PRINTK
err = dbgp_enable_ep();
......
......@@ -892,10 +892,11 @@ static int dummy_udc_probe (struct platform_device *pdev)
return rc;
}
platform_set_drvdata (pdev, dum);
rc = device_create_file (&dum->gadget.dev, &dev_attr_function);
if (rc < 0)
device_unregister (&dum->gadget.dev);
else
platform_set_drvdata(pdev, dum);
return rc;
}
......@@ -1995,11 +1996,29 @@ static int __init init (void)
retval = platform_device_add(the_hcd_pdev);
if (retval < 0)
goto err_add_hcd;
if (!the_controller) {
/*
* The hcd was added successfully but its probe function failed
* for some reason.
*/
retval = -EINVAL;
goto err_add_udc;
}
retval = platform_device_add(the_udc_pdev);
if (retval < 0)
goto err_add_udc;
if (!platform_get_drvdata(the_udc_pdev)) {
/*
* The udc was added successfully but its probe function failed
* for some reason.
*/
retval = -EINVAL;
goto err_probe_udc;
}
return retval;
err_probe_udc:
platform_device_del(the_udc_pdev);
err_add_udc:
platform_device_del(the_hcd_pdev);
err_add_hcd:
......
......@@ -177,7 +177,7 @@ static struct uac_format_type_i_discrete_descriptor_1 as_type_i_desc = {
};
/* Standard ISO OUT Endpoint Descriptor */
static struct usb_endpoint_descriptor as_out_ep_desc __initdata = {
static struct usb_endpoint_descriptor as_out_ep_desc = {
.bLength = USB_DT_ENDPOINT_AUDIO_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_OUT,
......
......@@ -347,6 +347,7 @@ struct fsg_operations {
/* Data shared by all the FSG instances. */
struct fsg_common {
struct usb_gadget *gadget;
struct usb_composite_dev *cdev;
struct fsg_dev *fsg, *new_fsg;
wait_queue_head_t fsg_wait;
......@@ -613,6 +614,11 @@ static int fsg_setup(struct usb_function *f,
if (!fsg_is_set(fsg->common))
return -EOPNOTSUPP;
++fsg->common->ep0_req_tag; /* Record arrival of a new request */
req->context = NULL;
req->length = 0;
dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl));
switch (ctrl->bRequest) {
case USB_BULK_RESET_REQUEST:
......@@ -1584,37 +1590,6 @@ static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
return rc;
}
static int pad_with_zeros(struct fsg_dev *fsg)
{
struct fsg_buffhd *bh = fsg->common->next_buffhd_to_fill;
u32 nkeep = bh->inreq->length;
u32 nsend;
int rc;
bh->state = BUF_STATE_EMPTY; /* For the first iteration */
fsg->common->usb_amount_left = nkeep + fsg->common->residue;
while (fsg->common->usb_amount_left > 0) {
/* Wait for the next buffer to be free */
while (bh->state != BUF_STATE_EMPTY) {
rc = sleep_thread(fsg->common);
if (rc)
return rc;
}
nsend = min(fsg->common->usb_amount_left, FSG_BUFLEN);
memset(bh->buf + nkeep, 0, nsend - nkeep);
bh->inreq->length = nsend;
bh->inreq->zero = 0;
start_transfer(fsg, fsg->bulk_in, bh->inreq,
&bh->inreq_busy, &bh->state);
bh = fsg->common->next_buffhd_to_fill = bh->next;
fsg->common->usb_amount_left -= nsend;
nkeep = 0;
}
return 0;
}
static int throw_away_data(struct fsg_common *common)
{
struct fsg_buffhd *bh;
......@@ -1702,6 +1677,10 @@ static int finish_reply(struct fsg_common *common)
if (common->data_size == 0) {
/* Nothing to send */
/* Don't know what to do if common->fsg is NULL */
} else if (!fsg_is_set(common)) {
rc = -EIO;
/* If there's no residue, simply send the last buffer */
} else if (common->residue == 0) {
bh->inreq->zero = 0;
......@@ -1710,24 +1689,19 @@ static int finish_reply(struct fsg_common *common)
common->next_buffhd_to_fill = bh->next;
/*
* For Bulk-only, if we're allowed to stall then send the
* short packet and halt the bulk-in endpoint. If we can't
* stall, pad out the remaining data with 0's.
* For Bulk-only, mark the end of the data with a short
* packet. If we are allowed to stall, halt the bulk-in
* endpoint. (Note: This violates the Bulk-Only Transport
* specification, which requires us to pad the data if we
* don't halt the endpoint. Presumably nobody will mind.)
*/
} else if (common->can_stall) {
} else {
bh->inreq->zero = 1;
if (!start_in_transfer(common, bh))
/* Don't know what to do if
* common->fsg is NULL */
rc = -EIO;
common->next_buffhd_to_fill = bh->next;
if (common->fsg)
if (common->can_stall)
rc = halt_bulk_in_endpoint(common->fsg);
} else if (fsg_is_set(common)) {
rc = pad_with_zeros(common->fsg);
} else {
/* Don't know what to do if common->fsg is NULL */
rc = -EIO;
}
break;
......@@ -1910,7 +1884,7 @@ static int check_command(struct fsg_common *common, int cmnd_size,
common->lun, lun);
/* Check the LUN */
if (common->lun >= 0 && common->lun < common->nluns) {
if (common->lun < common->nluns) {
curlun = &common->luns[common->lun];
common->curlun = curlun;
if (common->cmnd[0] != REQUEST_SENSE) {
......@@ -2468,7 +2442,7 @@ static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
struct fsg_dev *fsg = fsg_from_func(f);
fsg->common->new_fsg = fsg;
raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
return 0;
return USB_GADGET_DELAYED_STATUS;
}
static void fsg_disable(struct usb_function *f)
......@@ -2604,6 +2578,8 @@ static void handle_exception(struct fsg_common *common)
case FSG_STATE_CONFIG_CHANGE:
do_set_interface(common, common->new_fsg);
if (common->new_fsg)
usb_composite_setup_continue(common->cdev);
break;
case FSG_STATE_EXIT:
......@@ -2774,6 +2750,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
common->gadget = gadget;
common->ep0 = gadget->ep0;
common->ep0req = cdev->req;
common->cdev = cdev;
/* Maybe allocate device-global string IDs, and patch descriptors */
if (fsg_strings[FSG_STRING_INTERFACE].id == 0) {
......@@ -2800,6 +2777,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common,
for (i = 0, lcfg = cfg->luns; i < nluns; ++i, ++curlun, ++lcfg) {
curlun->cdrom = !!lcfg->cdrom;
curlun->ro = lcfg->cdrom || lcfg->ro;
curlun->initially_ro = curlun->ro;
curlun->removable = lcfg->removable;
curlun->dev.release = fsg_lun_release;
curlun->dev.parent = &gadget->dev;
......
......@@ -420,8 +420,7 @@ rndis_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
*/
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
| USB_CDC_SEND_ENCAPSULATED_COMMAND:
if (w_length > req->length || w_value
|| w_index != rndis->ctrl_id)
if (w_value || w_index != rndis->ctrl_id)
goto invalid;
/* read the request; process it later */
value = w_length;
......
......@@ -1947,37 +1947,6 @@ static int wedge_bulk_in_endpoint(struct fsg_dev *fsg)
return rc;
}
static int pad_with_zeros(struct fsg_dev *fsg)
{
struct fsg_buffhd *bh = fsg->next_buffhd_to_fill;
u32 nkeep = bh->inreq->length;
u32 nsend;
int rc;
bh->state = BUF_STATE_EMPTY; // For the first iteration
fsg->usb_amount_left = nkeep + fsg->residue;
while (fsg->usb_amount_left > 0) {
/* Wait for the next buffer to be free */
while (bh->state != BUF_STATE_EMPTY) {
rc = sleep_thread(fsg);
if (rc)
return rc;
}
nsend = min(fsg->usb_amount_left, (u32) mod_data.buflen);
memset(bh->buf + nkeep, 0, nsend - nkeep);
bh->inreq->length = nsend;
bh->inreq->zero = 0;
start_transfer(fsg, fsg->bulk_in, bh->inreq,
&bh->inreq_busy, &bh->state);
bh = fsg->next_buffhd_to_fill = bh->next;
fsg->usb_amount_left -= nsend;
nkeep = 0;
}
return 0;
}
static int throw_away_data(struct fsg_dev *fsg)
{
struct fsg_buffhd *bh;
......@@ -2082,18 +2051,20 @@ static int finish_reply(struct fsg_dev *fsg)
}
}
/* For Bulk-only, if we're allowed to stall then send the
* short packet and halt the bulk-in endpoint. If we can't
* stall, pad out the remaining data with 0's. */
/*
* For Bulk-only, mark the end of the data with a short
* packet. If we are allowed to stall, halt the bulk-in
* endpoint. (Note: This violates the Bulk-Only Transport
* specification, which requires us to pad the data if we
* don't halt the endpoint. Presumably nobody will mind.)
*/
else {
if (mod_data.can_stall) {
bh->inreq->zero = 1;
start_transfer(fsg, fsg->bulk_in, bh->inreq,
&bh->inreq_busy, &bh->state);
fsg->next_buffhd_to_fill = bh->next;
bh->inreq->zero = 1;
start_transfer(fsg, fsg->bulk_in, bh->inreq,
&bh->inreq_busy, &bh->state);
fsg->next_buffhd_to_fill = bh->next;
if (mod_data.can_stall)
rc = halt_bulk_in_endpoint(fsg);
} else
rc = pad_with_zeros(fsg);
}
break;
......@@ -2314,7 +2285,7 @@ static int check_command(struct fsg_dev *fsg, int cmnd_size,
fsg->lun = lun; // Use LUN from the command
/* Check the LUN */
if (fsg->lun >= 0 && fsg->lun < fsg->nluns) {
if (fsg->lun < fsg->nluns) {
fsg->curlun = curlun = &fsg->luns[fsg->lun];
if (fsg->cmnd[0] != REQUEST_SENSE) {
curlun->sense_data = SS_NO_SENSE;
......
......@@ -207,7 +207,7 @@ struct qe_frame{
/* Frame status field */
/* Receive side */
#define FRAME_OK 0x00000000 /* Frame tranmitted or received OK */
#define FRAME_OK 0x00000000 /* Frame transmitted or received OK */
#define FRAME_ERROR 0x80000000 /* Error occurred on frame */
#define START_FRAME_LOST 0x40000000 /* START_FRAME_LOST */
#define END_FRAME_LOST 0x20000000 /* END_FRAME_LOST */
......
此差异已折叠。
......@@ -275,7 +275,9 @@ struct usb_sys_interface {
#define USB_MODE_CTRL_MODE_IDLE 0x00000000
#define USB_MODE_CTRL_MODE_DEVICE 0x00000002
#define USB_MODE_CTRL_MODE_HOST 0x00000003
#define USB_MODE_CTRL_MODE_MASK 0x00000003
#define USB_MODE_CTRL_MODE_RSV 0x00000001
#define USB_MODE_ES 0x00000004 /* Endian Select */
#define USB_MODE_SETUP_LOCK_OFF 0x00000008
#define USB_MODE_STREAM_DISABLE 0x00000010
/* Endpoint Flush Register */
......@@ -461,6 +463,7 @@ struct fsl_ep {
struct fsl_udc {
struct usb_gadget gadget;
struct usb_gadget_driver *driver;
struct fsl_usb2_platform_data *pdata;
struct completion *done; /* to make sure release() is done */
struct fsl_ep *eps;
unsigned int max_ep;
......@@ -473,6 +476,8 @@ struct fsl_udc {
unsigned vbus_active:1;
unsigned stopped:1;
unsigned remote_wakeup:1;
unsigned already_stopped:1;
unsigned big_endian_desc:1;
struct ep_queue_head *ep_qh; /* Endpoints Queue-Head */
struct fsl_req *status_req; /* ep0 status request */
......@@ -483,6 +488,7 @@ struct fsl_udc {
dma_addr_t ep_qh_dma; /* dma address of QH */
u32 max_pipes; /* Device max pipes */
u32 bus_reset; /* Device is bus resetting */
u32 resume_state; /* USB state to resume */
u32 usb_state; /* USB current state */
u32 ep0_state; /* Endpoint zero state */
......
......@@ -136,6 +136,12 @@
#define gadget_is_s3c_hsotg(g) 0
#endif
#ifdef CONFIG_USB_S3C_HSUDC
#define gadget_is_s3c_hsudc(g) (!strcmp("s3c-hsudc", (g)->name))
#else
#define gadget_is_s3c_hsudc(g) 0
#endif
#ifdef CONFIG_USB_GADGET_EG20T
#define gadget_is_pch(g) (!strcmp("pch_udc", (g)->name))
#else
......@@ -148,6 +154,12 @@
#define gadget_is_ci13xxx_msm(g) 0
#endif
#ifdef CONFIG_USB_GADGET_RENESAS_USBHS
#define gadget_is_renesas_usbhs(g) (!strcmp("renesas_usbhs_udc", (g)->name))
#else
#define gadget_is_renesas_usbhs(g) 0
#endif
/**
* usb_gadget_controller_number - support bcdDevice id convention
* @gadget: the controller being driven
......@@ -207,6 +219,11 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
return 0x27;
else if (gadget_is_ci13xxx_msm(gadget))
return 0x28;
else if (gadget_is_renesas_usbhs(gadget))
return 0x29;
else if (gadget_is_s3c_hsudc(gadget))
return 0x30;
return -ENOENT;
}
......
......@@ -1189,6 +1189,8 @@ printer_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
else if (gadget->a_alt_hnp_support)
DBG(dev, "HNP needs a different root port\n");
value = printer_set_config(dev, wValue);
if (!value)
value = set_interface(dev, PRINTER_INTERFACE);
break;
case USB_REQ_GET_CONFIGURATION:
if (ctrl->bRequestType != USB_DIR_IN)
......
/* linux/drivers/usb/gadget/s3c-hsotg.c
*
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
* Copyright 2008 Openmoko, Inc.
* Copyright 2008 Simtec Electronics
......@@ -613,11 +616,10 @@ static unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep)
maxpkt = S3C_DxEPTSIZ_PktCnt_LIMIT + 1;
} else {
maxsize = 64+64;
if (hs_ep->dir_in) {
if (hs_ep->dir_in)
maxpkt = S3C_DIEPTSIZ0_PktCnt_LIMIT + 1;
} else {
else
maxpkt = 2;
}
}
/* we made the constant loading easier above by using +1 */
......@@ -679,6 +681,14 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
__func__, readl(hsotg->regs + epctrl_reg), index,
hs_ep->dir_in ? "in" : "out");
/* If endpoint is stalled, we will restart request later */
ctrl = readl(hsotg->regs + epctrl_reg);
if (ctrl & S3C_DxEPCTL_Stall) {
dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index);
return;
}
length = ureq->length - ureq->actual;
if (0)
......@@ -731,18 +741,6 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
/* write size / packets */
writel(epsize, hsotg->regs + epsize_reg);
ctrl = readl(hsotg->regs + epctrl_reg);
if (ctrl & S3C_DxEPCTL_Stall) {
dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index);
/* not sure what we can do here, if it is EP0 then we should
* get this cleared once the endpoint has transmitted the
* STALL packet, otherwise it needs to be cleared by the
* host.
*/
}
if (using_dma(hsotg)) {
unsigned int dma_reg;
......@@ -1047,6 +1045,20 @@ static int s3c_hsotg_process_req_status(struct s3c_hsotg *hsotg,
static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value);
/**
* get_ep_head - return the first request on the endpoint
* @hs_ep: The controller endpoint to get
*
* Get the first request on the endpoint.
*/
static struct s3c_hsotg_req *get_ep_head(struct s3c_hsotg_ep *hs_ep)
{
if (list_empty(&hs_ep->queue))
return NULL;
return list_first_entry(&hs_ep->queue, struct s3c_hsotg_req, queue);
}
/**
* s3c_hsotg_process_req_featire - process request {SET,CLEAR}_FEATURE
* @hsotg: The device state
......@@ -1055,8 +1067,12 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value);
static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg,
struct usb_ctrlrequest *ctrl)
{
struct s3c_hsotg_ep *ep0 = &hsotg->eps[0];
struct s3c_hsotg_req *hs_req;
bool restart;
bool set = (ctrl->bRequest == USB_REQ_SET_FEATURE);
struct s3c_hsotg_ep *ep;
int ret;
dev_dbg(hsotg->dev, "%s: %s_FEATURE\n",
__func__, set ? "SET" : "CLEAR");
......@@ -1072,6 +1088,36 @@ static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg,
switch (le16_to_cpu(ctrl->wValue)) {
case USB_ENDPOINT_HALT:
s3c_hsotg_ep_sethalt(&ep->ep, set);
ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0);
if (ret) {
dev_err(hsotg->dev,
"%s: failed to send reply\n", __func__);
return ret;
}
if (!set) {
/*
* If we have request in progress,
* then complete it
*/
if (ep->req) {
hs_req = ep->req;
ep->req = NULL;
list_del_init(&hs_req->queue);
hs_req->req.complete(&ep->ep,
&hs_req->req);
}
/* If we have pending request, then start it */
restart = !list_empty(&ep->queue);
if (restart) {
hs_req = get_ep_head(ep);
s3c_hsotg_start_req(hsotg, ep,
hs_req, false);
}
}
break;
default:
......@@ -1148,14 +1194,6 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret);
}
if (ret > 0) {
if (!ep0->dir_in) {
/* need to generate zlp in reply or take data */
/* todo - deal with any data we might be sent? */
ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0);
}
}
/* the request is either unhandlable, or is not formatted correctly
* so respond with a STALL for the status stage to indicate failure.
*/
......@@ -1246,20 +1284,6 @@ static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg)
}
}
/**
* get_ep_head - return the first request on the endpoint
* @hs_ep: The controller endpoint to get
*
* Get the first request on the endpoint.
*/
static struct s3c_hsotg_req *get_ep_head(struct s3c_hsotg_ep *hs_ep)
{
if (list_empty(&hs_ep->queue))
return NULL;
return list_first_entry(&hs_ep->queue, struct s3c_hsotg_req, queue);
}
/**
* s3c_hsotg_complete_request - complete a request given to us
* @hsotg: The device state.
......@@ -1683,6 +1707,37 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg,
dev_err(hsotg->dev, "ep%d: bad mps of %d\n", ep, mps);
}
/**
* s3c_hsotg_txfifo_flush - flush Tx FIFO
* @hsotg: The driver state
* @idx: The index for the endpoint (0..15)
*/
static void s3c_hsotg_txfifo_flush(struct s3c_hsotg *hsotg, unsigned int idx)
{
int timeout;
int val;
writel(S3C_GRSTCTL_TxFNum(idx) | S3C_GRSTCTL_TxFFlsh,
hsotg->regs + S3C_GRSTCTL);
/* wait until the fifo is flushed */
timeout = 100;
while (1) {
val = readl(hsotg->regs + S3C_GRSTCTL);
if ((val & (S3C_GRSTCTL_TxFFlsh)) == 0)
break;
if (--timeout == 0) {
dev_err(hsotg->dev,
"%s: timeout flushing fifo (GRSTCTL=%08x)\n",
__func__, val);
}
udelay(1);
}
}
/**
* s3c_hsotg_trytx - check to see if anything needs transmitting
......@@ -1775,10 +1830,12 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
u32 epctl_reg = dir_in ? S3C_DIEPCTL(idx) : S3C_DOEPCTL(idx);
u32 epsiz_reg = dir_in ? S3C_DIEPTSIZ(idx) : S3C_DOEPTSIZ(idx);
u32 ints;
u32 clear = 0;
ints = readl(hsotg->regs + epint_reg);
/* Clear endpoint interrupts */
writel(ints, hsotg->regs + epint_reg);
dev_dbg(hsotg->dev, "%s: ep%d(%s) DxEPINT=0x%08x\n",
__func__, idx, dir_in ? "in" : "out", ints);
......@@ -1801,19 +1858,28 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
s3c_hsotg_handle_outdone(hsotg, idx, false);
}
clear |= S3C_DxEPINT_XferCompl;
}
if (ints & S3C_DxEPINT_EPDisbld) {
dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__);
clear |= S3C_DxEPINT_EPDisbld;
if (dir_in) {
int epctl = readl(hsotg->regs + epctl_reg);
s3c_hsotg_txfifo_flush(hsotg, idx);
if ((epctl & S3C_DxEPCTL_Stall) &&
(epctl & S3C_DxEPCTL_EPType_Bulk)) {
int dctl = readl(hsotg->regs + S3C_DCTL);
dctl |= S3C_DCTL_CGNPInNAK;
writel(dctl, hsotg->regs + S3C_DCTL);
}
}
}
if (ints & S3C_DxEPINT_AHBErr) {
if (ints & S3C_DxEPINT_AHBErr)
dev_dbg(hsotg->dev, "%s: AHBErr\n", __func__);
clear |= S3C_DxEPINT_AHBErr;
}
if (ints & S3C_DxEPINT_Setup) { /* Setup or Timeout */
dev_dbg(hsotg->dev, "%s: Setup/Timeout\n", __func__);
......@@ -1829,14 +1895,10 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
else
s3c_hsotg_handle_outdone(hsotg, 0, true);
}
clear |= S3C_DxEPINT_Setup;
}
if (ints & S3C_DxEPINT_Back2BackSetup) {
if (ints & S3C_DxEPINT_Back2BackSetup)
dev_dbg(hsotg->dev, "%s: B2BSetup/INEPNakEff\n", __func__);
clear |= S3C_DxEPINT_Back2BackSetup;
}
if (dir_in) {
/* not sure if this is important, but we'll clear it anyway
......@@ -1844,14 +1906,12 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
if (ints & S3C_DIEPMSK_INTknTXFEmpMsk) {
dev_dbg(hsotg->dev, "%s: ep%d: INTknTXFEmpMsk\n",
__func__, idx);
clear |= S3C_DIEPMSK_INTknTXFEmpMsk;
}
/* this probably means something bad is happening */
if (ints & S3C_DIEPMSK_INTknEPMisMsk) {
dev_warn(hsotg->dev, "%s: ep%d: INTknEP\n",
__func__, idx);
clear |= S3C_DIEPMSK_INTknEPMisMsk;
}
/* FIFO has space or is empty (see GAHBCFG) */
......@@ -1860,11 +1920,8 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
dev_dbg(hsotg->dev, "%s: ep%d: TxFIFOEmpty\n",
__func__, idx);
s3c_hsotg_trytx(hsotg, hs_ep);
clear |= S3C_DIEPMSK_TxFIFOEmpty;
}
}
writel(clear, hsotg->regs + epint_reg);
}
/**
......@@ -2056,7 +2113,6 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
dev_info(hsotg->dev, "OTGInt: %08x\n", otgint);
writel(otgint, hsotg->regs + S3C_GOTGINT);
writel(S3C_GINTSTS_OTGInt, hsotg->regs + S3C_GINTSTS);
}
if (gintsts & S3C_GINTSTS_DisconnInt) {
......@@ -2072,8 +2128,9 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
}
if (gintsts & S3C_GINTSTS_EnumDone) {
s3c_hsotg_irq_enumdone(hsotg);
writel(S3C_GINTSTS_EnumDone, hsotg->regs + S3C_GINTSTS);
s3c_hsotg_irq_enumdone(hsotg);
}
if (gintsts & S3C_GINTSTS_ConIDStsChng) {
......@@ -2101,10 +2158,6 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
if (daint_in & 1)
s3c_hsotg_epint(hsotg, ep, 1);
}
writel(daint, hsotg->regs + S3C_DAINT);
writel(gintsts & (S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt),
hsotg->regs + S3C_GINTSTS);
}
if (gintsts & S3C_GINTSTS_USBRst) {
......@@ -2112,6 +2165,8 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
readl(hsotg->regs + S3C_GNPTXSTS));
writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS);
kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true);
/* it seems after a reset we can end up with a situation
......@@ -2123,8 +2178,6 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
s3c_hsotg_init_fifo(hsotg);
s3c_hsotg_enqueue_setup(hsotg);
writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS);
}
/* check both FIFOs */
......@@ -2138,8 +2191,6 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_NPTxFEmp);
s3c_hsotg_irq_fifoempty(hsotg, false);
writel(S3C_GINTSTS_NPTxFEmp, hsotg->regs + S3C_GINTSTS);
}
if (gintsts & S3C_GINTSTS_PTxFEmp) {
......@@ -2149,8 +2200,6 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_PTxFEmp);
s3c_hsotg_irq_fifoempty(hsotg, true);
writel(S3C_GINTSTS_PTxFEmp, hsotg->regs + S3C_GINTSTS);
}
if (gintsts & S3C_GINTSTS_RxFLvl) {
......@@ -2159,7 +2208,6 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
* set. */
s3c_hsotg_handle_rx(hsotg);
writel(S3C_GINTSTS_RxFLvl, hsotg->regs + S3C_GINTSTS);
}
if (gintsts & S3C_GINTSTS_ModeMis) {
......@@ -2193,19 +2241,17 @@ static irqreturn_t s3c_hsotg_irq(int irq, void *pw)
if (gintsts & S3C_GINTSTS_GOUTNakEff) {
dev_info(hsotg->dev, "GOUTNakEff triggered\n");
s3c_hsotg_dump(hsotg);
writel(S3C_DCTL_CGOUTNak, hsotg->regs + S3C_DCTL);
writel(S3C_GINTSTS_GOUTNakEff, hsotg->regs + S3C_GINTSTS);
s3c_hsotg_dump(hsotg);
}
if (gintsts & S3C_GINTSTS_GINNakEff) {
dev_info(hsotg->dev, "GINNakEff triggered\n");
s3c_hsotg_dump(hsotg);
writel(S3C_DCTL_CGNPInNAK, hsotg->regs + S3C_DCTL);
writel(S3C_GINTSTS_GINNakEff, hsotg->regs + S3C_GINTSTS);
s3c_hsotg_dump(hsotg);
}
/* if we've had fifo events, we should try and go around the
......@@ -2403,11 +2449,6 @@ static int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
dev_info(hs->dev, "ep_dequeue(%p,%p)\n", ep, req);
if (hs_req == hs_ep->req) {
dev_dbg(hs->dev, "%s: already in progress\n", __func__);
return -EINPROGRESS;
}
spin_lock_irqsave(&hs_ep->lock, flags);
if (!on_list(hs_ep, hs_req)) {
......@@ -2429,6 +2470,7 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
unsigned long irqflags;
u32 epreg;
u32 epctl;
u32 xfertype;
dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value);
......@@ -2439,10 +2481,17 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
epreg = S3C_DIEPCTL(index);
epctl = readl(hs->regs + epreg);
if (value)
epctl |= S3C_DxEPCTL_Stall;
else
if (value) {
epctl |= S3C_DxEPCTL_Stall + S3C_DxEPCTL_SNAK;
if (epctl & S3C_DxEPCTL_EPEna)
epctl |= S3C_DxEPCTL_EPDis;
} else {
epctl &= ~S3C_DxEPCTL_Stall;
xfertype = epctl & S3C_DxEPCTL_EPType_MASK;
if (xfertype == S3C_DxEPCTL_EPType_Bulk ||
xfertype == S3C_DxEPCTL_EPType_Intterupt)
epctl |= S3C_DxEPCTL_SetD0PID;
}
writel(epctl, hs->regs + epreg);
......@@ -2451,8 +2500,13 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)
if (value)
epctl |= S3C_DxEPCTL_Stall;
else
else {
epctl &= ~S3C_DxEPCTL_Stall;
xfertype = epctl & S3C_DxEPCTL_EPType_MASK;
if (xfertype == S3C_DxEPCTL_EPType_Bulk ||
xfertype == S3C_DxEPCTL_EPType_Intterupt)
epctl |= S3C_DxEPCTL_SetD0PID;
}
writel(epctl, hs->regs + epreg);
......@@ -2491,9 +2545,9 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg)
timeout = 1000;
do {
grstctl = readl(hsotg->regs + S3C_GRSTCTL);
} while (!(grstctl & S3C_GRSTCTL_CSftRst) && timeout-- > 0);
} while ((grstctl & S3C_GRSTCTL_CSftRst) && timeout-- > 0);
if (!(grstctl & S3C_GRSTCTL_CSftRst)) {
if (grstctl & S3C_GRSTCTL_CSftRst) {
dev_err(hsotg->dev, "Failed to get CSftRst asserted\n");
return -EINVAL;
}
......@@ -2510,13 +2564,10 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg)
return -ETIMEDOUT;
}
if (grstctl & S3C_GRSTCTL_CSftRst)
continue;
if (!(grstctl & S3C_GRSTCTL_AHBIdle))
continue;
break; /* reset done */
break; /* reset done */
}
dev_dbg(hsotg->dev, "reset successful\n");
......@@ -2588,6 +2639,12 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
writel(1 << 18 | S3C_DCFG_DevSpd_HS, hsotg->regs + S3C_DCFG);
/* Clear any pending OTG interrupts */
writel(0xffffffff, hsotg->regs + S3C_GOTGINT);
/* Clear any pending interrupts */
writel(0xffffffff, hsotg->regs + S3C_GINTSTS);
writel(S3C_GINTSTS_DisconnInt | S3C_GINTSTS_SessReqInt |
S3C_GINTSTS_ConIDStsChng | S3C_GINTSTS_USBRst |
S3C_GINTSTS_EnumDone | S3C_GINTSTS_OTGInt |
......@@ -3261,7 +3318,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
hsotg->clk = clk_get(&pdev->dev, "otg");
if (IS_ERR(hsotg->clk)) {
dev_err(dev, "cannot get otg clock\n");
ret = -EINVAL;
ret = PTR_ERR(hsotg->clk);
goto err_mem;
}
......
此差异已折叠。
......@@ -708,13 +708,14 @@ static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr,
static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
ssize_t rc = count;
ssize_t rc;
struct fsg_lun *curlun = fsg_lun_from_dev(dev);
struct rw_semaphore *filesem = dev_get_drvdata(dev);
unsigned long ro;
unsigned ro;
if (strict_strtoul(buf, 2, &ro))
return -EINVAL;
rc = kstrtouint(buf, 2, &ro);
if (rc)
return rc;
/*
* Allow the write-enable status to change only while the
......@@ -728,6 +729,7 @@ static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr,
curlun->ro = ro;
curlun->initially_ro = ro;
LDBG(curlun, "read-only status set to %d\n", curlun->ro);
rc = count;
}
up_read(filesem);
return rc;
......@@ -738,10 +740,12 @@ static ssize_t fsg_store_nofua(struct device *dev,
const char *buf, size_t count)
{
struct fsg_lun *curlun = fsg_lun_from_dev(dev);
unsigned long nofua;
unsigned nofua;
int ret;
if (strict_strtoul(buf, 2, &nofua))
return -EINVAL;
ret = kstrtouint(buf, 2, &nofua);
if (ret)
return ret;
/* Sync data when switching from async mode to sync */
if (!nofua && curlun->nofua)
......
......@@ -106,13 +106,13 @@ config USB_EHCI_BIG_ENDIAN_MMIO
depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX || \
ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
PPC_MPC512x || CPU_CAVIUM_OCTEON || \
PMC_MSP)
PMC_MSP || SPARC_LEON)
default y
config USB_EHCI_BIG_ENDIAN_DESC
bool
depends on USB_EHCI_HCD && (440EPX || ARCH_IXP4XX || XPS_USB_HCD_XILINX || \
PPC_MPC512x || PMC_MSP)
PPC_MPC512x || PMC_MSP || SPARC_LEON)
default y
config XPS_USB_HCD_XILINX
......@@ -188,6 +188,12 @@ config USB_EHCI_SH
Enables support for the on-chip EHCI controller on the SuperH.
If you use the PCI EHCI controller, this option is not necessary.
config USB_EHCI_S5P
boolean "S5P EHCI support"
depends on USB_EHCI_HCD && PLAT_S5P
help
Enable support for the S5P SOC's on-chip EHCI controller.
config USB_W90X900_EHCI
bool "W90X900(W90P910) EHCI support"
depends on USB_EHCI_HCD && ARCH_W90X900
......@@ -202,6 +208,15 @@ config USB_CNS3XXX_EHCI
It is needed for high-speed (480Mbit/sec) USB 2.0 device
support.
config USB_EHCI_ATH79
bool "EHCI support for AR7XXX/AR9XXX SoCs"
depends on USB_EHCI_HCD && (SOC_AR71XX || SOC_AR724X || SOC_AR913X)
select USB_EHCI_ROOT_HUB_TT
default y
---help---
Enables support for the built-in EHCI controller present
on the Atheros AR7XXX/AR9XXX SoCs.
config USB_OXU210HP_HCD
tristate "OXU210HP HCD support"
depends on USB
......@@ -287,6 +302,14 @@ config USB_OHCI_HCD_OMAP3
Enables support for the on-chip OHCI controller on
OMAP3 and later chips.
config USB_OHCI_ATH79
bool "USB OHCI support for the Atheros AR71XX/AR7240 SoCs"
depends on USB_OHCI_HCD && (SOC_AR71XX || SOC_AR724X)
default y
help
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)
......@@ -373,7 +396,7 @@ config USB_OHCI_LITTLE_ENDIAN
config USB_UHCI_HCD
tristate "UHCI HCD (most Intel and VIA) support"
depends on USB && PCI
depends on USB && (PCI || SPARC_LEON)
---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
......@@ -382,11 +405,27 @@ config USB_UHCI_HCD
with Intel PCI chipsets (like intel 430TX, 440FX, 440LX, 440BX,
i810, i820) conform to this standard. Also all VIA PCI chipsets
(like VIA VP2, VP3, MVP3, Apollo Pro, Apollo Pro II or Apollo Pro
133). If unsure, say Y.
133) and LEON/GRLIB SoCs with the GRUSBHC controller.
If unsure, say Y.
To compile this driver as a module, choose M here: the
module will be called uhci-hcd.
config USB_UHCI_SUPPORT_NON_PCI_HC
bool
depends on USB_UHCI_HCD
default y if SPARC_LEON
config USB_UHCI_BIG_ENDIAN_MMIO
bool
depends on USB_UHCI_SUPPORT_NON_PCI_HC && SPARC_LEON
default y
config USB_UHCI_BIG_ENDIAN_DESC
bool
depends on USB_UHCI_SUPPORT_NON_PCI_HC && SPARC_LEON
default y
config USB_FHCI_HCD
tristate "Freescale QE USB Host Controller support"
depends on USB && OF_GPIO && QE_GPIO && QUICC_ENGINE
......@@ -444,6 +483,16 @@ config USB_SL811_HCD
To compile this driver as a module, choose M here: the
module will be called sl811-hcd.
config USB_SL811_HCD_ISO
bool "partial ISO support"
depends on USB_SL811_HCD
help
The driver doesn't support iso_frame_desc (yet), but for some simple
devices that just queue one ISO frame per URB, then ISO transfers
"should" work using the normal urb status fields.
If unsure, say N.
config USB_SL811_CS
tristate "CF/PCMCIA support for SL811HS HCD"
depends on USB_SL811_HCD && PCMCIA
......
/*
* Bus Glue for Atheros AR7XXX/AR9XXX built-in EHCI controller.
*
* Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* Parts of this file are based on Atheros' 2.6.15 BSP
* Copyright (C) 2007 Atheros Communications, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#include <linux/platform_device.h>
enum {
EHCI_ATH79_IP_V1 = 0,
EHCI_ATH79_IP_V2,
};
static const struct platform_device_id ehci_ath79_id_table[] = {
{
.name = "ar71xx-ehci",
.driver_data = EHCI_ATH79_IP_V1,
},
{
.name = "ar724x-ehci",
.driver_data = EHCI_ATH79_IP_V2,
},
{
.name = "ar913x-ehci",
.driver_data = EHCI_ATH79_IP_V2,
},
{
/* terminating entry */
},
};
MODULE_DEVICE_TABLE(platform, ehci_ath79_id_table);
static int ehci_ath79_init(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct platform_device *pdev = to_platform_device(hcd->self.controller);
const struct platform_device_id *id;
int hclength;
int ret;
id = platform_get_device_id(pdev);
if (!id) {
dev_err(hcd->self.controller, "missing device id\n");
return -EINVAL;
}
hclength = HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
switch (id->driver_data) {
case EHCI_ATH79_IP_V1:
ehci->has_synopsys_hc_bug = 1;
ehci->caps = hcd->regs;
ehci->regs = hcd->regs + hclength;
break;
case EHCI_ATH79_IP_V2:
hcd->has_tt = 1;
ehci->caps = hcd->regs + 0x100;
ehci->regs = hcd->regs + 0x100 + hclength;
break;
default:
BUG();
}
dbg_hcs_params(ehci, "reset");
dbg_hcc_params(ehci, "reset");
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
ehci->sbrn = 0x20;
ehci_reset(ehci);
ret = ehci_init(hcd);
if (ret)
return ret;
ehci_port_power(ehci, 0);
return 0;
}
static const struct hc_driver ehci_ath79_hc_driver = {
.description = hcd_name,
.product_desc = "Atheros built-in EHCI controller",
.hcd_priv_size = sizeof(struct ehci_hcd),
.irq = ehci_irq,
.flags = HCD_MEMORY | HCD_USB2,
.reset = ehci_ath79_init,
.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,
.hub_status_data = ehci_hub_status_data,
.hub_control = ehci_hub_control,
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};
static int ehci_ath79_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
struct resource *res;
int irq;
int ret;
if (usb_disabled())
return -ENODEV;
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
dev_dbg(&pdev->dev, "no IRQ specified\n");
return -ENODEV;
}
irq = res->start;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_dbg(&pdev->dev, "no base address specified\n");
return -ENODEV;
}
hcd = usb_create_hcd(&ehci_ath79_hc_driver, &pdev->dev,
dev_name(&pdev->dev));
if (!hcd)
return -ENOMEM;
hcd->rsrc_start = res->start;
hcd->rsrc_len = res->end - res->start + 1;
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
dev_dbg(&pdev->dev, "controller already in use\n");
ret = -EBUSY;
goto err_put_hcd;
}
hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
if (!hcd->regs) {
dev_dbg(&pdev->dev, "error mapping memory\n");
ret = -EFAULT;
goto err_release_region;
}
ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
if (ret)
goto err_iounmap;
return 0;
err_iounmap:
iounmap(hcd->regs);
err_release_region:
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
err_put_hcd:
usb_put_hcd(hcd);
return ret;
}
static int ehci_ath79_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);
return 0;
}
static struct platform_driver ehci_ath79_driver = {
.probe = ehci_ath79_probe,
.remove = ehci_ath79_remove,
.id_table = ehci_ath79_id_table,
.driver = {
.owner = THIS_MODULE,
.name = "ath79-ehci",
}
};
MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ath79-ehci");
......@@ -56,7 +56,7 @@ static int ehci_atmel_setup(struct usb_hcd *hcd)
/* registers start at offset 0x0 */
ehci->caps = hcd->regs;
ehci->regs = hcd->regs +
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
dbg_hcs_params(ehci, "reset");
dbg_hcc_params(ehci, "reset");
......
......@@ -175,7 +175,8 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
ehci = hcd_to_ehci(hcd);
ehci->caps = hcd->regs;
ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
ehci->regs = hcd->regs +
HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
/* cache this readonly data; minimize chip reads */
ehci->hcs_params = readl(&ehci->caps->hcs_params);
......@@ -215,10 +216,7 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
unsigned long flags;
int rc;
return 0;
rc = 0;
int rc = 0;
if (time_before(jiffies, ehci->next_statechange))
msleep(10);
......@@ -233,13 +231,13 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
(void)ehci_readl(ehci, &ehci->regs->intr_enable);
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
au1xxx_stop_ehc();
spin_unlock_irqrestore(&ehci->lock, flags);
// could save FLADJ in case of Vaux power loss
// ... we'd only use it to handle clock skew
au1xxx_stop_ehc();
return rc;
}
......
......@@ -34,7 +34,7 @@ static int cns3xxx_ehci_init(struct usb_hcd *hcd)
ehci->caps = hcd->regs;
ehci->regs = hcd->regs
+ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+ HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
hcd->has_tt = 0;
......
......@@ -726,7 +726,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
}
/* Capability Registers */
i = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
i = HC_VERSION(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
temp = scnprintf (next, size,
"bus %s, device %s\n"
"%s\n"
......
......@@ -117,6 +117,9 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
pdata->regs = hcd->regs;
if (pdata->power_budget)
hcd->power_budget = pdata->power_budget;
/*
* do platform specific init: check the clock, grab/config pins, etc.
*/
......@@ -134,6 +137,30 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
if (retval != 0)
goto err4;
#ifdef CONFIG_USB_OTG
if (pdata->operating_mode == FSL_USB2_DR_OTG) {
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
ehci->transceiver = otg_get_transceiver();
dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, transceiver=0x%p\n",
hcd, ehci, ehci->transceiver);
if (ehci->transceiver) {
retval = otg_set_host(ehci->transceiver,
&ehci_to_hcd(ehci)->self);
if (retval) {
if (ehci->transceiver)
put_device(ehci->transceiver->dev);
goto err4;
}
} else {
dev_err(&pdev->dev, "can't find transceiver\n");
retval = -ENODEV;
goto err4;
}
}
#endif
return retval;
err4:
......@@ -164,6 +191,12 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
struct platform_device *pdev)
{
struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
if (ehci->transceiver) {
otg_set_host(ehci->transceiver, NULL);
put_device(ehci->transceiver->dev);
}
usb_remove_hcd(hcd);
......@@ -291,7 +324,7 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
/* EHCI registers start at offset 0x100 */
ehci->caps = hcd->regs + 0x100;
ehci->regs = hcd->regs + 0x100 +
HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
dbg_hcs_params(ehci, "reset");
dbg_hcc_params(ehci, "reset");
......@@ -328,6 +361,149 @@ struct ehci_fsl {
#ifdef CONFIG_PM
#ifdef CONFIG_PPC_MPC512x
static int ehci_fsl_mpc512x_drv_suspend(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct fsl_usb2_platform_data *pdata = dev->platform_data;
u32 tmp;
#ifdef DEBUG
u32 mode = ehci_readl(ehci, hcd->regs + FSL_SOC_USB_USBMODE);
mode &= USBMODE_CM_MASK;
tmp = ehci_readl(ehci, hcd->regs + 0x140); /* usbcmd */
dev_dbg(dev, "suspend=%d already_suspended=%d "
"mode=%d usbcmd %08x\n", pdata->suspended,
pdata->already_suspended, mode, tmp);
#endif
/*
* If the controller is already suspended, then this must be a
* PM suspend. Remember this fact, so that we will leave the
* controller suspended at PM resume time.
*/
if (pdata->suspended) {
dev_dbg(dev, "already suspended, leaving early\n");
pdata->already_suspended = 1;
return 0;
}
dev_dbg(dev, "suspending...\n");
hcd->state = HC_STATE_SUSPENDED;
dev->power.power_state = PMSG_SUSPEND;
/* ignore non-host interrupts */
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
/* stop the controller */
tmp = ehci_readl(ehci, &ehci->regs->command);
tmp &= ~CMD_RUN;
ehci_writel(ehci, tmp, &ehci->regs->command);
/* save EHCI registers */
pdata->pm_command = ehci_readl(ehci, &ehci->regs->command);
pdata->pm_command &= ~CMD_RUN;
pdata->pm_status = ehci_readl(ehci, &ehci->regs->status);
pdata->pm_intr_enable = ehci_readl(ehci, &ehci->regs->intr_enable);
pdata->pm_frame_index = ehci_readl(ehci, &ehci->regs->frame_index);
pdata->pm_segment = ehci_readl(ehci, &ehci->regs->segment);
pdata->pm_frame_list = ehci_readl(ehci, &ehci->regs->frame_list);
pdata->pm_async_next = ehci_readl(ehci, &ehci->regs->async_next);
pdata->pm_configured_flag =
ehci_readl(ehci, &ehci->regs->configured_flag);
pdata->pm_portsc = ehci_readl(ehci, &ehci->regs->port_status[0]);
pdata->pm_usbgenctrl = ehci_readl(ehci,
hcd->regs + FSL_SOC_USB_USBGENCTRL);
/* clear the W1C bits */
pdata->pm_portsc &= cpu_to_hc32(ehci, ~PORT_RWC_BITS);
pdata->suspended = 1;
/* clear PP to cut power to the port */
tmp = ehci_readl(ehci, &ehci->regs->port_status[0]);
tmp &= ~PORT_POWER;
ehci_writel(ehci, tmp, &ehci->regs->port_status[0]);
return 0;
}
static int ehci_fsl_mpc512x_drv_resume(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct fsl_usb2_platform_data *pdata = dev->platform_data;
u32 tmp;
dev_dbg(dev, "suspend=%d already_suspended=%d\n",
pdata->suspended, pdata->already_suspended);
/*
* If the controller was already suspended at suspend time,
* then don't resume it now.
*/
if (pdata->already_suspended) {
dev_dbg(dev, "already suspended, leaving early\n");
pdata->already_suspended = 0;
return 0;
}
if (!pdata->suspended) {
dev_dbg(dev, "not suspended, leaving early\n");
return 0;
}
pdata->suspended = 0;
dev_dbg(dev, "resuming...\n");
/* set host mode */
tmp = USBMODE_CM_HOST | (pdata->es ? USBMODE_ES : 0);
ehci_writel(ehci, tmp, hcd->regs + FSL_SOC_USB_USBMODE);
ehci_writel(ehci, pdata->pm_usbgenctrl,
hcd->regs + FSL_SOC_USB_USBGENCTRL);
ehci_writel(ehci, ISIPHYCTRL_PXE | ISIPHYCTRL_PHYE,
hcd->regs + FSL_SOC_USB_ISIPHYCTRL);
/* restore EHCI registers */
ehci_writel(ehci, pdata->pm_command, &ehci->regs->command);
ehci_writel(ehci, pdata->pm_intr_enable, &ehci->regs->intr_enable);
ehci_writel(ehci, pdata->pm_frame_index, &ehci->regs->frame_index);
ehci_writel(ehci, pdata->pm_segment, &ehci->regs->segment);
ehci_writel(ehci, pdata->pm_frame_list, &ehci->regs->frame_list);
ehci_writel(ehci, pdata->pm_async_next, &ehci->regs->async_next);
ehci_writel(ehci, pdata->pm_configured_flag,
&ehci->regs->configured_flag);
ehci_writel(ehci, pdata->pm_portsc, &ehci->regs->port_status[0]);
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
hcd->state = HC_STATE_RUNNING;
dev->power.power_state = PMSG_ON;
tmp = ehci_readl(ehci, &ehci->regs->command);
tmp |= CMD_RUN;
ehci_writel(ehci, tmp, &ehci->regs->command);
usb_hcd_resume_root_hub(hcd);
return 0;
}
#else
static inline int ehci_fsl_mpc512x_drv_suspend(struct device *dev)
{
return 0;
}
static inline int ehci_fsl_mpc512x_drv_resume(struct device *dev)
{
return 0;
}
#endif /* CONFIG_PPC_MPC512x */
static struct ehci_fsl *hcd_to_ehci_fsl(struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
......@@ -341,6 +517,11 @@ static int ehci_fsl_drv_suspend(struct device *dev)
struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
void __iomem *non_ehci = hcd->regs;
if (of_device_is_compatible(dev->parent->of_node,
"fsl,mpc5121-usb2-dr")) {
return ehci_fsl_mpc512x_drv_suspend(dev);
}
ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd),
device_may_wakeup(dev));
if (!fsl_deep_sleep())
......@@ -357,6 +538,11 @@ static int ehci_fsl_drv_resume(struct device *dev)
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
void __iomem *non_ehci = hcd->regs;
if (of_device_is_compatible(dev->parent->of_node,
"fsl,mpc5121-usb2-dr")) {
return ehci_fsl_mpc512x_drv_resume(dev);
}
ehci_prepare_ports_for_controller_resume(ehci);
if (!fsl_deep_sleep())
return 0;
......@@ -391,6 +577,38 @@ static struct dev_pm_ops ehci_fsl_pm_ops = {
#define EHCI_FSL_PM_OPS NULL
#endif /* CONFIG_PM */
#ifdef CONFIG_USB_OTG
static int ehci_start_port_reset(struct usb_hcd *hcd, unsigned port)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
u32 status;
if (!port)
return -EINVAL;
port--;
/* start port reset before HNP protocol time out */
status = readl(&ehci->regs->port_status[port]);
if (!(status & PORT_CONNECT))
return -ENODEV;
/* khubd will finish the reset later */
if (ehci_is_TDI(ehci)) {
writel(PORT_RESET |
(status & ~(PORT_CSC | PORT_PEC | PORT_OCC)),
&ehci->regs->port_status[port]);
} else {
writel(PORT_RESET, &ehci->regs->port_status[port]);
}
return 0;
}
#else
#define ehci_start_port_reset NULL
#endif /* CONFIG_USB_OTG */
static const struct hc_driver ehci_fsl_hc_driver = {
.description = hcd_name,
.product_desc = "Freescale On-Chip EHCI Host Controller",
......@@ -430,6 +648,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
.hub_control = ehci_hub_control,
.bus_suspend = ehci_bus_suspend,
.bus_resume = ehci_bus_resume,
.start_port_reset = ehci_start_port_reset,
.relinquish_port = ehci_relinquish_port,
.port_handed_over = ehci_port_handed_over,
......
......@@ -27,6 +27,10 @@
#define PORT_PTS_SERIAL (3<<30)
#define PORT_PTS_PTW (1<<28)
#define FSL_SOC_USB_PORTSC2 0x188
#define FSL_SOC_USB_USBMODE 0x1a8
#define USBMODE_CM_MASK (3 << 0) /* controller mode mask */
#define USBMODE_CM_HOST (3 << 0) /* controller mode: host */
#define USBMODE_ES (1 << 2) /* (Big) Endian Select */
#define FSL_SOC_USB_USBGENCTRL 0x200
#define USBGENCTRL_PPP (1 << 3)
......
/*
* Driver for Aeroflex Gaisler GRLIB GRUSBHC EHCI host controller
*
* GRUSBHC is typically found on LEON/GRLIB SoCs
*
* (c) Jan Andersson <jan@gaisler.com>
*
* Based on ehci-ppc-of.c which is:
* (c) Valentine Barshak <vbarshak@ru.mvista.com>
* and in turn based on "ehci-ppc-soc.c" by Stefan Roese <sr@denx.de>
* and "ohci-ppc-of.c" by Sylvain Munaut <tnt@246tNt.com>
*
* 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
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/signal.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#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_halt(ehci);
if (retval)
return retval;
retval = ehci_init(hcd);
if (retval)
return retval;
ehci->sbrn = 0x20;
ehci_port_power(ehci, 1);
return ehci_reset(ehci);
}
static const struct hc_driver ehci_grlib_hc_driver = {
.description = hcd_name,
.product_desc = "GRLIB GRUSBHC EHCI",
.hcd_priv_size = sizeof(struct ehci_hcd),
/*
* generic hardware linkage
*/
.irq = ehci_irq,
.flags = HCD_MEMORY | HCD_USB2,
/*
* basic lifecycle operations
*/
.reset = ehci_grlib_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,
#ifdef 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 int __devinit ehci_hcd_grlib_probe(struct platform_device *op)
{
struct device_node *dn = op->dev.of_node;
struct usb_hcd *hcd;
struct ehci_hcd *ehci = NULL;
struct resource res;
u32 hc_capbase;
int irq;
int rv;
if (usb_disabled())
return -ENODEV;
dev_dbg(&op->dev, "initializing GRUSBHC EHCI USB Controller\n");
rv = of_address_to_resource(dn, 0, &res);
if (rv)
return rv;
/* usb_create_hcd requires dma_mask != NULL */
op->dev.dma_mask = &op->dev.coherent_dma_mask;
hcd = usb_create_hcd(&ehci_grlib_hc_driver, &op->dev,
"GRUSBHC EHCI USB");
if (!hcd)
return -ENOMEM;
hcd->rsrc_start = res.start;
hcd->rsrc_len = res.end - res.start + 1;
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__);
rv = -EBUSY;
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;
}
ehci = hcd_to_ehci(hcd);
ehci->caps = hcd->regs;
/* determine endianness of this implementation */
hc_capbase = ehci_readl(ehci, &ehci->caps->hc_capbase);
if (HC_VERSION(ehci, hc_capbase) != GRUSBHC_HCIVERSION) {
ehci->big_endian_mmio = 1;
ehci->big_endian_desc = 1;
ehci->big_endian_capbase = 1;
}
ehci->regs = hcd->regs +
HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
/* cache this readonly data; minimize chip reads */
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
rv = usb_add_hcd(hcd, irq, 0);
if (rv)
goto err_ehci;
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;
}
static int ehci_hcd_grlib_remove(struct platform_device *op)
{
struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
dev_set_drvdata(&op->dev, NULL);
dev_dbg(&op->dev, "stopping GRLIB GRUSBHC EHCI USB Controller\n");
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);
return 0;
}
static void ehci_hcd_grlib_shutdown(struct platform_device *op)
{
struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
if (hcd->driver->shutdown)
hcd->driver->shutdown(hcd);
}
static const struct of_device_id ehci_hcd_grlib_of_match[] = {
{
.name = "GAISLER_EHCI",
},
{
.name = "01_026",
},
{},
};
MODULE_DEVICE_TABLE(of, ehci_hcd_grlib_of_match);
static struct platform_driver ehci_grlib_driver = {
.probe = ehci_hcd_grlib_probe,
.remove = ehci_hcd_grlib_remove,
.shutdown = ehci_hcd_grlib_shutdown,
.driver = {
.name = "grlib-ehci",
.owner = THIS_MODULE,
.of_match_table = ehci_hcd_grlib_of_match,
},
};
......@@ -739,7 +739,7 @@ static int ehci_run (struct usb_hcd *hcd)
up_write(&ehci_cf_port_reset_rwsem);
ehci->last_periodic_enable = ktime_get_real();
temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
temp = HC_VERSION(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
ehci_info (ehci,
"USB %x.%x started, EHCI %x.%02x%s\n",
((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
......@@ -777,8 +777,9 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
goto dead;
}
/* Shared IRQ? */
masked_status = status & INTR_MASK;
if (!masked_status) { /* irq sharing? */
if (!masked_status || unlikely(hcd->state == HC_STATE_HALT)) {
spin_unlock(&ehci->lock);
return IRQ_NONE;
}
......@@ -873,6 +874,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
dead:
ehci_reset(ehci);
ehci_writel(ehci, 0, &ehci->regs->configured_flag);
usb_hc_died(hcd);
/* generic layer kills/unlinks all urbs, then
* uses ehci_stop to clean up the rest
*/
......@@ -1265,6 +1267,21 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER tegra_ehci_driver
#endif
#ifdef CONFIG_USB_EHCI_S5P
#include "ehci-s5p.c"
#define PLATFORM_DRIVER s5p_ehci_driver
#endif
#ifdef CONFIG_USB_EHCI_ATH79
#include "ehci-ath79.c"
#define PLATFORM_DRIVER ehci_ath79_driver
#endif
#ifdef CONFIG_SPARC_LEON
#include "ehci-grlib.c"
#define PLATFORM_DRIVER ehci_grlib_driver
#endif
#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
!defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
!defined(XILINX_OF_PLATFORM_DRIVER)
......
此差异已折叠。
......@@ -23,7 +23,7 @@ static int ixp4xx_ehci_init(struct usb_hcd *hcd)
ehci->caps = hcd->regs + 0x100;
ehci->regs = hcd->regs + 0x100
+ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+ HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
hcd->has_tt = 1;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部