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 int irq; 86 int err = -ENOMEM; 87 88 BUG_ON(!dev->dev.platform_data); 89 90 if (usb_disabled()) 91 return -ENODEV; 92 93 irq = platform_get_irq(dev, 0); 94 if (irq < 0) { 95 pr_err("no irq provided"); 96 return irq; 97 } 98 res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); 99 if (!res_mem) { 100 pr_err("no memory recourse provided"); 101 return -ENXIO; 102 } 103 104 hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev, 105 dev_name(&dev->dev)); 106 if (!hcd) 107 return -ENOMEM; 108 109 hcd->rsrc_start = res_mem->start; 110 hcd->rsrc_len = resource_size(res_mem); 111 112 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { 113 pr_err("controller already in use"); 114 err = -EBUSY; 115 goto err_put_hcd; 116 } 117 118 hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); 119 if (!hcd->regs) 120 goto err_release_region; 121 err = usb_add_hcd(hcd, irq, IRQF_SHARED); 122 if (err) 123 goto err_iounmap; 124 125 platform_set_drvdata(dev, hcd); 126 127 return err; 128 129 err_iounmap: 130 iounmap(hcd->regs); 131 err_release_region: 132 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 133 err_put_hcd: 134 usb_put_hcd(hcd); 135 return err; 136 } 137 138 static int __devexit ehci_platform_remove(struct platform_device *dev) 139 { 140 struct usb_hcd *hcd = platform_get_drvdata(dev); 141 142 usb_remove_hcd(hcd); 143 iounmap(hcd->regs); 144 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 145 usb_put_hcd(hcd); 146 platform_set_drvdata(dev, NULL); 147 148 return 0; 149 } 150 151 #ifdef CONFIG_PM 152 153 static int ehci_platform_suspend(struct device *dev) 154 { 155 struct usb_hcd *hcd = dev_get_drvdata(dev); 156 bool do_wakeup = device_may_wakeup(dev); 157 158 return ehci_suspend(hcd, do_wakeup); 159 } 160 161 static int ehci_platform_resume(struct device *dev) 162 { 163 struct usb_hcd *hcd = dev_get_drvdata(dev); 164 165 ehci_resume(hcd, false); 166 return 0; 167 } 168 169 #else /* !CONFIG_PM */ 170 #define ehci_platform_suspend NULL 171 #define ehci_platform_resume NULL 172 #endif /* CONFIG_PM */ 173 174 static const struct platform_device_id ehci_platform_table[] = { 175 { "ehci-platform", 0 }, 176 { } 177 }; 178 MODULE_DEVICE_TABLE(platform, ehci_platform_table); 179 180 static const struct dev_pm_ops ehci_platform_pm_ops = { 181 .suspend = ehci_platform_suspend, 182 .resume = ehci_platform_resume, 183 }; 184 185 static struct platform_driver ehci_platform_driver = { 186 .id_table = ehci_platform_table, 187 .probe = ehci_platform_probe, 188 .remove = __devexit_p(ehci_platform_remove), 189 .shutdown = usb_hcd_platform_shutdown, 190 .driver = { 191 .owner = THIS_MODULE, 192 .name = "ehci-platform", 193 .pm = &ehci_platform_pm_ops, 194 } 195 }; 196