diff options
Diffstat (limited to 'ANDROID_3.4.5/drivers/usb/host')
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/host/Kconfig | 15 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/host/ehci-hcd.c | 51 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/host/ehci-hub.c | 337 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/host/ehci-pci.c | 29 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/host/ehci-q.c | 7 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/host/ehci-sched.c | 7 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/host/ehci.h | 23 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/host/pci-quirks.c | 9 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/host/uhci-hcd.c | 9 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/host/uhci-hub.c | 11 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/usb/host/uhci-pci.c | 26 |
11 files changed, 490 insertions, 34 deletions
diff --git a/ANDROID_3.4.5/drivers/usb/host/Kconfig b/ANDROID_3.4.5/drivers/usb/host/Kconfig index f788eb86..302bae2a 100644 --- a/ANDROID_3.4.5/drivers/usb/host/Kconfig +++ b/ANDROID_3.4.5/drivers/usb/host/Kconfig @@ -63,6 +63,21 @@ config USB_EHCI_HCD To compile this driver as a module, choose M here: the module will be called ehci-hcd. +#CharlesTu, for test mode # +config USB_EHCI_EHSET + bool "Embedded High-speed Host Electrical Test Support (EXPERIMENTAL)" + depends on USB_EHCI_HCD + default y + ---help--- + This option is only used if you are developing firmware for + an embedded device with a Hi-speed USB Host or OTG port. + + If you say Y here, software support for the Embedded High-speed + Host Electrical Tests will be added to the EHCI driver. This is + one of the tests performed during High-speed USB Host certification + testing. + + If you are at all unsure then say N here. config USB_EHCI_ROOT_HUB_TT bool "Root Hub Transaction Translators" depends on USB_EHCI_HCD diff --git a/ANDROID_3.4.5/drivers/usb/host/ehci-hcd.c b/ANDROID_3.4.5/drivers/usb/host/ehci-hcd.c index bb73df65..dabd379f 100644 --- a/ANDROID_3.4.5/drivers/usb/host/ehci-hcd.c +++ b/ANDROID_3.4.5/drivers/usb/host/ehci-hcd.c @@ -130,6 +130,10 @@ MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us"); /*-------------------------------------------------------------------------*/ +extern unsigned int usb_storage_id; +extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); +unsigned int usb_param[2] = {0xff}; + static void timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action) { @@ -599,6 +603,14 @@ static void ehci_stop (struct usb_hcd *hcd) ehci_readl(ehci, &ehci->regs->status)); } +int env_mos_gpio; +unsigned int env_active; +unsigned int env_port; +unsigned int env_bitmap; +unsigned int env_ctraddr; +unsigned int env_ocaddr; +unsigned int env_odaddr; + /* one-time init, only for memory state */ static int ehci_init(struct usb_hcd *hcd) { @@ -607,7 +619,14 @@ static int ehci_init(struct usb_hcd *hcd) int retval; u32 hcc_params; struct ehci_qh_hw *hw; - + char usb_env_name[] = "wmt.usb.param"; + char usb_env_val[20] = "0"; + int varlen = 20; + + char usb_resume_env_name[] = "wmt.gpo.usb"; + char usb_resume_env_val[80] = "0"; + int varlen_resume = 80; + spin_lock_init(&ehci->lock); /* @@ -720,7 +739,37 @@ static int ehci_init(struct usb_hcd *hcd) temp |= hird << 24; } ehci->command = temp; + + if(wmt_getsyspara(usb_env_name, usb_env_val, &varlen) == 0) { + sscanf(usb_env_val,"%X:%X", &usb_param[0],&usb_param[1]); + //printk("usb_param[0] =%x ,usb_param[1]=%x \n",usb_param[0],usb_param[1]); + if (usb_param[0] & 0x01) { + if(usb_param[1] <= 0x03 ) { + usb_storage_id = usb_param[1]+1; + //printk("usb_storage_id =%x , it should be small than or equal 4 .\n",usb_storage_id); + } else { + usb_storage_id = 2;// default port B + } + } else { + usb_storage_id=0; //disable + } + } + + if(wmt_getsyspara(usb_resume_env_name, usb_resume_env_val, &varlen_resume) == 0) { + sscanf(usb_resume_env_val,"%d:%X:%X:%X:%X:%X", &env_mos_gpio,&env_active,&env_bitmap,&env_ctraddr,&env_ocaddr,&env_odaddr); + + if (env_active) { + env_port = (env_active >> 4); + env_active &= 0x1; + env_ctraddr = ((env_ctraddr & 0xffffff) | 0xfe000000); + env_ocaddr = ((env_ocaddr & 0xffffff) | 0xfe000000); + env_odaddr = ((env_odaddr & 0xffffff) | 0xfe000000); + } + } else + env_active = 0; + printk("env_mos_gpio=%d env_active =%x ,env_port=%x env_bitmap=%x env_ctraddr=%x env_ocaddr=%x env_odaddr=%x \n",env_mos_gpio,env_active,env_port,env_bitmap,env_ctraddr,env_ocaddr,env_odaddr); + /* Accept arbitrarily long scatter-gather lists */ if (!(hcd->driver->flags & HCD_LOCAL_MEM)) hcd->self.sg_tablesize = ~0; diff --git a/ANDROID_3.4.5/drivers/usb/host/ehci-hub.c b/ANDROID_3.4.5/drivers/usb/host/ehci-hub.c index 38fe0762..714ca48b 100644 --- a/ANDROID_3.4.5/drivers/usb/host/ehci-hub.c +++ b/ANDROID_3.4.5/drivers/usb/host/ehci-hub.c @@ -128,6 +128,9 @@ static int __maybe_unused ehci_port_change(struct ehci_hcd *ehci) return 0; } +extern char enable_ehci_wake; +extern char enable_ehci_disc_wakeup; + static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, bool suspending, bool do_wakeup) { @@ -171,10 +174,13 @@ static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, * If we are resuming the controller, set the wakeup flags. */ if (!suspending) { - if (t1 & PORT_CONNECT) - t2 |= PORT_WKOC_E | PORT_WKDISC_E; - else - t2 |= PORT_WKOC_E | PORT_WKCONN_E; + if (enable_ehci_wake && enable_ehci_disc_wakeup) { + if (t1 & PORT_CONNECT) + t2 |= PORT_WKOC_E | PORT_WKDISC_E; + else + t2 |= PORT_WKOC_E | PORT_WKCONN_E; + } else + t2 |= PORT_WKOC_E; } ehci_vdbg(ehci, "port %d, %08x -> %08x\n", port + 1, t1, t2); @@ -254,7 +260,10 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) if (t1 & PORT_OWNER) set_bit(port, &ehci->owned_ports); else if ((t1 & PORT_PE) && !(t1 & PORT_SUSPEND)) { - t2 |= PORT_SUSPEND; + if (enable_ehci_wake) + t2 |= PORT_SUSPEND; + else + t2 &= ~PORT_PE;// CharlesTu, disable port set_bit(port, &ehci->bus_suspended); } @@ -265,10 +274,13 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) * condition happens here(connection change during bits * set), the port change detection will finally fix it. */ - if (t1 & PORT_CONNECT) - t2 |= PORT_WKOC_E | PORT_WKDISC_E; - else - t2 |= PORT_WKOC_E | PORT_WKCONN_E; + if (enable_ehci_wake && enable_ehci_disc_wakeup) { + if (t1 & PORT_CONNECT) + t2 |= PORT_WKOC_E | PORT_WKDISC_E; + else + t2 |= PORT_WKOC_E | PORT_WKCONN_E; + } else + t2 |= PORT_WKOC_E; } if (t1 != t2) { @@ -602,6 +614,16 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) * controller by the user. */ + /* + *CharlesTu,2009.08.17,patch Trancend 8GB usb device , + *copy and fast hot plug reset slowly issue. + *Due to Transcend 8GB device ,connect slowly and reset_done clear 0 + */ + /*if (!(temp & PORT_CONNECT))*/ + if (!(temp & (PORT_CONNECT|PORT_RESET))) + ehci->reset_done [i] = 0; + + if ((temp & mask) != 0 || test_bit(i, &ehci->port_c_suspend) || (ehci->reset_done[i] && time_after_eq( jiffies, ehci->reset_done[i]))) { @@ -611,6 +633,27 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) buf [1] |= 1 << (i - 7); status = STS_PCD; } + /*CharlesTu,090415,patch usb card reader plug/unplug fastly + * port fail issue. Due to the port reset assert and not clear. + */ + if ((temp & PORT_RESET) + && time_after (jiffies, ehci->reset_done [i])) { + /*printk("port reset \n");*/ + /* force reset to complete */ + ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET), + &ehci->regs->port_status [i]); + /* REVISIT: some hardware needs 550+ usec to clear + * this bit; seems too long to spin routinely... + */ + retval = handshake(ehci, + &ehci->regs->port_status [i], + PORT_RESET, 0, 750); + if (retval != 0) { + ehci_err (ehci, "port %d reset error %d\n", + i + 1, retval); + + } + } } /* FIXME autosuspend idle root hubs */ spin_unlock_irqrestore (&ehci->lock, flags); @@ -653,6 +696,190 @@ ehci_hub_descriptor ( } /*-------------------------------------------------------------------------*/ +/*{CharlesTu,2010.08.26, for test mode --------------------------------*/ +#ifdef CONFIG_USB_EHCI_EHSET + +static int +single_step_set_feature( struct usb_hcd *hcd, u8 port) +{ + struct usb_bus *bus = hcd_to_bus(hcd); + struct usb_device *udev; + struct ehci_hcd *ehci = hcd_to_ehci (hcd); + struct list_head qtd_list; + struct list_head setup_list; + struct list_head data_list; + struct ehci_qtd *qtd; + struct urb urb; + struct usb_ctrlrequest setup_packet; + char data_buffer[USB_DT_DEVICE_SIZE]; + + ehci_info (ehci, "Testing SINGLE_STEP_SET_FEATURE\n"); + + if (bus == NULL) { + ehci_err (ehci, "EHSET: usb_bus pointer is NULL\n"); + return -EPIPE; + } + + udev = bus->root_hub; + if (udev == NULL) { + ehci_err (ehci, "EHSET: root_hub pointer is NULL\n"); + return -EPIPE; + } + /* Charles, modify for MVL5 */ + /*udev = udev->children[port - 1];*/ + udev = udev->children[port ]; + + if (udev == NULL) { + ehci_err (ehci, "EHSET: No test device found on port %d\n", + port); + return -EPIPE; + } + + setup_packet.bRequestType = USB_DIR_IN; + setup_packet.bRequest = USB_REQ_GET_DESCRIPTOR; + setup_packet.wValue = (USB_DT_DEVICE << 8); + setup_packet.wIndex = 0; + setup_packet.wLength = USB_DT_DEVICE_SIZE; + + INIT_LIST_HEAD (&qtd_list); + INIT_LIST_HEAD (&setup_list); + INIT_LIST_HEAD (&data_list); + + urb.transfer_buffer_length = USB_DT_DEVICE_SIZE; + urb.dev = udev; + urb.pipe = usb_rcvctrlpipe(udev, 0); + /* Charles, modify for MVL5 */ + urb.hcpriv = udev->ep0.hcpriv; + /*urb.hcpriv = udev->ep0.hcpriv; */ + + urb.setup_packet = (char *)&setup_packet; + urb.transfer_buffer = data_buffer; + urb.transfer_flags = URB_HCD_DRIVER_TEST; + //spin_lock_init(&urb.lock); + + urb.setup_dma = dma_map_single( hcd->self.controller, + urb.setup_packet, + sizeof (struct usb_ctrlrequest), + DMA_TO_DEVICE); + urb.transfer_dma = dma_map_single ( + hcd->self.controller, + urb.transfer_buffer, + sizeof (struct usb_ctrlrequest), + DMA_TO_DEVICE); + + if (!urb.setup_dma || !urb.transfer_dma) { + ehci_err (ehci, "dma_map_single Failed\n"); + return -EBUSY; + } + + if (!qh_urb_transaction (ehci, &urb, &qtd_list, GFP_ATOMIC)) { + ehci_err (ehci, "qh_urb_transaction Failed\n"); + return -EBUSY; + } + + qtd = container_of (qtd_list.next, struct ehci_qtd, qtd_list); + list_del_init (&qtd->qtd_list); + list_add (&qtd->qtd_list, &setup_list); + qtd = container_of (qtd_list.next, struct ehci_qtd, qtd_list); + list_del_init (&qtd->qtd_list); + list_add (&qtd->qtd_list, &data_list); + qtd = container_of (qtd_list.next, struct ehci_qtd, qtd_list); + list_del_init (&qtd->qtd_list); + ehci_qtd_free (ehci, qtd); + + ehci_info (ehci, "Sending SETUP PHASE\n"); + /* Charles, modify for MVL5 */ + //if (submit_async (ehci, &udev->ep0, &urb, &setup_list, GFP_ATOMIC)) { + if (submit_async (ehci, &urb, &setup_list, GFP_ATOMIC)) { + ehci_err (ehci, "Failed to queue up qtds\n"); + return -EBUSY; + } + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies(15000)); + urb.status = 0; + urb.actual_length = 0; + + ehci_info (ehci, "Sending DATA PHASE\n"); + /* Charles, modify for MVL5 */ + //if (submit_async (ehci, &udev->ep0, &urb, &data_list, GFP_ATOMIC)) { + + if (submit_async (ehci, &urb, &setup_list, GFP_ATOMIC)) { + + ehci_err (ehci, "Failed to queue up qtds\n"); + return -EBUSY; + } + + return 0; +} +static void stop_test(struct ehci_hcd *ehci) +{ + volatile unsigned int temp32 = 0; + //int ports = 0,i = 0; + + /*reset HC */ + temp32 = readl(&ehci->regs->command); + ehci_info(ehci, "command before set reset 0x%8.8x\n", temp32); + temp32 |= 0x00000002; + writel(temp32, &ehci->regs->command); + temp32 = readl (&ehci->regs->command); + ehci_info(ehci, "command after set reset 0x%8.8x\n", temp32); + while ((readl(&ehci->regs->command)) & 0x00000002) + ; + + /*set CF bit*/ + temp32 = readl(&ehci->regs->configured_flag); + ehci_info(ehci, "CF before set CF 0x%8.8x\n", temp32); + if (!temp32) + writel (FLAG_CF, &ehci->regs->configured_flag); + temp32 = readl(&ehci->regs->configured_flag); + while (!((readl(&ehci->regs->configured_flag)) & 0x00000001)) + ; + ehci_info(ehci, "CF after set CF 0x%8.8x\n", temp32); + + +} +#endif +/*CharlesTu}-------------------------------------------------------------*/ + +static int handshake_wmt (struct ehci_hcd *ehci, void __iomem *ptr, + u32 mask, u32 done, int usec) +{ + u32 result; + u32 result1; + int usec_250; + + if (usec > 1000) + usec_250 = usec - 261; + else + usec_250 = usec; + + do { + result = ehci_readl(ehci, ptr); + result1 = result; + if (result == ~(u32)0) /* card removed */ + return -ENODEV; + result &= mask; + if (result == done) + return 0; + udelay (1); + usec--; + if (usec == usec_250) { + ehci_writel(ehci, + result1 & ~(PORT_RWC_BITS | PORT_RESUME | PORT_SUSPEND), + ptr); +// printk("*2nd clear resume\n"); + } + } while (usec > 0); + return -ETIMEDOUT; +} + +extern unsigned int env_active; +extern unsigned int env_port; +extern unsigned int env_bitmap; +extern unsigned int env_ctraddr; +extern unsigned int env_ocaddr; +extern unsigned int env_odaddr; static int ehci_hub_control ( struct usb_hcd *hcd, @@ -670,7 +897,8 @@ static int ehci_hub_control ( u32 temp, temp1, status; unsigned long flags; int retval = 0; - unsigned selector; + unsigned selector=0; + u8 port_num = 0; //CharlesTu, for testmode /* * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR. @@ -742,7 +970,8 @@ static int ehci_hub_control ( spin_lock_irqsave(&ehci->lock, flags); } /* resume signaling for 20 msec */ - temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); + //temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); + temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS | PORT_SUSPEND); ehci_writel(ehci, temp | PORT_RESUME, status_reg); ehci->reset_done[wIndex] = jiffies + msecs_to_jiffies(20); @@ -839,11 +1068,28 @@ static int ehci_hub_control ( /* stop resume signaling */ temp = ehci_readl(ehci, status_reg); +// ehci_writel(ehci, +// temp & ~(PORT_RWC_BITS | PORT_RESUME), +// status_reg); + if ((env_active) && (env_port == wIndex)) { + *((volatile unsigned char *)(env_ctraddr)) |= env_bitmap; + *((volatile unsigned char *)(env_ocaddr)) |= env_bitmap; + *((volatile unsigned char *)(env_odaddr)) |= env_bitmap; + } ehci_writel(ehci, - temp & ~(PORT_RWC_BITS | PORT_RESUME), - status_reg); + temp & ~(PORT_RWC_BITS | PORT_RESUME | PORT_SUSPEND), + status_reg); clear_bit(wIndex, &ehci->resuming_ports); - retval = handshake(ehci, status_reg, + + udelay(1); + + if ((env_active) && (env_port == wIndex)) { + *((volatile unsigned char *)(env_odaddr)) &= (~env_bitmap); + } + +// retval = handshake(ehci, status_reg, +// PORT_RESUME, 0, 2000 /* 2msec */); + retval = handshake_wmt(ehci, status_reg, PORT_RESUME, 0, 2000 /* 2msec */); if (retval != 0) { ehci_err(ehci, @@ -984,7 +1230,12 @@ static int ehci_hub_control ( * mode if we have hostpc feature */ temp &= ~PORT_WKCONN_E; - temp |= PORT_WKDISC_E | PORT_WKOC_E; + + if (enable_ehci_wake && enable_ehci_disc_wakeup) + temp |= PORT_WKDISC_E | PORT_WKOC_E; + else + temp |= PORT_WKOC_E; + ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); if (hostpc_reg) { spin_unlock_irqrestore(&ehci->lock, flags); @@ -1040,12 +1291,13 @@ static int ehci_hub_control ( * or else system reboot). See EHCI 2.3.9 and 4.14 for info * about the EHCI-specific stuff. */ +/* case USB_PORT_FEAT_TEST: if (!selector || selector > 5) goto error; ehci_quiesce(ehci); - /* Put all enabled ports into suspend */ + // Put all enabled ports into suspend while (ports--) { u32 __iomem *sreg = &ehci->regs->port_status[ports]; @@ -1060,6 +1312,59 @@ static int ehci_hub_control ( temp |= selector << 16; ehci_writel(ehci, temp, status_reg); break; +*/ + /*{CharlesTu, 2010.8.26, for test mode */ + case USB_PORT_FEAT_TEST: + ehci_info(ehci, "selector : %x\n ", selector); + //selector = (wIndex >> 8) & 0xff; + port_num = (wIndex) & 0xff; + ehci_info(ehci, "USB_PORT_FEAT_TEST : running test %x " + "on port %d\n", selector, port_num); + if (!selector || selector > 5) + ehci_info(ehci, "USB_PORT_FEAT_TEST 1: running test %x " + "on port %d\n", selector, port_num); + + switch (selector) { + case USB_PORT_TEST_J: + case USB_PORT_TEST_K: + case USB_PORT_TEST_SE0_NAK: + case USB_PORT_TEST_PACKET: + case USB_PORT_TEST_FORCE_ENABLE: + ehci_quiesce(ehci); + ehci_halt(ehci); +#ifdef CONFIG_USB_EHCI_EHSET + stop_test(ehci); +#endif + temp = ehci_readl(ehci, &ehci->regs->command); + temp &= 0xfffffffe; + writel(temp, &ehci->regs->command); + + temp = readl(&ehci->regs->port_status [(wIndex & 0x00ff)]); + temp &= 0xfff0ffff; + writel(temp, &ehci->regs->port_status[port_num]); + temp |= selector << 16; + writel(temp, &ehci->regs->port_status[port_num]); + break; +#ifdef CONFIG_USB_EHCI_EHSET + case USB_PORT_TEST_SINGLE_STEP_SET_FEATURE: + spin_unlock_irqrestore (&ehci->lock, flags); + if (single_step_set_feature(hcd, port_num)) { + spin_lock_irqsave (&ehci->lock, flags); + goto error; + } + spin_lock_irqsave (&ehci->lock, flags); + break; +#endif + + default: + goto error; + ehci_quiesce(ehci); + ehci_halt(ehci); + temp |= selector << 16; + writel (temp, &ehci->regs->port_status[port_num - 1]); + } + break; + /*CharlesTu} */ default: goto error; diff --git a/ANDROID_3.4.5/drivers/usb/host/ehci-pci.c b/ANDROID_3.4.5/drivers/usb/host/ehci-pci.c index 12348179..49726685 100644 --- a/ANDROID_3.4.5/drivers/usb/host/ehci-pci.c +++ b/ANDROID_3.4.5/drivers/usb/host/ehci-pci.c @@ -27,6 +27,8 @@ /*-------------------------------------------------------------------------*/ +extern char enable_ehci_wake; + /* called after powerup, by probe or system-pm "wakeup" */ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) { @@ -334,7 +336,7 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) struct ehci_hcd *ehci = hcd_to_ehci(hcd); unsigned long flags; int rc = 0; - + u16 pmc_enable = 0; if (time_before(jiffies, ehci->next_statechange)) msleep(10); @@ -352,7 +354,12 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) // could save FLADJ in case of Vaux power loss // ... we'd only use it to handle clock skew - + //CharlesTu,for PM high memory + if (enable_ehci_wake) { + pci_read_config_word(to_pci_dev(hcd->self.controller), 0x84, &pmc_enable); + pmc_enable |= 0x103; + pci_write_config_word(to_pci_dev(hcd->self.controller), 0x84, pmc_enable); + } return rc; } @@ -399,6 +406,13 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) * a '1' to the port switchover registers should have no effect if the * port was already switched over. */ + u16 pmc_enable = 0; + //CharlesTu,for PM high memory + if (enable_ehci_wake) { + pci_read_config_word(pdev, 0x84, &pmc_enable); + pmc_enable &= ~0x03; + pci_write_config_word(pdev, 0x84, pmc_enable); + } if (usb_is_intel_switchable_ehci(pdev)) ehci_enable_xhci_companion(); @@ -409,7 +423,11 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) /* Mark hardware accessible again as we are out of D3 state by now */ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - + /*CharlesTu,2011.01,21,move ahead,due to vbus lost when suspend + * when resume ehci hub activate ,type= HUB_RESET_RESUME + */ + if (!enable_ehci_wake) + usb_root_hub_lost_power(hcd->self.root_hub); /* If CF is still set and we aren't resuming from hibernation * then we maintained PCI Vaux power. * Just undo the effect of ehci_pci_suspend(). @@ -425,8 +443,9 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) ehci_readl(ehci, &ehci->regs->intr_enable); return 0; } - - usb_root_hub_lost_power(hcd->self.root_hub); + /*CharlesTu,2011.01,21,move ahead,due to vbus lost when suspend*/ + if (enable_ehci_wake) + usb_root_hub_lost_power(hcd->self.root_hub); /* Else reset, to cope with power loss or flush-to-storage * style "resume" having let BIOS kick in during reboot. diff --git a/ANDROID_3.4.5/drivers/usb/host/ehci-q.c b/ANDROID_3.4.5/drivers/usb/host/ehci-q.c index 36ca5077..9e11e38a 100644 --- a/ANDROID_3.4.5/drivers/usb/host/ehci-q.c +++ b/ANDROID_3.4.5/drivers/usb/host/ehci-q.c @@ -286,7 +286,12 @@ __acquires(ehci->lock) status, urb->actual_length, urb->transfer_buffer_length); #endif - + /*{CharlesTu, 2008.12.26, for test mode */ +#ifdef CONFIG_USB_EHCI_EHSET + if (likely(urb->transfer_flags == URB_HCD_DRIVER_TEST)) + return; +#endif + /*CharlesTu}*/ /* complete() can reenter this HCD */ usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); spin_unlock (&ehci->lock); diff --git a/ANDROID_3.4.5/drivers/usb/host/ehci-sched.c b/ANDROID_3.4.5/drivers/usb/host/ehci-sched.c index a60679cb..757e3463 100644 --- a/ANDROID_3.4.5/drivers/usb/host/ehci-sched.c +++ b/ANDROID_3.4.5/drivers/usb/host/ehci-sched.c @@ -655,7 +655,8 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) qh_put (qh); /* maybe turn off periodic schedule */ - return disable_periodic(ehci); + //return disable_periodic(ehci); + return 0; } static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) @@ -1767,7 +1768,7 @@ itd_complete ( ehci_urb_done(ehci, urb, 0); retval = true; urb = NULL; - (void) disable_periodic(ehci); + //(void) disable_periodic(ehci); gri ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { @@ -2163,7 +2164,7 @@ sitd_complete ( ehci_urb_done(ehci, urb, 0); retval = true; urb = NULL; - (void) disable_periodic(ehci); + //(void) disable_periodic(ehci);//gri ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { diff --git a/ANDROID_3.4.5/drivers/usb/host/ehci.h b/ANDROID_3.4.5/drivers/usb/host/ehci.h index 2694ed65..f04172ef 100644 --- a/ANDROID_3.4.5/drivers/usb/host/ehci.h +++ b/ANDROID_3.4.5/drivers/usb/host/ehci.h @@ -771,5 +771,26 @@ static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci) #endif /* DEBUG */ /*-------------------------------------------------------------------------*/ - +/*{CharlesTu, 2010.08.26, for test mode */ + +static struct list_head * +qh_urb_transaction ( + struct ehci_hcd *ehci, + struct urb *urb, + struct list_head *head, + gfp_t flags +); + +static int submit_async ( + struct ehci_hcd *ehci, + struct urb *urb, + struct list_head *qtd_list, + gfp_t mem_flags +) ; + +static inline void ehci_qtd_free ( + struct ehci_hcd *ehci, + struct ehci_qtd *qtd); + +/*CharlesTu}*/ #endif /* __LINUX_EHCI_HCD_H */ diff --git a/ANDROID_3.4.5/drivers/usb/host/pci-quirks.c b/ANDROID_3.4.5/drivers/usb/host/pci-quirks.c index df0828cb..2efade76 100644 --- a/ANDROID_3.4.5/drivers/usb/host/pci-quirks.c +++ b/ANDROID_3.4.5/drivers/usb/host/pci-quirks.c @@ -389,7 +389,7 @@ EXPORT_SYMBOL_GPL(uhci_reset_hc); */ int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base) { - u16 legsup; + //u16 legsup; unsigned int cmd, intr; /* @@ -402,16 +402,19 @@ int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base) * * If any of these conditions are violated we do a complete reset. */ + #if 0 pci_read_config_word(pdev, UHCI_USBLEGSUP, &legsup); if (legsup & ~(UHCI_USBLEGSUP_RO | UHCI_USBLEGSUP_RWC)) { dev_dbg(&pdev->dev, "%s: legsup = 0x%04x\n", __func__, legsup); goto reset_needed; } + #endif cmd = inw(base + UHCI_USBCMD); - if ((cmd & UHCI_USBCMD_RUN) || !(cmd & UHCI_USBCMD_CONFIGURE) || - !(cmd & UHCI_USBCMD_EGSM)) { +// if ((cmd & UHCI_USBCMD_RUN) || !(cmd & UHCI_USBCMD_CONFIGURE) || +// !(cmd & UHCI_USBCMD_EGSM)) { + if ((cmd & UHCI_USBCMD_RUN) || !(cmd & UHCI_USBCMD_EGSM)) { dev_dbg(&pdev->dev, "%s: cmd = 0x%04x\n", __func__, cmd); goto reset_needed; diff --git a/ANDROID_3.4.5/drivers/usb/host/uhci-hcd.c b/ANDROID_3.4.5/drivers/usb/host/uhci-hcd.c index e4db3506..3e0d2a8c 100644 --- a/ANDROID_3.4.5/drivers/usb/host/uhci-hcd.c +++ b/ANDROID_3.4.5/drivers/usb/host/uhci-hcd.c @@ -89,6 +89,8 @@ static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state); static void wakeup_rh(struct uhci_hcd *uhci); static void uhci_get_current_frame_number(struct uhci_hcd *uhci); +extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); + /* * Calculate the link pointer DMA value for the first Skeleton QH in a frame. */ @@ -338,6 +340,11 @@ __acquires(uhci->lock) uhci->RD_enable = !!int_enable; uhci_writew(uhci, int_enable, USBINTR); + //gri + uhci_writew(uhci, 0, USBCMD); + mb(); + while (!(uhci_readw(uhci, USBSTS) & USBSTS_HCH)); + // uhci_writew(uhci, egsm_enable | USBCMD_CF, USBCMD); mb(); udelay(5); @@ -855,7 +862,7 @@ static int __init uhci_hcd_init(void) int retval = -ENOMEM; if (usb_disabled()) - return -ENODEV; + return -ENODEV; printk(KERN_INFO "uhci_hcd: " DRIVER_DESC "%s\n", ignore_oc ? ", overcurrent ignored" : ""); diff --git a/ANDROID_3.4.5/drivers/usb/host/uhci-hub.c b/ANDROID_3.4.5/drivers/usb/host/uhci-hub.c index 768d5429..fb0da10f 100644 --- a/ANDROID_3.4.5/drivers/usb/host/uhci-hub.c +++ b/ANDROID_3.4.5/drivers/usb/host/uhci-hub.c @@ -98,9 +98,12 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, { int status; int i; + u16 tmp; + if (uhci_readw(uhci, port_addr) & SUSPEND_BITS) { CLR_RH_PORTSTAT(SUSPEND_BITS); + wmb(); if (test_bit(port, &uhci->resuming_ports)) set_bit(port, &uhci->port_c_suspend); @@ -110,9 +113,13 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, * Experiments show that some controllers take longer, so * we'll poll for completion. */ for (i = 0; i < 10; ++i) { - if (!(uhci_readw(uhci, port_addr) & SUSPEND_BITS)) - break; udelay(1); + tmp = uhci_readw(uhci, port_addr); + //if (!(uhci_readw(uhci, port_addr) & SUSPEND_BITS)){ + //printk("uhci_finish_suspend 01\n"); + if (!(tmp & SUSPEND_BITS)){ + break; + } } } clear_bit(port, &uhci->resuming_ports); diff --git a/ANDROID_3.4.5/drivers/usb/host/uhci-pci.c b/ANDROID_3.4.5/drivers/usb/host/uhci-pci.c index c300bd2f..2de5a93b 100644 --- a/ANDROID_3.4.5/drivers/usb/host/uhci-pci.c +++ b/ANDROID_3.4.5/drivers/usb/host/uhci-pci.c @@ -18,6 +18,7 @@ */ #include "pci-quirks.h" +#include <mach/hardware.h> /* * Make sure the controller is completely inactive, unable to @@ -162,11 +163,16 @@ static void uhci_shutdown(struct pci_dev *pdev) #ifdef CONFIG_PM +extern char enable_ehci_wake; +extern char enable_uhci0_wake; +extern char enable_uhci1_wake; + static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci)); int rc = 0; + u16 pmc_enable = 0; dev_dbg(uhci_dev(uhci), "%s\n", __func__); @@ -192,6 +198,12 @@ static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) pci_write_config_byte(pdev, USBRES_INTEL, USBPORT1EN | USBPORT2EN); } + //CharlesTu, for PM + if (((hcd->self.busnum == 2) && enable_uhci0_wake) || ((hcd->self.busnum == 3) && enable_uhci1_wake)){ + pci_read_config_word(to_pci_dev(uhci_dev(uhci)), 0x84, &pmc_enable); + pmc_enable |= 0x103; + pci_write_config_word(to_pci_dev(uhci_dev(uhci)), 0x84, pmc_enable); + } done_okay: clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); @@ -203,7 +215,19 @@ done: static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); - + u16 pmc_enable = 0; + /*CharlesTu,2009.08.30,patch uhci device disconnet irq nobody care issue + * Before clear D3 mode ,disable UHCI resume interrupt + * The right sequence: disconnect->wakeup->D0 mode->clear resume. + */ + if (enable_ehci_wake){ + REG8_VAL(USB20_HOST_DEVICE_CFG_BASE_ADDR+0x0304) &= ~0x02; + REG8_VAL(USB20_HOST_DEVICE_CFG_BASE_ADDR+0x1504) &= ~0x02; + + pci_read_config_word(to_pci_dev(uhci_dev(uhci)), 0x84, &pmc_enable); + pmc_enable &= ~0x03; + pci_write_config_word(to_pci_dev(uhci_dev(uhci)), 0x84, pmc_enable); + } dev_dbg(uhci_dev(uhci), "%s\n", __func__); /* Since we aren't in D3 any more, it's safe to set this flag |