1 /* 2 * Generic platform ehci driver 3 * 4 * Copyright 2007 Steven Brown <sbrown@cortland.com> 5 * Copyright 2010-2012 Hauke Mehrtens <hauke@hauke-m.de> 6 * 7 * Derived from the ohci-ssb driver 8 * Copyright 2007 Michael Buesch <m@bues.ch> 9 * 10 * Derived from the EHCI-PCI driver 11 * Copyright (c) 2000-2004 by David Brownell 12 * 13 * Derived from the ohci-pci driver 14 * Copyright 1999 Roman Weissgaerber 15 * Copyright 2000-2002 David Brownell 16 * Copyright 1999 Linus Torvalds 17 * Copyright 1999 Gregory P. Smith 18 * 19 * Licensed under the GNU/GPL. See COPYING for details. 20 */ 21 #include <linux/platform_device.h> 22 #include <linux/usb/ehci_pdriver.h> 23 24 static int ehci_platform_reset(struct usb_hcd *hcd) 25 { 26 struct platform_device *pdev = to_platform_device(hcd->self.controller); 27 struct usb_ehci_pdata *pdata = pdev->dev.platform_data; 28 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 29 int retval; 30 31 hcd->has_tt = pdata->has_tt; 32 ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug; 33 ehci->big_endian_desc = pdata->big_endian_desc; 34 ehci->big_endian_mmio = pdata->big_endian_mmio; 35 36 ehci->caps = hcd->regs + pdata->caps_offset; 37 retval = ehci_setup(hcd); 38 if (retval) 39 return retval; 40 41 if (pdata->port_power_on) 42 ehci_port_power(ehci, 1); 43 if (pdata->port_power_off) 44 ehci_port_power(ehci, 0); 45 46 return 0; 47 } 48 49 static const struct hc_driver ehci_platform_hc_driver = { 50 .description = hcd_name, 51 .product_desc = "Generic Platform EHCI Controller", 52 .hcd_priv_size = sizeof(struct ehci_hcd), 53 54 .irq = ehci_irq, 55 .flags = HCD_MEMORY | HCD_USB2, 56 57 .reset = ehci_platform_reset, 58 .start = ehci_run, 59 .stop = ehci_stop, 60 .shutdown = ehci_shutdown, 61 62 .urb_enqueue = ehci_urb_enqueue, 63 .urb_dequeue = ehci_urb_dequeue, 64 .endpoint_disable = ehci_endpoint_disable, 65 .endpoint_reset = ehci_endpoint_reset, 66 67 .get_frame_number = ehci_get_frame, 68 69 .hub_status_data = ehci_hub_status_data, 70 .hub_control = ehci_hub_control, 71 #if defined(CONFIG_PM) 72 .bus_suspend = ehci_bus_suspend, 73 .bus_resume = ehci_bus_resume, 74 #endif 75 .relinquish_port = ehci_relinquish_port, 76 .port_handed_over = ehci_port_handed_over, 77 78 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, 79 }; 80 81 static int __devinit ehci_platform_probe(struct platform_device *dev) 82 { 83 struct usb_hcd *hcd; 84 struct resource *res_mem; 85 struct usb_ehci_pdata *pdata = dev->dev.platform_data; 86 int irq; 87 int err = -ENOMEM; 88 89 if (!pdata) { 90 WARN_ON(1); 91 return -ENODEV; 92 } 93 94 if (usb_disabled()) 95 return -ENODEV; 96 97 irq = platform_get_irq(dev, 0); 98 if (irq < 0) { 99 pr_err("no irq provided"); 100 return irq; 101 } 102 res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); 103 if (!res_mem) { 104 pr_err("no memory recourse provided"); 105 return -ENXIO; 106 } 107 108 if (pdata->power_on) { 109 err = pdata->power_on(dev); 110 if (err < 0) 111 return err; 112 } 113 114 hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev, 115 dev_name(&dev->dev)); 116 if (!hcd) { 117 err = -ENOMEM; 118 goto err_power; 119 } 120 121 hcd->rsrc_start = res_mem->start; 122 hcd->rsrc_len = resource_size(res_mem); 123 124 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { 125 pr_err("controller already in use"); 126 err = -EBUSY; 127 goto err_put_hcd; 128 } 129 130 hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); 131 if (!hcd->regs) { 132 err = -ENOMEM; 133 goto err_release_region; 134 } 135 err = usb_add_hcd(hcd, irq, IRQF_SHARED); 136 if (err) 137 goto err_iounmap; 138 139 platform_set_drvdata(dev, hcd); 140 141 return err; 142 143 err_iounmap: 144 iounmap(hcd->regs); 145 err_release_region: 146 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 147 err_put_hcd: 148 usb_put_hcd(hcd); 149 err_power: 150 if (pdata->power_off) 151 pdata->power_off(dev); 152 153 return err; 154 } 155 156 static int __devexit ehci_platform_remove(struct platform_device *dev) 157 { 158 struct usb_hcd *hcd = platform_get_drvdata(dev); 159 struct usb_ehci_pdata *pdata = dev->dev.platform_data; 160 161 usb_remove_hcd(hcd); 162 iounmap(hcd->regs); 163 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 164 usb_put_hcd(hcd); 165 platform_set_drvdata(dev, NULL); 166 167 if (pdata->power_off) 168 pdata->power_off(dev); 169 170 return 0; 171 } 172 173 #ifdef CONFIG_PM 174 175 static int ehci_platform_suspend(struct device *dev) 176 { 177 struct usb_hcd *hcd = dev_get_drvdata(dev); 178 struct usb_ehci_pdata *pdata = dev->platform_data; 179 struct platform_device *pdev = 180 container_of(dev, struct platform_device, dev); 181 bool do_wakeup = device_may_wakeup(dev); 182 int ret; 183 184 ret = ehci_suspend(hcd, do_wakeup); 185 186 if (pdata->power_suspend) 187 pdata->power_suspend(pdev); 188 189 return ret; 190 } 191 192 static int ehci_platform_resume(struct device *dev) 193 { 194 struct usb_hcd *hcd = dev_get_drvdata(dev); 195 struct usb_ehci_pdata *pdata = dev->platform_data; 196 struct platform_device *pdev = 197 container_of(dev, struct platform_device, dev); 198 199 if (pdata->power_on) { 200 int err = pdata->power_on(pdev); 201 if (err < 0) 202 return err; 203 } 204 205 ehci_resume(hcd, false); 206 return 0; 207 } 208 209 #else /* !CONFIG_PM */ 210 #define ehci_platform_suspend NULL 211 #define ehci_platform_resume NULL 212 #endif /* CONFIG_PM */ 213 214 static const struct platform_device_id ehci_platform_table[] = { 215 { "ehci-platform", 0 }, 216 { } 217 }; 218 MODULE_DEVICE_TABLE(platform, ehci_platform_table); 219 220 static const struct dev_pm_ops ehci_platform_pm_ops = { 221 .suspend = ehci_platform_suspend, 222 .resume = ehci_platform_resume, 223 }; 224 225 static struct platform_driver ehci_platform_driver = { 226 .id_table = ehci_platform_table, 227 .probe = ehci_platform_probe, 228 .remove = __devexit_p(ehci_platform_remove), 229 .shutdown = usb_hcd_platform_shutdown, 230 .driver = { 231 .owner = THIS_MODULE, 232 .name = "ehci-platform", 233 .pm = &ehci_platform_pm_ops, 234 } 235 }; 236