17e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack/*
27e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
37e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
47e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack *
57e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack * This program is free software; you can redistribute it and/or modify it
67e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack * under the terms of the GNU General Public License as published by the
77e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack * Free Software Foundation; either version 2 of the License, or (at your
87e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack * option) any later version.
97e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack *
107e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack * This program is distributed in the hope that it will be useful, but
117e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
127e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
137e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack * for more details.
147e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack *
157e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack * You should have received a copy of the GNU General Public License
167e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack * along with this program; if not, write to the Free Software Foundation,
177e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
187e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack */
197e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
20dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern#include <linux/kernel.h>
21dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern#include <linux/module.h>
22dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern#include <linux/io.h>
237e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack#include <linux/platform_device.h>
247e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack#include <linux/clk.h>
257e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack#include <linux/delay.h>
267e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack#include <linux/usb/otg.h>
27a464dc4d4044c936d4558725fa2229fb4a1aa932Arnaud Patard#include <linux/usb/ulpi.h>
285a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
29dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern#include <linux/usb.h>
30dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern#include <linux/usb/hcd.h>
3182906b13a6f4f42edec92f0a3e480e1bdd9b3f91Arnd Bergmann#include <linux/platform_data/usb-ehci-mxc.h>
32dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern#include "ehci.h"
33dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern
34dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern#define DRIVER_DESC "Freescale On-Chip EHCI Host driver"
35dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern
36dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Sternstatic const char hcd_name[] = "ehci-mxc";
37dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern
387e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack#define ULPI_VIEWPORT_OFFSET	0x170
397e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
407e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mackstruct ehci_mxc_priv {
41c943740ccd7ccfc7e92c80d194d0a8a80ab7b55cSascha Hauer	struct clk *usbclk, *ahbclk, *phyclk;
427e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack};
437e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
44dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Sternstatic struct hc_driver __read_mostly ehci_mxc_hc_driver;
457e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
4662d08a1151d2755dc580a8311a6684275e4aeb94Andi Kleenstatic const struct ehci_driver_overrides ehci_mxc_overrides __initconst = {
47dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern	.extra_priv_size =	sizeof(struct ehci_mxc_priv),
487e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack};
497e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
507e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mackstatic int ehci_mxc_drv_probe(struct platform_device *pdev)
517e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack{
52d4f09e28d7bc5c1adde8229b1e89401f23fb44f9Jingoo Han	struct mxc_usbh_platform_data *pdata = dev_get_platdata(&pdev->dev);
537e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	struct usb_hcd *hcd;
547e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	struct resource *res;
55724c85251f78f1332e0a28f80cead0cee5b7c906Uwe Kleine-König	int irq, ret;
567e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	struct ehci_mxc_priv *priv;
577e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	struct device *dev = &pdev->dev;
580247a7bcd4273fa10c4aba9b3f567c659bab2d2bFabio Estevam	struct ehci_hcd *ehci;
597e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
607e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	if (!pdata) {
617e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack		dev_err(dev, "No platform data given, bailing out.\n");
627e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack		return -EINVAL;
637e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	}
647e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
657e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	irq = platform_get_irq(pdev, 0);
667e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
677e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	hcd = usb_create_hcd(&ehci_mxc_hc_driver, dev, dev_name(dev));
687e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	if (!hcd)
697e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack		return -ENOMEM;
707e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
717e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
727e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	if (!res) {
737e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack		dev_err(dev, "Found HC with no register addr. Check setup!\n");
747e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack		ret = -ENODEV;
75af09c060895b9c9137c02943c71302ac0fc9555aJulia Lawall		goto err_alloc;
767e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	}
777e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
787e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	hcd->rsrc_start = res->start;
797e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	hcd->rsrc_len = resource_size(res);
807e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
81148e11349b0c9c7199fd3096254bd3ea16d59a05Thierry Reding	hcd->regs = devm_ioremap_resource(&pdev->dev, res);
82148e11349b0c9c7199fd3096254bd3ea16d59a05Thierry Reding	if (IS_ERR(hcd->regs)) {
83148e11349b0c9c7199fd3096254bd3ea16d59a05Thierry Reding		ret = PTR_ERR(hcd->regs);
84af09c060895b9c9137c02943c71302ac0fc9555aJulia Lawall		goto err_alloc;
857e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	}
867e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
87dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern	hcd->has_tt = 1;
88dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern	ehci = hcd_to_ehci(hcd);
89dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern	priv = (struct ehci_mxc_priv *) ehci->priv;
90dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern
917e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	/* enable clocks */
92af09c060895b9c9137c02943c71302ac0fc9555aJulia Lawall	priv->usbclk = devm_clk_get(&pdev->dev, "ipg");
937e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	if (IS_ERR(priv->usbclk)) {
947e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack		ret = PTR_ERR(priv->usbclk);
95af09c060895b9c9137c02943c71302ac0fc9555aJulia Lawall		goto err_alloc;
967e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	}
97198ad2cecde16ce309a65f2fddd5f6d3442f8250Sascha Hauer	clk_prepare_enable(priv->usbclk);
987e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
99af09c060895b9c9137c02943c71302ac0fc9555aJulia Lawall	priv->ahbclk = devm_clk_get(&pdev->dev, "ahb");
100c943740ccd7ccfc7e92c80d194d0a8a80ab7b55cSascha Hauer	if (IS_ERR(priv->ahbclk)) {
101c943740ccd7ccfc7e92c80d194d0a8a80ab7b55cSascha Hauer		ret = PTR_ERR(priv->ahbclk);
102c943740ccd7ccfc7e92c80d194d0a8a80ab7b55cSascha Hauer		goto err_clk_ahb;
1037e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	}
104c943740ccd7ccfc7e92c80d194d0a8a80ab7b55cSascha Hauer	clk_prepare_enable(priv->ahbclk);
1057e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
1063bb8029a2445e289efade6133b01545143336f70Eric Bénard	/* "dr" device has its own clock on i.MX51 */
107af09c060895b9c9137c02943c71302ac0fc9555aJulia Lawall	priv->phyclk = devm_clk_get(&pdev->dev, "phy");
108c943740ccd7ccfc7e92c80d194d0a8a80ab7b55cSascha Hauer	if (IS_ERR(priv->phyclk))
109c943740ccd7ccfc7e92c80d194d0a8a80ab7b55cSascha Hauer		priv->phyclk = NULL;
110c943740ccd7ccfc7e92c80d194d0a8a80ab7b55cSascha Hauer	if (priv->phyclk)
111c943740ccd7ccfc7e92c80d194d0a8a80ab7b55cSascha Hauer		clk_prepare_enable(priv->phyclk);
112711669e5b80b6f2d88f61ed8a9681f83d8cbd201Arnaud Patard
113711669e5b80b6f2d88f61ed8a9681f83d8cbd201Arnaud Patard
114711669e5b80b6f2d88f61ed8a9681f83d8cbd201Arnaud Patard	/* call platform specific init function */
115711669e5b80b6f2d88f61ed8a9681f83d8cbd201Arnaud Patard	if (pdata->init) {
116711669e5b80b6f2d88f61ed8a9681f83d8cbd201Arnaud Patard		ret = pdata->init(pdev);
117711669e5b80b6f2d88f61ed8a9681f83d8cbd201Arnaud Patard		if (ret) {
118711669e5b80b6f2d88f61ed8a9681f83d8cbd201Arnaud Patard			dev_err(dev, "platform init failed\n");
119711669e5b80b6f2d88f61ed8a9681f83d8cbd201Arnaud Patard			goto err_init;
120711669e5b80b6f2d88f61ed8a9681f83d8cbd201Arnaud Patard		}
121711669e5b80b6f2d88f61ed8a9681f83d8cbd201Arnaud Patard		/* platforms need some time to settle changed IO settings */
122711669e5b80b6f2d88f61ed8a9681f83d8cbd201Arnaud Patard		mdelay(10);
123711669e5b80b6f2d88f61ed8a9681f83d8cbd201Arnaud Patard	}
124711669e5b80b6f2d88f61ed8a9681f83d8cbd201Arnaud Patard
1250247a7bcd4273fa10c4aba9b3f567c659bab2d2bFabio Estevam	/* EHCI registers start at offset 0x100 */
1260247a7bcd4273fa10c4aba9b3f567c659bab2d2bFabio Estevam	ehci->caps = hcd->regs + 0x100;
1270247a7bcd4273fa10c4aba9b3f567c659bab2d2bFabio Estevam	ehci->regs = hcd->regs + 0x100 +
128c430131a02d677aa708f56342c1565edfdacb3c0Jan Andersson		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
1290247a7bcd4273fa10c4aba9b3f567c659bab2d2bFabio Estevam
1300247a7bcd4273fa10c4aba9b3f567c659bab2d2bFabio Estevam	/* set up the PORTSCx register */
1310247a7bcd4273fa10c4aba9b3f567c659bab2d2bFabio Estevam	ehci_writel(ehci, pdata->portsc, &ehci->regs->port_status[0]);
1320247a7bcd4273fa10c4aba9b3f567c659bab2d2bFabio Estevam
1330247a7bcd4273fa10c4aba9b3f567c659bab2d2bFabio Estevam	/* is this really needed? */
1340247a7bcd4273fa10c4aba9b3f567c659bab2d2bFabio Estevam	msleep(10);
1350247a7bcd4273fa10c4aba9b3f567c659bab2d2bFabio Estevam
1367e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	/* Initialize the transceiver */
1377e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	if (pdata->otg) {
1387e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack		pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET;
139b96d3b08365f5a9603f50f3aadca6012f7eaffa1Heikki Krogerus		ret = usb_phy_init(pdata->otg);
1404c9715de52b9b6256bf1e9510917111a47b0c176Wolfram Sang		if (ret) {
1414c9715de52b9b6256bf1e9510917111a47b0c176Wolfram Sang			dev_err(dev, "unable to init transceiver, probably missing\n");
1424c9715de52b9b6256bf1e9510917111a47b0c176Wolfram Sang			ret = -ENODEV;
1434c9715de52b9b6256bf1e9510917111a47b0c176Wolfram Sang			goto err_add;
1444c9715de52b9b6256bf1e9510917111a47b0c176Wolfram Sang		}
1456e13c6505cdff9766d5268ffb8c972c1a2f996e6Heikki Krogerus		ret = otg_set_vbus(pdata->otg->otg, 1);
1464c9715de52b9b6256bf1e9510917111a47b0c176Wolfram Sang		if (ret) {
1477e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack			dev_err(dev, "unable to enable vbus on transceiver\n");
1484c9715de52b9b6256bf1e9510917111a47b0c176Wolfram Sang			goto err_add;
1494c9715de52b9b6256bf1e9510917111a47b0c176Wolfram Sang		}
1507e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	}
1517e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
152dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern	platform_set_drvdata(pdev, hcd);
1537e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
154b5dd18d8747010e3f3eb1cc76a49f94291938559Yong Zhang	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
1557e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	if (ret)
1567e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack		goto err_add;
1577e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
1583c9740a117d40a74412775b5d3fe2b88a7635a0ePeter Chen	device_wakeup_enable(hcd->self.controller);
1597e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	return 0;
1607e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
1617e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mackerr_add:
1627e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	if (pdata && pdata->exit)
1637e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack		pdata->exit(pdev);
1647e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mackerr_init:
165af09c060895b9c9137c02943c71302ac0fc9555aJulia Lawall	if (priv->phyclk)
166c943740ccd7ccfc7e92c80d194d0a8a80ab7b55cSascha Hauer		clk_disable_unprepare(priv->phyclk);
167c943740ccd7ccfc7e92c80d194d0a8a80ab7b55cSascha Hauer
168c943740ccd7ccfc7e92c80d194d0a8a80ab7b55cSascha Hauer	clk_disable_unprepare(priv->ahbclk);
1697e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mackerr_clk_ahb:
170198ad2cecde16ce309a65f2fddd5f6d3442f8250Sascha Hauer	clk_disable_unprepare(priv->usbclk);
1717e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mackerr_alloc:
1727e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	usb_put_hcd(hcd);
1737e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	return ret;
1747e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack}
1757e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
17639d35681d5380b403855202dcd75575a8d5b0ec1Dmitry Torokhovstatic int ehci_mxc_drv_remove(struct platform_device *pdev)
1777e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack{
178d4f09e28d7bc5c1adde8229b1e89401f23fb44f9Jingoo Han	struct mxc_usbh_platform_data *pdata = dev_get_platdata(&pdev->dev);
179dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern	struct usb_hcd *hcd = platform_get_drvdata(pdev);
180dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
181dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern	struct ehci_mxc_priv *priv = (struct ehci_mxc_priv *) ehci->priv;
182dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern
183dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern	usb_remove_hcd(hcd);
1847e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
1857e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	if (pdata && pdata->exit)
1867e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack		pdata->exit(pdev);
1877e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
188f375fc520d4df0cd9fcb570f33c103c6c0311f9eDaniel Mack	if (pdata && pdata->otg)
189b96d3b08365f5a9603f50f3aadca6012f7eaffa1Heikki Krogerus		usb_phy_shutdown(pdata->otg);
1907e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
191198ad2cecde16ce309a65f2fddd5f6d3442f8250Sascha Hauer	clk_disable_unprepare(priv->usbclk);
192c943740ccd7ccfc7e92c80d194d0a8a80ab7b55cSascha Hauer	clk_disable_unprepare(priv->ahbclk);
193c943740ccd7ccfc7e92c80d194d0a8a80ab7b55cSascha Hauer
194af09c060895b9c9137c02943c71302ac0fc9555aJulia Lawall	if (priv->phyclk)
195c943740ccd7ccfc7e92c80d194d0a8a80ab7b55cSascha Hauer		clk_disable_unprepare(priv->phyclk);
1967e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
197dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern	usb_put_hcd(hcd);
1987e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	return 0;
1997e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack}
2007e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
2017e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel MackMODULE_ALIAS("platform:mxc-ehci");
2027e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack
2037e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mackstatic struct platform_driver ehci_mxc_driver = {
2047e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	.probe = ehci_mxc_drv_probe,
205dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern	.remove = ehci_mxc_drv_remove,
206aaf6b52d50f85ed792c9c8987f5169f3dce2adeaRoger Quadros	.shutdown = usb_hcd_platform_shutdown,
2077e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	.driver = {
2087e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack		   .name = "mxc-ehci",
2097e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack	},
2107e8d5cd93fac4d3720d8f780b350c9421e8997d4Daniel Mack};
211dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern
212dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Sternstatic int __init ehci_mxc_init(void)
213dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern{
214dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern	if (usb_disabled())
215dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern		return -ENODEV;
216dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern
217dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
218dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern
219dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern	ehci_init_driver(&ehci_mxc_hc_driver, &ehci_mxc_overrides);
220dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern	return platform_driver_register(&ehci_mxc_driver);
221dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern}
222dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Sternmodule_init(ehci_mxc_init);
223dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern
224dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Sternstatic void __exit ehci_mxc_cleanup(void)
225dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern{
226dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern	platform_driver_unregister(&ehci_mxc_driver);
227dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern}
228dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Sternmodule_exit(ehci_mxc_cleanup);
229dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan Stern
230dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan SternMODULE_DESCRIPTION(DRIVER_DESC);
231dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan SternMODULE_AUTHOR("Sascha Hauer");
232dba63b2f733ebfd89bbb15e8fe8ca10fd3871a7fAlan SternMODULE_LICENSE("GPL");
233