New PCI fixup version, should better assign IRQs for boards, thanks Gabor !
[openwrt/svn-archive/archive.git] / target / linux / adm5120-2.6 / files / arch / mips / pci / fixup-adm5120.c
index 07119ef3adae0cc877ec7d2ab684578e1e191b03..e8389152b57c62d2d10aa42ff29bc5e4f6b64e97 100644 (file)
 #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;