Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.10 217 lines 5.1 kB view raw
1/* 2 * OHCI HCD (Host Controller Driver) for USB. 3 * 4 * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> 5 * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> 6 * (C) Copyright 2002 Hewlett-Packard Company 7 * 8 * Bus Glue for ep93xx. 9 * 10 * Written by Christopher Hoover <ch@hpl.hp.com> 11 * Based on fragments of previous driver by Russell King et al. 12 * 13 * Modified for LH7A404 from ohci-sa1111.c 14 * by Durgesh Pattamatta <pattamattad@sharpsec.com> 15 * 16 * Modified for pxa27x from ohci-lh7a404.c 17 * by Nick Bane <nick@cecomputing.co.uk> 26-8-2004 18 * 19 * Modified for ep93xx from ohci-pxa27x.c 20 * by Lennert Buytenhek <buytenh@wantstofly.org> 28-2-2006 21 * Based on an earlier driver by Ray Lehtiniemi 22 * 23 * This file is licenced under the GPL. 24 */ 25 26#include <linux/clk.h> 27#include <linux/device.h> 28#include <linux/signal.h> 29#include <linux/platform_device.h> 30 31static struct clk *usb_host_clock; 32 33static void ep93xx_start_hc(struct device *dev) 34{ 35 clk_enable(usb_host_clock); 36} 37 38static void ep93xx_stop_hc(struct device *dev) 39{ 40 clk_disable(usb_host_clock); 41} 42 43static int usb_hcd_ep93xx_probe(const struct hc_driver *driver, 44 struct platform_device *pdev) 45{ 46 int retval; 47 struct usb_hcd *hcd; 48 49 if (pdev->resource[1].flags != IORESOURCE_IRQ) { 50 dev_dbg(&pdev->dev, "resource[1] is not IORESOURCE_IRQ\n"); 51 return -ENOMEM; 52 } 53 54 hcd = usb_create_hcd(driver, &pdev->dev, "ep93xx"); 55 if (hcd == NULL) 56 return -ENOMEM; 57 58 hcd->rsrc_start = pdev->resource[0].start; 59 hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1; 60 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { 61 usb_put_hcd(hcd); 62 retval = -EBUSY; 63 goto err1; 64 } 65 66 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); 67 if (hcd->regs == NULL) { 68 dev_dbg(&pdev->dev, "ioremap failed\n"); 69 retval = -ENOMEM; 70 goto err2; 71 } 72 73 usb_host_clock = clk_get(&pdev->dev, NULL); 74 if (IS_ERR(usb_host_clock)) { 75 dev_dbg(&pdev->dev, "clk_get failed\n"); 76 retval = PTR_ERR(usb_host_clock); 77 goto err3; 78 } 79 80 ep93xx_start_hc(&pdev->dev); 81 82 ohci_hcd_init(hcd_to_ohci(hcd)); 83 84 retval = usb_add_hcd(hcd, pdev->resource[1].start, 0); 85 if (retval == 0) 86 return retval; 87 88 ep93xx_stop_hc(&pdev->dev); 89err3: 90 iounmap(hcd->regs); 91err2: 92 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 93err1: 94 usb_put_hcd(hcd); 95 96 return retval; 97} 98 99static void usb_hcd_ep93xx_remove(struct usb_hcd *hcd, 100 struct platform_device *pdev) 101{ 102 usb_remove_hcd(hcd); 103 ep93xx_stop_hc(&pdev->dev); 104 clk_put(usb_host_clock); 105 iounmap(hcd->regs); 106 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 107 usb_put_hcd(hcd); 108} 109 110static int ohci_ep93xx_start(struct usb_hcd *hcd) 111{ 112 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 113 int ret; 114 115 if ((ret = ohci_init(ohci)) < 0) 116 return ret; 117 118 if ((ret = ohci_run(ohci)) < 0) { 119 dev_err(hcd->self.controller, "can't start %s\n", 120 hcd->self.bus_name); 121 ohci_stop(hcd); 122 return ret; 123 } 124 125 return 0; 126} 127 128static struct hc_driver ohci_ep93xx_hc_driver = { 129 .description = hcd_name, 130 .product_desc = "EP93xx OHCI", 131 .hcd_priv_size = sizeof(struct ohci_hcd), 132 .irq = ohci_irq, 133 .flags = HCD_USB11 | HCD_MEMORY, 134 .start = ohci_ep93xx_start, 135 .stop = ohci_stop, 136 .shutdown = ohci_shutdown, 137 .urb_enqueue = ohci_urb_enqueue, 138 .urb_dequeue = ohci_urb_dequeue, 139 .endpoint_disable = ohci_endpoint_disable, 140 .get_frame_number = ohci_get_frame, 141 .hub_status_data = ohci_hub_status_data, 142 .hub_control = ohci_hub_control, 143#ifdef CONFIG_PM 144 .bus_suspend = ohci_bus_suspend, 145 .bus_resume = ohci_bus_resume, 146#endif 147 .start_port_reset = ohci_start_port_reset, 148}; 149 150extern int usb_disabled(void); 151 152static int ohci_hcd_ep93xx_drv_probe(struct platform_device *pdev) 153{ 154 int ret; 155 156 ret = -ENODEV; 157 if (!usb_disabled()) 158 ret = usb_hcd_ep93xx_probe(&ohci_ep93xx_hc_driver, pdev); 159 160 return ret; 161} 162 163static int ohci_hcd_ep93xx_drv_remove(struct platform_device *pdev) 164{ 165 struct usb_hcd *hcd = platform_get_drvdata(pdev); 166 167 usb_hcd_ep93xx_remove(hcd, pdev); 168 169 return 0; 170} 171 172#ifdef CONFIG_PM 173static int ohci_hcd_ep93xx_drv_suspend(struct platform_device *pdev, pm_message_t state) 174{ 175 struct usb_hcd *hcd = platform_get_drvdata(pdev); 176 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 177 178 if (time_before(jiffies, ohci->next_statechange)) 179 msleep(5); 180 ohci->next_statechange = jiffies; 181 182 ep93xx_stop_hc(&pdev->dev); 183 return 0; 184} 185 186static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev) 187{ 188 struct usb_hcd *hcd = platform_get_drvdata(pdev); 189 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 190 191 if (time_before(jiffies, ohci->next_statechange)) 192 msleep(5); 193 ohci->next_statechange = jiffies; 194 195 ep93xx_start_hc(&pdev->dev); 196 197 ohci_resume(hcd, false); 198 return 0; 199} 200#endif 201 202 203static struct platform_driver ohci_hcd_ep93xx_driver = { 204 .probe = ohci_hcd_ep93xx_drv_probe, 205 .remove = ohci_hcd_ep93xx_drv_remove, 206 .shutdown = usb_hcd_platform_shutdown, 207#ifdef CONFIG_PM 208 .suspend = ohci_hcd_ep93xx_drv_suspend, 209 .resume = ohci_hcd_ep93xx_drv_resume, 210#endif 211 .driver = { 212 .name = "ep93xx-ohci", 213 .owner = THIS_MODULE, 214 }, 215}; 216 217MODULE_ALIAS("platform:ep93xx-ohci");