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