Merge branches 'release', 'asus', 'sony-laptop' and 'thinkpad' into release
[pandora-kernel.git] / arch / powerpc / platforms / celleb / pci.c
1 /*
2  * Support for PCI on Celleb platform.
3  *
4  * (C) Copyright 2006-2007 TOSHIBA CORPORATION
5  *
6  * This code is based on arch/powerpc/kernel/rtas_pci.c:
7  *  Copyright (C) 2001 Dave Engebretsen, IBM Corporation
8  *  Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License along
21  * with this program; if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24
25 #undef DEBUG
26
27 #include <linux/kernel.h>
28 #include <linux/threads.h>
29 #include <linux/pci.h>
30 #include <linux/string.h>
31 #include <linux/init.h>
32 #include <linux/bootmem.h>
33 #include <linux/pci_regs.h>
34 #include <linux/of.h>
35 #include <linux/of_device.h>
36
37 #include <asm/io.h>
38 #include <asm/irq.h>
39 #include <asm/prom.h>
40 #include <asm/machdep.h>
41 #include <asm/pci-bridge.h>
42 #include <asm/ppc-pci.h>
43
44 #include "pci.h"
45 #include "interrupt.h"
46
47 #define MAX_PCI_DEVICES    32
48 #define MAX_PCI_FUNCTIONS   8
49 #define MAX_PCI_BASE_ADDRS  3 /* use 64 bit address */
50
51 /* definition for fake pci configuration area for GbE, .... ,and etc. */
52
53 struct celleb_pci_resource {
54         struct resource r[MAX_PCI_BASE_ADDRS];
55 };
56
57 struct celleb_pci_private {
58         unsigned char *fake_config[MAX_PCI_DEVICES][MAX_PCI_FUNCTIONS];
59         struct celleb_pci_resource *res[MAX_PCI_DEVICES][MAX_PCI_FUNCTIONS];
60 };
61
62 static inline u8 celleb_fake_config_readb(void *addr)
63 {
64         u8 *p = addr;
65         return *p;
66 }
67
68 static inline u16 celleb_fake_config_readw(void *addr)
69 {
70         __le16 *p = addr;
71         return le16_to_cpu(*p);
72 }
73
74 static inline u32 celleb_fake_config_readl(void *addr)
75 {
76         __le32 *p = addr;
77         return le32_to_cpu(*p);
78 }
79
80 static inline void celleb_fake_config_writeb(u32 val, void *addr)
81 {
82         u8 *p = addr;
83         *p = val;
84 }
85
86 static inline void celleb_fake_config_writew(u32 val, void *addr)
87 {
88         __le16 val16;
89         __le16 *p = addr;
90         val16 = cpu_to_le16(val);
91         *p = val16;
92 }
93
94 static inline void celleb_fake_config_writel(u32 val, void *addr)
95 {
96         __le32 val32;
97         __le32 *p = addr;
98         val32 = cpu_to_le32(val);
99         *p = val32;
100 }
101
102 static unsigned char *get_fake_config_start(struct pci_controller *hose,
103                                             int devno, int fn)
104 {
105         struct celleb_pci_private *private = hose->private_data;
106
107         if (private == NULL)
108                 return NULL;
109
110         return private->fake_config[devno][fn];
111 }
112
113 static struct celleb_pci_resource *get_resource_start(
114                                 struct pci_controller *hose,
115                                 int devno, int fn)
116 {
117         struct celleb_pci_private *private = hose->private_data;
118
119         if (private == NULL)
120                 return NULL;
121
122         return private->res[devno][fn];
123 }
124
125
126 static void celleb_config_read_fake(unsigned char *config, int where,
127                                     int size, u32 *val)
128 {
129         char *p = config + where;
130
131         switch (size) {
132         case 1:
133                 *val = celleb_fake_config_readb(p);
134                 break;
135         case 2:
136                 *val = celleb_fake_config_readw(p);
137                 break;
138         case 4:
139                 *val = celleb_fake_config_readl(p);
140                 break;
141         }
142 }
143
144 static void celleb_config_write_fake(unsigned char *config, int where,
145                                      int size, u32 val)
146 {
147         char *p = config + where;
148
149         switch (size) {
150         case 1:
151                 celleb_fake_config_writeb(val, p);
152                 break;
153         case 2:
154                 celleb_fake_config_writew(val, p);
155                 break;
156         case 4:
157                 celleb_fake_config_writel(val, p);
158                 break;
159         }
160 }
161
162 static int celleb_fake_pci_read_config(struct pci_bus *bus,
163                 unsigned int devfn, int where, int size, u32 *val)
164 {
165         char *config;
166         struct device_node *node;
167         struct pci_controller *hose;
168         unsigned int devno = devfn >> 3;
169         unsigned int fn = devfn & 0x7;
170
171         /* allignment check */
172         BUG_ON(where % size);
173
174         pr_debug("    fake read: bus=0x%x, ", bus->number);
175         node = (struct device_node *)bus->sysdata;
176         hose = pci_find_hose_for_OF_device(node);
177         config = get_fake_config_start(hose, devno, fn);
178
179         pr_debug("devno=0x%x, where=0x%x, size=0x%x, ", devno, where, size);
180         if (!config) {
181                 pr_debug("failed\n");
182                 return PCIBIOS_DEVICE_NOT_FOUND;
183         }
184
185         celleb_config_read_fake(config, where, size, val);
186         pr_debug("val=0x%x\n", *val);
187
188         return PCIBIOS_SUCCESSFUL;
189 }
190
191
192 static int celleb_fake_pci_write_config(struct pci_bus *bus,
193                  unsigned int devfn, int where, int size, u32 val)
194 {
195         char *config;
196         struct device_node *node;
197         struct pci_controller *hose;
198         struct celleb_pci_resource *res;
199         unsigned int devno = devfn >> 3;
200         unsigned int fn = devfn & 0x7;
201
202         /* allignment check */
203         BUG_ON(where % size);
204
205         node = (struct device_node *)bus->sysdata;
206         hose = pci_find_hose_for_OF_device(node);
207         config = get_fake_config_start(hose, devno, fn);
208
209         if (!config)
210                 return PCIBIOS_DEVICE_NOT_FOUND;
211
212         if (val == ~0) {
213                 int i = (where - PCI_BASE_ADDRESS_0) >> 3;
214
215                 switch (where) {
216                 case PCI_BASE_ADDRESS_0:
217                 case PCI_BASE_ADDRESS_2:
218                         if (size != 4)
219                                 return PCIBIOS_DEVICE_NOT_FOUND;
220                         res = get_resource_start(hose, devno, fn);
221                         if (!res)
222                                 return PCIBIOS_DEVICE_NOT_FOUND;
223                         celleb_config_write_fake(config, where, size,
224                                         (res->r[i].end - res->r[i].start));
225                         return PCIBIOS_SUCCESSFUL;
226                 case PCI_BASE_ADDRESS_1:
227                 case PCI_BASE_ADDRESS_3:
228                 case PCI_BASE_ADDRESS_4:
229                 case PCI_BASE_ADDRESS_5:
230                         break;
231                 default:
232                         break;
233                 }
234         }
235
236         celleb_config_write_fake(config, where, size, val);
237         pr_debug("    fake write: where=%x, size=%d, val=%x\n",
238                  where, size, val);
239
240         return PCIBIOS_SUCCESSFUL;
241 }
242
243 static struct pci_ops celleb_fake_pci_ops = {
244         .read = celleb_fake_pci_read_config,
245         .write = celleb_fake_pci_write_config,
246 };
247
248 static inline void celleb_setup_pci_base_addrs(struct pci_controller *hose,
249                                         unsigned int devno, unsigned int fn,
250                                         unsigned int num_base_addr)
251 {
252         u32 val;
253         unsigned char *config;
254         struct celleb_pci_resource *res;
255
256         config = get_fake_config_start(hose, devno, fn);
257         res = get_resource_start(hose, devno, fn);
258
259         if (!config || !res)
260                 return;
261
262         switch (num_base_addr) {
263         case 3:
264                 val = (res->r[2].start & 0xfffffff0)
265                     | PCI_BASE_ADDRESS_MEM_TYPE_64;
266                 celleb_config_write_fake(config, PCI_BASE_ADDRESS_4, 4, val);
267                 val = res->r[2].start >> 32;
268                 celleb_config_write_fake(config, PCI_BASE_ADDRESS_5, 4, val);
269                 /* FALLTHROUGH */
270         case 2:
271                 val = (res->r[1].start & 0xfffffff0)
272                     | PCI_BASE_ADDRESS_MEM_TYPE_64;
273                 celleb_config_write_fake(config, PCI_BASE_ADDRESS_2, 4, val);
274                 val = res->r[1].start >> 32;
275                 celleb_config_write_fake(config, PCI_BASE_ADDRESS_3, 4, val);
276                 /* FALLTHROUGH */
277         case 1:
278                 val = (res->r[0].start & 0xfffffff0)
279                     | PCI_BASE_ADDRESS_MEM_TYPE_64;
280                 celleb_config_write_fake(config, PCI_BASE_ADDRESS_0, 4, val);
281                 val = res->r[0].start >> 32;
282                 celleb_config_write_fake(config, PCI_BASE_ADDRESS_1, 4, val);
283                 break;
284         }
285
286         val = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
287         celleb_config_write_fake(config, PCI_COMMAND, 2, val);
288 }
289
290 static int __init celleb_setup_fake_pci_device(struct device_node *node,
291                                                struct pci_controller *hose)
292 {
293         unsigned int rlen;
294         int num_base_addr = 0;
295         u32 val;
296         const u32 *wi0, *wi1, *wi2, *wi3, *wi4;
297         unsigned int devno, fn;
298         struct celleb_pci_private *private = hose->private_data;
299         unsigned char **config = NULL;
300         struct celleb_pci_resource **res = NULL;
301         const char *name;
302         const unsigned long *li;
303         int size, result;
304
305         if (private == NULL) {
306                 printk(KERN_ERR "PCI: "
307                        "memory space for pci controller is not assigned\n");
308                 goto error;
309         }
310
311         name = of_get_property(node, "model", &rlen);
312         if (!name) {
313                 printk(KERN_ERR "PCI: model property not found.\n");
314                 goto error;
315         }
316
317         wi4 = of_get_property(node, "reg", &rlen);
318         if (wi4 == NULL)
319                 goto error;
320
321         devno = ((wi4[0] >> 8) & 0xff) >> 3;
322         fn = (wi4[0] >> 8) & 0x7;
323
324         pr_debug("PCI: celleb_setup_fake_pci() %s devno=%x fn=%x\n", name,
325                  devno, fn);
326
327         size = 256;
328         config = &private->fake_config[devno][fn];
329         *config = alloc_maybe_bootmem(size, GFP_KERNEL);
330         if (*config == NULL) {
331                 printk(KERN_ERR "PCI: "
332                        "not enough memory for fake configuration space\n");
333                 goto error;
334         }
335         pr_debug("PCI: fake config area assigned 0x%016lx\n",
336                  (unsigned long)*config);
337
338         size = sizeof(struct celleb_pci_resource);
339         res = &private->res[devno][fn];
340         *res = alloc_maybe_bootmem(size, GFP_KERNEL);
341         if (*res == NULL) {
342                 printk(KERN_ERR
343                        "PCI: not enough memory for resource data space\n");
344                 goto error;
345         }
346         pr_debug("PCI: res assigned 0x%016lx\n", (unsigned long)*res);
347
348         wi0 = of_get_property(node, "device-id", NULL);
349         wi1 = of_get_property(node, "vendor-id", NULL);
350         wi2 = of_get_property(node, "class-code", NULL);
351         wi3 = of_get_property(node, "revision-id", NULL);
352         if (!wi0 || !wi1 || !wi2 || !wi3) {
353                 printk(KERN_ERR "PCI: Missing device tree properties.\n");
354                 goto error;
355         }
356
357         celleb_config_write_fake(*config, PCI_DEVICE_ID, 2, wi0[0] & 0xffff);
358         celleb_config_write_fake(*config, PCI_VENDOR_ID, 2, wi1[0] & 0xffff);
359         pr_debug("class-code = 0x%08x\n", wi2[0]);
360
361         celleb_config_write_fake(*config, PCI_CLASS_PROG, 1, wi2[0] & 0xff);
362         celleb_config_write_fake(*config, PCI_CLASS_DEVICE, 2,
363                                  (wi2[0] >> 8) & 0xffff);
364         celleb_config_write_fake(*config, PCI_REVISION_ID, 1, wi3[0]);
365
366         while (num_base_addr < MAX_PCI_BASE_ADDRS) {
367                 result = of_address_to_resource(node,
368                                 num_base_addr, &(*res)->r[num_base_addr]);
369                 if (result)
370                         break;
371                 num_base_addr++;
372         }
373
374         celleb_setup_pci_base_addrs(hose, devno, fn, num_base_addr);
375
376         li = of_get_property(node, "interrupts", &rlen);
377         if (!li) {
378                 printk(KERN_ERR "PCI: interrupts not found.\n");
379                 goto error;
380         }
381         val = li[0];
382         celleb_config_write_fake(*config, PCI_INTERRUPT_PIN, 1, 1);
383         celleb_config_write_fake(*config, PCI_INTERRUPT_LINE, 1, val);
384
385 #ifdef DEBUG
386         pr_debug("PCI: %s irq=%ld\n", name, li[0]);
387         for (i = 0; i < 6; i++) {
388                 celleb_config_read_fake(*config,
389                                         PCI_BASE_ADDRESS_0 + 0x4 * i, 4,
390                                         &val);
391                 pr_debug("PCI: %s fn=%d base_address_%d=0x%x\n",
392                          name, fn, i, val);
393         }
394 #endif
395
396         celleb_config_write_fake(*config, PCI_HEADER_TYPE, 1,
397                                  PCI_HEADER_TYPE_NORMAL);
398
399         return 0;
400
401 error:
402         if (mem_init_done) {
403                 if (config && *config)
404                         kfree(*config);
405                 if (res && *res)
406                         kfree(*res);
407
408         } else {
409                 if (config && *config) {
410                         size = 256;
411                         free_bootmem((unsigned long)(*config), size);
412                 }
413                 if (res && *res) {
414                         size = sizeof(struct celleb_pci_resource);
415                         free_bootmem((unsigned long)(*res), size);
416                 }
417         }
418
419         return 1;
420 }
421
422 static int __init phb_set_bus_ranges(struct device_node *dev,
423                                      struct pci_controller *phb)
424 {
425         const int *bus_range;
426         unsigned int len;
427
428         bus_range = of_get_property(dev, "bus-range", &len);
429         if (bus_range == NULL || len < 2 * sizeof(int))
430                 return 1;
431
432         phb->first_busno = bus_range[0];
433         phb->last_busno = bus_range[1];
434
435         return 0;
436 }
437
438 static void __init celleb_alloc_private_mem(struct pci_controller *hose)
439 {
440         hose->private_data =
441                 alloc_maybe_bootmem(sizeof(struct celleb_pci_private),
442                         GFP_KERNEL);
443 }
444
445 static int __init celleb_setup_fake_pci(struct device_node *dev,
446                                         struct pci_controller *phb)
447 {
448         struct device_node *node;
449
450         phb->ops = &celleb_fake_pci_ops;
451         celleb_alloc_private_mem(phb);
452
453         for (node = of_get_next_child(dev, NULL);
454              node != NULL; node = of_get_next_child(dev, node))
455                 celleb_setup_fake_pci_device(node, phb);
456
457         return 0;
458 }
459
460 void __init fake_pci_workaround_init(struct pci_controller *phb)
461 {
462         /**
463          *  We will add fake pci bus to scc_pci_bus for the purpose to improve
464          *  I/O Macro performance. But device-tree and device drivers
465          *  are not ready to use address with a token.
466          */
467
468         /* celleb_pci_add_one(phb, NULL); */
469 }
470
471 static struct of_device_id celleb_phb_match[] __initdata = {
472         {
473                 .name = "pci-pseudo",
474                 .data = celleb_setup_fake_pci,
475         }, {
476                 .name = "epci",
477                 .data = celleb_setup_epci,
478         }, {
479         },
480 };
481
482 int __init celleb_setup_phb(struct pci_controller *phb)
483 {
484         struct device_node *dev = phb->dn;
485         const struct of_device_id *match;
486         int (*setup_func)(struct device_node *, struct pci_controller *);
487
488         match = of_match_node(celleb_phb_match, dev);
489         if (!match)
490                 return 1;
491
492         phb_set_bus_ranges(dev, phb);
493         phb->buid = 1;
494
495         setup_func = match->data;
496         return (*setup_func)(dev, phb);
497 }
498
499 int celleb_pci_probe_mode(struct pci_bus *bus)
500 {
501         return PCI_PROBE_DEVTREE;
502 }