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