static int tegra_ehci_remove(struct platform_device *pdev) { struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); struct usb_hcd *hcd = NULL; if (tegra == NULL) return -EINVAL; hcd = ehci_to_hcd(tegra->ehci); if (hcd == NULL) return -EINVAL; #ifdef CONFIG_USB_OTG_UTILS if (tegra->transceiver) { otg_set_host(tegra->transceiver->otg, NULL); usb_put_transceiver(tegra->transceiver); } #endif if (tegra->irq) disable_irq_wake(tegra->irq); /* Make sure phy is powered ON to access USB register */ if(!tegra_usb_phy_hw_accessible(tegra->phy)) tegra_usb_phy_power_on(tegra->phy); usb_remove_hcd(hcd); tegra_usb_phy_power_off(tegra->phy); usb_phy_shutdown(get_usb_phy(tegra->phy)); iounmap(hcd->regs); usb_put_hcd(hcd); return 0; }
static int tegra_ehci_remove(struct platform_device *pdev) { struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); struct usb_hcd *hcd = NULL; struct usb_device *rhdev = NULL; struct tegra_usb_platform_data *pdata; unsigned long timeout = 0; if (tegra == NULL) return -EINVAL; hcd = ehci_to_hcd(tegra->ehci); if (hcd == NULL) return -EINVAL; #ifdef CONFIG_TEGRA_EHCI_BOOST_CPU_FREQ cancel_delayed_work(&tegra->boost_cpu_freq_work); pm_qos_update_request(&tegra->boost_cpu_freq_req, PM_QOS_DEFAULT_VALUE); tegra->cpu_boost_in_work = false; #endif rhdev = hcd->self.root_hub; pdata = dev_get_platdata(&pdev->dev); #ifdef CONFIG_USB_OTG_UTILS if (tegra->transceiver) { otg_set_host(tegra->transceiver->otg, NULL); usb_put_transceiver(tegra->transceiver); } #endif if (tegra->irq) disable_irq_wake(tegra->irq); /* Make sure phy is powered ON to access USB register */ if(!tegra_usb_phy_hw_accessible(tegra->phy)) tegra_usb_phy_power_on(tegra->phy); if (pdata->port_otg) { timeout = jiffies + 5 * HZ; /* wait for devices connected to root hub to disconnect*/ while (time_before(jiffies, timeout) && rhdev && rhdev->children[0]) ; /* wait for any control packets sent to root hub to complete */ mdelay(1000); } usb_remove_hcd(hcd); tegra_usb_phy_power_off(tegra->phy); usb_phy_shutdown(get_usb_phy(tegra->phy)); iounmap(hcd->regs); usb_put_hcd(hcd); return 0; }
static int tegra_ehci_remove(struct platform_device *pdev) { struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); dev_info(&pdev->dev, "%s+\n", __func__); //htc_dbg if (tegra == NULL || hcd == NULL) return -EINVAL; #ifdef CONFIG_USB_OTG_UTILS if (tegra->transceiver) { otg_set_host(tegra->transceiver, NULL); otg_put_transceiver(tegra->transceiver); } #endif if (tegra->irq) disable_irq_wake(tegra->irq); /* Make sure phy is powered ON to access USB register */ if(!tegra_usb_phy_hw_accessible(tegra->phy)) tegra_usb_phy_power_on(tegra->phy); pr_info("+%s:usb_remove_hcd\n", __func__); uhsic_phy_remove(tegra->phy); usb_remove_hcd(hcd); usb_put_hcd(hcd); ehci_remove = 1; tegra_usb_phy_power_off(tegra->phy); tegra_usb_phy_close(tegra->phy); iounmap(hcd->regs); platform_set_drvdata(pdev, NULL); //htc++ #ifdef CONFIG_QCT_9K_MODEM if (Modem_is_QCT_MDM9K()) { extern struct platform_device tegra_ehci2_device; if (&tegra_ehci2_device == pdev) { mdm_hsic_ehci_hcd = NULL; mdm_hsic_usb_hcd = NULL; mdm_hsic_phy = NULL; pr_info("%s:: mdm_hsic_ehci_hcd = %x, mdm_hsic_usb_hcd = %x, mdm_hsic_phy = %x\n", __func__, (unsigned int)mdm_hsic_ehci_hcd, (unsigned int)mdm_hsic_usb_hcd, (unsigned int)mdm_hsic_phy); } } #endif //CONFIG_QCT_9K_MODEM //htc-- dev_info(&pdev->dev, "%s-\n", __func__); //htc_dbg return 0; }
static int tegra_ehci_remove(struct platform_device *pdev) { struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); struct usb_device *rhdev = NULL; struct tegra_usb_platform_data *pdata; unsigned long timeout = 0; wake_lock_destroy(&tegra->ehci_wake_lock); #ifdef CONFIG_TEGRA_EHCI_BOOST_CPU_FREQ cancel_delayed_work_sync(&tegra->boost_cpu_freq_work); tegra->cpu_boost_in_work = false; pm_qos_remove_request(&tegra->boost_cpu_freq_req); #endif rhdev = hcd->self.root_hub; pdata = dev_get_platdata(&pdev->dev); if (!IS_ERR_OR_NULL(tegra->transceiver)) otg_set_host(tegra->transceiver->otg, NULL); /* Make sure phy is powered ON to access USB register */ if(!tegra_usb_phy_hw_accessible(tegra->phy)) tegra_usb_phy_power_on(tegra->phy); if (pdata->port_otg) { timeout = jiffies + 5 * HZ; /* wait for devices connected to root hub to disconnect*/ while (rhdev && usb_hub_find_child(rhdev, 1)) { /* wait for any control packets sent to root hub to complete */ if (time_after(jiffies, timeout)) break; msleep(20); cpu_relax(); } } #ifdef CONFIG_TEGRA_EHCI_BOOST_CPU_FREQ device_remove_file(hcd->self.controller, &dev_attr_boost_enable); #endif usb_remove_hcd(hcd); usb_put_hcd(hcd); tegra_usb_phy_power_off(tegra->phy); usb_phy_shutdown(get_usb_phy(tegra->phy)); mutex_destroy(&tegra->sync_lock); tegra_pd_remove_device(&pdev->dev); return 0; }
static void tegra_ehci_shutdown(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); struct platform_device *pdev = to_platform_device(hcd->self.controller); struct tegra_usb_platform_data *pdata = dev_get_platdata(&pdev->dev); mutex_lock(&tegra->sync_lock); if (tegra_usb_phy_hw_accessible(tegra->phy)) { ehci_silence_controller(ehci); } if (pdata->port_otg) tegra_usb_enable_vbus(tegra->phy, false); mutex_unlock(&tegra->sync_lock); }
static void tegra_ehci_shutdown(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); mutex_lock(&tegra->sync_lock); del_timer_sync(&ehci->watchdog); del_timer_sync(&ehci->iaa_watchdog); if (tegra_usb_phy_hw_accessible(tegra->phy)) { spin_lock_irq(&ehci->lock); ehci_silence_controller(ehci); spin_unlock_irq(&ehci->lock); } mutex_unlock(&tegra->sync_lock); }
static int tegra_ehci_hub_control( struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength ) { struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval = 0; u32 __iomem *status_reg; if (!tegra_usb_phy_hw_accessible(tegra->phy)) { if (buf) memset(buf, 0, wLength); return retval; } /* Do tegra phy specific actions based on the type request */ switch (typeReq) { case GetPortStatus: if (tegra->port_resuming) { u32 cmd; int delay = ehci->reset_done[wIndex-1] - jiffies; /* Sometimes it seems we get called too soon... In that case, wait.*/ if (delay > 0) { ehci_dbg(ehci, "GetPortStatus called too soon, waiting %dms...\n", delay); mdelay(jiffies_to_msecs(delay)); } status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1]; /* Ensure the port PORT_SUSPEND and PORT_RESUME has cleared */ if (handshake(ehci, status_reg, (PORT_SUSPEND | PORT_RESUME), 0, 25000)) { EHCI_DBG("%s: timeout waiting for SUSPEND to clear\n", __func__); } tegra_usb_phy_post_resume(tegra->phy); tegra->port_resuming = 0; /* If run bit is not set by now enable it */ cmd = ehci_readl(ehci, &ehci->regs->command); if (!(cmd & CMD_RUN)) { cmd |= CMD_RUN; ehci->command |= CMD_RUN; ehci_writel(ehci, cmd, &ehci->regs->command); } /* Now we can safely re-enable irqs */ ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); } break; case ClearPortFeature: if (wValue == USB_PORT_FEAT_SUSPEND) { tegra_usb_phy_pre_resume(tegra->phy, false); tegra->port_resuming = 1; } else if (wValue == USB_PORT_FEAT_ENABLE) { u32 temp; temp = ehci_readl(ehci, &ehci->regs->port_status[0]) & ~PORT_RWC_BITS; ehci_writel(ehci, temp & ~PORT_PE, &ehci->regs->port_status[0]); return retval; } break; case SetPortFeature: if (wValue == USB_PORT_FEAT_SUSPEND) tegra_usb_phy_pre_suspend(tegra->phy); break; } /* handle ehci hub control request */ retval = ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); /* do tegra phy specific actions based on the type request */ if (!retval) { switch (typeReq) { case SetPortFeature: if (wValue == USB_PORT_FEAT_SUSPEND) { tegra_usb_phy_post_suspend(tegra->phy); } else if (wValue == USB_PORT_FEAT_RESET) { if (wIndex == 1) tegra_usb_phy_bus_reset(tegra->phy); } else if (wValue == USB_PORT_FEAT_POWER) { if (wIndex == 1) tegra_usb_phy_port_power(tegra->phy); } break; case ClearPortFeature: if (wValue == USB_PORT_FEAT_SUSPEND) { /* tegra USB controller needs 25 ms to resume the port */ ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25); } break; } } return retval; }
static int tegra_ehci_hub_control( struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength ) { struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); struct ehci_hcd *ehci = hcd_to_ehci(hcd); int retval = 0; u32 __iomem *status_reg; void __iomem *apb_misc = IO_ADDRESS(TEGRA_APB_MISC_BASE); struct platform_device *pdev = container_of(hcd->self.controller, struct platform_device, dev); int ehci_id = pdev->id; if (!tegra_usb_phy_hw_accessible(tegra->phy)) { if (buf) memset(buf, 0, wLength); return retval; } if(ehci_id == MODEM_EHCI_ID){ printk(KERN_INFO"%s: req:0x%x wV:0x%x wI:0x%x MODE:0x%x CMD:0x%x PORTSC:0x%x STS:0x%x HOSTPC1:0x%x\n", __func__, typeReq, wValue, wIndex, readl(hcd->regs + 0x1f8), readl(&ehci->regs->command), readl(&ehci->regs->port_status[0]), readl(&ehci->regs->status), readl(hcd->regs + 0x1b4)); printk(KERN_INFO"%s: INTR:0x%x STAT_CFG0:0x%x ASDBGREG:0x%x OBSCTRL:0x%x OBSDATA:0x%x port_resuming:%d\n", __func__, readl(hcd->regs + 0x138), readl(hcd->regs + 0xc28), readl(apb_misc + 0x810), readl(apb_misc + 0x818), readl(apb_misc + 0x81c), tegra->port_resuming); } /* Do tegra phy specific actions based on the type request */ switch (typeReq) { case GetPortStatus: if (tegra->port_resuming) { u32 cmd; int delay = ehci->reset_done[wIndex-1] - jiffies; /* Sometimes it seems we get called too soon... In that case, wait.*/ if (delay > 0) { printk(KERN_INFO"GetPortStatus called too soon, waiting %dms...\n",jiffies_to_msecs(delay)); ehci_dbg(ehci, "GetPortStatus called too soon, waiting %dms...\n", jiffies_to_msecs(delay)); mdelay(jiffies_to_msecs(delay)); } status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1]; tegra_usb_phy_post_resume(tegra->phy); tegra->port_resuming = 0; /* If run bit is not set by now enable it */ cmd = ehci_readl(ehci, &ehci->regs->command); if (!(cmd & CMD_RUN)) { cmd |= CMD_RUN; ehci->command |= CMD_RUN; ehci_writel(ehci, cmd, &ehci->regs->command); } /* Now we can safely re-enable irqs */ ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); } break; case ClearPortFeature: if (wValue == USB_PORT_FEAT_SUSPEND) { tegra_usb_phy_pre_resume(tegra->phy, false); tegra->port_resuming = 1; } else if (wValue == USB_PORT_FEAT_ENABLE) { u32 temp; temp = ehci_readl(ehci, &ehci->regs->port_status[0]) & ~PORT_RWC_BITS; ehci_writel(ehci, temp & ~PORT_PE, &ehci->regs->port_status[0]); return retval; } break; } /* handle ehci hub control request */ retval = ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); /* do tegra phy specific actions based on the type request */ if (!retval) { switch (typeReq) { case SetPortFeature: if (wValue == USB_PORT_FEAT_SUSPEND) { /* Need a 4ms delay for controller to suspend */ mdelay(4); tegra_usb_phy_post_suspend(tegra->phy); } else if (wValue == USB_PORT_FEAT_RESET) { if (ehci->reset_done[0] && wIndex == 1) tegra_usb_phy_bus_reset(tegra->phy); } else if (wValue == USB_PORT_FEAT_POWER) { if (wIndex == 1) tegra_usb_phy_port_power(tegra->phy); } break; case ClearPortFeature: if (wValue == USB_PORT_FEAT_SUSPEND) { /* tegra USB controller needs 25 ms to resume the port */ ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25); } break; } } return retval; }