ehci-tegra.c revision a448e4dc25303fe551e4dafe16c8c7c34f1b9d82
179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby/* 279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * EHCI-compliant USB host controller driver for NVIDIA Tegra SoCs 379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * 479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * Copyright (C) 2010 Google, Inc. 579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * Copyright (C) 2009 NVIDIA Corporation 679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * 779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * This program is free software; you can redistribute it and/or modify it 879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * under the terms of the GNU General Public License as published by the 979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * Free Software Foundation; either version 2 of the License, or (at your 1079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * option) any later version. 1179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * 1279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * This program is distributed in the hope that it will be useful, but WITHOUT 1379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 1579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * more details. 1679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * 1779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby */ 1879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 1979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#include <linux/clk.h> 2079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#include <linux/platform_device.h> 2179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#include <linux/platform_data/tegra_usb.h> 2279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#include <linux/irq.h> 2379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#include <linux/usb/otg.h> 244a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson#include <linux/gpio.h> 254a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson#include <linux/of.h> 264a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson#include <linux/of_gpio.h> 274a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 2879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#include <mach/usb_phy.h> 294a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson#include <mach/iomap.h> 3079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 31fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell#define TEGRA_USB_DMA_ALIGN 32 32fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 3379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystruct tegra_ehci_hcd { 3479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct ehci_hcd *ehci; 3579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_usb_phy *phy; 3679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct clk *clk; 3779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct clk *emc_clk; 388675381109b0eb1c948a423c2b35e3f4509cb25eHeikki Krogerus struct usb_phy *transceiver; 3979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int host_resumed; 4079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int bus_suspended; 4179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int port_resuming; 4279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int power_down_on_bus_suspend; 4379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby enum tegra_usb_phy_port_speed port_speed; 4479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby}; 4579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 4679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic void tegra_ehci_power_up(struct usb_hcd *hcd) 4779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 4879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); 4979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 5079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby clk_enable(tegra->emc_clk); 5179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby clk_enable(tegra->clk); 5279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_usb_phy_power_on(tegra->phy); 5379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->host_resumed = 1; 5479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 5579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 5679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic void tegra_ehci_power_down(struct usb_hcd *hcd) 5779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 5879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); 5979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 6079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->host_resumed = 0; 6179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_usb_phy_power_off(tegra->phy); 6279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby clk_disable(tegra->clk); 6379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby clk_disable(tegra->emc_clk); 6479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 6579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 661f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Linstatic int tegra_ehci_internal_port_reset( 671f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin struct ehci_hcd *ehci, 681f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin u32 __iomem *portsc_reg 691f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin) 701f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin{ 711f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin u32 temp; 721f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin unsigned long flags; 731f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin int retval = 0; 741f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin int i, tries; 751f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin u32 saved_usbintr; 761f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 771f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin spin_lock_irqsave(&ehci->lock, flags); 781f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin saved_usbintr = ehci_readl(ehci, &ehci->regs->intr_enable); 791f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* disable USB interrupt */ 801f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, 0, &ehci->regs->intr_enable); 811f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin spin_unlock_irqrestore(&ehci->lock, flags); 821f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 831f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* 841f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Here we have to do Port Reset at most twice for 851f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Port Enable bit to be set. 861f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin */ 871f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin for (i = 0; i < 2; i++) { 881f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp = ehci_readl(ehci, portsc_reg); 891f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp |= PORT_RESET; 901f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, temp, portsc_reg); 911f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin mdelay(10); 921f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp &= ~PORT_RESET; 931f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, temp, portsc_reg); 941f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin mdelay(1); 951f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin tries = 100; 961f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin do { 971f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin mdelay(1); 981f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* 991f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Up to this point, Port Enable bit is 1001f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * expected to be set after 2 ms waiting. 1011f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * USB1 usually takes extra 45 ms, for safety, 1021f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * we take 100 ms as timeout. 1031f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin */ 1041f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp = ehci_readl(ehci, portsc_reg); 1051f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin } while (!(temp & PORT_PE) && tries--); 1061f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin if (temp & PORT_PE) 1071f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin break; 1081f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin } 1091f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin if (i == 2) 1101f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin retval = -ETIMEDOUT; 1111f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 1121f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* 1131f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Clear Connect Status Change bit if it's set. 1141f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * We can't clear PORT_PEC. It will also cause PORT_PE to be cleared. 1151f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin */ 1161f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin if (temp & PORT_CSC) 1171f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, PORT_CSC, portsc_reg); 1181f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 1191f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* 1201f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Write to clear any interrupt status bits that might be set 1211f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * during port reset. 1221f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin */ 1231f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp = ehci_readl(ehci, &ehci->regs->status); 1241f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, temp, &ehci->regs->status); 1251f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 1261f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* restore original interrupt enable bits */ 1271f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, saved_usbintr, &ehci->regs->intr_enable); 1281f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin return retval; 1291f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin} 1301f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 13179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_hub_control( 13279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct usb_hcd *hcd, 13379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u16 typeReq, 13479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u16 wValue, 13579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u16 wIndex, 13679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby char *buf, 13779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u16 wLength 13879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby) 13979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 14079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct ehci_hcd *ehci = hcd_to_ehci(hcd); 14179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); 14279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u32 __iomem *status_reg; 14379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u32 temp; 14479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby unsigned long flags; 14579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int retval = 0; 14679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 14779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1]; 14879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 14979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_lock_irqsave(&ehci->lock, flags); 15079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 15179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* 15279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * In ehci_hub_control() for USB_PORT_FEAT_ENABLE clears the other bits 15379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * that are write on clear, by writing back the register read value, so 15479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * USB_PORT_FEAT_ENABLE is handled by masking the set on clear bits 15579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby */ 15679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (typeReq == ClearPortFeature && wValue == USB_PORT_FEAT_ENABLE) { 15779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp = ehci_readl(ehci, status_reg) & ~PORT_RWC_BITS; 15879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_writel(ehci, temp & ~PORT_PE, status_reg); 15979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 16079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 16179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 16279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby else if (typeReq == GetPortStatus) { 16379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp = ehci_readl(ehci, status_reg); 16479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (tegra->port_resuming && !(temp & PORT_SUSPEND)) { 16579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Resume completed, re-enable disconnect detection */ 16679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->port_resuming = 0; 16779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_usb_phy_postresume(tegra->phy); 16879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 16979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 17079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 17179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby else if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { 17279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp = ehci_readl(ehci, status_reg); 17379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) { 17479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby retval = -EPIPE; 17579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 17679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 17779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 17879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp &= ~PORT_WKCONN_E; 17979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp |= PORT_WKDISC_E | PORT_WKOC_E; 18079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); 18179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 18279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* 18379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * If a transaction is in progress, there may be a delay in 18479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * suspending the port. Poll until the port is suspended. 18579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby */ 18679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (handshake(ehci, status_reg, PORT_SUSPEND, 18779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby PORT_SUSPEND, 5000)) 18879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pr_err("%s: timeout waiting for SUSPEND\n", __func__); 18979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 19079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports); 19179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 19279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 19379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 1941f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* For USB1 port we need to issue Port Reset twice internally */ 1951f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin if (tegra->phy->instance == 0 && 1961f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_RESET)) { 1971f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin spin_unlock_irqrestore(&ehci->lock, flags); 1981f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin return tegra_ehci_internal_port_reset(ehci, status_reg); 1991f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin } 2001f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 20179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* 20279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * Tegra host controller will time the resume operation to clear the bit 20379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * when the port control state switches to HS or FS Idle. This behavior 20479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * is different from EHCI where the host controller driver is required 20579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * to set this bit to a zero after the resume duration is timed in the 20679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * driver. 20779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby */ 20879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby else if (typeReq == ClearPortFeature && 20979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby wValue == USB_PORT_FEAT_SUSPEND) { 21079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp = ehci_readl(ehci, status_reg); 21179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if ((temp & PORT_RESET) || !(temp & PORT_PE)) { 21279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby retval = -EPIPE; 21379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 21479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 21579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 21679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!(temp & PORT_SUSPEND)) 21779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 21879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 21979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Disable disconnect detection during port resume */ 22079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_usb_phy_preresume(tegra->phy); 22179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 22279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25); 22379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 22479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); 22579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* start resume signalling */ 22679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_writel(ehci, temp | PORT_RESUME, status_reg); 227a448e4dc25303fe551e4dafe16c8c7c34f1b9d82Alan Stern set_bit(wIndex-1, &ehci->resuming_ports); 22879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 22979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_unlock_irqrestore(&ehci->lock, flags); 23079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby msleep(20); 23179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_lock_irqsave(&ehci->lock, flags); 23279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 23379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Poll until the controller clears RESUME and SUSPEND */ 23479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (handshake(ehci, status_reg, PORT_RESUME, 0, 2000)) 23579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pr_err("%s: timeout waiting for RESUME\n", __func__); 23679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (handshake(ehci, status_reg, PORT_SUSPEND, 0, 2000)) 23779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pr_err("%s: timeout waiting for SUSPEND\n", __func__); 23879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 23979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci->reset_done[wIndex-1] = 0; 240a448e4dc25303fe551e4dafe16c8c7c34f1b9d82Alan Stern clear_bit(wIndex-1, &ehci->resuming_ports); 24179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 24279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->port_resuming = 1; 24379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 24479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 24579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 24679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_unlock_irqrestore(&ehci->lock, flags); 24779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 24879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Handle the hub control events here */ 24979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); 25079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobydone: 25179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_unlock_irqrestore(&ehci->lock, flags); 25279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return retval; 25379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 25479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 25579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic void tegra_ehci_restart(struct usb_hcd *hcd) 25679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 25779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct ehci_hcd *ehci = hcd_to_ehci(hcd); 25879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 25979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_reset(ehci); 26079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 26179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* setup the frame list and Async q heads */ 26279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list); 26379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next); 26479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* setup the command register and set the controller in RUN mode */ 26579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); 26679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci->command |= CMD_RUN; 26779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_writel(ehci, ehci->command, &ehci->regs->command); 26879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 26979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby down_write(&ehci_cf_port_reset_rwsem); 27079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); 27179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* flush posted writes */ 27279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_readl(ehci, &ehci->regs->command); 27379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby up_write(&ehci_cf_port_reset_rwsem); 27479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 27579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 27679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_usb_suspend(struct usb_hcd *hcd) 27779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 27879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); 27979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct ehci_regs __iomem *hw = tegra->ehci->regs; 28079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby unsigned long flags; 28179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 28279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_lock_irqsave(&tegra->ehci->lock, flags); 28379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 28479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3; 28579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_halt(tegra->ehci); 28679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 28779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 28879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_unlock_irqrestore(&tegra->ehci->lock, flags); 28979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 29079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_ehci_power_down(hcd); 29179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return 0; 29279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 29379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 29479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_usb_resume(struct usb_hcd *hcd) 29579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 29679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); 29779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct ehci_hcd *ehci = hcd_to_ehci(hcd); 29879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct ehci_regs __iomem *hw = ehci->regs; 29979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby unsigned long val; 30079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 30179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 30279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_ehci_power_up(hcd); 30379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 30479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) { 30579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Wait for the phy to detect new devices 30679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * before we restart the controller */ 30779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby msleep(10); 30879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto restart; 30979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 31079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 31179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Force the phy to keep data lines in suspend state */ 31279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed); 31379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 31479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Enable host mode */ 31579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tdi_reset(ehci); 31679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 31779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Enable Port Power */ 31879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby val = readl(&hw->port_status[0]); 31979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby val |= PORT_POWER; 32079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby writel(val, &hw->port_status[0]); 32179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby udelay(10); 32279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 32379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Check if the phy resume from LP0. When the phy resume from LP0 32479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * USB register will be reset. */ 32579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!readl(&hw->async_next)) { 32679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Program the field PTC based on the saved speed mode */ 32779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby val = readl(&hw->port_status[0]); 32879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby val &= ~PORT_TEST(~0); 32979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH) 33079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby val |= PORT_TEST_FORCE; 33179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL) 33279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby val |= PORT_TEST(6); 33379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) 33479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby val |= PORT_TEST(7); 33579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby writel(val, &hw->port_status[0]); 33679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby udelay(10); 33779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 33879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Disable test mode by setting PTC field to NORMAL_OP */ 33979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby val = readl(&hw->port_status[0]); 34079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby val &= ~PORT_TEST(~0); 34179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby writel(val, &hw->port_status[0]); 34279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby udelay(10); 34379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 34479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 34579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Poll until CCS is enabled */ 34679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (handshake(ehci, &hw->port_status[0], PORT_CONNECT, 34779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby PORT_CONNECT, 2000)) { 34879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__); 34979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto restart; 35079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 35179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 35279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Poll until PE is enabled */ 35379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (handshake(ehci, &hw->port_status[0], PORT_PE, 35479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby PORT_PE, 2000)) { 35579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__); 35679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto restart; 35779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 35879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 35979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Clear the PCI status, to avoid an interrupt taken upon resume */ 36079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby val = readl(&hw->status); 36179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby val |= STS_PCD; 36279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby writel(val, &hw->status); 36379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 36479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */ 36579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby val = readl(&hw->port_status[0]); 36679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if ((val & PORT_POWER) && (val & PORT_PE)) { 36779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby val |= PORT_SUSPEND; 36879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby writel(val, &hw->port_status[0]); 36979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 37079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Wait until port suspend completes */ 37179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND, 37279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby PORT_SUSPEND, 1000)) { 37379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pr_err("%s: timeout waiting for PORT_SUSPEND\n", 37479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby __func__); 37579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto restart; 37679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 37779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 37879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 37979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_ehci_phy_restore_end(tegra->phy); 38079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return 0; 38179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 38279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobyrestart: 38379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH) 38479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_ehci_phy_restore_end(tegra->phy); 38579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 38679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_ehci_restart(hcd); 38779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return 0; 38879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 38979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 39079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic void tegra_ehci_shutdown(struct usb_hcd *hcd) 39179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 39279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); 39379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 39479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* ehci_shutdown touches the USB controller registers, make sure 39579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * controller has clocks to it */ 39679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!tegra->host_resumed) 39779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_ehci_power_up(hcd); 39879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 39979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_shutdown(hcd); 40079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 40179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 40279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_setup(struct usb_hcd *hcd) 40379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 40479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct ehci_hcd *ehci = hcd_to_ehci(hcd); 40579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int retval; 40679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 40779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* EHCI registers start at offset 0x100 */ 40879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci->caps = hcd->regs + 0x100; 40979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci->regs = hcd->regs + 0x100 + 410c430131a02d677aa708f56342c1565edfdacb3c0Jan Andersson HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase)); 41179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 41279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dbg_hcs_params(ehci, "reset"); 41379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dbg_hcc_params(ehci, "reset"); 41479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 41579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* cache this readonly data; minimize chip reads */ 41679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci->hcs_params = readl(&ehci->caps->hcs_params); 41779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 41879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* switch to host mode */ 41979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby hcd->has_tt = 1; 42079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_reset(ehci); 42179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 42279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby retval = ehci_halt(ehci); 42379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (retval) 42479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return retval; 42579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 42679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* data structure init */ 42779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby retval = ehci_init(hcd); 42879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (retval) 42979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return retval; 43079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 43179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci->sbrn = 0x20; 43279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 43379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_port_power(ehci, 1); 43479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return retval; 43579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 43679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 43779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#ifdef CONFIG_PM 43879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_bus_suspend(struct usb_hcd *hcd) 43979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 44079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); 44179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int error_status = 0; 44279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 44379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby error_status = ehci_bus_suspend(hcd); 44479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!error_status && tegra->power_down_on_bus_suspend) { 44579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_usb_suspend(hcd); 44679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->bus_suspended = 1; 44779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 44879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 44979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return error_status; 45079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 45179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 45279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_bus_resume(struct usb_hcd *hcd) 45379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 45479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); 45579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 45679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (tegra->bus_suspended && tegra->power_down_on_bus_suspend) { 45779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_usb_resume(hcd); 45879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->bus_suspended = 0; 45979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 46079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 46179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_usb_phy_preresume(tegra->phy); 46279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->port_resuming = 1; 46379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return ehci_bus_resume(hcd); 46479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 46579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#endif 46679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 467fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morellstruct temp_buffer { 468fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell void *kmalloc_ptr; 469fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell void *old_xfer_buffer; 470fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell u8 data[0]; 471fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell}; 472fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 473fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morellstatic void free_temp_buffer(struct urb *urb) 474fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell{ 475fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell enum dma_data_direction dir; 476fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell struct temp_buffer *temp; 477fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 478fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) 479fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return; 480fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 481fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; 482fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 483fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell temp = container_of(urb->transfer_buffer, struct temp_buffer, 484fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell data); 485fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 486fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (dir == DMA_FROM_DEVICE) 487fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell memcpy(temp->old_xfer_buffer, temp->data, 488fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer_length); 489fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer = temp->old_xfer_buffer; 490fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell kfree(temp->kmalloc_ptr); 491fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 492fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER; 493fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell} 494fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 495fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morellstatic int alloc_temp_buffer(struct urb *urb, gfp_t mem_flags) 496fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell{ 497fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell enum dma_data_direction dir; 498fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell struct temp_buffer *temp, *kmalloc_ptr; 499fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell size_t kmalloc_size; 500fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 501fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (urb->num_sgs || urb->sg || 502fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer_length == 0 || 503fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell !((uintptr_t)urb->transfer_buffer & (TEGRA_USB_DMA_ALIGN - 1))) 504fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return 0; 505fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 506fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; 507fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 508fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell /* Allocate a buffer with enough padding for alignment */ 509fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell kmalloc_size = urb->transfer_buffer_length + 510fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell sizeof(struct temp_buffer) + TEGRA_USB_DMA_ALIGN - 1; 511fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 512fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell kmalloc_ptr = kmalloc(kmalloc_size, mem_flags); 513fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (!kmalloc_ptr) 514fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return -ENOMEM; 515fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 516fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell /* Position our struct temp_buffer such that data is aligned */ 517fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell temp = PTR_ALIGN(kmalloc_ptr + 1, TEGRA_USB_DMA_ALIGN) - 1; 518fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 519fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell temp->kmalloc_ptr = kmalloc_ptr; 520fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell temp->old_xfer_buffer = urb->transfer_buffer; 521fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (dir == DMA_TO_DEVICE) 522fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell memcpy(temp->data, urb->transfer_buffer, 523fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer_length); 524fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer = temp->data; 525fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 526fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER; 527fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 528fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return 0; 529fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell} 530fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 531fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morellstatic int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, 532fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell gfp_t mem_flags) 533fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell{ 534fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell int ret; 535fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 536fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell ret = alloc_temp_buffer(urb, mem_flags); 537fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (ret) 538fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return ret; 539fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 540fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags); 541fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (ret) 542fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell free_temp_buffer(urb); 543fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 544fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return ret; 545fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell} 546fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 547fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morellstatic void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) 548fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell{ 549fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell usb_hcd_unmap_urb_for_dma(hcd, urb); 550fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell free_temp_buffer(urb); 551fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell} 552fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 55379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic const struct hc_driver tegra_ehci_hc_driver = { 55479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .description = hcd_name, 55579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .product_desc = "Tegra EHCI Host Controller", 55679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .hcd_priv_size = sizeof(struct ehci_hcd), 55779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 55879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .flags = HCD_USB2 | HCD_MEMORY, 55979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 56079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .reset = tegra_ehci_setup, 56179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .irq = ehci_irq, 56279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 56379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .start = ehci_run, 56479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .stop = ehci_stop, 56579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .shutdown = tegra_ehci_shutdown, 56679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .urb_enqueue = ehci_urb_enqueue, 56779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .urb_dequeue = ehci_urb_dequeue, 568fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell .map_urb_for_dma = tegra_ehci_map_urb_for_dma, 569fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell .unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma, 57079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .endpoint_disable = ehci_endpoint_disable, 57179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .endpoint_reset = ehci_endpoint_reset, 57279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .get_frame_number = ehci_get_frame, 57379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .hub_status_data = ehci_hub_status_data, 57479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .hub_control = tegra_ehci_hub_control, 57579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, 57679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#ifdef CONFIG_PM 57779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .bus_suspend = tegra_ehci_bus_suspend, 57879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .bus_resume = tegra_ehci_bus_resume, 57979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#endif 58079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .relinquish_port = ehci_relinquish_port, 58179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .port_handed_over = ehci_port_handed_over, 58279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby}; 58379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 5844a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johanssonstatic int setup_vbus_gpio(struct platform_device *pdev) 5854a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson{ 5864a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson int err = 0; 5874a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson int gpio; 5884a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 5894a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson if (!pdev->dev.of_node) 5904a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson return 0; 5914a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 5924a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson gpio = of_get_named_gpio(pdev->dev.of_node, "nvidia,vbus-gpio", 0); 5934a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson if (!gpio_is_valid(gpio)) 5944a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson return 0; 5954a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 5964a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson err = gpio_request(gpio, "vbus_gpio"); 5974a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson if (err) { 5984a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson dev_err(&pdev->dev, "can't request vbus gpio %d", gpio); 5994a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson return err; 6004a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson } 6014a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson err = gpio_direction_output(gpio, 1); 6024a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson if (err) { 6034a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson dev_err(&pdev->dev, "can't enable vbus\n"); 6044a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson return err; 6054a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson } 6064a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson gpio_set_value(gpio, 1); 6074a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 6084a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson return err; 6094a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson} 6104a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 6114a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johanssonstatic u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32); 6124a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 61379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_probe(struct platform_device *pdev) 61479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 61579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct resource *res; 61679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct usb_hcd *hcd; 61779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra; 61879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_platform_data *pdata; 61979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int err = 0; 62079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int irq; 62179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int instance = pdev->id; 62279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 62379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pdata = pdev->dev.platform_data; 62479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!pdata) { 62579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Platform data missing\n"); 62679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return -EINVAL; 62779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 62879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 6294a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson /* Right now device-tree probed devices don't get dma_mask set. 6304a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson * Since shared usb code relies on it, set it here for now. 6314a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson * Once we have dma capability bindings this can go away. 6324a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson */ 6334a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson if (!pdev->dev.dma_mask) 6344a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson pdev->dev.dma_mask = &tegra_ehci_dma_mask; 6354a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 6364a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson setup_vbus_gpio(pdev); 6374a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 63879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra = kzalloc(sizeof(struct tegra_ehci_hcd), GFP_KERNEL); 63979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!tegra) 64079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return -ENOMEM; 64179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 64279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev, 64379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_name(&pdev->dev)); 64479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!hcd) { 64579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Unable to create HCD\n"); 64679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = -ENOMEM; 64779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto fail_hcd; 64879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 64979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 65079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby platform_set_drvdata(pdev, tegra); 65179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 65279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->clk = clk_get(&pdev->dev, NULL); 65379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (IS_ERR(tegra->clk)) { 65479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Can't get ehci clock\n"); 65579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = PTR_ERR(tegra->clk); 65679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto fail_clk; 65779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 65879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 65979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = clk_enable(tegra->clk); 66079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (err) 66179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto fail_clken; 66279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 66379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->emc_clk = clk_get(&pdev->dev, "emc"); 66479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (IS_ERR(tegra->emc_clk)) { 66579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Can't get emc clock\n"); 66679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = PTR_ERR(tegra->emc_clk); 66779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto fail_emc_clk; 66879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 66979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 67079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby clk_enable(tegra->emc_clk); 67179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby clk_set_rate(tegra->emc_clk, 400000000); 67279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 67379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 67479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!res) { 67579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to get I/O memory\n"); 67679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = -ENXIO; 67779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto fail_io; 67879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 67979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby hcd->rsrc_start = res->start; 68079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby hcd->rsrc_len = resource_size(res); 68179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby hcd->regs = ioremap(res->start, resource_size(res)); 68279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!hcd->regs) { 68379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to remap I/O memory\n"); 68479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = -ENOMEM; 68579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto fail_io; 68679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 68779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 6884a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson /* This is pretty ugly and needs to be fixed when we do only 6894a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson * device-tree probing. Old code relies on the platform_device 6904a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson * numbering that we lack for device-tree-instantiated devices. 6914a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson */ 6924a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson if (instance < 0) { 6934a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson switch (res->start) { 6944a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson case TEGRA_USB_BASE: 6954a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson instance = 0; 6964a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson break; 6974a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson case TEGRA_USB2_BASE: 6984a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson instance = 1; 6994a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson break; 7004a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson case TEGRA_USB3_BASE: 7014a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson instance = 2; 7024a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson break; 7034a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson default: 7044a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson err = -ENODEV; 7054a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson dev_err(&pdev->dev, "unknown usb instance\n"); 7064a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson goto fail_phy; 7074a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson } 7084a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson } 7094a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 71079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->phy = tegra_usb_phy_open(instance, hcd->regs, pdata->phy_config, 71179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby TEGRA_USB_PHY_MODE_HOST); 71279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (IS_ERR(tegra->phy)) { 71379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to open USB phy\n"); 71479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = -ENXIO; 71579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto fail_phy; 71679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 71779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 71879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = tegra_usb_phy_power_on(tegra->phy); 71979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (err) { 72079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to power on the phy\n"); 72179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto fail; 72279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 72379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 72479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->host_resumed = 1; 72579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->power_down_on_bus_suspend = pdata->power_down_on_bus_suspend; 72679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->ehci = hcd_to_ehci(hcd); 72779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 72879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby irq = platform_get_irq(pdev, 0); 72979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!irq) { 73079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to get IRQ\n"); 73179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = -ENODEV; 73279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto fail; 73379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 73479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby set_irq_flags(irq, IRQF_VALID); 73579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 73679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#ifdef CONFIG_USB_OTG_UTILS 73779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (pdata->operating_mode == TEGRA_USB_OTG) { 738b96d3b08365f5a9603f50f3aadca6012f7eaffa1Heikki Krogerus tegra->transceiver = usb_get_transceiver(); 73979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (tegra->transceiver) 7406e13c6505cdff9766d5268ffb8c972c1a2f996e6Heikki Krogerus otg_set_host(tegra->transceiver->otg, &hcd->self); 74179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 74279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#endif 74379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 744b5dd18d8747010e3f3eb1cc76a49f94291938559Yong Zhang err = usb_add_hcd(hcd, irq, IRQF_SHARED); 74579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (err) { 74679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to add USB HCD\n"); 74779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto fail; 74879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 74979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 75079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return err; 75179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 75279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobyfail: 75379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#ifdef CONFIG_USB_OTG_UTILS 75479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (tegra->transceiver) { 7556e13c6505cdff9766d5268ffb8c972c1a2f996e6Heikki Krogerus otg_set_host(tegra->transceiver->otg, NULL); 756b96d3b08365f5a9603f50f3aadca6012f7eaffa1Heikki Krogerus usb_put_transceiver(tegra->transceiver); 75779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 75879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#endif 75979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_usb_phy_close(tegra->phy); 76079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobyfail_phy: 76179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby iounmap(hcd->regs); 76279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobyfail_io: 76379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby clk_disable(tegra->emc_clk); 76479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby clk_put(tegra->emc_clk); 76579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobyfail_emc_clk: 76679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby clk_disable(tegra->clk); 76779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobyfail_clken: 76879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby clk_put(tegra->clk); 76979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobyfail_clk: 77079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby usb_put_hcd(hcd); 77179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobyfail_hcd: 77279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby kfree(tegra); 77379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return err; 77479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 77579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 77679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#ifdef CONFIG_PM 77779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_resume(struct platform_device *pdev) 77879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 77979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); 78079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); 78179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 78279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (tegra->bus_suspended) 78379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return 0; 78479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 78579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return tegra_usb_resume(hcd); 78679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 78779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 78879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_suspend(struct platform_device *pdev, pm_message_t state) 78979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 79079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); 79179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); 79279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 79379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (tegra->bus_suspended) 79479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return 0; 79579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 79679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (time_before(jiffies, tegra->ehci->next_statechange)) 79779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby msleep(10); 79879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 79979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return tegra_usb_suspend(hcd); 80079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 80179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#endif 80279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 80379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_remove(struct platform_device *pdev) 80479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 80579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); 80679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); 80779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 80879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (tegra == NULL || hcd == NULL) 80979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return -EINVAL; 81079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 81179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#ifdef CONFIG_USB_OTG_UTILS 81279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (tegra->transceiver) { 8136e13c6505cdff9766d5268ffb8c972c1a2f996e6Heikki Krogerus otg_set_host(tegra->transceiver->otg, NULL); 814b96d3b08365f5a9603f50f3aadca6012f7eaffa1Heikki Krogerus usb_put_transceiver(tegra->transceiver); 81579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 81679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#endif 81779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 81879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby usb_remove_hcd(hcd); 81979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby usb_put_hcd(hcd); 82079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 82179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_usb_phy_close(tegra->phy); 82279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby iounmap(hcd->regs); 82379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 82479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby clk_disable(tegra->clk); 82579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby clk_put(tegra->clk); 82679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 82779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby clk_disable(tegra->emc_clk); 82879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby clk_put(tegra->emc_clk); 82979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 83079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby kfree(tegra); 83179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return 0; 83279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 83379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 83479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic void tegra_ehci_hcd_shutdown(struct platform_device *pdev) 83579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 83679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); 83779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); 83879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 83979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (hcd->driver->shutdown) 84079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby hcd->driver->shutdown(hcd); 84179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 84279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 8434a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johanssonstatic struct of_device_id tegra_ehci_of_match[] __devinitdata = { 8444a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson { .compatible = "nvidia,tegra20-ehci", }, 8454a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson { }, 8464a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson}; 8474a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 84879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic struct platform_driver tegra_ehci_driver = { 84979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .probe = tegra_ehci_probe, 85079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .remove = tegra_ehci_remove, 85179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#ifdef CONFIG_PM 85279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .suspend = tegra_ehci_suspend, 85379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .resume = tegra_ehci_resume, 85479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#endif 85579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .shutdown = tegra_ehci_hcd_shutdown, 85679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .driver = { 85779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .name = "tegra-ehci", 8584a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson .of_match_table = tegra_ehci_of_match, 85979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 86079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby}; 861