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 35 if (pdata->num_ports) 36 ohci->num_ports = pdata->num_ports; 37 38 err = ohci_init(ohci); 39 40 return err; 41 } 42 43 static int ohci_platform_start(struct usb_hcd *hcd) 44 { 45 struct ohci_hcd *ohci = hcd_to_ohci(hcd); 46 int err; 47 48 err = ohci_run(ohci); 49 if (err < 0) { 50 ohci_err(ohci, "can't start\n"); 51 ohci_stop(hcd); 52 } 53 54 return err; 55 } 56 57 static const struct hc_driver ohci_platform_hc_driver = { 58 .description = hcd_name, 59 .product_desc = "Generic Platform OHCI Controller", 60 .hcd_priv_size = sizeof(struct ohci_hcd), 61 62 .irq = ohci_irq, 63 .flags = HCD_MEMORY | HCD_USB11, 64 65 .reset = ohci_platform_reset, 66 .start = ohci_platform_start, 67 .stop = ohci_stop, 68 .shutdown = ohci_shutdown, 69 70 .urb_enqueue = ohci_urb_enqueue, 71 .urb_dequeue = ohci_urb_dequeue, 72 .endpoint_disable = ohci_endpoint_disable, 73 74 .get_frame_number = ohci_get_frame, 75 76 .hub_status_data = ohci_hub_status_data, 77 .hub_control = ohci_hub_control, 78 #ifdef CONFIG_PM 79 .bus_suspend = ohci_bus_suspend, 80 .bus_resume = ohci_bus_resume, 81 #endif 82 83 .start_port_reset = ohci_start_port_reset, 84 }; 85 86 static int ohci_platform_probe(struct platform_device *dev) 87 { 88 struct usb_hcd *hcd; 89 struct resource *res_mem; 90 struct usb_ohci_pdata *pdata = dev->dev.platform_data; 91 int irq; 92 int err = -ENOMEM; 93 94 if (!pdata) { 95 WARN_ON(1); 96 return -ENODEV; 97 } 98 99 if (usb_disabled()) 100 return -ENODEV; 101 102 irq = platform_get_irq(dev, 0); 103 if (irq < 0) { 104 dev_err(&dev->dev, "no irq provided"); 105 return irq; 106 } 107 108 res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); 109 if (!res_mem) { 110 dev_err(&dev->dev, "no memory resource provided"); 111 return -ENXIO; 112 } 113 114 if (pdata->power_on) { 115 err = pdata->power_on(dev); 116 if (err < 0) 117 return err; 118 } 119 120 hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev, 121 dev_name(&dev->dev)); 122 if (!hcd) { 123 err = -ENOMEM; 124 goto err_power; 125 } 126 127 hcd->rsrc_start = res_mem->start; 128 hcd->rsrc_len = resource_size(res_mem); 129 130 hcd->regs = devm_request_and_ioremap(&dev->dev, res_mem); 131 if (!hcd->regs) { 132 err = -ENOMEM; 133 goto err_put_hcd; 134 } 135 err = usb_add_hcd(hcd, irq, IRQF_SHARED); 136 if (err) 137 goto err_put_hcd; 138 139 platform_set_drvdata(dev, hcd); 140 141 return err; 142 143 err_put_hcd: 144 usb_put_hcd(hcd); 145 err_power: 146 if (pdata->power_off) 147 pdata->power_off(dev); 148 149 return err; 150 } 151 152 static int ohci_platform_remove(struct platform_device *dev) 153 { 154 struct usb_hcd *hcd = platform_get_drvdata(dev); 155 struct usb_ohci_pdata *pdata = dev->dev.platform_data; 156 157 usb_remove_hcd(hcd); 158 usb_put_hcd(hcd); 159 platform_set_drvdata(dev, NULL); 160 161 if (pdata->power_off) 162 pdata->power_off(dev); 163 164 return 0; 165 } 166 167 #ifdef CONFIG_PM 168 169 static int ohci_platform_suspend(struct device *dev) 170 { 171 struct usb_ohci_pdata *pdata = dev->platform_data; 172 struct platform_device *pdev = 173 container_of(dev, struct platform_device, dev); 174 175 if (pdata->power_suspend) 176 pdata->power_suspend(pdev); 177 178 return 0; 179 } 180 181 static int ohci_platform_resume(struct device *dev) 182 { 183 struct usb_hcd *hcd = dev_get_drvdata(dev); 184 struct usb_ohci_pdata *pdata = dev->platform_data; 185 struct platform_device *pdev = 186 container_of(dev, struct platform_device, dev); 187 188 if (pdata->power_on) { 189 int err = pdata->power_on(pdev); 190 if (err < 0) 191 return err; 192 } 193 194 ohci_resume(hcd, false); 195 return 0; 196 } 197 198 #else /* !CONFIG_PM */ 199 #define ohci_platform_suspend NULL 200 #define ohci_platform_resume NULL 201 #endif /* CONFIG_PM */ 202 203 static const struct platform_device_id ohci_platform_table[] = { 204 { "ohci-platform", 0 }, 205 { } 206 }; 207 MODULE_DEVICE_TABLE(platform, ohci_platform_table); 208 209 static const struct dev_pm_ops ohci_platform_pm_ops = { 210 .suspend = ohci_platform_suspend, 211 .resume = ohci_platform_resume, 212 }; 213 214 static struct platform_driver ohci_platform_driver = { 215 .id_table = ohci_platform_table, 216 .probe = ohci_platform_probe, 217 .remove = ohci_platform_remove, 218 .shutdown = usb_hcd_platform_shutdown, 219 .driver = { 220 .owner = THIS_MODULE, 221 .name = "ohci-platform", 222 .pm = &ohci_platform_pm_ops, 223 } 224 }; 225