2 * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
3 * Copyright (C) 2003, 2004 Paul Mundt
4 * Copyright (C) 2004 Richard Curnow
6 * May be copied or modified under the terms of the GNU General Public
7 * License. See linux/COPYING for more information.
9 * Support functions for the SH5 PCI hardware.
12 #include <linux/config.h>
13 #include <linux/kernel.h>
14 #include <linux/rwsem.h>
15 #include <linux/smp.h>
16 #include <linux/smp_lock.h>
17 #include <linux/interrupt.h>
18 #include <linux/init.h>
19 #include <linux/errno.h>
20 #include <linux/pci.h>
21 #include <linux/delay.h>
22 #include <linux/types.h>
24 #include <linux/irq.h>
27 #include <asm/hardware.h>
30 static unsigned long pcicr_virt
;
31 unsigned long pciio_virt
;
33 static void __init
pci_fixup_ide_bases(struct pci_dev
*d
)
38 * PCI IDE controllers use non-standard I/O port decoding, respect it.
40 if ((d
->class >> 8) != PCI_CLASS_STORAGE_IDE
)
42 printk("PCI: IDE base address fixup for %s\n", pci_name(d
));
44 struct resource
*r
= &d
->resource
[i
];
45 if ((r
->start
& ~0x80) == 0x374) {
51 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID
, PCI_ANY_ID
, pci_fixup_ide_bases
);
53 char * __init
pcibios_setup(char *str
)
58 /* Rounds a number UP to the nearest power of two. Used for
59 * sizing the PCI window.
61 static u32 __init
r2p2(u32 num
)
77 /* If the original number isn't a power of 2, round it up */
84 extern unsigned long long memory_start
, memory_end
;
86 int __init
sh5pci_init(unsigned memStart
, unsigned memSize
)
91 pcicr_virt
= onchip_remap(SH5PCI_ICR_BASE
, 1024, "PCICR");
93 panic("Unable to remap PCICR\n");
96 pciio_virt
= onchip_remap(SH5PCI_IO_BASE
, 0x10000, "PCIIO");
98 panic("Unable to remap PCIIO\n");
101 pr_debug("Register base addres is 0x%08lx\n", pcicr_virt
);
103 /* Clear snoop registers */
104 SH5PCI_WRITE(CSCR0
, 0);
105 SH5PCI_WRITE(CSCR1
, 0);
107 pr_debug("Wrote to reg\n");
109 /* Switch off interrupts */
110 SH5PCI_WRITE(INTM
, 0);
111 SH5PCI_WRITE(AINTM
, 0);
112 SH5PCI_WRITE(PINTM
, 0);
114 /* Set bus active, take it out of reset */
115 uval
= SH5PCI_READ(CR
);
117 /* Set command Register */
118 SH5PCI_WRITE(CR
, uval
| CR_LOCK_MASK
| CR_CFINT
| CR_FTO
| CR_PFE
| CR_PFCS
| CR_BMAM
);
120 uval
=SH5PCI_READ(CR
);
121 pr_debug("CR is actually 0x%08x\n",uval
);
123 /* Allow it to be a master */
124 /* NB - WE DISABLE I/O ACCESS to stop overlap */
125 /* set WAIT bit to enable stepping, an attempt to improve stability */
126 SH5PCI_WRITE_SHORT(CSR_CMD
,
127 PCI_COMMAND_MEMORY
| PCI_COMMAND_MASTER
| PCI_COMMAND_WAIT
);
130 ** Set translation mapping memory in order to convert the address
131 ** used for the main bus, to the PCI internal address.
133 SH5PCI_WRITE(MBR
,0x40000000);
135 /* Always set the max size 512M */
136 SH5PCI_WRITE(MBMR
, PCISH5_MEM_SIZCONV(512*1024*1024));
139 ** I/O addresses are mapped at internal PCI specific address
140 ** as is described into the configuration bridge table.
141 ** These are changed to 0, to allow cards that have legacy
142 ** io such as vga to function correctly. We set the SH5 IOBAR to
143 ** 256K, which is a bit big as we can only have 64K of address space
146 SH5PCI_WRITE(IOBR
,0x0);
148 pr_debug("PCI:Writing 0x%08x to IOBR\n",0);
150 /* Set up a 256K window. Totally pointless waste of address space */
151 SH5PCI_WRITE(IOBMR
,0);
152 pr_debug("PCI:Writing 0x%08x to IOBMR\n",0);
154 /* The SH5 has a HUGE 256K I/O region, which breaks the PCI spec. Ideally,
155 * we would want to map the I/O region somewhere, but it is so big this is not
158 SH5PCI_WRITE(CSR_IBAR0
,~0);
159 /* Set memory size value */
160 memSize
= memory_end
- memory_start
;
162 /* Now we set up the mbars so the PCI bus can see the memory of the machine */
163 if (memSize
< (1024 * 1024)) {
164 printk(KERN_ERR
"PCISH5: Ridiculous memory size of 0x%x?\n", memSize
);
169 lsr0
= (memSize
> (512 * 1024 * 1024)) ? 0x1ff00001 : ((r2p2(memSize
) - 0x100000) | 0x1);
170 SH5PCI_WRITE(LSR0
, lsr0
);
172 pr_debug("PCI:Writing 0x%08x to LSR0\n",lsr0
);
175 SH5PCI_WRITE(CSR_MBAR0
, memory_start
);
176 SH5PCI_WRITE(LAR0
, memory_start
);
178 SH5PCI_WRITE(CSR_MBAR1
,0);
179 SH5PCI_WRITE(LAR1
,0);
180 SH5PCI_WRITE(LSR1
,0);
182 pr_debug("PCI:Writing 0x%08llx to CSR_MBAR0\n",memory_start
);
183 pr_debug("PCI:Writing 0x%08llx to LAR0\n",memory_start
);
185 /* Enable the PCI interrupts on the device */
186 SH5PCI_WRITE(INTM
, ~0);
187 SH5PCI_WRITE(AINTM
, ~0);
188 SH5PCI_WRITE(PINTM
, ~0);
190 pr_debug("Switching on all error interrupts\n");
195 static int sh5pci_read(struct pci_bus
*bus
, unsigned int devfn
, int where
,
198 SH5PCI_WRITE(PAR
, CONFIG_CMD(bus
, devfn
, where
));
202 *val
= (u8
)SH5PCI_READ_BYTE(PDR
+ (where
& 3));
205 *val
= (u16
)SH5PCI_READ_SHORT(PDR
+ (where
& 2));
208 *val
= SH5PCI_READ(PDR
);
212 return PCIBIOS_SUCCESSFUL
;
215 static int sh5pci_write(struct pci_bus
*bus
, unsigned int devfn
, int where
,
218 SH5PCI_WRITE(PAR
, CONFIG_CMD(bus
, devfn
, where
));
222 SH5PCI_WRITE_BYTE(PDR
+ (where
& 3), (u8
)val
);
225 SH5PCI_WRITE_SHORT(PDR
+ (where
& 2), (u16
)val
);
228 SH5PCI_WRITE(PDR
, val
);
232 return PCIBIOS_SUCCESSFUL
;
235 static struct pci_ops pci_config_ops
= {
237 .write
= sh5pci_write
,
240 /* Everything hangs off this */
241 static struct pci_bus
*pci_root_bus
;
244 static u8 __init
no_swizzle(struct pci_dev
*dev
, u8
* pin
)
246 pr_debug("swizzle for dev %d on bus %d slot %d pin is %d\n",
247 dev
->devfn
,dev
->bus
->number
, PCI_SLOT(dev
->devfn
),*pin
);
248 return PCI_SLOT(dev
->devfn
);
251 static inline u8
bridge_swizzle(u8 pin
, u8 slot
)
253 return (((pin
-1) + slot
) % 4) + 1;
256 u8 __init
common_swizzle(struct pci_dev
*dev
, u8
*pinp
)
258 if (dev
->bus
->number
!= 0) {
261 pin
= bridge_swizzle(pin
, PCI_SLOT(dev
->devfn
));
262 /* Move up the chain of bridges. */
263 dev
= dev
->bus
->self
;
264 } while (dev
->bus
->self
);
267 /* The slot is the slot of the last bridge. */
270 return PCI_SLOT(dev
->devfn
);
273 /* This needs to be shunted out of here into the board specific bit */
275 static int __init
map_cayman_irq(struct pci_dev
*dev
, u8 slot
, u8 pin
)
279 /* The complication here is that the PCI IRQ lines from the Cayman's 2
280 5V slots get into the CPU via a different path from the IRQ lines
281 from the 3 3.3V slots. Thus, we have to detect whether the card's
282 interrupts go via the 5V or 3.3V path, i.e. the 'bridge swizzling'
283 at the point where we cross from 5V to 3.3V is not the normal case.
285 The added complication is that we don't know that the 5V slots are
286 always bus 2, because a card containing a PCI-PCI bridge may be
287 plugged into a 3.3V slot, and this changes the bus numbering.
289 Also, the Cayman has an intermediate PCI bus that goes a custom
290 expansion board header (and to the secondary bridge). This bus has
291 never been used in practice.
293 The 1ary onboard PCI-PCI bridge is device 3 on bus 0
294 The 2ary onboard PCI-PCI bridge is device 0 on the 2ary bus of the 1ary bridge.
303 while (dev
->bus
->number
> 0) {
305 slot
= path
[i
].slot
= PCI_SLOT(dev
->devfn
);
306 pin
= path
[i
].pin
= bridge_swizzle(pin
, slot
);
307 dev
= dev
->bus
->self
;
309 if (i
> 3) panic("PCI path to root bus too long!\n");
312 slot
= PCI_SLOT(dev
->devfn
);
313 /* This is the slot on bus 0 through which the device is eventually
316 /* Now work back up. */
317 if ((slot
< 3) || (i
== 0)) {
318 /* Bus 0 (incl. PCI-PCI bridge itself) : perform the final
320 result
= IRQ_INTA
+ bridge_swizzle(pin
, slot
) - 1;
326 panic("PCI expansion bus device found - not handled!\n");
333 /* 'pin' was swizzled earlier wrt slot, don't do it again. */
334 result
= IRQ_P2INTA
+ (pin
- 1);
336 /* IRQ for 2ary PCI-PCI bridge : unused */
345 irqreturn_t
pcish5_err_irq(int irq
, void *dev_id
, struct pt_regs
*regs
)
347 unsigned pci_int
, pci_air
, pci_cir
, pci_aint
;
349 pci_int
= SH5PCI_READ(INT
);
350 pci_cir
= SH5PCI_READ(CIR
);
351 pci_air
= SH5PCI_READ(AIR
);
354 printk("PCI INTERRUPT (at %08llx)!\n", regs
->pc
);
355 printk("PCI INT -> 0x%x\n", pci_int
& 0xffff);
356 printk("PCI AIR -> 0x%x\n", pci_air
);
357 printk("PCI CIR -> 0x%x\n", pci_cir
);
358 SH5PCI_WRITE(INT
, ~0);
361 pci_aint
= SH5PCI_READ(AINT
);
363 printk("PCI ARB INTERRUPT!\n");
364 printk("PCI AINT -> 0x%x\n", pci_aint
);
365 printk("PCI AIR -> 0x%x\n", pci_air
);
366 printk("PCI CIR -> 0x%x\n", pci_cir
);
367 SH5PCI_WRITE(AINT
, ~0);
373 irqreturn_t
pcish5_serr_irq(int irq
, void *dev_id
, struct pt_regs
*regs
)
375 printk("SERR IRQ\n");
380 #define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
383 pcibios_size_bridge(struct pci_bus
*bus
, struct resource
*ior
,
384 struct resource
*memr
)
386 struct resource io_res
, mem_res
;
388 struct pci_dev
*bridge
= bus
->self
;
389 struct list_head
*ln
;
392 return; /* host bridge, nothing to do */
394 /* set reasonable default locations for pcibios_align_resource */
395 io_res
.start
= PCIBIOS_MIN_IO
;
396 mem_res
.start
= PCIBIOS_MIN_MEM
;
398 io_res
.end
= io_res
.start
;
399 mem_res
.end
= mem_res
.start
;
401 /* Collect information about how our direct children are layed out. */
402 for (ln
=bus
->devices
.next
; ln
!= &bus
->devices
; ln
=ln
->next
) {
406 /* Skip bridges for now */
407 if (dev
->class >> 8 == PCI_CLASS_BRIDGE_PCI
)
410 for (i
= 0; i
< PCI_NUM_RESOURCES
; i
++) {
414 memcpy(&res
, &dev
->resource
[i
], sizeof(res
));
415 size
= res
.end
- res
.start
+ 1;
417 if (res
.flags
& IORESOURCE_IO
) {
418 res
.start
= io_res
.end
;
419 pcibios_align_resource(dev
, &res
, size
, 0);
420 io_res
.end
= res
.start
+ size
;
421 } else if (res
.flags
& IORESOURCE_MEM
) {
422 res
.start
= mem_res
.end
;
423 pcibios_align_resource(dev
, &res
, size
, 0);
424 mem_res
.end
= res
.start
+ size
;
429 /* And for all of the subordinate busses. */
430 for (ln
=bus
->children
.next
; ln
!= &bus
->children
; ln
=ln
->next
)
431 pcibios_size_bridge(pci_bus_b(ln
), &io_res
, &mem_res
);
433 /* turn the ending locations into sizes (subtract start) */
434 io_res
.end
-= io_res
.start
;
435 mem_res
.end
-= mem_res
.start
;
437 /* Align the sizes up by bridge rules */
438 io_res
.end
= ROUND_UP(io_res
.end
, 4*1024) - 1;
439 mem_res
.end
= ROUND_UP(mem_res
.end
, 1*1024*1024) - 1;
441 /* Adjust the bridge's allocation requirements */
442 bridge
->resource
[0].end
= bridge
->resource
[0].start
+ io_res
.end
;
443 bridge
->resource
[1].end
= bridge
->resource
[1].start
+ mem_res
.end
;
445 bridge
->resource
[PCI_BRIDGE_RESOURCES
].end
=
446 bridge
->resource
[PCI_BRIDGE_RESOURCES
].start
+ io_res
.end
;
447 bridge
->resource
[PCI_BRIDGE_RESOURCES
+1].end
=
448 bridge
->resource
[PCI_BRIDGE_RESOURCES
+1].start
+ mem_res
.end
;
450 /* adjust parent's resource requirements */
452 ior
->end
= ROUND_UP(ior
->end
, 4*1024);
453 ior
->end
+= io_res
.end
;
457 memr
->end
= ROUND_UP(memr
->end
, 1*1024*1024);
458 memr
->end
+= mem_res
.end
;
464 static void __init
pcibios_size_bridges(void)
466 struct resource io_res
, mem_res
;
468 memset(&io_res
, 0, sizeof(io_res
));
469 memset(&mem_res
, 0, sizeof(mem_res
));
471 pcibios_size_bridge(pci_root_bus
, &io_res
, &mem_res
);
474 static int __init
pcibios_init(void)
476 if (request_irq(IRQ_ERR
, pcish5_err_irq
,
477 SA_INTERRUPT
, "PCI Error",NULL
) < 0) {
478 printk(KERN_ERR
"PCISH5: Cannot hook PCI_PERR interrupt\n");
482 if (request_irq(IRQ_SERR
, pcish5_serr_irq
,
483 SA_INTERRUPT
, "PCI SERR interrupt", NULL
) < 0) {
484 printk(KERN_ERR
"PCISH5: Cannot hook PCI_SERR interrupt\n");
488 /* The pci subsytem needs to know where memory is and how much
489 * of it there is. I've simply made these globals. A better mechanism
490 * is probably needed.
492 sh5pci_init(__pa(memory_start
),
493 __pa(memory_end
) - __pa(memory_start
));
495 pci_root_bus
= pci_scan_bus(0, &pci_config_ops
, NULL
);
496 pcibios_size_bridges();
497 pci_assign_unassigned_resources();
498 pci_fixup_irqs(no_swizzle
, map_cayman_irq
);
503 subsys_initcall(pcibios_init
);
505 void __init
pcibios_fixup_bus(struct pci_bus
*bus
)
507 struct pci_dev
*dev
= bus
->self
;
514 &dev
->resource
[PCI_BRIDGE_RESOURCES
+i
];
515 bus
->resource
[i
]->name
= bus
->name
;
517 bus
->resource
[0]->flags
|= IORESOURCE_IO
;
518 bus
->resource
[1]->flags
|= IORESOURCE_MEM
;
520 /* For now, propagate host limits to the bus;
521 * we'll adjust them later. */
524 bus
->resource
[0]->end
= 64*1024 - 1 ;
525 bus
->resource
[1]->end
= PCIBIOS_MIN_MEM
+(256*1024*1024)-1;
526 bus
->resource
[0]->start
= PCIBIOS_MIN_IO
;
527 bus
->resource
[1]->start
= PCIBIOS_MIN_MEM
;
529 bus
->resource
[0]->end
= 0
530 bus
->resource
[1]->end
= 0
531 bus
->resource
[0]->start
=0
532 bus
->resource
[1]->start
= 0;
534 /* Turn off downstream PF memory address range by default */
535 bus
->resource
[2]->start
= 1024*1024;
536 bus
->resource
[2]->end
= bus
->resource
[2]->start
- 1;