From 2c847dc6482912e8c3c1483924acde706e496091 Mon Sep 17 00:00:00 2001
From: Florian Fainelli <florian@openwrt.org>
Date: Sun, 17 Jun 2007 14:04:15 +0000
Subject: [PATCH] New PCI fixup version, should better assign IRQs for boards,
 thanks Gabor !

SVN-Revision: 7654
---
 .../files/arch/mips/pci/fixup-adm5120.c       | 131 +++++++++++++++---
 1 file changed, 109 insertions(+), 22 deletions(-)

diff --git a/target/linux/adm5120-2.6/files/arch/mips/pci/fixup-adm5120.c b/target/linux/adm5120-2.6/files/arch/mips/pci/fixup-adm5120.c
index 07119ef3ad..e8389152b5 100644
--- a/target/linux/adm5120-2.6/files/arch/mips/pci/fixup-adm5120.c
+++ b/target/linux/adm5120-2.6/files/arch/mips/pci/fixup-adm5120.c
@@ -40,32 +40,62 @@
 #include <asm/mach-adm5120/adm5120_defs.h>
 #include <asm/mach-adm5120/adm5120_irq.h>
 
-static void adm5120_pci_fixup(struct pci_dev *dev)
-{
-	if (dev->devfn !=0)
-		return;
+struct adm5120_pci_irq {
+	u8	slot;
+	u8	func;
+	u8	pin;
+	unsigned irq;
+};
 
-	/* setup COMMAND register */
-	pci_write_config_word(dev, PCI_COMMAND, 
-		(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER));
+#define PCIIRQ(s,f,p,i) { 	\
+	.slot = (s),		\
+	.func = (f),		\
+	.pin  = (p),		\
+	.irq  = (i)		\
+	}
 
-	/* setup CACHE_LINE_SIZE register */
-	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 4);
+static struct adm5120_pci_irq default_pci_irqs[] __initdata = {
+	PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0),
+};
 
-	/* setting up BARS */
-	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0);
-	pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0);
-}
+static struct adm5120_pci_irq rb1xx_pci_irqs[] __initdata = {
+	PCIIRQ(1, 0, 1, ADM5120_IRQ_PCI0),
+	PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI1),
+	PCIIRQ(3, 0, 1, ADM5120_IRQ_PCI2)
+};
 
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ADMTEK, PCI_DEVICE_ID_ADMTEK_ADM5120, 
-	adm5120_pci_fixup);
+static struct adm5120_pci_irq cas771_pci_irqs[] __initdata = {
+	PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0),
+	PCIIRQ(3, 0, 1, ADM5120_IRQ_PCI1),
+	PCIIRQ(3, 2, 3, ADM5120_IRQ_PCI2)
+};
+
+static struct adm5120_pci_irq np28g_pci_irqs[] __initdata = {
+	PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0),
+	PCIIRQ(3, 0, 1, ADM5120_IRQ_PCI0),
+	PCIIRQ(3, 1, 2, ADM5120_IRQ_PCI1),
+	PCIIRQ(3, 2, 3, ADM5120_IRQ_PCI2)
+};
 
+#define GETMAP(n) do { 				\
+		nr_irqs = ARRAY_SIZE(n ## _pci_irqs); 	\
+		p = n ## _pci_irqs;			\
+	} while (0)
 
 int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
+	struct adm5120_pci_irq	*p;
+	int nr_irqs;
+	int i;
 	int irq;
 	
 	irq = -1;
+	if (slot < 1 || slot > 3) {
+		printk("PCI: slot number %u is not supported\n", slot);
+		goto out;
+	}
+	
+	GETMAP(default);
 
 	switch (mips_machtype) {
 	case MACH_ADM5120_RB_111:
@@ -73,21 +103,78 @@ int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 	case MACH_ADM5120_RB_133:
 	case MACH_ADM5120_RB_133C:
 	case MACH_ADM5120_RB_153:
-		if (slot > 0 && slot < 4)
-			irq = slot + 5;
+		GETMAP(rb1xx);
+		break;
+	case MACH_ADM5120_NP28G:
+		GETMAP(np28g);
+		break;
+	case MACH_ADM5120_P335:
+	case MACH_ADM5120_P334WT:
+		/* using default mapping */
 		break;
+#if 0
+	case MACH_ADM5120_CAS771:
+		GETMAP(cas771)
+		break;
+	case MACH_ADM5120_CAS630:
+	case MACH_ADM5120_CAS670:
+	case MACH_ADM5120_CAS700:
+	case MACH_ADM5120_CAS790:
+	case MACH_ADM5120_CAS861:
+#endif
+	case MACH_ADM5120_NP27G:
+	case MACH_ADM5120_NP28GHS:
+	case MACH_ADM5120_WP54AG:
+	case MACH_ADM5120_WP54G:
+	case MACH_ADM5120_WP54G_WRT:
+	case MACH_ADM5120_WPP54AG:
+	case MACH_ADM5120_WPP54G:
 	default:
-		if (slot > 1 && slot < 5)
-			irq = ADM5120_IRQ_PCI0+slot-1;
+		printk("PCI: irq map is unknown for %s, using defaults.\n",
+			adm5120_board_name());
 		break;
 	}
 	
-	printk(KERN_INFO "PCI: mapping irq for device %s, slot:%u, pin:%u, "
-		"irq:%d\n", pci_name(dev), slot, pin, irq);
-		
+	for (i=0; i<nr_irqs; i++, p++) {
+		if ((p->slot == slot) && (PCI_FUNC(dev->devfn) == p->func) && 
+		    (p->pin == pin)) {
+			irq = p->irq;
+			break;
+		}
+	}
+	
+	if (irq < 0) {
+		printk(KERN_INFO "PCI: no irq found for %s pin:%u\n",
+			pci_name(dev), pin);
+	} else {
+		printk(KERN_INFO "PCI: mapping irq for %s pin:%u, irq:%d\n",
+			pci_name(dev), pin, irq);		
+	}
+
+out:
 	return irq;
 }
 
+static void adm5120_pci_fixup(struct pci_dev *dev)
+{
+	if (dev->devfn != 0)
+		return;
+
+	/* setup COMMAND register */
+	pci_write_config_word(dev, PCI_COMMAND, 
+		(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER));
+
+	/* setup CACHE_LINE_SIZE register */
+	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 4);
+
+	/* setting up BARS */
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0);
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0);
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ADMTEK, PCI_DEVICE_ID_ADMTEK_ADM5120, 
+	adm5120_pci_fixup);
+
 int pcibios_plat_dev_init(struct pci_dev *dev)
 {
 	return 0;
-- 
2.30.2