ehci-tegra.c revision de3f233703080bfbbd5861d27660db7a2e476238
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/clk/tegra.h> 219fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#include <linux/dma-mapping.h> 22ded017ee6c7b90f7356bd8488f8af1c10ba90490Kishon Vijay Abraham I#include <linux/err.h> 234a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson#include <linux/gpio.h> 249fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#include <linux/io.h> 259fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#include <linux/irq.h> 269fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#include <linux/module.h> 274a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson#include <linux/of.h> 284a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson#include <linux/of_gpio.h> 299fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#include <linux/platform_device.h> 309fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#include <linux/platform_data/tegra_usb.h> 31ebf20de453042c066a289b90dd14d59de03dba2fAlan Stern#include <linux/pm_runtime.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 4154388b281c877b2797bb0fc97c099fb7ffd5336aStephen Warren#define TEGRA_USB_BASE 0xC5000000 4254388b281c877b2797bb0fc97c099fb7ffd5336aStephen Warren#define TEGRA_USB2_BASE 0xC5004000 4354388b281c877b2797bb0fc97c099fb7ffd5336aStephen Warren#define TEGRA_USB3_BASE 0xC5008000 4479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 459fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) 469fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 47fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell#define TEGRA_USB_DMA_ALIGN 32 48fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 499fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#define DRIVER_DESC "Tegra EHCI driver" 509fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar#define DRV_NAME "tegra-ehci" 519fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 529fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudarstatic struct hc_driver __read_mostly tegra_ehci_hc_driver; 539fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 549fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudarstatic int (*orig_hub_control)(struct usb_hcd *hcd, 559fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar u16 typeReq, u16 wValue, u16 wIndex, 569fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar char *buf, u16 wLength); 579fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 5879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystruct tegra_ehci_hcd { 5979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_usb_phy *phy; 6079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct clk *clk; 6179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int port_resuming; 62585355c5b54e2ecdcd6463aec264d907bc416727Venu Byravarasu bool needs_double_reset; 6379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby enum tegra_usb_phy_port_speed port_speed; 6479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby}; 6579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 661f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Linstatic int tegra_ehci_internal_port_reset( 671f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin struct ehci_hcd *ehci, 681f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin u32 __iomem *portsc_reg 691f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin) 701f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin{ 711f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin u32 temp; 721f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin unsigned long flags; 731f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin int retval = 0; 741f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin int i, tries; 751f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin u32 saved_usbintr; 761f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 771f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin spin_lock_irqsave(&ehci->lock, flags); 781f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin saved_usbintr = ehci_readl(ehci, &ehci->regs->intr_enable); 791f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* disable USB interrupt */ 801f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, 0, &ehci->regs->intr_enable); 811f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin spin_unlock_irqrestore(&ehci->lock, flags); 821f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 831f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* 841f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Here we have to do Port Reset at most twice for 851f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Port Enable bit to be set. 861f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin */ 871f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin for (i = 0; i < 2; i++) { 881f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp = ehci_readl(ehci, portsc_reg); 891f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp |= PORT_RESET; 901f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, temp, portsc_reg); 911f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin mdelay(10); 921f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp &= ~PORT_RESET; 931f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, temp, portsc_reg); 941f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin mdelay(1); 951f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin tries = 100; 961f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin do { 971f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin mdelay(1); 981f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* 991f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Up to this point, Port Enable bit is 1001f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * expected to be set after 2 ms waiting. 1011f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * USB1 usually takes extra 45 ms, for safety, 1021f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * we take 100 ms as timeout. 1031f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin */ 1041f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp = ehci_readl(ehci, portsc_reg); 1051f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin } while (!(temp & PORT_PE) && tries--); 1061f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin if (temp & PORT_PE) 1071f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin break; 1081f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin } 1091f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin if (i == 2) 1101f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin retval = -ETIMEDOUT; 1111f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 1121f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* 1131f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Clear Connect Status Change bit if it's set. 1141f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * We can't clear PORT_PEC. It will also cause PORT_PE to be cleared. 1151f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin */ 1161f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin if (temp & PORT_CSC) 1171f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, PORT_CSC, portsc_reg); 1181f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 1191f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* 1201f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * Write to clear any interrupt status bits that might be set 1211f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin * during port reset. 1221f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin */ 1231f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin temp = ehci_readl(ehci, &ehci->regs->status); 1241f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, temp, &ehci->regs->status); 1251f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 1261f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* restore original interrupt enable bits */ 1271f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin ehci_writel(ehci, saved_usbintr, &ehci->regs->intr_enable); 1281f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin return retval; 1291f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin} 1301f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 13179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_hub_control( 13279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct usb_hcd *hcd, 13379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u16 typeReq, 13479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u16 wValue, 13579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u16 wIndex, 13679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby char *buf, 13779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u16 wLength 13879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby) 13979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 140c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren struct ehci_hcd *ehci = hcd_to_ehci(hcd); 141c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren struct tegra_ehci_hcd *tegra = (struct tegra_ehci_hcd *)ehci->priv; 14279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u32 __iomem *status_reg; 14379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby u32 temp; 14479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby unsigned long flags; 14579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int retval = 0; 14679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 14779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1]; 14879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 14979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_lock_irqsave(&ehci->lock, flags); 15079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 1516d5f89c7b4fa5f8d6dc757982402c032183ffd8dStephen Warren if (typeReq == GetPortStatus) { 15279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp = ehci_readl(ehci, status_reg); 15379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (tegra->port_resuming && !(temp & PORT_SUSPEND)) { 15479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Resume completed, re-enable disconnect detection */ 15579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->port_resuming = 0; 156ab137d04db5a4b32250ce5ef1b288ce6cf06adf6Venu Byravarasu tegra_usb_phy_postresume(hcd->phy); 15779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 15879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 15979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 16079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby else if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { 16179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp = ehci_readl(ehci, status_reg); 16279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) { 16379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby retval = -EPIPE; 16479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 16579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 16679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 167b08765749332c54c65c1a6515c01c6eb3fc1843eStephen Warren temp &= ~(PORT_RWC_BITS | PORT_WKCONN_E); 16879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp |= PORT_WKDISC_E | PORT_WKOC_E; 16979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); 17079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 17179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* 17279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * If a transaction is in progress, there may be a delay in 17379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * suspending the port. Poll until the port is suspended. 17479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby */ 1752f3a6b86528994027c8241f9666f0fbcf3d3130bManjunath Goudar if (ehci_handshake(ehci, status_reg, PORT_SUSPEND, 17679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby PORT_SUSPEND, 5000)) 17779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pr_err("%s: timeout waiting for SUSPEND\n", __func__); 17879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 17979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports); 18079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 18179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 18279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 1831f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin /* For USB1 port we need to issue Port Reset twice internally */ 184585355c5b54e2ecdcd6463aec264d907bc416727Venu Byravarasu if (tegra->needs_double_reset && 1851f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_RESET)) { 1861f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin spin_unlock_irqrestore(&ehci->lock, flags); 1871f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin return tegra_ehci_internal_port_reset(ehci, status_reg); 1881f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin } 1891f594b64a4f74ece0b7166ca4db05a71a64bd685Jim Lin 19079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* 19179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * Tegra host controller will time the resume operation to clear the bit 19279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * when the port control state switches to HS or FS Idle. This behavior 19379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * is different from EHCI where the host controller driver is required 19479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * to set this bit to a zero after the resume duration is timed in the 19579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby * driver. 19679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby */ 19779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby else if (typeReq == ClearPortFeature && 19879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby wValue == USB_PORT_FEAT_SUSPEND) { 19979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp = ehci_readl(ehci, status_reg); 20079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if ((temp & PORT_RESET) || !(temp & PORT_PE)) { 20179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby retval = -EPIPE; 20279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 20379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 20479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 20579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!(temp & PORT_SUSPEND)) 20679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 20779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 20879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Disable disconnect detection during port resume */ 209ab137d04db5a4b32250ce5ef1b288ce6cf06adf6Venu Byravarasu tegra_usb_phy_preresume(hcd->phy); 21079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 21179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25); 21279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 21379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); 21479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* start resume signalling */ 21579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci_writel(ehci, temp | PORT_RESUME, status_reg); 216a448e4dc25303fe551e4dafe16c8c7c34f1b9d82Alan Stern set_bit(wIndex-1, &ehci->resuming_ports); 21779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 21879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_unlock_irqrestore(&ehci->lock, flags); 21979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby msleep(20); 22079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_lock_irqsave(&ehci->lock, flags); 22179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 22279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Poll until the controller clears RESUME and SUSPEND */ 2232f3a6b86528994027c8241f9666f0fbcf3d3130bManjunath Goudar if (ehci_handshake(ehci, status_reg, PORT_RESUME, 0, 2000)) 22479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pr_err("%s: timeout waiting for RESUME\n", __func__); 2252f3a6b86528994027c8241f9666f0fbcf3d3130bManjunath Goudar if (ehci_handshake(ehci, status_reg, PORT_SUSPEND, 0, 2000)) 22679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pr_err("%s: timeout waiting for SUSPEND\n", __func__); 22779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 22879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby ehci->reset_done[wIndex-1] = 0; 229a448e4dc25303fe551e4dafe16c8c7c34f1b9d82Alan Stern clear_bit(wIndex-1, &ehci->resuming_ports); 23079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 23179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby tegra->port_resuming = 1; 23279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby goto done; 23379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 23479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 23579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_unlock_irqrestore(&ehci->lock, flags); 23679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 23779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby /* Handle the hub control events here */ 2389fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar return orig_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); 2399fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 24079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobydone: 24179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby spin_unlock_irqrestore(&ehci->lock, flags); 24279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return retval; 24379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 24479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 245fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasustruct dma_aligned_buffer { 246fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell void *kmalloc_ptr; 247fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell void *old_xfer_buffer; 248fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell u8 data[0]; 249fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell}; 250fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 251fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasustatic void free_dma_aligned_buffer(struct urb *urb) 252fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell{ 253fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu struct dma_aligned_buffer *temp; 254fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 255fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) 256fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return; 257fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 258fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu temp = container_of(urb->transfer_buffer, 259fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu struct dma_aligned_buffer, data); 260fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 261fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu if (usb_urb_dir_in(urb)) 262fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell memcpy(temp->old_xfer_buffer, temp->data, 263fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer_length); 264fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer = temp->old_xfer_buffer; 265fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell kfree(temp->kmalloc_ptr); 266fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 267fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER; 268fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell} 269fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 270fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasustatic int alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags) 271fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell{ 272fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu struct dma_aligned_buffer *temp, *kmalloc_ptr; 273fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell size_t kmalloc_size; 274fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 275fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (urb->num_sgs || urb->sg || 276fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer_length == 0 || 277fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell !((uintptr_t)urb->transfer_buffer & (TEGRA_USB_DMA_ALIGN - 1))) 278fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return 0; 279fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 280fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell /* Allocate a buffer with enough padding for alignment */ 281fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell kmalloc_size = urb->transfer_buffer_length + 282fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu sizeof(struct dma_aligned_buffer) + TEGRA_USB_DMA_ALIGN - 1; 283fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 284fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell kmalloc_ptr = kmalloc(kmalloc_size, mem_flags); 285fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (!kmalloc_ptr) 286fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return -ENOMEM; 287fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 288fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu /* Position our struct dma_aligned_buffer such that data is aligned */ 289fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell temp = PTR_ALIGN(kmalloc_ptr + 1, TEGRA_USB_DMA_ALIGN) - 1; 290fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell temp->kmalloc_ptr = kmalloc_ptr; 291fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell temp->old_xfer_buffer = urb->transfer_buffer; 292fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu if (usb_urb_dir_out(urb)) 293fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell memcpy(temp->data, urb->transfer_buffer, 294fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer_length); 295fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_buffer = temp->data; 296fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 297fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER; 298fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 299fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return 0; 300fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell} 301fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 302fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morellstatic int tegra_ehci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, 303fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell gfp_t mem_flags) 304fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell{ 305fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell int ret; 306fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 307fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu ret = alloc_dma_aligned_buffer(urb, mem_flags); 308fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (ret) 309fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return ret; 310fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 311fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags); 312fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell if (ret) 313fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu free_dma_aligned_buffer(urb); 314fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 315fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell return ret; 316fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell} 317fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 318fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morellstatic void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) 319fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell{ 320fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell usb_hcd_unmap_urb_for_dma(hcd, urb); 321fe375774bd88a358d24c3f624373117c642f6999Venu Byravarasu free_dma_aligned_buffer(urb); 322fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell} 323fbf9865c6d96f4a131092d2018056e86113e5ceaRobert Morell 32479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_probe(struct platform_device *pdev) 32579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 32679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct resource *res; 32779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct usb_hcd *hcd; 328c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren struct ehci_hcd *ehci; 32979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_hcd *tegra; 33079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby struct tegra_ehci_platform_data *pdata; 33179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int err = 0; 33279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby int irq; 3332d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu struct device_node *np_phy; 334bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu struct usb_phy *u_phy; 33579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 33679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby pdata = pdev->dev.platform_data; 33779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!pdata) { 33879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Platform data missing\n"); 33979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return -EINVAL; 34079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 34179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 3424a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson /* Right now device-tree probed devices don't get dma_mask set. 3434a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson * Since shared usb code relies on it, set it here for now. 3444a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson * Once we have dma capability bindings this can go away. 3454a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson */ 3464a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson if (!pdev->dev.dma_mask) 3473b9561e9d9b88eca9d4ed6aab025dec2eeeed501Stephen Warren pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; 3483b9561e9d9b88eca9d4ed6aab025dec2eeeed501Stephen Warren if (!pdev->dev.coherent_dma_mask) 3493b9561e9d9b88eca9d4ed6aab025dec2eeeed501Stephen Warren pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); 3504a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 351c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev, 352c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren dev_name(&pdev->dev)); 353c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren if (!hcd) { 354c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren dev_err(&pdev->dev, "Unable to create HCD\n"); 355f5b8c8b6d3b4697f28b818d8784e3e4b2a290022Mikko Perttunen return -ENOMEM; 356c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren } 357c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren platform_set_drvdata(pdev, hcd); 358c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren ehci = hcd_to_ehci(hcd); 359c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren tegra = (struct tegra_ehci_hcd *)ehci->priv; 360c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren 361c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren hcd->has_tt = 1; 36279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 363bc2ff98ffa52d36b5df925a1f783ff2e035ed55eJulia Lawall tegra->clk = devm_clk_get(&pdev->dev, NULL); 36479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (IS_ERR(tegra->clk)) { 36579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Can't get ehci clock\n"); 366c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren err = PTR_ERR(tegra->clk); 367c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren goto cleanup_hcd_create; 36879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 36979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 37020de12ccf900d71eee1344adc7ae0dcd7db9b4abPrashant Gaikwad err = clk_prepare_enable(tegra->clk); 37179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (err) 372c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren goto cleanup_clk_get; 37379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 374eb5369edca4f4307a6035dc6f6813698b0762906Venu Byravarasu tegra_periph_reset_assert(tegra->clk); 375eb5369edca4f4307a6035dc6f6813698b0762906Venu Byravarasu udelay(1); 376eb5369edca4f4307a6035dc6f6813698b0762906Venu Byravarasu tegra_periph_reset_deassert(tegra->clk); 377eb5369edca4f4307a6035dc6f6813698b0762906Venu Byravarasu 3782d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu np_phy = of_parse_phandle(pdev->dev.of_node, "nvidia,phy", 0); 3792d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu if (!np_phy) { 3802d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu err = -ENODEV; 381c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren goto cleanup_clk_en; 3822d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu } 3832d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu 3842d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu u_phy = tegra_usb_get_phy(np_phy); 3852d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu if (IS_ERR(u_phy)) { 3862d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu err = PTR_ERR(u_phy); 387c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren goto cleanup_clk_en; 3882d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu } 389c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren hcd->phy = u_phy; 3902d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu 391585355c5b54e2ecdcd6463aec264d907bc416727Venu Byravarasu tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node, 392585355c5b54e2ecdcd6463aec264d907bc416727Venu Byravarasu "nvidia,needs-double-reset"); 393585355c5b54e2ecdcd6463aec264d907bc416727Venu Byravarasu 39479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 39579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!res) { 39679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to get I/O memory\n"); 39779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = -ENXIO; 398c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren goto cleanup_clk_en; 39979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 40079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby hcd->rsrc_start = res->start; 40179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby hcd->rsrc_len = resource_size(res); 402bc2ff98ffa52d36b5df925a1f783ff2e035ed55eJulia Lawall hcd->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 40379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!hcd->regs) { 40479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to remap I/O memory\n"); 40579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = -ENOMEM; 406c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren goto cleanup_clk_en; 4074a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson } 408c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren ehci->caps = hcd->regs + 0x100; 4094a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 4102d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu err = usb_phy_init(hcd->phy); 4112d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu if (err) { 4122d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu dev_err(&pdev->dev, "Failed to initialize phy\n"); 413c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren goto cleanup_clk_en; 41479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 41579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 416bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu u_phy->otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg), 417bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu GFP_KERNEL); 418bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu if (!u_phy->otg) { 419bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu dev_err(&pdev->dev, "Failed to alloc memory for otg\n"); 420bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu err = -ENOMEM; 4212d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu goto cleanup_phy; 422bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu } 423bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu u_phy->otg->host = hcd_to_bus(hcd); 424bbdabdb62d86090511410728644a19291bf300cfVenu Byravarasu 425ab137d04db5a4b32250ce5ef1b288ce6cf06adf6Venu Byravarasu err = usb_phy_set_suspend(hcd->phy, 0); 42679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (err) { 42779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to power on the phy\n"); 4282d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu goto cleanup_phy; 42979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 43079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 43179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby irq = platform_get_irq(pdev, 0); 43279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (!irq) { 43379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to get IRQ\n"); 43479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby err = -ENODEV; 4352d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasu goto cleanup_phy; 43679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 43779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 438de3f233703080bfbbd5861d27660db7a2e476238Tuomas Tynkkynen otg_set_host(u_phy->otg, &hcd->self); 43979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 440b5dd18d8747010e3f3eb1cc76a49f94291938559Yong Zhang err = usb_add_hcd(hcd, irq, IRQF_SHARED); 44179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (err) { 44279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby dev_err(&pdev->dev, "Failed to add USB HCD\n"); 443de3f233703080bfbbd5861d27660db7a2e476238Tuomas Tynkkynen goto cleanup_otg_set_host; 44479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 44579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 44679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return err; 44779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 448de3f233703080bfbbd5861d27660db7a2e476238Tuomas Tynkkynencleanup_otg_set_host: 449de3f233703080bfbbd5861d27660db7a2e476238Tuomas Tynkkynen otg_set_host(u_phy->otg, NULL); 4508fefcfdd276be1459aaa2b2648037d2c0e1a3caaThierry Redingcleanup_phy: 451ab137d04db5a4b32250ce5ef1b288ce6cf06adf6Venu Byravarasu usb_phy_shutdown(hcd->phy); 452c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warrencleanup_clk_en: 453c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren clk_disable_unprepare(tegra->clk); 454c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warrencleanup_clk_get: 455c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren clk_put(tegra->clk); 4562d22b42db02fdafeb7b990c2c25caabff4dd46feVenu Byravarasucleanup_hcd_create: 45779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby usb_put_hcd(hcd); 45879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return err; 45979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 46079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 46179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic int tegra_ehci_remove(struct platform_device *pdev) 46279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 463c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren struct usb_hcd *hcd = platform_get_drvdata(pdev); 464c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren struct tegra_ehci_hcd *tegra = 465c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren (struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv; 46679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 467de3f233703080bfbbd5861d27660db7a2e476238Tuomas Tynkkynen otg_set_host(hcd->phy->otg, NULL); 46879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 469ab137d04db5a4b32250ce5ef1b288ce6cf06adf6Venu Byravarasu usb_phy_shutdown(hcd->phy); 47079ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby usb_remove_hcd(hcd); 471ecc8a0cdca18df5c9a7e84ab29160259123f3ae5Venu Byravarasu usb_put_hcd(hcd); 472ecc8a0cdca18df5c9a7e84ab29160259123f3ae5Venu Byravarasu 47320de12ccf900d71eee1344adc7ae0dcd7db9b4abPrashant Gaikwad clk_disable_unprepare(tegra->clk); 47479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 47579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby return 0; 47679ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 47779ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 47879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic void tegra_ehci_hcd_shutdown(struct platform_device *pdev) 47979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby{ 480c19d14d6d0120e73418294e6a30db0566e5daf02Stephen Warren struct usb_hcd *hcd = platform_get_drvdata(pdev); 48179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 48279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby if (hcd->driver->shutdown) 48379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby hcd->driver->shutdown(hcd); 48479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby} 48579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby 486d3608b6dafc570bb671c3338288eb2523f8cd52aBill Pembertonstatic struct of_device_id tegra_ehci_of_match[] = { 4874a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson { .compatible = "nvidia,tegra20-ehci", }, 4884a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson { }, 4894a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson}; 4904a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson 49179ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Gobystatic struct platform_driver tegra_ehci_driver = { 49279ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .probe = tegra_ehci_probe, 49379ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .remove = tegra_ehci_remove, 49479ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .shutdown = tegra_ehci_hcd_shutdown, 49579ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby .driver = { 4969fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar .name = DRV_NAME, 4974a53f4e692c5df8a4bf9bf059b8007d575b0204aOlof Johansson .of_match_table = tegra_ehci_of_match, 49879ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby } 49979ad3b5add4a683af02d1b51ccb699d1b01f1fbfBenoit Goby}; 5009fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 5019fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudarstatic const struct ehci_driver_overrides tegra_overrides __initconst = { 5029fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar .extra_priv_size = sizeof(struct tegra_ehci_hcd), 5039fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar}; 5049fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 5059fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudarstatic int __init ehci_tegra_init(void) 5069fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar{ 5079fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar if (usb_disabled()) 5089fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar return -ENODEV; 5099fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 5109fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar pr_info(DRV_NAME ": " DRIVER_DESC "\n"); 5119fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 5129fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar ehci_init_driver(&tegra_ehci_hc_driver, &tegra_overrides); 5139fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 5149fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar /* 5159fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar * The Tegra HW has some unusual quirks, which require Tegra-specific 5169fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar * workarounds. We override certain hc_driver functions here to 5179fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar * achieve that. We explicitly do not enhance ehci_driver_overrides to 5189fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar * allow this more easily, since this is an unusual case, and we don't 5199fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar * want to encourage others to override these functions by making it 5209fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar * too easy. 5219fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar */ 5229fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 5239fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar orig_hub_control = tegra_ehci_hc_driver.hub_control; 5249fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 5259fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar tegra_ehci_hc_driver.map_urb_for_dma = tegra_ehci_map_urb_for_dma; 5269fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar tegra_ehci_hc_driver.unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma; 5279fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar tegra_ehci_hc_driver.hub_control = tegra_ehci_hub_control; 5289fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 5299fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar return platform_driver_register(&tegra_ehci_driver); 5309fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar} 5319fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudarmodule_init(ehci_tegra_init); 5329fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 5339fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudarstatic void __exit ehci_tegra_cleanup(void) 5349fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar{ 5359fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar platform_driver_unregister(&tegra_ehci_driver); 5369fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar} 5379fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudarmodule_exit(ehci_tegra_cleanup); 5389fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath Goudar 5399fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath GoudarMODULE_DESCRIPTION(DRIVER_DESC); 5409fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath GoudarMODULE_LICENSE("GPL"); 5419fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath GoudarMODULE_ALIAS("platform:" DRV_NAME); 5429fc5f24e43da17df75af75d446c9d89a4bcfce8cManjunath GoudarMODULE_DEVICE_TABLE(of, tegra_ehci_of_match); 543