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 #if (PSR_PCI_ARBIT_EN > 1)
93 /* Check if running in slave mode */
94 if ((mfdcr(DCRN_CHPSR
) & PSR_PCI_ARBIT_EN
) == 0) {
95 printk("Running as PCI slave, kernel PCI disabled !\n");
99 /* Setup PCI32 hose */
100 hose_a
= pcibios_alloc_controller();
103 setup_indirect_pci(hose_a
, PPC405_PCI_CONFIG_ADDR
,
104 PPC405_PCI_CONFIG_DATA
);
106 pcip
= ioremap(PPC4xx_PCI_LCFG_PADDR
, PAGE_SIZE
);
109 #if defined(CONFIG_BIOS_FIXUP)
110 bios_fixup(hose_a
, pcip
);
112 new_pmm_min
= 0xffffffff;
113 for (reg_index
= 0; reg_index
< 3; reg_index
++) {
114 tmp_size
= in_le32(&pcip
->pmm
[reg_index
].ma
); // mask & attrs
115 /* test the enable bit */
116 if ((tmp_size
& 0x1) == 0)
118 tmp_addr
= in_le32(&pcip
->pmm
[reg_index
].pcila
); // PCI addr
119 if (tmp_addr
< PPC405_PCI_PHY_MEM_BASE
) {
121 "Disabling mapping to PCI mem addr 0x%8.8x\n",
123 out_le32(&pcip
->pmm
[reg_index
].ma
, tmp_size
& ~1); // *_PMMOMA
126 tmp_addr
= in_le32(&pcip
->pmm
[reg_index
].la
); // *_PMMOLA
127 if (tmp_addr
< new_pmm_min
)
128 new_pmm_min
= tmp_addr
;
129 tmp_addr
= tmp_addr
+
130 (0xffffffff - (tmp_size
& 0xffffc000));
131 if (tmp_addr
> PPC405_PCI_UPPER_MEM
) {
132 new_pmm_max
= tmp_addr
; // PPC405_PCI_UPPER_MEM
134 new_pmm_max
= PPC405_PCI_UPPER_MEM
;
142 hose_a
->first_busno
= 0;
143 hose_a
->last_busno
= 0xff;
144 hose_a
->pci_mem_offset
= 0;
146 /* Setup bridge memory/IO ranges & resources
147 * TODO: Handle firmwares setting up a legacy ISA mem base
149 hose_a
->io_space
.start
= PPC405_PCI_LOWER_IO
;
150 hose_a
->io_space
.end
= PPC405_PCI_UPPER_IO
;
151 hose_a
->mem_space
.start
= new_pmm_min
;
152 hose_a
->mem_space
.end
= new_pmm_max
;
153 hose_a
->io_base_phys
= PPC405_PCI_PHY_IO_BASE
;
154 hose_a
->io_base_virt
= ioremap(hose_a
->io_base_phys
, 0x10000);
155 hose_a
->io_resource
.start
= 0;
156 hose_a
->io_resource
.end
= PPC405_PCI_UPPER_IO
- PPC405_PCI_LOWER_IO
;
157 hose_a
->io_resource
.flags
= IORESOURCE_IO
;
158 hose_a
->io_resource
.name
= "PCI I/O";
159 hose_a
->mem_resources
[0].start
= new_pmm_min
;
160 hose_a
->mem_resources
[0].end
= new_pmm_max
;
161 hose_a
->mem_resources
[0].flags
= IORESOURCE_MEM
;
162 hose_a
->mem_resources
[0].name
= "PCI Memory";
163 isa_io_base
= (int) hose_a
->io_base_virt
;
164 isa_mem_base
= 0; /* ISA not implemented */
165 ISA_DMA_THRESHOLD
= 0x00ffffff; /* ??? ISA not implemented */
167 /* Scan busses & initial setup by pci_auto */
168 hose_a
->last_busno
= pciauto_bus_scan(hose_a
, hose_a
->first_busno
);
169 hose_a
->last_busno
= 0;
172 ppc_md
.pcibios_fixup
= NULL
;
173 ppc_md
.pci_exclude_device
= ppc4xx_exclude_device
;
174 ppc_md
.pcibios_fixup_resources
= ppc405_pcibios_fixup_resources
;
175 ppc_md
.pci_swizzle
= common_swizzle
;
176 ppc_md
.pci_map_irq
= ppc405_map_irq
;