1 /* 2 * Generic platform ohci driver 3 * 4 * Copyright 2007 Michael Buesch <m@bues.ch> 5 * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de> 6 * 7 * Derived from the OCHI-SSB driver 8 * Derived from the OHCI-PCI driver 9 * Copyright 1999 Roman Weissgaerber 10 * Copyright 2000-2002 David Brownell 11 * Copyright 1999 Linus Torvalds 12 * Copyright 1999 Gregory P. Smith 13 * 14 * Licensed under the GNU/GPL. See COPYING for details. 15 */ 16 #include <linux/platform_device.h> 17 #include <linux/usb/ohci_pdriver.h> 18 19 static int ohci_platform_reset(struct usb_hcd *hcd) 20 { 21 struct platform_device *pdev = to_platform_device(hcd->self.controller); 22 struct usb_ohci_pdata *pdata = pdev->dev.platform_data; 23 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 24 int err; 25 26 if (pdata->big_endian_desc) 27 ohci->flags |= OHCI_QUIRK_BE_DESC; 28 if (pdata->big_endian_mmio) 29 ohci->flags |= OHCI_QUIRK_BE_MMIO; 30 if (pdata->no_big_frame_no) 31 ohci->flags |= OHCI_QUIRK_FRAME_NO; 32 33 ohci_hcd_init(ohci); 34 err = ohci_init(ohci); 35 36 return err; 37 } 38 39 static int ohci_platform_start(struct usb_hcd *hcd) 40 { 41 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 42 int err; 43 44 err = ohci_run(ohci); 45 if (err < 0) { 46 ohci_err(ohci, "can't start\n"); 47 ohci_stop(hcd); 48 } 49 50 return err; 51 } 52 53 static const struct hc_driver ohci_platform_hc_driver = { 54 .description = hcd_name, 55 .product_desc = "Generic Platform OHCI Controller", 56 .hcd_priv_size = sizeof(struct ohci_hcd), 57 58 .irq = ohci_irq, 59 .flags = HCD_MEMORY | HCD_USB11, 60 61 .reset = ohci_platform_reset, 62 .start = ohci_platform_start, 63 .stop = ohci_stop, 64 .shutdown = ohci_shutdown, 65 66 .urb_enqueue = ohci_urb_enqueue, 67 .urb_dequeue = ohci_urb_dequeue, 68 .endpoint_disable = ohci_endpoint_disable, 69 70 .get_frame_number = ohci_get_frame, 71 72 .hub_status_data = ohci_hub_status_data, 73 .hub_control = ohci_hub_control, 74 #ifdef CONFIG_PM 75 .bus_suspend = ohci_bus_suspend, 76 .bus_resume = ohci_bus_resume, 77 #endif 78 79 .start_port_reset = ohci_start_port_reset, 80 }; 81 82 static int __devinit ohci_platform_probe(struct platform_device *dev) 83 { 84 struct usb_hcd *hcd; 85 struct resource *res_mem; 86 int irq; 87 int err = -ENOMEM; 88 89 BUG_ON(!dev->dev.platform_data); 90 91 if (usb_disabled()) 92 return -ENODEV; 93 94 irq = platform_get_irq(dev, 0); 95 if (irq < 0) { 96 pr_err("no irq provieded"); 97 return irq; 98 } 99 100 res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); 101 if (!res_mem) { 102 pr_err("no memory recourse provieded"); 103 return -ENXIO; 104 } 105 106 hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev, 107 dev_name(&dev->dev)); 108 if (!hcd) 109 return -ENOMEM; 110 111 hcd->rsrc_start = res_mem->start; 112 hcd->rsrc_len = resource_size(res_mem); 113 114 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { 115 pr_err("controller already in use"); 116 err = -EBUSY; 117 goto err_put_hcd; 118 } 119 120 hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); 121 if (!hcd->regs) 122 goto err_release_region; 123 err = usb_add_hcd(hcd, irq, IRQF_SHARED); 124 if (err) 125 goto err_iounmap; 126 127 platform_set_drvdata(dev, hcd); 128 129 return err; 130 131 err_iounmap: 132 iounmap(hcd->regs); 133 err_release_region: 134 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 135 err_put_hcd: 136 usb_put_hcd(hcd); 137 return err; 138 } 139 140 static int __devexit ohci_platform_remove(struct platform_device *dev) 141 { 142 struct usb_hcd *hcd = platform_get_drvdata(dev); 143 144 usb_remove_hcd(hcd); 145 iounmap(hcd->regs); 146 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 147 usb_put_hcd(hcd); 148 platform_set_drvdata(dev, NULL); 149 150 return 0; 151 } 152 153 #ifdef CONFIG_PM 154 155 static int ohci_platform_suspend(struct device *dev) 156 { 157 return 0; 158 } 159 160 static int ohci_platform_resume(struct device *dev) 161 { 162 struct usb_hcd *hcd = dev_get_drvdata(dev); 163 164 ohci_finish_controller_resume(hcd); 165 return 0; 166 } 167 168 #else /* !CONFIG_PM */ 169 #define ohci_platform_suspend NULL 170 #define ohci_platform_resume NULL 171 #endif /* CONFIG_PM */ 172 173 static const struct platform_device_id ohci_platform_table[] = { 174 { "ohci-platform", 0 }, 175 { } 176 }; 177 MODULE_DEVICE_TABLE(platform, ohci_platform_table); 178 179 static const struct dev_pm_ops ohci_platform_pm_ops = { 180 .suspend = ohci_platform_suspend, 181 .resume = ohci_platform_resume, 182 }; 183 184 static struct platform_driver ohci_platform_driver = { 185 .id_table = ohci_platform_table, 186 .probe = ohci_platform_probe, 187 .remove = __devexit_p(ohci_platform_remove), 188 .shutdown = usb_hcd_platform_shutdown, 189 .driver = { 190 .owner = THIS_MODULE, 191 .name = "ohci-platform", 192 .pm = &ohci_platform_pm_ops, 193 } 194 }; 195