ehci-tegra.c revision bbdabdb62d86090511410728644a19291bf300cf
179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby/* 279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * EHCI-compliant USB host controller driver for NVIDIA Tegra SoCs 379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * 479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * Copyright (C) 2010 Google, Inc. 5bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu * Copyright (C) 2009 - 2013 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> 20ded017ee6c7b90f7356bd8488f8af1c10ba90490Kishon Vijay Abraham I#include <linux/err.h> 2179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#include <linux/platform_device.h> 2279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#include <linux/platform_data/tegra_usb.h> 2379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#include <linux/irq.h> 2479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#include <linux/usb/otg.h> 254a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson#include <linux/gpio.h> 264a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson#include <linux/of.h> 274a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson#include <linux/of_gpio.h> 28ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern#include <linux/pm_runtime.h> 29bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu#include <linux/usb/ehci_def.h> 301ba8216f0bc02af6ba70d1108d60eb1b064395e4Venu Byravarasu#include <linux/usb/tegra_usb_phy.h> 3154388b281c877b2797bb0fc97c099fb7ffd5336aStephen Warren 3254388b281c877b2797bb0fc97c099fb7ffd5336aStephen Warren#define TEGRA_USB_BASE 0xC5000000 3354388b281c877b2797bb0fc97c099fb7ffd5336aStephen Warren#define TEGRA_USB2_BASE 0xC5004000 3454388b281c877b2797bb0fc97c099fb7ffd5336aStephen Warren#define TEGRA_USB3_BASE 0xC5008000 3579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 36bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu/* PORTSC registers */ 37bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu#define TEGRA_USB_PORTSC1 0x184 38bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu#define TEGRA_USB_PORTSC1_PTS(x) (((x) & 0x3) << 30) 39bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu#define TEGRA_USB_PORTSC1_PHCD (1 << 23) 40bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu 41fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell#define TEGRA_USB_DMA_ALIGN 32 42fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 4379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystruct tegra_ehci_hcd { 4479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct ehci_hcd *ehci; 4579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_usb_phy *phy; 4679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct clk *clk; 4779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct clk *emc_clk; 488675381109b0eb1c948a423c2b35e3f4509cb25eHeikki Krogerus struct usb_phy *transceiver; 4979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int host_resumed; 5079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int port_resuming; 51585355c5b54e2ecdcd6463aec264d907bc416727Venu Byravarasu bool needs_double_reset; 5279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby enum tegra_usb_phy_port_speed port_speed; 5379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby}; 5479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 5579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic void tegra_ehci_power_up(struct usb_hcd *hcd) 5679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 5779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); 5879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 5920de12ccf900d71eee1344adc7ae0dcd7db9b4abPrashant Gaikwad clk_prepare_enable(tegra->emc_clk); 6020de12ccf900d71eee1344adc7ae0dcd7db9b4abPrashant Gaikwad clk_prepare_enable(tegra->clk); 611ba8216f0bc02af6ba70d1108d60eb1b064395e4Venu Byravarasu usb_phy_set_suspend(&tegra->phy->u_phy, 0); 6279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->host_resumed = 1; 6379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 6479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 6579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic void tegra_ehci_power_down(struct usb_hcd *hcd) 6679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 6779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); 6879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 6979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->host_resumed = 0; 701ba8216f0bc02af6ba70d1108d60eb1b064395e4Venu Byravarasu usb_phy_set_suspend(&tegra->phy->u_phy, 1); 7120de12ccf900d71eee1344adc7ae0dcd7db9b4abPrashant Gaikwad clk_disable_unprepare(tegra->clk); 7220de12ccf900d71eee1344adc7ae0dcd7db9b4abPrashant Gaikwad clk_disable_unprepare(tegra->emc_clk); 7379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 7479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 751f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Linstatic int tegra_ehci_internal_port_reset( 761f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin struct ehci_hcd *ehci, 771f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin u32 __iomem *portsc_reg 781f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin) 791f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin{ 801f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin u32 temp; 811f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin unsigned long flags; 821f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin int retval = 0; 831f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin int i, tries; 841f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin u32 saved_usbintr; 851f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 861f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin spin_lock_irqsave(&ehci->lock, flags); 871f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin saved_usbintr = ehci_readl(ehci, &ehci->regs->intr_enable); 881f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* disable USB interrupt */ 891f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, 0, &ehci->regs->intr_enable); 901f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin spin_unlock_irqrestore(&ehci->lock, flags); 911f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 921f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* 931f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Here we have to do Port Reset at most twice for 941f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Port Enable bit to be set. 951f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin */ 961f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin for (i = 0; i < 2; i++) { 971f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp = ehci_readl(ehci, portsc_reg); 981f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp |= PORT_RESET; 991f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, temp, portsc_reg); 1001f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin mdelay(10); 1011f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp &= ~PORT_RESET; 1021f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, temp, portsc_reg); 1031f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin mdelay(1); 1041f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin tries = 100; 1051f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin do { 1061f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin mdelay(1); 1071f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* 1081f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Up to this point, Port Enable bit is 1091f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * expected to be set after 2 ms waiting. 1101f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * USB1 usually takes extra 45 ms, for safety, 1111f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * we take 100 ms as timeout. 1121f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin */ 1131f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp = ehci_readl(ehci, portsc_reg); 1141f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin } while (!(temp & PORT_PE) && tries--); 1151f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin if (temp & PORT_PE) 1161f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin break; 1171f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin } 1181f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin if (i == 2) 1191f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin retval = -ETIMEDOUT; 1201f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 1211f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* 1221f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Clear Connect Status Change bit if it's set. 1231f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * We can't clear PORT_PEC. It will also cause PORT_PE to be cleared. 1241f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin */ 1251f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin if (temp & PORT_CSC) 1261f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, PORT_CSC, portsc_reg); 1271f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 1281f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* 1291f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Write to clear any interrupt status bits that might be set 1301f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * during port reset. 1311f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin */ 1321f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp = ehci_readl(ehci, &ehci->regs->status); 1331f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, temp, &ehci->regs->status); 1341f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 1351f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* restore original interrupt enable bits */ 1361f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, saved_usbintr, &ehci->regs->intr_enable); 1371f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin return retval; 1381f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin} 1391f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 14079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_hub_control( 14179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct usb_hcd *hcd, 14279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u16 typeReq, 14379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u16 wValue, 14479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u16 wIndex, 14579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby char *buf, 14679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u16 wLength 14779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby) 14879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 14979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct ehci_hcd *ehci = hcd_to_ehci(hcd); 15079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); 15179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u32 __iomem *status_reg; 15279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u32 temp; 15379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby unsigned long flags; 15479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int retval = 0; 15579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 15679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1]; 15779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 15879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_lock_irqsave(&ehci->lock, flags); 15979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 1606d5f89c7b4fa5f8d6dc757982402c032183ffd8dStephen Warren if (typeReq == GetPortStatus) { 16179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp = ehci_readl(ehci, status_reg); 16279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (tegra->port_resuming && !(temp & PORT_SUSPEND)) { 16379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Resume completed, re-enable disconnect detection */ 16479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->port_resuming = 0; 16579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_usb_phy_postresume(tegra->phy); 16679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 16779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 16879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 16979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby else if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { 17079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp = ehci_readl(ehci, status_reg); 17179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) { 17279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby retval = -EPIPE; 17379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 17479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 17579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 176b08765749332c54c65c1a6515c01c6eb3fc1843eStephen Warren temp &= ~(PORT_RWC_BITS | PORT_WKCONN_E); 17779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp |= PORT_WKDISC_E | PORT_WKOC_E; 17879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); 17979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 18079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* 18179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * If a transaction is in progress, there may be a delay in 18279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * suspending the port. Poll until the port is suspended. 18379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby */ 18479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (handshake(ehci, status_reg, PORT_SUSPEND, 18579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby PORT_SUSPEND, 5000)) 18679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pr_err("%s: timeout waiting for SUSPEND\n", __func__); 18779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 18879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports); 18979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 19079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 19179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 1921f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* For USB1 port we need to issue Port Reset twice internally */ 193585355c5b54e2ecdcd6463aec264d907bc416727Venu Byravarasu if (tegra->needs_double_reset && 1941f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_RESET)) { 1951f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin spin_unlock_irqrestore(&ehci->lock, flags); 1961f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin return tegra_ehci_internal_port_reset(ehci, status_reg); 1971f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin } 1981f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 19979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* 20079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * Tegra host controller will time the resume operation to clear the bit 20179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * when the port control state switches to HS or FS Idle. This behavior 20279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * is different from EHCI where the host controller driver is required 20379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * to set this bit to a zero after the resume duration is timed in the 20479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * driver. 20579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby */ 20679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby else if (typeReq == ClearPortFeature && 20779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby wValue == USB_PORT_FEAT_SUSPEND) { 20879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp = ehci_readl(ehci, status_reg); 20979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if ((temp & PORT_RESET) || !(temp & PORT_PE)) { 21079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby retval = -EPIPE; 21179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 21279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 21379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 21479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!(temp & PORT_SUSPEND)) 21579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 21679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 21779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Disable disconnect detection during port resume */ 21879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_usb_phy_preresume(tegra->phy); 21979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 22079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25); 22179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 22279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); 22379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* start resume signalling */ 22479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_writel(ehci, temp | PORT_RESUME, status_reg); 225a448e4dc25303fe551e4dafe16c8c7c34f1b9d82Alan Stern set_bit(wIndex-1, &ehci->resuming_ports); 22679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 22779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_unlock_irqrestore(&ehci->lock, flags); 22879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby msleep(20); 22979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_lock_irqsave(&ehci->lock, flags); 23079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 23179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Poll until the controller clears RESUME and SUSPEND */ 23279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (handshake(ehci, status_reg, PORT_RESUME, 0, 2000)) 23379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pr_err("%s: timeout waiting for RESUME\n", __func__); 23479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (handshake(ehci, status_reg, PORT_SUSPEND, 0, 2000)) 23579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pr_err("%s: timeout waiting for SUSPEND\n", __func__); 23679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 23779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci->reset_done[wIndex-1] = 0; 238a448e4dc25303fe551e4dafe16c8c7c34f1b9d82Alan Stern clear_bit(wIndex-1, &ehci->resuming_ports); 23979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 24079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->port_resuming = 1; 24179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 24279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 24379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 24479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_unlock_irqrestore(&ehci->lock, flags); 24579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 24679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Handle the hub control events here */ 24779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); 24879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobydone: 24979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_unlock_irqrestore(&ehci->lock, flags); 25079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return retval; 25179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 25279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 25379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic void tegra_ehci_restart(struct usb_hcd *hcd) 25479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 25579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct ehci_hcd *ehci = hcd_to_ehci(hcd); 25679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 25779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_reset(ehci); 25879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 25979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* setup the frame list and Async q heads */ 26079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list); 26179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next); 26279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* setup the command register and set the controller in RUN mode */ 26379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); 26479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci->command |= CMD_RUN; 26579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_writel(ehci, ehci->command, &ehci->regs->command); 26679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 26779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby down_write(&ehci_cf_port_reset_rwsem); 26879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); 26979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* flush posted writes */ 27079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_readl(ehci, &ehci->regs->command); 27179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby up_write(&ehci_cf_port_reset_rwsem); 27279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 27379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 27479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic void tegra_ehci_shutdown(struct usb_hcd *hcd) 27579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 27679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); 27779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 27879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* ehci_shutdown touches the USB controller registers, make sure 27979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * controller has clocks to it */ 28079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!tegra->host_resumed) 28179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra_ehci_power_up(hcd); 28279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 28379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_shutdown(hcd); 28479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 28579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 28679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_setup(struct usb_hcd *hcd) 28779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 28879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct ehci_hcd *ehci = hcd_to_ehci(hcd); 28979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 29079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* EHCI registers start at offset 0x100 */ 29179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci->caps = hcd->regs + 0x100; 29279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 29379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* switch to host mode */ 29479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby hcd->has_tt = 1; 29579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 296c73cee717e7d5da0698acb720ad1219646fe4f46Alan Stern return ehci_setup(hcd); 29779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 29879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 299fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasustruct dma_aligned_buffer { 300fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell void *kmalloc_ptr; 301fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell void *old_xfer_buffer; 302fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell u8 data[0]; 303fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell}; 304fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 305fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasustatic void free_dma_aligned_buffer(struct urb *urb) 306fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell{ 307fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu struct dma_aligned_buffer *temp; 308fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 309fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) 310fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return; 311fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 312fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu temp = container_of(urb->transfer_buffer, 313fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu struct dma_aligned_buffer, data); 314fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 315fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu if (usb_urb_dir_in(urb)) 316fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell memcpy(temp->old_xfer_buffer, temp->data, 317fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer_length); 318fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer = temp->old_xfer_buffer; 319fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell kfree(temp->kmalloc_ptr); 320fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 321fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER; 322fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell} 323fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 324fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasustatic int alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags) 325fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell{ 326fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu struct dma_aligned_buffer *temp, *kmalloc_ptr; 327fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell size_t kmalloc_size; 328fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 329fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (urb->num_sgs || urb->sg || 330fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer_length == 0 || 331fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell !((uintptr_t)urb->transfer_buffer & (TEGRA_USB_DMA_ALIGN - 1))) 332fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return 0; 333fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 334fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell /* Allocate a buffer with enough padding for alignment */ 335fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell kmalloc_size = urb->transfer_buffer_length + 336fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu sizeof(struct dma_aligned_buffer) + TEGRA_USB_DMA_ALIGN - 1; 337fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 338fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell kmalloc_ptr = kmalloc(kmalloc_size, mem_flags); 339fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (!kmalloc_ptr) 340fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return -ENOMEM; 341fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 342fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu /* Position our struct dma_aligned_buffer such that data is aligned */ 343fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell temp = PTR_ALIGN(kmalloc_ptr + 1, TEGRA_USB_DMA_ALIGN) - 1; 344fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell temp->kmalloc_ptr = kmalloc_ptr; 345fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell temp->old_xfer_buffer = urb->transfer_buffer; 346fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu if (usb_urb_dir_out(urb)) 347fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell memcpy(temp->data, urb->transfer_buffer, 348fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer_length); 349fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer = temp->data; 350fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 351fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER; 352fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 353fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return 0; 354fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell} 355fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 356fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morellstatic int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, 357fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell gfp_t mem_flags) 358fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell{ 359fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell int ret; 360fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 361fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu ret = alloc_dma_aligned_buffer(urb, mem_flags); 362fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (ret) 363fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return ret; 364fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 365fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags); 366fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (ret) 367fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu free_dma_aligned_buffer(urb); 368fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 369fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return ret; 370fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell} 371fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 372fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morellstatic void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) 373fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell{ 374fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell usb_hcd_unmap_urb_for_dma(hcd, urb); 375fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu free_dma_aligned_buffer(urb); 376fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell} 377fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 37879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic const struct hc_driver tegra_ehci_hc_driver = { 37979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .description = hcd_name, 38079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .product_desc = "Tegra EHCI Host Controller", 38179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .hcd_priv_size = sizeof(struct ehci_hcd), 38279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .flags = HCD_USB2 | HCD_MEMORY, 38379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 384c6fa0b4c4e09a13e034a1c6c542dc2b3539ba1b8Venu Byravarasu /* standard ehci functions */ 38579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .irq = ehci_irq, 38679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .start = ehci_run, 38779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .stop = ehci_stop, 38879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .urb_enqueue = ehci_urb_enqueue, 38979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .urb_dequeue = ehci_urb_dequeue, 39079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .endpoint_disable = ehci_endpoint_disable, 39179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .endpoint_reset = ehci_endpoint_reset, 39279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .get_frame_number = ehci_get_frame, 39379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .hub_status_data = ehci_hub_status_data, 39479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, 395c6fa0b4c4e09a13e034a1c6c542dc2b3539ba1b8Venu Byravarasu .relinquish_port = ehci_relinquish_port, 396c6fa0b4c4e09a13e034a1c6c542dc2b3539ba1b8Venu Byravarasu .port_handed_over = ehci_port_handed_over, 397c6fa0b4c4e09a13e034a1c6c542dc2b3539ba1b8Venu Byravarasu 398c6fa0b4c4e09a13e034a1c6c542dc2b3539ba1b8Venu Byravarasu /* modified ehci functions for tegra */ 399c6fa0b4c4e09a13e034a1c6c542dc2b3539ba1b8Venu Byravarasu .reset = tegra_ehci_setup, 400c6fa0b4c4e09a13e034a1c6c542dc2b3539ba1b8Venu Byravarasu .shutdown = tegra_ehci_shutdown, 401c6fa0b4c4e09a13e034a1c6c542dc2b3539ba1b8Venu Byravarasu .map_urb_for_dma = tegra_ehci_map_urb_for_dma, 402c6fa0b4c4e09a13e034a1c6c542dc2b3539ba1b8Venu Byravarasu .unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma, 403c6fa0b4c4e09a13e034a1c6c542dc2b3539ba1b8Venu Byravarasu .hub_control = tegra_ehci_hub_control, 40479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#ifdef CONFIG_PM 405ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern .bus_suspend = ehci_bus_suspend, 406ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern .bus_resume = ehci_bus_resume, 40779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#endif 40879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby}; 40979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 410434103adea3f63f6550f4b2bd16653328f933a66Stephen Warrenstatic int setup_vbus_gpio(struct platform_device *pdev, 411434103adea3f63f6550f4b2bd16653328f933a66Stephen Warren struct tegra_ehci_platform_data *pdata) 4124a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson{ 4134a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson int err = 0; 4144a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson int gpio; 4154a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 416434103adea3f63f6550f4b2bd16653328f933a66Stephen Warren gpio = pdata->vbus_gpio; 417434103adea3f63f6550f4b2bd16653328f933a66Stephen Warren if (!gpio_is_valid(gpio)) 418434103adea3f63f6550f4b2bd16653328f933a66Stephen Warren gpio = of_get_named_gpio(pdev->dev.of_node, 419434103adea3f63f6550f4b2bd16653328f933a66Stephen Warren "nvidia,vbus-gpio", 0); 4204a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson if (!gpio_is_valid(gpio)) 4214a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson return 0; 4224a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 4234a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson err = gpio_request(gpio, "vbus_gpio"); 4244a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson if (err) { 4254a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson dev_err(&pdev->dev, "can't request vbus gpio %d", gpio); 4264a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson return err; 4274a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson } 4284a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson err = gpio_direction_output(gpio, 1); 4294a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson if (err) { 4304a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson dev_err(&pdev->dev, "can't enable vbus\n"); 4314a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson return err; 4324a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson } 4334a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 4344a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson return err; 4354a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson} 4364a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 437ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern#ifdef CONFIG_PM 438ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 439ebf20de453042c066a289b90dd14d59de03dba2fAlan Sternstatic int controller_suspend(struct device *dev) 440ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern{ 441ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern struct tegra_ehci_hcd *tegra = 442ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern platform_get_drvdata(to_platform_device(dev)); 443ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern struct ehci_hcd *ehci = tegra->ehci; 444ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern struct usb_hcd *hcd = ehci_to_hcd(ehci); 445ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern struct ehci_regs __iomem *hw = ehci->regs; 446ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern unsigned long flags; 447ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 448ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern if (time_before(jiffies, ehci->next_statechange)) 449ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern msleep(10); 450ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 451c4f3476436f7452b97c8accb5dd7d53219a11a3fAlan Stern ehci_halt(ehci); 452ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 453c4f3476436f7452b97c8accb5dd7d53219a11a3fAlan Stern spin_lock_irqsave(&ehci->lock, flags); 454ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3; 455ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 456ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern spin_unlock_irqrestore(&ehci->lock, flags); 457ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 458ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern tegra_ehci_power_down(hcd); 459ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern return 0; 460ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern} 461ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 462ebf20de453042c066a289b90dd14d59de03dba2fAlan Sternstatic int controller_resume(struct device *dev) 463ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern{ 464ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern struct tegra_ehci_hcd *tegra = 465ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern platform_get_drvdata(to_platform_device(dev)); 466ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern struct ehci_hcd *ehci = tegra->ehci; 467ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern struct usb_hcd *hcd = ehci_to_hcd(ehci); 468ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern struct ehci_regs __iomem *hw = ehci->regs; 469ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern unsigned long val; 470ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 471ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 472ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern tegra_ehci_power_up(hcd); 473ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 474ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) { 475ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern /* Wait for the phy to detect new devices 476ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern * before we restart the controller */ 477ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern msleep(10); 478ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern goto restart; 479ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern } 480ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 481ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern /* Force the phy to keep data lines in suspend state */ 482ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed); 483ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 484ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern /* Enable host mode */ 485ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern tdi_reset(ehci); 486ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 487ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern /* Enable Port Power */ 488ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern val = readl(&hw->port_status[0]); 489ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern val |= PORT_POWER; 490ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern writel(val, &hw->port_status[0]); 491ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern udelay(10); 492ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 493ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern /* Check if the phy resume from LP0. When the phy resume from LP0 494ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern * USB register will be reset. */ 495ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern if (!readl(&hw->async_next)) { 496ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern /* Program the field PTC based on the saved speed mode */ 497ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern val = readl(&hw->port_status[0]); 498ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern val &= ~PORT_TEST(~0); 499ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH) 500ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern val |= PORT_TEST_FORCE; 501ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL) 502ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern val |= PORT_TEST(6); 503ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) 504ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern val |= PORT_TEST(7); 505ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern writel(val, &hw->port_status[0]); 506ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern udelay(10); 507ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 508ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern /* Disable test mode by setting PTC field to NORMAL_OP */ 509ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern val = readl(&hw->port_status[0]); 510ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern val &= ~PORT_TEST(~0); 511ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern writel(val, &hw->port_status[0]); 512ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern udelay(10); 513ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern } 514ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 515ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern /* Poll until CCS is enabled */ 516ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern if (handshake(ehci, &hw->port_status[0], PORT_CONNECT, 517ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern PORT_CONNECT, 2000)) { 518ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__); 519ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern goto restart; 520ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern } 521ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 522ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern /* Poll until PE is enabled */ 523ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern if (handshake(ehci, &hw->port_status[0], PORT_PE, 524ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern PORT_PE, 2000)) { 525ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__); 526ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern goto restart; 527ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern } 528ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 529ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern /* Clear the PCI status, to avoid an interrupt taken upon resume */ 530ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern val = readl(&hw->status); 531ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern val |= STS_PCD; 532ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern writel(val, &hw->status); 533ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 534ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */ 535ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern val = readl(&hw->port_status[0]); 536ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern if ((val & PORT_POWER) && (val & PORT_PE)) { 537ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern val |= PORT_SUSPEND; 538ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern writel(val, &hw->port_status[0]); 539ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 540ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern /* Wait until port suspend completes */ 541ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND, 542ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern PORT_SUSPEND, 1000)) { 543ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern pr_err("%s: timeout waiting for PORT_SUSPEND\n", 544ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern __func__); 545ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern goto restart; 546ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern } 547ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern } 548ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 549ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern tegra_ehci_phy_restore_end(tegra->phy); 550ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern goto done; 551ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 552ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern restart: 553ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH) 554ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern tegra_ehci_phy_restore_end(tegra->phy); 555ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 556ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern tegra_ehci_restart(hcd); 557ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 558ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern done: 559ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern tegra_usb_phy_preresume(tegra->phy); 560ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern tegra->port_resuming = 1; 561ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern return 0; 562ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern} 563ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 564ebf20de453042c066a289b90dd14d59de03dba2fAlan Sternstatic int tegra_ehci_suspend(struct device *dev) 565ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern{ 566ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern struct tegra_ehci_hcd *tegra = 567ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern platform_get_drvdata(to_platform_device(dev)); 568ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); 569ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern int rc = 0; 570ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 571ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern /* 572ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern * When system sleep is supported and USB controller wakeup is 573ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern * implemented: If the controller is runtime-suspended and the 574ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern * wakeup setting needs to be changed, call pm_runtime_resume(). 575ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern */ 576ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern if (HCD_HW_ACCESSIBLE(hcd)) 577ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern rc = controller_suspend(dev); 578ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern return rc; 579ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern} 580ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 581ebf20de453042c066a289b90dd14d59de03dba2fAlan Sternstatic int tegra_ehci_resume(struct device *dev) 582ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern{ 583ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern int rc; 584ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 585ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern rc = controller_resume(dev); 586ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern if (rc == 0) { 587ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern pm_runtime_disable(dev); 588ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern pm_runtime_set_active(dev); 589ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern pm_runtime_enable(dev); 590ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern } 591ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern return rc; 592ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern} 593ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 594ebf20de453042c066a289b90dd14d59de03dba2fAlan Sternstatic int tegra_ehci_runtime_suspend(struct device *dev) 595ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern{ 596ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern return controller_suspend(dev); 597ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern} 598ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 599ebf20de453042c066a289b90dd14d59de03dba2fAlan Sternstatic int tegra_ehci_runtime_resume(struct device *dev) 600ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern{ 601ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern return controller_resume(dev); 602ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern} 603ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 604ebf20de453042c066a289b90dd14d59de03dba2fAlan Sternstatic const struct dev_pm_ops tegra_ehci_pm_ops = { 605ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern .suspend = tegra_ehci_suspend, 606ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern .resume = tegra_ehci_resume, 607ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern .runtime_suspend = tegra_ehci_runtime_suspend, 608ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern .runtime_resume = tegra_ehci_runtime_resume, 609ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern}; 610ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 611ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern#endif 612ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 613bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu/* Bits of PORTSC1, which will get cleared by writing 1 into them */ 614bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu#define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) 615bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu 616bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasuvoid tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val) 617bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu{ 618bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu unsigned long val; 619bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu struct usb_hcd *hcd = bus_to_hcd(x->otg->host); 620bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu void __iomem *base = hcd->regs; 621bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu 622bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS; 623bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu val &= ~TEGRA_USB_PORTSC1_PTS(3); 624bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3); 625bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu writel(val, base + TEGRA_USB_PORTSC1); 626bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu} 627bbdabdb62d86090511410728644a19291bf300cfVenu ByravarasuEXPORT_SYMBOL_GPL(tegra_ehci_set_pts); 628bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu 629bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasuvoid tegra_ehci_set_phcd(struct usb_phy *x, bool enable) 630bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu{ 631bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu unsigned long val; 632bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu struct usb_hcd *hcd = bus_to_hcd(x->otg->host); 633bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu void __iomem *base = hcd->regs; 634bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu 635bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS; 636bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu if (enable) 637bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu val |= TEGRA_USB_PORTSC1_PHCD; 638bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu else 639bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu val &= ~TEGRA_USB_PORTSC1_PHCD; 640bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu writel(val, base + TEGRA_USB_PORTSC1); 641bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu} 642bbdabdb62d86090511410728644a19291bf300cfVenu ByravarasuEXPORT_SYMBOL_GPL(tegra_ehci_set_phcd); 643bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu 6444a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johanssonstatic u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32); 6454a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 64679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_probe(struct platform_device *pdev) 64779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 64879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct resource *res; 64979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct usb_hcd *hcd; 65079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra; 65179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_platform_data *pdata; 65279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int err = 0; 65379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int irq; 65479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int instance = pdev->id; 655bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu struct usb_phy *u_phy; 65679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 65779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pdata = pdev->dev.platform_data; 65879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!pdata) { 65979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Platform data missing\n"); 66079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return -EINVAL; 66179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 66279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 6634a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson /* Right now device-tree probed devices don't get dma_mask set. 6644a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson * Since shared usb code relies on it, set it here for now. 6654a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson * Once we have dma capability bindings this can go away. 6664a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson */ 6674a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson if (!pdev->dev.dma_mask) 6684a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson pdev->dev.dma_mask = &tegra_ehci_dma_mask; 6694a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 670434103adea3f63f6550f4b2bd16653328f933a66Stephen Warren setup_vbus_gpio(pdev, pdata); 6714a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 672bc2ff98ffa52d36b5df925a1f783ff2e035ed55eJulia Lawall tegra = devm_kzalloc(&pdev->dev, sizeof(struct tegra_ehci_hcd), 673bc2ff98ffa52d36b5df925a1f783ff2e035ed55eJulia Lawall GFP_KERNEL); 67479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!tegra) 67579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return -ENOMEM; 67679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 67779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev, 67879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_name(&pdev->dev)); 67979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!hcd) { 68079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Unable to create HCD\n"); 681bc2ff98ffa52d36b5df925a1f783ff2e035ed55eJulia Lawall return -ENOMEM; 68279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 68379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 68479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby platform_set_drvdata(pdev, tegra); 68579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 686bc2ff98ffa52d36b5df925a1f783ff2e035ed55eJulia Lawall tegra->clk = devm_clk_get(&pdev->dev, NULL); 68779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (IS_ERR(tegra->clk)) { 68879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Can't get ehci clock\n"); 68979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = PTR_ERR(tegra->clk); 69079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto fail_clk; 69179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 69279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 69320de12ccf900d71eee1344adc7ae0dcd7db9b4abPrashant Gaikwad err = clk_prepare_enable(tegra->clk); 69479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (err) 695bc2ff98ffa52d36b5df925a1f783ff2e035ed55eJulia Lawall goto fail_clk; 69679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 697bc2ff98ffa52d36b5df925a1f783ff2e035ed55eJulia Lawall tegra->emc_clk = devm_clk_get(&pdev->dev, "emc"); 69879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (IS_ERR(tegra->emc_clk)) { 69979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Can't get emc clock\n"); 70079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = PTR_ERR(tegra->emc_clk); 70179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto fail_emc_clk; 70279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 70379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 70420de12ccf900d71eee1344adc7ae0dcd7db9b4abPrashant Gaikwad clk_prepare_enable(tegra->emc_clk); 70579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby clk_set_rate(tegra->emc_clk, 400000000); 70679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 707585355c5b54e2ecdcd6463aec264d907bc416727Venu Byravarasu tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node, 708585355c5b54e2ecdcd6463aec264d907bc416727Venu Byravarasu "nvidia,needs-double-reset"); 709585355c5b54e2ecdcd6463aec264d907bc416727Venu Byravarasu 71079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 71179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!res) { 71279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to get I/O memory\n"); 71379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = -ENXIO; 71479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto fail_io; 71579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 71679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby hcd->rsrc_start = res->start; 71779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby hcd->rsrc_len = resource_size(res); 718bc2ff98ffa52d36b5df925a1f783ff2e035ed55eJulia Lawall hcd->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 71979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!hcd->regs) { 72079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to remap I/O memory\n"); 72179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = -ENOMEM; 72279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto fail_io; 72379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 72479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 7254a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson /* This is pretty ugly and needs to be fixed when we do only 7264a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson * device-tree probing. Old code relies on the platform_device 7274a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson * numbering that we lack for device-tree-instantiated devices. 7284a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson */ 7294a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson if (instance < 0) { 7304a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson switch (res->start) { 7314a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson case TEGRA_USB_BASE: 7324a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson instance = 0; 7334a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson break; 7344a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson case TEGRA_USB2_BASE: 7354a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson instance = 1; 7364a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson break; 7374a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson case TEGRA_USB3_BASE: 7384a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson instance = 2; 7394a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson break; 7404a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson default: 7414a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson err = -ENODEV; 7424a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson dev_err(&pdev->dev, "unknown usb instance\n"); 743bc2ff98ffa52d36b5df925a1f783ff2e035ed55eJulia Lawall goto fail_io; 7444a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson } 7454a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson } 7464a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 747aa607ebf93a5fc26275a575781399df971dd1b91Stephen Warren tegra->phy = tegra_usb_phy_open(&pdev->dev, instance, hcd->regs, 748aa607ebf93a5fc26275a575781399df971dd1b91Stephen Warren pdata->phy_config, 749aa607ebf93a5fc26275a575781399df971dd1b91Stephen Warren TEGRA_USB_PHY_MODE_HOST); 75079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (IS_ERR(tegra->phy)) { 75179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to open USB phy\n"); 75279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = -ENXIO; 753bc2ff98ffa52d36b5df925a1f783ff2e035ed55eJulia Lawall goto fail_io; 75479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 75579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 7561ba8216f0bc02af6ba70d1108d60eb1b064395e4Venu Byravarasu usb_phy_init(&tegra->phy->u_phy); 7571ba8216f0bc02af6ba70d1108d60eb1b064395e4Venu Byravarasu 758bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu hcd->phy = u_phy = &tegra->phy->u_phy; 759bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu u_phy->otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg), 760bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu GFP_KERNEL); 761bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu if (!u_phy->otg) { 762bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu dev_err(&pdev->dev, "Failed to alloc memory for otg\n"); 763bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu err = -ENOMEM; 764bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu goto fail_io; 765bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu } 766bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu u_phy->otg->host = hcd_to_bus(hcd); 767bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu 7681ba8216f0bc02af6ba70d1108d60eb1b064395e4Venu Byravarasu err = usb_phy_set_suspend(&tegra->phy->u_phy, 0); 76979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (err) { 77079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to power on the phy\n"); 77179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto fail; 77279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 77379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 77479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->host_resumed = 1; 77579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->ehci = hcd_to_ehci(hcd); 77679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 77779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby irq = platform_get_irq(pdev, 0); 77879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!irq) { 77979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to get IRQ\n"); 78079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = -ENODEV; 78179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto fail; 78279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 78379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 78479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#ifdef CONFIG_USB_OTG_UTILS 78579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (pdata->operating_mode == TEGRA_USB_OTG) { 786bc2ff98ffa52d36b5df925a1f783ff2e035ed55eJulia Lawall tegra->transceiver = 787bc2ff98ffa52d36b5df925a1f783ff2e035ed55eJulia Lawall devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); 788ded017ee6c7b90f7356bd8488f8af1c10ba90490Kishon Vijay Abraham I if (!IS_ERR_OR_NULL(tegra->transceiver)) 7896e13c6505cdff9766d5268ffb8c972c1a2f996e6Heikki Krogerus otg_set_host(tegra->transceiver->otg, &hcd->self); 79079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 79179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#endif 79279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 793b5dd18d8747010e3f3eb1cc76a49f94291938559Yong Zhang err = usb_add_hcd(hcd, irq, IRQF_SHARED); 79479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (err) { 79579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to add USB HCD\n"); 79679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto fail; 79779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 79879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 799ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern pm_runtime_set_active(&pdev->dev); 800ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern pm_runtime_get_noresume(&pdev->dev); 801ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 802ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern /* Don't skip the pm_runtime_forbid call if wakeup isn't working */ 803ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern /* if (!pdata->power_down_on_bus_suspend) */ 804ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern pm_runtime_forbid(&pdev->dev); 805ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern pm_runtime_enable(&pdev->dev); 806ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern pm_runtime_put_sync(&pdev->dev); 80779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return err; 80879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 80979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobyfail: 81079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#ifdef CONFIG_USB_OTG_UTILS 811bc2ff98ffa52d36b5df925a1f783ff2e035ed55eJulia Lawall if (!IS_ERR_OR_NULL(tegra->transceiver)) 8126e13c6505cdff9766d5268ffb8c972c1a2f996e6Heikki Krogerus otg_set_host(tegra->transceiver->otg, NULL); 81379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#endif 8141ba8216f0bc02af6ba70d1108d60eb1b064395e4Venu Byravarasu usb_phy_shutdown(&tegra->phy->u_phy); 81579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobyfail_io: 81620de12ccf900d71eee1344adc7ae0dcd7db9b4abPrashant Gaikwad clk_disable_unprepare(tegra->emc_clk); 81779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobyfail_emc_clk: 81820de12ccf900d71eee1344adc7ae0dcd7db9b4abPrashant Gaikwad clk_disable_unprepare(tegra->clk); 81979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobyfail_clk: 82079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby usb_put_hcd(hcd); 82179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return err; 82279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 82379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 82479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_remove(struct platform_device *pdev) 82579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 82679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); 82779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); 82879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 829ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern pm_runtime_get_sync(&pdev->dev); 830ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern pm_runtime_disable(&pdev->dev); 831ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern pm_runtime_put_noidle(&pdev->dev); 832ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern 83379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#ifdef CONFIG_USB_OTG_UTILS 834bc2ff98ffa52d36b5df925a1f783ff2e035ed55eJulia Lawall if (!IS_ERR_OR_NULL(tegra->transceiver)) 8356e13c6505cdff9766d5268ffb8c972c1a2f996e6Heikki Krogerus otg_set_host(tegra->transceiver->otg, NULL); 83679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby#endif 83779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 83879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby usb_remove_hcd(hcd); 839ecc8a0cdca18df5c9a7e84ab29160259123f3ae5Venu Byravarasu usb_put_hcd(hcd); 840ecc8a0cdca18df5c9a7e84ab29160259123f3ae5Venu Byravarasu 8411ba8216f0bc02af6ba70d1108d60eb1b064395e4Venu Byravarasu usb_phy_shutdown(&tegra->phy->u_phy); 84279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 84320de12ccf900d71eee1344adc7ae0dcd7db9b4abPrashant Gaikwad clk_disable_unprepare(tegra->clk); 84479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 84520de12ccf900d71eee1344adc7ae0dcd7db9b4abPrashant Gaikwad clk_disable_unprepare(tegra->emc_clk); 84679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 84779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return 0; 84879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 84979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 85079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic void tegra_ehci_hcd_shutdown(struct platform_device *pdev) 85179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 85279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); 85379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); 85479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 85579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (hcd->driver->shutdown) 85679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby hcd->driver->shutdown(hcd); 85779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 85879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 859d3608b6dafc570bb671c3338288eb2523f8cd52aBill Pembertonstatic struct of_device_id tegra_ehci_of_match[] = { 8604a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson { .compatible = "nvidia,tegra20-ehci", }, 8614a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson { }, 8624a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson}; 8634a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 86479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic struct platform_driver tegra_ehci_driver = { 86579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .probe = tegra_ehci_probe, 86679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .remove = tegra_ehci_remove, 86779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .shutdown = tegra_ehci_hcd_shutdown, 86879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .driver = { 86979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .name = "tegra-ehci", 8704a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson .of_match_table = tegra_ehci_of_match, 871ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern#ifdef CONFIG_PM 872ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern .pm = &tegra_ehci_pm_ops, 873ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern#endif 87479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 87579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby}; 876