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 struct usb_ohci_pdata *pdata = dev->dev.platform_data; 87 int irq; 88 int err = -ENOMEM; 89 90 if (!pdata) { 91 WARN_ON(1); 92 return -ENODEV; 93 } 94 95 if (usb_disabled()) 96 return -ENODEV; 97 98 irq = platform_get_irq(dev, 0); 99 if (irq < 0) { 100 pr_err("no irq provided"); 101 return irq; 102 } 103 104 res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); 105 if (!res_mem) { 106 pr_err("no memory recourse provided"); 107 return -ENXIO; 108 } 109 110 if (pdata->power_on) { 111 err = pdata->power_on(dev); 112 if (err < 0) 113 return err; 114 } 115 116 hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev, 117 dev_name(&dev->dev)); 118 if (!hcd) { 119 err = -ENOMEM; 120 goto err_power; 121 } 122 123 hcd->rsrc_start = res_mem->start; 124 hcd->rsrc_len = resource_size(res_mem); 125 126 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { 127 pr_err("controller already in use"); 128 err = -EBUSY; 129 goto err_put_hcd; 130 } 131 132 hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); 133 if (!hcd->regs) { 134 err = -ENOMEM; 135 goto err_release_region; 136 } 137 err = usb_add_hcd(hcd, irq, IRQF_SHARED); 138 if (err) 139 goto err_iounmap; 140 141 platform_set_drvdata(dev, hcd); 142 143 return err; 144 145 err_iounmap: 146 iounmap(hcd->regs); 147 err_release_region: 148 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 149 err_put_hcd: 150 usb_put_hcd(hcd); 151 err_power: 152 if (pdata->power_off) 153 pdata->power_off(dev); 154 155 return err; 156 } 157 158 static int __devexit ohci_platform_remove(struct platform_device *dev) 159 { 160 struct usb_hcd *hcd = platform_get_drvdata(dev); 161 struct usb_ohci_pdata *pdata = dev->dev.platform_data; 162 163 usb_remove_hcd(hcd); 164 iounmap(hcd->regs); 165 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 166 usb_put_hcd(hcd); 167 platform_set_drvdata(dev, NULL); 168 169 if (pdata->power_off) 170 pdata->power_off(dev); 171 172 return 0; 173 } 174 175 #ifdef CONFIG_PM 176 177 static int ohci_platform_suspend(struct device *dev) 178 { 179 struct usb_ohci_pdata *pdata = dev->platform_data; 180 struct platform_device *pdev = 181 container_of(dev, struct platform_device, dev); 182 183 if (pdata->power_suspend) 184 pdata->power_suspend(pdev); 185 186 return 0; 187 } 188 189 static int ohci_platform_resume(struct device *dev) 190 { 191 struct usb_hcd *hcd = dev_get_drvdata(dev); 192 struct usb_ohci_pdata *pdata = dev->platform_data; 193 struct platform_device *pdev = 194 container_of(dev, struct platform_device, dev); 195 196 if (pdata->power_on) { 197 int err = pdata->power_on(pdev); 198 if (err < 0) 199 return err; 200 } 201 202 ohci_finish_controller_resume(hcd); 203 return 0; 204 } 205 206 #else /* !CONFIG_PM */ 207 #define ohci_platform_suspend NULL 208 #define ohci_platform_resume NULL 209 #endif /* CONFIG_PM */ 210 211 static const struct platform_device_id ohci_platform_table[] = { 212 { "ohci-platform", 0 }, 213 { } 214 }; 215 MODULE_DEVICE_TABLE(platform, ohci_platform_table); 216 217 static const struct dev_pm_ops ohci_platform_pm_ops = { 218 .suspend = ohci_platform_suspend, 219 .resume = ohci_platform_resume, 220 }; 221 222 static struct platform_driver ohci_platform_driver = { 223 .id_table = ohci_platform_table, 224 .probe = ohci_platform_probe, 225 .remove = __devexit_p(ohci_platform_remove), 226 .shutdown = usb_hcd_platform_shutdown, 227 .driver = { 228 .owner = THIS_MODULE, 229 .name = "ohci-platform", 230 .pm = &ohci_platform_pm_ops, 231 } 232 }; 233