Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[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
39         ret = of_address_to_resource(dp, 0, &memory);
40         if (ret)
41                 return -ENXIO;
42
43         res = request_mem_region(memory.start, memory.end - memory.start + 1,
44                         dev->dev.bus_id);
45         if (!res)
46                 return -EBUSY;
47
48         res_len = memory.end - memory.start + 1;
49
50         if (of_irq_map_one(dp, 0, &oirq)) {
51                 ret = -ENODEV;
52                 goto release_reg;
53         }
54
55         virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
56                         oirq.size);
57
58         hcd = isp1760_register(memory.start, res_len, virq,
59                 IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev->dev.bus_id);
60         if (IS_ERR(hcd)) {
61                 ret = PTR_ERR(hcd);
62                 goto release_reg;
63         }
64
65         dev_set_drvdata(&dev->dev, hcd);
66         return ret;
67
68 release_reg:
69         release_mem_region(memory.start, memory.end - memory.start + 1);
70         return ret;
71 }
72
73 static int of_isp1760_remove(struct of_device *dev)
74 {
75         struct usb_hcd *hcd = dev_get_drvdata(&dev->dev);
76
77         dev_set_drvdata(&dev->dev, NULL);
78
79         usb_remove_hcd(hcd);
80         iounmap(hcd->regs);
81         release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
82         usb_put_hcd(hcd);
83         return 0;
84 }
85
86 static struct of_device_id of_isp1760_match[] = {
87         {
88                 .compatible = "nxp,usb-isp1760",
89         },
90         { },
91 };
92 MODULE_DEVICE_TABLE(of, of_isp1760_match);
93
94 static struct of_platform_driver isp1760_of_driver = {
95         .name           = "nxp-isp1760",
96         .match_table    = of_isp1760_match,
97         .probe          = of_isp1760_probe,
98         .remove         = of_isp1760_remove,
99 };
100 #endif
101
102 #ifdef CONFIG_USB_ISP1760_PCI
103 static u32 nxp_pci_io_base;
104 static u32 iolength;
105 static u32 pci_mem_phy0;
106 static u32 length;
107 static u8 __iomem *chip_addr;
108 static u8 __iomem *iobase;
109
110 static int __devinit isp1761_pci_probe(struct pci_dev *dev,
111                 const struct pci_device_id *id)
112 {
113         u8 latency, limit;
114         __u32 reg_data;
115         int retry_count;
116         int length;
117         int status = 1;
118         struct usb_hcd *hcd;
119
120         if (usb_disabled())
121                 return -ENODEV;
122
123         if (pci_enable_device(dev) < 0)
124                 return -ENODEV;
125
126         if (!dev->irq)
127                 return -ENODEV;
128
129         /* Grab the PLX PCI mem maped port start address we need  */
130         nxp_pci_io_base = pci_resource_start(dev, 0);
131         iolength = pci_resource_len(dev, 0);
132
133         if (!request_mem_region(nxp_pci_io_base, iolength, "ISP1761 IO MEM")) {
134                 printk(KERN_ERR "request region #1\n");
135                 return -EBUSY;
136         }
137
138         iobase = ioremap_nocache(nxp_pci_io_base, iolength);
139         if (!iobase) {
140                 printk(KERN_ERR "ioremap #1\n");
141                 release_mem_region(nxp_pci_io_base, iolength);
142                 return -ENOMEM;
143         }
144         /* Grab the PLX PCI shared memory of the ISP 1761 we need  */
145         pci_mem_phy0 = pci_resource_start(dev, 3);
146         length = pci_resource_len(dev, 3);
147
148         if (length < 0xffff) {
149                 printk(KERN_ERR "memory length for this resource is less than "
150                                 "required\n");
151                 release_mem_region(nxp_pci_io_base, iolength);
152                 iounmap(iobase);
153                 return  -ENOMEM;
154         }
155
156         if (!request_mem_region(pci_mem_phy0, length, "ISP-PCI")) {
157                 printk(KERN_ERR "host controller already in use\n");
158                 release_mem_region(nxp_pci_io_base, iolength);
159                 iounmap(iobase);
160                 return -EBUSY;
161         }
162
163         /* bad pci latencies can contribute to overruns */
164         pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency);
165         if (latency) {
166                 pci_read_config_byte(dev, PCI_MAX_LAT, &limit);
167                 if (limit && limit < latency)
168                         pci_write_config_byte(dev, PCI_LATENCY_TIMER, limit);
169         }
170
171         /* Try to check whether we can access Scratch Register of
172          * Host Controller or not. The initial PCI access is retried until
173          * local init for the PCI bridge is completed
174          */
175         retry_count = 20;
176         reg_data = 0;
177         while ((reg_data != 0xFACE) && retry_count) {
178                 /*by default host is in 16bit mode, so
179                  * io operations at this stage must be 16 bit
180                  * */
181                 writel(0xface, chip_addr + HC_SCRATCH_REG);
182                 udelay(100);
183                 reg_data = readl(chip_addr + HC_SCRATCH_REG);
184                 retry_count--;
185         }
186
187         /* Host Controller presence is detected by writing to scratch register
188          * and reading back and checking the contents are same or not
189          */
190         if (reg_data != 0xFACE) {
191                 err("scratch register mismatch %x", reg_data);
192                 goto clean;
193         }
194
195         pci_set_master(dev);
196
197         status = readl(iobase + 0x68);
198         status |= 0x900;
199         writel(status, iobase + 0x68);
200
201         dev->dev.dma_mask = NULL;
202         hcd = isp1760_register(pci_mem_phy0, length, dev->irq,
203                 IRQF_SHARED | IRQF_DISABLED, &dev->dev, dev->dev.bus_id);
204         pci_set_drvdata(dev, hcd);
205         if (!hcd)
206                 return 0;
207 clean:
208         status = -ENODEV;
209         iounmap(iobase);
210         release_mem_region(pci_mem_phy0, length);
211         release_mem_region(nxp_pci_io_base, iolength);
212         return status;
213 }
214 static void isp1761_pci_remove(struct pci_dev *dev)
215 {
216         struct usb_hcd *hcd;
217
218         hcd = pci_get_drvdata(dev);
219
220         usb_remove_hcd(hcd);
221         iounmap(hcd->regs);
222         release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
223         usb_put_hcd(hcd);
224
225         pci_disable_device(dev);
226
227         iounmap(iobase);
228         iounmap(chip_addr);
229
230         release_mem_region(nxp_pci_io_base, iolength);
231         release_mem_region(pci_mem_phy0, length);
232 }
233
234 static void isp1761_pci_shutdown(struct pci_dev *dev)
235 {
236         printk(KERN_ERR "ips1761_pci_shutdown\n");
237 }
238
239 static const struct pci_device_id isp1760_plx [] = { {
240         /* handle any USB 2.0 EHCI controller */
241         PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_OTHER << 8) | (0x06 << 16)), ~0),
242                 .driver_data = 0,
243 },
244 { /* end: all zeroes */ }
245 };
246 MODULE_DEVICE_TABLE(pci, isp1760_plx);
247
248 static struct pci_driver isp1761_pci_driver = {
249         .name =         "isp1760",
250         .id_table =     isp1760_plx,
251         .probe =        isp1761_pci_probe,
252         .remove =       isp1761_pci_remove,
253         .shutdown =     isp1761_pci_shutdown,
254 };
255 #endif
256
257 static int __init isp1760_init(void)
258 {
259         int ret = -ENODEV;
260
261         init_kmem_once();
262
263 #ifdef CONFIG_USB_ISP1760_OF
264         ret = of_register_platform_driver(&isp1760_of_driver);
265         if (ret) {
266                 deinit_kmem_cache();
267                 return ret;
268         }
269 #endif
270 #ifdef CONFIG_USB_ISP1760_PCI
271         ret = pci_register_driver(&isp1761_pci_driver);
272         if (ret)
273                 goto unreg_of;
274 #endif
275         return ret;
276
277 #ifdef CONFIG_USB_ISP1760_PCI
278 unreg_of:
279 #endif
280 #ifdef CONFIG_USB_ISP1760_OF
281         of_unregister_platform_driver(&isp1760_of_driver);
282 #endif
283         deinit_kmem_cache();
284         return ret;
285 }
286 module_init(isp1760_init);
287
288 static void __exit isp1760_exit(void)
289 {
290 #ifdef CONFIG_USB_ISP1760_OF
291         of_unregister_platform_driver(&isp1760_of_driver);
292 #endif
293 #ifdef CONFIG_USB_ISP1760_PCI
294         pci_unregister_driver(&isp1761_pci_driver);
295 #endif
296         deinit_kmem_cache();
297 }
298 module_exit(isp1760_exit);