patch-2.1.115 linux/arch/ppc/kernel/pmac_pci.c

Next file: linux/arch/ppc/kernel/pmac_setup.c
Previous file: linux/arch/ppc/kernel/pci.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.114/linux/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c
@@ -12,7 +12,6 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -33,6 +32,7 @@
  */
 #define APPLE_VENDID	0x106b
 #define BANDIT_DEVID	1
+#define BANDIT_DEVID_2	8
 #define BANDIT_REVID	3
 
 #define BANDIT_DEVNUM	11
@@ -96,8 +96,10 @@
 	struct bridge_data *bp;
 
 	*val = 0xffff;
-	if (bus > max_bus || (bp = bridges[bus]) == 0 || (offset & 1) != 0)
+	if (bus > max_bus || (bp = bridges[bus]) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
+	if ((offset & 1) != 0)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
 	if (bus == bp->bus_number) {
 		if (dev_fn < (11 << 3))
 			return PCIBIOS_DEVICE_NOT_FOUND;
@@ -118,8 +120,10 @@
 	struct bridge_data *bp;
 
 	*val = 0xffffffff;
-	if (bus > max_bus || (bp = bridges[bus]) == 0 || (offset & 3) != 0)
+	if (bus > max_bus || (bp = bridges[bus]) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
+	if ((offset & 3) != 0)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
 	if (bus == bp->bus_number) {
 		if (dev_fn < (11 << 3))
 			return PCIBIOS_DEVICE_NOT_FOUND;
@@ -160,8 +164,10 @@
 {
 	struct bridge_data *bp;
 
-	if (bus > max_bus || (bp = bridges[bus]) == 0 || (offset & 1) != 0)
+	if (bus > max_bus || (bp = bridges[bus]) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
+	if ((offset & 1) != 0)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
 	if (bus == bp->bus_number) {
 		if (dev_fn < (11 << 3))
 			return PCIBIOS_DEVICE_NOT_FOUND;
@@ -181,8 +187,10 @@
 {
 	struct bridge_data *bp;
 
-	if (bus > max_bus || (bp = bridges[bus]) == 0 || (offset & 3) != 0)
+	if (bus > max_bus || (bp = bridges[bus]) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
+	if ((offset & 3) != 0)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
 	if (bus == bp->bus_number) {
 		if (dev_fn < (11 << 3))
 			return PCIBIOS_DEVICE_NOT_FOUND;
@@ -197,6 +205,92 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
+#define GRACKLE_CFA(b, d, o)	(0x80 | ((b) << 8) | ((d) << 16) \
+				 | (((o) & ~3) << 24))
+
+int grackle_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
+				     unsigned char offset, unsigned char *val)
+{
+	struct bridge_data *bp;
+
+	*val = 0xff;
+	if (bus > max_bus || (bp = bridges[bus]) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));
+	*val = in_8(bp->cfg_data + (offset & 3));
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int grackle_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
+				     unsigned char offset, unsigned short *val)
+{
+	struct bridge_data *bp;
+
+	*val = 0xffff;
+	if (bus > max_bus || (bp = bridges[bus]) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if ((offset & 1) != 0)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));
+	*val = in_le16((volatile unsigned short *)(bp->cfg_data + (offset&3)));
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int grackle_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
+				      unsigned char offset, unsigned int *val)
+{
+	struct bridge_data *bp;
+
+	*val = 0xffffffff;
+	if (bus > max_bus || (bp = bridges[bus]) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if ((offset & 3) != 0)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));
+	*val = in_le32((volatile unsigned int *)bp->cfg_data);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int grackle_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
+				      unsigned char offset, unsigned char val)
+{
+	struct bridge_data *bp;
+
+	if (bus > max_bus || (bp = bridges[bus]) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));
+	out_8(bp->cfg_data + (offset & 3), val);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int grackle_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
+				      unsigned char offset, unsigned short val)
+{
+	struct bridge_data *bp;
+
+	if (bus > max_bus || (bp = bridges[bus]) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if ((offset & 1) != 0)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));
+	out_le16((volatile unsigned short *)(bp->cfg_data + (offset&3)), val);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int grackle_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
+				    unsigned char offset, unsigned int val)
+{
+	struct bridge_data *bp;
+
+	if (bus > max_bus || (bp = bridges[bus]) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if ((offset & 1) != 0)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	out_be32(bp->cfg_addr, GRACKLE_CFA(bus, dev_fn, offset));
+	out_le32((volatile unsigned int *)bp->cfg_data, val);
+	return PCIBIOS_SUCCESSFUL;
+}
+
 /*
  * For a bandit bridge, turn on cache coherency if necessary.
  * N.B. we can't use pcibios_*_config_* here because bridges[]
@@ -211,7 +305,17 @@
 	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID);
 	udelay(2);
 	vendev = in_le32((volatile unsigned int *)bp->cfg_data);
-	if (vendev != (BANDIT_DEVID << 16) + APPLE_VENDID) {
+	if (vendev == (BANDIT_DEVID << 16) + APPLE_VENDID) {
+		/* read the revision id */
+		out_le32(bp->cfg_addr,
+			 (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID);
+		udelay(2);
+		rev = in_8(bp->cfg_data);
+		if (rev != BANDIT_REVID)
+			printk(KERN_WARNING
+			       "Unknown revision %d for bandit at %p\n",
+			       rev, bp->io_base);
+	} else if (vendev != (BANDIT_DEVID_2 << 16) + APPLE_VENDID) {
 		printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);
 		return;
 	}
@@ -246,6 +350,7 @@
 	max_bus = 0;
 	add_bridges(find_devices("bandit"), &mem_start);
 	add_bridges(find_devices("chaos"), &mem_start);
+	add_bridges(find_devices("pci"), &mem_start);
 	bridges = (struct bridge_data **) mem_start;
 	mem_start += (max_bus + 1) * sizeof(struct bridge_data *);
 	memset(bridges, 0, (max_bus + 1) * sizeof(struct bridge_data *));
@@ -256,6 +361,11 @@
 	return mem_start;
 }
 
+/*
+ * We assume that if we have a G3 powermac, we have one bridge called
+ * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise,
+ * if we have one or more bandit or chaos bridges, we don't have a MPC106.
+ */
 __initfunc(static void add_bridges(struct device_node *dev, unsigned long *mem_ptr))
 {
 	int *bus_range;
@@ -284,15 +394,22 @@
 		printk(" controlled by %s at %x\n", dev->name, addr->address);
 		bp = (struct bridge_data *) *mem_ptr;
 		*mem_ptr += sizeof(struct bridge_data);
-		bp->cfg_addr = (volatile unsigned int *)
-			ioremap(addr->address + 0x800000, 0x1000);
-		bp->cfg_data = (volatile unsigned char *)
-			ioremap(addr->address + 0xc00000, 0x1000);
-		bp->io_base = (void *) ioremap(addr->address, 0x10000);
-#ifdef CONFIG_PMAC
+		if (strcmp(dev->name, "pci") != 0) {
+			bp->cfg_addr = (volatile unsigned int *)
+				ioremap(addr->address + 0x800000, 0x1000);
+			bp->cfg_data = (volatile unsigned char *)
+				ioremap(addr->address + 0xc00000, 0x1000);
+			bp->io_base = (void *) ioremap(addr->address, 0x10000);
+		} else {
+			/* XXX */
+			bp->cfg_addr = (volatile unsigned int *)
+				ioremap(0xfec00000, 0x1000);
+			bp->cfg_data = (volatile unsigned char *)
+				ioremap(0xfee00000, 0x1000);
+			bp->io_base = (void *) ioremap(0xfe000000, 0x10000);
+		}
 		if (isa_io_base == 0)
 			isa_io_base = (unsigned long) bp->io_base;
-#endif
 		bp->bus_number = bus_range[0];
 		bp->max_bus = bus_range[1];
 		bp->next = bridge_list;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov