From ca15306cb8a92c9f2abfc816ef5b69545c838d9f Mon Sep 17 00:00:00 2001 From: Fisher Cheng Date: Fri, 23 Nov 2012 14:16:46 +0800 Subject: cleo/linux,common/include: add USB host driver, closes #4212 --- .../Spidcom/targets/msk500/linux26.config.part | 110 +++++ .../arch/arm/mach-spc300/board-mse500.c | 3 + .../arch/arm/mach-spc300/spc300-devices.c | 55 +++ .../arch/arm/mach-spc300/spc300-devices.h | 7 + .../arch/arm/mach-spc300/spc300.c | 12 + .../linux-2.6.25.10-spc300/drivers/usb/Kconfig | 1 + .../drivers/usb/core/buffer.c | 17 +- .../linux-2.6.25.10-spc300/drivers/usb/core/hcd.c | 12 + .../linux-2.6.25.10-spc300/drivers/usb/core/hcd.h | 20 + .../linux-2.6.25.10-spc300/drivers/usb/core/hub.c | 390 +++++++++++++++- .../drivers/usb/core/message.c | 5 + .../drivers/usb/core/quirks.c | 3 + .../drivers/usb/core/sysfs.c | 6 + .../linux-2.6.25.10-spc300/drivers/usb/core/urb.c | 26 ++ .../drivers/usb/host/ehci-hcd.c | 35 +- .../drivers/usb/host/ehci-hub.c | 22 +- .../drivers/usb/host/ehci-mem.c | 20 + .../drivers/usb/host/ehci-mstar.c | 518 +++++++++++++++++++++ .../drivers/usb/host/ehci-mstar.h | 107 +++++ .../drivers/usb/host/ehci-q.c | 80 +++- .../drivers/usb/host/ehci-sched.c | 113 ++++- .../linux-2.6.25.10-spc300/drivers/usb/host/ehci.h | 81 +++- .../drivers/usb/mon/mon_bin.c | 5 + .../drivers/usb/serial/ftdi_sio.c | 1 + .../drivers/usb/serial/ftdi_sio.h | 7 + .../drivers/usb/storage/scsiglue.c | 19 + .../drivers/usb/storage/unusual_devs.h | 24 + .../drivers/usb/storage/usb.c | 4 + .../linux-2.6.25.10-spc300/include/linux/usb.h | 4 + .../include/linux/usb/quirks.h | 7 + 30 files changed, 1697 insertions(+), 17 deletions(-) create mode 100644 cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-mstar.c create mode 100644 cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-mstar.h (limited to 'cleopatre') diff --git a/cleopatre/buildroot/target/device/Spidcom/targets/msk500/linux26.config.part b/cleopatre/buildroot/target/device/Spidcom/targets/msk500/linux26.config.part index 80c777e806..d84ec0cf36 100644 --- a/cleopatre/buildroot/target/device/Spidcom/targets/msk500/linux26.config.part +++ b/cleopatre/buildroot/target/device/Spidcom/targets/msk500/linux26.config.part @@ -13,3 +13,113 @@ CONFIG_SUSPEND_FREEZER=y CONFIG_REALTEK_PHY=y CONFIG_NETDEV_1000=y + +# +# Kernel Features +# +# CONFIG_AEABI is not set + +# +# UBI - Unsorted block images +# +# CONFIG_BLK_DEV_UB is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set + +# +# USB-based Watchdog Cards +# +# CONFIG_USBPCWATCHDOG is not set + +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB_ARCH_HAS_OHCI is not set +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_SUSPEND is not set +# CONFIG_USB_PERSIST is not set +# CONFIG_USB_OTG is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_EHCI_TT_NEWSCHED=y +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# may also be needed; see USB_STORAGE Help for more information +# +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MON is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_PHIDGET is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_GADGET is not set + +# +# Security options +# +# CONFIG_SECURITY_ROOTPLUG is not set + diff --git a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/board-mse500.c b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/board-mse500.c index 10b612ac75..315a521a30 100644 --- a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/board-mse500.c +++ b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/board-mse500.c @@ -111,6 +111,9 @@ static void __init mse500_init(void) #endif spc300_add_device_wdt(); mse500_copy_sram_section(); +#ifdef CONFIG_USB_EHCI_HCD + spc300_add_device_ehci(); +#endif } MACHINE_START(MSE500, "MSE500 300 mode - ARM MSE500 based board") diff --git a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.c b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.c index ad69b6b9d5..5e80bdb83c 100644 --- a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.c +++ b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.c @@ -43,6 +43,48 @@ */ #define SPC300_MTD_PARTITION_NB_MAX 7 +#ifdef CONFIG_USB_EHCI_HCD +/** + * USB EHCI Devices Structures + */ +static struct resource mstar_usb_ehci_resources[] = { + [0] = { + .start = USB_UTMI_BASE, + .end = USB_UTMI_BASE + SZ_512 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = USB_UHC_BASE, + .end = USB_UHC_BASE + SZ_512 - 1, + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = USB_USBC_BASE, + .end = USB_USBC_BASE + SZ_512 - 1, + .flags = IORESOURCE_MEM, + }, + [3] = { + .start = INT_UHC, + .end = INT_UHC, + .flags = IORESOURCE_IRQ, + }, +}; + +/* The dmamask must be set for EHCI to work */ +static u64 ehci_dmamask = 0x7ffffff; //tony add for limit DMA range + +static struct platform_device Mstar_usb_ehci_device = { + .name = "Mstar-ehci-1", + .id = 0, + .dev = { + .dma_mask = &ehci_dmamask, + .coherent_dma_mask = 0xffffffff, //tony add for limit DMA range + }, + .num_resources = ARRAY_SIZE(mstar_usb_ehci_resources), + .resource = mstar_usb_ehci_resources, +}; +#endif + /** * UART Devices Structures */ @@ -392,6 +434,19 @@ static struct platform_device spc300_pcm_device = { }; #endif +#ifdef CONFIG_USB_EHCI_HCD +/** + * Register USB EHCI. + */ +void __init spc300_add_device_ehci(void) +{ + platform_device_register(&Mstar_usb_ehci_device); +} +#endif + +/** + * Register UART 0 device. + */ void __init spc300_add_device_uart0(void) { amba_device_register(amba_devs[0], &iomem_resource); diff --git a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.h b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.h index a933d74c87..30ef053256 100644 --- a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.h +++ b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.h @@ -37,6 +37,13 @@ struct spc300_afe_spi_dev { uint32_t spimode; }; +#ifdef CONFIG_USB_EHCI_HCD +/** + * Register USB EHCI. + */ +void spc300_add_device_ehci(void); +#endif + /** * Register UART 0 device. */ diff --git a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300.c b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300.c index a17a03f9ef..2b8d6c074b 100644 --- a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300.c +++ b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300.c @@ -79,6 +79,14 @@ struct sys_timer spc300_timer = { static struct map_desc spc300_io_desc[] __initdata = { /* virtual physical length domain */ + { IO_ADDRESS(TOPREG_BASE) , __phys_to_pfn(TOPREG_BASE) , SZ_256 , MT_DEVICE }, +#ifdef CONFIG_CHIP_FEATURE_IOMUX + { IO_ADDRESS(IOMUX_BASE) , __phys_to_pfn(IOMUX_BASE) , SZ_256 , MT_DEVICE }, +#endif + { IO_ADDRESS(ARM_BRG_BASE) , __phys_to_pfn(ARM_BRG_BASE) , SZ_256 , MT_DEVICE }, +#ifdef CONFIG_CHIP_FEATURE_MIU_CTRL + { IO_ADDRESS(MIU_BASE) , __phys_to_pfn(MIU_BASE) , SZ_512 , MT_DEVICE }, +#endif { IO_ADDRESS(ARM_ICTL_BASE) , __phys_to_pfn(ARM_ICTL_BASE) , SZ_1K , MT_DEVICE }, { IO_ADDRESS(ARM_TIMER1_BASE) , __phys_to_pfn(ARM_TIMER1_BASE) , SZ_1K , MT_DEVICE }, { IO_ADDRESS(ARM_UART1_BASE) , __phys_to_pfn(ARM_UART1_BASE) , SZ_1K , MT_DEVICE }, @@ -93,6 +101,10 @@ static struct map_desc spc300_io_desc[] __initdata = { #ifdef CONFIG_CHIP_FEATURE_SRAM { IO_ADDRESS(SRAM_BASE) , __phys_to_pfn(SRAM_BASE) , SRAM_SIZE , MT_DEVICE }, #endif +#ifdef CONFIG_USB_EHCI_HCD + { IO_ADDRESS(USB_UTMI_BASE) , __phys_to_pfn(USB_UTMI_BASE) , SZ_1K , MT_DEVICE }, + { IO_ADDRESS(USB_UHC_BASE) , __phys_to_pfn(USB_UHC_BASE) , SZ_1K , MT_DEVICE } +#endif }; static struct map_desc spc300_nvram_io_desc; static struct map_desc spc300_plccode_io_desc; diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/Kconfig b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/Kconfig index 755823cdf6..d8f8ae7051 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/Kconfig +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/Kconfig @@ -55,6 +55,7 @@ config USB_ARCH_HAS_EHCI default y if PPC_83xx default y if SOC_AU1200 default y if ARCH_IXP4XX + default y if ARM default PCI # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/buffer.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/buffer.c index cadb2dc1d2..3a4e896a54 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/buffer.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/buffer.c @@ -15,12 +15,25 @@ #include #include #include "hcd.h" +#include "../host/ehci-mstar.h" /* * DMA-Coherent Buffers */ - +#if _USB_128_ALIGMENT +/* FIXME tune these based on pool statistics ... */ +static const size_t pool_max [HCD_BUFFER_POOLS] = { + /* platforms without dma-friendly caches might need to + * prevent cacheline sharing... + */ + 128, //Jonas: for 128 cache line alignemnt + 256, + 512, + PAGE_SIZE / 2 + /* bigger --> allocate pages */ +}; +#else /* FIXME tune these based on pool statistics ... */ static const size_t pool_max [HCD_BUFFER_POOLS] = { /* platforms without dma-friendly caches might need to @@ -32,7 +45,7 @@ static const size_t pool_max [HCD_BUFFER_POOLS] = { PAGE_SIZE / 2 /* bigger --> allocate pages */ }; - +#endif /* SETUP primitives */ diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/hcd.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/hcd.c index e52ed1663b..16cd7bd0bf 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/hcd.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/hcd.c @@ -44,6 +44,7 @@ #include "usb.h" #include "hcd.h" #include "hub.h" +#include "../host/ehci-mstar.h" /*-------------------------------------------------------------------------*/ @@ -1486,6 +1487,11 @@ rescan: } spin_unlock_irq(&hcd_urb_list_lock); +#if defined(MSTAR_PATCH_HOTPLUG) + /* 120316, modify for wifi load/unload repeatly */ + msleep(10); +#endif + /* Wait until the endpoint queue is completely empty */ while (!list_empty (&ep->urb_list)) { spin_lock_irq(&hcd_urb_list_lock); @@ -1500,6 +1506,12 @@ rescan: spin_unlock_irq(&hcd_urb_list_lock); if (urb) { +#if defined(MSTAR_PATCH_HOTPLUG) + //Add by Austin for ISO hotlpug + usb_hcd_unlink_urb_from_ep (hcd,urb); + if (atomic_read (&urb->use_count) > 0) + atomic_dec (&urb->use_count); +#endif usb_kill_urb (urb); usb_put_urb (urb); } diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/hcd.h b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/hcd.h index 2d1c3d5e47..5e30540647 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/hcd.h +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/hcd.h @@ -21,6 +21,8 @@ #include +#include "../host/ehci-mstar.h" + /* This file contains declarations of usbcore internals that are mostly * used or exposed by Host Controller Drivers. */ @@ -123,6 +125,20 @@ struct usb_hcd { #define HC_IS_RUNNING(state) ((state) & __ACTIVE) #define HC_IS_SUSPENDED(state) ((state) & __SUSPEND) +#if defined(MSTAR_PATCH_USB_HCD) + // Refactoring --- 2011.10.27 --- + u8 port_index; + u32 utmi_base; + u32 ehc_base; + u32 usbc_base; + + u32 root_port_devnum; + u8 enum_port_flag; + u8 rootflag; + + spinlock_t lock_usbreset; +#endif + /* more shared queuing code would be good; it should support * smarter scheduling, handle transaction translators, etc; * input size of periodic table to an interrupt scheduler. @@ -214,6 +230,10 @@ struct hc_driver { /* force handover of high-speed port to full-speed companion */ void (*relinquish_port)(struct usb_hcd *, int); +#if defined(MSTAR_PATCH_USB_HCD) + /* has a port been handed over to a companion? */ + int (*port_handed_over)(struct usb_hcd *, int); +#endif }; extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/hub.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/hub.c index 7f1bc97011..dd61da9618 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/hub.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/hub.c @@ -1171,6 +1171,10 @@ static inline void usb_stop_pm(struct usb_device *udev) void usb_disconnect(struct usb_device **pdev) { struct usb_device *udev = *pdev; +#if defined(MSTAR_PATCH_HOTPLUG) && defined(MSTAR_PATCH_USB_HCD) + struct usb_hcd *hcd = container_of(udev->bus, struct usb_hcd, self); + int devnum=udev->devnum; +#endif int i; if (!udev) { @@ -1183,6 +1187,10 @@ void usb_disconnect(struct usb_device **pdev) * this quiesces everyting except pending urbs. */ usb_set_device_state(udev, USB_STATE_NOTATTACHED); +#if defined(MSTAR_PATCH_HOTPLUG) && defined(MSTAR_PATCH_USB_HCD) + //tony clear device number when disconnect + udev->devnum1=0; +#endif dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum); usb_lock_device(udev); @@ -1221,6 +1229,22 @@ void usb_disconnect(struct usb_device **pdev) usb_stop_pm(udev); put_device(&udev->dev); + +#if defined(MSTAR_PATCH_HOTPLUG) && defined(MSTAR_PATCH_USB_HCD) + if (hcd->root_port_devnum == devnum) { + printk("root hub reinitial\n"); + hcd->driver->stop(hcd); + hcd->driver->reset(hcd); + hcd->driver->start(hcd); + hcd->root_port_devnum=0; + hcd->enum_port_flag=0; + + //clear force full speed + writeb(readb((void*)(hcd->ehc_base+0x40*2)) & 0x7f, + (void*)(hcd->ehc_base+0x40*2)); + } +#endif + } #ifdef CONFIG_USB_ANNOUNCE_NEW_DEVICES @@ -1561,13 +1585,19 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, int delay_time, ret; u16 portstatus; u16 portchange; +#if defined(MSTAR_PATCH_USB_HCD) + u8 tmp; + struct usb_hcd *usb_hcd = bus_to_hcd(udev->bus); +#endif for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT; delay_time += delay) { /* wait to give the device a chance to reset */ msleep(delay); - +#if defined(MSTAR_PATCH_USB_HCD) + if ( (readb((void*)(usb_hcd->ehc_base+0x30*2)) & 0x03) == 0x01) { +#endif /* read and decode port status */ ret = hub_port_status(hub, port1, &portstatus, &portchange); if (ret < 0) @@ -1592,6 +1622,58 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, udev->speed = USB_SPEED_LOW; else udev->speed = USB_SPEED_FULL; + +#if defined(MSTAR_PATCH_USB_HCD) + if ((usb_hcd->rootflag==1) + && (readb((void*)(usb_hcd->ehc_base+0x30*2)) & 0x01)) { + tmp = readb((void*)(usb_hcd->ehc_base+0x40*2)); + if (tmp & 0x80) { + hub->hdev->speed = USB_SPEED_FULL; + udev->speed = USB_SPEED_FULL; + writeb(readb((void*)(usb_hcd->ehc_base+0x34*2)) | 0x08, + (void*)(usb_hcd->ehc_base+0x34*2)); + writeb(readb((void*)(usb_hcd->ehc_base+0x34*2)) & 0xfb, + (void*)(usb_hcd->ehc_base+0x34*2)); + } else { + //Host Speed Type (LS/FS/HS) + tmp = readb ((void*)(usb_hcd->ehc_base+0x41*2-1)); + if ((tmp & 0x06) == 0x04) { + hub->hdev->speed = USB_SPEED_HIGH; + udev->speed = USB_SPEED_HIGH; + /* tony add for Babble issue (HS) + * 1.Babble issue (EOF1): + * (1) if device is HS => bit <3:2> set 11 + * (2) if device is FS => bit <3:2> set 10 + */ + writeb(readb((void*)(usb_hcd->ehc_base+0x34*2)) | 0x0c, + (void*)(usb_hcd->ehc_base+0x34*2)); + dev_dbg(hub->intfdev, "HS 4868:%x\n" , + readb((void*)(usb_hcd->ehc_base+0x34*2))); + + } else if ((tmp & 0x06) == 0x00) { + hub->hdev->speed = USB_SPEED_FULL; + udev->speed = USB_SPEED_FULL; + /* tony add for Babble issue (FS) + * 1.Babble issue (EOF1): + * (1) if device is HS => bit <3:2> set 11 + * (2) if device is FS => bit <3:2> set 10 + */ + writeb(readb((void*)(usb_hcd->ehc_base+0x34*2)) | 0x08, + (void*)(usb_hcd->ehc_base+0x34*2)); + writeb(readb((void*)(usb_hcd->ehc_base+0x34*2)) & 0xfb, + (void*)(usb_hcd->ehc_base+0x34*2)); + dev_dbg( hub->intfdev, "FS 4868:%x\n", + readb((void*)(usb_hcd->ehc_base+0x34*2))); + } else if((tmp & 0x06) == 0x02) { + hub->hdev->speed = USB_SPEED_LOW; + udev->speed = USB_SPEED_LOW; + } else { + printk ("unknow port1 usb device speed:%x\n",tmp); + } + } + usb_hcd->rootflag=0; + } +#endif return 0; } @@ -1602,6 +1684,11 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, dev_dbg (hub->intfdev, "port %d not reset yet, waiting %dms\n", port1, delay); +#if defined(MSTAR_PATCH_USB_HCD) + } else { + return -ENOTCONN; + } +#endif } return -EBUSY; @@ -1666,6 +1753,49 @@ static int hub_port_reset(struct usb_hub *hub, int port1, return status; } +#if defined(MSTAR_PATCH_USB_HCD) +//Colin, 090430 for fail to get device descriptor (FS devices) +void port_reset(unsigned int, unsigned int); + +static void issue_port_reset(struct usb_hub *hub) +{ + int ii; + struct usb_device *hdev = hub->hdev; + unsigned int u32_uhc_base=0; + unsigned int u32_utmi_base=0; + unsigned int u32_usbc_base=0; + struct usb_hcd *hcd = bus_to_hcd(hdev->bus); + + u32_uhc_base=hcd->ehc_base; + u32_utmi_base=hcd->utmi_base; + u32_usbc_base=hcd->usbc_base; + + //Stop the Host controller + if ((readb((void*)(u32_uhc_base+0x10*2)) & 0x01) != 0) { + writeb( readb((void*)(u32_uhc_base+0x10*2)) & ~0x01, + (void*)(u32_uhc_base+0x10*2)); + + ii = 0; + while ((readb((void*)(u32_uhc_base+0x10*2)) & 0x01) != 0) { + if (ii++ > 100) { + printk("timeout to stop HC\n"); + break; + } + mdelay(1); + } + } + + port_reset(u32_utmi_base, u32_uhc_base); + + writeb(readb((void*)(u32_uhc_base+0x30*2)) | 0x02, + (void*)(u32_uhc_base+0x30*2)); + + //Start the Host Controller + writeb(readb((void*)(u32_uhc_base+0x10*2)) | 0x01, + (void*)(u32_uhc_base+0x10*2)); +} +#endif + #ifdef CONFIG_PM #ifdef CONFIG_USB_SUSPEND @@ -2132,6 +2262,9 @@ static int hub_port_debounce(struct usb_hub *hub, int port1) if (portchange & USB_PORT_STAT_C_CONNECTION) { clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_CONNECTION); +#if defined(MSTAR_PATCH_USB_HCD) + total_time = 0; // reset the counter +#endif } if (total_time >= HUB_DEBOUNCE_TIMEOUT) @@ -2201,10 +2334,55 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, char *speed, *type; int devnum = udev->devnum; +#if defined(MSTAR_PATCH_USB_HCD) + int retval2; + unsigned long flag; + struct usb_hcd *hcd = bus_to_hcd(hdev->bus); + + printk("====> hub_port_init %d \n", port1); +#if defined(MSTAR_PATCH_HOTPLUG) + udev->devnum1=udev->devnum; +#endif +#endif + /* root hub ports have a slightly longer reset period * (from USB 2.0 spec, section 7.1.7.5) */ if (!hdev->parent) { +#if defined(MSTAR_PATCH_USB_HCD) + /* some card reader need more time to prepare, Colin, 090305, + * increase to 300ms for Newman device */ + mdelay(300); + if (readb((void*)(hcd->ehc_base+0x30*2)) & 0x01) { + printk("udev->speed: %d\n", udev->speed); + printk("Plug in USB Port%d\n", hcd->port_index); + hcd->enum_port_flag=2; //initial enum_port1_flag + hcd->rootflag=1; + + /* Prevent task switch out when device connected at power on. */ + spin_lock_irqsave(&hcd->lock_usbreset, flag); + writeb(0x00, (void*)(hcd->ehc_base+0x50*2)); + port_reset(hcd->utmi_base, hcd->ehc_base); + + /* tony write bit1 for clear port change bit, + * some device this bit will be 1 */ + writeb(readb((void*)(hcd->ehc_base+0x30*2)) | 0x02, + (void*)(hcd->ehc_base+0x30*2)); + /* tony add for prepare ehci work 20080919 */ + writeb(readb((void*)(hcd->ehc_base+0x10*2)) | 0x01, + (void*)(hcd->ehc_base+0x10*2)); + + spin_unlock_irqrestore(&hcd->lock_usbreset, flag); +#if defined(MSTAR_PATCH_HOTPLUG) + hcd->root_port_devnum = devnum; //tony HOTPLUG +#endif + } else { + printk("hub_port_init: port status change ...\n"); + printk("port %d status: 0x%x\n", hcd->port_index, + readb((void*)(hcd->ehc_base+0x30*2))); + return (-ENOTCONN); //Jonas: patch for some USB-HD devices. + } +#endif delay = HUB_ROOT_RESET_TIME; if (port1 == hdev->bus->otg_port) hdev->bus->b_hnp_enable = 0; @@ -2228,7 +2406,11 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, dev_dbg(&udev->dev, "device reset changed speed!\n"); goto fail; } +#if defined(MSTAR_PATCH_USB_HCD) +#else oldspeed = udev->speed; +#endif + printk("udev->speed: %d\n", udev->speed); /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... * it's fixed size except for full speed devices. @@ -2247,8 +2429,11 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, * the device descriptor to get bMaxPacketSize0 and * then correct our initial guess. */ +#if defined(MSTAR_PATCH_USB_HCD) +#else udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); break; +#endif case USB_SPEED_LOW: /* fixed at 8 */ udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(8); break; @@ -2294,6 +2479,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, * first 8 bytes of the device descriptor to get the ep0 maxpacket * value. */ +#if !defined(MSTAR_PATCH_USB_HCD) //tony add for hub connect for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) { if (USE_NEW_SCHEME(retry_counter)) { struct usb_device_descriptor *buf; @@ -2355,12 +2541,44 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, } #undef GET_DESCRIPTOR_BUFSIZE } +#endif +#if defined(MSTAR_PATCH_USB_HCD) + //Colin, 090317, for Transcend card reader, TUR not ready + if (usb_get_device_descriptor(udev, 8) < 0) + { + printk("First get dev desc failed\n"); + } + + if(!hdev->parent) + issue_port_reset(hub); + else + hub_port_reset(hub, port1, udev, delay); + + msleep(100); +#endif + +#if defined(MSTAR_PATCH_USB_HCD) + //tony add for hub connect + for (i = 0; i < GET_DESCRIPTOR_TRIES; ++i) { +#endif for (j = 0; j < SET_ADDRESS_TRIES; ++j) { retval = hub_set_address(udev, devnum); +#if defined(MSTAR_PATCH_USB_HCD) + if (retval == 0) +#else if (retval >= 0) +#endif break; + msleep(200); +#if defined(MSTAR_PATCH_USB_HCD) + retval2 = hub_port_reset(hub, port1, udev, delay); + if (retval2 < 0) { + printk("<1>set_addr and port_reset failed!\n"); + goto fail; + } +#endif } if (retval < 0) { dev_err(&udev->dev, @@ -2374,9 +2592,30 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, * - read ep0 maxpacket even for high and low speed, */ msleep(10); + +#if defined(MSTAR_PATCH_USB_HCD) + /* tony add for hub connect */ + retval = usb_get_device_descriptor(udev, 8); + + if (retval >= 8) + break; + + msleep(100); + + if (retval != 8) { + dev_err(&udev->dev, "device descriptor " + "read/%s, error %d\n", + "8", retval); + if (retval >= 0) + retval = -EMSGSIZE; + goto fail; + } +#else if (USE_NEW_SCHEME(retry_counter)) break; +#endif +#if !defined(MSTAR_PATCH_USB_HCD) //tony mark add for hub retval = usb_get_device_descriptor(udev, 8); if (retval < 8) { dev_err(&udev->dev, "device descriptor " @@ -2391,7 +2630,11 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, } if (retval) goto fail; +#endif +#if defined(MSTAR_PATCH_USB_HCD) + } +#endif i = udev->descriptor.bMaxPacketSize0 == 0xff? 512 : udev->descriptor.bMaxPacketSize0; if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) { @@ -2533,6 +2776,22 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, if (printk_ratelimit()) dev_err (hub_dev, "connect-debounce failed, " "port %d disabled\n", port1); +#if defined(MSTAR_PATCH_HOTPLUG) && defined(MSTAR_PATCH_USB_HCD) + //Colin, for the plug in-out USB disk quickly. + if (hub->hdev->parent == NULL) { + printk("root hub reinitial\n"); + hcd->driver->stop(hcd); + hcd->driver->reset(hcd); + hcd->driver->start(hcd); + + hcd->root_port_devnum=0; + hcd->enum_port_flag=0; + + //clear force full speed + writeb(readb((void*)(hcd->ehc_base + 0x40*2)) & 0x7f, + (void*)(hcd->ehc_base + 0x40*2)); + } +#endif goto done; } portstatus = status; @@ -2664,12 +2923,35 @@ loop: if ((status == -ENOTCONN) || (status == -ENOTSUPP)) break; } + +#if defined(MSTAR_PATCH_USB_HCD) + if ((hub->hdev->parent==NULL) + && (!hcd->driver->port_handed_over + || !(hcd->driver->port_handed_over)(hcd, port1))) { + if (hcd->enum_port_flag==2) { + // for Plug-in/out the USB disk quickly + if ((readb((void*)(hcd->ehc_base+0x30*2)) & 0x01) + && (readb((void*)(hcd->ehc_base+0x41*2-1)) & 0x04)) { + printk("Force FS \n"); + //tony will force device to FS and enum again + hcd->enum_port_flag=1; + } + } + dev_err(hub_dev, "unable to enumerate USB device on port %d\n", port1); + } +#else dev_err(hub_dev, "unable to enumerate USB device on port %d\n", port1); +#endif done: +#if defined(MSTAR_PATCH_USB_HCD) + //Jonas: we don't need it ! + return; +#else hub_port_disable(hub, port1, 1); if (hcd->driver->relinquish_port && !hub->hdev->parent) hcd->driver->relinquish_port(hcd, port1); +#endif } static void hub_events(void) @@ -2685,6 +2967,11 @@ static void hub_events(void) u16 portchange; int i, ret; int connect_change; +#if defined(MSTAR_PATCH_HOTPLUG) && defined(MSTAR_PATCH_USB_HCD) + struct usb_hcd *hcd; + u8 temp; + int count = 250 * 1000; +#endif /* * We restart the list every time to avoid a deadlock with @@ -2693,7 +2980,9 @@ static void hub_events(void) * Not the most efficient, but avoids deadlocks. */ while (1) { - +#if defined(MSTAR_PATCH_HOTPLUG) && defined(MSTAR_PATCH_USB_HCD) +testtry: +#endif /* Grab the first entry at the beginning of the list */ spin_lock_irq(&hub_event_lock); if (list_empty(&hub_event_list)) { @@ -2769,7 +3058,14 @@ static void hub_events(void) ret = hub_port_status(hub, i, &portstatus, &portchange); +#if defined(MSTAR_PATCH_HOTPLUG) && defined(MSTAR_PATCH_USB_HCD) + //tony add for disconnect & hotplug + hcd = bus_to_hcd(hdev->bus); + temp = readb((void*)(hcd->ehc_base+0x30*2)); + if ((ret < 0 ) && ((temp & 0x03)==0x01)) +#else if (ret < 0) +#endif continue; if (hub->activating && !hdev->children[i-1] && @@ -2847,6 +3143,57 @@ static void hub_events(void) if (connect_change) hub_port_connect_change(hub, i, portstatus, portchange); + +#if defined(MSTAR_PATCH_HOTPLUG) && defined(MSTAR_PATCH_USB_HCD) + /* tony add for compatibility issue if enum fail + * then go into FS and retry enum */ + hcd = bus_to_hcd(hub->hdev->bus); + + if(hcd->enum_port_flag==1) { + //tony just try 1 time + hcd->enum_port_flag=0; + //stop run + writeb(readb((void*)(hcd->ehc_base+0x10*2))&0xfe, + (void*)(hcd->ehc_base+0x10*2)); + //reset HC + writeb(readb((void*)(hcd->ehc_base+0x10*2))|0x02, + (void*)(hcd->ehc_base+0x10*2)); + + count = 250 * 1000; //waiting for reset complete + + do { + temp = readb((void*)(hcd->ehc_base+0x10*2)); + temp &= 0x02; + if (temp == 0x00) + break; + udelay (1); + count--; + if(count==0) + printk("Port 1 Reset time out error\n"); + } while (count> 0); + + //force full speed + writeb(readb((void*)(hcd->ehc_base+0x40*2))|0x80, + (void*)(hcd->ehc_base+0x40*2)); + //run bit=1, async bit=1 + writeb(readb((void*)(hcd->ehc_base+0x10*2))|0x09, + (void*)(hcd->ehc_base+0x10*2)); + //set interrupt enable + writeb(readb((void*)(hcd->ehc_base+0x18*2))|0x37, + (void*)(hcd->ehc_base+0x18*2)); + writeb(readb((void*)(hcd->ehc_base+0x34*2))|0x40, + (void*)(hcd->ehc_base+0x34*2)); + //set full speed more fast (EOF1) + writeb(readb((void*)(hcd->ehc_base+0x34*2))|0x08, + (void*)(hcd->ehc_base+0x34*2)); + //avoid babble issue if FS + writeb(readb((void*)(hcd->ehc_base+0x34*2))&0xfb, + (void*)(hcd->ehc_base+0x34*2)); + usb_unlock_device(hdev); + + goto testtry; + } +#endif } /* end for i */ /* deal with hub status changes */ @@ -2928,6 +3275,45 @@ static struct usb_driver hub_driver = { .supports_autosuspend = 1, }; +#if defined(MSTAR_PATCH_USB_HCD) +void port_reset(unsigned int reg_utmi, unsigned int reg_uhc) +{ + writeb(0x10, (void*)(reg_utmi+0x2C*2)); + writeb(0x00, (void*)(reg_utmi+0x2D*2-1)); + writeb(0x00, (void*)(reg_utmi+0x2E*2)); + writeb(0x00, (void*)(reg_utmi+0x2F*2-1)); + writeb(0x80 ,(void*)(reg_utmi+0x2A*2)); + + #if (MSTAR_EHC_RTERM_PATCH) + writeb(readb((void*)(reg_utmi+0x13*2-1)) | 0x70, (void*)(reg_utmi+0x13*2-1)); + #endif + + //Force HS TX current enable and CDR stage select + writeb(readb((void*)(reg_uhc+0x31*2-1)) | 0x01, (void*)(reg_uhc+0x31*2-1)); + mdelay(50); //80 + + writeb(0x0 ,(void*)(reg_utmi+0x2A*2)); + + mdelay(20); + + //Force HS TX current enable and CDR stage select + writeb(readb((void*)(reg_uhc+0x31*2-1)) & 0xfe, (void*)(reg_uhc+0x31*2-1)); + writeb(readb((void*)(reg_utmi+0x2c*2)) | 0x98, (void*)(reg_utmi+0x2c*2)); + writeb(readb((void*)(reg_utmi+0x2e*2)) | 0x10, (void*)(reg_utmi+0x2e*2)); + writeb(readb((void*)(reg_utmi+0x2f*2-1)) | 0x01, (void*)(reg_utmi+0x2f*2-1)); + writeb(readb((void*)(reg_utmi+0x2d*2-1)) | 0x02, (void*)(reg_utmi+0x2d*2-1)); + + #if (MSTAR_EHC_RTERM_PATCH) + writeb(readb((void*)(reg_utmi+0x13*2-1))&0x8F, (void*)(reg_utmi+0x13*2-1)); + #endif + + //reset UTMI + writeb(readb((void*)(reg_utmi+0x06*2))|0x03, (void*)(reg_utmi+0x06*2)); + writeb(readb((void*)(reg_utmi+0x06*2))&(~0x03), (void*)(reg_utmi+0x06*2)); + +} +#endif + int usb_hub_init(void) { if (usb_register(&hub_driver) < 0) { diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/message.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/message.c index c311f67b7f..e229d94335 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/message.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/message.c @@ -1615,7 +1615,12 @@ free_interfaces: } kfree(new_interfaces); +#if defined (CONFIG_CHIP_MSE500) + if (cp->string == NULL + && !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) +#else if (cp->string == NULL) +#endif cp->string = usb_cache_string(dev, cp->desc.iConfiguration); /* Now that all the interfaces are set up, register them diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/quirks.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/quirks.c index dfc5418ea1..289f268425 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/quirks.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/quirks.c @@ -47,6 +47,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* Edirol SD-20 */ { USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Saitek Cyborg Gold Joystick */ + { USB_DEVICE(0x06a3, 0x0006), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, + /* M-Systems Flash Disk Pioneers */ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/sysfs.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/sysfs.c index a37ccbd1e0..268d0d2ba8 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/sysfs.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/sysfs.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "usb.h" /* Active configuration fields */ @@ -790,7 +791,12 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf) if (retval) return retval; +#if defined (CONFIG_CHIP_MSE500) + if (alt->string == NULL + && !(udev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) +#else if (alt->string == NULL) +#endif alt->string = usb_cache_string(udev, alt->desc.iInterface); if (alt->string) retval = device_create_file(dev, &dev_attr_interface); diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/urb.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/urb.c index 9d7e63292c..643d3c3633 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/urb.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/urb.c @@ -7,6 +7,8 @@ #include #include #include "hcd.h" +#include "../host/ehci-mstar.h" + #define to_urb(d) container_of(d, struct urb, kref) @@ -285,6 +287,9 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) struct usb_device *dev; struct usb_host_endpoint *ep; int is_out; +#if defined(MSTAR_PATCH_HOTPLUG) && defined(MSTAR_PATCH_USB_HCD) + struct usb_hcd *hcd; +#endif if (!urb || urb->hcpriv || !urb->complete) return -EINVAL; @@ -429,8 +434,19 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) case USB_SPEED_FULL: /* units are frames/msec */ case USB_SPEED_LOW: if (xfertype == USB_ENDPOINT_XFER_INT) { +#if defined(MSTAR_PATCH_HOTPLUG) && defined(MSTAR_PATCH_USB_HCD) + hcd = bus_to_hcd(urb->dev->bus); + if ((readb((void*)(hcd->ehc_base+0x30*2)) & 0x01)) { + if (urb->interval > 255) { + /* Colin, 090305, + * Don't return EINVAL, the root hub would stop */ + urb->interval = 255; + } + } +#else if (urb->interval > 255) return -EINVAL; +#endif /* NOTE ohci only handles up to 32 */ max = 128; } else { @@ -549,12 +565,22 @@ void usb_kill_urb(struct urb *urb) might_sleep(); if (!(urb && urb->dev && urb->ep)) return; +#if defined(MSTAR_PATCH_USB_HCD) + if(atomic_read(&urb->use_count) < 0) //Add by Austin for ISO hotplug + return; +#endif mutex_lock(&reject_mutex); ++urb->reject; mutex_unlock(&reject_mutex); usb_hcd_unlink_urb(urb, -ENOENT); +#if defined(MSTAR_PATCH_USB_HCD) + //120314, modify for wifi load/unload repeatly + wait_event_timeout(usb_kill_urb_queue, + atomic_read(&urb->use_count) <= 0, msecs_to_jiffies(2000)); +#else wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); +#endif mutex_lock(&reject_mutex); --urb->reject; diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-hcd.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-hcd.c index 46ee7f4c09..a73dd2f2fe 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-hcd.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-hcd.c @@ -126,7 +126,10 @@ module_param (park, uint, S_IRUGO); MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets"); /* for flakey hardware, ignore overcurrent indicators */ -static int ignore_oc = 0; + +//tony ignore oc +static int ignore_oc = 1; + module_param (ignore_oc, bool, S_IRUGO); MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); @@ -499,11 +502,15 @@ static int ehci_init(struct usb_hcd *hcd) /* controllers may cache some of the periodic schedule ... */ hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); +#if defined(MSTAR_PATCH_USB_HCD) + //tony add for FUSB200 + ehci->i_thresh = 8; +#else if (HCC_ISOC_CACHE(hcc_params)) // full frame cache ehci->i_thresh = 8; else // N microframes cached ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); - +#endif ehci->reclaim = NULL; ehci->next_uframe = -1; @@ -553,7 +560,9 @@ static int ehci_init(struct usb_hcd *hcd) } } ehci->command = temp; - +#if defined(MSTAR_PATCH_USB_HCD) + ehci_port_power(ehci, 0); //tony +#endif return 0; } @@ -804,7 +813,15 @@ static int ehci_urb_enqueue ( if (urb->dev->speed == USB_SPEED_HIGH) return itd_submit (ehci, urb, mem_flags); else +#if defined(MSTAR_PATCH_USB_HCD) + //Colin, patch for not real split-transaction mode + if ( (readb((void*)(hcd->ehc_base+0x41*2-1)) & 0x06) != 0x04) + return itd_submit (ehci, urb, mem_flags); + else return sitd_submit (ehci, urb, mem_flags); +#else + return sitd_submit (ehci, urb, mem_flags); +#endif } } @@ -944,7 +961,11 @@ rescan: */ if (qh->hw_info1 == 0) { ehci_vdbg (ehci, "iso delay\n"); +#if defined(MSTAR_PATCH_HOTPLUG) && defined(MSTAR_PATCH_USB_HCD) + goto done; //Add by Austin for ISO hotlpug +#else goto idle_timeout; +#endif } if (!HC_IS_RUNNING (hcd->state)) @@ -962,7 +983,10 @@ rescan: /* FALL THROUGH */ case QH_STATE_UNLINK: /* wait for hw to finish? */ case QH_STATE_UNLINK_WAIT: +#if defined(MSTAR_PATCH_HOTPLUG) && defined(MSTAR_PATCH_USB_HCD) +#else idle_timeout: +#endif spin_unlock_irqrestore (&ehci->lock, flags); schedule_timeout_uninterruptible(1); goto rescan; @@ -1043,6 +1067,11 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ixp4xx_ehci_driver #endif +#ifdef CONFIG_CHIP_MSE500 +#include "ehci-mstar.c" +#define PLATFORM_DRIVER ehci_hcd_mstar_driver +#endif + #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) #error "missing bus glue for ehci-hcd" diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-hub.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-hub.c index 4e065e556e..3607822e58 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-hub.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-hub.c @@ -588,7 +588,11 @@ static int ehci_hub_control ( goto error; wIndex--; temp = ehci_readl(ehci, status_reg); - +#if defined(MSTAR_PATCH_USB_HCD) + //tony add for FUSB200 + if(temp & PORT_OWNER) + break; +#endif /* * Even if OWNER is set, so the port is owned by the * companion controller, khubd needs to be able to clear @@ -835,6 +839,9 @@ static int ehci_hub_control ( "port %d low speed --> companion\n", wIndex + 1); temp |= PORT_OWNER; +#if defined(MSTAR_PATCH_USB_HCD) + ehci_writel(ehci, temp, status_reg); +#endif } else { ehci_vdbg (ehci, "port %d reset\n", wIndex + 1); temp |= PORT_RESET; @@ -889,3 +896,16 @@ static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum) set_owner(ehci, --portnum, PORT_OWNER); } +#if defined(CONFIG_CHIP_MSE500) +static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + u32 __iomem *reg; + + if (ehci_is_TDI(ehci)) + return 0; + reg = &ehci->regs->port_status[portnum - 1]; + return ehci_readl(ehci, reg) & PORT_OWNER; +} +#endif + diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-mem.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-mem.c index 0431397836..55f0c3ad8d 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-mem.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-mem.c @@ -170,7 +170,11 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) ehci->qtd_pool = dma_pool_create ("ehci_qtd", ehci_to_hcd(ehci)->self.controller, sizeof (struct ehci_qtd), +#if _USB_128_ALIGMENT + 128 /* byte alignment (for hw parts) */, +#else 32 /* byte alignment (for hw parts) */, +#endif 4096 /* can't cross 4K */); if (!ehci->qtd_pool) { goto fail; @@ -180,7 +184,11 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) ehci->qh_pool = dma_pool_create ("ehci_qh", ehci_to_hcd(ehci)->self.controller, sizeof (struct ehci_qh), +#if _USB_128_ALIGMENT + 128 /* byte alignment (for hw parts) */, +#else 32 /* byte alignment (for hw parts) */, +#endif 4096 /* can't cross 4K */); if (!ehci->qh_pool) { goto fail; @@ -194,7 +202,15 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) ehci->itd_pool = dma_pool_create ("ehci_itd", ehci_to_hcd(ehci)->self.controller, sizeof (struct ehci_itd), +#if _USB_128_ALIGMENT + 128 /* byte alignment (for hw parts) */, +#else +#if defined(MSTAR_PATCH_USB_HCD) + 64 /* byte alignment (for hw parts) */, +#else 32 /* byte alignment (for hw parts) */, +#endif +#endif 4096 /* can't cross 4K */); if (!ehci->itd_pool) { goto fail; @@ -204,7 +220,11 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) ehci->sitd_pool = dma_pool_create ("ehci_sitd", ehci_to_hcd(ehci)->self.controller, sizeof (struct ehci_sitd), +#if _USB_128_ALIGMENT + 128 /* byte alignment (for hw parts) */, +#else 32 /* byte alignment (for hw parts) */, +#endif 4096 /* can't cross 4K */); if (!ehci->sitd_pool) { goto fail; diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-mstar.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-mstar.c new file mode 100644 index 0000000000..df57d7da02 --- /dev/null +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-mstar.c @@ -0,0 +1,518 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2006-2008 MStar Semiconductor, Inc. +// All rights reserved. +// +// Unless otherwise stipulated in writing, any and all information contained +// herein regardless in any format shall remain the sole proprietary of +// MStar Semiconductor Inc. and be kept in strict confidence +// (ˇ§MStar Confidential Informationˇ¨) by the recipient. +// Any unauthorized act including without limitation unauthorized disclosure, +// copying, use, reproduction, sale, distribution, modification, disassembling, +// reverse engineering and compiling of the contents of MStar Confidential +// Information is unlawful and strictly prohibited. MStar hereby reserves the +// rights to any and all damages, losses, costs and expenses resulting therefrom. +// +//////////////////////////////////////////////////////////////////////////////// +#include +#include "ehci.h" +#include "ehci-mstar.h" + +//#define MDrv_Timer_Delayms(x) mdelay(x) + +#define SA_INTERRUPT IRQF_DISABLED + +//#define EHCI_POLLING +#if defined(EHCI_POLLING) + #include + struct semaphore thread_sem; +#endif + +static const struct hc_driver ehci_mstar_hc_driver = { + .description = hcd_name, + .product_desc = "Mstar EHCI", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* + * generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_MEMORY | HCD_USB2, + + /* + * basic lifecycle operations + * + * FIXME -- ehci_init() doesn't do enough here. + * See ehci-ppc-soc for a complete implementation. + */ + + .reset = ehci_init, + .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, + + /* + * scheduling support + */ + .get_frame_number = ehci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, + .bus_suspend = ehci_bus_suspend, + .bus_resume = ehci_bus_resume, + .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, +}; + +spinlock_t l2prefetch_lock=SPIN_LOCK_UNLOCKED; +#define REG_REC_CLR_FLAG (*((volatile u32 *)(IO_ADDRESS(ARM_BRG_BASE)))) +#define REG_MIU_SW_RST (*((volatile u32 *)(IO_ADDRESS(MIU_BASE) + 0x3C))) +#define REG_MIU_PROTECT2_STR (*((volatile u32 *)(IO_ADDRESS(MIU_BASE) + 0x60))) + +void chip_flush_memory(void) +{ + unsigned long dw_lock_flag = 0; + spin_lock_irqsave(&l2prefetch_lock, dw_lock_flag); + REG_REC_CLR_FLAG |= 0x00000004; + do { + if ((REG_REC_CLR_FLAG&0x00000004)==0) + break; + } while(1); + spin_unlock_irqrestore(&l2prefetch_lock, dw_lock_flag); +} + +unsigned int gehc_base, gutmi_base; + +void usb_pll_initial(unsigned int utmi_base, unsigned int usbc_base, + unsigned int uhc_base) +{ + // Disable MAC initial suspend, Reset UHC + writeb(0x0a, (void*) (usbc_base)); + + // Release UHC reset, enable UHC and OTG XIU function + writeb(0x28, (void*) (usbc_base)); + + writew(readb((void*)(utmi_base+0x02)) | 0x04, (void*) (utmi_base+0x02)); + + // PLL_TEST[30:28]: 3'b101 for IBIAS current select + // PLL_TEST[23] CLK480 to digital output source selection + writew(0x00e0, (void*) (utmi_base+0x22*2)); + + // PLL_TEST[15]: Bypass 480MHz clock divider + // PLL_TEST[7:4]: 5'b0101_0 for 1.0x + // PLL_TEST[0]: 1: synthesizer clock, 2'b11, 0: XIN_C + writew(0x8003, (void*) (utmi_base+0x20*2)); + + writew(0x0001, (void*) (utmi_base+0x24*2)); + + // Enable CLK12_SEL bit <2> for select low voltage crystal clock + writew(0x2084, (void*) (utmi_base+0x02*2)); + + // #7=0 Enable band-gap current #3=0 Disable force_pll_on + writew(0x0007, (void*) (utmi_base+0x08*2)); + + // reg_pdn: bit<15>, bit <2> ref_pdn # Turn on reference voltage and regulator + writew(0x6bc3, (void*) (utmi_base)); + mdelay(1); + + // Turn on UPLL, reg_pdn: bit<9> + writew(0x69c3, (void*) (utmi_base)); + mdelay(2); + + // Turn all (including hs_current) use override mode + writew(0x0001, (void*) (utmi_base)); +} + +//----------------------------------------- +void titania3_series_start_ehc(unsigned int utmi_base, unsigned int usbc_base, + unsigned int uhc_base, unsigned int flag) +{ + printk("titania3_series_start_ehc start\n"); + + gehc_base = uhc_base; + gutmi_base = utmi_base; + usb_pll_initial(utmi_base, usbc_base, uhc_base); + + if (flag & EHCFLAG_TESTPKG) { + writew(0x2084, (void*) (utmi_base+0x2*2)); + writew(0x8051, (void*) (utmi_base+0x20*2)); + } + + // Disable MAC initial suspend, Reset UHC + writeb(0x0a, (void*) (usbc_base)); + + // Release UHC reset, enable UHC and OTG XIU function + writeb(0x28, (void*) (usbc_base)); + + // set reg_double_data_rate, To get better jitter performance + writeb(readb((void*)(utmi_base+0x0D*2-1)) | 0x01, + (void*) (utmi_base+0x0D*2-1)); + + if (flag & EHCFLAG_DOUBLE_DATARATE) { + if ((flag & EHCFLAG_DDR_MASK) == EHCFLAG_DDR_x15) { + // Set usb bus = 480MHz x 1.5 + writeb(readb((void*)(utmi_base+0x20*2)) | 0x76, + (void*) (utmi_base+0x20*2)); + } else if ((flag & EHCFLAG_DDR_MASK) == EHCFLAG_DDR_x18) { + // Set usb bus = 480MHz x 1.8 + writeb(readb((void*)(utmi_base+0x20*2)) | 0x8e, + (void*) (utmi_base+0x20*2)); + } + + //Set slew rate control for overspeed (or 960MHz) + writeb(readb((void*)(utmi_base+0x2c*2)) |0x1, + (void*) (utmi_base+0x2c*2)); + } + + // Disable force_pll_on + writeb(readb((void*)(utmi_base+0x09*2-1)) & ~0x08, + (void*) (utmi_base+0x09*2-1)); + + // Enable band-gap current + writeb(readb((void*)(utmi_base+0x08*2)) & ~0x80, + (void*) (utmi_base+0x08*2)); + + // reg_pdn: bit<15>, bit <2> ref_pdn + writeb(0xC3, (void*)(utmi_base)); + + // delay 1ms + mdelay(1); + + // Turn on UPLL, reg_pdn: bit<9> + writeb(0x69, (void*) (utmi_base+0x01*2-1)); + + // delay 2ms + mdelay(2); + + // Turn all (including hs_current) use override mode + writeb(0x01, (void*) (utmi_base)); + + // Turn on UPLL, reg_pdn: bit<9> + writeb(0, (void*) (utmi_base+0x01*2-1)); + + // Disable MAC initial suspend, Reset UHC + writeb(0x0A, (void*) (usbc_base)); + + // Release UHC reset, enable UHC XIU function + writeb(0x28, (void*) (usbc_base)); + + // set CA_START as 1 + writeb(readb((void*)(utmi_base+0x3C*2)) | 0x01, + (void*) (utmi_base+0x3C*2)); + mdelay(10); + + // release CA_START + writeb(readb((void*)(utmi_base+0x3C*2)) & ~0x01, + (void*) (utmi_base+0x3C*2)); + + // polling bit <1> (CA_END) + while ((readb((void*)(utmi_base+0x3C*2)) & 0x02) == 0); + + if (flag & EHCFLAG_DPDM_SWAP) { + // dp dm swap + writeb(readb((void*)(utmi_base+0x0b*2-1)) |0x20, + (void*) (utmi_base+0x0b*2-1)); + } + + //UHC select enable + writeb(readb((void*)(usbc_base+0x02*2)) & ~0x03, + (void*) (usbc_base+0x02*2)); + + //UHC select enable + writeb(readb((void*)(usbc_base+0x02*2)) | 0x01, + (void*) (usbc_base+0x02*2)); + + //0: VBUS On. + writeb(readb((void*)(uhc_base+0x40*2)) & ~0x10, + (void*) (uhc_base+0x40*2)); + mdelay(1); // delay 1ms + + // Active HIGH + writeb(readb((void*)(uhc_base+0x40*2)) | 0x08, + (void*) (uhc_base+0x40*2)); + mdelay(1); // delay 1ms + + //improve the efficiency of USB access MIU when system is busy + writeb(readb((void*)(uhc_base+0x81*2-1)) | 0x8F, + (void*) (uhc_base+0x81*2-1)); + + //reg_tx_force_hs_current_enable + writeb((readb((void*)(utmi_base+0x06*2)) & 0x9F) | 0x40, + (void*) (utmi_base+0x06*2)); + + //Disconnect window select + writeb(readb((void*)(utmi_base+0x03*2-1)) | 0x28, + (void*) (utmi_base+0x03*2-1)); + + //Disconnect window select + writeb(readb((void*)(utmi_base+0x03*2-1)) & 0xef, + (void*) (utmi_base+0x03*2-1)); + + //Disable improved CDR + writeb(readb((void*)(utmi_base+0x07*2-1)) & 0xfd, + (void*) (utmi_base+0x07*2-1)); + + // UTMI RX anti-dead-loc, ISI effect improvement + writeb(readb((void*)(utmi_base+0x09*2-1)) |0x81, + (void*) (utmi_base+0x09*2-1)); + + if ((flag & EHCFLAG_DOUBLE_DATARATE)==0) { + // TX timing select latch path + writeb(readb((void*)(utmi_base+0x0b*2-1)) |0x80, + (void*) (utmi_base+0x0b*2-1)); + } + + // Chirp signal source select + writeb(readb((void*)(utmi_base+0x15*2-1)) |0x20, + (void*) (utmi_base+0x15*2-1)); + // change to 55 interface + writeb(readb((void*)(utmi_base+0x15*2-1)) |0x40, + (void*) (utmi_base+0x15*2-1)); + writeb(readb((void*)(utmi_base+0x2c*2)) |0x98, + (void*) (utmi_base+0x2c*2)); + writeb(readb((void*)(utmi_base+0x2e*2)) |0x10, + (void*) (utmi_base+0x2e*2)); + writeb(readb((void*)(utmi_base+0x2f*2-1)) |0x01, + (void*) (utmi_base+0x2f*2-1)); + writeb(readb((void*)(utmi_base+0x2d*2-1)) |0x02, + (void*) (utmi_base+0x2d*2-1)); + + +#if defined(ENABLE_PWR_NOISE_ECO) + //enable use eof2 to reset state machineˇ¨ (power noise) + writeb(readb((void*)(usbc_base+0x02*2)) | 0x40, + (void*) (usbc_base+0x02*2)); +#endif + //enable Preamble function + writeb(readb((void*)(usbc_base+0x0e*2)) | 0x08, + (void*) (usbc_base+0x0e*2)); + + if (flag & EHCFLAG_TESTPKG) { + writew(0x0600, (void*) (utmi_base+0x14*2)); + writew(0x0038, (void*) (utmi_base+0x10*2)); + writew(0x0BFE, (void*) (utmi_base+0x32*2)); + } +} + +/*-------------------------------------------------------------------------*/ + +/* configure so an HC device and id are always provided */ +/* always called with process context; sleeping is OK */ + +/** + * usb_ehci_au1xxx_probe - initialize Au1xxx-based HCDs + * Context: !in_interrupt() + * + * Allocates basic resources for this USB host controller, and + * then invokes the start() method for the HCD associated with it + * through the hotplug entry's driver_data. + * + */ + + +#if defined(EHCI_POLLING) +static int ehci_polling_thread(void * __hcd) +{ + struct usb_hcd *hcd = __hcd; + spinlock_t *poll_lock; + u8 regv; + + printk(KERN_WARNING "ehci_polling_thread start\n"); + down(&thread_sem); + do { + set_current_state(TASK_INTERRUPTIBLE); + + regv = readb((void*)(hcd->ehc_base+0x14*2)); + + if (regv == 0) { + msleep(1); + continue; + } + + set_current_state(TASK_RUNNING); + printk("ehci_irq\n"); + ehci_irq(__hcd); + } while(1); + up(&thread_sem); + + return 0; +} +#endif + +int usb_ehci_mstar_probe(const struct hc_driver *driver, + struct usb_hcd **hcd_out, struct platform_device *dev) +{ + int retval=0; + struct usb_hcd *hcd; + struct ehci_hcd *ehci; + + struct resource *regs; + u32 utmi_base; + u32 uhc_base; + u32 usbc_base; + +#if defined(EHCI_POLLING) + struct task_struct *th; +#endif + + //Benson modify for kafe + //Restore Registers base address + regs = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!regs) + return -ENXIO; + + utmi_base = (u32)ioremap(regs->start, (regs->end - regs->start) + 1); + + printk("utmi_base:%x\n", utmi_base); + regs = platform_get_resource(dev, IORESOURCE_MEM, 1); + if (!regs) + return -ENXIO; + + uhc_base = (u32)ioremap(regs->start, (regs->end - regs->start) + 1); + printk("uhc_base:%x\n", uhc_base); + regs = platform_get_resource(dev, IORESOURCE_MEM, 2); + if (!regs) + return -ENXIO; + + usbc_base = (u32)ioremap(regs->start, (regs->end - regs->start) + 1); + printk("usbc_base:%x\n", usbc_base); + if (0==strcmp(dev->name, "Mstar-ehci-1")) { + printk("Mstar-ehci-1 H.W init\n"); + titania3_series_start_ehc(utmi_base, usbc_base, uhc_base, 0); + } + + //------------------------------------------- + if (dev->resource[3].flags != IORESOURCE_IRQ) { + pr_debug("resource[3] is not IORESOURCE_IRQ"); + retval = -ENOMEM; + } + hcd = usb_create_hcd(driver, &dev->dev, "mstar"); + if (!hcd) + return -ENOMEM; + hcd->rsrc_start = dev->resource[1].start; + hcd->rsrc_len = dev->resource[1].end - dev->resource[1].start + 1; + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { + pr_debug("request_mem_region failed"); + retval = -EBUSY; + goto err1; + } + + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + if (!hcd->regs) { + pr_debug("ioremap failed"); + retval = -ENOMEM; + goto err2; + } + + ehci = hcd_to_ehci(hcd); + ehci->caps = hcd->regs; + + ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(0, &ehci->caps->hc_capbase)); + + /* cache this readonly data; minimize chip reads */ + ehci->hcs_params = ehci_readl(0, &ehci->caps->hcs_params); + + /* ehci_hcd_init(hcd_to_ehci(hcd)); */ + retval = usb_add_hcd(hcd, dev->resource[3].start, SA_INTERRUPT); + +#if defined(MSTAR_PATCH_USB_HCD) + if (0==strcmp(dev->name, "Mstar-ehci-1")) { + hcd->port_index = 1; + hcd->utmi_base = utmi_base; + hcd->ehc_base = uhc_base; + hcd->usbc_base = usbc_base; + } + hcd->root_port_devnum = 0; + hcd->enum_port_flag = 0; + hcd->rootflag = 0; + hcd->lock_usbreset = SPIN_LOCK_UNLOCKED; +#endif + +#if defined(EHCI_POLLING) + init_MUTEX(&thread_sem); + th = kthread_run(ehci_polling_thread, hcd, "ehci-polling"); + if (IS_ERR(th)) { + printk(KERN_WARNING "Unable to start the ehci-polling thread\n"); + retval = PTR_ERR(th); + goto err2; + } +#endif + + if (retval == 0) + return retval; + +err2: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); +err1: + usb_put_hcd(hcd); + return retval; +} + +/* may be called without controller electrically present */ +/* may be called with controller, bus, and devices active */ + +/** + * usb_ehci_hcd_au1xxx_remove - shutdown processing for Au1xxx-based HCDs + * @dev: USB Host Controller being removed + * Context: !in_interrupt() + * + * Reverses the effect of usb_ehci_hcd_au1xxx_probe(), first invoking + * the HCD's stop() method. It is always called from a thread + * context, normally "rmmod", "apmd", or something similar. + * + */ +void usb_ehci_mstar_remove(struct usb_hcd *hcd, struct platform_device *dev) +{ + usb_remove_hcd(hcd); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); +} + +/*-------------------------------------------------------------------------*/ + +static int ehci_hcd_mstar_drv_probe(struct platform_device *pdev) +{ + struct usb_hcd *hcd = NULL; + int ret; + + pr_debug("In ehci_hcd_mstar_drv_probe\n"); + + if (usb_disabled()) + return -ENODEV; + + /* FIXME we only want one one probe() not two */ + ret = usb_ehci_mstar_probe(&ehci_mstar_hc_driver, &hcd, pdev); + return ret; +} + +static int ehci_hcd_mstar_drv_remove(struct platform_device *pdev) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + + /* FIXME we only want one one remove() not two */ + usb_ehci_mstar_remove(hcd, pdev); + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static struct platform_driver ehci_hcd_mstar_driver = { + .probe = ehci_hcd_mstar_drv_probe, + .remove = ehci_hcd_mstar_drv_remove, + .driver = { + .name = "Mstar-ehci-1", + } +}; + diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-mstar.h b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-mstar.h new file mode 100644 index 0000000000..a9ecff7d6b --- /dev/null +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-mstar.h @@ -0,0 +1,107 @@ + +#ifndef _EHCI_MSTAR_H +#define _EHCI_MSTAR_H + +#include + +#define MSTAR_PATCH_USB_HCD //Benson 2012/09/10 + +#define MSTAR_PATCH_HOTPLUG //tony add for hotplug when read/write device + +#define _MSTAR_USB_BASEADR 0xEC000000 + +#define _MSTAR_UTMI0_BASE IO_ADDRESS(_MSTAR_USB_BASEADR+0x0E00) +#define _MSTAR_UHC0_BASE IO_ADDRESS(_MSTAR_USB_BASEADR+0x1200) +#define _MSTAR_USBC0_BASE IO_ADDRESS(_MSTAR_USB_BASEADR+0x1400) + +/* 20120411 PM_TOP base for read chip ID */ +#if defined(CONFIG_MSTAR_AMBER7) +#define _MSTAR_PM_TOP_BASE (0xbf000000+(0x1E00*2)) +#endif + +#define DISABLE 0 +#define ENABLE 1 + +#define BIT0 0x01 +#define BIT1 0x02 +#define BIT2 0x04 +#define BIT3 0x08 +#define BIT4 0x10 +#define BIT5 0x20 +#define BIT6 0x40 +#define BIT7 0x80 + + +#define _USB_T3_WBTIMEOUT_PATCH 1 + + +#if defined(CONFIG_MSTAR_TITANIA8) || \ + defined(CONFIG_MSTAR_TITANIA9) || \ + defined(CONFIG_MSTAR_JANUS2) || \ + defined(CONFIG_MSTAR_TITANIA11) || \ + defined(CONFIG_MSTAR_TITANIA12) || \ + defined(CONFIG_MSTAR_TITANIA13) || \ + defined(CONFIG_MSTAR_AMBER1) || \ + defined(CONFIG_MSTAR_AMBER6) || \ + defined(CONFIG_MSTAR_AMBER7) || \ + defined(CONFIG_MSTAR_AMETHYST) || \ + defined(CONFIG_MSTAR_AMBER5) || \ + defined(CONFIG_MSTAR_EMERALD) +#define _USB_128_ALIGMENT 1 +#else +#define _USB_128_ALIGMENT 0 +#endif + +//Colin, 20120118, new chip doesn't need this patch. +#if 0 + #define _USB_SHORT_PACKET_LOSE_INT_PATCH 1 +#else + #define _USB_SHORT_PACKET_LOSE_INT_PATCH 0 +#endif + +//mdata patch default open for all old projects +#if 0 +#define _USB_SPLIT_MDATA_BLOCKING_PATCH 0 +#else +#define _USB_SPLIT_MDATA_BLOCKING_PATCH 1 +#endif + +#if defined(CONFIG_MSTAR_AMETHYST) || \ + defined(CONFIG_MSTAR_JANUS2) || \ + defined(CONFIG_MSTAR_AMBER7) || \ + defined(CONFIG_MSTAR_AMBER5) ||\ + defined(CONFIG_MSTAR_EMERALD) +#define ENABLE_LS_CROSS_POINT_ECO +#endif + +#define ENABLE_PWR_NOISE_ECO + +#if defined(CONFIG_MSTAR_AMBER7) || \ + defined(CONFIG_MSTAR_AMBER5) || \ + defined(CONFIG_MSTAR_EMERALD) +#define ENABLE_TX_RX_RESET_CLK_GATING_ECO +#endif + +#if defined(CONFIG_MSTAR_AMBER5) +#define ENABLE_LOSS_SHORT_PACKET_INTR_ECO +#endif + +#if defined(CONFIG_MSTAR_AMBER5) +#define ENABLE_BABBLE_ECO +#endif + +//----------------------------------------- +// Titania3_series_start_ehc flag: +// Use low word as flag +#define EHCFLAG_NONE 0x0 +#define EHCFLAG_DPDM_SWAP 0x1 +#define EHCFLAG_TESTPKG 0x2 +#define EHCFLAG_DOUBLE_DATARATE 0x4 +// Use high word as data +#define EHCFLAG_DDR_MASK 0xF0000000 +#define EHCFLAG_DDR_x15 0x10000000 //480MHz x1.5 +#define EHCFLAG_DDR_x18 0x20000000 //480MHz x1.8 +//----------------------------------------- + +#endif /* _EHCI_MSTAR_H */ + diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-q.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-q.c index 2e49de820b..43c7de559d 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-q.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-q.c @@ -38,6 +38,10 @@ * buffer low/full speed data so the host collects it at high speed. */ +#if _USB_T3_WBTIMEOUT_PATCH +extern void chip_flush_memory(void); +#endif + /*-------------------------------------------------------------------------*/ /* fill a qtd, returning how much of the buffer we were able to queue up */ @@ -334,9 +338,39 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) token = hc32_to_cpu(ehci, qtd->hw_token); /* always clean up qtds the hc de-activated */ +#if defined(MSTAR_PATCH_USB_HCD) +retry_xacterr: +#endif if ((token & QTD_STS_ACTIVE) == 0) { - + /* on STALL, error, and short reads this urb must + * complete and all its qtds must be recycled. + */ if ((token & QTD_STS_HALT) != 0) { +#if defined(MSTAR_PATCH_USB_HCD) + /* retry transaction errors until we + * reach the software xacterr limit + */ + if ((token & QTD_STS_XACT) + && (QTD_CERR(token) == 0) + && (--qh->xacterrs > 0) + && (!urb->unlinked)) { + ehci_dbg (ehci, "detected XactErr len %d/%d retry %d\n", + qtd->length - QTD_LENGTH(token), qtd->length, + QH_XACTERR_MAX - qh->xacterrs); + + /* reset the token in the qtd and the + * qh overlay (which still contains + * the qtd) so that we pick up from + * where we left off + */ + token &= ~QTD_STS_HALT; + token |= QTD_STS_ACTIVE | (EHCI_TUNE_CERR << 10); + qtd->hw_token = cpu_to_hc32(ehci, token); + wmb(); + qh->hw_token = cpu_to_hc32(ehci, token); + goto retry_xacterr; + } +#endif stopped = 1; /* magic dummy for some short reads; qh won't advance. @@ -348,7 +382,30 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) stopped = 1; goto halt; } +#if defined(MSTAR_PATCH_USB_HCD) +#if _USB_SPLIT_MDATA_BLOCKING_PATCH + /* SplitXstate = 1 in qTD + * hub addr + * split complite mask + * Interrupt IN transaction + */ + else if((token & QTD_STS_STS) + && (hc32_to_cpu(ehci, qh->hw_info2) & QH_HUBADDR) + && (hc32_to_cpu(ehci, qh->hw_info2) & QH_CMASK) + && usb_pipeint(urb->pipe) && usb_pipein(urb->pipe) + && ((urb->dev->speed == USB_SPEED_LOW) + || (urb->dev->speed == USB_SPEED_FULL))) { + u32 hw_token; + + hw_token = hc32_to_cpu(ehci, qh->hw_token); + hw_token ^= QTD_TOGGLE; + hw_token &= ~QTD_STS_STS; + wmb (); + qh->hw_token = cpu_to_hc32(ehci, hw_token); + } +#endif +#endif /* stop scanning when we reach qtds the hc is using */ } else if (likely (!stopped && HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) { @@ -409,6 +466,10 @@ halt: } list_del (&qtd->qtd_list); last = qtd; +#if defined(MSTAR_PATCH_USB_HCD) + /* reinit the xacterr counter for the next qtd */ + qh->xacterrs = QH_XACTERR_MAX; +#endif } /* last urb's completion might still need calling */ @@ -545,7 +606,15 @@ qh_urb_transaction ( */ for (;;) { int this_qtd_len; - +#if defined(MSTAR_PATCH_USB_HCD) +#if _USB_SHORT_PACKET_LOSE_INT_PATCH + if (is_input && usb_pipebulk (urb->pipe) + && (!(urb->transfer_flags & URB_NO_INTERRUPT)) + && (!(urb->transfer_flags & URB_SHORT_NOT_OK))) { + token |= cpu_to_hc32(ehci, QTD_IOC); + } +#endif +#endif this_qtd_len = qtd_fill(ehci, qtd, buf, len, token, maxpacket); len -= this_qtd_len; buf += this_qtd_len; @@ -820,6 +889,9 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) head->qh_next.qh = qh; head->hw_next = dma; +#if defined(MSTAR_PATCH_USB_HCD) + qh->xacterrs = QH_XACTERR_MAX; +#endif qh->qh_state = QH_STATE_LINKED; /* qtd completions reported later by interrupt */ } @@ -960,6 +1032,10 @@ submit_async ( */ if (likely (qh->qh_state == QH_STATE_IDLE)) qh_link_async (ehci, qh_get (qh)); + +#if _USB_T3_WBTIMEOUT_PATCH + chip_flush_memory(); +#endif done: spin_unlock_irqrestore (&ehci->lock, flags); if (unlikely (qh == NULL)) diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-sched.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-sched.c index 8a8e08a51b..2c665dbde2 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-sched.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-sched.c @@ -35,6 +35,9 @@ */ static int ehci_get_frame (struct usb_hcd *hcd); +#if _USB_T3_WBTIMEOUT_PATCH +extern void chip_flush_memory(void); +#endif /*-------------------------------------------------------------------------*/ @@ -840,7 +843,9 @@ static int intr_submit ( /* ... update usbfs periodic stats */ ehci_to_hcd(ehci)->self.bandwidth_int_reqs++; - +#if _USB_T3_WBTIMEOUT_PATCH + chip_flush_memory(); +#endif done: if (unlikely(status)) usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); @@ -886,7 +891,9 @@ iso_stream_init ( unsigned epnum, maxp; int is_input; long bandwidth; - +#if defined(MSTAR_PATCH_USB_HCD) + struct usb_hcd *hcd = ehci_to_hcd(ehci); +#endif /* * this might be a "high bandwidth" highspeed endpoint, * as encoded in the ep descriptor's wMaxPacket field @@ -927,10 +934,16 @@ iso_stream_init ( int hs_transfers; addr = dev->ttport << 24; +#if defined(MSTAR_PATCH_USB_HCD) + if (dev->tt) { +#endif if (!ehci_is_TDI(ehci) || (dev->tt->hub != ehci_to_hcd(ehci)->self.root_hub)) addr |= dev->tt->hub->devnum << 16; +#if defined(MSTAR_PATCH_USB_HCD) + } +#endif addr |= epnum << 8; addr |= dev->devnum; stream->usecs = HS_USECS_ISO (maxp); @@ -956,6 +969,21 @@ iso_stream_init ( /* stream->splits gets created from raw_mask later */ stream->address = cpu_to_hc32(ehci, addr); + +#if defined(MSTAR_PATCH_USB_HCD) + //Colin, patch for not real split-transaction mode + if (((readb((void*)(hcd->ehc_base+0x41*2-1)) & 0x06) != 0x04) + && (dev->speed != USB_SPEED_HIGH)) { + unsigned multi = 1; + + maxp = max_packet(maxp); + buf1 |= maxp; + + stream->buf0 = cpu_to_hc32(ehci, (epnum << 8) | dev->devnum); + stream->buf1 = cpu_to_hc32(ehci, buf1); + stream->buf2 = cpu_to_hc32(ehci, multi); + } +#endif } stream->bandwidth = bandwidth; @@ -969,6 +997,9 @@ iso_stream_init ( static void iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream) { +#if defined(MSTAR_PATCH_USB_HCD) + struct usb_hcd *hcd = ehci_to_hcd(ehci); +#endif stream->refcount--; /* free whenever just a dev->ep reference remains. @@ -994,12 +1025,26 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream) dma_pool_free (ehci->itd_pool, itd, itd->itd_dma); } else { +#if defined(MSTAR_PATCH_USB_HCD) + /* Colin, patch for not real split-transaction mode */ + if (((readb((void*)(hcd->ehc_base+0x41*2-1)) & 0x06) != 0x04) + && (stream->udev->speed != USB_SPEED_HIGH)) { + struct ehci_itd *itd; + + itd = list_entry (entry, struct ehci_itd, itd_list); + dma_pool_free (ehci->itd_pool, itd, itd->itd_dma); + } else { +#endif + struct ehci_sitd *sitd; sitd = list_entry (entry, struct ehci_sitd, sitd_list); dma_pool_free (ehci->sitd_pool, sitd, sitd->sitd_dma); +#if defined(MSTAR_PATCH_USB_HCD) + } +#endif } } @@ -1157,17 +1202,28 @@ itd_urb_transaction ( unsigned num_itds; struct ehci_iso_sched *sched; unsigned long flags; - +#if defined(MSTAR_PATCH_USB_HCD) + struct usb_hcd *hcd = ehci_to_hcd(ehci); +#endif sched = iso_sched_alloc (urb->number_of_packets, mem_flags); if (unlikely (sched == NULL)) return -ENOMEM; itd_sched_init(ehci, sched, stream, urb); - +#if defined(MSTAR_PATCH_USB_HCD) + //Colin, patch for not real split-transaction mode + if (((readb((void*)(hcd->ehc_base+0x41*2-1)) & 0x06) != 0x04) + && (urb->dev->speed != USB_SPEED_HIGH)) { + num_itds = urb->number_of_packets; + } else { +#endif if (urb->interval < 8) num_itds = 1 + (sched->span + 7) / 8; else num_itds = urb->number_of_packets; +#if defined(MSTAR_PATCH_USB_HCD) + } +#endif /* allocate/init ITDs */ spin_lock_irqsave (&ehci->lock, flags); @@ -1502,7 +1558,15 @@ itd_link_urb ( unsigned next_uframe, uframe, frame; struct ehci_iso_sched *iso_sched = urb->hcpriv; struct ehci_itd *itd; +#if defined(MSTAR_PATCH_USB_HCD) + struct usb_hcd *hcd = ehci_to_hcd(ehci); + //Colin, patch for not real split-transaction mode + if (((readb((void*)(hcd->ehc_base+0x41*2-1)) & 0x06) != 0x04) + && (urb->dev->speed != USB_SPEED_HIGH)) + next_uframe = stream->next_uframe; + else +#endif next_uframe = stream->next_uframe % mod; if (unlikely (list_empty(&stream->td_list))) { @@ -1533,7 +1597,21 @@ itd_link_urb ( itd->urb = usb_get_urb (urb); itd_init (ehci, stream, itd); } +#if defined(MSTAR_PATCH_USB_HCD) + //Colin, patch for not real split-transaction mode + if (((readb((void*)(hcd->ehc_base+0x41*2-1)) & 0x06) != 0x04) + && (urb->dev->speed != USB_SPEED_HIGH)) { + uframe = 0; //always is transaction 0 of itd + frame = next_uframe >> 3; + itd_patch(ehci, itd, iso_sched, packet, uframe); + itd_link (ehci, frame % ehci->periodic_size, itd); + itd = NULL; + next_uframe += stream->interval << 3; + stream->depth += stream->interval << 3; + packet++; + } else { +#endif uframe = next_uframe & 0x07; frame = next_uframe >> 3; @@ -1551,6 +1629,14 @@ itd_link_urb ( itd = NULL; } } +#if defined(MSTAR_PATCH_USB_HCD) + } + //Colin, patch for not real split-transaction mode + if (((readb((void*)(hcd->ehc_base+0x41*2-1)) & 0x06) != 0x04) + && (urb->dev->speed != USB_SPEED_HIGH)) + stream->next_uframe = next_uframe % mod; + else +#endif stream->next_uframe = next_uframe; /* don't need that schedule data any more */ @@ -1588,7 +1674,9 @@ itd_complete ( struct ehci_iso_stream *stream = itd->stream; struct usb_device *dev; unsigned retval = false; - +#if defined(MSTAR_PATCH_USB_HCD) + struct usb_hcd *hcd = ehci_to_hcd(ehci); +#endif /* for each uframe with a packet */ for (uframe = 0; uframe < 8; uframe++) { if (likely (itd->index[uframe] == -1)) @@ -1598,6 +1686,13 @@ itd_complete ( t = hc32_to_cpup(ehci, &itd->hw_transaction [uframe]); itd->hw_transaction [uframe] = 0; +#if defined(MSTAR_PATCH_USB_HCD) + //Colin, patch for not real split-transaction mode + if (((readb((void*)(hcd->ehc_base+0x41*2-1)) & 0x06) != 0x04) + && (urb->dev->speed != USB_SPEED_HIGH)) + stream->depth -= stream->interval << 3; + else +#endif stream->depth -= stream->interval; /* report transfer status */ @@ -1617,7 +1712,12 @@ itd_complete ( desc->actual_length = EHCI_ITD_LENGTH (t); } else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) { desc->status = 0; +#if defined(MSTAR_PATCH_USB_HCD) + //Our EHCI send back left data which haven't recved + desc->actual_length = desc->length - EHCI_ITD_LENGTH (t); +#else desc->actual_length = EHCI_ITD_LENGTH (t); +#endif } } @@ -1712,6 +1812,9 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); else usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); +#if _USB_T3_WBTIMEOUT_PATCH + chip_flush_memory(); +#endif done_not_linked: spin_unlock_irqrestore (&ehci->lock, flags); diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci.h b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci.h index bf92d209a1..6dde61eee1 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci.h +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci.h @@ -77,7 +77,11 @@ struct ehci_hcd { /* one per controller */ unsigned scanning : 1; /* periodic schedule support */ +#if defined(CONFIG_CHIP_MSE500) +#define DEFAULT_I_TDPS 256 /* some HCs can do less */ +#else #define DEFAULT_I_TDPS 1024 /* some HCs can do less */ +#endif unsigned periodic_size; __hc32 *periodic; /* hw periodic table */ dma_addr_t periodic_dma; @@ -278,6 +282,50 @@ struct ehci_regs { /* ASYNCLISTADDR: offset 0x18 */ u32 async_next; /* address of next async queue head */ +#if defined(CONFIG_CHIP_MSE500) + /* Reserved: offset 0x1C */ + u32 reserved [1]; + + /* PORTSC: offset 0x20 */ + u32 port_status [1]; /* up to N_PORTS */ +/* 31:23 reserved */ +#define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */ +#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */ +#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */ +/* 19:16 for port testing */ +#define PORT_LED_OFF (0<<14) +#define PORT_LED_AMBER (1<<14) +#define PORT_LED_GREEN (2<<14) +#define PORT_LED_MASK (3<<14) +#define PORT_OWNER (1<<13) /* true: companion hc owns this port */ +#define PORT_POWER (1<<12) /* true: has power (see PPC) */ +#define PORT_USB11(x) (((x)&(3<<10))==(1<<10)) /* USB 1.1 device */ +/* 11:10 for detecting lowspeed devices (reset vs release ownership) */ +/* 9 reserved */ +#define PORT_RESET (1<<8) /* reset port */ +#define PORT_SUSPEND (1<<7) /* suspend port */ +#define PORT_RESUME (1<<6) /* resume it */ +#define PORT_OCC (1<<5) /* over current change */ +#define PORT_OC (1<<4) /* over current active */ +#define PORT_PEC (1<<3) /* port enable change */ +#define PORT_PE (1<<2) /* port enable */ +#define PORT_CSC (1<<1) /* connect status change */ +#define PORT_CONNECT (1<<0) /* device connected */ +#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) + u32 hcmisc ; + u32 reserved1 [2]; + /* offset 0x30 */ + u32 bmcs; + u32 busmonintsts; + u32 busmoninten; + + /* CONFIGFLAG: offset 0x40 */ + u32 configured_flag; +#define FLAG_CF (1<<0) /* true: we'll support "high speed" */ + + /* reserved: offset 0x44 */ + u32 reserved3 [1]; +#else u32 reserved [9]; /* CONFIGFLAG: offset 0x40 */ @@ -310,6 +358,8 @@ struct ehci_regs { #define PORT_CSC (1<<1) /* connect status change */ #define PORT_CONNECT (1<<0) /* device connected */ #define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) +#endif + } __attribute__ ((packed)); #define USBMODE 0x68 /* USB Device mode */ @@ -386,7 +436,11 @@ struct ehci_qtd { struct list_head qtd_list; /* sw qtd list */ struct urb *urb; /* qtd's urb */ size_t length; /* length of buffer */ +#if _USB_128_ALIGMENT +} __attribute__ ((aligned (128))); +#else } __attribute__ ((aligned (32))); +#endif /* mask NakCnt+T in qh->hw_alt_next */ #define QTD_MASK(ehci) cpu_to_hc32 (ehci, ~0x1f) @@ -489,6 +543,10 @@ struct ehci_qh { #define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */ #define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ +#if defined(CONFIG_CHIP_MSE500) + u8 xacterrs; /* XactErr retry counter */ +#define QH_XACTERR_MAX 32 /* XactErr retry limit */ +#endif /* periodic schedule info */ u8 usecs; /* intr bandwidth */ u8 gap_uf; /* uframes split/csplit gap */ @@ -498,8 +556,11 @@ struct ehci_qh { unsigned short start; /* where polling starts */ #define NO_FRAME ((unsigned short)~0) /* pick new start */ struct usb_device *dev; /* access to TT */ +#if _USB_128_ALIGMENT +} __attribute__ ((aligned (128))); +#else } __attribute__ ((aligned (32))); - +#endif /*-------------------------------------------------------------------------*/ /* description of one iso transaction (up to 3 KB data if highspeed) */ @@ -602,8 +663,11 @@ struct ehci_itd { unsigned frame; /* where scheduled */ unsigned pg; unsigned index[8]; /* in urb->iso_frame_desc */ +#if _USB_128_ALIGMENT +} __attribute__ ((aligned (128))); +#else } __attribute__ ((aligned (32))); - +#endif /*-------------------------------------------------------------------------*/ /* @@ -757,9 +821,16 @@ static inline unsigned int ehci_readl(const struct ehci_hcd *ehci, return ehci_big_endian_mmio(ehci) ? readl_be(regs) : readl(regs); +#else +#if defined (CONFIG_CHIP_MSE500) + regs = (u32 *)( ((unsigned int)regs & 0xffffff00) + + (((unsigned int)regs & 0x000000ff)*2) ); + return (readl((void*)(unsigned int)regs) & 0x0000ffff) + |((readl((void*)((unsigned int)regs+4))<<16) & 0xffff0000); #else return readl(regs); #endif +#endif } static inline void ehci_writel(const struct ehci_hcd *ehci, @@ -769,9 +840,15 @@ static inline void ehci_writel(const struct ehci_hcd *ehci, ehci_big_endian_mmio(ehci) ? writel_be(val, regs) : writel(val, regs); +#else +#if defined (CONFIG_CHIP_MSE500) + regs = (u32 *)(((unsigned int)regs & 0xffffff00) + (((unsigned int)regs & 0x000000ff)*2)) ; + writel(val & 0x0000ffff,(void*)regs) ; + writel(((val>>16) & 0x0000ffff),(void*)((unsigned int)regs+4)) ; #else writel(val, regs); #endif +#endif } /*-------------------------------------------------------------------------*/ diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/mon/mon_bin.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/mon/mon_bin.c index 1774ba5c4c..ebb184dc63 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/mon/mon_bin.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/mon/mon_bin.c @@ -19,6 +19,7 @@ #include #include "usb_mon.h" +#include "../host/ehci-mstar.h" /* * Defined by USB 2.0 clause 9.3, table 9.2. @@ -1138,7 +1139,11 @@ static int mon_alloc_buff(struct mon_pgmap *map, int npages) return -ENOMEM; } map[n].ptr = (unsigned char *) vaddr; +#if defined(MSTAR_PATCH_USB_HCD) + map[n].pg = virt_to_page((volatile const void *)vaddr); +#else map[n].pg = virt_to_page(vaddr); +#endif } return 0; } diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/serial/ftdi_sio.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/serial/ftdi_sio.c index af2bd47d1a..178a952123 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/serial/ftdi_sio.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/serial/ftdi_sio.c @@ -367,6 +367,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_OOCDLINK_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, + { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/serial/ftdi_sio.h b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/serial/ftdi_sio.h index 0e1c569b26..13eb93f21a 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/serial/ftdi_sio.h +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/serial/ftdi_sio.h @@ -586,6 +586,13 @@ #define RATOC_VENDOR_ID 0x0584 #define RATOC_PRODUCT_ID_USB60F 0xb020 +/* + * JETI SPECTROMETER SPECBOS 1201 + * http://www.jeti.com/products/sys/scb/scb1201.php + */ +#define JETI_VID 0x0c6c +#define JETI_SPC1201_PID 0x04b2 + /* * BmRequestType: 1100 0000b * bRequest: FTDI_E2_READ diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/storage/scsiglue.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/storage/scsiglue.c index 8c1e2954f3..38b93ecbfa 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/storage/scsiglue.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/storage/scsiglue.c @@ -60,6 +60,8 @@ #include "debug.h" #include "transport.h" #include "protocol.h" +#include "../host/ehci-mstar.h" + /*********************************************************************** * Host functions @@ -89,6 +91,10 @@ static int slave_alloc (struct scsi_device *sdev) * mask. Guaranteeing proper alignment of the first buffer will * have the desired effect because, except at the beginning and * the end, scatter-gather buffers follow page boundaries. */ +#if defined(MSTAR_PATCH_HOTPLUG) && defined(MSTAR_PATCH_USB_HCD) + //tony if disconnect, update will cause kernel panic + if(us->pusb_dev->devnum1==us->pusb_dev->devnum) +#endif blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1)); /* @@ -122,7 +128,20 @@ static int slave_configure(struct scsi_device *sdev) if (sdev->request_queue->max_sectors > max_sectors) blk_queue_max_sectors(sdev->request_queue, max_sectors); +#if defined(MSTAR_PATCH_HOTPLUG) && defined(MSTAR_PATCH_USB_HCD) + } else if (sdev->type == TYPE_TAPE) { + /* Tapes need much higher max_sector limits, so just + * raise it to the maximum possible (4 GB / 512) and + * let the queue segment size sort out the real limit. + */ + blk_queue_max_sectors(sdev->request_queue, 0x7FFFFF); + } +#ifdef CONFIG_HIGHMEM + blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_HIGH); +#endif +#else } +#endif /* We can't put these settings in slave_alloc() because that gets * called before the device type is known. Consequently these diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/storage/unusual_devs.h b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/storage/unusual_devs.h index f1d14c95b5..f35d21875f 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/storage/unusual_devs.h +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/storage/unusual_devs.h @@ -1164,6 +1164,15 @@ UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0xffff, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), +/* Reported by Rauch Wolke + * and augmented by binbin (Bugzilla #12882) + */ +UNUSUAL_DEV( 0x07c4, 0xa4a5, 0x0000, 0xffff, + "Simple Tech/Datafab", + "CF+SM Reader", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE | US_FL_MAX_SECTORS_64 ), + /* Casio QV 2x00/3x00/4000/8000 digital still cameras are not conformant * to the USB storage specification in two ways: * - They tell us they are using transport protocol CBI. In reality they @@ -1729,6 +1738,21 @@ UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_CAPACITY_HEURISTICS), +/*Colin, 090317, for Transcend 16GB JF V85, wrong residual*/ +UNUSUAL_DEV( 0x058F, 0x6387, 0x0000, 0x9999, + "JetFlash", + "Mass Storage Device", + US_SC_SCSI, US_PR_BULK, NULL, + US_FL_IGNORE_RESIDUE ), + +/* Reported by Dimong huang */ + +UNUSUAL_DEV( 0x0dd8, 0x1414, 0x0100, 0x0100, + "Netac", + "USB Flash Disk", + US_SC_SCSI, US_PR_BULK, NULL, + US_FL_MAX_SECTORS_64 ), + /* Control/Bulk transport for all SubClass values */ USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR), USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR), diff --git a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/storage/usb.c b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/storage/usb.c index ac6114eea0..c10be0b0fb 100644 --- a/cleopatre/linux-2.6.25.10-spc300/drivers/usb/storage/usb.c +++ b/cleopatre/linux-2.6.25.10-spc300/drivers/usb/storage/usb.c @@ -907,6 +907,10 @@ static int usb_stor_scan_thread(void * __us) if (delay_use > 0) { printk(KERN_DEBUG "usb-storage: waiting for device " "to settle before scanning\n"); +#if defined (CONFIG_CHIP_MSE500) + //tony add for reducing usb device connect time + delay_use= 0; +#endif wait_event_freezable_timeout(us->delay_wait, test_bit(US_FLIDX_DISCONNECTING, &us->flags), delay_use * HZ); diff --git a/cleopatre/linux-2.6.25.10-spc300/include/linux/usb.h b/cleopatre/linux-2.6.25.10-spc300/include/linux/usb.h index 583e0481df..b43f83e119 100644 --- a/cleopatre/linux-2.6.25.10-spc300/include/linux/usb.h +++ b/cleopatre/linux-2.6.25.10-spc300/include/linux/usb.h @@ -356,6 +356,10 @@ struct usb_tt; */ struct usb_device { int devnum; /* Address on USB bus */ +#ifdef CONFIG_CHIP_MSE500 + int devnum1; /* tony for hotplug check, + * MSTAR_PATCH_HOTPLUG && MSTAR_PATCH_USB_HCD */ +#endif char devpath [16]; /* Use in messages: /port/port/... */ enum usb_device_state state; /* configured, not attached, etc */ enum usb_device_speed speed; /* high/full/low (or error) */ diff --git a/cleopatre/linux-2.6.25.10-spc300/include/linux/usb/quirks.h b/cleopatre/linux-2.6.25.10-spc300/include/linux/usb/quirks.h index 1f999ec8d0..9aa642cbf3 100644 --- a/cleopatre/linux-2.6.25.10-spc300/include/linux/usb/quirks.h +++ b/cleopatre/linux-2.6.25.10-spc300/include/linux/usb/quirks.h @@ -3,6 +3,8 @@ * Only quirks that affect the whole device, not an interface, * belong here. */ +#ifndef __LINUX_USB_QUIRKS_H +#define __LINUX_USB_QUIRKS_H /* string descriptors must not be fetched using a 255-byte read */ #define USB_QUIRK_STRING_FETCH_255 0x00000001 @@ -12,3 +14,8 @@ /* device can't handle Set-Interface requests */ #define USB_QUIRK_NO_SET_INTF 0x00000004 + +/* device can't handle its Configuration or Interface strings */ +#define USB_QUIRK_CONFIG_INTF_STRINGS 0x00000008 +#endif /* __LINUX_USB_QUIRKS_H */ + -- cgit v1.2.3