1/* 2 * OHCI HCD for Netlogic XLS processors. 3 * 4 * (C) Copyright 2011 Netlogic Microsystems Inc. 5 * 6 * Based on ohci-au1xxx.c, and other Linux OHCI drivers. 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file COPYING in the main directory of this archive for 10 * more details. 11 */ 12 13#include <linux/platform_device.h> 14#include <linux/signal.h> 15 16static int ohci_xls_probe_internal(const struct hc_driver *driver, 17 struct platform_device *dev) 18{ 19 struct resource *res; 20 struct usb_hcd *hcd; 21 int retval, irq; 22 23 /* Get our IRQ from an earlier registered Platform Resource */ 24 irq = platform_get_irq(dev, 0); 25 if (irq < 0) { 26 dev_err(&dev->dev, "Found HC with no IRQ\n"); 27 return -ENODEV; 28 } 29 30 /* Get our Memory Handle */ 31 res = platform_get_resource(dev, IORESOURCE_MEM, 0); 32 if (!res) { 33 dev_err(&dev->dev, "MMIO Handle incorrect!\n"); 34 return -ENODEV; 35 } 36 37 hcd = usb_create_hcd(driver, &dev->dev, "XLS"); 38 if (!hcd) { 39 retval = -ENOMEM; 40 goto err1; 41 } 42 hcd->rsrc_start = res->start; 43 hcd->rsrc_len = resource_size(res); 44 45 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, 46 driver->description)) { 47 dev_dbg(&dev->dev, "Controller already in use\n"); 48 retval = -EBUSY; 49 goto err2; 50 } 51 52 hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); 53 if (hcd->regs == NULL) { 54 dev_dbg(&dev->dev, "error mapping memory\n"); 55 retval = -EFAULT; 56 goto err3; 57 } 58 59 retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); 60 if (retval != 0) 61 goto err4; 62 return retval; 63 64err4: 65 iounmap(hcd->regs); 66err3: 67 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 68err2: 69 usb_put_hcd(hcd); 70err1: 71 dev_err(&dev->dev, "init fail, %d\n", retval); 72 return retval; 73} 74 75static int ohci_xls_reset(struct usb_hcd *hcd) 76{ 77 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 78 79 ohci_hcd_init(ohci); 80 return ohci_init(ohci); 81} 82 83static int __devinit ohci_xls_start(struct usb_hcd *hcd) 84{ 85 struct ohci_hcd *ohci; 86 int ret; 87 88 ohci = hcd_to_ohci(hcd); 89 ret = ohci_run(ohci); 90 if (ret < 0) { 91 err("can't start %s", hcd->self.bus_name); 92 ohci_stop(hcd); 93 return ret; 94 } 95 return 0; 96} 97 98static struct hc_driver ohci_xls_hc_driver = { 99 .description = hcd_name, 100 .product_desc = "XLS OHCI Host Controller", 101 .hcd_priv_size = sizeof(struct ohci_hcd), 102 .irq = ohci_irq, 103 .flags = HCD_MEMORY | HCD_USB11, 104 .reset = ohci_xls_reset, 105 .start = ohci_xls_start, 106 .stop = ohci_stop, 107 .shutdown = ohci_shutdown, 108 .urb_enqueue = ohci_urb_enqueue, 109 .urb_dequeue = ohci_urb_dequeue, 110 .endpoint_disable = ohci_endpoint_disable, 111 .get_frame_number = ohci_get_frame, 112 .hub_status_data = ohci_hub_status_data, 113 .hub_control = ohci_hub_control, 114#ifdef CONFIG_PM 115 .bus_suspend = ohci_bus_suspend, 116 .bus_resume = ohci_bus_resume, 117#endif 118 .start_port_reset = ohci_start_port_reset, 119}; 120 121static int ohci_xls_probe(struct platform_device *dev) 122{ 123 int ret; 124 125 pr_debug("In ohci_xls_probe"); 126 if (usb_disabled()) 127 return -ENODEV; 128 ret = ohci_xls_probe_internal(&ohci_xls_hc_driver, dev); 129 return ret; 130} 131 132static int ohci_xls_remove(struct platform_device *dev) 133{ 134 struct usb_hcd *hcd = platform_get_drvdata(dev); 135 136 usb_remove_hcd(hcd); 137 iounmap(hcd->regs); 138 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 139 usb_put_hcd(hcd); 140 return 0; 141} 142 143static struct platform_driver ohci_xls_driver = { 144 .probe = ohci_xls_probe, 145 .remove = ohci_xls_remove, 146 .shutdown = usb_hcd_platform_shutdown, 147 .driver = { 148 .name = "ohci-xls-0", 149 .owner = THIS_MODULE, 150 }, 151}; 152