Branch data Line data Source code
1 : : /*
2 : : * Glue code for the ISP1760 driver and bus
3 : : * Currently there is support for
4 : : * - OpenFirmware
5 : : * - PCI
6 : : * - PDEV (generic platform device centralized driver model)
7 : : *
8 : : * (c) 2007 Sebastian Siewior <bigeasy@linutronix.de>
9 : : *
10 : : */
11 : :
12 : : #include <linux/usb.h>
13 : : #include <linux/io.h>
14 : : #include <linux/module.h>
15 : : #include <linux/platform_device.h>
16 : : #include <linux/usb/isp1760.h>
17 : : #include <linux/usb/hcd.h>
18 : :
19 : : #include "isp1760-hcd.h"
20 : :
21 : : #if defined(CONFIG_OF) && defined(CONFIG_OF_IRQ)
22 : : #include <linux/slab.h>
23 : : #include <linux/of.h>
24 : : #include <linux/of_platform.h>
25 : : #include <linux/of_address.h>
26 : : #include <linux/of_irq.h>
27 : : #include <linux/of_gpio.h>
28 : : #endif
29 : :
30 : : #ifdef CONFIG_PCI
31 : : #include <linux/pci.h>
32 : : #endif
33 : :
34 : : #if defined(CONFIG_OF) && defined(CONFIG_OF_IRQ)
35 : : struct isp1760 {
36 : : struct usb_hcd *hcd;
37 : : int rst_gpio;
38 : : };
39 : :
40 : 0 : static int of_isp1760_probe(struct platform_device *dev)
41 : : {
42 : : struct isp1760 *drvdata;
43 : 0 : struct device_node *dp = dev->dev.of_node;
44 : : struct resource *res;
45 : : struct resource memory;
46 : : int virq;
47 : : resource_size_t res_len;
48 : : int ret;
49 : : unsigned int devflags = 0;
50 : : enum of_gpio_flags gpio_flags;
51 : 0 : u32 bus_width = 0;
52 : :
53 : : drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
54 [ # # ]: 0 : if (!drvdata)
55 : : return -ENOMEM;
56 : :
57 : 0 : ret = of_address_to_resource(dp, 0, &memory);
58 [ # # ]: 0 : if (ret) {
59 : : ret = -ENXIO;
60 : : goto free_data;
61 : : }
62 : :
63 : 0 : res_len = resource_size(&memory);
64 : :
65 : 0 : res = request_mem_region(memory.start, res_len, dev_name(&dev->dev));
66 [ # # ]: 0 : if (!res) {
67 : : ret = -EBUSY;
68 : : goto free_data;
69 : : }
70 : :
71 : 0 : virq = irq_of_parse_and_map(dp, 0);
72 [ # # ]: 0 : if (!virq) {
73 : : ret = -ENODEV;
74 : : goto release_reg;
75 : : }
76 : :
77 [ # # ]: 0 : if (of_device_is_compatible(dp, "nxp,usb-isp1761"))
78 : : devflags |= ISP1760_FLAG_ISP1761;
79 : :
80 : : /* Some systems wire up only 16 of the 32 data lines */
81 : : of_property_read_u32(dp, "bus-width", &bus_width);
82 [ # # ]: 0 : if (bus_width == 16)
83 : 0 : devflags |= ISP1760_FLAG_BUS_WIDTH_16;
84 : :
85 [ # # ]: 0 : if (of_get_property(dp, "port1-otg", NULL) != NULL)
86 : 0 : devflags |= ISP1760_FLAG_OTG_EN;
87 : :
88 [ # # ]: 0 : if (of_get_property(dp, "analog-oc", NULL) != NULL)
89 : 0 : devflags |= ISP1760_FLAG_ANALOG_OC;
90 : :
91 [ # # ]: 0 : if (of_get_property(dp, "dack-polarity", NULL) != NULL)
92 : 0 : devflags |= ISP1760_FLAG_DACK_POL_HIGH;
93 : :
94 [ # # ]: 0 : if (of_get_property(dp, "dreq-polarity", NULL) != NULL)
95 : 0 : devflags |= ISP1760_FLAG_DREQ_POL_HIGH;
96 : :
97 : 0 : drvdata->rst_gpio = of_get_gpio_flags(dp, 0, &gpio_flags);
98 [ # # ]: 0 : if (gpio_is_valid(drvdata->rst_gpio)) {
99 : 0 : ret = gpio_request(drvdata->rst_gpio, dev_name(&dev->dev));
100 [ # # ]: 0 : if (!ret) {
101 [ # # ]: 0 : if (!(gpio_flags & OF_GPIO_ACTIVE_LOW)) {
102 : 0 : devflags |= ISP1760_FLAG_RESET_ACTIVE_HIGH;
103 : 0 : gpio_direction_output(drvdata->rst_gpio, 0);
104 : : } else {
105 : 0 : gpio_direction_output(drvdata->rst_gpio, 1);
106 : : }
107 : : } else {
108 : 0 : drvdata->rst_gpio = ret;
109 : : }
110 : : }
111 : :
112 : 0 : drvdata->hcd = isp1760_register(memory.start, res_len, virq,
113 : : IRQF_SHARED, drvdata->rst_gpio,
114 : 0 : &dev->dev, dev_name(&dev->dev),
115 : : devflags);
116 [ # # ]: 0 : if (IS_ERR(drvdata->hcd)) {
117 : : ret = PTR_ERR(drvdata->hcd);
118 : : goto free_gpio;
119 : : }
120 : :
121 : : platform_set_drvdata(dev, drvdata);
122 : 0 : return ret;
123 : :
124 : : free_gpio:
125 [ # # ]: 0 : if (gpio_is_valid(drvdata->rst_gpio))
126 : 0 : gpio_free(drvdata->rst_gpio);
127 : : release_reg:
128 : 0 : release_mem_region(memory.start, res_len);
129 : : free_data:
130 : 0 : kfree(drvdata);
131 : 0 : return ret;
132 : : }
133 : :
134 : 0 : static int of_isp1760_remove(struct platform_device *dev)
135 : : {
136 : : struct isp1760 *drvdata = platform_get_drvdata(dev);
137 : :
138 : 0 : usb_remove_hcd(drvdata->hcd);
139 : 0 : iounmap(drvdata->hcd->regs);
140 : 0 : release_mem_region(drvdata->hcd->rsrc_start, drvdata->hcd->rsrc_len);
141 : 0 : usb_put_hcd(drvdata->hcd);
142 : :
143 [ # # ]: 0 : if (gpio_is_valid(drvdata->rst_gpio))
144 : 0 : gpio_free(drvdata->rst_gpio);
145 : :
146 : 0 : kfree(drvdata);
147 : 0 : return 0;
148 : : }
149 : :
150 : : static const struct of_device_id of_isp1760_match[] = {
151 : : {
152 : : .compatible = "nxp,usb-isp1760",
153 : : },
154 : : {
155 : : .compatible = "nxp,usb-isp1761",
156 : : },
157 : : { },
158 : : };
159 : : MODULE_DEVICE_TABLE(of, of_isp1760_match);
160 : :
161 : : static struct platform_driver isp1760_of_driver = {
162 : : .driver = {
163 : : .name = "nxp-isp1760",
164 : : .owner = THIS_MODULE,
165 : : .of_match_table = of_isp1760_match,
166 : : },
167 : : .probe = of_isp1760_probe,
168 : : .remove = of_isp1760_remove,
169 : : };
170 : : #endif
171 : :
172 : : #ifdef CONFIG_PCI
173 : : static int isp1761_pci_probe(struct pci_dev *dev,
174 : : const struct pci_device_id *id)
175 : : {
176 : : u8 latency, limit;
177 : : __u32 reg_data;
178 : : int retry_count;
179 : : struct usb_hcd *hcd;
180 : : unsigned int devflags = 0;
181 : : int ret_status = 0;
182 : :
183 : : resource_size_t pci_mem_phy0;
184 : : resource_size_t memlength;
185 : :
186 : : u8 __iomem *chip_addr;
187 : : u8 __iomem *iobase;
188 : : resource_size_t nxp_pci_io_base;
189 : : resource_size_t iolength;
190 : :
191 : : if (usb_disabled())
192 : : return -ENODEV;
193 : :
194 : : if (pci_enable_device(dev) < 0)
195 : : return -ENODEV;
196 : :
197 : : if (!dev->irq)
198 : : return -ENODEV;
199 : :
200 : : /* Grab the PLX PCI mem maped port start address we need */
201 : : nxp_pci_io_base = pci_resource_start(dev, 0);
202 : : iolength = pci_resource_len(dev, 0);
203 : :
204 : : if (!request_mem_region(nxp_pci_io_base, iolength, "ISP1761 IO MEM")) {
205 : : printk(KERN_ERR "request region #1\n");
206 : : return -EBUSY;
207 : : }
208 : :
209 : : iobase = ioremap_nocache(nxp_pci_io_base, iolength);
210 : : if (!iobase) {
211 : : printk(KERN_ERR "ioremap #1\n");
212 : : ret_status = -ENOMEM;
213 : : goto cleanup1;
214 : : }
215 : : /* Grab the PLX PCI shared memory of the ISP 1761 we need */
216 : : pci_mem_phy0 = pci_resource_start(dev, 3);
217 : : memlength = pci_resource_len(dev, 3);
218 : : if (memlength < 0xffff) {
219 : : printk(KERN_ERR "memory length for this resource is wrong\n");
220 : : ret_status = -ENOMEM;
221 : : goto cleanup2;
222 : : }
223 : :
224 : : if (!request_mem_region(pci_mem_phy0, memlength, "ISP-PCI")) {
225 : : printk(KERN_ERR "host controller already in use\n");
226 : : ret_status = -EBUSY;
227 : : goto cleanup2;
228 : : }
229 : :
230 : : /* map available memory */
231 : : chip_addr = ioremap_nocache(pci_mem_phy0,memlength);
232 : : if (!chip_addr) {
233 : : printk(KERN_ERR "Error ioremap failed\n");
234 : : ret_status = -ENOMEM;
235 : : goto cleanup3;
236 : : }
237 : :
238 : : /* bad pci latencies can contribute to overruns */
239 : : pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency);
240 : : if (latency) {
241 : : pci_read_config_byte(dev, PCI_MAX_LAT, &limit);
242 : : if (limit && limit < latency)
243 : : pci_write_config_byte(dev, PCI_LATENCY_TIMER, limit);
244 : : }
245 : :
246 : : /* Try to check whether we can access Scratch Register of
247 : : * Host Controller or not. The initial PCI access is retried until
248 : : * local init for the PCI bridge is completed
249 : : */
250 : : retry_count = 20;
251 : : reg_data = 0;
252 : : while ((reg_data != 0xFACE) && retry_count) {
253 : : /*by default host is in 16bit mode, so
254 : : * io operations at this stage must be 16 bit
255 : : * */
256 : : writel(0xface, chip_addr + HC_SCRATCH_REG);
257 : : udelay(100);
258 : : reg_data = readl(chip_addr + HC_SCRATCH_REG) & 0x0000ffff;
259 : : retry_count--;
260 : : }
261 : :
262 : : iounmap(chip_addr);
263 : :
264 : : /* Host Controller presence is detected by writing to scratch register
265 : : * and reading back and checking the contents are same or not
266 : : */
267 : : if (reg_data != 0xFACE) {
268 : : dev_err(&dev->dev, "scratch register mismatch %x\n", reg_data);
269 : : ret_status = -ENOMEM;
270 : : goto cleanup3;
271 : : }
272 : :
273 : : pci_set_master(dev);
274 : :
275 : : /* configure PLX PCI chip to pass interrupts */
276 : : #define PLX_INT_CSR_REG 0x68
277 : : reg_data = readl(iobase + PLX_INT_CSR_REG);
278 : : reg_data |= 0x900;
279 : : writel(reg_data, iobase + PLX_INT_CSR_REG);
280 : :
281 : : dev->dev.dma_mask = NULL;
282 : : hcd = isp1760_register(pci_mem_phy0, memlength, dev->irq,
283 : : IRQF_SHARED, -ENOENT, &dev->dev, dev_name(&dev->dev),
284 : : devflags);
285 : : if (IS_ERR(hcd)) {
286 : : ret_status = -ENODEV;
287 : : goto cleanup3;
288 : : }
289 : :
290 : : /* done with PLX IO access */
291 : : iounmap(iobase);
292 : : release_mem_region(nxp_pci_io_base, iolength);
293 : :
294 : : pci_set_drvdata(dev, hcd);
295 : : return 0;
296 : :
297 : : cleanup3:
298 : : release_mem_region(pci_mem_phy0, memlength);
299 : : cleanup2:
300 : : iounmap(iobase);
301 : : cleanup1:
302 : : release_mem_region(nxp_pci_io_base, iolength);
303 : : return ret_status;
304 : : }
305 : :
306 : : static void isp1761_pci_remove(struct pci_dev *dev)
307 : : {
308 : : struct usb_hcd *hcd;
309 : :
310 : : hcd = pci_get_drvdata(dev);
311 : :
312 : : usb_remove_hcd(hcd);
313 : : iounmap(hcd->regs);
314 : : release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
315 : : usb_put_hcd(hcd);
316 : :
317 : : pci_disable_device(dev);
318 : : }
319 : :
320 : : static void isp1761_pci_shutdown(struct pci_dev *dev)
321 : : {
322 : : printk(KERN_ERR "ips1761_pci_shutdown\n");
323 : : }
324 : :
325 : : static const struct pci_device_id isp1760_plx [] = {
326 : : {
327 : : .class = PCI_CLASS_BRIDGE_OTHER << 8,
328 : : .class_mask = ~0,
329 : : .vendor = PCI_VENDOR_ID_PLX,
330 : : .device = 0x5406,
331 : : .subvendor = PCI_VENDOR_ID_PLX,
332 : : .subdevice = 0x9054,
333 : : },
334 : : { }
335 : : };
336 : : MODULE_DEVICE_TABLE(pci, isp1760_plx);
337 : :
338 : : static struct pci_driver isp1761_pci_driver = {
339 : : .name = "isp1760",
340 : : .id_table = isp1760_plx,
341 : : .probe = isp1761_pci_probe,
342 : : .remove = isp1761_pci_remove,
343 : : .shutdown = isp1761_pci_shutdown,
344 : : };
345 : : #endif
346 : :
347 : 0 : static int isp1760_plat_probe(struct platform_device *pdev)
348 : : {
349 : : int ret = 0;
350 : : struct usb_hcd *hcd;
351 : 0 : struct resource *mem_res;
352 : : struct resource *irq_res;
353 : : resource_size_t mem_size;
354 : 0 : struct isp1760_platform_data *priv = dev_get_platdata(&pdev->dev);
355 : : unsigned int devflags = 0;
356 : : unsigned long irqflags = IRQF_SHARED;
357 : :
358 : 0 : mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
359 [ # # ]: 0 : if (!mem_res) {
360 : 0 : pr_warning("isp1760: Memory resource not available\n");
361 : : ret = -ENODEV;
362 : 0 : goto out;
363 : : }
364 : : mem_size = resource_size(mem_res);
365 [ # # ]: 0 : if (!request_mem_region(mem_res->start, mem_size, "isp1760")) {
366 : 0 : pr_warning("isp1760: Cannot reserve the memory resource\n");
367 : : ret = -EBUSY;
368 : 0 : goto out;
369 : : }
370 : :
371 : 0 : irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
372 [ # # ]: 0 : if (!irq_res) {
373 : 0 : pr_warning("isp1760: IRQ resource not available\n");
374 : : ret = -ENODEV;
375 : 0 : goto cleanup;
376 : : }
377 : :
378 : 0 : irqflags |= irq_res->flags & IRQF_TRIGGER_MASK;
379 : :
380 [ # # ]: 0 : if (priv) {
381 [ # # ]: 0 : if (priv->is_isp1761)
382 : : devflags |= ISP1760_FLAG_ISP1761;
383 [ # # ]: 0 : if (priv->bus_width_16)
384 : 0 : devflags |= ISP1760_FLAG_BUS_WIDTH_16;
385 [ # # ]: 0 : if (priv->port1_otg)
386 : 0 : devflags |= ISP1760_FLAG_OTG_EN;
387 [ # # ]: 0 : if (priv->analog_oc)
388 : 0 : devflags |= ISP1760_FLAG_ANALOG_OC;
389 [ # # ]: 0 : if (priv->dack_polarity_high)
390 : 0 : devflags |= ISP1760_FLAG_DACK_POL_HIGH;
391 [ # # ]: 0 : if (priv->dreq_polarity_high)
392 : 0 : devflags |= ISP1760_FLAG_DREQ_POL_HIGH;
393 : : }
394 : :
395 : 0 : hcd = isp1760_register(mem_res->start, mem_size, irq_res->start,
396 : : irqflags, -ENOENT,
397 : 0 : &pdev->dev, dev_name(&pdev->dev), devflags);
398 : :
399 : : platform_set_drvdata(pdev, hcd);
400 : :
401 [ # # ]: 0 : if (IS_ERR(hcd)) {
402 : 0 : pr_warning("isp1760: Failed to register the HCD device\n");
403 : : ret = -ENODEV;
404 : 0 : goto cleanup;
405 : : }
406 : :
407 : 0 : pr_info("ISP1760 USB device initialised\n");
408 : 0 : return ret;
409 : :
410 : : cleanup:
411 : 0 : release_mem_region(mem_res->start, mem_size);
412 : : out:
413 : 0 : return ret;
414 : : }
415 : :
416 : 0 : static int isp1760_plat_remove(struct platform_device *pdev)
417 : : {
418 : 0 : struct resource *mem_res;
419 : : resource_size_t mem_size;
420 : : struct usb_hcd *hcd = platform_get_drvdata(pdev);
421 : :
422 : 0 : usb_remove_hcd(hcd);
423 : :
424 : 0 : mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
425 : : mem_size = resource_size(mem_res);
426 : 0 : release_mem_region(mem_res->start, mem_size);
427 : :
428 : 0 : usb_put_hcd(hcd);
429 : :
430 : 0 : return 0;
431 : : }
432 : :
433 : : static struct platform_driver isp1760_plat_driver = {
434 : : .probe = isp1760_plat_probe,
435 : : .remove = isp1760_plat_remove,
436 : : .driver = {
437 : : .name = "isp1760",
438 : : },
439 : : };
440 : :
441 : 0 : static int __init isp1760_init(void)
442 : : {
443 : : int ret, any_ret = -ENODEV;
444 : :
445 : 0 : init_kmem_once();
446 : :
447 : 0 : ret = platform_driver_register(&isp1760_plat_driver);
448 [ # # ]: 0 : if (!ret)
449 : : any_ret = 0;
450 : : #if defined(CONFIG_OF) && defined(CONFIG_OF_IRQ)
451 : 0 : ret = platform_driver_register(&isp1760_of_driver);
452 [ # # ]: 0 : if (!ret)
453 : : any_ret = 0;
454 : : #endif
455 : : #ifdef CONFIG_PCI
456 : : ret = pci_register_driver(&isp1761_pci_driver);
457 : : if (!ret)
458 : : any_ret = 0;
459 : : #endif
460 : :
461 [ # # ]: 0 : if (any_ret)
462 : 0 : deinit_kmem_cache();
463 : 0 : return any_ret;
464 : : }
465 : : module_init(isp1760_init);
466 : :
467 : 0 : static void __exit isp1760_exit(void)
468 : : {
469 : 0 : platform_driver_unregister(&isp1760_plat_driver);
470 : : #if defined(CONFIG_OF) && defined(CONFIG_OF_IRQ)
471 : 0 : platform_driver_unregister(&isp1760_of_driver);
472 : : #endif
473 : : #ifdef CONFIG_PCI
474 : : pci_unregister_driver(&isp1761_pci_driver);
475 : : #endif
476 : 0 : deinit_kmem_cache();
477 : 0 : }
478 : : module_exit(isp1760_exit);
|