summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cleopatre/buildroot/target/device/Spidcom/targets/msk500/linux26.config.part110
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/board-mse500.c3
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.c55
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.h7
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300.c12
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/Kconfig1
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/buffer.c17
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/hcd.c12
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/hcd.h20
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/hub.c390
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/message.c5
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/quirks.c3
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/sysfs.c6
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/core/urb.c26
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-hcd.c35
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-hub.c22
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-mem.c20
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-mstar.c518
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-mstar.h107
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-q.c80
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci-sched.c113
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/host/ehci.h81
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/mon/mon_bin.c5
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/serial/ftdi_sio.c1
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/serial/ftdi_sio.h7
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/storage/scsiglue.c19
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/storage/unusual_devs.h24
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/drivers/usb/storage/usb.c4
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/include/linux/usb.h4
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/include/linux/usb/quirks.h7
-rw-r--r--common/include/asm/arch/ips/hardware/arm_apb.h2
-rw-r--r--common/include/asm/arch/ips/hardware/bus_sys.h9
-rw-r--r--common/include/asm/arch/irqs.h2
33 files changed, 1710 insertions, 17 deletions
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 <linux/dmapool.h>
#include <linux/usb.h>
#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 <linux/rwsem.h>
+#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 <linux/kernel.h>
#include <linux/string.h>
#include <linux/usb.h>
+#include <linux/usb/quirks.h>
#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 <linux/usb.h>
#include <linux/wait.h>
#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 <linux/platform_device.h>
+#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 <linux/kthread.h>
+ 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 <asm/io.h>
+
+#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
/*-------------------------------------------------------------------------*/
/*
@@ -758,8 +822,15 @@ static inline unsigned int ehci_readl(const struct ehci_hcd *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,
@@ -770,8 +841,14 @@ static inline void ehci_writel(const struct ehci_hcd *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 <asm/uaccess.h>
#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
@@ -587,6 +587,13 @@
#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
* wValue: 0
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 <rauchwolke@gmx.net>
+ * and augmented by binbin <binbinsh@gmail.com> (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 <Dimong.huang@mstarsemil.com> */
+
+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 */
+
diff --git a/common/include/asm/arch/ips/hardware/arm_apb.h b/common/include/asm/arch/ips/hardware/arm_apb.h
index ca9eb5bf3a..04d9c8e45d 100644
--- a/common/include/asm/arch/ips/hardware/arm_apb.h
+++ b/common/include/asm/arch/ips/hardware/arm_apb.h
@@ -46,6 +46,8 @@
#define ARM_GPIO_BASE (ARM_APB_BASE+0x60000)
#include "arm_gpio.h"
+#define ARM_BRG_BASE (ARM_APB_BASE+0x8000000)
+
#ifdef CONFIG_CHIP_FEATURE_EXTRA_TIMERS
#define ARM_TIMER3_BASE (ARM_APB_BASE+0x70000)
diff --git a/common/include/asm/arch/ips/hardware/bus_sys.h b/common/include/asm/arch/ips/hardware/bus_sys.h
index 1944576b29..e4a04349ec 100644
--- a/common/include/asm/arch/ips/hardware/bus_sys.h
+++ b/common/include/asm/arch/ips/hardware/bus_sys.h
@@ -73,6 +73,15 @@
#include "msepll.h"
#endif
+#if defined(CONFIG_USB_EHCI_HCD)
+#define USB_UTMI_BASE (0xEC000E00)
+#define USB_UHC_BASE (0xEC001200)
+#define USB_USBC_BASE (0xEC001400)
+#endif
+
+#define TOPREG_BASE (0xEC001A00)
+
+
#if defined (CONFIG_CHIP_FEATURE_IOMUX)
#define IOMUX_OFFSET (0x1C00)
#define IOMUX_BASE (EXT_REG_BANK_BASE + IOMUX_OFFSET)
diff --git a/common/include/asm/arch/irqs.h b/common/include/asm/arch/irqs.h
index ee7dac7286..81d7395eae 100644
--- a/common/include/asm/arch/irqs.h
+++ b/common/include/asm/arch/irqs.h
@@ -101,6 +101,8 @@
#define INT_TIMER_4 33
#define INT_ETH2 34
+#define INT_UHC 44
+
#define INTMASK_TIMER_1 (1 << INT_TIMER_1)
#define INTMASK_TIMER_2 (1 << INT_TIMER_2)
#define INTMASK_GPIO (1 << INT_GPIO)