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