blob: 649b336677483571f5420cabe0f023fbc8697421 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
3 * Copyright (C) 2003, 2004 Paul Mundt
4 * Copyright (C) 2004 Richard Curnow
5 *
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
8 *
9 * Support functions for the SH5 PCI hardware.
10 */
11
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include <linux/kernel.h>
13#include <linux/rwsem.h>
14#include <linux/smp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <linux/interrupt.h>
16#include <linux/init.h>
17#include <linux/errno.h>
18#include <linux/pci.h>
19#include <linux/delay.h>
20#include <linux/types.h>
21#include <asm/pci.h>
22#include <linux/irq.h>
23
24#include <asm/io.h>
25#include <asm/hardware.h>
26#include "pci_sh5.h"
27
28static unsigned long pcicr_virt;
29unsigned long pciio_virt;
30
31static void __init pci_fixup_ide_bases(struct pci_dev *d)
32{
33 int i;
34
35 /*
36 * PCI IDE controllers use non-standard I/O port decoding, respect it.
37 */
38 if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
39 return;
40 printk("PCI: IDE base address fixup for %s\n", pci_name(d));
41 for(i=0; i<4; i++) {
42 struct resource *r = &d->resource[i];
43 if ((r->start & ~0x80) == 0x374) {
44 r->start |= 2;
45 r->end = r->start;
46 }
47 }
48}
49DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
50
51char * __init pcibios_setup(char *str)
52{
53 return str;
54}
55
56/* Rounds a number UP to the nearest power of two. Used for
57 * sizing the PCI window.
58 */
59static u32 __init r2p2(u32 num)
60{
61 int i = 31;
62 u32 tmp = num;
63
64 if (num == 0)
65 return 0;
66
67 do {
68 if (tmp & (1 << 31))
69 break;
70 i--;
71 tmp <<= 1;
72 } while (i >= 0);
73
74 tmp = 1 << i;
75 /* If the original number isn't a power of 2, round it up */
76 if (tmp != num)
77 tmp <<= 1;
78
79 return tmp;
80}
81
82extern unsigned long long memory_start, memory_end;
83
84int __init sh5pci_init(unsigned memStart, unsigned memSize)
85{
86 u32 lsr0;
87 u32 uval;
88
89 pcicr_virt = onchip_remap(SH5PCI_ICR_BASE, 1024, "PCICR");
90 if (!pcicr_virt) {
91 panic("Unable to remap PCICR\n");
92 }
93
94 pciio_virt = onchip_remap(SH5PCI_IO_BASE, 0x10000, "PCIIO");
95 if (!pciio_virt) {
96 panic("Unable to remap PCIIO\n");
97 }
98
99 pr_debug("Register base addres is 0x%08lx\n", pcicr_virt);
100
101 /* Clear snoop registers */
102 SH5PCI_WRITE(CSCR0, 0);
103 SH5PCI_WRITE(CSCR1, 0);
104
105 pr_debug("Wrote to reg\n");
106
107 /* Switch off interrupts */
108 SH5PCI_WRITE(INTM, 0);
109 SH5PCI_WRITE(AINTM, 0);
110 SH5PCI_WRITE(PINTM, 0);
111
112 /* Set bus active, take it out of reset */
113 uval = SH5PCI_READ(CR);
114
115 /* Set command Register */
116 SH5PCI_WRITE(CR, uval | CR_LOCK_MASK | CR_CFINT| CR_FTO | CR_PFE | CR_PFCS | CR_BMAM);
117
118 uval=SH5PCI_READ(CR);
119 pr_debug("CR is actually 0x%08x\n",uval);
120
121 /* Allow it to be a master */
122 /* NB - WE DISABLE I/O ACCESS to stop overlap */
123 /* set WAIT bit to enable stepping, an attempt to improve stability */
124 SH5PCI_WRITE_SHORT(CSR_CMD,
125 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_WAIT);
126
127 /*
128 ** Set translation mapping memory in order to convert the address
129 ** used for the main bus, to the PCI internal address.
130 */
131 SH5PCI_WRITE(MBR,0x40000000);
132
133 /* Always set the max size 512M */
134 SH5PCI_WRITE(MBMR, PCISH5_MEM_SIZCONV(512*1024*1024));
135
136 /*
137 ** I/O addresses are mapped at internal PCI specific address
138 ** as is described into the configuration bridge table.
139 ** These are changed to 0, to allow cards that have legacy
140 ** io such as vga to function correctly. We set the SH5 IOBAR to
141 ** 256K, which is a bit big as we can only have 64K of address space
142 */
143
144 SH5PCI_WRITE(IOBR,0x0);
145
146 pr_debug("PCI:Writing 0x%08x to IOBR\n",0);
147
148 /* Set up a 256K window. Totally pointless waste of address space */
149 SH5PCI_WRITE(IOBMR,0);
150 pr_debug("PCI:Writing 0x%08x to IOBMR\n",0);
151
152 /* The SH5 has a HUGE 256K I/O region, which breaks the PCI spec. Ideally,
153 * we would want to map the I/O region somewhere, but it is so big this is not
154 * that easy!
155 */
156 SH5PCI_WRITE(CSR_IBAR0,~0);
157 /* Set memory size value */
158 memSize = memory_end - memory_start;
159
160 /* Now we set up the mbars so the PCI bus can see the memory of the machine */
161 if (memSize < (1024 * 1024)) {
162 printk(KERN_ERR "PCISH5: Ridiculous memory size of 0x%x?\n", memSize);
163 return -EINVAL;
164 }
165
166 /* Set LSR 0 */
167 lsr0 = (memSize > (512 * 1024 * 1024)) ? 0x1ff00001 : ((r2p2(memSize) - 0x100000) | 0x1);
168 SH5PCI_WRITE(LSR0, lsr0);
169
170 pr_debug("PCI:Writing 0x%08x to LSR0\n",lsr0);
171
172 /* Set MBAR 0 */
173 SH5PCI_WRITE(CSR_MBAR0, memory_start);
174 SH5PCI_WRITE(LAR0, memory_start);
175
176 SH5PCI_WRITE(CSR_MBAR1,0);
177 SH5PCI_WRITE(LAR1,0);
178 SH5PCI_WRITE(LSR1,0);
179
180 pr_debug("PCI:Writing 0x%08llx to CSR_MBAR0\n",memory_start);
181 pr_debug("PCI:Writing 0x%08llx to LAR0\n",memory_start);
182
183 /* Enable the PCI interrupts on the device */
184 SH5PCI_WRITE(INTM, ~0);
185 SH5PCI_WRITE(AINTM, ~0);
186 SH5PCI_WRITE(PINTM, ~0);
187
188 pr_debug("Switching on all error interrupts\n");
189
190 return(0);
191}
192
193static int sh5pci_read(struct pci_bus *bus, unsigned int devfn, int where,
194 int size, u32 *val)
195{
196 SH5PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where));
197
198 switch (size) {
199 case 1:
200 *val = (u8)SH5PCI_READ_BYTE(PDR + (where & 3));
201 break;
202 case 2:
203 *val = (u16)SH5PCI_READ_SHORT(PDR + (where & 2));
204 break;
205 case 4:
206 *val = SH5PCI_READ(PDR);
207 break;
208 }
209
210 return PCIBIOS_SUCCESSFUL;
211}
212
213static int sh5pci_write(struct pci_bus *bus, unsigned int devfn, int where,
214 int size, u32 val)
215{
216 SH5PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where));
217
218 switch (size) {
219 case 1:
220 SH5PCI_WRITE_BYTE(PDR + (where & 3), (u8)val);
221 break;
222 case 2:
223 SH5PCI_WRITE_SHORT(PDR + (where & 2), (u16)val);
224 break;
225 case 4:
226 SH5PCI_WRITE(PDR, val);
227 break;
228 }
229
230 return PCIBIOS_SUCCESSFUL;
231}
232
233static struct pci_ops pci_config_ops = {
234 .read = sh5pci_read,
235 .write = sh5pci_write,
236};
237
238/* Everything hangs off this */
239static struct pci_bus *pci_root_bus;
240
241
242static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
243{
244 pr_debug("swizzle for dev %d on bus %d slot %d pin is %d\n",
245 dev->devfn,dev->bus->number, PCI_SLOT(dev->devfn),*pin);
246 return PCI_SLOT(dev->devfn);
247}
248
249static inline u8 bridge_swizzle(u8 pin, u8 slot)
250{
251 return (((pin-1) + slot) % 4) + 1;
252}
253
254u8 __init common_swizzle(struct pci_dev *dev, u8 *pinp)
255{
256 if (dev->bus->number != 0) {
257 u8 pin = *pinp;
258 do {
259 pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
260 /* Move up the chain of bridges. */
261 dev = dev->bus->self;
262 } while (dev->bus->self);
263 *pinp = pin;
264
265 /* The slot is the slot of the last bridge. */
266 }
267
268 return PCI_SLOT(dev->devfn);
269}
270
271/* This needs to be shunted out of here into the board specific bit */
272
273static int __init map_cayman_irq(struct pci_dev *dev, u8 slot, u8 pin)
274{
275 int result = -1;
276
277 /* The complication here is that the PCI IRQ lines from the Cayman's 2
278 5V slots get into the CPU via a different path from the IRQ lines
279 from the 3 3.3V slots. Thus, we have to detect whether the card's
280 interrupts go via the 5V or 3.3V path, i.e. the 'bridge swizzling'
281 at the point where we cross from 5V to 3.3V is not the normal case.
282
283 The added complication is that we don't know that the 5V slots are
284 always bus 2, because a card containing a PCI-PCI bridge may be
285 plugged into a 3.3V slot, and this changes the bus numbering.
286
287 Also, the Cayman has an intermediate PCI bus that goes a custom
288 expansion board header (and to the secondary bridge). This bus has
289 never been used in practice.
290
291 The 1ary onboard PCI-PCI bridge is device 3 on bus 0
292 The 2ary onboard PCI-PCI bridge is device 0 on the 2ary bus of the 1ary bridge.
293 */
294
295 struct slot_pin {
296 int slot;
297 int pin;
298 } path[4];
299 int i=0;
300
301 while (dev->bus->number > 0) {
302
303 slot = path[i].slot = PCI_SLOT(dev->devfn);
304 pin = path[i].pin = bridge_swizzle(pin, slot);
305 dev = dev->bus->self;
306 i++;
307 if (i > 3) panic("PCI path to root bus too long!\n");
308 }
309
310 slot = PCI_SLOT(dev->devfn);
311 /* This is the slot on bus 0 through which the device is eventually
312 reachable. */
313
314 /* Now work back up. */
315 if ((slot < 3) || (i == 0)) {
316 /* Bus 0 (incl. PCI-PCI bridge itself) : perform the final
317 swizzle now. */
318 result = IRQ_INTA + bridge_swizzle(pin, slot) - 1;
319 } else {
320 i--;
321 slot = path[i].slot;
322 pin = path[i].pin;
323 if (slot > 0) {
324 panic("PCI expansion bus device found - not handled!\n");
325 } else {
326 if (i > 0) {
327 /* 5V slots */
328 i--;
329 slot = path[i].slot;
330 pin = path[i].pin;
331 /* 'pin' was swizzled earlier wrt slot, don't do it again. */
332 result = IRQ_P2INTA + (pin - 1);
333 } else {
334 /* IRQ for 2ary PCI-PCI bridge : unused */
335 result = -1;
336 }
337 }
338 }
339
340 return result;
341}
342
343irqreturn_t pcish5_err_irq(int irq, void *dev_id, struct pt_regs *regs)
344{
345 unsigned pci_int, pci_air, pci_cir, pci_aint;
346
347 pci_int = SH5PCI_READ(INT);
348 pci_cir = SH5PCI_READ(CIR);
349 pci_air = SH5PCI_READ(AIR);
350
351 if (pci_int) {
352 printk("PCI INTERRUPT (at %08llx)!\n", regs->pc);
353 printk("PCI INT -> 0x%x\n", pci_int & 0xffff);
354 printk("PCI AIR -> 0x%x\n", pci_air);
355 printk("PCI CIR -> 0x%x\n", pci_cir);
356 SH5PCI_WRITE(INT, ~0);
357 }
358
359 pci_aint = SH5PCI_READ(AINT);
360 if (pci_aint) {
361 printk("PCI ARB INTERRUPT!\n");
362 printk("PCI AINT -> 0x%x\n", pci_aint);
363 printk("PCI AIR -> 0x%x\n", pci_air);
364 printk("PCI CIR -> 0x%x\n", pci_cir);
365 SH5PCI_WRITE(AINT, ~0);
366 }
367
368 return IRQ_HANDLED;
369}
370
371irqreturn_t pcish5_serr_irq(int irq, void *dev_id, struct pt_regs *regs)
372{
373 printk("SERR IRQ\n");
374
375 return IRQ_NONE;
376}
377
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378static void __init
379pcibios_size_bridge(struct pci_bus *bus, struct resource *ior,
380 struct resource *memr)
381{
382 struct resource io_res, mem_res;
383 struct pci_dev *dev;
384 struct pci_dev *bridge = bus->self;
385 struct list_head *ln;
386
387 if (!bridge)
388 return; /* host bridge, nothing to do */
389
390 /* set reasonable default locations for pcibios_align_resource */
391 io_res.start = PCIBIOS_MIN_IO;
392 mem_res.start = PCIBIOS_MIN_MEM;
393
394 io_res.end = io_res.start;
395 mem_res.end = mem_res.start;
396
397 /* Collect information about how our direct children are layed out. */
398 for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
399 int i;
400 dev = pci_dev_b(ln);
401
402 /* Skip bridges for now */
403 if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
404 continue;
405
406 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
407 struct resource res;
408 unsigned long size;
409
410 memcpy(&res, &dev->resource[i], sizeof(res));
411 size = res.end - res.start + 1;
412
413 if (res.flags & IORESOURCE_IO) {
414 res.start = io_res.end;
415 pcibios_align_resource(dev, &res, size, 0);
416 io_res.end = res.start + size;
417 } else if (res.flags & IORESOURCE_MEM) {
418 res.start = mem_res.end;
419 pcibios_align_resource(dev, &res, size, 0);
420 mem_res.end = res.start + size;
421 }
422 }
423 }
424
425 /* And for all of the subordinate busses. */
426 for (ln=bus->children.next; ln != &bus->children; ln=ln->next)
427 pcibios_size_bridge(pci_bus_b(ln), &io_res, &mem_res);
428
429 /* turn the ending locations into sizes (subtract start) */
430 io_res.end -= io_res.start;
431 mem_res.end -= mem_res.start;
432
433 /* Align the sizes up by bridge rules */
Milind Arun Choudhary47e77ee2007-05-14 08:24:59 +0900434 io_res.end = ALIGN(io_res.end, 4*1024) - 1;
435 mem_res.end = ALIGN(mem_res.end, 1*1024*1024) - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
437 /* Adjust the bridge's allocation requirements */
438 bridge->resource[0].end = bridge->resource[0].start + io_res.end;
439 bridge->resource[1].end = bridge->resource[1].start + mem_res.end;
440
441 bridge->resource[PCI_BRIDGE_RESOURCES].end =
442 bridge->resource[PCI_BRIDGE_RESOURCES].start + io_res.end;
443 bridge->resource[PCI_BRIDGE_RESOURCES+1].end =
444 bridge->resource[PCI_BRIDGE_RESOURCES+1].start + mem_res.end;
445
446 /* adjust parent's resource requirements */
447 if (ior) {
Milind Arun Choudhary47e77ee2007-05-14 08:24:59 +0900448 ior->end = ALIGN(ior->end, 4*1024);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 ior->end += io_res.end;
450 }
451
452 if (memr) {
Milind Arun Choudhary47e77ee2007-05-14 08:24:59 +0900453 memr->end = ALIGN(memr->end, 1*1024*1024);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 memr->end += mem_res.end;
455 }
456}
457
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458static void __init pcibios_size_bridges(void)
459{
460 struct resource io_res, mem_res;
461
462 memset(&io_res, 0, sizeof(io_res));
463 memset(&mem_res, 0, sizeof(mem_res));
464
465 pcibios_size_bridge(pci_root_bus, &io_res, &mem_res);
466}
467
468static int __init pcibios_init(void)
469{
470 if (request_irq(IRQ_ERR, pcish5_err_irq,
Thomas Gleixner5fb55ae2006-07-01 19:29:24 -0700471 IRQF_DISABLED, "PCI Error",NULL) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 printk(KERN_ERR "PCISH5: Cannot hook PCI_PERR interrupt\n");
473 return -EINVAL;
474 }
475
476 if (request_irq(IRQ_SERR, pcish5_serr_irq,
Thomas Gleixner5fb55ae2006-07-01 19:29:24 -0700477 IRQF_DISABLED, "PCI SERR interrupt", NULL) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 printk(KERN_ERR "PCISH5: Cannot hook PCI_SERR interrupt\n");
479 return -EINVAL;
480 }
481
482 /* The pci subsytem needs to know where memory is and how much
483 * of it there is. I've simply made these globals. A better mechanism
484 * is probably needed.
485 */
486 sh5pci_init(__pa(memory_start),
487 __pa(memory_end) - __pa(memory_start));
488
489 pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL);
490 pcibios_size_bridges();
491 pci_assign_unassigned_resources();
492 pci_fixup_irqs(no_swizzle, map_cayman_irq);
493
494 return 0;
495}
496
497subsys_initcall(pcibios_init);
498
499void __init pcibios_fixup_bus(struct pci_bus *bus)
500{
501 struct pci_dev *dev = bus->self;
502 int i;
503
504#if 1
505 if(dev) {
506 for(i=0; i<3; i++) {
507 bus->resource[i] =
508 &dev->resource[PCI_BRIDGE_RESOURCES+i];
509 bus->resource[i]->name = bus->name;
510 }
511 bus->resource[0]->flags |= IORESOURCE_IO;
512 bus->resource[1]->flags |= IORESOURCE_MEM;
513
514 /* For now, propagate host limits to the bus;
515 * we'll adjust them later. */
516
517#if 1
518 bus->resource[0]->end = 64*1024 - 1 ;
519 bus->resource[1]->end = PCIBIOS_MIN_MEM+(256*1024*1024)-1;
520 bus->resource[0]->start = PCIBIOS_MIN_IO;
521 bus->resource[1]->start = PCIBIOS_MIN_MEM;
522#else
523 bus->resource[0]->end = 0
524 bus->resource[1]->end = 0
525 bus->resource[0]->start =0
526 bus->resource[1]->start = 0;
527#endif
528 /* Turn off downstream PF memory address range by default */
529 bus->resource[2]->start = 1024*1024;
530 bus->resource[2]->end = bus->resource[2]->start - 1;
531 }
532#endif
533
534}
535