From 57f0f512b273f60d52568b8c6b77e17f5636edc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Fabian=20Silva=20Delgado?= Date: Wed, 5 Aug 2015 17:04:01 -0300 Subject: Initial import --- drivers/usb/host/ehci-w90x900.c | 148 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 drivers/usb/host/ehci-w90x900.c (limited to 'drivers/usb/host/ehci-w90x900.c') diff --git a/drivers/usb/host/ehci-w90x900.c b/drivers/usb/host/ehci-w90x900.c new file mode 100644 index 000000000..e42a29e8e --- /dev/null +++ b/drivers/usb/host/ehci-w90x900.c @@ -0,0 +1,148 @@ +/* + * linux/driver/usb/host/ehci-w90x900.c + * + * Copyright (c) 2008 Nuvoton technology corporation. + * + * Wan ZongShun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation;version 2 of the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ehci.h" + +/* enable phy0 and phy1 for w90p910 */ +#define ENPHY (0x01<<8) +#define PHY0_CTR (0xA4) +#define PHY1_CTR (0xA8) + +#define DRIVER_DESC "EHCI w90x900 driver" + +static const char hcd_name[] = "ehci-w90x900 "; + +static struct hc_driver __read_mostly ehci_w90x900_hc_driver; + +static int usb_w90x900_probe(const struct hc_driver *driver, + struct platform_device *pdev) +{ + struct usb_hcd *hcd; + struct ehci_hcd *ehci; + struct resource *res; + int retval = 0, irq; + unsigned long val; + + hcd = usb_create_hcd(driver, &pdev->dev, "w90x900 EHCI"); + if (!hcd) { + retval = -ENOMEM; + goto err1; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + hcd->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hcd->regs)) { + retval = PTR_ERR(hcd->regs); + goto err2; + } + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + + ehci = hcd_to_ehci(hcd); + ehci->caps = hcd->regs; + ehci->regs = hcd->regs + + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); + + /* enable PHY 0,1,the regs only apply to w90p910 + * 0xA4,0xA8 were offsets of PHY0 and PHY1 controller of + * w90p910 IC relative to ehci->regs. + */ + val = __raw_readl(ehci->regs+PHY0_CTR); + val |= ENPHY; + __raw_writel(val, ehci->regs+PHY0_CTR); + + val = __raw_readl(ehci->regs+PHY1_CTR); + val |= ENPHY; + __raw_writel(val, ehci->regs+PHY1_CTR); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + retval = irq; + goto err2; + } + + retval = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (retval != 0) + goto err2; + + device_wakeup_enable(hcd->self.controller); + return retval; +err2: + usb_put_hcd(hcd); +err1: + return retval; +} + +static void usb_w90x900_remove(struct usb_hcd *hcd, + struct platform_device *pdev) +{ + usb_remove_hcd(hcd); + usb_put_hcd(hcd); +} + +static int ehci_w90x900_probe(struct platform_device *pdev) +{ + if (usb_disabled()) + return -ENODEV; + + return usb_w90x900_probe(&ehci_w90x900_hc_driver, pdev); +} + +static int ehci_w90x900_remove(struct platform_device *pdev) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + + usb_w90x900_remove(hcd, pdev); + + return 0; +} + +static struct platform_driver ehci_hcd_w90x900_driver = { + .probe = ehci_w90x900_probe, + .remove = ehci_w90x900_remove, + .driver = { + .name = "w90x900-ehci", + }, +}; + +static int __init ehci_w90X900_init(void) +{ + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_DESC "\n", hcd_name); + + ehci_init_driver(&ehci_w90x900_hc_driver, NULL); + return platform_driver_register(&ehci_hcd_w90x900_driver); +} +module_init(ehci_w90X900_init); + +static void __exit ehci_w90X900_cleanup(void) +{ + platform_driver_unregister(&ehci_hcd_w90x900_driver); +} +module_exit(ehci_w90X900_cleanup); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Wan ZongShun "); +MODULE_ALIAS("platform:w90p910-ehci"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3