powerpc/44x: Add AMCC Arches eval board support
[linux-2.6] / 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  *
7  * (c) 2007 Sebastian Siewior <bigeasy@linutronix.de>
8  *
9  */
10
11 #include <linux/usb.h>
12 #include <linux/io.h>
13
14 #include "../core/hcd.h"
15 #include "isp1760-hcd.h"
16
17 #ifdef CONFIG_USB_ISP1760_OF
18 #include <linux/of.h>
19 #include <linux/of_platform.h>
20 #endif
21
22 #ifdef CONFIG_USB_ISP1760_PCI
23 #include <linux/pci.h>
24 #endif
25
26 #ifdef CONFIG_USB_ISP1760_OF
27 static int of_isp1760_probe(struct of_device *dev,
28                 const struct of_device_id *match)
29 {
30         struct usb_hcd *hcd;
31         struct device_node *dp = dev->node;
32         struct resource *res;
33         struct resource memory;
34         struct of_irq oirq;
35         int virq;
36         u64 res_len;
37         int ret;
38         const unsigned int *prop;
39         unsigned int devflags = 0;
40
41         ret = of_address_to_resource(dp, 0, &memory);
42         if (ret)
43                 return -ENXIO;
44
45         res = request_mem_region(memory.start, memory.end - memory.start + 1,
46                         dev_name(&dev->dev));
47         if (!res)
48                 return -EBUSY;
49
50         res_len = memory.end - memory.start + 1;
51
52         if (of_irq_map_one(dp, 0, &oirq)) {
53                 ret = -ENODEV;
54                 goto release_reg;
55         }
56
57         virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
58                         oirq.size);
59
60         if (of_device_is_compatible(dp, "nxp,usb-isp1761"))
61                 devflags |= ISP1760_FLAG_ISP1761;
62
63         if (of_get_property(dp, "port1-disable", NULL) != NULL)
64                 devflags |= ISP1760_FLAG_PORT1_DIS;
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_USB_ISP1760_PCI
132 static u32 nxp_pci_io_base;
133 static u32 iolength;
134 static u32 pci_mem_phy0;
135 static u32 length;
136 static u8 __iomem *chip_addr;
137 static u8 __iomem *iobase;
138
139 static int __devinit isp1761_pci_probe(struct pci_dev *dev,
140                 const struct pci_device_id *id)
141 {
142         u8 latency, limit;
143         __u32 reg_data;
144         int retry_count;
145         int length;
146         int status = 1;
147         struct usb_hcd *hcd;
148         unsigned int devflags = 0;
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                 release_mem_region(nxp_pci_io_base, iolength);
172                 return -ENOMEM;
173         }
174         /* Grab the PLX PCI shared memory of the ISP 1761 we need  */
175         pci_mem_phy0 = pci_resource_start(dev, 3);
176         length = pci_resource_len(dev, 3);
177
178         if (length < 0xffff) {
179                 printk(KERN_ERR "memory length for this resource is less than "
180                                 "required\n");
181                 release_mem_region(nxp_pci_io_base, iolength);
182                 iounmap(iobase);
183                 return  -ENOMEM;
184         }
185
186         if (!request_mem_region(pci_mem_phy0, length, "ISP-PCI")) {
187                 printk(KERN_ERR "host controller already in use\n");
188                 release_mem_region(nxp_pci_io_base, iolength);
189                 iounmap(iobase);
190                 return -EBUSY;
191         }
192
193         /* bad pci latencies can contribute to overruns */
194         pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency);
195         if (latency) {
196                 pci_read_config_byte(dev, PCI_MAX_LAT, &limit);
197                 if (limit && limit < latency)
198                         pci_write_config_byte(dev, PCI_LATENCY_TIMER, limit);
199         }
200
201         /* Try to check whether we can access Scratch Register of
202          * Host Controller or not. The initial PCI access is retried until
203          * local init for the PCI bridge is completed
204          */
205         retry_count = 20;
206         reg_data = 0;
207         while ((reg_data != 0xFACE) && retry_count) {
208                 /*by default host is in 16bit mode, so
209                  * io operations at this stage must be 16 bit
210                  * */
211                 writel(0xface, chip_addr + HC_SCRATCH_REG);
212                 udelay(100);
213                 reg_data = readl(chip_addr + HC_SCRATCH_REG);
214                 retry_count--;
215         }
216
217         /* Host Controller presence is detected by writing to scratch register
218          * and reading back and checking the contents are same or not
219          */
220         if (reg_data != 0xFACE) {
221                 err("scratch register mismatch %x", reg_data);
222                 goto clean;
223         }
224
225         pci_set_master(dev);
226
227         status = readl(iobase + 0x68);
228         status |= 0x900;
229         writel(status, iobase + 0x68);
230
231         dev->dev.dma_mask = NULL;
232         hcd = isp1760_register(pci_mem_phy0, length, dev->irq,
233                 IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev_name(&dev->dev),
234                 devflags);
235         pci_set_drvdata(dev, hcd);
236         if (!hcd)
237                 return 0;
238 clean:
239         status = -ENODEV;
240         iounmap(iobase);
241         release_mem_region(pci_mem_phy0, length);
242         release_mem_region(nxp_pci_io_base, iolength);
243         return status;
244 }
245 static void isp1761_pci_remove(struct pci_dev *dev)
246 {
247         struct usb_hcd *hcd;
248
249         hcd = pci_get_drvdata(dev);
250
251         usb_remove_hcd(hcd);
252         iounmap(hcd->regs);
253         release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
254         usb_put_hcd(hcd);
255
256         pci_disable_device(dev);
257
258         iounmap(iobase);
259         iounmap(chip_addr);
260
261         release_mem_region(nxp_pci_io_base, iolength);
262         release_mem_region(pci_mem_phy0, length);
263 }
264
265 static void isp1761_pci_shutdown(struct pci_dev *dev)
266 {
267         printk(KERN_ERR "ips1761_pci_shutdown\n");
268 }
269
270 static const struct pci_device_id isp1760_plx [] = { {
271         /* handle any USB 2.0 EHCI controller */
272         PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_OTHER << 8) | (0x06 << 16)), ~0),
273                 .driver_data = 0,
274 },
275 { /* end: all zeroes */ }
276 };
277 MODULE_DEVICE_TABLE(pci, isp1760_plx);
278
279 static struct pci_driver isp1761_pci_driver = {
280         .name =         "isp1760",
281         .id_table =     isp1760_plx,
282         .probe =        isp1761_pci_probe,
283         .remove =       isp1761_pci_remove,
284         .shutdown =     isp1761_pci_shutdown,
285 };
286 #endif
287
288 static int __init isp1760_init(void)
289 {
290         int ret = -ENODEV;
291
292         init_kmem_once();
293
294 #ifdef CONFIG_USB_ISP1760_OF
295         ret = of_register_platform_driver(&isp1760_of_driver);
296         if (ret) {
297                 deinit_kmem_cache();
298                 return ret;
299         }
300 #endif
301 #ifdef CONFIG_USB_ISP1760_PCI
302         ret = pci_register_driver(&isp1761_pci_driver);
303         if (ret)
304                 goto unreg_of;
305 #endif
306         return ret;
307
308 #ifdef CONFIG_USB_ISP1760_PCI
309 unreg_of:
310 #endif
311 #ifdef CONFIG_USB_ISP1760_OF
312         of_unregister_platform_driver(&isp1760_of_driver);
313 #endif
314         deinit_kmem_cache();
315         return ret;
316 }
317 module_init(isp1760_init);
318
319 static void __exit isp1760_exit(void)
320 {
321 #ifdef CONFIG_USB_ISP1760_OF
322         of_unregister_platform_driver(&isp1760_of_driver);
323 #endif
324 #ifdef CONFIG_USB_ISP1760_PCI
325         pci_unregister_driver(&isp1761_pci_driver);
326 #endif
327         deinit_kmem_cache();
328 }
329 module_exit(isp1760_exit);