I'm rewriting the Alchemy PCI driver to be a platform driver, and one thing that bugs me to no end is that for every PCI controller the same global pcibios_map_irq function is called. Instead I'd like to pass the per-board pci irq tables through platform data and provide a per-controller map_irq callback. This patch adds a maq_irq callback to struct pci_controller, and uses it if available in pcibios_init(). Run-tested on a DB1500 board. Comments welcome! Signed-off-by: Manuel Lauss <manuel.lauss@xxxxxxxxxxxxxx> --- Eventually I'd like to do this also with pcibios_plat_dev_init, which is unused except on octeon and SSB-bus BCM chips. arch/mips/alchemy/common/pci.c | 8 ++++++++ arch/mips/alchemy/devboards/db1x00/board_setup.c | 8 ++++---- arch/mips/include/asm/pci.h | 2 ++ arch/mips/pci/fixup-au1000.c | 4 +--- arch/mips/pci/pci.c | 9 ++++++--- 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/arch/mips/alchemy/common/pci.c b/arch/mips/alchemy/common/pci.c index 7866cf5..e7bd034 100644 --- a/arch/mips/alchemy/common/pci.c +++ b/arch/mips/alchemy/common/pci.c @@ -53,10 +53,18 @@ static struct resource pci_mem_resource = { extern struct pci_ops au1x_pci_ops; +extern char irq_tab_alchemy[][5]; + +int alchemy_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + return irq_tab_alchemy[slot][pin]; +} + static struct pci_controller au1x_controller = { .pci_ops = &au1x_pci_ops, .io_resource = &pci_io_resource, .mem_resource = &pci_mem_resource, + .map_irq = alchemy_pci_map_irq, }; #if defined(CONFIG_SOC_AU1500) || defined(CONFIG_SOC_AU1550) diff --git a/arch/mips/alchemy/devboards/db1x00/board_setup.c b/arch/mips/alchemy/devboards/db1x00/board_setup.c index 5c956fe..8f6b926 100644 --- a/arch/mips/alchemy/devboards/db1x00/board_setup.c +++ b/arch/mips/alchemy/devboards/db1x00/board_setup.c @@ -41,7 +41,7 @@ #include <prom.h> #ifdef CONFIG_MIPS_DB1500 -char irq_tab_alchemy[][5] __initdata = { +char irq_tab_alchemy[][5] = { [12] = { -1, AU1500_PCI_INTA, 0xff, 0xff, 0xff }, /* IDSEL 12 - HPT371 */ [13] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, AU1500_PCI_INTC, AU1500_PCI_INTD }, /* IDSEL 13 - PCI slot */ }; @@ -50,7 +50,7 @@ char irq_tab_alchemy[][5] __initdata = { #ifdef CONFIG_MIPS_DB1550 -char irq_tab_alchemy[][5] __initdata = { +char irq_tab_alchemy[][5] = { [11] = { -1, AU1550_PCI_INTC, 0xff, 0xff, 0xff }, /* IDSEL 11 - on-board HPT371 */ [12] = { -1, AU1550_PCI_INTB, AU1550_PCI_INTC, AU1550_PCI_INTD, AU1550_PCI_INTA }, /* IDSEL 12 - PCI slot 2 (left) */ [13] = { -1, AU1550_PCI_INTA, AU1550_PCI_INTB, AU1550_PCI_INTC, AU1550_PCI_INTD }, /* IDSEL 13 - PCI slot 1 (right) */ @@ -59,7 +59,7 @@ char irq_tab_alchemy[][5] __initdata = { #ifdef CONFIG_MIPS_BOSPORUS -char irq_tab_alchemy[][5] __initdata = { +char irq_tab_alchemy[][5] = { [11] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, 0xff, 0xff }, /* IDSEL 11 - miniPCI */ [12] = { -1, AU1500_PCI_INTA, 0xff, 0xff, 0xff }, /* IDSEL 12 - SN1741 */ [13] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, AU1500_PCI_INTC, AU1500_PCI_INTD }, /* IDSEL 13 - PCI slot */ @@ -91,7 +91,7 @@ const char *get_system_type(void) #ifdef CONFIG_MIPS_MIRAGE -char irq_tab_alchemy[][5] __initdata = { +char irq_tab_alchemy[][5] = { [11] = { -1, AU1500_PCI_INTD, 0xff, 0xff, 0xff }, /* IDSEL 11 - SMI VGX */ [12] = { -1, 0xff, 0xff, AU1500_PCI_INTC, 0xff }, /* IDSEL 12 - PNX1300 */ [13] = { -1, AU1500_PCI_INTA, AU1500_PCI_INTB, 0xff, 0xff }, /* IDSEL 13 - miniPCI */ diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h index 576397c..a5d30ef 100644 --- a/arch/mips/include/asm/pci.h +++ b/arch/mips/include/asm/pci.h @@ -45,6 +45,8 @@ struct pci_controller { of the PCI controller */ int (*get_busno)(void); void (*set_busno)(int busno); + + int (*map_irq)(const struct pci_dev *dev, u8 slot, u8 pin); }; /* diff --git a/arch/mips/pci/fixup-au1000.c b/arch/mips/pci/fixup-au1000.c index e2ddfc4..448d8e5 100644 --- a/arch/mips/pci/fixup-au1000.c +++ b/arch/mips/pci/fixup-au1000.c @@ -29,11 +29,9 @@ #include <linux/pci.h> #include <linux/init.h> -extern char irq_tab_alchemy[][5]; - int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { - return irq_tab_alchemy[slot][pin]; + return -1; } /* Do platform specific device initialization at pci_enable_device() time */ diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 33bba7b..74f62e4 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -154,10 +154,13 @@ static int __init pcibios_init(void) struct pci_controller *hose; /* Scan all of the recorded PCI controllers. */ - for (hose = hose_head; hose; hose = hose->next) + for (hose = hose_head; hose; hose = hose->next) { pcibios_scanbus(hose); - - pci_fixup_irqs(pci_common_swizzle, pcibios_map_irq); + if (hose->map_irq) + pci_fixup_irqs(pci_common_swizzle, hose->map_irq); + else + pci_fixup_irqs(pci_common_swizzle, pcibios_map_irq); + } pci_initialized = 1; -- 1.7.6