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

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)