2 * Authors: Frank Rowand <frank_rowand@mvista.com>,
3 * Debbie Chu <debbie_chu@mvista.com>, or source@mvista.com
4 * Further modifications by Armin Kuster <akuster@mvista.com>
6 * 2000 (c) MontaVista, Software, Inc. This file is licensed under
7 * the terms of the GNU General Public License version 2. This program
8 * is licensed "as is" without any warranty of any kind, whether express
11 * Based on arch/ppc/kernel/indirect.c, Copyright (C) 1998 Gabriel Paubert.
14 #include <linux/pci.h>
16 #include <asm/system.h>
17 #include <asm/machdep.h>
18 #include <linux/init.h>
19 #include <linux/errno.h>
21 #include <asm/ibm4xx.h>
22 #include <asm/pci-bridge.h>
23 #include <asm/ibm_ocp_pci.h>
26 extern void bios_fixup(struct pci_controller
*, struct pcil0_regs
*);
27 extern int ppc405_map_irq(struct pci_dev
*dev
, unsigned char idsel
,
31 ppc405_pcibios_fixup_resources(struct pci_dev
*dev
)
34 unsigned long max_host_addr
;
35 unsigned long min_host_addr
;
39 * openbios puts some graphics cards in the same range as the host
40 * controller uses to map to SDRAM. Fix it.
44 max_host_addr
= PPC405_PCI_MEM_BASE
- 1;
46 for (i
= 0; i
< DEVICE_COUNT_RESOURCE
; i
++) {
47 res
= dev
->resource
+ i
;
50 if ((res
->flags
& IORESOURCE_MEM
) &&
51 (((res
->start
>= min_host_addr
)
52 && (res
->start
<= max_host_addr
))
53 || ((res
->end
>= min_host_addr
)
54 && (res
->end
<= max_host_addr
))
55 || ((res
->start
< min_host_addr
)
56 && (res
->end
> max_host_addr
))
60 /* force pcibios_assign_resources() to assign a new address */
61 res
->end
-= res
->start
;
68 ppc4xx_exclude_device(unsigned char bus
, unsigned char devfn
)
70 /* We prevent us from seeing ourselves to avoid having
71 * the kernel try to remap our BAR #1 and fuck up bus
72 * master from external PCI devices
74 return (bus
== 0 && devfn
== 0);
78 ppc4xx_find_bridges(void)
80 struct pci_controller
*hose_a
;
81 struct pcil0_regs
*pcip
;
82 unsigned int tmp_addr
;
83 unsigned int tmp_size
;
84 unsigned int reg_index
;
85 unsigned int new_pmm_max
= 0;
86 unsigned int new_pmm_min
= 0;
92 /* Setup PCI32 hose */
93 hose_a
= pcibios_alloc_controller();
96 setup_indirect_pci(hose_a
, PPC405_PCI_CONFIG_ADDR
,
97 PPC405_PCI_CONFIG_DATA
);
99 pcip
= ioremap(PPC4xx_PCI_LCFG_PADDR
, PAGE_SIZE
);
102 #if defined(CONFIG_BIOS_FIXUP)
103 bios_fixup(hose_a
, pcip
);
105 new_pmm_min
= 0xffffffff;
106 for (reg_index
= 0; reg_index
< 3; reg_index
++) {
107 tmp_size
= in_le32(&pcip
->pmm
[reg_index
].ma
); // mask & attrs
108 /* test the enable bit */
109 if ((tmp_size
& 0x1) == 0)
111 tmp_addr
= in_le32(&pcip
->pmm
[reg_index
].pcila
); // PCI addr
112 if (tmp_addr
< PPC405_PCI_PHY_MEM_BASE
) {
114 "Disabling mapping to PCI mem addr 0x%8.8x\n",
116 out_le32(&pcip
->pmm
[reg_index
].ma
, tmp_size
& ~1); // *_PMMOMA
119 tmp_addr
= in_le32(&pcip
->pmm
[reg_index
].la
); // *_PMMOLA
120 if (tmp_addr
< new_pmm_min
)
121 new_pmm_min
= tmp_addr
;
122 tmp_addr
= tmp_addr
+
123 (0xffffffff - (tmp_size
& 0xffffc000));
124 if (tmp_addr
> PPC405_PCI_UPPER_MEM
) {
125 new_pmm_max
= tmp_addr
; // PPC405_PCI_UPPER_MEM
127 new_pmm_max
= PPC405_PCI_UPPER_MEM
;
135 hose_a
->first_busno
= 0;
136 hose_a
->last_busno
= 0xff;
137 hose_a
->pci_mem_offset
= 0;
139 /* Setup bridge memory/IO ranges & resources
140 * TODO: Handle firmwares setting up a legacy ISA mem base
142 hose_a
->io_space
.start
= PPC405_PCI_LOWER_IO
;
143 hose_a
->io_space
.end
= PPC405_PCI_UPPER_IO
;
144 hose_a
->mem_space
.start
= new_pmm_min
;
145 hose_a
->mem_space
.end
= new_pmm_max
;
146 hose_a
->io_base_phys
= PPC405_PCI_PHY_IO_BASE
;
147 hose_a
->io_base_virt
= ioremap(hose_a
->io_base_phys
, 0x10000);
148 hose_a
->io_resource
.start
= 0;
149 hose_a
->io_resource
.end
= PPC405_PCI_UPPER_IO
- PPC405_PCI_LOWER_IO
;
150 hose_a
->io_resource
.flags
= IORESOURCE_IO
;
151 hose_a
->io_resource
.name
= "PCI I/O";
152 hose_a
->mem_resources
[0].start
= new_pmm_min
;
153 hose_a
->mem_resources
[0].end
= new_pmm_max
;
154 hose_a
->mem_resources
[0].flags
= IORESOURCE_MEM
;
155 hose_a
->mem_resources
[0].name
= "PCI Memory";
156 isa_io_base
= (int) hose_a
->io_base_virt
;
157 isa_mem_base
= 0; /* ISA not implemented */
158 ISA_DMA_THRESHOLD
= 0x00ffffff; /* ??? ISA not implemented */
160 /* Scan busses & initial setup by pci_auto */
161 hose_a
->last_busno
= pciauto_bus_scan(hose_a
, hose_a
->first_busno
);
162 hose_a
->last_busno
= 0;
165 ppc_md
.pcibios_fixup
= NULL
;
166 ppc_md
.pci_exclude_device
= ppc4xx_exclude_device
;
167 ppc_md
.pcibios_fixup_resources
= ppc405_pcibios_fixup_resources
;
168 ppc_md
.pci_swizzle
= common_swizzle
;
169 ppc_md
.pci_map_irq
= ppc405_map_irq
;