patch-2.4.0-test2 linux/arch/ppc/kernel/chrp_pci.c
Next file: linux/arch/ppc/kernel/chrp_setup.c
Previous file: linux/arch/ppc/kernel/align.c
Back to the patch index
Back to the overall index
- Lines: 242
- Date:
Mon Jun 19 17:59:36 2000
- Orig file:
v2.4.0-test1/linux/arch/ppc/kernel/chrp_pci.c
- Orig date:
Tue May 23 15:31:34 2000
diff -u --recursive --new-file v2.4.0-test1/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c
@@ -2,6 +2,7 @@
* CHRP pci routines.
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/delay.h>
@@ -21,6 +22,10 @@
#include "pci.h"
+#ifdef CONFIG_POWER4
+static unsigned long pci_address_offset(int, unsigned int);
+#endif /* CONFIG_POWER4 */
+
/* LongTrail */
#define pci_config_addr(bus, dev, offset) \
(GG2_PCI_CONFIG_BASE | ((bus)<<16) | ((dev)<<8) | (offset))
@@ -172,8 +177,11 @@
unsigned char offset, unsigned char *val)
{
unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
- if ( call_rtas( "read-pci-config", 2, 2, (ulong *)&val, addr, 1 ) != 0 )
+ unsigned long ret;
+
+ if (call_rtas( "read-pci-config", 2, 2, &ret, addr, 1) != 0)
return PCIBIOS_DEVICE_NOT_FOUND;
+ *val = ret;
return PCIBIOS_SUCCESSFUL;
}
@@ -181,8 +189,11 @@
unsigned char offset, unsigned short *val)
{
unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
- if ( call_rtas( "read-pci-config", 2, 2, (ulong *)&val, addr, 2 ) != 0 )
+ unsigned long ret;
+
+ if (call_rtas("read-pci-config", 2, 2, &ret, addr, 2) != 0)
return PCIBIOS_DEVICE_NOT_FOUND;
+ *val = ret;
return PCIBIOS_SUCCESSFUL;
}
@@ -191,8 +202,11 @@
unsigned char offset, unsigned int *val)
{
unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
- if ( call_rtas( "read-pci-config", 2, 2, (ulong *)&val, addr, 4 ) != 0 )
+ unsigned long ret;
+
+ if (call_rtas("read-pci-config", 2, 2, &ret, addr, 4) != 0)
return PCIBIOS_DEVICE_NOT_FOUND;
+ *val = ret;
return PCIBIOS_SUCCESSFUL;
}
@@ -275,14 +289,33 @@
{
struct pci_dev *dev;
int i;
+ int *brp;
+ struct device_node *np;
extern struct pci_ops generic_pci_ops;
- /* Some IBM's with the python have >1 bus, this finds them */
- for ( i = 0; i < python_busnr ; i++ )
- pci_scan_bus(i+1, &generic_pci_ops, NULL);
+#ifndef CONFIG_POWER4
+ np = find_devices("device-tree");
+ if (np != 0) {
+ for (np = np->child; np != NULL; np = np->sibling) {
+ if (np->type == NULL || strcmp(np->type, "pci") != 0)
+ continue;
+ if ((brp = (int *) get_property(np, "bus-range", NULL)) == 0)
+ continue;
+ if (brp[0] != 0) /* bus 0 is already done */
+ pci_scan_bus(brp[0], &generic_pci_ops, NULL);
+ }
+ }
+#else
+ /* XXX kludge for now because we can't properly handle
+ physical addresses > 4GB. -- paulus */
+ pci_scan_bus(0x1e, &generic_pci_ops, NULL);
+#endif /* CONFIG_POWER4 */
/* PCI interrupts are controlled by the OpenPIC */
pci_for_each_dev(dev) {
+ np = find_pci_device_OFnode(dev->bus->number, dev->devfn);
+ if ( (np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0))
+ dev->irq = np->intrs[0].line;
if ( dev->irq )
dev->irq = openpic_to_irq( dev->irq );
/* these need to be absolute addrs for OF and Matrox FB -- Cort */
@@ -301,10 +334,30 @@
pcibios_write_config_word(dev->bus->number,
dev->devfn, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD);
}
- if ( (dev->bus->number > 0) &&
- ((dev->vendor == PCI_VENDOR_ID_NCR) ||
- (dev->vendor == PCI_VENDOR_ID_AMD)))
- dev->resource[0].start += (dev->bus->number*0x08000000);
+#ifdef CONFIG_POWER4
+ for (i = 0; i < 6; ++i) {
+ unsigned long offset;
+ if (dev->resource[i].start == 0)
+ continue;
+ offset = pci_address_offset(dev->bus->number,
+ dev->resource[i].flags);
+ if (offset) {
+ dev->resource[i].start += offset;
+ dev->resource[i].end += offset;
+ printk("device %x.%x[%d] now [%lx..%lx]\n",
+ dev->bus->number, dev->devfn, i,
+ dev->resource[i].start,
+ dev->resource[i].end);
+ }
+ /* zap the 2nd function of the winbond chip */
+ if (dev->resource[i].flags & IORESOURCE_IO
+ && dev->bus->number == 0 && dev->devfn == 0x81)
+ dev->resource[i].flags &= ~IORESOURCE_IO;
+ }
+#else
+ if (dev->bus->number > 0 && python_busnr > 0)
+ dev->resource[0].start += dev->bus->number*0x01000000;
+#endif
}
}
@@ -316,7 +369,11 @@
chrp_setup_pci_ptrs(void)
{
struct device_node *py;
-
+
+#ifdef CONFIG_POWER4
+ set_config_access_method(rtas);
+ pci_dram_offset = 0;
+#else /* CONFIG_POWER4 */
if ( !strncmp("MOT",
get_property(find_path_device("/"), "model", NULL),3) )
{
@@ -327,23 +384,27 @@
}
else
{
- if ( (py = find_compatible_devices( "pci", "IBM,python" )) )
+ if ((py = find_compatible_devices("pci", "IBM,python")) != 0
+ || (py = find_compatible_devices("pci", "IBM,python3.0")) != 0)
{
+ char *name = get_property(find_path_device("/"), "name", NULL);
+
/* find out how many pythons */
while ( (py = py->next) ) python_busnr++;
set_config_access_method(python);
+
/*
* We base these values on the machine type but should
* try to read them from the python controller itself.
* -- Cort
*/
- if ( !strncmp("IBM,7025-F50", get_property(find_path_device("/"), "name", NULL),12) )
+ if ( !strncmp("IBM,7025-F50", name, 12) )
{
pci_dram_offset = 0x80000000;
isa_mem_base = 0xa0000000;
isa_io_base = 0x88000000;
- } else if ( !strncmp("IBM,7043-260",
- get_property(find_path_device("/"), "name", NULL),12) )
+ } else if ( !strncmp("IBM,7043-260", name, 12)
+ || !strncmp("IBM,7044-270", name, 12))
{
pci_dram_offset = 0x0;
isa_mem_base = 0xc0000000;
@@ -372,6 +433,66 @@
}
}
}
+#endif /* CONFIG_POWER4 */
ppc_md.pcibios_fixup = chrp_pcibios_fixup;
}
+
+#ifdef CONFIG_PPC64BRIDGE
+/*
+ * Hack alert!!!
+ * 64-bit machines like POWER3 and POWER4 have > 32 bit
+ * physical addresses. For now we remap particular parts
+ * of the 32-bit physical address space that the Linux
+ * page table gives us into parts of the physical address
+ * space above 4GB so we can access the I/O devices.
+ */
+
+#ifdef CONFIG_POWER4
+static unsigned long pci_address_offset(int busnr, unsigned int flags)
+{
+ unsigned long offset = 0;
+
+ if (busnr >= 0x1e) {
+ if (flags & IORESOURCE_IO)
+ offset = -0x100000;
+ else if (flags & IORESOURCE_MEM)
+ offset = 0x38000000;
+ } else if (busnr <= 0xf) {
+ if (flags & IORESOURCE_MEM)
+ offset = -0x40000000;
+ else
+ }
+ return offset;
+}
+
+unsigned long phys_to_bus(unsigned long pa)
+{
+ if (pa >= 0xf8000000)
+ pa -= 0x38000000;
+ else if (pa >= 0x80000000 && pa < 0xc0000000)
+ pa += 0x40000000;
+ return pa;
+}
+
+unsigned long bus_to_phys(unsigned int ba, int busnr)
+{
+ return ba + pci_address_offset(busnr, IORESOURCE_MEM);
+}
+
+#else /* CONFIG_POWER4 */
+/*
+ * For now assume I/O addresses are < 4GB and PCI bridges don't
+ * remap addresses on POWER3 machines.
+ */
+unsigned long phys_to_bus(unsigned long pa)
+{
+ return pa;
+}
+
+unsigned long bus_to_phys(unsigned int ba, int busnr)
+{
+ return ba;
+}
+#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_PPC64BRIDGE */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)