1/* 2 * linux/driver/usb/host/ehci-w90x900.c 3 * 4 * Copyright (c) 2008 Nuvoton technology corporation. 5 * 6 * Wan ZongShun <mcuos.com@gmail.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation;version 2 of the License. 11 * 12 */ 13 14#include <linux/platform_device.h> 15 16/*ebable phy0 and phy1 for w90p910*/ 17#define ENPHY (0x01<<8) 18#define PHY0_CTR (0xA4) 19#define PHY1_CTR (0xA8) 20 21static int __devinit usb_w90x900_probe(const struct hc_driver *driver, 22 struct platform_device *pdev) 23{ 24 struct usb_hcd *hcd; 25 struct ehci_hcd *ehci; 26 struct resource *res; 27 int retval = 0, irq; 28 unsigned long val; 29 30 31 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 32 if (!res) { 33 retval = -ENXIO; 34 goto err1; 35 } 36 37 hcd = usb_create_hcd(driver, &pdev->dev, "w90x900 EHCI"); 38 if (!hcd) { 39 retval = -ENOMEM; 40 goto err1; 41 } 42 43 hcd->rsrc_start = res->start; 44 hcd->rsrc_len = res->end - res->start + 1; 45 46 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { 47 retval = -EBUSY; 48 goto err2; 49 } 50 51 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); 52 if (hcd->regs == NULL) { 53 retval = -EFAULT; 54 goto err3; 55 } 56 57 ehci = hcd_to_ehci(hcd); 58 ehci->caps = hcd->regs; 59 ehci->regs = hcd->regs + 60 HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); 61 62 /* enable PHY 0,1,the regs only apply to w90p910 63 * 0xA4,0xA8 were offsets of PHY0 and PHY1 controller of 64 * w90p910 IC relative to ehci->regs. 65 */ 66 val = __raw_readl(ehci->regs+PHY0_CTR); 67 val |= ENPHY; 68 __raw_writel(val, ehci->regs+PHY0_CTR); 69 70 val = __raw_readl(ehci->regs+PHY1_CTR); 71 val |= ENPHY; 72 __raw_writel(val, ehci->regs+PHY1_CTR); 73 74 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); 75 ehci->sbrn = 0x20; 76 77 irq = platform_get_irq(pdev, 0); 78 if (irq < 0) 79 goto err4; 80 81 retval = usb_add_hcd(hcd, irq, IRQF_SHARED); 82 if (retval != 0) 83 goto err4; 84 85 ehci_writel(ehci, 1, &ehci->regs->configured_flag); 86 87 return retval; 88err4: 89 iounmap(hcd->regs); 90err3: 91 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 92err2: 93 usb_put_hcd(hcd); 94err1: 95 return retval; 96} 97 98static 99void usb_w90x900_remove(struct usb_hcd *hcd, struct platform_device *pdev) 100{ 101 usb_remove_hcd(hcd); 102 iounmap(hcd->regs); 103 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 104 usb_put_hcd(hcd); 105} 106 107static const struct hc_driver ehci_w90x900_hc_driver = { 108 .description = hcd_name, 109 .product_desc = "Nuvoton w90x900 EHCI Host Controller", 110 .hcd_priv_size = sizeof(struct ehci_hcd), 111 112 /* 113 * generic hardware linkage 114 */ 115 .irq = ehci_irq, 116 .flags = HCD_USB2|HCD_MEMORY, 117 118 /* 119 * basic lifecycle operations 120 */ 121 .reset = ehci_init, 122 .start = ehci_run, 123 124 .stop = ehci_stop, 125 .shutdown = ehci_shutdown, 126 127 /* 128 * managing i/o requests and associated device resources 129 */ 130 .urb_enqueue = ehci_urb_enqueue, 131 .urb_dequeue = ehci_urb_dequeue, 132 .endpoint_disable = ehci_endpoint_disable, 133 134 /* 135 * scheduling support 136 */ 137 .get_frame_number = ehci_get_frame, 138 139 /* 140 * root hub support 141 */ 142 .hub_status_data = ehci_hub_status_data, 143 .hub_control = ehci_hub_control, 144#ifdef CONFIG_PM 145 .bus_suspend = ehci_bus_suspend, 146 .bus_resume = ehci_bus_resume, 147#endif 148 .relinquish_port = ehci_relinquish_port, 149 .port_handed_over = ehci_port_handed_over, 150}; 151 152static int __devinit ehci_w90x900_probe(struct platform_device *pdev) 153{ 154 if (usb_disabled()) 155 return -ENODEV; 156 157 return usb_w90x900_probe(&ehci_w90x900_hc_driver, pdev); 158} 159 160static int __devexit ehci_w90x900_remove(struct platform_device *pdev) 161{ 162 struct usb_hcd *hcd = platform_get_drvdata(pdev); 163 164 usb_w90x900_remove(hcd, pdev); 165 166 return 0; 167} 168 169static struct platform_driver ehci_hcd_w90x900_driver = { 170 .probe = ehci_w90x900_probe, 171 .remove = __devexit_p(ehci_w90x900_remove), 172 .driver = { 173 .name = "w90x900-ehci", 174 .owner = THIS_MODULE, 175 }, 176}; 177 178MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); 179MODULE_DESCRIPTION("w90p910 usb ehci driver!"); 180MODULE_LICENSE("GPL"); 181MODULE_ALIAS("platform:w90p910-ehci"); 182