180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson/* 21af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov * Copyright 2005-2009 MontaVista Software, Inc. 358c559e6509f276d0afb4621b2122e994e70160cRamneek Mehresh * Copyright 2008,2012 Freescale Semiconductor, Inc. 480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * 580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * This program is free software; you can redistribute it and/or modify it 680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * under the terms of the GNU General Public License as published by the 780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * Free Software Foundation; either version 2 of the License, or (at your 880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * option) any later version. 980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * 1080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * This program is distributed in the hope that it will be useful, but 1180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 1280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * for more details. 1480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * 1580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * You should have received a copy of the GNU General Public License 1680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * along with this program; if not, write to the Free Software Foundation, 1780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * 1980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * Ported to 834x by Randy Vinson <rvinson@mvista.com> using code provided 2080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * by Hunter Wu. 211af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov * Power Management support by Dave Liu <daveliu@freescale.com>, 221af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov * Jerry Huang <Chang-Ming.Huang@freescale.com> and 231af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov * Anton Vorontsov <avorontsov@ru.mvista.com>. 2480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson */ 2580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 261af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov#include <linux/kernel.h> 271af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov#include <linux/types.h> 281af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov#include <linux/delay.h> 291af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov#include <linux/pm.h> 30ded017ee6c7b90f7356bd8488f8af1c10ba90490Kishon Vijay Abraham I#include <linux/err.h> 3180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson#include <linux/platform_device.h> 3280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson#include <linux/fsl_devices.h> 3380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 3480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson#include "ehci-fsl.h" 3580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 3680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson/* configure so an HC device and id are always provided */ 3780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson/* always called with process context; sleeping is OK */ 3880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 3980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson/** 4080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * usb_hcd_fsl_probe - initialize FSL-based HCDs 4180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * @drvier: Driver to be used for this HCD 4280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * @pdev: USB Host Controller being probed 4380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * Context: !in_interrupt() 4480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * 4580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * Allocates basic resources for this USB host controller. 4680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * 4780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson */ 48dad3843f035a273f9b64e133467e8dcbfaf0ce60Anton Vorontsovstatic int usb_hcd_fsl_probe(const struct hc_driver *driver, 49dad3843f035a273f9b64e133467e8dcbfaf0ce60Anton Vorontsov struct platform_device *pdev) 5080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson{ 5180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson struct fsl_usb2_platform_data *pdata; 5280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson struct usb_hcd *hcd; 5380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson struct resource *res; 5480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson int irq; 5580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson int retval; 5680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 5780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson pr_debug("initializing FSL-SOC USB Controller\n"); 5880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 5980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson /* Need platform data for setup */ 6037c3a3c4ffde23115c58bec7694082b3a44c6da5Jingoo Han pdata = dev_get_platdata(&pdev->dev); 6180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson if (!pdata) { 6280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson dev_err(&pdev->dev, 637071a3ce0ca058ad2a9e3e8c33f30fb0bce62005Kay Sievers "No platform data for %s.\n", dev_name(&pdev->dev)); 6480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson return -ENODEV; 6580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson } 6680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 6780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson /* 6880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * This is a host mode driver, verify that we're supposed to be 6980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * in host mode. 7080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson */ 7180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson if (!((pdata->operating_mode == FSL_USB2_DR_HOST) || 72ba02978a48f0117b3d0aced97a30615a5d7412e2Li Yang (pdata->operating_mode == FSL_USB2_MPH_HOST) || 73ba02978a48f0117b3d0aced97a30615a5d7412e2Li Yang (pdata->operating_mode == FSL_USB2_DR_OTG))) { 7480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson dev_err(&pdev->dev, 7580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson "Non Host Mode configured for %s. Wrong driver linked.\n", 767071a3ce0ca058ad2a9e3e8c33f30fb0bce62005Kay Sievers dev_name(&pdev->dev)); 7780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson return -ENODEV; 7880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson } 7980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 8080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 8180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson if (!res) { 8280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson dev_err(&pdev->dev, 8380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson "Found HC with no IRQ. Check %s setup!\n", 847071a3ce0ca058ad2a9e3e8c33f30fb0bce62005Kay Sievers dev_name(&pdev->dev)); 8580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson return -ENODEV; 8680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson } 8780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson irq = res->start; 8880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 897071a3ce0ca058ad2a9e3e8c33f30fb0bce62005Kay Sievers hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); 9080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson if (!hcd) { 9180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson retval = -ENOMEM; 9280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson goto err1; 9380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson } 9480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 9580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 9680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson if (!res) { 9780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson dev_err(&pdev->dev, 9880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson "Found HC with no register addr. Check %s setup!\n", 997071a3ce0ca058ad2a9e3e8c33f30fb0bce62005Kay Sievers dev_name(&pdev->dev)); 10080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson retval = -ENODEV; 10180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson goto err2; 10280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson } 10380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson hcd->rsrc_start = res->start; 10428f65c11f2ffb3957259dece647a24f8ad2e241bJoe Perches hcd->rsrc_len = resource_size(res); 1057667fe69e743c338bb121678dd14f1dc3ae27acbJingoo Han hcd->regs = devm_ioremap_resource(&pdev->dev, res); 1067667fe69e743c338bb121678dd14f1dc3ae27acbJingoo Han if (IS_ERR(hcd->regs)) { 1077667fe69e743c338bb121678dd14f1dc3ae27acbJingoo Han retval = PTR_ERR(hcd->regs); 10880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson goto err2; 10980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson } 11080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 111230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin pdata->regs = hcd->regs; 11280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 11383722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin if (pdata->power_budget) 11483722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin hcd->power_budget = pdata->power_budget; 11583722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin 116230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin /* 117230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin * do platform specific init: check the clock, grab/config pins, etc. 118230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin */ 119230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin if (pdata->init && pdata->init(pdev)) { 120230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin retval = -ENODEV; 1217667fe69e743c338bb121678dd14f1dc3ae27acbJingoo Han goto err2; 122230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin } 123230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin 124230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin /* Enable USB controller, 83xx or 8536 */ 125ad1260e9fbf768d6bed227d9604ebee76a84aae3Ramneek Mehresh if (pdata->have_sysif_regs && pdata->controller_ver < FSL_USB_VER_1_6) 126230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4); 127230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin 128230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin /* Don't need to set host mode here. It will be done by tdi_reset() */ 12980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 130b5dd18d8747010e3f3eb1cc76a49f94291938559Yong Zhang retval = usb_add_hcd(hcd, irq, IRQF_SHARED); 13180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson if (retval != 0) 1327667fe69e743c338bb121678dd14f1dc3ae27acbJingoo Han goto err2; 1333c9740a117d40a74412775b5d3fe2b88a7635a0ePeter Chen device_wakeup_enable(hcd->self.controller); 13483722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin 13583722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin#ifdef CONFIG_USB_OTG 13683722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin if (pdata->operating_mode == FSL_USB2_DR_OTG) { 13783722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin struct ehci_hcd *ehci = hcd_to_ehci(hcd); 13883722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin 1393d46e73dfdb840f460e5b06416965d132570ec33Antoine Tenart hcd->usb_phy = usb_get_phy(USB_PHY_TYPE_USB2); 140c2e935a7db6e7354e9dd138b7f6f4c53affc09d9Richard Zhao dev_dbg(&pdev->dev, "hcd=0x%p ehci=0x%p, phy=0x%p\n", 1413d46e73dfdb840f460e5b06416965d132570ec33Antoine Tenart hcd, ehci, hcd->usb_phy); 14283722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin 1433d46e73dfdb840f460e5b06416965d132570ec33Antoine Tenart if (!IS_ERR_OR_NULL(hcd->usb_phy)) { 1443d46e73dfdb840f460e5b06416965d132570ec33Antoine Tenart retval = otg_set_host(hcd->usb_phy->otg, 14583722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin &ehci_to_hcd(ehci)->self); 14683722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin if (retval) { 1473d46e73dfdb840f460e5b06416965d132570ec33Antoine Tenart usb_put_phy(hcd->usb_phy); 1487667fe69e743c338bb121678dd14f1dc3ae27acbJingoo Han goto err2; 14983722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin } 15083722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin } else { 151c2e935a7db6e7354e9dd138b7f6f4c53affc09d9Richard Zhao dev_err(&pdev->dev, "can't find phy\n"); 15283722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin retval = -ENODEV; 1537667fe69e743c338bb121678dd14f1dc3ae27acbJingoo Han goto err2; 15483722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin } 15583722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin } 15683722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin#endif 15780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson return retval; 15880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 15980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson err2: 16080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson usb_put_hcd(hcd); 16180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson err1: 1627071a3ce0ca058ad2a9e3e8c33f30fb0bce62005Kay Sievers dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval); 163230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin if (pdata->exit) 164230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin pdata->exit(pdev); 16580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson return retval; 16680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson} 16780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 16880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson/* may be called without controller electrically present */ 16980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson/* may be called with controller, bus, and devices active */ 17080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 17180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson/** 17280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * usb_hcd_fsl_remove - shutdown processing for FSL-based HCDs 17380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * @dev: USB Host Controller being removed 17480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * Context: !in_interrupt() 17580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * 17680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * Reverses the effect of usb_hcd_fsl_probe(). 17780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * 17880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson */ 179dad3843f035a273f9b64e133467e8dcbfaf0ce60Anton Vorontsovstatic void usb_hcd_fsl_remove(struct usb_hcd *hcd, 180dad3843f035a273f9b64e133467e8dcbfaf0ce60Anton Vorontsov struct platform_device *pdev) 18180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson{ 182d4f09e28d7bc5c1adde8229b1e89401f23fb44f9Jingoo Han struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev); 18383722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin 1843d46e73dfdb840f460e5b06416965d132570ec33Antoine Tenart if (!IS_ERR_OR_NULL(hcd->usb_phy)) { 1853d46e73dfdb840f460e5b06416965d132570ec33Antoine Tenart otg_set_host(hcd->usb_phy->otg, NULL); 1863d46e73dfdb840f460e5b06416965d132570ec33Antoine Tenart usb_put_phy(hcd->usb_phy); 18783722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin } 188230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin 18980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson usb_remove_hcd(hcd); 190230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin 191230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin /* 192230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin * do platform specific un-initialization: 193230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin * release iomux pins, disable clock, etc. 194230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin */ 195230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin if (pdata->exit) 196230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin pdata->exit(pdev); 19780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson usb_put_hcd(hcd); 19880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson} 19980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 2003735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liustatic int ehci_fsl_setup_phy(struct usb_hcd *hcd, 201230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin enum fsl_usb2_phy_modes phy_mode, 202230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin unsigned int port_offset) 20380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson{ 2043735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu u32 portsc; 20558c559e6509f276d0afb4621b2122e994e70160cRamneek Mehresh struct ehci_hcd *ehci = hcd_to_ehci(hcd); 20628c56ea1431421dec51b7b229369e991481453dfShengzhou Liu void __iomem *non_ehci = hcd->regs; 20758c559e6509f276d0afb4621b2122e994e70160cRamneek Mehresh struct device *dev = hcd->self.controller; 208d4f09e28d7bc5c1adde8229b1e89401f23fb44f9Jingoo Han struct fsl_usb2_platform_data *pdata = dev_get_platdata(dev); 209f941f6922533316556d4dc6eee9c19d4a832c560Anatolij Gustschin 21058c559e6509f276d0afb4621b2122e994e70160cRamneek Mehresh if (pdata->controller_ver < 0) { 21158c559e6509f276d0afb4621b2122e994e70160cRamneek Mehresh dev_warn(hcd->self.controller, "Could not get controller version\n"); 212d479c911789e14a19b86ca09b0b634f1449c8c6bBen Collins return -ENODEV; 21358c559e6509f276d0afb4621b2122e994e70160cRamneek Mehresh } 214230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin 215230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]); 216230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW); 217230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin 21880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson switch (phy_mode) { 21980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson case FSL_USB2_PHY_ULPI: 220f66dea709cd9309b2ee9f715697818001fb518deAnatolij Gustschin if (pdata->have_sysif_regs && pdata->controller_ver) { 22158c559e6509f276d0afb4621b2122e994e70160cRamneek Mehresh /* controller version 1.6 or above */ 222ad1260e9fbf768d6bed227d9604ebee76a84aae3Ramneek Mehresh clrbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN); 2233735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu setbits32(non_ehci + FSL_SOC_USB_CTRL, 224ad1260e9fbf768d6bed227d9604ebee76a84aae3Ramneek Mehresh ULPI_PHY_CLK_SEL | USB_CTRL_USB_EN); 22558c559e6509f276d0afb4621b2122e994e70160cRamneek Mehresh } 22680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson portsc |= PORT_PTS_ULPI; 22780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson break; 22880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson case FSL_USB2_PHY_SERIAL: 22980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson portsc |= PORT_PTS_SERIAL; 23080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson break; 23180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson case FSL_USB2_PHY_UTMI_WIDE: 23280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson portsc |= PORT_PTS_PTW; 23380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson /* fall through */ 23480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson case FSL_USB2_PHY_UTMI: 235f66dea709cd9309b2ee9f715697818001fb518deAnatolij Gustschin if (pdata->have_sysif_regs && pdata->controller_ver) { 23658c559e6509f276d0afb4621b2122e994e70160cRamneek Mehresh /* controller version 1.6 or above */ 2373735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN); 23858c559e6509f276d0afb4621b2122e994e70160cRamneek Mehresh mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to 23958c559e6509f276d0afb4621b2122e994e70160cRamneek Mehresh become stable - 10ms*/ 24058c559e6509f276d0afb4621b2122e994e70160cRamneek Mehresh } 24128c56ea1431421dec51b7b229369e991481453dfShengzhou Liu /* enable UTMI PHY */ 242f941f6922533316556d4dc6eee9c19d4a832c560Anatolij Gustschin if (pdata->have_sysif_regs) 243f941f6922533316556d4dc6eee9c19d4a832c560Anatolij Gustschin setbits32(non_ehci + FSL_SOC_USB_CTRL, 244f941f6922533316556d4dc6eee9c19d4a832c560Anatolij Gustschin CTRL_UTMI_PHY_EN); 24580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson portsc |= PORT_PTS_UTMI; 24680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson break; 24780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson case FSL_USB2_PHY_NONE: 24880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson break; 24980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson } 2503735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu 251d183c81929beeba842b74422f754446ef2b8b49cNikita Yushchenko if (pdata->have_sysif_regs && 252d183c81929beeba842b74422f754446ef2b8b49cNikita Yushchenko pdata->controller_ver > FSL_USB_VER_1_6 && 253f66dea709cd9309b2ee9f715697818001fb518deAnatolij Gustschin (phy_mode == FSL_USB2_PHY_ULPI)) { 2543735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu /* check PHY_CLK_VALID to get phy clk valid */ 255eee41b49b80420e3e8c118d18dfacb7da43c1caaShengzhou Liu if (!(spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) & 256eee41b49b80420e3e8c118d18dfacb7da43c1caaShengzhou Liu PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0) || 257eee41b49b80420e3e8c118d18dfacb7da43c1caaShengzhou Liu in_be32(non_ehci + FSL_SOC_USB_PRICTRL))) { 258f4fbb6d56474d0eae9b819b1549476d2470e12beJingoo Han dev_warn(hcd->self.controller, "USB PHY clock invalid\n"); 2593735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu return -EINVAL; 2603735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu } 2613735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu } 2623735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu 263083522d76662cda71328df1f3d75e5a9057c7c9fBenjamin Herrenschmidt ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); 2643735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu 265f66dea709cd9309b2ee9f715697818001fb518deAnatolij Gustschin if (phy_mode != FSL_USB2_PHY_ULPI && pdata->have_sysif_regs) 2663735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN); 2673735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu 2683735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu return 0; 26980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson} 27080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 2713735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liustatic int ehci_fsl_usb_setup(struct ehci_hcd *ehci) 27280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson{ 273230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin struct usb_hcd *hcd = ehci_to_hcd(ehci); 27480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson struct fsl_usb2_platform_data *pdata; 27580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson void __iomem *non_ehci = hcd->regs; 27680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 277d4f09e28d7bc5c1adde8229b1e89401f23fb44f9Jingoo Han pdata = dev_get_platdata(hcd->self.controller); 278230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin 279230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin if (pdata->have_sysif_regs) { 2804c954326823585bd014f36b2babd39c107c2bbb4Pan Jiafei /* 2814c954326823585bd014f36b2babd39c107c2bbb4Pan Jiafei * Turn on cache snooping hardware, since some PowerPC platforms 2824c954326823585bd014f36b2babd39c107c2bbb4Pan Jiafei * wholly rely on hardware to deal with cache coherent 2834c954326823585bd014f36b2babd39c107c2bbb4Pan Jiafei */ 28440acc095302aee380491df5f58d98945243468ecLi Yang 2854c954326823585bd014f36b2babd39c107c2bbb4Pan Jiafei /* Setup Snooping for all the 4GB space */ 2864c954326823585bd014f36b2babd39c107c2bbb4Pan Jiafei /* SNOOP1 starts from 0x0, size 2G */ 2874c954326823585bd014f36b2babd39c107c2bbb4Pan Jiafei out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0 | SNOOP_SIZE_2GB); 2884c954326823585bd014f36b2babd39c107c2bbb4Pan Jiafei /* SNOOP2 starts from 0x80000000, size 2G */ 2894c954326823585bd014f36b2babd39c107c2bbb4Pan Jiafei out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB); 2904c954326823585bd014f36b2babd39c107c2bbb4Pan Jiafei } 29140acc095302aee380491df5f58d98945243468ecLi Yang 292ba02978a48f0117b3d0aced97a30615a5d7412e2Li Yang if ((pdata->operating_mode == FSL_USB2_DR_HOST) || 293ba02978a48f0117b3d0aced97a30615a5d7412e2Li Yang (pdata->operating_mode == FSL_USB2_DR_OTG)) 2943735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0)) 2953735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu return -EINVAL; 29680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 29780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson if (pdata->operating_mode == FSL_USB2_MPH_HOST) { 2988cd42e97bf451bbbb2f54dc571366ae5a72faaeaKumar Gala unsigned int chip, rev, svr; 2998cd42e97bf451bbbb2f54dc571366ae5a72faaeaKumar Gala 3008cd42e97bf451bbbb2f54dc571366ae5a72faaeaKumar Gala svr = mfspr(SPRN_SVR); 3018cd42e97bf451bbbb2f54dc571366ae5a72faaeaKumar Gala chip = svr >> 16; 3028cd42e97bf451bbbb2f54dc571366ae5a72faaeaKumar Gala rev = (svr >> 4) & 0xf; 3038cd42e97bf451bbbb2f54dc571366ae5a72faaeaKumar Gala 3048cd42e97bf451bbbb2f54dc571366ae5a72faaeaKumar Gala /* Deal with USB Erratum #14 on MPC834x Rev 1.0 & 1.1 chips */ 3058cd42e97bf451bbbb2f54dc571366ae5a72faaeaKumar Gala if ((rev == 1) && (chip >= 0x8050) && (chip <= 0x8055)) 3068cd42e97bf451bbbb2f54dc571366ae5a72faaeaKumar Gala ehci->has_fsl_port_bug = 1; 3078cd42e97bf451bbbb2f54dc571366ae5a72faaeaKumar Gala 30880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) 3093735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0)) 3103735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu return -EINVAL; 3113735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu 31280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) 3133735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1)) 3143735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu return -EINVAL; 31580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson } 31680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 317230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin if (pdata->have_sysif_regs) { 31808d7660d45bc3e14b0fafe2e891ca50b4b18591aKumar Gala#ifdef CONFIG_FSL_SOC_BOOKE 319230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x00000008); 320230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000080); 3214f5342583c67fde6825d39b19c6b252db80beaf2Srikanth Srinivasan#else 322230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin out_be32(non_ehci + FSL_SOC_USB_PRICTRL, 0x0000000c); 323230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin out_be32(non_ehci + FSL_SOC_USB_AGECNTTHRSH, 0x00000040); 3244f5342583c67fde6825d39b19c6b252db80beaf2Srikanth Srinivasan#endif 325230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); 326230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin } 3273735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu 3283735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu return 0; 32980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson} 33080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 33180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson/* called after powerup, by probe or system-pm "wakeup" */ 33280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinsonstatic int ehci_fsl_reinit(struct ehci_hcd *ehci) 33380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson{ 3343735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu if (ehci_fsl_usb_setup(ehci)) 3353735ba8db8e6ea22ad3ff524328926d8d780a884Shengzhou Liu return -EINVAL; 33680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 33780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson return 0; 33880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson} 33980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 34080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson/* called during probe() after chip reset completes */ 34180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinsonstatic int ehci_fsl_setup(struct usb_hcd *hcd) 34280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson{ 34380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson struct ehci_hcd *ehci = hcd_to_ehci(hcd); 34480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson int retval; 345230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin struct fsl_usb2_platform_data *pdata; 346761bbcb74e4611414937ea480ba60bb970648755Anatolij Gustschin struct device *dev; 347230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin 348761bbcb74e4611414937ea480ba60bb970648755Anatolij Gustschin dev = hcd->self.controller; 349d4f09e28d7bc5c1adde8229b1e89401f23fb44f9Jingoo Han pdata = dev_get_platdata(hcd->self.controller); 350230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin ehci->big_endian_desc = pdata->big_endian_desc; 351230f7ede6c2f0e403f29e03e0251a470aa9350ddAnatolij Gustschin ehci->big_endian_mmio = pdata->big_endian_mmio; 35280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 35380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson /* EHCI registers start at offset 0x100 */ 35480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson ehci->caps = hcd->regs + 0x100; 35580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 356e6604a7fd71f9bd2890e07800e191167d7f5751bChristian Engelmayer#ifdef CONFIG_PPC_83xx 357e6604a7fd71f9bd2890e07800e191167d7f5751bChristian Engelmayer /* 358e6604a7fd71f9bd2890e07800e191167d7f5751bChristian Engelmayer * Deal with MPC834X that need port power to be cycled after the power 359e6604a7fd71f9bd2890e07800e191167d7f5751bChristian Engelmayer * fault condition is removed. Otherwise the state machine does not 360e6604a7fd71f9bd2890e07800e191167d7f5751bChristian Engelmayer * reflect PORTSC[CSC] correctly. 361e6604a7fd71f9bd2890e07800e191167d7f5751bChristian Engelmayer */ 362e6604a7fd71f9bd2890e07800e191167d7f5751bChristian Engelmayer ehci->need_oc_pp_cycle = 1; 363e6604a7fd71f9bd2890e07800e191167d7f5751bChristian Engelmayer#endif 364e6604a7fd71f9bd2890e07800e191167d7f5751bChristian Engelmayer 36565fd42724aee31018b0bb53f4cb04971423be664Matthieu CASTET hcd->has_tt = 1; 36665fd42724aee31018b0bb53f4cb04971423be664Matthieu CASTET 3671a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern retval = ehci_setup(hcd); 36880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson if (retval) 36980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson return retval; 37080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 371761bbcb74e4611414937ea480ba60bb970648755Anatolij Gustschin if (of_device_is_compatible(dev->parent->of_node, 372761bbcb74e4611414937ea480ba60bb970648755Anatolij Gustschin "fsl,mpc5121-usb2-dr")) { 373761bbcb74e4611414937ea480ba60bb970648755Anatolij Gustschin /* 374761bbcb74e4611414937ea480ba60bb970648755Anatolij Gustschin * set SBUSCFG:AHBBRST so that control msgs don't 375761bbcb74e4611414937ea480ba60bb970648755Anatolij Gustschin * fail when doing heavy PATA writes. 376761bbcb74e4611414937ea480ba60bb970648755Anatolij Gustschin */ 377761bbcb74e4611414937ea480ba60bb970648755Anatolij Gustschin ehci_writel(ehci, SBUSCFG_INCR8, 378761bbcb74e4611414937ea480ba60bb970648755Anatolij Gustschin hcd->regs + FSL_SOC_USB_SBUSCFG); 379761bbcb74e4611414937ea480ba60bb970648755Anatolij Gustschin } 380761bbcb74e4611414937ea480ba60bb970648755Anatolij Gustschin 38180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson retval = ehci_fsl_reinit(ehci); 38280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson return retval; 38380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson} 38480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 3851af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsovstruct ehci_fsl { 3861af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov struct ehci_hcd ehci; 3871af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 3881af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov#ifdef CONFIG_PM 3891af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov /* Saved USB PHY settings, need to restore after deep sleep. */ 3901af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov u32 usb_ctrl; 3911af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov#endif 3921af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov}; 3931af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 3941af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov#ifdef CONFIG_PM 3951af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 39613b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin#ifdef CONFIG_PPC_MPC512x 39713b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschinstatic int ehci_fsl_mpc512x_drv_suspend(struct device *dev) 39813b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin{ 39913b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin struct usb_hcd *hcd = dev_get_drvdata(dev); 40013b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin struct ehci_hcd *ehci = hcd_to_ehci(hcd); 401d4f09e28d7bc5c1adde8229b1e89401f23fb44f9Jingoo Han struct fsl_usb2_platform_data *pdata = dev_get_platdata(dev); 40213b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin u32 tmp; 40313b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 4041c20163d30db28552a341d5e0d6c007d4c8dc8beOliver Neukum#ifdef CONFIG_DYNAMIC_DEBUG 40513b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin u32 mode = ehci_readl(ehci, hcd->regs + FSL_SOC_USB_USBMODE); 40613b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin mode &= USBMODE_CM_MASK; 40713b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin tmp = ehci_readl(ehci, hcd->regs + 0x140); /* usbcmd */ 40813b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 40913b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin dev_dbg(dev, "suspend=%d already_suspended=%d " 41013b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin "mode=%d usbcmd %08x\n", pdata->suspended, 41113b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->already_suspended, mode, tmp); 41213b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin#endif 41313b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 41413b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin /* 41513b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin * If the controller is already suspended, then this must be a 41613b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin * PM suspend. Remember this fact, so that we will leave the 41713b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin * controller suspended at PM resume time. 41813b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin */ 41913b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin if (pdata->suspended) { 42013b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin dev_dbg(dev, "already suspended, leaving early\n"); 42113b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->already_suspended = 1; 42213b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin return 0; 42313b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin } 42413b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 42513b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin dev_dbg(dev, "suspending...\n"); 42613b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 427e8799906045302776b35b66b16495c575db3b69cAlan Stern ehci->rh_state = EHCI_RH_SUSPENDED; 42813b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin dev->power.power_state = PMSG_SUSPEND; 42913b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 43013b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin /* ignore non-host interrupts */ 43113b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 43213b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 43313b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin /* stop the controller */ 43413b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin tmp = ehci_readl(ehci, &ehci->regs->command); 43513b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin tmp &= ~CMD_RUN; 43613b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin ehci_writel(ehci, tmp, &ehci->regs->command); 43713b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 43813b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin /* save EHCI registers */ 43913b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->pm_command = ehci_readl(ehci, &ehci->regs->command); 44013b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->pm_command &= ~CMD_RUN; 44113b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->pm_status = ehci_readl(ehci, &ehci->regs->status); 44213b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->pm_intr_enable = ehci_readl(ehci, &ehci->regs->intr_enable); 44313b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->pm_frame_index = ehci_readl(ehci, &ehci->regs->frame_index); 44413b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->pm_segment = ehci_readl(ehci, &ehci->regs->segment); 44513b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->pm_frame_list = ehci_readl(ehci, &ehci->regs->frame_list); 44613b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->pm_async_next = ehci_readl(ehci, &ehci->regs->async_next); 44713b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->pm_configured_flag = 44813b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin ehci_readl(ehci, &ehci->regs->configured_flag); 44913b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->pm_portsc = ehci_readl(ehci, &ehci->regs->port_status[0]); 45013b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->pm_usbgenctrl = ehci_readl(ehci, 45113b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin hcd->regs + FSL_SOC_USB_USBGENCTRL); 45213b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 45313b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin /* clear the W1C bits */ 45413b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->pm_portsc &= cpu_to_hc32(ehci, ~PORT_RWC_BITS); 45513b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 45613b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->suspended = 1; 45713b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 45813b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin /* clear PP to cut power to the port */ 45913b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin tmp = ehci_readl(ehci, &ehci->regs->port_status[0]); 46013b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin tmp &= ~PORT_POWER; 46113b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin ehci_writel(ehci, tmp, &ehci->regs->port_status[0]); 46213b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 46313b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin return 0; 46413b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin} 46513b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 46613b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschinstatic int ehci_fsl_mpc512x_drv_resume(struct device *dev) 46713b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin{ 46813b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin struct usb_hcd *hcd = dev_get_drvdata(dev); 46913b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin struct ehci_hcd *ehci = hcd_to_ehci(hcd); 470d4f09e28d7bc5c1adde8229b1e89401f23fb44f9Jingoo Han struct fsl_usb2_platform_data *pdata = dev_get_platdata(dev); 47113b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin u32 tmp; 47213b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 47313b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin dev_dbg(dev, "suspend=%d already_suspended=%d\n", 47413b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->suspended, pdata->already_suspended); 47513b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 47613b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin /* 47713b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin * If the controller was already suspended at suspend time, 47813b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin * then don't resume it now. 47913b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin */ 48013b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin if (pdata->already_suspended) { 48113b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin dev_dbg(dev, "already suspended, leaving early\n"); 48213b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->already_suspended = 0; 48313b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin return 0; 48413b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin } 48513b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 48613b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin if (!pdata->suspended) { 48713b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin dev_dbg(dev, "not suspended, leaving early\n"); 48813b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin return 0; 48913b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin } 49013b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 49113b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin pdata->suspended = 0; 49213b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 49313b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin dev_dbg(dev, "resuming...\n"); 49413b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 49513b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin /* set host mode */ 49613b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin tmp = USBMODE_CM_HOST | (pdata->es ? USBMODE_ES : 0); 49713b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin ehci_writel(ehci, tmp, hcd->regs + FSL_SOC_USB_USBMODE); 49813b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 49913b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin ehci_writel(ehci, pdata->pm_usbgenctrl, 50013b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin hcd->regs + FSL_SOC_USB_USBGENCTRL); 50113b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin ehci_writel(ehci, ISIPHYCTRL_PXE | ISIPHYCTRL_PHYE, 50213b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin hcd->regs + FSL_SOC_USB_ISIPHYCTRL); 50313b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 504761bbcb74e4611414937ea480ba60bb970648755Anatolij Gustschin ehci_writel(ehci, SBUSCFG_INCR8, hcd->regs + FSL_SOC_USB_SBUSCFG); 505761bbcb74e4611414937ea480ba60bb970648755Anatolij Gustschin 50613b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin /* restore EHCI registers */ 50713b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin ehci_writel(ehci, pdata->pm_command, &ehci->regs->command); 50813b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin ehci_writel(ehci, pdata->pm_intr_enable, &ehci->regs->intr_enable); 50913b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin ehci_writel(ehci, pdata->pm_frame_index, &ehci->regs->frame_index); 51013b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin ehci_writel(ehci, pdata->pm_segment, &ehci->regs->segment); 51113b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin ehci_writel(ehci, pdata->pm_frame_list, &ehci->regs->frame_list); 51213b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin ehci_writel(ehci, pdata->pm_async_next, &ehci->regs->async_next); 51313b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin ehci_writel(ehci, pdata->pm_configured_flag, 51413b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin &ehci->regs->configured_flag); 51513b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin ehci_writel(ehci, pdata->pm_portsc, &ehci->regs->port_status[0]); 51613b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 51713b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 518e8799906045302776b35b66b16495c575db3b69cAlan Stern ehci->rh_state = EHCI_RH_RUNNING; 51913b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin dev->power.power_state = PMSG_ON; 52013b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 52113b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin tmp = ehci_readl(ehci, &ehci->regs->command); 52213b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin tmp |= CMD_RUN; 52313b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin ehci_writel(ehci, tmp, &ehci->regs->command); 52413b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 52513b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin usb_hcd_resume_root_hub(hcd); 52613b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 52713b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin return 0; 52813b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin} 52913b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin#else 53013b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschinstatic inline int ehci_fsl_mpc512x_drv_suspend(struct device *dev) 53113b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin{ 53213b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin return 0; 53313b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin} 53413b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 53513b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschinstatic inline int ehci_fsl_mpc512x_drv_resume(struct device *dev) 53613b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin{ 53713b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin return 0; 53813b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin} 53913b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin#endif /* CONFIG_PPC_MPC512x */ 54013b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 5411af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsovstatic struct ehci_fsl *hcd_to_ehci_fsl(struct usb_hcd *hcd) 5421af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov{ 5431af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov struct ehci_hcd *ehci = hcd_to_ehci(hcd); 5441af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 5451af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov return container_of(ehci, struct ehci_fsl, ehci); 5461af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov} 5471af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 5481af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsovstatic int ehci_fsl_drv_suspend(struct device *dev) 5491af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov{ 5501af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov struct usb_hcd *hcd = dev_get_drvdata(dev); 5511af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd); 5521af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov void __iomem *non_ehci = hcd->regs; 5531af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 55413b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin if (of_device_is_compatible(dev->parent->of_node, 55513b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin "fsl,mpc5121-usb2-dr")) { 55613b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin return ehci_fsl_mpc512x_drv_suspend(dev); 55713b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin } 55813b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 5594147200d25c423e627ab4487530b3d9f2ef829c8Alan Stern ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), 5604147200d25c423e627ab4487530b3d9f2ef829c8Alan Stern device_may_wakeup(dev)); 5611af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov if (!fsl_deep_sleep()) 5621af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov return 0; 5631af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 5641af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov ehci_fsl->usb_ctrl = in_be32(non_ehci + FSL_SOC_USB_CTRL); 5651af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov return 0; 5661af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov} 5671af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 5681af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsovstatic int ehci_fsl_drv_resume(struct device *dev) 5691af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov{ 5701af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov struct usb_hcd *hcd = dev_get_drvdata(dev); 5711af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd); 5721af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov struct ehci_hcd *ehci = hcd_to_ehci(hcd); 5731af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov void __iomem *non_ehci = hcd->regs; 5741af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 57513b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin if (of_device_is_compatible(dev->parent->of_node, 57613b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin "fsl,mpc5121-usb2-dr")) { 57713b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin return ehci_fsl_mpc512x_drv_resume(dev); 57813b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin } 57913b7ee2a953f07d994b6bc3439cdd4a718de6f80Anatolij Gustschin 58016032c4f5b291af541e9114a09ea20ff5a0dc474Alan Stern ehci_prepare_ports_for_controller_resume(ehci); 5811af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov if (!fsl_deep_sleep()) 5821af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov return 0; 5831af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 5841af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov usb_root_hub_lost_power(hcd->self.root_hub); 5851af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 5861af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov /* Restore USB PHY settings and enable the controller. */ 5871af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov out_be32(non_ehci + FSL_SOC_USB_CTRL, ehci_fsl->usb_ctrl); 5881af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 5891af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov ehci_reset(ehci); 5901af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov ehci_fsl_reinit(ehci); 5911af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 5921af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov return 0; 5931af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov} 5941af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 5951af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsovstatic int ehci_fsl_drv_restore(struct device *dev) 5961af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov{ 5971af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov struct usb_hcd *hcd = dev_get_drvdata(dev); 5981af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 5991af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov usb_root_hub_lost_power(hcd->self.root_hub); 6001af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov return 0; 6011af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov} 6021af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 6031af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsovstatic struct dev_pm_ops ehci_fsl_pm_ops = { 6041af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov .suspend = ehci_fsl_drv_suspend, 6051af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov .resume = ehci_fsl_drv_resume, 6061af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov .restore = ehci_fsl_drv_restore, 6071af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov}; 6081af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 6091af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov#define EHCI_FSL_PM_OPS (&ehci_fsl_pm_ops) 6101af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov#else 6111af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov#define EHCI_FSL_PM_OPS NULL 6121af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov#endif /* CONFIG_PM */ 6131af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov 61483722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin#ifdef CONFIG_USB_OTG 61583722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschinstatic int ehci_start_port_reset(struct usb_hcd *hcd, unsigned port) 61683722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin{ 61783722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin struct ehci_hcd *ehci = hcd_to_ehci(hcd); 61883722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin u32 status; 61983722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin 62083722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin if (!port) 62183722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin return -EINVAL; 62283722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin 62383722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin port--; 62483722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin 62583722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin /* start port reset before HNP protocol time out */ 62683722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin status = readl(&ehci->regs->port_status[port]); 62783722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin if (!(status & PORT_CONNECT)) 62883722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin return -ENODEV; 62983722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin 63037ebb54915dc42944f6ae92fe53b9531c3903801Petr Mladek /* hub_wq will finish the reset later */ 63183722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin if (ehci_is_TDI(ehci)) { 63283722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin writel(PORT_RESET | 63383722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin (status & ~(PORT_CSC | PORT_PEC | PORT_OCC)), 63483722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin &ehci->regs->port_status[port]); 63583722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin } else { 63683722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin writel(PORT_RESET, &ehci->regs->port_status[port]); 63783722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin } 63883722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin 63983722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin return 0; 64083722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin} 64183722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin#else 64283722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin#define ehci_start_port_reset NULL 64383722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin#endif /* CONFIG_USB_OTG */ 64483722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin 64583722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin 64680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinsonstatic const struct hc_driver ehci_fsl_hc_driver = { 64780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson .description = hcd_name, 64880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson .product_desc = "Freescale On-Chip EHCI Host Controller", 6491af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov .hcd_priv_size = sizeof(struct ehci_fsl), 65080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 65180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson /* 65280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * generic hardware linkage 65380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson */ 65480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson .irq = ehci_irq, 655c04ee4b1136e462722567cf6e76bb35a181574a7Greg Kroah-Hartman .flags = HCD_USB2 | HCD_MEMORY | HCD_BH, 65680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 65780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson /* 65880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * basic lifecycle operations 65980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson */ 66080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson .reset = ehci_fsl_setup, 66180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson .start = ehci_run, 66280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson .stop = ehci_stop, 66364a21d025d3a979a8715f2ec7acabca7b5406c8aAleksey Gorelov .shutdown = ehci_shutdown, 66480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 66580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson /* 66680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * managing i/o requests and associated device resources 66780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson */ 66880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson .urb_enqueue = ehci_urb_enqueue, 66980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson .urb_dequeue = ehci_urb_dequeue, 67080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson .endpoint_disable = ehci_endpoint_disable, 671b18ffd49e86102a9ed0a1cc83fdafe3891e844e5Alan Stern .endpoint_reset = ehci_endpoint_reset, 67280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 67380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson /* 67480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * scheduling support 67580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson */ 67680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson .get_frame_number = ehci_get_frame, 67780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 67880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson /* 67980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson * root hub support 68080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson */ 68180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson .hub_status_data = ehci_hub_status_data, 68280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson .hub_control = ehci_hub_control, 68380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson .bus_suspend = ehci_bus_suspend, 68480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson .bus_resume = ehci_bus_resume, 68583722bc9430424de1614ff31696f73a40b3d81a9Anatolij Gustschin .start_port_reset = ehci_start_port_reset, 68690da096ee46b682011b7d549e52b81cf9742e60bBalaji Rao .relinquish_port = ehci_relinquish_port, 6873a31155cfff0935e4b178f3dca733d2d60d2eb8dAlan Stern .port_handed_over = ehci_port_handed_over, 688914b701280a76f96890ad63eb0fa99bf204b961cAlan Stern 689914b701280a76f96890ad63eb0fa99bf204b961cAlan Stern .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, 69080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson}; 69180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 69280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinsonstatic int ehci_fsl_drv_probe(struct platform_device *pdev) 69380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson{ 69480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson if (usb_disabled()) 69580cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson return -ENODEV; 69680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 697135db0485cdfa808d69420889ca4a2fad8aed9dfDavid Brownell /* FIXME we only want one one probe() not two */ 69880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson return usb_hcd_fsl_probe(&ehci_fsl_hc_driver, pdev); 69980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson} 70080cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 70180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinsonstatic int ehci_fsl_drv_remove(struct platform_device *pdev) 70280cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson{ 70380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson struct usb_hcd *hcd = platform_get_drvdata(pdev); 70480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 705135db0485cdfa808d69420889ca4a2fad8aed9dfDavid Brownell /* FIXME we only want one one remove() not two */ 70680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson usb_hcd_fsl_remove(hcd, pdev); 70780cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson return 0; 70880cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson} 70980cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 710135db0485cdfa808d69420889ca4a2fad8aed9dfDavid BrownellMODULE_ALIAS("platform:fsl-ehci"); 71180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson 71201cced250722d22d99c2342979490f93ca886521Kumar Galastatic struct platform_driver ehci_fsl_driver = { 71380cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson .probe = ehci_fsl_drv_probe, 71480cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson .remove = ehci_fsl_drv_remove, 71564a21d025d3a979a8715f2ec7acabca7b5406c8aAleksey Gorelov .shutdown = usb_hcd_platform_shutdown, 71680cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson .driver = { 7171af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov .name = "fsl-ehci", 7189e873d429b583e59b25d0705d705239844a98717Libo Chen .owner = THIS_MODULE, 7191af107744253b01b4cf119a9bb3369376b01658bAnton Vorontsov .pm = EHCI_FSL_PM_OPS, 720135db0485cdfa808d69420889ca4a2fad8aed9dfDavid Brownell }, 72180cb9aee01245b38325dd84f1359b14a3f01f10dRandy Vinson}; 722