2 * FILE NAME: ppc405_pci.c
4 * BRIEF MODULE DESCRIPTION:
5 * Based on arch/ppc/kernel/indirect.c, Copyright (C) 1998 Gabriel Paubert.
7 * Author: MontaVista Software, Inc. <source@mvista.com>
8 * Frank Rowand <frank_rowand@mvista.com>
9 * Debbie Chu <debbie_chu@mvista.com>
11 * Copyright 2000 MontaVista Software Inc.
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
21 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * You should have received a copy of the GNU General Public License along
30 * with this program; if not, write to the Free Software Foundation, Inc.,
31 * 675 Mass Ave, Cambridge, MA 02139, USA.
35 * converted to using ocp register & core_ocp[];
38 * change get_ocp_paddr to ocp_get_paddr
41 * added PSR_PCI_ARBIT_EN check , not all 4xx have a pin strap reg
44 #include <linux/pci.h>
46 #include <asm/system.h>
47 #include <asm/machdep.h>
48 #include <linux/init.h>
49 #include <linux/errno.h>
50 #include <asm/ibm4xx.h>
51 #include <asm/pci-bridge.h>
54 #ifdef CONFIG_DEBUG_BRINGUP
55 #define DBG(x...) printk(x)
60 extern void bios_fixup(struct pci_controller *, struct pcil0_regs *);
61 extern int ppc405_map_irq(struct pci_dev *dev, unsigned char idsel,
65 ppc405_pcibios_fixup_resources(struct pci_dev *dev)
68 unsigned long max_host_addr;
69 unsigned long min_host_addr;
73 * openbios puts some graphics cards in the same range as the host
74 * controller uses to map to SDRAM. Fix it.
78 max_host_addr = PPC405_PCI_MEM_BASE - 1;
80 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
81 res = dev->resource + i;
84 if ((res->flags & IORESOURCE_MEM) &&
85 (((res->start >= min_host_addr)
86 && (res->start <= max_host_addr))
87 || ((res->end >= min_host_addr)
88 && (res->end <= max_host_addr))
89 || ((res->start < min_host_addr)
90 && (res->end > max_host_addr))
94 DBG(KERN_ERR "PCI: 0x%lx <= resource[%d] <= 0x%lx"
95 ", bus 0x%x dev 0x%2.2x.%1.1x,\n"
97 KERN_ERR " fixup will be attempted later\n",
98 min_host_addr, i, max_host_addr,
99 dev->bus->number, PCI_SLOT(dev->devfn),
100 PCI_FUNC(dev->devfn), dev->name);
102 /* force pcibios_assign_resources() to assign a new address */
103 res->end -= res->start;
110 ppc4xx_exclude_device(unsigned char bus, unsigned char devfn)
112 /* We prevent us from seeing ourselves to avoid having
113 * the kernel try to remap our BAR #1 and fuck up bus
114 * master from external PCI devices
116 return (bus == 0 && devfn == 0);
120 ppc4xx_find_bridges(void)
122 struct pci_controller *hose_a;
123 struct pcil0_regs *pcip;
124 unsigned int tmp_addr;
125 unsigned int tmp_size;
126 unsigned int reg_index;
127 unsigned int new_pmm_max;
128 unsigned int new_pmm_min;
134 #if (PSR_PCI_ARBIT_EN > 1)
135 /* Check if running in slave mode */
136 if ((mfdcr(DCRN_CHPSR) & PSR_PCI_ARBIT_EN) == 0) {
137 printk("Running as PCI slave, kernel PCI disabled !\n");
141 /* Setup PCI32 hose */
142 hose_a = pcibios_alloc_controller();
145 setup_indirect_pci(hose_a, PPC405_PCI_CONFIG_ADDR,
146 PPC405_PCI_CONFIG_DATA);
148 pcip = ioremap((unsigned long) ocp_get_paddr(PCI, 0), PAGE_SIZE);
151 #if defined(CONFIG_BIOS_FIXUP)
152 bios_fixup(hose_a, pcip);
154 new_pmm_min = 0xffffffff;
155 for (reg_index = 0; reg_index < 3; reg_index++) {
156 tmp_size = in_le32((void *) &(pcip->pmm[reg_index].ma)); // *_PMM0MA
157 if (tmp_size & 0x1) {
158 tmp_addr = in_le32((void *) &(pcip->pmm[reg_index].pcila)); // *_PMM0PCILA
159 if (tmp_addr < PPC405_PCI_PHY_MEM_BASE) {
161 "Disabling mapping to PCI mem addr 0x%8.8x\n",
163 out_le32((void *) &(pcip->pmm[reg_index].ma), tmp_size & ~1); // *_PMMOMA
165 tmp_addr = in_le32((void *) &(pcip->pmm[reg_index].la)); // *_PMMOLA
166 if (tmp_addr < new_pmm_min)
167 new_pmm_min = tmp_addr;
169 tmp_addr + (0xffffffff -
172 if (tmp_addr > PPC405_PCI_UPPER_MEM) {
173 new_pmm_max = tmp_addr; // PPC405_PCI_UPPER_MEM
176 PPC405_PCI_UPPER_MEM;
186 hose_a->first_busno = 0;
187 hose_a->last_busno = 0xff;
188 hose_a->pci_mem_offset = 0;
190 /* Setup bridge memory/IO ranges & resources
191 * TODO: Handle firmwares setting up a legacy ISA mem base
193 hose_a->io_space.start = PPC405_PCI_LOWER_IO;
194 hose_a->io_space.end = PPC405_PCI_UPPER_IO;
195 hose_a->mem_space.start = new_pmm_min;
196 hose_a->mem_space.end = new_pmm_max;
197 hose_a->io_base_phys = PPC405_PCI_PHY_IO_BASE;
198 hose_a->io_base_virt = ioremap(hose_a->io_base_phys, 0x10000);
199 hose_a->io_resource.start = 0;
200 hose_a->io_resource.end = PPC405_PCI_UPPER_IO - PPC405_PCI_LOWER_IO;
201 hose_a->io_resource.flags = IORESOURCE_IO;
202 hose_a->io_resource.name = "PCI I/O";
203 hose_a->mem_resources[0].start = new_pmm_min;
204 hose_a->mem_resources[0].end = new_pmm_max;
205 hose_a->mem_resources[0].flags = IORESOURCE_MEM;
206 hose_a->mem_resources[0].name = "PCI Memory";
207 isa_io_base = (int) hose_a->io_base_virt;
208 isa_mem_base = 0; /* ISA not implemented */
209 ISA_DMA_THRESHOLD = 0x00ffffff; /* ??? ISA not implemented */
211 /* Scan busses & initial setup by pci_auto */
212 hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
213 hose_a->last_busno = 0;
216 ppc_md.pcibios_fixup = NULL;
217 ppc_md.pci_exclude_device = ppc4xx_exclude_device;
218 ppc_md.pcibios_fixup_resources = ppc405_pcibios_fixup_resources;
219 ppc_md.pci_swizzle = common_swizzle;
220 ppc_md.pci_map_irq = ppc405_map_irq;