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> 209fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#include <linux/dma-mapping.h> 21ded017ee6c7b90f7356bd8488f8af1c10ba90490Kishon Vijay Abraham I#include <linux/err.h> 224a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson#include <linux/gpio.h> 239fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#include <linux/io.h> 249fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#include <linux/irq.h> 259fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#include <linux/module.h> 264a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson#include <linux/of.h> 27327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen#include <linux/of_device.h> 284a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson#include <linux/of_gpio.h> 299fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#include <linux/platform_device.h> 30ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern#include <linux/pm_runtime.h> 3175606f5d32fabef51c1337eac274492c0470d774Stephen Warren#include <linux/reset.h> 329fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#include <linux/slab.h> 33bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu#include <linux/usb/ehci_def.h> 341ba8216f0bc02af6ba70d1108d60eb1b064395e4Venu Byravarasu#include <linux/usb/tegra_usb_phy.h> 359fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#include <linux/usb.h> 369fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#include <linux/usb/hcd.h> 379fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#include <linux/usb/otg.h> 389fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 399fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#include "ehci.h" 4054388b281c877b2797bb0fc97c099fb7ffd5336aStephen Warren 419fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) 429fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 43fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell#define TEGRA_USB_DMA_ALIGN 32 44fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 459fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#define DRIVER_DESC "Tegra EHCI driver" 469fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#define DRV_NAME "tegra-ehci" 479fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 489fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudarstatic struct hc_driver __read_mostly tegra_ehci_hc_driver; 49a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynenstatic bool usb1_reset_attempted; 509fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 51327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynenstruct tegra_ehci_soc_config { 52327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen bool has_hostpc; 53327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen}; 54327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen 5579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystruct tegra_ehci_hcd { 5679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_usb_phy *phy; 5779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct clk *clk; 5875606f5d32fabef51c1337eac274492c0470d774Stephen Warren struct reset_control *rst; 5979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int port_resuming; 60585355c5b54e2ecdcd6463aec264d907bc416727Venu Byravarasu bool needs_double_reset; 6179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby enum tegra_usb_phy_port_speed port_speed; 6279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby}; 6379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 64a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen/* 65a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen * The 1st USB controller contains some UTMI pad registers that are global for 66a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen * all the controllers on the chip. Those registers are also cleared when 67a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen * reset is asserted to the 1st controller. This means that the 1st controller 68a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen * can only be reset when no other controlled has finished probing. So we'll 69a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen * reset the 1st controller before doing any other setup on any of the 70a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen * controllers, and then never again. 71a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen * 72a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen * Since this is a PHY issue, the Tegra PHY driver should probably be doing 73a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen * the resetting of the USB controllers. But to keep compatibility with old 74a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen * device trees that don't have reset phandles in the PHYs, do it here. 75a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen * Those old DTs will be vulnerable to total USB breakage if the 1st EHCI 76a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen * device isn't the first one to finish probing, so warn them. 77a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen */ 78a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynenstatic int tegra_reset_usb_controller(struct platform_device *pdev) 79a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen{ 80a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen struct device_node *phy_np; 81a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen struct usb_hcd *hcd = platform_get_drvdata(pdev); 82a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen struct tegra_ehci_hcd *tegra = 83a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen (struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv; 84a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen 85a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen phy_np = of_parse_phandle(pdev->dev.of_node, "nvidia,phy", 0); 86a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen if (!phy_np) 87a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen return -ENOENT; 88a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen 89a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen if (!usb1_reset_attempted) { 90a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen struct reset_control *usb1_reset; 91a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen 92a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen usb1_reset = of_reset_control_get(phy_np, "usb"); 93a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen if (IS_ERR(usb1_reset)) { 94a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen dev_warn(&pdev->dev, 95a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen "can't get utmi-pads reset from the PHY\n"); 96a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen dev_warn(&pdev->dev, 97a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen "continuing, but please update your DT\n"); 98a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen } else { 99a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen reset_control_assert(usb1_reset); 100a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen udelay(1); 101a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen reset_control_deassert(usb1_reset); 102a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen } 103a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen 104a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen reset_control_put(usb1_reset); 105a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen usb1_reset_attempted = true; 106a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen } 107a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen 108a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen if (!of_property_read_bool(phy_np, "nvidia,has-utmi-pad-registers")) { 109a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen reset_control_assert(tegra->rst); 110a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen udelay(1); 111a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen reset_control_deassert(tegra->rst); 112a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen } 113a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen 114a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen of_node_put(phy_np); 115a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen 116a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen return 0; 117a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen} 118a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen 1191f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Linstatic int tegra_ehci_internal_port_reset( 1201f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin struct ehci_hcd *ehci, 1211f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin u32 __iomem *portsc_reg 1221f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin) 1231f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin{ 1241f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin u32 temp; 1251f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin unsigned long flags; 1261f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin int retval = 0; 1271f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin int i, tries; 1281f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin u32 saved_usbintr; 1291f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 1301f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin spin_lock_irqsave(&ehci->lock, flags); 1311f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin saved_usbintr = ehci_readl(ehci, &ehci->regs->intr_enable); 1321f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* disable USB interrupt */ 1331f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, 0, &ehci->regs->intr_enable); 1341f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin spin_unlock_irqrestore(&ehci->lock, flags); 1351f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 1361f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* 1371f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Here we have to do Port Reset at most twice for 1381f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Port Enable bit to be set. 1391f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin */ 1401f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin for (i = 0; i < 2; i++) { 1411f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp = ehci_readl(ehci, portsc_reg); 1421f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp |= PORT_RESET; 1431f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, temp, portsc_reg); 1441f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin mdelay(10); 1451f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp &= ~PORT_RESET; 1461f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, temp, portsc_reg); 1471f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin mdelay(1); 1481f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin tries = 100; 1491f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin do { 1501f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin mdelay(1); 1511f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* 1521f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Up to this point, Port Enable bit is 1531f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * expected to be set after 2 ms waiting. 1541f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * USB1 usually takes extra 45 ms, for safety, 1551f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * we take 100 ms as timeout. 1561f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin */ 1571f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp = ehci_readl(ehci, portsc_reg); 1581f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin } while (!(temp & PORT_PE) && tries--); 1591f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin if (temp & PORT_PE) 1601f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin break; 1611f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin } 1621f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin if (i == 2) 1631f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin retval = -ETIMEDOUT; 1641f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 1651f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* 1661f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Clear Connect Status Change bit if it's set. 1671f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * We can't clear PORT_PEC. It will also cause PORT_PE to be cleared. 1681f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin */ 1691f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin if (temp & PORT_CSC) 1701f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, PORT_CSC, portsc_reg); 1711f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 1721f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* 1731f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Write to clear any interrupt status bits that might be set 1741f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * during port reset. 1751f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin */ 1761f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp = ehci_readl(ehci, &ehci->regs->status); 1771f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, temp, &ehci->regs->status); 1781f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 1791f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* restore original interrupt enable bits */ 1801f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, saved_usbintr, &ehci->regs->intr_enable); 1811f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin return retval; 1821f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin} 1831f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 18479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_hub_control( 18579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct usb_hcd *hcd, 18679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u16 typeReq, 18779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u16 wValue, 18879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u16 wIndex, 18979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby char *buf, 19079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u16 wLength 19179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby) 19279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 193c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren struct ehci_hcd *ehci = hcd_to_ehci(hcd); 194c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren struct tegra_ehci_hcd *tegra = (struct tegra_ehci_hcd *)ehci->priv; 19579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u32 __iomem *status_reg; 19679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u32 temp; 19779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby unsigned long flags; 19879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int retval = 0; 19979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 20079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1]; 20179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 20279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_lock_irqsave(&ehci->lock, flags); 20379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 2046d5f89c7b4fa5f8d6dc757982402c032183ffd8dStephen Warren if (typeReq == GetPortStatus) { 20579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp = ehci_readl(ehci, status_reg); 20679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (tegra->port_resuming && !(temp & PORT_SUSPEND)) { 20779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Resume completed, re-enable disconnect detection */ 20879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->port_resuming = 0; 2093d46e73dfdb840f460e5b06416965d132570ec33Antoine Tenart tegra_usb_phy_postresume(hcd->usb_phy); 21079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 21179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 21279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 21379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby else if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { 21479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp = ehci_readl(ehci, status_reg); 21579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) { 21679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby retval = -EPIPE; 21779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 21879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 21979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 220b08765749332c54c65c1a6515c01c6eb3fc1843eStephen Warren temp &= ~(PORT_RWC_BITS | PORT_WKCONN_E); 22179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp |= PORT_WKDISC_E | PORT_WKOC_E; 22279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); 22379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 22479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* 22579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * If a transaction is in progress, there may be a delay in 22679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * suspending the port. Poll until the port is suspended. 22779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby */ 2282f3a6b86528994027c8241f9666f0fbcf3d3130bManjunath Goudar if (ehci_handshake(ehci, status_reg, PORT_SUSPEND, 22979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby PORT_SUSPEND, 5000)) 23079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pr_err("%s: timeout waiting for SUSPEND\n", __func__); 23179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 23279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports); 23379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 23479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 23579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 2361f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* For USB1 port we need to issue Port Reset twice internally */ 237585355c5b54e2ecdcd6463aec264d907bc416727Venu Byravarasu if (tegra->needs_double_reset && 2381f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_RESET)) { 2391f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin spin_unlock_irqrestore(&ehci->lock, flags); 2401f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin return tegra_ehci_internal_port_reset(ehci, status_reg); 2411f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin } 2421f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 24379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* 24479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * Tegra host controller will time the resume operation to clear the bit 24579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * when the port control state switches to HS or FS Idle. This behavior 24679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * is different from EHCI where the host controller driver is required 24779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * to set this bit to a zero after the resume duration is timed in the 24879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * driver. 24979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby */ 25079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby else if (typeReq == ClearPortFeature && 25179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby wValue == USB_PORT_FEAT_SUSPEND) { 25279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp = ehci_readl(ehci, status_reg); 25379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if ((temp & PORT_RESET) || !(temp & PORT_PE)) { 25479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby retval = -EPIPE; 25579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 25679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 25779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 25879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!(temp & PORT_SUSPEND)) 25979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 26079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 26179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Disable disconnect detection during port resume */ 2623d46e73dfdb840f460e5b06416965d132570ec33Antoine Tenart tegra_usb_phy_preresume(hcd->usb_phy); 26379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 26479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25); 26579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 26679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); 26779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* start resume signalling */ 26879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_writel(ehci, temp | PORT_RESUME, status_reg); 269a448e4dc25303fe551e4dafe16c8c7c34f1b9d82Alan Stern set_bit(wIndex-1, &ehci->resuming_ports); 27079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 27179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_unlock_irqrestore(&ehci->lock, flags); 27279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby msleep(20); 27379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_lock_irqsave(&ehci->lock, flags); 27479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 27579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Poll until the controller clears RESUME and SUSPEND */ 2762f3a6b86528994027c8241f9666f0fbcf3d3130bManjunath Goudar if (ehci_handshake(ehci, status_reg, PORT_RESUME, 0, 2000)) 27779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pr_err("%s: timeout waiting for RESUME\n", __func__); 2782f3a6b86528994027c8241f9666f0fbcf3d3130bManjunath Goudar if (ehci_handshake(ehci, status_reg, PORT_SUSPEND, 0, 2000)) 27979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pr_err("%s: timeout waiting for SUSPEND\n", __func__); 28079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 28179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci->reset_done[wIndex-1] = 0; 282a448e4dc25303fe551e4dafe16c8c7c34f1b9d82Alan Stern clear_bit(wIndex-1, &ehci->resuming_ports); 28379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 28479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->port_resuming = 1; 28579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 28679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 28779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 28879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_unlock_irqrestore(&ehci->lock, flags); 28979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 29079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Handle the hub control events here */ 29137769939082ae0749405133e09eac2c3ccb8fcf0Laurent Pinchart return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); 2929fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 29379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobydone: 29479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_unlock_irqrestore(&ehci->lock, flags); 29579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return retval; 29679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 29779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 298fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasustruct dma_aligned_buffer { 299fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell void *kmalloc_ptr; 300fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell void *old_xfer_buffer; 301fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell u8 data[0]; 302fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell}; 303fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 304fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasustatic void free_dma_aligned_buffer(struct urb *urb) 305fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell{ 306fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu struct dma_aligned_buffer *temp; 307fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 308fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) 309fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return; 310fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 311fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu temp = container_of(urb->transfer_buffer, 312fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu struct dma_aligned_buffer, data); 313fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 314fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu if (usb_urb_dir_in(urb)) 315fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell memcpy(temp->old_xfer_buffer, temp->data, 316fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer_length); 317fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer = temp->old_xfer_buffer; 318fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell kfree(temp->kmalloc_ptr); 319fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 320fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER; 321fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell} 322fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 323fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasustatic int alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags) 324fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell{ 325fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu struct dma_aligned_buffer *temp, *kmalloc_ptr; 326fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell size_t kmalloc_size; 327fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 328fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (urb->num_sgs || urb->sg || 329fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer_length == 0 || 330fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell !((uintptr_t)urb->transfer_buffer & (TEGRA_USB_DMA_ALIGN - 1))) 331fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return 0; 332fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 333fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell /* Allocate a buffer with enough padding for alignment */ 334fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell kmalloc_size = urb->transfer_buffer_length + 335fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu sizeof(struct dma_aligned_buffer) + TEGRA_USB_DMA_ALIGN - 1; 336fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 337fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell kmalloc_ptr = kmalloc(kmalloc_size, mem_flags); 338fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (!kmalloc_ptr) 339fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return -ENOMEM; 340fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 341fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu /* Position our struct dma_aligned_buffer such that data is aligned */ 342fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell temp = PTR_ALIGN(kmalloc_ptr + 1, TEGRA_USB_DMA_ALIGN) - 1; 343fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell temp->kmalloc_ptr = kmalloc_ptr; 344fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell temp->old_xfer_buffer = urb->transfer_buffer; 345fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu if (usb_urb_dir_out(urb)) 346fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell memcpy(temp->data, urb->transfer_buffer, 347fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer_length); 348fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer = temp->data; 349fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 350fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER; 351fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 352fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return 0; 353fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell} 354fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 355fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morellstatic int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, 356fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell gfp_t mem_flags) 357fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell{ 358fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell int ret; 359fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 360fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu ret = alloc_dma_aligned_buffer(urb, mem_flags); 361fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (ret) 362fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return ret; 363fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 364fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags); 365fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (ret) 366fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu free_dma_aligned_buffer(urb); 367fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 368fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return ret; 369fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell} 370fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 371fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morellstatic void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) 372fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell{ 373fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell usb_hcd_unmap_urb_for_dma(hcd, urb); 374fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu free_dma_aligned_buffer(urb); 375fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell} 376fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 377327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynenstatic const struct tegra_ehci_soc_config tegra30_soc_config = { 378327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen .has_hostpc = true, 379327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen}; 380327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen 381327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynenstatic const struct tegra_ehci_soc_config tegra20_soc_config = { 382327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen .has_hostpc = false, 383327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen}; 384327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen 3851b45049a37a67912ac15b7ae07ad1a095de2f669Jingoo Hanstatic const struct of_device_id tegra_ehci_of_match[] = { 386327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen { .compatible = "nvidia,tegra30-ehci", .data = &tegra30_soc_config }, 387327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen { .compatible = "nvidia,tegra20-ehci", .data = &tegra20_soc_config }, 388327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen { }, 389327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen}; 390327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen 39179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_probe(struct platform_device *pdev) 39279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 393327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen const struct of_device_id *match; 394327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen const struct tegra_ehci_soc_config *soc_config; 39579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct resource *res; 39679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct usb_hcd *hcd; 397c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren struct ehci_hcd *ehci; 39879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra; 39979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int err = 0; 40079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int irq; 401bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu struct usb_phy *u_phy; 40279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 403327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen match = of_match_device(tegra_ehci_of_match, &pdev->dev); 404327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen if (!match) { 405327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen dev_err(&pdev->dev, "Error: No device match found\n"); 406327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen return -ENODEV; 407327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen } 408327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen soc_config = match->data; 409327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen 4104a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson /* Right now device-tree probed devices don't get dma_mask set. 4114a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson * Since shared usb code relies on it, set it here for now. 4124a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson * Once we have dma capability bindings this can go away. 4134a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson */ 414e1fd7341837238c6c5380c5073887d238f706cf0Russell King err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); 41522d9d8e8316d7f69046c8805ce9aa8d9c43d4e5bRussell King if (err) 41622d9d8e8316d7f69046c8805ce9aa8d9c43d4e5bRussell King return err; 4174a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 418c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev, 419c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren dev_name(&pdev->dev)); 420c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren if (!hcd) { 421c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren dev_err(&pdev->dev, "Unable to create HCD\n"); 422f5b8c8b6d3b4697f28b818d8784e3e4b2a290022Mikko Perttunen return -ENOMEM; 423c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren } 424c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren platform_set_drvdata(pdev, hcd); 425c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren ehci = hcd_to_ehci(hcd); 426c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren tegra = (struct tegra_ehci_hcd *)ehci->priv; 427c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren 428c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren hcd->has_tt = 1; 42979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 430bc2ff98ffa52d36b5df925a1f783ff2e035ed55eJulia Lawall tegra->clk = devm_clk_get(&pdev->dev, NULL); 43179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (IS_ERR(tegra->clk)) { 43279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Can't get ehci clock\n"); 433c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren err = PTR_ERR(tegra->clk); 434c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren goto cleanup_hcd_create; 43579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 43679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 43775606f5d32fabef51c1337eac274492c0470d774Stephen Warren tegra->rst = devm_reset_control_get(&pdev->dev, "usb"); 43875606f5d32fabef51c1337eac274492c0470d774Stephen Warren if (IS_ERR(tegra->rst)) { 43975606f5d32fabef51c1337eac274492c0470d774Stephen Warren dev_err(&pdev->dev, "Can't get ehci reset\n"); 44075606f5d32fabef51c1337eac274492c0470d774Stephen Warren err = PTR_ERR(tegra->rst); 44175606f5d32fabef51c1337eac274492c0470d774Stephen Warren goto cleanup_hcd_create; 44275606f5d32fabef51c1337eac274492c0470d774Stephen Warren } 44375606f5d32fabef51c1337eac274492c0470d774Stephen Warren 44420de12ccf900d71eee1344adc7ae0dcd7db9b4abPrashant Gaikwad err = clk_prepare_enable(tegra->clk); 44579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (err) 446dafbe92edbfe4a4fd224f6d09a91650edcf7f442Wei Yongjun goto cleanup_hcd_create; 44779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 448a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen err = tegra_reset_usb_controller(pdev); 449a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen if (err) 450a47cc24cd1e5a55ef0b240180ce7ec6a9afc939dTuomas Tynkkynen goto cleanup_clk_en; 451eb5369edca4f4307a6035dc6f6813698b0762906Venu Byravarasu 4527db71a9a6707284f3d9075fff2ad674f6a51c359Tuomas Tynkkynen u_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0); 4532d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu if (IS_ERR(u_phy)) { 4542d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu err = PTR_ERR(u_phy); 455c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren goto cleanup_clk_en; 4562d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu } 4573d46e73dfdb840f460e5b06416965d132570ec33Antoine Tenart hcd->usb_phy = u_phy; 4582d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu 459585355c5b54e2ecdcd6463aec264d907bc416727Venu Byravarasu tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node, 460585355c5b54e2ecdcd6463aec264d907bc416727Venu Byravarasu "nvidia,needs-double-reset"); 461585355c5b54e2ecdcd6463aec264d907bc416727Venu Byravarasu 46279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 46379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!res) { 46479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to get I/O memory\n"); 46579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = -ENXIO; 466c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren goto cleanup_clk_en; 46779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 46879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby hcd->rsrc_start = res->start; 46979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby hcd->rsrc_len = resource_size(res); 4706ba96dcebf3b4c4a8befaa37dca0c590b0deceacVivek Gautam hcd->regs = devm_ioremap_resource(&pdev->dev, res); 4716ba96dcebf3b4c4a8befaa37dca0c590b0deceacVivek Gautam if (IS_ERR(hcd->regs)) { 4726ba96dcebf3b4c4a8befaa37dca0c590b0deceacVivek Gautam err = PTR_ERR(hcd->regs); 473c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren goto cleanup_clk_en; 4744a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson } 475c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren ehci->caps = hcd->regs + 0x100; 476327d8b424578254f0c1e71f83960bf8934063529Tuomas Tynkkynen ehci->has_hostpc = soc_config->has_hostpc; 4774a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 4783d46e73dfdb840f460e5b06416965d132570ec33Antoine Tenart err = usb_phy_init(hcd->usb_phy); 4792d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu if (err) { 4802d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu dev_err(&pdev->dev, "Failed to initialize phy\n"); 481c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren goto cleanup_clk_en; 48279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 48379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 484bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu u_phy->otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg), 485bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu GFP_KERNEL); 486bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu if (!u_phy->otg) { 487bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu dev_err(&pdev->dev, "Failed to alloc memory for otg\n"); 488bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu err = -ENOMEM; 4892d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu goto cleanup_phy; 490bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu } 491bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu u_phy->otg->host = hcd_to_bus(hcd); 492bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu 4933d46e73dfdb840f460e5b06416965d132570ec33Antoine Tenart err = usb_phy_set_suspend(hcd->usb_phy, 0); 49479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (err) { 49579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to power on the phy\n"); 4962d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu goto cleanup_phy; 49779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 49879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 49979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby irq = platform_get_irq(pdev, 0); 50079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!irq) { 50179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to get IRQ\n"); 50279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = -ENODEV; 5032d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu goto cleanup_phy; 50479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 50579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 506de3f233703080bfbbd5861d27660db7a2e476238Tuomas Tynkkynen otg_set_host(u_phy->otg, &hcd->self); 50779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 508b5dd18d8747010e3f3eb1cc76a49f94291938559Yong Zhang err = usb_add_hcd(hcd, irq, IRQF_SHARED); 50979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (err) { 51079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to add USB HCD\n"); 511de3f233703080bfbbd5861d27660db7a2e476238Tuomas Tynkkynen goto cleanup_otg_set_host; 51279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 5133c9740a117d40a74412775b5d3fe2b88a7635a0ePeter Chen device_wakeup_enable(hcd->self.controller); 51479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 51579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return err; 51679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 517de3f233703080bfbbd5861d27660db7a2e476238Tuomas Tynkkynencleanup_otg_set_host: 518de3f233703080bfbbd5861d27660db7a2e476238Tuomas Tynkkynen otg_set_host(u_phy->otg, NULL); 5198fefcfdd276be1459aaa2b2648037d2c0e1a3caaThierry Redingcleanup_phy: 5203d46e73dfdb840f460e5b06416965d132570ec33Antoine Tenart usb_phy_shutdown(hcd->usb_phy); 521c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warrencleanup_clk_en: 522c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren clk_disable_unprepare(tegra->clk); 5232d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasucleanup_hcd_create: 52479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby usb_put_hcd(hcd); 52579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return err; 52679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 52779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 52879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_remove(struct platform_device *pdev) 52979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 530c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren struct usb_hcd *hcd = platform_get_drvdata(pdev); 531c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren struct tegra_ehci_hcd *tegra = 532c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren (struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv; 53379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 5343d46e73dfdb840f460e5b06416965d132570ec33Antoine Tenart otg_set_host(hcd->usb_phy->otg, NULL); 53579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 5363d46e73dfdb840f460e5b06416965d132570ec33Antoine Tenart usb_phy_shutdown(hcd->usb_phy); 53779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby usb_remove_hcd(hcd); 538ecc8a0cdca18df5c9a7e84ab29160259123f3ae5Venu Byravarasu 53920de12ccf900d71eee1344adc7ae0dcd7db9b4abPrashant Gaikwad clk_disable_unprepare(tegra->clk); 54079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 5416a70b621227d1fd3efd150fce63ea4d51d4acaa9Tuomas Tynkkynen usb_put_hcd(hcd); 5426a70b621227d1fd3efd150fce63ea4d51d4acaa9Tuomas Tynkkynen 54379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return 0; 54479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 54579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 54679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic void tegra_ehci_hcd_shutdown(struct platform_device *pdev) 54779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 548c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren struct usb_hcd *hcd = platform_get_drvdata(pdev); 54979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 55079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (hcd->driver->shutdown) 55179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby hcd->driver->shutdown(hcd); 55279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 55379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 55479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic struct platform_driver tegra_ehci_driver = { 55579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .probe = tegra_ehci_probe, 55679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .remove = tegra_ehci_remove, 55779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .shutdown = tegra_ehci_hcd_shutdown, 55879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .driver = { 5599fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar .name = DRV_NAME, 5604a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson .of_match_table = tegra_ehci_of_match, 56179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 56279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby}; 5639fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 5644f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warrenstatic int tegra_ehci_reset(struct usb_hcd *hcd) 5654f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren{ 5664f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren struct ehci_hcd *ehci = hcd_to_ehci(hcd); 5674f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren int retval; 5684f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren int txfifothresh; 5694f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren 5704f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren retval = ehci_setup(hcd); 5714f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren if (retval) 5724f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren return retval; 5734f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren 5744f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren /* 5754f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren * We should really pull this value out of tegra_ehci_soc_config, but 5764f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren * to avoid needing access to it, make use of the fact that Tegra20 is 5774f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren * the only one so far that needs a value of 10, and Tegra20 is the 5784f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren * only one which doesn't set has_hostpc. 5794f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren */ 5804f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren txfifothresh = ehci->has_hostpc ? 0x10 : 10; 5814f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren ehci_writel(ehci, txfifothresh << 16, &ehci->regs->txfill_tuning); 5824f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren 5834f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren return 0; 5844f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren} 5854f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren 5869fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudarstatic const struct ehci_driver_overrides tegra_overrides __initconst = { 5879fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar .extra_priv_size = sizeof(struct tegra_ehci_hcd), 5884f2fe2d27472f4a5dbd875888af4fc5175f3fdc5Stephen Warren .reset = tegra_ehci_reset, 5899fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar}; 5909fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 5919fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudarstatic int __init ehci_tegra_init(void) 5929fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar{ 5939fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar if (usb_disabled()) 5949fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar return -ENODEV; 5959fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 5969fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar pr_info(DRV_NAME ": " DRIVER_DESC "\n"); 5979fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 5989fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar ehci_init_driver(&tegra_ehci_hc_driver, &tegra_overrides); 5999fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 6009fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar /* 6019fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar * The Tegra HW has some unusual quirks, which require Tegra-specific 6029fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar * workarounds. We override certain hc_driver functions here to 6039fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar * achieve that. We explicitly do not enhance ehci_driver_overrides to 6049fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar * allow this more easily, since this is an unusual case, and we don't 6059fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar * want to encourage others to override these functions by making it 6069fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar * too easy. 6079fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar */ 6089fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 6099fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar tegra_ehci_hc_driver.map_urb_for_dma = tegra_ehci_map_urb_for_dma; 6109fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar tegra_ehci_hc_driver.unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma; 6119fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar tegra_ehci_hc_driver.hub_control = tegra_ehci_hub_control; 6129fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 6139fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar return platform_driver_register(&tegra_ehci_driver); 6149fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar} 6159fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudarmodule_init(ehci_tegra_init); 6169fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 6179fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudarstatic void __exit ehci_tegra_cleanup(void) 6189fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar{ 6199fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar platform_driver_unregister(&tegra_ehci_driver); 6209fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar} 6219fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudarmodule_exit(ehci_tegra_cleanup); 6229fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 6239fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath GoudarMODULE_DESCRIPTION(DRIVER_DESC); 6249fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath GoudarMODULE_LICENSE("GPL"); 6259fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath GoudarMODULE_ALIAS("platform:" DRV_NAME); 6269fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath GoudarMODULE_DEVICE_TABLE(of, tegra_ehci_of_match); 627