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 .update_device = ehci_update_device, 79 80 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, 81 }; 82 83 static int __devinit ehci_platform_probe(struct platform_device *dev) 84 { 85 struct usb_hcd *hcd; 86 struct resource *res_mem; 87 int irq; 88 int err = -ENOMEM; 89 90 BUG_ON(!dev->dev.platform_data); 91 92 if (usb_disabled()) 93 return -ENODEV; 94 95 irq = platform_get_irq(dev, 0); 96 if (irq < 0) { 97 pr_err("no irq provieded"); 98 return irq; 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(&ehci_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 ehci_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 ehci_platform_suspend(struct device *dev) 156 { 157 struct usb_hcd *hcd = dev_get_drvdata(dev); 158 bool wakeup = device_may_wakeup(dev); 159 160 ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), wakeup); 161 return 0; 162 } 163 164 static int ehci_platform_resume(struct device *dev) 165 { 166 struct usb_hcd *hcd = dev_get_drvdata(dev); 167 168 ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd)); 169 return 0; 170 } 171 172 #else /* !CONFIG_PM */ 173 #define ehci_platform_suspend NULL 174 #define ehci_platform_resume NULL 175 #endif /* CONFIG_PM */ 176 177 static const struct platform_device_id ehci_platform_table[] = { 178 { "ehci-platform", 0 }, 179 { } 180 }; 181 MODULE_DEVICE_TABLE(platform, ehci_platform_table); 182 183 static const struct dev_pm_ops ehci_platform_pm_ops = { 184 .suspend = ehci_platform_suspend, 185 .resume = ehci_platform_resume, 186 }; 187 188 static struct platform_driver ehci_platform_driver = { 189 .id_table = ehci_platform_table, 190 .probe = ehci_platform_probe, 191 .remove = __devexit_p(ehci_platform_remove), 192 .shutdown = usb_hcd_platform_shutdown, 193 .driver = { 194 .owner = THIS_MODULE, 195 .name = "ehci-platform", 196 .pm = &ehci_platform_pm_ops, 197 } 198 }; 199