diff options
Diffstat (limited to 'arch/mips/pci')
59 files changed, 3005 insertions, 1356 deletions
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index ce995d3d944..ff8a5539b36 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -21,16 +21,16 @@ obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \ obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o - +obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o # # These are still pretty much in the old state, watch, go blind. # obj-$(CONFIG_LASAT) += pci-lasat.o obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o -obj-$(CONFIG_SOC_PNX8550) += fixup-pnx8550.o ops-pnx8550.o obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-loongson2.o obj-$(CONFIG_LEMOTE_MACH2F) += fixup-lemote2f.o ops-loongson2.o -obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o +obj-$(CONFIG_LEMOTE_MACH3A) += fixup-loongson3.o ops-loongson3.o +obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o pci-malta.o obj-$(CONFIG_PMC_MSP7120_GW) += fixup-pmcmsp.o ops-pmcmsp.o obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o obj-$(CONFIG_PMC_MSP7120_FPGA) += fixup-pmcmsp.o ops-pmcmsp.o @@ -42,6 +42,7 @@ obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o obj-$(CONFIG_LANTIQ) += fixup-lantiq.o obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o +obj-$(CONFIG_SOC_RT3883) += pci-rt3883.o obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o @@ -53,12 +54,12 @@ obj-$(CONFIG_TOSHIBA_RBTX4927) += fixup-rbtx4927.o obj-$(CONFIG_TOSHIBA_RBTX4938) += fixup-rbtx4938.o obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o -obj-$(CONFIG_WR_PPMC) += fixup-wrppmc.o obj-$(CONFIG_MIKROTIK_RB532) += pci-rc32434.o ops-rc32434.o fixup-rc32434.o -obj-$(CONFIG_CPU_CAVIUM_OCTEON) += pci-octeon.o pcie-octeon.o +obj-$(CONFIG_CAVIUM_OCTEON_SOC) += pci-octeon.o pcie-octeon.o obj-$(CONFIG_CPU_XLR) += pci-xlr.o obj-$(CONFIG_CPU_XLP) += pci-xlp.o ifdef CONFIG_PCI_MSI -obj-$(CONFIG_CPU_CAVIUM_OCTEON) += msi-octeon.o +obj-$(CONFIG_CAVIUM_OCTEON_SOC) += msi-octeon.o +obj-$(CONFIG_CPU_XLP) += msi-xlp.o endif diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c index 9553b14002d..a138e8ee5cf 100644 --- a/arch/mips/pci/fixup-cobalt.c +++ b/arch/mips/pci/fixup-cobalt.c @@ -94,14 +94,14 @@ static void qube_raq_galileo_fixup(struct pci_dev *dev) * --x--x--x--x--x--x--x--x--x--x--x--x--x--x--x--x--x--x--x--x-- * * On all machines prior to Q2, we had the STOP line disconnected - * from Galileo to VIA on PCI. The new Galileo does not function + * from Galileo to VIA on PCI. The new Galileo does not function * correctly unless we have it connected. * * Therefore we must set the disconnect/retry cycle values to * something sensible when using the new Galileo. */ - printk(KERN_INFO "Galileo: revision %u\n", dev->revision); + printk(KERN_INFO "Galileo: revision %u\n", dev->revision); #if 0 if (dev->revision >= 0x10) { @@ -149,30 +149,30 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, qube_raq_via_board_id_fixup); static char irq_tab_qube1[] __initdata = { - [COBALT_PCICONF_CPU] = 0, - [COBALT_PCICONF_ETH0] = QUBE1_ETH0_IRQ, + [COBALT_PCICONF_CPU] = 0, + [COBALT_PCICONF_ETH0] = QUBE1_ETH0_IRQ, [COBALT_PCICONF_RAQSCSI] = SCSI_IRQ, - [COBALT_PCICONF_VIA] = 0, + [COBALT_PCICONF_VIA] = 0, [COBALT_PCICONF_PCISLOT] = PCISLOT_IRQ, - [COBALT_PCICONF_ETH1] = 0 + [COBALT_PCICONF_ETH1] = 0 }; static char irq_tab_cobalt[] __initdata = { - [COBALT_PCICONF_CPU] = 0, - [COBALT_PCICONF_ETH0] = ETH0_IRQ, + [COBALT_PCICONF_CPU] = 0, + [COBALT_PCICONF_ETH0] = ETH0_IRQ, [COBALT_PCICONF_RAQSCSI] = SCSI_IRQ, - [COBALT_PCICONF_VIA] = 0, + [COBALT_PCICONF_VIA] = 0, [COBALT_PCICONF_PCISLOT] = PCISLOT_IRQ, - [COBALT_PCICONF_ETH1] = ETH1_IRQ + [COBALT_PCICONF_ETH1] = ETH1_IRQ }; static char irq_tab_raq2[] __initdata = { - [COBALT_PCICONF_CPU] = 0, - [COBALT_PCICONF_ETH0] = ETH0_IRQ, + [COBALT_PCICONF_CPU] = 0, + [COBALT_PCICONF_ETH0] = ETH0_IRQ, [COBALT_PCICONF_RAQSCSI] = RAQ2_SCSI_IRQ, - [COBALT_PCICONF_VIA] = 0, + [COBALT_PCICONF_VIA] = 0, [COBALT_PCICONF_PCISLOT] = PCISLOT_IRQ, - [COBALT_PCICONF_ETH1] = ETH1_IRQ + [COBALT_PCICONF_ETH1] = ETH1_IRQ }; int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) diff --git a/arch/mips/pci/fixup-emma2rh.c b/arch/mips/pci/fixup-emma2rh.c index beaec32b02e..19caf775c20 100644 --- a/arch/mips/pci/fixup-emma2rh.c +++ b/arch/mips/pci/fixup-emma2rh.c @@ -42,7 +42,7 @@ * */ -#define MAX_SLOT_NUM 10 +#define MAX_SLOT_NUM 10 static unsigned char irq_map[][5] __initdata = { [3] = {0, MARKEINS_PCI_IRQ_INTB, MARKEINS_PCI_IRQ_INTC, MARKEINS_PCI_IRQ_INTD, 0,}, diff --git a/arch/mips/pci/fixup-fuloong2e.c b/arch/mips/pci/fixup-fuloong2e.c index 63ab4a042cd..50da773faed 100644 --- a/arch/mips/pci/fixup-fuloong2e.c +++ b/arch/mips/pci/fixup-fuloong2e.c @@ -6,9 +6,9 @@ * Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology * Author: Fuxin Zhang, zhangfx@lemote.com * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ #include <linux/init.h> @@ -152,7 +152,7 @@ static void loongson2e_686b_func1_fixup(struct pci_dev *pdev) /* disable read prefetch/write post buffers */ pci_write_config_byte(pdev, 0x41, 0x02); - /* use 3/4 as fifo thresh hold */ + /* use 3/4 as fifo thresh hold */ pci_write_config_byte(pdev, 0x43, 0x0a); pci_write_config_byte(pdev, 0x44, 0x00); diff --git a/arch/mips/pci/fixup-ip32.c b/arch/mips/pci/fixup-ip32.c index 190fffd08d3..133685e215e 100644 --- a/arch/mips/pci/fixup-ip32.c +++ b/arch/mips/pci/fixup-ip32.c @@ -22,13 +22,13 @@ #define INTC MACEPCI_SHARED1_IRQ #define INTD MACEPCI_SHARED2_IRQ static char irq_tab_mace[][5] __initdata = { - /* Dummy INT#A INT#B INT#C INT#D */ - {0, 0, 0, 0, 0}, /* This is placeholder row - never used */ - {0, SCSI0, SCSI0, SCSI0, SCSI0}, - {0, SCSI1, SCSI1, SCSI1, SCSI1}, - {0, INTA0, INTB, INTC, INTD}, - {0, INTA1, INTC, INTD, INTB}, - {0, INTA2, INTD, INTB, INTC}, + /* Dummy INT#A INT#B INT#C INT#D */ + {0, 0, 0, 0, 0}, /* This is placeholder row - never used */ + {0, SCSI0, SCSI0, SCSI0, SCSI0}, + {0, SCSI1, SCSI1, SCSI1, SCSI1}, + {0, INTA0, INTB, INTC, INTD}, + {0, INTA1, INTC, INTD, INTB}, + {0, INTA2, INTD, INTB, INTC}, }; diff --git a/arch/mips/pci/fixup-lantiq.c b/arch/mips/pci/fixup-lantiq.c index 6c829df28dc..c2ce41ea61d 100644 --- a/arch/mips/pci/fixup-lantiq.c +++ b/arch/mips/pci/fixup-lantiq.c @@ -25,16 +25,5 @@ int pcibios_plat_dev_init(struct pci_dev *dev) int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { - struct of_irq dev_irq; - int irq; - - if (of_irq_map_pci(dev, &dev_irq)) { - dev_err(&dev->dev, "trying to map irq for unknown slot:%d pin:%d\n", - slot, pin); - return 0; - } - irq = irq_create_of_mapping(dev_irq.controller, dev_irq.specifier, - dev_irq.size); - dev_info(&dev->dev, "SLOT:%d PIN:%d IRQ:%d\n", slot, pin, irq); - return irq; + return of_irq_parse_and_map_pci(dev, slot, pin); } diff --git a/arch/mips/pci/fixup-lemote2f.c b/arch/mips/pci/fixup-lemote2f.c index 519daaebb5d..95ab9a1bd01 100644 --- a/arch/mips/pci/fixup-lemote2f.c +++ b/arch/mips/pci/fixup-lemote2f.c @@ -31,7 +31,7 @@ /* all the pci device has the PCIA pin, check the datasheet. */ static char irq_tab[][5] __initdata = { - /* INTA INTB INTC INTD */ + /* INTA INTB INTC INTD */ {0, 0, 0, 0, 0}, /* 11: Unused */ {0, 0, 0, 0, 0}, /* 12: Unused */ {0, 0, 0, 0, 0}, /* 13: Unused */ @@ -69,15 +69,15 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) case 2: pci_write_config_byte(dev, PCI_INTERRUPT_LINE, CS5536_IDE_INTR); - return CS5536_IDE_INTR; /* for IDE */ + return CS5536_IDE_INTR; /* for IDE */ case 3: pci_write_config_byte(dev, PCI_INTERRUPT_LINE, CS5536_ACC_INTR); - return CS5536_ACC_INTR; /* for AUDIO */ - case 4: /* for OHCI */ - case 5: /* for EHCI */ - case 6: /* for UDC */ - case 7: /* for OTG */ + return CS5536_ACC_INTR; /* for AUDIO */ + case 4: /* for OHCI */ + case 5: /* for EHCI */ + case 6: /* for UDC */ + case 7: /* for OTG */ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, CS5536_USB_INTR); return CS5536_USB_INTR; diff --git a/arch/mips/pci/fixup-loongson3.c b/arch/mips/pci/fixup-loongson3.c new file mode 100644 index 00000000000..d708ae46d32 --- /dev/null +++ b/arch/mips/pci/fixup-loongson3.c @@ -0,0 +1,66 @@ +/* + * fixup-loongson3.c + * + * Copyright (C) 2012 Lemote, Inc. + * Author: Xiang Yu, xiangy@lemote.com + * Chen Huacai, chenhc@lemote.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <linux/pci.h> +#include <boot_param.h> + +static void print_fixup_info(const struct pci_dev *pdev) +{ + dev_info(&pdev->dev, "Device %x:%x, irq %d\n", + pdev->vendor, pdev->device, pdev->irq); +} + +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + print_fixup_info(dev); + return dev->irq; +} + +static void pci_fixup_radeon(struct pci_dev *pdev) +{ + if (pdev->resource[PCI_ROM_RESOURCE].start) + return; + + if (!loongson_sysconf.vgabios_addr) + return; + + pdev->resource[PCI_ROM_RESOURCE].start = + loongson_sysconf.vgabios_addr; + pdev->resource[PCI_ROM_RESOURCE].end = + loongson_sysconf.vgabios_addr + 256*1024 - 1; + pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_COPY; + + dev_info(&pdev->dev, "BAR %d: assigned %pR for Radeon ROM\n", + PCI_ROM_RESOURCE, &pdev->resource[PCI_ROM_RESOURCE]); +} + +DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_ATI, PCI_ANY_ID, + PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_radeon); + +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} diff --git a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c index 75d03f6be3b..40e920c653c 100644 --- a/arch/mips/pci/fixup-malta.c +++ b/arch/mips/pci/fixup-malta.c @@ -1,5 +1,6 @@ #include <linux/init.h> #include <linux/pci.h> +#include <asm/mips-boards/piix4.h> /* PCI interrupt pins */ #define PCIA 1 @@ -12,7 +13,7 @@ static char pci_irq[5] = { }; static char irq_tab[][5] __initdata = { - /* INTA INTB INTC INTD */ + /* INTA INTB INTC INTD */ {0, 0, 0, 0, 0 }, /* 0: GT64120 PCI bridge */ {0, 0, 0, 0, 0 }, /* 1: Unused */ {0, 0, 0, 0, 0 }, /* 2: Unused */ @@ -23,7 +24,7 @@ static char irq_tab[][5] __initdata = { {0, 0, 0, 0, 0 }, /* 7: Unused */ {0, 0, 0, 0, 0 }, /* 8: Unused */ {0, 0, 0, 0, 0 }, /* 9: Unused */ - {0, 0, 0, 0, PCID }, /* 10: PIIX4 USB */ + {0, 0, 0, 0, PCID }, /* 10: PIIX4 USB */ {0, PCIB, 0, 0, 0 }, /* 11: AMD 79C973 Ethernet */ {0, PCIC, 0, 0, 0 }, /* 12: Crystal 4281 Sound */ {0, 0, 0, 0, 0 }, /* 13: Unused */ @@ -31,9 +32,9 @@ static char irq_tab[][5] __initdata = { {0, 0, 0, 0, 0 }, /* 15: Unused */ {0, 0, 0, 0, 0 }, /* 16: Unused */ {0, 0, 0, 0, 0 }, /* 17: Bonito/SOC-it PCI Bridge*/ - {0, PCIA, PCIB, PCIC, PCID }, /* 18: PCI Slot 1 */ - {0, PCIB, PCIC, PCID, PCIA }, /* 19: PCI Slot 2 */ - {0, PCIC, PCID, PCIA, PCIB }, /* 20: PCI Slot 3 */ + {0, PCIA, PCIB, PCIC, PCID }, /* 18: PCI Slot 1 */ + {0, PCIB, PCIC, PCID, PCIA }, /* 19: PCI Slot 2 */ + {0, PCIC, PCID, PCIA, PCIB }, /* 20: PCI Slot 3 */ {0, PCID, PCIA, PCIB, PCIC } /* 21: PCI Slot 4 */ }; @@ -50,12 +51,28 @@ int pcibios_plat_dev_init(struct pci_dev *dev) return 0; } +static void malta_piix_func3_base_fixup(struct pci_dev *dev) +{ + /* Set a sane PM I/O base address */ + pci_write_config_word(dev, PIIX4_FUNC3_PMBA, 0x1000); + + /* Enable access to the PM I/O region */ + pci_write_config_byte(dev, PIIX4_FUNC3_PMREGMISC, + PIIX4_FUNC3_PMREGMISC_EN); +} + +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, + malta_piix_func3_base_fixup); + static void malta_piix_func0_fixup(struct pci_dev *pdev) { unsigned char reg_val; - static int piixirqmap[16] = { /* PIIX PIRQC[A:D] irq mappings */ - 0, 0, 0, 3, - 4, 5, 6, 7, + u32 reg_val32; + u16 reg_val16; + /* PIIX PIRQC[A:D] irq mappings */ + static int piixirqmap[PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MAX] = { + 0, 0, 0, 3, + 4, 5, 6, 7, 0, 9, 10, 11, 12, 0, 14, 15 }; @@ -63,11 +80,12 @@ static void malta_piix_func0_fixup(struct pci_dev *pdev) /* Interrogate PIIX4 to get PCI IRQ mapping */ for (i = 0; i <= 3; i++) { - pci_read_config_byte(pdev, 0x60+i, ®_val); - if (reg_val & 0x80) + pci_read_config_byte(pdev, PIIX4_FUNC0_PIRQRC+i, ®_val); + if (reg_val & PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_DISABLE) pci_irq[PCIA+i] = 0; /* Disabled */ else - pci_irq[PCIA+i] = piixirqmap[reg_val & 15]; + pci_irq[PCIA+i] = piixirqmap[reg_val & + PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MASK]; } /* Done by YAMON 2.00 onwards */ @@ -76,9 +94,25 @@ static void malta_piix_func0_fixup(struct pci_dev *pdev) * Set top of main memory accessible by ISA or DMA * devices to 16 Mb. */ - pci_read_config_byte(pdev, 0x69, ®_val); - pci_write_config_byte(pdev, 0x69, reg_val | 0xf0); + pci_read_config_byte(pdev, PIIX4_FUNC0_TOM, ®_val); + pci_write_config_byte(pdev, PIIX4_FUNC0_TOM, reg_val | + PIIX4_FUNC0_TOM_TOP_OF_MEMORY_MASK); } + + /* Mux SERIRQ to its pin */ + pci_read_config_dword(pdev, PIIX4_FUNC0_GENCFG, ®_val32); + pci_write_config_dword(pdev, PIIX4_FUNC0_GENCFG, + reg_val32 | PIIX4_FUNC0_GENCFG_SERIRQ); + + /* Enable SERIRQ */ + pci_read_config_byte(pdev, PIIX4_FUNC0_SERIRQC, ®_val); + reg_val |= PIIX4_FUNC0_SERIRQC_EN | PIIX4_FUNC0_SERIRQC_CONT; + pci_write_config_byte(pdev, PIIX4_FUNC0_SERIRQC, reg_val); + + /* Enable response to special cycles */ + pci_read_config_word(pdev, PCI_COMMAND, ®_val16); + pci_write_config_word(pdev, PCI_COMMAND, + reg_val16 | PCI_COMMAND_SPECIAL); } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, @@ -93,10 +127,14 @@ static void malta_piix_func1_fixup(struct pci_dev *pdev) /* * IDE Decode enable. */ - pci_read_config_byte(pdev, 0x41, ®_val); - pci_write_config_byte(pdev, 0x41, reg_val|0x80); - pci_read_config_byte(pdev, 0x43, ®_val); - pci_write_config_byte(pdev, 0x43, reg_val|0x80); + pci_read_config_byte(pdev, PIIX4_FUNC1_IDETIM_PRIMARY_HI, + ®_val); + pci_write_config_byte(pdev, PIIX4_FUNC1_IDETIM_PRIMARY_HI, + reg_val|PIIX4_FUNC1_IDETIM_PRIMARY_HI_IDE_DECODE_EN); + pci_read_config_byte(pdev, PIIX4_FUNC1_IDETIM_SECONDARY_HI, + ®_val); + pci_write_config_byte(pdev, PIIX4_FUNC1_IDETIM_SECONDARY_HI, + reg_val|PIIX4_FUNC1_IDETIM_SECONDARY_HI_IDE_DECODE_EN); } } @@ -108,10 +146,12 @@ static void quirk_dlcsetup(struct pci_dev *dev) { u8 odlc, ndlc; - (void) pci_read_config_byte(dev, 0x82, &odlc); + (void) pci_read_config_byte(dev, PIIX4_FUNC0_DLC, &odlc); /* Enable passive releases and delayed transaction */ - ndlc = odlc | 7; - (void) pci_write_config_byte(dev, 0x82, ndlc); + ndlc = odlc | PIIX4_FUNC0_DLC_USBPR_EN | + PIIX4_FUNC0_DLC_PASSIVE_RELEASE_EN | + PIIX4_FUNC0_DLC_DELAYED_TRANSACTION_EN; + (void) pci_write_config_byte(dev, PIIX4_FUNC0_DLC, ndlc); } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, diff --git a/arch/mips/pci/fixup-pmcmsp.c b/arch/mips/pci/fixup-pmcmsp.c index 65735b1b766..fab405c21c2 100644 --- a/arch/mips/pci/fixup-pmcmsp.c +++ b/arch/mips/pci/fixup-pmcmsp.c @@ -48,117 +48,117 @@ #if defined(CONFIG_PMC_MSP7120_GW) /* Garibaldi Board IRQ wiring to PCI slots */ static char irq_tab[][5] __initdata = { - /* INTA INTB INTC INTD */ - {0, 0, 0, 0, 0 }, /* (AD[0]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[1]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[2]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[3]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[4]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[5]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[6]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[7]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[8]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[9]): Unused */ - {0, 0, 0, 0, 0 }, /* 0 (AD[10]): Unused */ - {0, 0, 0, 0, 0 }, /* 1 (AD[11]): Unused */ - {0, 0, 0, 0, 0 }, /* 2 (AD[12]): Unused */ - {0, 0, 0, 0, 0 }, /* 3 (AD[13]): Unused */ - {0, 0, 0, 0, 0 }, /* 4 (AD[14]): Unused */ - {0, 0, 0, 0, 0 }, /* 5 (AD[15]): Unused */ - {0, 0, 0, 0, 0 }, /* 6 (AD[16]): Unused */ - {0, 0, 0, 0, 0 }, /* 7 (AD[17]): Unused */ - {0, 0, 0, 0, 0 }, /* 8 (AD[18]): Unused */ - {0, 0, 0, 0, 0 }, /* 9 (AD[19]): Unused */ - {0, 0, 0, 0, 0 }, /* 10 (AD[20]): Unused */ - {0, 0, 0, 0, 0 }, /* 11 (AD[21]): Unused */ - {0, 0, 0, 0, 0 }, /* 12 (AD[22]): Unused */ - {0, 0, 0, 0, 0 }, /* 13 (AD[23]): Unused */ - {0, 0, 0, 0, 0 }, /* 14 (AD[24]): Unused */ - {0, 0, 0, 0, 0 }, /* 15 (AD[25]): Unused */ - {0, 0, 0, 0, 0 }, /* 16 (AD[26]): Unused */ - {0, 0, 0, 0, 0 }, /* 17 (AD[27]): Unused */ - {0, IRQ4, IRQ4, 0, 0 }, /* 18 (AD[28]): slot 0 */ - {0, 0, 0, 0, 0 }, /* 19 (AD[29]): Unused */ - {0, IRQ5, IRQ5, 0, 0 }, /* 20 (AD[30]): slot 1 */ - {0, IRQ6, IRQ6, 0, 0 } /* 21 (AD[31]): slot 2 */ + /* INTA INTB INTC INTD */ + {0, 0, 0, 0, 0 }, /* (AD[0]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[1]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[2]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[3]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[4]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[5]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[6]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[7]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[8]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[9]): Unused */ + {0, 0, 0, 0, 0 }, /* 0 (AD[10]): Unused */ + {0, 0, 0, 0, 0 }, /* 1 (AD[11]): Unused */ + {0, 0, 0, 0, 0 }, /* 2 (AD[12]): Unused */ + {0, 0, 0, 0, 0 }, /* 3 (AD[13]): Unused */ + {0, 0, 0, 0, 0 }, /* 4 (AD[14]): Unused */ + {0, 0, 0, 0, 0 }, /* 5 (AD[15]): Unused */ + {0, 0, 0, 0, 0 }, /* 6 (AD[16]): Unused */ + {0, 0, 0, 0, 0 }, /* 7 (AD[17]): Unused */ + {0, 0, 0, 0, 0 }, /* 8 (AD[18]): Unused */ + {0, 0, 0, 0, 0 }, /* 9 (AD[19]): Unused */ + {0, 0, 0, 0, 0 }, /* 10 (AD[20]): Unused */ + {0, 0, 0, 0, 0 }, /* 11 (AD[21]): Unused */ + {0, 0, 0, 0, 0 }, /* 12 (AD[22]): Unused */ + {0, 0, 0, 0, 0 }, /* 13 (AD[23]): Unused */ + {0, 0, 0, 0, 0 }, /* 14 (AD[24]): Unused */ + {0, 0, 0, 0, 0 }, /* 15 (AD[25]): Unused */ + {0, 0, 0, 0, 0 }, /* 16 (AD[26]): Unused */ + {0, 0, 0, 0, 0 }, /* 17 (AD[27]): Unused */ + {0, IRQ4, IRQ4, 0, 0 }, /* 18 (AD[28]): slot 0 */ + {0, 0, 0, 0, 0 }, /* 19 (AD[29]): Unused */ + {0, IRQ5, IRQ5, 0, 0 }, /* 20 (AD[30]): slot 1 */ + {0, IRQ6, IRQ6, 0, 0 } /* 21 (AD[31]): slot 2 */ }; #elif defined(CONFIG_PMC_MSP7120_EVAL) /* MSP7120 Eval Board IRQ wiring to PCI slots */ static char irq_tab[][5] __initdata = { - /* INTA INTB INTC INTD */ - {0, 0, 0, 0, 0 }, /* (AD[0]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[1]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[2]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[3]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[4]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[5]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[6]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[7]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[8]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[9]): Unused */ - {0, 0, 0, 0, 0 }, /* 0 (AD[10]): Unused */ - {0, 0, 0, 0, 0 }, /* 1 (AD[11]): Unused */ - {0, 0, 0, 0, 0 }, /* 2 (AD[12]): Unused */ - {0, 0, 0, 0, 0 }, /* 3 (AD[13]): Unused */ - {0, 0, 0, 0, 0 }, /* 4 (AD[14]): Unused */ - {0, 0, 0, 0, 0 }, /* 5 (AD[15]): Unused */ - {0, IRQ6, IRQ6, 0, 0 }, /* 6 (AD[16]): slot 3 (mini) */ - {0, IRQ5, IRQ5, 0, 0 }, /* 7 (AD[17]): slot 2 (mini) */ - {0, IRQ4, IRQ4, IRQ4, IRQ4}, /* 8 (AD[18]): slot 0 (PCI) */ - {0, IRQ5, IRQ5, IRQ5, IRQ5}, /* 9 (AD[19]): slot 1 (PCI) */ - {0, 0, 0, 0, 0 }, /* 10 (AD[20]): Unused */ - {0, 0, 0, 0, 0 }, /* 11 (AD[21]): Unused */ - {0, 0, 0, 0, 0 }, /* 12 (AD[22]): Unused */ - {0, 0, 0, 0, 0 }, /* 13 (AD[23]): Unused */ - {0, 0, 0, 0, 0 }, /* 14 (AD[24]): Unused */ - {0, 0, 0, 0, 0 }, /* 15 (AD[25]): Unused */ - {0, 0, 0, 0, 0 }, /* 16 (AD[26]): Unused */ - {0, 0, 0, 0, 0 }, /* 17 (AD[27]): Unused */ - {0, 0, 0, 0, 0 }, /* 18 (AD[28]): Unused */ - {0, 0, 0, 0, 0 }, /* 19 (AD[29]): Unused */ - {0, 0, 0, 0, 0 }, /* 20 (AD[30]): Unused */ - {0, 0, 0, 0, 0 } /* 21 (AD[31]): Unused */ + /* INTA INTB INTC INTD */ + {0, 0, 0, 0, 0 }, /* (AD[0]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[1]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[2]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[3]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[4]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[5]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[6]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[7]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[8]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[9]): Unused */ + {0, 0, 0, 0, 0 }, /* 0 (AD[10]): Unused */ + {0, 0, 0, 0, 0 }, /* 1 (AD[11]): Unused */ + {0, 0, 0, 0, 0 }, /* 2 (AD[12]): Unused */ + {0, 0, 0, 0, 0 }, /* 3 (AD[13]): Unused */ + {0, 0, 0, 0, 0 }, /* 4 (AD[14]): Unused */ + {0, 0, 0, 0, 0 }, /* 5 (AD[15]): Unused */ + {0, IRQ6, IRQ6, 0, 0 }, /* 6 (AD[16]): slot 3 (mini) */ + {0, IRQ5, IRQ5, 0, 0 }, /* 7 (AD[17]): slot 2 (mini) */ + {0, IRQ4, IRQ4, IRQ4, IRQ4}, /* 8 (AD[18]): slot 0 (PCI) */ + {0, IRQ5, IRQ5, IRQ5, IRQ5}, /* 9 (AD[19]): slot 1 (PCI) */ + {0, 0, 0, 0, 0 }, /* 10 (AD[20]): Unused */ + {0, 0, 0, 0, 0 }, /* 11 (AD[21]): Unused */ + {0, 0, 0, 0, 0 }, /* 12 (AD[22]): Unused */ + {0, 0, 0, 0, 0 }, /* 13 (AD[23]): Unused */ + {0, 0, 0, 0, 0 }, /* 14 (AD[24]): Unused */ + {0, 0, 0, 0, 0 }, /* 15 (AD[25]): Unused */ + {0, 0, 0, 0, 0 }, /* 16 (AD[26]): Unused */ + {0, 0, 0, 0, 0 }, /* 17 (AD[27]): Unused */ + {0, 0, 0, 0, 0 }, /* 18 (AD[28]): Unused */ + {0, 0, 0, 0, 0 }, /* 19 (AD[29]): Unused */ + {0, 0, 0, 0, 0 }, /* 20 (AD[30]): Unused */ + {0, 0, 0, 0, 0 } /* 21 (AD[31]): Unused */ }; #else /* Unknown board -- don't assign any IRQs */ static char irq_tab[][5] __initdata = { - /* INTA INTB INTC INTD */ - {0, 0, 0, 0, 0 }, /* (AD[0]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[1]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[2]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[3]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[4]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[5]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[6]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[7]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[8]): Unused */ - {0, 0, 0, 0, 0 }, /* (AD[9]): Unused */ - {0, 0, 0, 0, 0 }, /* 0 (AD[10]): Unused */ - {0, 0, 0, 0, 0 }, /* 1 (AD[11]): Unused */ - {0, 0, 0, 0, 0 }, /* 2 (AD[12]): Unused */ - {0, 0, 0, 0, 0 }, /* 3 (AD[13]): Unused */ - {0, 0, 0, 0, 0 }, /* 4 (AD[14]): Unused */ - {0, 0, 0, 0, 0 }, /* 5 (AD[15]): Unused */ - {0, 0, 0, 0, 0 }, /* 6 (AD[16]): Unused */ - {0, 0, 0, 0, 0 }, /* 7 (AD[17]): Unused */ - {0, 0, 0, 0, 0 }, /* 8 (AD[18]): Unused */ - {0, 0, 0, 0, 0 }, /* 9 (AD[19]): Unused */ - {0, 0, 0, 0, 0 }, /* 10 (AD[20]): Unused */ - {0, 0, 0, 0, 0 }, /* 11 (AD[21]): Unused */ - {0, 0, 0, 0, 0 }, /* 12 (AD[22]): Unused */ - {0, 0, 0, 0, 0 }, /* 13 (AD[23]): Unused */ - {0, 0, 0, 0, 0 }, /* 14 (AD[24]): Unused */ - {0, 0, 0, 0, 0 }, /* 15 (AD[25]): Unused */ - {0, 0, 0, 0, 0 }, /* 16 (AD[26]): Unused */ - {0, 0, 0, 0, 0 }, /* 17 (AD[27]): Unused */ - {0, 0, 0, 0, 0 }, /* 18 (AD[28]): Unused */ - {0, 0, 0, 0, 0 }, /* 19 (AD[29]): Unused */ - {0, 0, 0, 0, 0 }, /* 20 (AD[30]): Unused */ - {0, 0, 0, 0, 0 } /* 21 (AD[31]): Unused */ + /* INTA INTB INTC INTD */ + {0, 0, 0, 0, 0 }, /* (AD[0]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[1]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[2]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[3]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[4]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[5]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[6]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[7]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[8]): Unused */ + {0, 0, 0, 0, 0 }, /* (AD[9]): Unused */ + {0, 0, 0, 0, 0 }, /* 0 (AD[10]): Unused */ + {0, 0, 0, 0, 0 }, /* 1 (AD[11]): Unused */ + {0, 0, 0, 0, 0 }, /* 2 (AD[12]): Unused */ + {0, 0, 0, 0, 0 }, /* 3 (AD[13]): Unused */ + {0, 0, 0, 0, 0 }, /* 4 (AD[14]): Unused */ + {0, 0, 0, 0, 0 }, /* 5 (AD[15]): Unused */ + {0, 0, 0, 0, 0 }, /* 6 (AD[16]): Unused */ + {0, 0, 0, 0, 0 }, /* 7 (AD[17]): Unused */ + {0, 0, 0, 0, 0 }, /* 8 (AD[18]): Unused */ + {0, 0, 0, 0, 0 }, /* 9 (AD[19]): Unused */ + {0, 0, 0, 0, 0 }, /* 10 (AD[20]): Unused */ + {0, 0, 0, 0, 0 }, /* 11 (AD[21]): Unused */ + {0, 0, 0, 0, 0 }, /* 12 (AD[22]): Unused */ + {0, 0, 0, 0, 0 }, /* 13 (AD[23]): Unused */ + {0, 0, 0, 0, 0 }, /* 14 (AD[24]): Unused */ + {0, 0, 0, 0, 0 }, /* 15 (AD[25]): Unused */ + {0, 0, 0, 0, 0 }, /* 16 (AD[26]): Unused */ + {0, 0, 0, 0, 0 }, /* 17 (AD[27]): Unused */ + {0, 0, 0, 0, 0 }, /* 18 (AD[28]): Unused */ + {0, 0, 0, 0, 0 }, /* 19 (AD[29]): Unused */ + {0, 0, 0, 0, 0 }, /* 20 (AD[30]): Unused */ + {0, 0, 0, 0, 0 } /* 21 (AD[31]): Unused */ }; #endif @@ -168,14 +168,14 @@ static char irq_tab[][5] __initdata = { * _________________________________________________________________________ * * DESCRIPTION: Perform platform specific device initialization at - * pci_enable_device() time. - * None are needed for the MSP7120 PCI Controller. + * pci_enable_device() time. + * None are needed for the MSP7120 PCI Controller. * - * INPUTS: dev - structure describing the PCI device + * INPUTS: dev - structure describing the PCI device * - * OUTPUTS: none + * OUTPUTS: none * - * RETURNS: PCIBIOS_SUCCESSFUL + * RETURNS: PCIBIOS_SUCCESSFUL * ****************************************************************************/ int pcibios_plat_dev_init(struct pci_dev *dev) @@ -190,16 +190,16 @@ int pcibios_plat_dev_init(struct pci_dev *dev) * * DESCRIPTION: Perform board supplied PCI IRQ mapping routine. * - * INPUTS: dev - unused - * slot - PCI slot. Identified by which bit of the AD[] bus - * drives the IDSEL line. AD[10] is 0, AD[31] is - * slot 21. - * pin - numbered using the scheme of the PCI_INTERRUPT_PIN - * field of the config header. + * INPUTS: dev - unused + * slot - PCI slot. Identified by which bit of the AD[] bus + * drives the IDSEL line. AD[10] is 0, AD[31] is + * slot 21. + * pin - numbered using the scheme of the PCI_INTERRUPT_PIN + * field of the config header. * - * OUTPUTS: none + * OUTPUTS: none * - * RETURNS: IRQ number + * RETURNS: IRQ number * ****************************************************************************/ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) diff --git a/arch/mips/pci/fixup-pnx8550.c b/arch/mips/pci/fixup-pnx8550.c deleted file mode 100644 index 96857ac63bf..00000000000 --- a/arch/mips/pci/fixup-pnx8550.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Philips PNX8550 pci fixups. - * - * Copyright 2005 Embedded Alley Solutions, Inc - * source@embeddealley.com - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - */ -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/init.h> - -#include <asm/mach-pnx8550/pci.h> -#include <asm/mach-pnx8550/int.h> - - -#undef DEBUG -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -extern char pnx8550_irq_tab[][5]; - -void __init pcibios_fixup_resources(struct pci_dev *dev) -{ - /* no need to fixup IO resources */ -} - -void __init pcibios_fixup(void) -{ - /* nothing to do here */ -} - -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -{ - return pnx8550_irq_tab[slot][pin]; -} - -/* Do platform specific device initialization at pci_enable_device() time */ -int pcibios_plat_dev_init(struct pci_dev *dev) -{ - return 0; -} diff --git a/arch/mips/pci/fixup-rc32434.c b/arch/mips/pci/fixup-rc32434.c index d0f6ecbf35f..7fcafd5da7d 100644 --- a/arch/mips/pci/fixup-rc32434.c +++ b/arch/mips/pci/fixup-rc32434.c @@ -27,7 +27,6 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/kernel.h> -#include <linux/init.h> #include <asm/mach-rc32434/rc32434.h> #include <asm/mach-rc32434/irq.h> diff --git a/arch/mips/pci/fixup-sb1250.c b/arch/mips/pci/fixup-sb1250.c index 1441becdcb6..8feae9154ba 100644 --- a/arch/mips/pci/fixup-sb1250.c +++ b/arch/mips/pci/fixup-sb1250.c @@ -8,7 +8,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/init.h> #include <linux/pci.h> /* diff --git a/arch/mips/pci/fixup-sni.c b/arch/mips/pci/fixup-sni.c index 5c8a79bb266..f67ebeeb420 100644 --- a/arch/mips/pci/fixup-sni.c +++ b/arch/mips/pci/fixup-sni.c @@ -41,12 +41,12 @@ * Logic CL-GD5434 VGA is device 3. */ static char irq_tab_rm200[8][5] __initdata = { - /* INTA INTB INTC INTD */ - { 0, 0, 0, 0, 0 }, /* EISA bridge */ + /* INTA INTB INTC INTD */ + { 0, 0, 0, 0, 0 }, /* EISA bridge */ { SCSI, SCSI, SCSI, SCSI, SCSI }, /* SCSI */ - { ETH, ETH, ETH, ETH, ETH }, /* Ethernet */ + { ETH, ETH, ETH, ETH, ETH }, /* Ethernet */ { INTB, INTB, INTB, INTB, INTB }, /* VGA */ - { 0, 0, 0, 0, 0 }, /* Unused */ + { 0, 0, 0, 0, 0 }, /* Unused */ { 0, INTB, INTC, INTD, INTA }, /* Slot 2 */ { 0, INTC, INTD, INTA, INTB }, /* Slot 3 */ { 0, INTD, INTA, INTB, INTC }, /* Slot 4 */ @@ -58,20 +58,20 @@ static char irq_tab_rm200[8][5] __initdata = { * The VGA card is optional for RM300 systems. */ static char irq_tab_rm300d[8][5] __initdata = { - /* INTA INTB INTC INTD */ - { 0, 0, 0, 0, 0 }, /* EISA bridge */ + /* INTA INTB INTC INTD */ + { 0, 0, 0, 0, 0 }, /* EISA bridge */ { SCSI, SCSI, SCSI, SCSI, SCSI }, /* SCSI */ { 0, INTC, INTD, INTA, INTB }, /* Slot 1 */ { INTB, INTB, INTB, INTB, INTB }, /* VGA */ - { 0, 0, 0, 0, 0 }, /* Unused */ + { 0, 0, 0, 0, 0 }, /* Unused */ { 0, INTB, INTC, INTD, INTA }, /* Slot 2 */ { 0, INTC, INTD, INTA, INTB }, /* Slot 3 */ { 0, INTD, INTA, INTB, INTC }, /* Slot 4 */ }; static char irq_tab_rm300e[5][5] __initdata = { - /* INTA INTB INTC INTD */ - { 0, 0, 0, 0, 0 }, /* HOST bridge */ + /* INTA INTB INTC INTD */ + { 0, 0, 0, 0, 0 }, /* HOST bridge */ { SCSI, SCSI, SCSI, SCSI, SCSI }, /* SCSI */ { 0, INTC, INTD, INTA, INTB }, /* Bridge/i960 */ { 0, INTD, INTA, INTB, INTC }, /* Slot 1 */ @@ -97,30 +97,30 @@ static char irq_tab_rm300e[5][5] __initdata = { #define INTD PCIT_IRQ_INTD static char irq_tab_pcit[13][5] __initdata = { - /* INTA INTB INTC INTD */ - { 0, 0, 0, 0, 0 }, /* HOST bridge */ + /* INTA INTB INTC INTD */ + { 0, 0, 0, 0, 0 }, /* HOST bridge */ { SCSI0, SCSI0, SCSI0, SCSI0, SCSI0 }, /* SCSI */ { SCSI1, SCSI1, SCSI1, SCSI1, SCSI1 }, /* SCSI */ - { ETH, ETH, ETH, ETH, ETH }, /* Ethernet */ - { 0, INTA, INTB, INTC, INTD }, /* PCI-PCI bridge */ - { 0, 0, 0, 0, 0 }, /* Unused */ - { 0, 0, 0, 0, 0 }, /* Unused */ - { 0, 0, 0, 0, 0 }, /* Unused */ - { 0, INTA, INTB, INTC, INTD }, /* Slot 1 */ - { 0, INTB, INTC, INTD, INTA }, /* Slot 2 */ - { 0, INTC, INTD, INTA, INTB }, /* Slot 3 */ - { 0, INTD, INTA, INTB, INTC }, /* Slot 4 */ - { 0, INTA, INTB, INTC, INTD }, /* Slot 5 */ + { ETH, ETH, ETH, ETH, ETH }, /* Ethernet */ + { 0, INTA, INTB, INTC, INTD }, /* PCI-PCI bridge */ + { 0, 0, 0, 0, 0 }, /* Unused */ + { 0, 0, 0, 0, 0 }, /* Unused */ + { 0, 0, 0, 0, 0 }, /* Unused */ + { 0, INTA, INTB, INTC, INTD }, /* Slot 1 */ + { 0, INTB, INTC, INTD, INTA }, /* Slot 2 */ + { 0, INTC, INTD, INTA, INTB }, /* Slot 3 */ + { 0, INTD, INTA, INTB, INTC }, /* Slot 4 */ + { 0, INTA, INTB, INTC, INTD }, /* Slot 5 */ }; static char irq_tab_pcit_cplus[13][5] __initdata = { - /* INTA INTB INTC INTD */ - { 0, 0, 0, 0, 0 }, /* HOST bridge */ - { 0, INTB, INTC, INTD, INTA }, /* PCI Slot 9 */ - { 0, 0, 0, 0, 0 }, /* PCI-EISA */ - { 0, 0, 0, 0, 0 }, /* Unused */ - { 0, INTA, INTB, INTC, INTD }, /* PCI-PCI bridge */ - { 0, INTB, INTC, INTD, INTA }, /* fixup */ + /* INTA INTB INTC INTD */ + { 0, 0, 0, 0, 0 }, /* HOST bridge */ + { 0, INTB, INTC, INTD, INTA }, /* PCI Slot 9 */ + { 0, 0, 0, 0, 0 }, /* PCI-EISA */ + { 0, 0, 0, 0, 0 }, /* Unused */ + { 0, INTA, INTB, INTC, INTD }, /* PCI-PCI bridge */ + { 0, INTB, INTC, INTD, INTA }, /* fixup */ }; static inline int is_rm300_revd(void) @@ -146,18 +146,18 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) } return irq_tab_pcit_cplus[slot][pin]; case SNI_BRD_PCI_TOWER: - return irq_tab_pcit[slot][pin]; + return irq_tab_pcit[slot][pin]; case SNI_BRD_PCI_MTOWER: - if (is_rm300_revd()) - return irq_tab_rm300d[slot][pin]; - /* fall through */ + if (is_rm300_revd()) + return irq_tab_rm300d[slot][pin]; + /* fall through */ case SNI_BRD_PCI_DESKTOP: - return irq_tab_rm200[slot][pin]; + return irq_tab_rm200[slot][pin]; case SNI_BRD_PCI_MTOWER_CPLUS: - return irq_tab_rm300e[slot][pin]; + return irq_tab_rm300e[slot][pin]; } return 0; diff --git a/arch/mips/pci/fixup-tb0219.c b/arch/mips/pci/fixup-tb0219.c index 8084b17d440..d0b0083fbd2 100644 --- a/arch/mips/pci/fixup-tb0219.c +++ b/arch/mips/pci/fixup-tb0219.c @@ -1,7 +1,7 @@ /* * fixup-tb0219.c, The TANBAC TB0219 specific PCI fixups. * - * Copyright (C) 2003 Megasolution Inc. <matsu@megasolution.jp> + * Copyright (C) 2003 Megasolution Inc. <matsu@megasolution.jp> * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify diff --git a/arch/mips/pci/fixup-tb0287.c b/arch/mips/pci/fixup-tb0287.c index 2fe29db4372..8c5039ed75d 100644 --- a/arch/mips/pci/fixup-tb0287.c +++ b/arch/mips/pci/fixup-tb0287.c @@ -1,7 +1,7 @@ /* * fixup-tb0287.c, The TANBAC TB0287 specific PCI fixups. * - * Copyright (C) 2005 Yoichi Yuasa <yuasa@linux-mips.org> + * Copyright (C) 2005 Yoichi Yuasa <yuasa@linux-mips.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/arch/mips/pci/fixup-wrppmc.c b/arch/mips/pci/fixup-wrppmc.c deleted file mode 100644 index 3d277549d5d..00000000000 --- a/arch/mips/pci/fixup-wrppmc.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * fixup-wrppmc.c: PPMC board specific PCI fixup - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2006, Wind River Inc. Rongkai.zhan (rongkai.zhan@windriver.com) - */ -#include <linux/init.h> -#include <linux/pci.h> -#include <asm/gt64120.h> - -/* PCI interrupt pins */ -#define PCI_INTA 1 -#define PCI_INTB 2 -#define PCI_INTC 3 -#define PCI_INTD 4 - -#define PCI_SLOT_MAXNR 32 /* Each PCI bus has 32 physical slots */ - -static char pci_irq_tab[PCI_SLOT_MAXNR][5] __initdata = { - /* 0 INTA INTB INTC INTD */ - [0] = {0, 0, 0, 0, 0}, /* Slot 0: GT64120 PCI bridge */ - [6] = {0, WRPPMC_PCI_INTA_IRQ, 0, 0, 0}, -}; - -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -{ - return pci_irq_tab[slot][pin]; -} - -/* Do platform specific device initialization at pci_enable_device() time */ -int pcibios_plat_dev_init(struct pci_dev *dev) -{ - return 0; -} diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c index d37be36dc65..ab0c5d14c6f 100644 --- a/arch/mips/pci/msi-octeon.c +++ b/arch/mips/pci/msi-octeon.c @@ -15,6 +15,7 @@ #include <asm/octeon/cvmx-npi-defs.h> #include <asm/octeon/cvmx-pci-defs.h> #include <asm/octeon/cvmx-npei-defs.h> +#include <asm/octeon/cvmx-sli-defs.h> #include <asm/octeon/cvmx-pexp-defs.h> #include <asm/octeon/pci-octeon.h> @@ -150,6 +151,7 @@ msi_irq_allocated: msg.address_lo = ((128ul << 20) + CVMX_PCI_MSI_RCV) & 0xffffffff; msg.address_hi = ((128ul << 20) + CVMX_PCI_MSI_RCV) >> 32; + break; case OCTEON_DMA_BAR_TYPE_BIG: /* When using big bar, Bar 0 is based at 0 */ msg.address_lo = (0 + CVMX_PCI_MSI_RCV) & 0xffffffff; @@ -161,6 +163,11 @@ msi_irq_allocated: msg.address_lo = (0 + CVMX_NPEI_PCIE_MSI_RCV) & 0xffffffff; msg.address_hi = (0 + CVMX_NPEI_PCIE_MSI_RCV) >> 32; break; + case OCTEON_DMA_BAR_TYPE_PCIE2: + /* When using PCIe2, Bar 0 is based at 0 */ + msg.address_lo = (0 + CVMX_SLI_PCIE_MSI_RCV) & 0xffffffff; + msg.address_hi = (0 + CVMX_SLI_PCIE_MSI_RCV) >> 32; + break; default: panic("arch_setup_msi_irq: Invalid octeon_dma_bar_type"); } diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c new file mode 100644 index 00000000000..fa374fe3746 --- /dev/null +++ b/arch/mips/pci/msi-xlp.c @@ -0,0 +1,572 @@ +/* + * Copyright (c) 2003-2012 Broadcom Corporation + * All Rights Reserved + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the Broadcom + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/msi.h> +#include <linux/mm.h> +#include <linux/irq.h> +#include <linux/irqdesc.h> +#include <linux/console.h> + +#include <asm/io.h> + +#include <asm/netlogic/interrupt.h> +#include <asm/netlogic/haldefs.h> +#include <asm/netlogic/common.h> +#include <asm/netlogic/mips-extns.h> + +#include <asm/netlogic/xlp-hal/iomap.h> +#include <asm/netlogic/xlp-hal/xlp.h> +#include <asm/netlogic/xlp-hal/pic.h> +#include <asm/netlogic/xlp-hal/pcibus.h> +#include <asm/netlogic/xlp-hal/bridge.h> + +#define XLP_MSIVEC_PER_LINK 32 +#define XLP_MSIXVEC_TOTAL (cpu_is_xlp9xx() ? 128 : 32) +#define XLP_MSIXVEC_PER_LINK (cpu_is_xlp9xx() ? 32 : 8) + +/* 128 MSI irqs per node, mapped starting at NLM_MSI_VEC_BASE */ +static inline int nlm_link_msiirq(int link, int msivec) +{ + return NLM_MSI_VEC_BASE + link * XLP_MSIVEC_PER_LINK + msivec; +} + +/* get the link MSI vector from irq number */ +static inline int nlm_irq_msivec(int irq) +{ + return (irq - NLM_MSI_VEC_BASE) % XLP_MSIVEC_PER_LINK; +} + +/* get the link from the irq number */ +static inline int nlm_irq_msilink(int irq) +{ + int total_msivec = XLP_MSIVEC_PER_LINK * PCIE_NLINKS; + + return ((irq - NLM_MSI_VEC_BASE) % total_msivec) / + XLP_MSIVEC_PER_LINK; +} + +/* + * For XLP 8xx/4xx/3xx/2xx, only 32 MSI-X vectors are possible because + * there are only 32 PIC interrupts for MSI. We split them statically + * and use 8 MSI-X vectors per link - this keeps the allocation and + * lookup simple. + * On XLP 9xx, there are 32 vectors per link, and the interrupts are + * not routed thru PIC, so we can use all 128 MSI-X vectors. + */ +static inline int nlm_link_msixirq(int link, int bit) +{ + return NLM_MSIX_VEC_BASE + link * XLP_MSIXVEC_PER_LINK + bit; +} + +/* get the link MSI vector from irq number */ +static inline int nlm_irq_msixvec(int irq) +{ + return (irq - NLM_MSIX_VEC_BASE) % XLP_MSIXVEC_TOTAL; +} + +/* get the link from MSIX vec */ +static inline int nlm_irq_msixlink(int msixvec) +{ + return msixvec / XLP_MSIXVEC_PER_LINK; +} + +/* + * Per link MSI and MSI-X information, set as IRQ handler data for + * MSI and MSI-X interrupts. + */ +struct xlp_msi_data { + struct nlm_soc_info *node; + uint64_t lnkbase; + uint32_t msi_enabled_mask; + uint32_t msi_alloc_mask; + uint32_t msix_alloc_mask; + spinlock_t msi_lock; +}; + +/* + * MSI Chip definitions + * + * On XLP, there is a PIC interrupt associated with each PCIe link on the + * chip (which appears as a PCI bridge to us). This gives us 32 MSI irqa + * per link and 128 overall. + * + * When a device connected to the link raises a MSI interrupt, we get a + * link interrupt and we then have to look at PCIE_MSI_STATUS register at + * the bridge to map it to the IRQ + */ +static void xlp_msi_enable(struct irq_data *d) +{ + struct xlp_msi_data *md = irq_data_get_irq_handler_data(d); + unsigned long flags; + int vec; + + vec = nlm_irq_msivec(d->irq); + spin_lock_irqsave(&md->msi_lock, flags); + md->msi_enabled_mask |= 1u << vec; + if (cpu_is_xlp9xx()) + nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN, + md->msi_enabled_mask); + else + nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask); + spin_unlock_irqrestore(&md->msi_lock, flags); +} + +static void xlp_msi_disable(struct irq_data *d) +{ + struct xlp_msi_data *md = irq_data_get_irq_handler_data(d); + unsigned long flags; + int vec; + + vec = nlm_irq_msivec(d->irq); + spin_lock_irqsave(&md->msi_lock, flags); + md->msi_enabled_mask &= ~(1u << vec); + if (cpu_is_xlp9xx()) + nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN, + md->msi_enabled_mask); + else + nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask); + spin_unlock_irqrestore(&md->msi_lock, flags); +} + +static void xlp_msi_mask_ack(struct irq_data *d) +{ + struct xlp_msi_data *md = irq_data_get_irq_handler_data(d); + int link, vec; + + link = nlm_irq_msilink(d->irq); + vec = nlm_irq_msivec(d->irq); + xlp_msi_disable(d); + + /* Ack MSI on bridge */ + if (cpu_is_xlp9xx()) + nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_STATUS, 1u << vec); + else + nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec); + + /* Ack at eirr and PIC */ + ack_c0_eirr(PIC_PCIE_LINK_MSI_IRQ(link)); + if (cpu_is_xlp9xx()) + nlm_pic_ack(md->node->picbase, + PIC_9XX_IRT_PCIE_LINK_INDEX(link)); + else + nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link)); +} + +static struct irq_chip xlp_msi_chip = { + .name = "XLP-MSI", + .irq_enable = xlp_msi_enable, + .irq_disable = xlp_msi_disable, + .irq_mask_ack = xlp_msi_mask_ack, + .irq_unmask = xlp_msi_enable, +}; + +/* + * XLP8XX/4XX/3XX/2XX: + * The MSI-X interrupt handling is different from MSI, there are 32 MSI-X + * interrupts generated by the PIC and each of these correspond to a MSI-X + * vector (0-31) that can be assigned. + * + * We divide the MSI-X vectors to 8 per link and do a per-link allocation + * + * XLP9XX: + * 32 MSI-X vectors are available per link, and the interrupts are not routed + * thru the PIC. PIC ack not needed. + * + * Enable and disable done using standard MSI functions. + */ +static void xlp_msix_mask_ack(struct irq_data *d) +{ + struct xlp_msi_data *md; + int link, msixvec; + uint32_t status_reg, bit; + + msixvec = nlm_irq_msixvec(d->irq); + link = nlm_irq_msixlink(msixvec); + mask_msi_irq(d); + md = irq_data_get_irq_handler_data(d); + + /* Ack MSI on bridge */ + if (cpu_is_xlp9xx()) { + status_reg = PCIE_9XX_MSIX_STATUSX(link); + bit = msixvec % XLP_MSIXVEC_PER_LINK; + } else { + status_reg = PCIE_MSIX_STATUS; + bit = msixvec; + } + nlm_write_reg(md->lnkbase, status_reg, 1u << bit); + + /* Ack at eirr and PIC */ + ack_c0_eirr(PIC_PCIE_MSIX_IRQ(link)); + if (!cpu_is_xlp9xx()) + nlm_pic_ack(md->node->picbase, + PIC_IRT_PCIE_MSIX_INDEX(msixvec)); +} + +static struct irq_chip xlp_msix_chip = { + .name = "XLP-MSIX", + .irq_enable = unmask_msi_irq, + .irq_disable = mask_msi_irq, + .irq_mask_ack = xlp_msix_mask_ack, + .irq_unmask = unmask_msi_irq, +}; + +void arch_teardown_msi_irq(unsigned int irq) +{ +} + +/* + * Setup a PCIe link for MSI. By default, the links are in + * legacy interrupt mode. We will switch them to MSI mode + * at the first MSI request. + */ +static void xlp_config_link_msi(uint64_t lnkbase, int lirq, uint64_t msiaddr) +{ + u32 val; + + if (cpu_is_xlp9xx()) { + val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0); + if ((val & 0x200) == 0) { + val |= 0x200; /* MSI Interrupt enable */ + nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val); + } + } else { + val = nlm_read_reg(lnkbase, PCIE_INT_EN0); + if ((val & 0x200) == 0) { + val |= 0x200; + nlm_write_reg(lnkbase, PCIE_INT_EN0, val); + } + } + + val = nlm_read_reg(lnkbase, 0x1); /* CMD */ + if ((val & 0x0400) == 0) { + val |= 0x0400; + nlm_write_reg(lnkbase, 0x1, val); + } + + /* Update IRQ in the PCI irq reg */ + val = nlm_read_pci_reg(lnkbase, 0xf); + val &= ~0x1fu; + val |= (1 << 8) | lirq; + nlm_write_pci_reg(lnkbase, 0xf, val); + + /* MSI addr */ + nlm_write_reg(lnkbase, PCIE_BRIDGE_MSI_ADDRH, msiaddr >> 32); + nlm_write_reg(lnkbase, PCIE_BRIDGE_MSI_ADDRL, msiaddr & 0xffffffff); + + /* MSI cap for bridge */ + val = nlm_read_reg(lnkbase, PCIE_BRIDGE_MSI_CAP); + if ((val & (1 << 16)) == 0) { + val |= 0xb << 16; /* mmc32, msi enable */ + nlm_write_reg(lnkbase, PCIE_BRIDGE_MSI_CAP, val); + } +} + +/* + * Allocate a MSI vector on a link + */ +static int xlp_setup_msi(uint64_t lnkbase, int node, int link, + struct msi_desc *desc) +{ + struct xlp_msi_data *md; + struct msi_msg msg; + unsigned long flags; + int msivec, irt, lirq, xirq, ret; + uint64_t msiaddr; + + /* Get MSI data for the link */ + lirq = PIC_PCIE_LINK_MSI_IRQ(link); + xirq = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0)); + md = irq_get_handler_data(xirq); + msiaddr = MSI_LINK_ADDR(node, link); + + spin_lock_irqsave(&md->msi_lock, flags); + if (md->msi_alloc_mask == 0) { + xlp_config_link_msi(lnkbase, lirq, msiaddr); + /* switch the link IRQ to MSI range */ + if (cpu_is_xlp9xx()) + irt = PIC_9XX_IRT_PCIE_LINK_INDEX(link); + else + irt = PIC_IRT_PCIE_LINK_INDEX(link); + nlm_setup_pic_irq(node, lirq, lirq, irt); + nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq, + node * nlm_threads_per_node(), 1 /*en */); + } + + /* allocate a MSI vec, and tell the bridge about it */ + msivec = fls(md->msi_alloc_mask); + if (msivec == XLP_MSIVEC_PER_LINK) { + spin_unlock_irqrestore(&md->msi_lock, flags); + return -ENOMEM; + } + md->msi_alloc_mask |= (1u << msivec); + spin_unlock_irqrestore(&md->msi_lock, flags); + + msg.address_hi = msiaddr >> 32; + msg.address_lo = msiaddr & 0xffffffff; + msg.data = 0xc00 | msivec; + + xirq = xirq + msivec; /* msi mapped to global irq space */ + ret = irq_set_msi_desc(xirq, desc); + if (ret < 0) + return ret; + + write_msi_msg(xirq, &msg); + return 0; +} + +/* + * Switch a link to MSI-X mode + */ +static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr) +{ + u32 val; + + val = nlm_read_reg(lnkbase, 0x2C); + if ((val & 0x80000000U) == 0) { + val |= 0x80000000U; + nlm_write_reg(lnkbase, 0x2C, val); + } + + if (cpu_is_xlp9xx()) { + val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0); + if ((val & 0x200) == 0) { + val |= 0x200; /* MSI Interrupt enable */ + nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val); + } + } else { + val = nlm_read_reg(lnkbase, PCIE_INT_EN0); + if ((val & 0x200) == 0) { + val |= 0x200; /* MSI Interrupt enable */ + nlm_write_reg(lnkbase, PCIE_INT_EN0, val); + } + } + + val = nlm_read_reg(lnkbase, 0x1); /* CMD */ + if ((val & 0x0400) == 0) { + val |= 0x0400; + nlm_write_reg(lnkbase, 0x1, val); + } + + /* Update IRQ in the PCI irq reg */ + val = nlm_read_pci_reg(lnkbase, 0xf); + val &= ~0x1fu; + val |= (1 << 8) | lirq; + nlm_write_pci_reg(lnkbase, 0xf, val); + + if (cpu_is_xlp9xx()) { + /* MSI-X addresses */ + nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_BASE, + msixaddr >> 8); + nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT, + (msixaddr + MSI_ADDR_SZ) >> 8); + } else { + /* MSI-X addresses */ + nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE, + msixaddr >> 8); + nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT, + (msixaddr + MSI_ADDR_SZ) >> 8); + } +} + +/* + * Allocate a MSI-X vector + */ +static int xlp_setup_msix(uint64_t lnkbase, int node, int link, + struct msi_desc *desc) +{ + struct xlp_msi_data *md; + struct msi_msg msg; + unsigned long flags; + int t, msixvec, lirq, xirq, ret; + uint64_t msixaddr; + + /* Get MSI data for the link */ + lirq = PIC_PCIE_MSIX_IRQ(link); + xirq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0)); + md = irq_get_handler_data(xirq); + msixaddr = MSIX_LINK_ADDR(node, link); + + spin_lock_irqsave(&md->msi_lock, flags); + /* switch the PCIe link to MSI-X mode at the first alloc */ + if (md->msix_alloc_mask == 0) + xlp_config_link_msix(lnkbase, lirq, msixaddr); + + /* allocate a MSI-X vec, and tell the bridge about it */ + t = fls(md->msix_alloc_mask); + if (t == XLP_MSIXVEC_PER_LINK) { + spin_unlock_irqrestore(&md->msi_lock, flags); + return -ENOMEM; + } + md->msix_alloc_mask |= (1u << t); + spin_unlock_irqrestore(&md->msi_lock, flags); + + xirq += t; + msixvec = nlm_irq_msixvec(xirq); + + msg.address_hi = msixaddr >> 32; + msg.address_lo = msixaddr & 0xffffffff; + msg.data = 0xc00 | msixvec; + + ret = irq_set_msi_desc(xirq, desc); + if (ret < 0) { + destroy_irq(xirq); + return ret; + } + + write_msi_msg(xirq, &msg); + return 0; +} + +int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) +{ + struct pci_dev *lnkdev; + uint64_t lnkbase; + int node, link, slot; + + lnkdev = xlp_get_pcie_link(dev); + if (lnkdev == NULL) { + dev_err(&dev->dev, "Could not find bridge\n"); + return 1; + } + slot = PCI_SLOT(lnkdev->devfn); + link = PCI_FUNC(lnkdev->devfn); + node = slot / 8; + lnkbase = nlm_get_pcie_base(node, link); + + if (desc->msi_attrib.is_msix) + return xlp_setup_msix(lnkbase, node, link, desc); + else + return xlp_setup_msi(lnkbase, node, link, desc); +} + +void __init xlp_init_node_msi_irqs(int node, int link) +{ + struct nlm_soc_info *nodep; + struct xlp_msi_data *md; + int irq, i, irt, msixvec, val; + + pr_info("[%d %d] Init node PCI IRT\n", node, link); + nodep = nlm_get_node(node); + + /* Alloc an MSI block for the link */ + md = kzalloc(sizeof(*md), GFP_KERNEL); + spin_lock_init(&md->msi_lock); + md->msi_enabled_mask = 0; + md->msi_alloc_mask = 0; + md->msix_alloc_mask = 0; + md->node = nodep; + md->lnkbase = nlm_get_pcie_base(node, link); + + /* extended space for MSI interrupts */ + irq = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0)); + for (i = irq; i < irq + XLP_MSIVEC_PER_LINK; i++) { + irq_set_chip_and_handler(i, &xlp_msi_chip, handle_level_irq); + irq_set_handler_data(i, md); + } + + for (i = 0; i < XLP_MSIXVEC_PER_LINK ; i++) { + if (cpu_is_xlp9xx()) { + val = ((node * nlm_threads_per_node()) << 7 | + PIC_PCIE_MSIX_IRQ(link) << 1 | 0 << 0); + nlm_write_pcie_reg(md->lnkbase, PCIE_9XX_MSIX_VECX(i + + (link * XLP_MSIXVEC_PER_LINK)), val); + } else { + /* Initialize MSI-X irts to generate one interrupt + * per link + */ + msixvec = link * XLP_MSIXVEC_PER_LINK + i; + irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec); + nlm_pic_init_irt(nodep->picbase, irt, + PIC_PCIE_MSIX_IRQ(link), + node * nlm_threads_per_node(), 1); + } + + /* Initialize MSI-X extended irq space for the link */ + irq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, i)); + irq_set_chip_and_handler(irq, &xlp_msix_chip, handle_level_irq); + irq_set_handler_data(irq, md); + } +} + +void nlm_dispatch_msi(int node, int lirq) +{ + struct xlp_msi_data *md; + int link, i, irqbase; + u32 status; + + link = lirq - PIC_PCIE_LINK_MSI_IRQ_BASE; + irqbase = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0)); + md = irq_get_handler_data(irqbase); + if (cpu_is_xlp9xx()) + status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSI_STATUS) & + md->msi_enabled_mask; + else + status = nlm_read_reg(md->lnkbase, PCIE_MSI_STATUS) & + md->msi_enabled_mask; + while (status) { + i = __ffs(status); + do_IRQ(irqbase + i); + status &= status - 1; + } +} + +void nlm_dispatch_msix(int node, int lirq) +{ + struct xlp_msi_data *md; + int link, i, irqbase; + u32 status; + + link = lirq - PIC_PCIE_MSIX_IRQ_BASE; + irqbase = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0)); + md = irq_get_handler_data(irqbase); + if (cpu_is_xlp9xx()) + status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSIX_STATUSX(link)); + else + status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS); + + /* narrow it down to the MSI-x vectors for our link */ + if (!cpu_is_xlp9xx()) + status = (status >> (link * XLP_MSIXVEC_PER_LINK)) & + ((1 << XLP_MSIXVEC_PER_LINK) - 1); + + while (status) { + i = __ffs(status); + do_IRQ(irqbase + i); + status &= status - 1; + } +} diff --git a/arch/mips/pci/ops-bcm63xx.c b/arch/mips/pci/ops-bcm63xx.c index 4a156629e95..13eea696bbe 100644 --- a/arch/mips/pci/ops-bcm63xx.c +++ b/arch/mips/pci/ops-bcm63xx.c @@ -9,7 +9,6 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/kernel.h> -#include <linux/init.h> #include <linux/delay.h> #include <linux/io.h> @@ -174,8 +173,8 @@ static int bcm63xx_pci_write(struct pci_bus *bus, unsigned int devfn, } struct pci_ops bcm63xx_pci_ops = { - .read = bcm63xx_pci_read, - .write = bcm63xx_pci_write + .read = bcm63xx_pci_read, + .write = bcm63xx_pci_write }; #ifdef CONFIG_CARDBUS @@ -370,8 +369,8 @@ static int bcm63xx_cb_read(struct pci_bus *bus, unsigned int devfn, return fake_cb_bridge_read(where, size, val); } - /* a configuration cycle for the device behind the cardbus - * bridge is actually done as a type 0 cycle on the primary + /* a configuration cycle for the device behind the cardbus + * bridge is actually done as a type 0 cycle on the primary * bus. This means that only one device can be on the cardbus * bus */ if (fake_cb_bridge_regs.bus_assigned && @@ -403,8 +402,8 @@ static int bcm63xx_cb_write(struct pci_bus *bus, unsigned int devfn, } struct pci_ops bcm63xx_cb_ops = { - .read = bcm63xx_cb_read, - .write = bcm63xx_cb_write, + .read = bcm63xx_cb_read, + .write = bcm63xx_cb_write, }; /* @@ -523,6 +522,6 @@ static int bcm63xx_pcie_write(struct pci_bus *bus, unsigned int devfn, struct pci_ops bcm63xx_pcie_ops = { - .read = bcm63xx_pcie_read, - .write = bcm63xx_pcie_write + .read = bcm63xx_pcie_read, + .write = bcm63xx_pcie_write }; diff --git a/arch/mips/pci/ops-bonito64.c b/arch/mips/pci/ops-bonito64.c index 1b3e03f20c5..c06205a8734 100644 --- a/arch/mips/pci/ops-bonito64.c +++ b/arch/mips/pci/ops-bonito64.c @@ -22,11 +22,10 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/kernel.h> -#include <linux/init.h> #include <asm/mips-boards/bonito64.h> -#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_READ 0 #define PCI_ACCESS_WRITE 1 #define CFG_SPACE_REG(offset) (void *)CKSEG1ADDR(_pcictrl_bonito_pcicfg + (offset)) @@ -137,7 +136,7 @@ static int bonito64_pcibios_write(struct pci_bus *bus, unsigned int devfn, data = val; else { if (bonito64_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, - where, &data)) + where, &data)) return -1; if (size == 1) diff --git a/arch/mips/pci/ops-gt64xxx_pci0.c b/arch/mips/pci/ops-gt64xxx_pci0.c index 3d896c5f413..effcbda9f52 100644 --- a/arch/mips/pci/ops-gt64xxx_pci0.c +++ b/arch/mips/pci/ops-gt64xxx_pci0.c @@ -23,21 +23,21 @@ #include <asm/gt64120.h> -#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_READ 0 #define PCI_ACCESS_WRITE 1 /* * PCI configuration cycle AD bus definition */ /* Type 0 */ -#define PCI_CFG_TYPE0_REG_SHF 0 -#define PCI_CFG_TYPE0_FUNC_SHF 8 +#define PCI_CFG_TYPE0_REG_SHF 0 +#define PCI_CFG_TYPE0_FUNC_SHF 8 /* Type 1 */ -#define PCI_CFG_TYPE1_REG_SHF 0 -#define PCI_CFG_TYPE1_FUNC_SHF 8 -#define PCI_CFG_TYPE1_DEV_SHF 11 -#define PCI_CFG_TYPE1_BUS_SHF 16 +#define PCI_CFG_TYPE1_REG_SHF 0 +#define PCI_CFG_TYPE1_FUNC_SHF 8 +#define PCI_CFG_TYPE1_DEV_SHF 11 +#define PCI_CFG_TYPE1_BUS_SHF 16 static int gt64xxx_pci0_pcibios_config_access(unsigned char access_type, struct pci_bus *bus, unsigned int devfn, int where, u32 * data) @@ -50,7 +50,7 @@ static int gt64xxx_pci0_pcibios_config_access(unsigned char access_type, /* Clear cause register bits */ GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | - GT_INTRCAUSE_TARABORT0_BIT)); + GT_INTRCAUSE_TARABORT0_BIT)); /* Setup address */ GT_WRITE(GT_PCI0_CFGADDR_OFS, @@ -87,7 +87,7 @@ static int gt64xxx_pci0_pcibios_config_access(unsigned char access_type, /* Clear bits */ GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | - GT_INTRCAUSE_TARABORT0_BIT)); + GT_INTRCAUSE_TARABORT0_BIT)); return -1; } @@ -106,7 +106,7 @@ static int gt64xxx_pci0_pcibios_read(struct pci_bus *bus, unsigned int devfn, u32 data = 0; if (gt64xxx_pci0_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, - where, &data)) + where, &data)) return PCIBIOS_DEVICE_NOT_FOUND; if (size == 1) @@ -128,7 +128,7 @@ static int gt64xxx_pci0_pcibios_write(struct pci_bus *bus, unsigned int devfn, data = val; else { if (gt64xxx_pci0_pcibios_config_access(PCI_ACCESS_READ, bus, - devfn, where, &data)) + devfn, where, &data)) return PCIBIOS_DEVICE_NOT_FOUND; if (size == 1) @@ -140,7 +140,7 @@ static int gt64xxx_pci0_pcibios_write(struct pci_bus *bus, unsigned int devfn, } if (gt64xxx_pci0_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, - where, &data)) + where, &data)) return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_SUCCESSFUL; diff --git a/arch/mips/pci/ops-lantiq.c b/arch/mips/pci/ops-lantiq.c index 1f2afb55cc7..e5738ee26f4 100644 --- a/arch/mips/pci/ops-lantiq.c +++ b/arch/mips/pci/ops-lantiq.c @@ -9,7 +9,6 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/kernel.h> -#include <linux/init.h> #include <linux/delay.h> #include <linux/mm.h> #include <asm/addrspace.h> @@ -23,7 +22,7 @@ #define LTQ_PCI_CFG_DEVNUM_SHF 11 #define LTQ_PCI_CFG_FUNNUM_SHF 8 -#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_READ 0 #define PCI_ACCESS_WRITE 1 static int ltq_pci_config_access(unsigned char access_type, struct pci_bus *bus, diff --git a/arch/mips/pci/ops-loongson2.c b/arch/mips/pci/ops-loongson2.c index afd221122d2..24138bb0cbe 100644 --- a/arch/mips/pci/ops-loongson2.c +++ b/arch/mips/pci/ops-loongson2.c @@ -14,7 +14,6 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/kernel.h> -#include <linux/init.h> #include <linux/export.h> #include <loongson.h> @@ -24,7 +23,7 @@ #include <cs5536/cs5536.h> #endif -#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_READ 0 #define PCI_ACCESS_WRITE 1 #define CFG_SPACE_REG(offset) \ diff --git a/arch/mips/pci/ops-loongson3.c b/arch/mips/pci/ops-loongson3.c new file mode 100644 index 00000000000..46ed541a3ec --- /dev/null +++ b/arch/mips/pci/ops-loongson3.c @@ -0,0 +1,101 @@ +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/kernel.h> + +#include <asm/mips-boards/bonito64.h> + +#include <loongson.h> + +#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_WRITE 1 + +#define HT1LO_PCICFG_BASE 0x1a000000 +#define HT1LO_PCICFG_BASE_TP1 0x1b000000 + +static int loongson3_pci_config_access(unsigned char access_type, + struct pci_bus *bus, unsigned int devfn, + int where, u32 *data) +{ + unsigned char busnum = bus->number; + u_int64_t addr, type; + void *addrp; + int device = PCI_SLOT(devfn); + int function = PCI_FUNC(devfn); + int reg = where & ~3; + + addr = (busnum << 16) | (device << 11) | (function << 8) | reg; + if (busnum == 0) { + if (device > 31) + return PCIBIOS_DEVICE_NOT_FOUND; + addrp = (void *)(TO_UNCAC(HT1LO_PCICFG_BASE) | (addr & 0xffff)); + type = 0; + + } else { + addrp = (void *)(TO_UNCAC(HT1LO_PCICFG_BASE_TP1) | (addr)); + type = 0x10000; + } + + if (access_type == PCI_ACCESS_WRITE) + writel(*data, addrp); + else { + *data = readl(addrp); + if (*data == 0xffffffff) { + *data = -1; + return PCIBIOS_DEVICE_NOT_FOUND; + } + } + return PCIBIOS_SUCCESSFUL; +} + +static int loongson3_pci_pcibios_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) +{ + u32 data = 0; + int ret = loongson3_pci_config_access(PCI_ACCESS_READ, + bus, devfn, where, &data); + + if (ret != PCIBIOS_SUCCESSFUL) + return ret; + + if (size == 1) + *val = (data >> ((where & 3) << 3)) & 0xff; + else if (size == 2) + *val = (data >> ((where & 3) << 3)) & 0xffff; + else + *val = data; + + return PCIBIOS_SUCCESSFUL; +} + +static int loongson3_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + u32 data = 0; + int ret; + + if (size == 4) + data = val; + else { + ret = loongson3_pci_config_access(PCI_ACCESS_READ, + bus, devfn, where, &data); + if (ret != PCIBIOS_SUCCESSFUL) + return ret; + + if (size == 1) + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + else if (size == 2) + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + } + + ret = loongson3_pci_config_access(PCI_ACCESS_WRITE, + bus, devfn, where, &data); + + return ret; +} + +struct pci_ops loongson_pci_ops = { + .read = loongson3_pci_pcibios_read, + .write = loongson3_pci_pcibios_write +}; diff --git a/arch/mips/pci/ops-mace.c b/arch/mips/pci/ops-mace.c index 1cfb5588699..6b5821febc3 100644 --- a/arch/mips/pci/ops-mace.c +++ b/arch/mips/pci/ops-mace.c @@ -6,7 +6,6 @@ * Copyright (C) 2000, 2001 Keith M Wesolowski */ #include <linux/kernel.h> -#include <linux/init.h> #include <linux/pci.h> #include <linux/types.h> #include <asm/pci.h> diff --git a/arch/mips/pci/ops-msc.c b/arch/mips/pci/ops-msc.c index 5d9fbb0f467..dbbf3657896 100644 --- a/arch/mips/pci/ops-msc.c +++ b/arch/mips/pci/ops-msc.c @@ -1,8 +1,8 @@ /* - * Copyright (C) 1999, 2000, 2004, 2005 MIPS Technologies, Inc. + * Copyright (C) 1999, 2000, 2004, 2005 MIPS Technologies, Inc. * All rights reserved. * Authors: Carsten Langgaard <carstenl@mips.com> - * Maciej W. Rozycki <macro@mips.com> + * Maciej W. Rozycki <macro@mips.com> * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) * * This program is free software; you can distribute it and/or modify it @@ -24,25 +24,24 @@ #include <linux/types.h> #include <linux/pci.h> #include <linux/kernel.h> -#include <linux/init.h> #include <asm/mips-boards/msc01_pci.h> -#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_READ 0 #define PCI_ACCESS_WRITE 1 /* * PCI configuration cycle AD bus definition */ /* Type 0 */ -#define PCI_CFG_TYPE0_REG_SHF 0 -#define PCI_CFG_TYPE0_FUNC_SHF 8 +#define PCI_CFG_TYPE0_REG_SHF 0 +#define PCI_CFG_TYPE0_FUNC_SHF 8 /* Type 1 */ -#define PCI_CFG_TYPE1_REG_SHF 0 -#define PCI_CFG_TYPE1_FUNC_SHF 8 -#define PCI_CFG_TYPE1_DEV_SHF 11 -#define PCI_CFG_TYPE1_BUS_SHF 16 +#define PCI_CFG_TYPE1_REG_SHF 0 +#define PCI_CFG_TYPE1_FUNC_SHF 8 +#define PCI_CFG_TYPE1_DEV_SHF 11 +#define PCI_CFG_TYPE1_BUS_SHF 16 static int msc_pcibios_config_access(unsigned char access_type, struct pci_bus *bus, unsigned int devfn, int where, u32 * data) @@ -97,7 +96,7 @@ static int msc_pcibios_read(struct pci_bus *bus, unsigned int devfn, return PCIBIOS_BAD_REGISTER_NUMBER; if (msc_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, - &data)) + &data)) return -1; if (size == 1) @@ -124,7 +123,7 @@ static int msc_pcibios_write(struct pci_bus *bus, unsigned int devfn, data = val; else { if (msc_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, - where, &data)) + where, &data)) return -1; if (size == 1) diff --git a/arch/mips/pci/ops-nile4.c b/arch/mips/pci/ops-nile4.c index 99929cf8841..a1a7c9f4096 100644 --- a/arch/mips/pci/ops-nile4.c +++ b/arch/mips/pci/ops-nile4.c @@ -1,12 +1,11 @@ #include <linux/kernel.h> -#include <linux/init.h> #include <linux/pci.h> #include <asm/bootinfo.h> #include <asm/lasat/lasat.h> #include <asm/nile4.h> -#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_READ 0 #define PCI_ACCESS_WRITE 1 #define LO(reg) (reg / 4) diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c index 389bf669d56..50034f985be 100644 --- a/arch/mips/pci/ops-pmcmsp.c +++ b/arch/mips/pci/ops-pmcmsp.c @@ -7,10 +7,10 @@ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * * Much of the code is derived from the original DDB5074 port by - * Geert Uytterhoeven <geert@sonycom.com> + * Geert Uytterhoeven <geert@linux-m68k.org> * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * @@ -53,96 +53,84 @@ static void pci_proc_init(void); /***************************************************************************** * - * FUNCTION: read_msp_pci_counts + * FUNCTION: show_msp_pci_counts * _________________________________________________________________________ * * DESCRIPTION: Prints the count of how many times each PCI - * interrupt has asserted. Can be invoked by the - * /proc filesystem. + * interrupt has asserted. Can be invoked by the + * /proc filesystem. * - * INPUTS: page - part of STDOUT calculation - * off - part of STDOUT calculation - * count - part of STDOUT calculation - * data - unused + * INPUTS: m - synthetic file construction data + * v - iterator * - * OUTPUTS: start - new start location - * eof - end of file pointer - * - * RETURNS: len - STDOUT length + * RETURNS: 0 or error * ****************************************************************************/ -static int read_msp_pci_counts(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int show_msp_pci_counts(struct seq_file *m, void *v) { int i; - int len = 0; unsigned int intcount, total = 0; for (i = 0; i < 32; ++i) { intcount = pci_int_count[i]; if (intcount != 0) { - len += sprintf(page + len, "[%d] = %u\n", i, intcount); + seq_printf(m, "[%d] = %u\n", i, intcount); total += intcount; } } - len += sprintf(page + len, "total = %u\n", total); - if (len <= off+count) - *eof = 1; - - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; + seq_printf(m, "total = %u\n", total); + return 0; +} - return len; +static int msp_pci_rd_cnt_open(struct inode *inode, struct file *file) +{ + return single_open(file, show_msp_pci_counts, NULL); } +static const struct file_operations msp_pci_rd_cnt_fops = { + .open = msp_pci_rd_cnt_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /***************************************************************************** * - * FUNCTION: gen_pci_cfg_wr + * FUNCTION: gen_pci_cfg_wr_show * _________________________________________________________________________ * * DESCRIPTION: Generates a configuration write cycle for debug purposes. - * The IDSEL line asserted and location and data written are - * immaterial. Just want to be able to prove that a - * configuration write can be correctly generated on the - * PCI bus. Intent is that this function by invocable from - * the /proc filesystem. - * - * INPUTS: page - part of STDOUT calculation - * off - part of STDOUT calculation - * count - part of STDOUT calculation - * data - unused + * The IDSEL line asserted and location and data written are + * immaterial. Just want to be able to prove that a + * configuration write can be correctly generated on the + * PCI bus. Intent is that this function by invocable from + * the /proc filesystem. * - * OUTPUTS: start - new start location - * eof - end of file pointer + * INPUTS: m - synthetic file construction data + * v - iterator * - * RETURNS: len - STDOUT length + * RETURNS: 0 or error * ****************************************************************************/ -static int gen_pci_cfg_wr(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int gen_pci_cfg_wr_show(struct seq_file *m, void *v) { unsigned char where = 0; /* Write to static Device/Vendor ID */ unsigned char bus_num = 0; /* Bus 0 */ unsigned char dev_fn = 0xF; /* Arbitrary device number */ u32 wr_data = 0xFF00AA00; /* Arbitrary data */ struct msp_pci_regs *preg = (void *)PCI_BASE_REG; - int len = 0; unsigned long value; int intr; - len += sprintf(page + len, "PMC MSP PCI: Beginning\n"); + seq_puts(m, "PMC MSP PCI: Beginning\n"); if (proc_init == 0) { pci_proc_init(); proc_init = ~0; } - len += sprintf(page + len, "PMC MSP PCI: Before Cfg Wr\n"); + seq_puts(m, "PMC MSP PCI: Before Cfg Wr\n"); /* * Generate PCI Configuration Write Cycle @@ -168,21 +156,22 @@ static int gen_pci_cfg_wr(char *page, char **start, off_t off, */ intr = preg->if_status; - len += sprintf(page + len, "PMC MSP PCI: After Cfg Wr\n"); - - /* Handle STDOUT calculations */ - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; + seq_puts(m, "PMC MSP PCI: After Cfg Wr\n"); + return 0; +} - return len; +static int gen_pci_cfg_wr_open(struct inode *inode, struct file *file) +{ + return single_open(file, gen_pci_cfg_wr_show, NULL); } +static const struct file_operations gen_pci_cfg_wr_fops = { + .open = gen_pci_cfg_wr_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /***************************************************************************** * * FUNCTION: pci_proc_init @@ -190,19 +179,17 @@ static int gen_pci_cfg_wr(char *page, char **start, off_t off, * * DESCRIPTION: Create entries in the /proc filesystem for debug access. * - * INPUTS: none + * INPUTS: none * - * OUTPUTS: none + * OUTPUTS: none * - * RETURNS: none + * RETURNS: none * ****************************************************************************/ static void pci_proc_init(void) { - create_proc_read_entry("pmc_msp_pci_rd_cnt", 0, NULL, - read_msp_pci_counts, NULL); - create_proc_read_entry("pmc_msp_pci_cfg_wr", 0, NULL, - gen_pci_cfg_wr, NULL); + proc_create("pmc_msp_pci_rd_cnt", 0, NULL, &msp_pci_rd_cnt_fops); + proc_create("pmc_msp_pci_cfg_wr", 0, NULL, &gen_pci_cfg_wr_fops); } #endif /* CONFIG_PROC_FS && PCI_COUNTERS */ @@ -214,44 +201,44 @@ static DEFINE_SPINLOCK(bpci_lock); * _________________________________________________________________________ * * DESCRIPTION: Defines the address range that pciauto() will use to - * assign to the I/O BARs of PCI devices. - * - * Use the start and end addresses of the MSP7120 PCI Host - * Controller I/O space, in the form that they appear on the - * PCI bus AFTER MSP7120 has performed address translation. - * - * For I/O accesses, MSP7120 ignores OATRAN and maps I/O - * accesses into the bottom 0xFFF region of address space, - * so that is the range to put into the pci_io_resource - * struct. - * - * In MSP4200, the start address was 0x04 instead of the - * expected 0x00. Will just assume there was a good reason - * for this! - * - * NOTES: Linux, by default, will assign I/O space to the lowest - * region of address space. Since MSP7120 and Linux, - * by default, have no offset in between how they map, the - * io_offset element of pci_controller struct should be set - * to zero. + * assign to the I/O BARs of PCI devices. + * + * Use the start and end addresses of the MSP7120 PCI Host + * Controller I/O space, in the form that they appear on the + * PCI bus AFTER MSP7120 has performed address translation. + * + * For I/O accesses, MSP7120 ignores OATRAN and maps I/O + * accesses into the bottom 0xFFF region of address space, + * so that is the range to put into the pci_io_resource + * struct. + * + * In MSP4200, the start address was 0x04 instead of the + * expected 0x00. Will just assume there was a good reason + * for this! + * + * NOTES: Linux, by default, will assign I/O space to the lowest + * region of address space. Since MSP7120 and Linux, + * by default, have no offset in between how they map, the + * io_offset element of pci_controller struct should be set + * to zero. * ELEMENTS: - * name - String used for a meaningful name. + * name - String used for a meaningful name. * - * start - Start address of MSP7120's I/O space, as MSP7120 presents - * the address on the PCI bus. + * start - Start address of MSP7120's I/O space, as MSP7120 presents + * the address on the PCI bus. * - * end - End address of MSP7120's I/O space, as MSP7120 presents - * the address on the PCI bus. + * end - End address of MSP7120's I/O space, as MSP7120 presents + * the address on the PCI bus. * - * flags - Attributes indicating the type of resource. In this case, - * indicate I/O space. + * flags - Attributes indicating the type of resource. In this case, + * indicate I/O space. * ****************************************************************************/ static struct resource pci_io_resource = { .name = "pci IO space", .start = 0x04, .end = 0x0FFF, - .flags = IORESOURCE_IO /* I/O space */ + .flags = IORESOURCE_IO /* I/O space */ }; /***************************************************************************** @@ -260,26 +247,26 @@ static struct resource pci_io_resource = { * _________________________________________________________________________ * * DESCRIPTION: Defines the address range that pciauto() will use to - * assign to the memory BARs of PCI devices. + * assign to the memory BARs of PCI devices. * - * The .start and .end values are dependent upon how address - * translation is performed by the OATRAN regiser. + * The .start and .end values are dependent upon how address + * translation is performed by the OATRAN regiser. * - * The values to use for .start and .end are the values - * in the form they appear on the PCI bus AFTER MSP7120 has - * performed OATRAN address translation. + * The values to use for .start and .end are the values + * in the form they appear on the PCI bus AFTER MSP7120 has + * performed OATRAN address translation. * * ELEMENTS: - * name - String used for a meaningful name. + * name - String used for a meaningful name. * - * start - Start address of MSP7120's memory space, as MSP7120 presents - * the address on the PCI bus. + * start - Start address of MSP7120's memory space, as MSP7120 presents + * the address on the PCI bus. * - * end - End address of MSP7120's memory space, as MSP7120 presents - * the address on the PCI bus. + * end - End address of MSP7120's memory space, as MSP7120 presents + * the address on the PCI bus. * - * flags - Attributes indicating the type of resource. In this case, - * indicate memory space. + * flags - Attributes indicating the type of resource. In this case, + * indicate memory space. * ****************************************************************************/ static struct resource pci_mem_resource = { @@ -295,17 +282,17 @@ static struct resource pci_mem_resource = { * _________________________________________________________________________ * * DESCRIPTION: PCI status interrupt handler. Updates the count of how - * many times each status bit has been set, then clears - * the status bits. If the appropriate macros are defined, - * these counts can be viewed via the /proc filesystem. + * many times each status bit has been set, then clears + * the status bits. If the appropriate macros are defined, + * these counts can be viewed via the /proc filesystem. * - * INPUTS: irq - unused - * dev_id - unused - * pt_regs - unused + * INPUTS: irq - unused + * dev_id - unused + * pt_regs - unused * - * OUTPUTS: none + * OUTPUTS: none * - * RETURNS: PCIBIOS_SUCCESSFUL - success + * RETURNS: PCIBIOS_SUCCESSFUL - success * ****************************************************************************/ static irqreturn_t bpci_interrupt(int irq, void *dev_id) @@ -335,41 +322,41 @@ static irqreturn_t bpci_interrupt(int irq, void *dev_id) * _________________________________________________________________________ * * DESCRIPTION: Performs a PCI configuration access (rd or wr), then - * checks that the access succeeded by querying MSP7120's - * PCI status bits. + * checks that the access succeeded by querying MSP7120's + * PCI status bits. * * INPUTS: - * access_type - kind of PCI configuration cycle to perform - * (read or write). Legal values are - * PCI_ACCESS_WRITE and PCI_ACCESS_READ. - * - * bus - pointer to the bus number of the device to - * be targeted for the configuration cycle. - * The only element of the pci_bus structure - * used is bus->number. This argument determines - * if the configuration access will be Type 0 or - * Type 1. Since MSP7120 assumes itself to be the - * PCI Host, any non-zero bus->number generates - * a Type 1 access. - * - * devfn - this is an 8-bit field. The lower three bits - * specify the function number of the device to - * be targeted for the configuration cycle, with - * all three-bit combinations being legal. The - * upper five bits specify the device number, - * with legal values being 10 to 31. - * - * where - address within the Configuration Header - * space to access. - * - * data - for write accesses, contains the data to - * write. + * access_type - kind of PCI configuration cycle to perform + * (read or write). Legal values are + * PCI_ACCESS_WRITE and PCI_ACCESS_READ. + * + * bus - pointer to the bus number of the device to + * be targeted for the configuration cycle. + * The only element of the pci_bus structure + * used is bus->number. This argument determines + * if the configuration access will be Type 0 or + * Type 1. Since MSP7120 assumes itself to be the + * PCI Host, any non-zero bus->number generates + * a Type 1 access. + * + * devfn - this is an 8-bit field. The lower three bits + * specify the function number of the device to + * be targeted for the configuration cycle, with + * all three-bit combinations being legal. The + * upper five bits specify the device number, + * with legal values being 10 to 31. + * + * where - address within the Configuration Header + * space to access. + * + * data - for write accesses, contains the data to + * write. * * OUTPUTS: - * data - for read accesses, contains the value read. + * data - for read accesses, contains the value read. * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * -1 - access failure + * RETURNS: PCIBIOS_SUCCESSFUL - success + * -1 - access failure * ****************************************************************************/ int msp_pcibios_config_access(unsigned char access_type, @@ -429,7 +416,7 @@ int msp_pcibios_config_access(unsigned char access_type, * for this Block Copy, called Block Copy 0 Fault (BC0F) and * Block Copy 1 Fault (BC1F). MSP4200 and MSP7120 don't have this * dedicated Block Copy block, so these two interrupts are now - * marked reserved. In case the Block Copy is resurrected in a + * marked reserved. In case the Block Copy is resurrected in a * future design, maintain the code that treats these two interrupts * specially. * @@ -439,7 +426,7 @@ int msp_pcibios_config_access(unsigned char access_type, preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F); /* Setup address that is to appear on PCI bus */ - preg->config_addr = BPCI_CFGADDR_ENABLE | + preg->config_addr = BPCI_CFGADDR_ENABLE | (bus_num << BPCI_CFGADDR_BUSNUM_SHF) | (dev_fn << BPCI_CFGADDR_FUNCTNUM_SHF) | (where & 0xFC); @@ -494,21 +481,21 @@ int msp_pcibios_config_access(unsigned char access_type, * _________________________________________________________________________ * * DESCRIPTION: Read a byte from PCI configuration address spac - * Since the hardware can't address 8 bit chunks - * directly, read a 32-bit chunk, then mask off extraneous - * bits. + * Since the hardware can't address 8 bit chunks + * directly, read a 32-bit chunk, then mask off extraneous + * bits. * - * INPUTS bus - structure containing attributes for the PCI bus - * that the read is destined for. - * devfn - device/function combination that the read is - * destined for. - * where - register within the Configuration Header space - * to access. + * INPUTS bus - structure containing attributes for the PCI bus + * that the read is destined for. + * devfn - device/function combination that the read is + * destined for. + * where - register within the Configuration Header space + * to access. * - * OUTPUTS val - read data + * OUTPUTS val - read data * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * -1 - read access failure + * RETURNS: PCIBIOS_SUCCESSFUL - success + * -1 - read access failure * ****************************************************************************/ static int @@ -541,22 +528,22 @@ msp_pcibios_read_config_byte(struct pci_bus *bus, * _________________________________________________________________________ * * DESCRIPTION: Read a word (16 bits) from PCI configuration address space. - * Since the hardware can't address 16 bit chunks - * directly, read a 32-bit chunk, then mask off extraneous - * bits. + * Since the hardware can't address 16 bit chunks + * directly, read a 32-bit chunk, then mask off extraneous + * bits. * - * INPUTS bus - structure containing attributes for the PCI bus - * that the read is destined for. - * devfn - device/function combination that the read is - * destined for. - * where - register within the Configuration Header space - * to access. + * INPUTS bus - structure containing attributes for the PCI bus + * that the read is destined for. + * devfn - device/function combination that the read is + * destined for. + * where - register within the Configuration Header space + * to access. * - * OUTPUTS val - read data + * OUTPUTS val - read data * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * PCIBIOS_BAD_REGISTER_NUMBER - bad register address - * -1 - read access failure + * RETURNS: PCIBIOS_SUCCESSFUL - success + * PCIBIOS_BAD_REGISTER_NUMBER - bad register address + * -1 - read access failure * ****************************************************************************/ static int @@ -600,20 +587,20 @@ msp_pcibios_read_config_word(struct pci_bus *bus, * _________________________________________________________________________ * * DESCRIPTION: Read a double word (32 bits) from PCI configuration - * address space. + * address space. * - * INPUTS bus - structure containing attributes for the PCI bus - * that the read is destined for. - * devfn - device/function combination that the read is - * destined for. - * where - register within the Configuration Header space - * to access. + * INPUTS bus - structure containing attributes for the PCI bus + * that the read is destined for. + * devfn - device/function combination that the read is + * destined for. + * where - register within the Configuration Header space + * to access. * - * OUTPUTS val - read data + * OUTPUTS val - read data * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * PCIBIOS_BAD_REGISTER_NUMBER - bad register address - * -1 - read access failure + * RETURNS: PCIBIOS_SUCCESSFUL - success + * PCIBIOS_BAD_REGISTER_NUMBER - bad register address + * -1 - read access failure * ****************************************************************************/ static int @@ -652,21 +639,21 @@ msp_pcibios_read_config_dword(struct pci_bus *bus, * _________________________________________________________________________ * * DESCRIPTION: Write a byte to PCI configuration address space. - * Since the hardware can't address 8 bit chunks - * directly, a read-modify-write is performed. + * Since the hardware can't address 8 bit chunks + * directly, a read-modify-write is performed. * - * INPUTS bus - structure containing attributes for the PCI bus - * that the write is destined for. - * devfn - device/function combination that the write is - * destined for. - * where - register within the Configuration Header space - * to access. - * val - value to write + * INPUTS bus - structure containing attributes for the PCI bus + * that the write is destined for. + * devfn - device/function combination that the write is + * destined for. + * where - register within the Configuration Header space + * to access. + * val - value to write * - * OUTPUTS none + * OUTPUTS none * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * -1 - write access failure + * RETURNS: PCIBIOS_SUCCESSFUL - success + * -1 - write access failure * ****************************************************************************/ static int @@ -700,22 +687,22 @@ msp_pcibios_write_config_byte(struct pci_bus *bus, * _________________________________________________________________________ * * DESCRIPTION: Write a word (16-bits) to PCI configuration address space. - * Since the hardware can't address 16 bit chunks - * directly, a read-modify-write is performed. + * Since the hardware can't address 16 bit chunks + * directly, a read-modify-write is performed. * - * INPUTS bus - structure containing attributes for the PCI bus - * that the write is destined for. - * devfn - device/function combination that the write is - * destined for. - * where - register within the Configuration Header space - * to access. - * val - value to write + * INPUTS bus - structure containing attributes for the PCI bus + * that the write is destined for. + * devfn - device/function combination that the write is + * destined for. + * where - register within the Configuration Header space + * to access. + * val - value to write * - * OUTPUTS none + * OUTPUTS none * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * PCIBIOS_BAD_REGISTER_NUMBER - bad register address - * -1 - write access failure + * RETURNS: PCIBIOS_SUCCESSFUL - success + * PCIBIOS_BAD_REGISTER_NUMBER - bad register address + * -1 - write access failure * ****************************************************************************/ static int @@ -753,21 +740,21 @@ msp_pcibios_write_config_word(struct pci_bus *bus, * _________________________________________________________________________ * * DESCRIPTION: Write a double word (32-bits) to PCI configuration address - * space. + * space. * - * INPUTS bus - structure containing attributes for the PCI bus - * that the write is destined for. - * devfn - device/function combination that the write is - * destined for. - * where - register within the Configuration Header space - * to access. - * val - value to write + * INPUTS bus - structure containing attributes for the PCI bus + * that the write is destined for. + * devfn - device/function combination that the write is + * destined for. + * where - register within the Configuration Header space + * to access. + * val - value to write * - * OUTPUTS none + * OUTPUTS none * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * PCIBIOS_BAD_REGISTER_NUMBER - bad register address - * -1 - write access failure + * RETURNS: PCIBIOS_SUCCESSFUL - success + * PCIBIOS_BAD_REGISTER_NUMBER - bad register address + * -1 - write access failure * ****************************************************************************/ static int @@ -794,22 +781,22 @@ msp_pcibios_write_config_dword(struct pci_bus *bus, * _________________________________________________________________________ * * DESCRIPTION: Interface the PCI configuration read request with - * the appropriate function, based on how many bytes - * the read request is. + * the appropriate function, based on how many bytes + * the read request is. * - * INPUTS bus - structure containing attributes for the PCI bus - * that the write is destined for. - * devfn - device/function combination that the write is - * destined for. - * where - register within the Configuration Header space - * to access. - * size - in units of bytes, should be 1, 2, or 4. + * INPUTS bus - structure containing attributes for the PCI bus + * that the write is destined for. + * devfn - device/function combination that the write is + * destined for. + * where - register within the Configuration Header space + * to access. + * size - in units of bytes, should be 1, 2, or 4. * - * OUTPUTS val - value read, with any extraneous bytes masked - * to zero. + * OUTPUTS val - value read, with any extraneous bytes masked + * to zero. * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * -1 - failure + * RETURNS: PCIBIOS_SUCCESSFUL - success + * -1 - failure * ****************************************************************************/ int @@ -845,22 +832,22 @@ msp_pcibios_read_config(struct pci_bus *bus, * _________________________________________________________________________ * * DESCRIPTION: Interface the PCI configuration write request with - * the appropriate function, based on how many bytes - * the read request is. + * the appropriate function, based on how many bytes + * the read request is. * - * INPUTS bus - structure containing attributes for the PCI bus - * that the write is destined for. - * devfn - device/function combination that the write is - * destined for. - * where - register within the Configuration Header space - * to access. - * size - in units of bytes, should be 1, 2, or 4. - * val - value to write + * INPUTS bus - structure containing attributes for the PCI bus + * that the write is destined for. + * devfn - device/function combination that the write is + * destined for. + * where - register within the Configuration Header space + * to access. + * size - in units of bytes, should be 1, 2, or 4. + * val - value to write * - * OUTPUTS: none + * OUTPUTS: none * - * RETURNS: PCIBIOS_SUCCESSFUL - success - * -1 - failure + * RETURNS: PCIBIOS_SUCCESSFUL - success + * -1 - failure * ****************************************************************************/ int @@ -897,11 +884,11 @@ msp_pcibios_write_config(struct pci_bus *bus, * _________________________________________________________________________ * * DESCRIPTION: structure to abstract the hardware specific PCI - * configuration accesses. + * configuration accesses. * * ELEMENTS: - * read - function for Linux to generate PCI Configuration reads. - * write - function for Linux to generate PCI Configuration writes. + * read - function for Linux to generate PCI Configuration reads. + * write - function for Linux to generate PCI Configuration writes. * ****************************************************************************/ struct pci_ops msp_pci_ops = { @@ -917,27 +904,27 @@ struct pci_ops msp_pci_ops = { * Describes the attributes of the MSP7120 PCI Host Controller * * ELEMENTS: - * pci_ops - abstracts the hardware specific PCI configuration - * accesses. + * pci_ops - abstracts the hardware specific PCI configuration + * accesses. * * mem_resource - address range pciauto() uses to assign to PCI device - * memory BARs. + * memory BARs. * * mem_offset - offset between how MSP7120 outbound PCI memory - * transaction addresses appear on the PCI bus and how Linux - * wants to configure memory BARs of the PCI devices. - * MSP7120 does nothing funky, so just set to zero. + * transaction addresses appear on the PCI bus and how Linux + * wants to configure memory BARs of the PCI devices. + * MSP7120 does nothing funky, so just set to zero. * * io_resource - address range pciauto() uses to assign to PCI device - * I/O BARs. + * I/O BARs. * - * io_offset - offset between how MSP7120 outbound PCI I/O - * transaction addresses appear on the PCI bus and how - * Linux defaults to configure I/O BARs of the PCI devices. - * MSP7120 maps outbound I/O accesses into the bottom - * bottom 4K of PCI address space (and ignores OATRAN). - * Since the Linux default is to configure I/O BARs to the - * bottom 4K, no special offset is needed. Just set to zero. + * io_offset - offset between how MSP7120 outbound PCI I/O + * transaction addresses appear on the PCI bus and how + * Linux defaults to configure I/O BARs of the PCI devices. + * MSP7120 maps outbound I/O accesses into the bottom + * bottom 4K of PCI address space (and ignores OATRAN). + * Since the Linux default is to configure I/O BARs to the + * bottom 4K, no special offset is needed. Just set to zero. * ****************************************************************************/ static struct pci_controller msp_pci_controller = { @@ -955,7 +942,7 @@ static struct pci_controller msp_pci_controller = { * _________________________________________________________________________ * * DESCRIPTION: Initialize the PCI Host Controller and register it with - * Linux so Linux can seize control of the PCI bus. + * Linux so Linux can seize control of the PCI bus. * ****************************************************************************/ void __init msp_pci_init(void) @@ -979,7 +966,7 @@ void __init msp_pci_init(void) *(unsigned long *)QFLUSH_REG_1 = 3; /* Configure PCI Host Controller. */ - preg->if_status = ~0; /* Clear cause register bits */ + preg->if_status = ~0; /* Clear cause register bits */ preg->config_addr = 0; /* Clear config access */ preg->oatran = MSP_PCI_OATRAN; /* PCI outbound addr translation */ preg->if_mask = 0xF8BF87C0; /* Enable all PCI status interrupts */ diff --git a/arch/mips/pci/ops-pnx8550.c b/arch/mips/pci/ops-pnx8550.c deleted file mode 100644 index 1e6213fa7bd..00000000000 --- a/arch/mips/pci/ops-pnx8550.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * - * 2.6 port, Embedded Alley Solutions, Inc - * - * Based on: - * Author: source@mvista.com - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - */ -#include <linux/types.h> -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/vmalloc.h> -#include <linux/delay.h> - -#include <asm/mach-pnx8550/pci.h> -#include <asm/mach-pnx8550/glb.h> - -static inline void clear_status(void) -{ - unsigned long pci_stat; - - pci_stat = inl(PCI_BASE | PCI_GPPM_STATUS); - outl(pci_stat, PCI_BASE | PCI_GPPM_ICLR); -} - -static inline unsigned int -calc_cfg_addr(struct pci_bus *bus, unsigned int devfn, int where) -{ - unsigned int addr; - - addr = ((bus->number > 0) ? (((bus->number & 0xff) << PCI_CFG_BUS_SHIFT) | 1) : 0); - addr |= ((devfn & 0xff) << PCI_CFG_FUNC_SHIFT) | (where & 0xfc); - - return addr; -} - -static int -config_access(unsigned int pci_cmd, struct pci_bus *bus, unsigned int devfn, int where, unsigned int pci_mode, unsigned int *val) -{ - unsigned int flags; - unsigned long loops = 0; - unsigned long ioaddr = calc_cfg_addr(bus, devfn, where); - - local_irq_save(flags); - /*Clear pending interrupt status */ - if (inl(PCI_BASE | PCI_GPPM_STATUS)) { - clear_status(); - while (!(inl(PCI_BASE | PCI_GPPM_STATUS) == 0)) ; - } - - outl(ioaddr, PCI_BASE | PCI_GPPM_ADDR); - - if ((pci_cmd == PCI_CMD_IOW) || (pci_cmd == PCI_CMD_CONFIG_WRITE)) - outl(*val, PCI_BASE | PCI_GPPM_WDAT); - - outl(INIT_PCI_CYCLE | pci_cmd | (pci_mode & PCI_BYTE_ENABLE_MASK), - PCI_BASE | PCI_GPPM_CTRL); - - loops = - ((loops_per_jiffy * - PCI_IO_JIFFIES_TIMEOUT) >> (PCI_IO_JIFFIES_SHIFT)); - while (1) { - if (inl(PCI_BASE | PCI_GPPM_STATUS) & GPPM_DONE) { - if ((pci_cmd == PCI_CMD_IOR) || - (pci_cmd == PCI_CMD_CONFIG_READ)) - *val = inl(PCI_BASE | PCI_GPPM_RDAT); - clear_status(); - local_irq_restore(flags); - return PCIBIOS_SUCCESSFUL; - } else if (inl(PCI_BASE | PCI_GPPM_STATUS) & GPPM_R_MABORT) { - break; - } - - loops--; - if (loops == 0) { - printk("%s : Arbiter Locked.\n", __func__); - } - } - - clear_status(); - if ((pci_cmd == PCI_CMD_IOR) || (pci_cmd == PCI_CMD_IOW)) { - printk("%s timeout (GPPM_CTRL=%X) ioaddr %lX pci_cmd %X\n", - __func__, inl(PCI_BASE | PCI_GPPM_CTRL), ioaddr, - pci_cmd); - } - - if ((pci_cmd == PCI_CMD_IOR) || (pci_cmd == PCI_CMD_CONFIG_READ)) - *val = 0xffffffff; - local_irq_restore(flags); - return PCIBIOS_DEVICE_NOT_FOUND; -} - -/* - * We can't address 8 and 16 bit words directly. Instead we have to - * read/write a 32bit word and mask/modify the data we actually want. - */ -static int -read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 * val) -{ - unsigned int data = 0; - int err; - - if (bus == NULL) - return -1; - - err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, ~(1 << (where & 3)), &data); - switch (where & 0x03) { - case 0: - *val = (unsigned char)(data & 0x000000ff); - break; - case 1: - *val = (unsigned char)((data & 0x0000ff00) >> 8); - break; - case 2: - *val = (unsigned char)((data & 0x00ff0000) >> 16); - break; - case 3: - *val = (unsigned char)((data & 0xff000000) >> 24); - break; - } - - return err; -} - -static int -read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 * val) -{ - unsigned int data = 0; - int err; - - if (bus == NULL) - return -1; - - if (where & 0x01) - return PCIBIOS_BAD_REGISTER_NUMBER; - - err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, ~(3 << (where & 3)), &data); - switch (where & 0x02) { - case 0: - *val = (unsigned short)(data & 0x0000ffff); - break; - case 2: - *val = (unsigned short)((data & 0xffff0000) >> 16); - break; - } - - return err; -} - -static int -read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 * val) -{ - int err; - if (bus == NULL) - return -1; - - if (where & 0x03) - return PCIBIOS_BAD_REGISTER_NUMBER; - - err = config_access(PCI_CMD_CONFIG_READ, bus, devfn, where, 0, val); - - return err; -} - -static int -write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val) -{ - unsigned int data = (unsigned int)val; - int err; - - if (bus == NULL) - return -1; - - switch (where & 0x03) { - case 1: - data = (data << 8); - break; - case 2: - data = (data << 16); - break; - case 3: - data = (data << 24); - break; - default: - break; - } - - err = config_access(PCI_CMD_CONFIG_WRITE, bus, devfn, where, ~(1 << (where & 3)), &data); - - return err; -} - -static int -write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val) -{ - unsigned int data = (unsigned int)val; - int err; - - if (bus == NULL) - return -1; - - if (where & 0x01) - return PCIBIOS_BAD_REGISTER_NUMBER; - - switch (where & 0x02) { - case 2: - data = (data << 16); - break; - default: - break; - } - err = config_access(PCI_CMD_CONFIG_WRITE, bus, devfn, where, ~(3 << (where & 3)), &data); - - return err; -} - -static int -write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val) -{ - int err; - if (bus == NULL) - return -1; - - if (where & 0x03) - return PCIBIOS_BAD_REGISTER_NUMBER; - - err = config_access(PCI_CMD_CONFIG_WRITE, bus, devfn, where, 0, &val); - - return err; -} - -static int config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) -{ - switch (size) { - case 1: { - u8 _val; - int rc = read_config_byte(bus, devfn, where, &_val); - *val = _val; - return rc; - } - case 2: { - u16 _val; - int rc = read_config_word(bus, devfn, where, &_val); - *val = _val; - return rc; - } - default: - return read_config_dword(bus, devfn, where, val); - } -} - -static int config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) -{ - switch (size) { - case 1: - return write_config_byte(bus, devfn, where, (u8) val); - case 2: - return write_config_word(bus, devfn, where, (u16) val); - default: - return write_config_dword(bus, devfn, where, val); - } -} - -struct pci_ops pnx8550_pci_ops = { - config_read, - config_write -}; diff --git a/arch/mips/pci/ops-rc32434.c b/arch/mips/pci/ops-rc32434.c index d1f8fa210ca..874ed6df976 100644 --- a/arch/mips/pci/ops-rc32434.c +++ b/arch/mips/pci/ops-rc32434.c @@ -26,7 +26,6 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <linux/delay.h> -#include <linux/init.h> #include <linux/io.h> #include <linux/pci.h> #include <linux/types.h> @@ -35,7 +34,7 @@ #include <asm/mach-rc32434/rc32434.h> #include <asm/mach-rc32434/pci.h> -#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_READ 0 #define PCI_ACCESS_WRITE 1 diff --git a/arch/mips/pci/ops-sni.c b/arch/mips/pci/ops-sni.c index 97ed25b92ed..35daa7fe657 100644 --- a/arch/mips/pci/ops-sni.c +++ b/arch/mips/pci/ops-sni.c @@ -14,8 +14,8 @@ /* * It seems that on the RM200 only lower 3 bits of the 5 bit PCI device - * address are decoded. We therefore manually have to reject attempts at - * reading outside this range. Being on the paranoid side we only do this + * address are decoded. We therefore manually have to reject attempts at + * reading outside this range. Being on the paranoid side we only do this * test for bus 0 and hope forwarding and decoding work properly for any * subordinated busses. * @@ -31,8 +31,8 @@ static int set_config_address(unsigned int busno, unsigned int devfn, int reg) *(volatile u32 *)PCIMT_CONFIG_ADDRESS = ((busno & 0xff) << 16) | - ((devfn & 0xff) << 8) | - (reg & 0xfc); + ((devfn & 0xff) << 8) | + (reg & 0xfc); return PCIBIOS_SUCCESSFUL; } diff --git a/arch/mips/pci/ops-tx3927.c b/arch/mips/pci/ops-tx3927.c index 02d64f77e96..d35dc9c9ab9 100644 --- a/arch/mips/pci/ops-tx3927.c +++ b/arch/mips/pci/ops-tx3927.c @@ -11,7 +11,7 @@ * Define the pci_ops for TX3927. * * Much of the code is derived from the original DDB5074 port by - * Geert Uytterhoeven <geert@sonycom.com> + * Geert Uytterhoeven <geert@linux-m68k.org> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/arch/mips/pci/ops-tx4927.c b/arch/mips/pci/ops-tx4927.c index 0d69d6f4ea4..0e046d82e4e 100644 --- a/arch/mips/pci/ops-tx4927.c +++ b/arch/mips/pci/ops-tx4927.c @@ -2,16 +2,16 @@ * Define the pci_ops for the PCIC on Toshiba TX4927, TX4938, etc. * * Based on linux/arch/mips/pci/ops-tx4938.c, - * linux/arch/mips/pci/fixup-rbtx4938.c, - * linux/arch/mips/txx9/rbtx4938/setup.c, + * linux/arch/mips/pci/fixup-rbtx4938.c, + * linux/arch/mips/txx9/rbtx4938/setup.c, * and RBTX49xx patch from CELF patch archive. * * 2003-2005 (c) MontaVista Software, Inc. * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) * (C) Copyright TOSHIBA CORPORATION 2000-2001, 2004-2007 * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ @@ -202,17 +202,20 @@ char *tx4927_pcibios_setup(char *str) unsigned long val; if (!strncmp(str, "trdyto=", 7)) { - if (strict_strtoul(str + 7, 0, &val) == 0) + u8 val = 0; + if (kstrtou8(str + 7, 0, &val) == 0) tx4927_pci_opts.trdyto = val; return NULL; } if (!strncmp(str, "retryto=", 8)) { - if (strict_strtoul(str + 8, 0, &val) == 0) + u8 val = 0; + if (kstrtou8(str + 8, 0, &val) == 0) tx4927_pci_opts.retryto = val; return NULL; } if (!strncmp(str, "gbwc=", 5)) { - if (strict_strtoul(str + 5, 0, &val) == 0) + u16 val; + if (kstrtou16(str + 5, 0, &val) == 0) tx4927_pci_opts.gbwc = val; return NULL; } diff --git a/arch/mips/pci/ops-vr41xx.c b/arch/mips/pci/ops-vr41xx.c index 28962a7c660..551128c7d92 100644 --- a/arch/mips/pci/ops-vr41xx.c +++ b/arch/mips/pci/ops-vr41xx.c @@ -33,7 +33,7 @@ #define PCICONFAREG (void __iomem *)KSEG1ADDR(0x0f000c18) static inline int set_pci_configuration_address(unsigned char number, - unsigned int devfn, int where) + unsigned int devfn, int where) { if (number == 0) { /* @@ -59,7 +59,7 @@ static inline int set_pci_configuration_address(unsigned char number, } static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, - int size, uint32_t *val) + int size, uint32_t *val) { uint32_t data; @@ -87,7 +87,7 @@ static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, } static int pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, - int size, uint32_t val) + int size, uint32_t val) { uint32_t data; int shift; diff --git a/arch/mips/pci/pci-alchemy.c b/arch/mips/pci/pci-alchemy.c index c4ea6cc55f9..563d1f61d6e 100644 --- a/arch/mips/pci/pci-alchemy.c +++ b/arch/mips/pci/pci-alchemy.c @@ -16,10 +16,11 @@ #include <linux/syscore_ops.h> #include <linux/vmalloc.h> +#include <asm/dma-coherence.h> #include <asm/mach-au1x00/au1000.h> #include <asm/tlbmisc.h> -#ifdef CONFIG_DEBUG_PCI +#ifdef CONFIG_PCI_DEBUG #define DBG(x...) printk(KERN_DEBUG x) #else #define DBG(x...) do {} while (0) @@ -29,7 +30,7 @@ #define PCI_ACCESS_WRITE 1 struct alchemy_pci_context { - struct pci_controller alchemy_pci_ctrl; /* leave as first member! */ + struct pci_controller alchemy_pci_ctrl; /* leave as first member! */ void __iomem *regs; /* ctrl base */ /* tools for wired entry for config space access */ unsigned long last_elo0; @@ -162,7 +163,7 @@ static int config_access(unsigned char access_type, struct pci_bus *bus, if (status & (1 << 29)) { *data = 0xffffffff; error = -1; - DBG("alchemy-pci: master abort on cfg access %d bus %d dev %d", + DBG("alchemy-pci: master abort on cfg access %d bus %d dev %d\n", access_type, bus->number, device); } else if ((status >> 28) & 0xf) { DBG("alchemy-pci: PCI ERR detected: dev %d, status %lx\n", @@ -381,7 +382,7 @@ static int alchemy_pci_probe(struct platform_device *pdev) r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { - dev_err(&pdev->dev, "no pcictl ctrl regs resource\n"); + dev_err(&pdev->dev, "no pcictl ctrl regs resource\n"); ret = -ENODEV; goto out1; } @@ -411,17 +412,15 @@ static int alchemy_pci_probe(struct platform_device *pdev) } ctx->alchemy_pci_ctrl.io_map_base = (unsigned long)virt_io; -#ifdef CONFIG_DMA_NONCOHERENT /* Au1500 revisions older than AD have borked coherent PCI */ if ((alchemy_get_cputype() == ALCHEMY_CPU_AU1500) && - (read_c0_prid() < 0x01030202)) { + (read_c0_prid() < 0x01030202) && !coherentio) { val = __raw_readl(ctx->regs + PCI_REG_CONFIG); val |= PCI_CONFIG_NC; __raw_writel(val, ctx->regs + PCI_REG_CONFIG); wmb(); dev_info(&pdev->dev, "non-coherent PCI on Au1500 AA/AB/AC\n"); } -#endif if (pd->board_map_irq) ctx->board_map_irq = pd->board_map_irq; @@ -482,7 +481,7 @@ out: static struct platform_driver alchemy_pcictl_driver = { .probe = alchemy_pci_probe, - .driver = { + .driver = { .name = "alchemy-pci", .owner = THIS_MODULE, }, diff --git a/arch/mips/pci/pci-ar71xx.c b/arch/mips/pci/pci-ar71xx.c index 1552522b871..d471a26dd5f 100644 --- a/arch/mips/pci/pci-ar71xx.c +++ b/arch/mips/pci/pci-ar71xx.c @@ -18,26 +18,11 @@ #include <linux/pci.h> #include <linux/pci_regs.h> #include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/platform_device.h> #include <asm/mach-ath79/ar71xx_regs.h> #include <asm/mach-ath79/ath79.h> -#include <asm/mach-ath79/pci.h> - -#define AR71XX_PCI_MEM_BASE 0x10000000 -#define AR71XX_PCI_MEM_SIZE 0x08000000 - -#define AR71XX_PCI_WIN0_OFFS 0x10000000 -#define AR71XX_PCI_WIN1_OFFS 0x11000000 -#define AR71XX_PCI_WIN2_OFFS 0x12000000 -#define AR71XX_PCI_WIN3_OFFS 0x13000000 -#define AR71XX_PCI_WIN4_OFFS 0x14000000 -#define AR71XX_PCI_WIN5_OFFS 0x15000000 -#define AR71XX_PCI_WIN6_OFFS 0x16000000 -#define AR71XX_PCI_WIN7_OFFS 0x07000000 - -#define AR71XX_PCI_CFG_BASE \ - (AR71XX_PCI_MEM_BASE + AR71XX_PCI_WIN7_OFFS + 0x10000) -#define AR71XX_PCI_CFG_SIZE 0x100 #define AR71XX_PCI_REG_CRP_AD_CBE 0x00 #define AR71XX_PCI_REG_CRP_WRDATA 0x04 @@ -63,8 +48,15 @@ #define AR71XX_PCI_IRQ_COUNT 5 -static DEFINE_SPINLOCK(ar71xx_pci_lock); -static void __iomem *ar71xx_pcicfg_base; +struct ar71xx_pci_controller { + void __iomem *cfg_base; + spinlock_t lock; + int irq; + int irq_base; + struct pci_controller pci_ctrl; + struct resource io_res; + struct resource mem_res; +}; /* Byte lane enable bits */ static const u8 ar71xx_pci_ble_table[4][4] = { @@ -107,9 +99,18 @@ static inline u32 ar71xx_pci_bus_addr(struct pci_bus *bus, unsigned int devfn, return ret; } -static int ar71xx_pci_check_error(int quiet) +static inline struct ar71xx_pci_controller * +pci_bus_to_ar71xx_controller(struct pci_bus *bus) +{ + struct pci_controller *hose; + + hose = (struct pci_controller *) bus->sysdata; + return container_of(hose, struct ar71xx_pci_controller, pci_ctrl); +} + +static int ar71xx_pci_check_error(struct ar71xx_pci_controller *apc, int quiet) { - void __iomem *base = ar71xx_pcicfg_base; + void __iomem *base = apc->cfg_base; u32 pci_err; u32 ahb_err; @@ -144,9 +145,10 @@ static int ar71xx_pci_check_error(int quiet) return !!(ahb_err | pci_err); } -static inline void ar71xx_pci_local_write(int where, int size, u32 value) +static inline void ar71xx_pci_local_write(struct ar71xx_pci_controller *apc, + int where, int size, u32 value) { - void __iomem *base = ar71xx_pcicfg_base; + void __iomem *base = apc->cfg_base; u32 ad_cbe; value = value << (8 * (where & 3)); @@ -162,7 +164,8 @@ static inline int ar71xx_pci_set_cfgaddr(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 cmd) { - void __iomem *base = ar71xx_pcicfg_base; + struct ar71xx_pci_controller *apc = pci_bus_to_ar71xx_controller(bus); + void __iomem *base = apc->cfg_base; u32 addr; addr = ar71xx_pci_bus_addr(bus, devfn, where); @@ -171,13 +174,14 @@ static inline int ar71xx_pci_set_cfgaddr(struct pci_bus *bus, __raw_writel(cmd | ar71xx_pci_get_ble(where, size, 0), base + AR71XX_PCI_REG_CFG_CBE); - return ar71xx_pci_check_error(1); + return ar71xx_pci_check_error(apc, 1); } static int ar71xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) { - void __iomem *base = ar71xx_pcicfg_base; + struct ar71xx_pci_controller *apc = pci_bus_to_ar71xx_controller(bus); + void __iomem *base = apc->cfg_base; unsigned long flags; u32 data; int err; @@ -186,7 +190,7 @@ static int ar71xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, ret = PCIBIOS_SUCCESSFUL; data = ~0; - spin_lock_irqsave(&ar71xx_pci_lock, flags); + spin_lock_irqsave(&apc->lock, flags); err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size, AR71XX_PCI_CFG_CMD_READ); @@ -195,7 +199,7 @@ static int ar71xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, else data = __raw_readl(base + AR71XX_PCI_REG_CFG_RDDATA); - spin_unlock_irqrestore(&ar71xx_pci_lock, flags); + spin_unlock_irqrestore(&apc->lock, flags); *value = (data >> (8 * (where & 3))) & ar71xx_pci_read_mask[size & 7]; @@ -205,7 +209,8 @@ static int ar71xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, static int ar71xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { - void __iomem *base = ar71xx_pcicfg_base; + struct ar71xx_pci_controller *apc = pci_bus_to_ar71xx_controller(bus); + void __iomem *base = apc->cfg_base; unsigned long flags; int err; int ret; @@ -213,7 +218,7 @@ static int ar71xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, value = value << (8 * (where & 3)); ret = PCIBIOS_SUCCESSFUL; - spin_lock_irqsave(&ar71xx_pci_lock, flags); + spin_lock_irqsave(&apc->lock, flags); err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size, AR71XX_PCI_CFG_CMD_WRITE); @@ -222,7 +227,7 @@ static int ar71xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, else __raw_writel(value, base + AR71XX_PCI_REG_CFG_WRDATA); - spin_unlock_irqrestore(&ar71xx_pci_lock, flags); + spin_unlock_irqrestore(&apc->lock, flags); return ret; } @@ -232,45 +237,28 @@ static struct pci_ops ar71xx_pci_ops = { .write = ar71xx_pci_write_config, }; -static struct resource ar71xx_pci_io_resource = { - .name = "PCI IO space", - .start = 0, - .end = 0, - .flags = IORESOURCE_IO, -}; - -static struct resource ar71xx_pci_mem_resource = { - .name = "PCI memory space", - .start = AR71XX_PCI_MEM_BASE, - .end = AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1, - .flags = IORESOURCE_MEM -}; - -static struct pci_controller ar71xx_pci_controller = { - .pci_ops = &ar71xx_pci_ops, - .mem_resource = &ar71xx_pci_mem_resource, - .io_resource = &ar71xx_pci_io_resource, -}; - static void ar71xx_pci_irq_handler(unsigned int irq, struct irq_desc *desc) { + struct ar71xx_pci_controller *apc; void __iomem *base = ath79_reset_base; u32 pending; + apc = irq_get_handler_data(irq); + pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) & __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); if (pending & AR71XX_PCI_INT_DEV0) - generic_handle_irq(ATH79_PCI_IRQ(0)); + generic_handle_irq(apc->irq_base + 0); else if (pending & AR71XX_PCI_INT_DEV1) - generic_handle_irq(ATH79_PCI_IRQ(1)); + generic_handle_irq(apc->irq_base + 1); else if (pending & AR71XX_PCI_INT_DEV2) - generic_handle_irq(ATH79_PCI_IRQ(2)); + generic_handle_irq(apc->irq_base + 2); else if (pending & AR71XX_PCI_INT_CORE) - generic_handle_irq(ATH79_PCI_IRQ(4)); + generic_handle_irq(apc->irq_base + 4); else spurious_interrupt(); @@ -278,10 +266,14 @@ static void ar71xx_pci_irq_handler(unsigned int irq, struct irq_desc *desc) static void ar71xx_pci_irq_unmask(struct irq_data *d) { - unsigned int irq = d->irq - ATH79_PCI_IRQ_BASE; + struct ar71xx_pci_controller *apc; + unsigned int irq; void __iomem *base = ath79_reset_base; u32 t; + apc = irq_data_get_irq_chip_data(d); + irq = d->irq - apc->irq_base; + t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); @@ -291,10 +283,14 @@ static void ar71xx_pci_irq_unmask(struct irq_data *d) static void ar71xx_pci_irq_mask(struct irq_data *d) { - unsigned int irq = d->irq - ATH79_PCI_IRQ_BASE; + struct ar71xx_pci_controller *apc; + unsigned int irq; void __iomem *base = ath79_reset_base; u32 t; + apc = irq_data_get_irq_chip_data(d); + irq = d->irq - apc->irq_base; + t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); @@ -309,7 +305,7 @@ static struct irq_chip ar71xx_pci_irq_chip = { .irq_mask_ack = ar71xx_pci_irq_mask, }; -static __init void ar71xx_pci_irq_init(void) +static void ar71xx_pci_irq_init(struct ar71xx_pci_controller *apc) { void __iomem *base = ath79_reset_base; int i; @@ -319,15 +315,19 @@ static __init void ar71xx_pci_irq_init(void) BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR71XX_PCI_IRQ_COUNT); - for (i = ATH79_PCI_IRQ_BASE; - i < ATH79_PCI_IRQ_BASE + AR71XX_PCI_IRQ_COUNT; i++) + apc->irq_base = ATH79_PCI_IRQ_BASE; + for (i = apc->irq_base; + i < apc->irq_base + AR71XX_PCI_IRQ_COUNT; i++) { irq_set_chip_and_handler(i, &ar71xx_pci_irq_chip, handle_level_irq); + irq_set_chip_data(i, apc); + } - irq_set_chained_handler(ATH79_CPU_IRQ_IP2, ar71xx_pci_irq_handler); + irq_set_handler_data(apc->irq, apc); + irq_set_chained_handler(apc->irq, ar71xx_pci_irq_handler); } -static __init void ar71xx_pci_reset(void) +static void ar71xx_pci_reset(void) { void __iomem *ddr_base = ath79_ddr_base; @@ -349,27 +349,80 @@ static __init void ar71xx_pci_reset(void) mdelay(100); } -__init int ar71xx_pcibios_init(void) +static int ar71xx_pci_probe(struct platform_device *pdev) { + struct ar71xx_pci_controller *apc; + struct resource *res; u32 t; - ar71xx_pcicfg_base = ioremap(AR71XX_PCI_CFG_BASE, AR71XX_PCI_CFG_SIZE); - if (ar71xx_pcicfg_base == NULL) + apc = devm_kzalloc(&pdev->dev, sizeof(struct ar71xx_pci_controller), + GFP_KERNEL); + if (!apc) return -ENOMEM; + spin_lock_init(&apc->lock); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base"); + apc->cfg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(apc->cfg_base)) + return PTR_ERR(apc->cfg_base); + + apc->irq = platform_get_irq(pdev, 0); + if (apc->irq < 0) + return -EINVAL; + + res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base"); + if (!res) + return -EINVAL; + + apc->io_res.parent = res; + apc->io_res.name = "PCI IO space"; + apc->io_res.start = res->start; + apc->io_res.end = res->end; + apc->io_res.flags = IORESOURCE_IO; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base"); + if (!res) + return -EINVAL; + + apc->mem_res.parent = res; + apc->mem_res.name = "PCI memory space"; + apc->mem_res.start = res->start; + apc->mem_res.end = res->end; + apc->mem_res.flags = IORESOURCE_MEM; + ar71xx_pci_reset(); /* setup COMMAND register */ t = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK; - ar71xx_pci_local_write(PCI_COMMAND, 4, t); + ar71xx_pci_local_write(apc, PCI_COMMAND, 4, t); /* clear bus errors */ - ar71xx_pci_check_error(1); + ar71xx_pci_check_error(apc, 1); + + ar71xx_pci_irq_init(apc); - ar71xx_pci_irq_init(); + apc->pci_ctrl.pci_ops = &ar71xx_pci_ops; + apc->pci_ctrl.mem_resource = &apc->mem_res; + apc->pci_ctrl.io_resource = &apc->io_res; - register_pci_controller(&ar71xx_pci_controller); + register_pci_controller(&apc->pci_ctrl); return 0; } + +static struct platform_driver ar71xx_pci_driver = { + .probe = ar71xx_pci_probe, + .driver = { + .name = "ar71xx-pci", + .owner = THIS_MODULE, + }, +}; + +static int __init ar71xx_pci_init(void) +{ + return platform_driver_register(&ar71xx_pci_driver); +} + +postcore_initcall(ar71xx_pci_init); diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c index 86d77a66645..785b2659b51 100644 --- a/arch/mips/pci/pci-ar724x.c +++ b/arch/mips/pci/pci-ar724x.c @@ -9,19 +9,13 @@ * by the Free Software Foundation. */ +#include <linux/spinlock.h> #include <linux/irq.h> #include <linux/pci.h> +#include <linux/module.h> +#include <linux/platform_device.h> #include <asm/mach-ath79/ath79.h> #include <asm/mach-ath79/ar71xx_regs.h> -#include <asm/mach-ath79/pci.h> - -#define AR724X_PCI_CFG_BASE 0x14000000 -#define AR724X_PCI_CFG_SIZE 0x1000 -#define AR724X_PCI_CTRL_BASE (AR71XX_APB_BASE + 0x000f0000) -#define AR724X_PCI_CTRL_SIZE 0x100 - -#define AR724X_PCI_MEM_BASE 0x10000000 -#define AR724X_PCI_MEM_SIZE 0x08000000 #define AR724X_PCI_REG_RESET 0x18 #define AR724X_PCI_REG_INT_STATUS 0x4c @@ -35,38 +29,112 @@ #define AR7240_BAR0_WAR_VALUE 0xffff -static DEFINE_SPINLOCK(ar724x_pci_lock); -static void __iomem *ar724x_pci_devcfg_base; -static void __iomem *ar724x_pci_ctrl_base; +#define AR724X_PCI_CMD_INIT (PCI_COMMAND_MEMORY | \ + PCI_COMMAND_MASTER | \ + PCI_COMMAND_INVALIDATE | \ + PCI_COMMAND_PARITY | \ + PCI_COMMAND_SERR | \ + PCI_COMMAND_FAST_BACK) + +struct ar724x_pci_controller { + void __iomem *devcfg_base; + void __iomem *ctrl_base; + void __iomem *crp_base; + + int irq; + int irq_base; + + bool link_up; + bool bar0_is_cached; + u32 bar0_value; -static u32 ar724x_pci_bar0_value; -static bool ar724x_pci_bar0_is_cached; -static bool ar724x_pci_link_up; + spinlock_t lock; -static inline bool ar724x_pci_check_link(void) + struct pci_controller pci_controller; + struct resource io_res; + struct resource mem_res; +}; + +static inline bool ar724x_pci_check_link(struct ar724x_pci_controller *apc) { u32 reset; - reset = __raw_readl(ar724x_pci_ctrl_base + AR724X_PCI_REG_RESET); + reset = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_RESET); return reset & AR724X_PCI_RESET_LINK_UP; } +static inline struct ar724x_pci_controller * +pci_bus_to_ar724x_controller(struct pci_bus *bus) +{ + struct pci_controller *hose; + + hose = (struct pci_controller *) bus->sysdata; + return container_of(hose, struct ar724x_pci_controller, pci_controller); +} + +static int ar724x_pci_local_write(struct ar724x_pci_controller *apc, + int where, int size, u32 value) +{ + unsigned long flags; + void __iomem *base; + u32 data; + int s; + + WARN_ON(where & (size - 1)); + + if (!apc->link_up) + return PCIBIOS_DEVICE_NOT_FOUND; + + base = apc->crp_base; + + spin_lock_irqsave(&apc->lock, flags); + data = __raw_readl(base + (where & ~3)); + + switch (size) { + case 1: + s = ((where & 3) * 8); + data &= ~(0xff << s); + data |= ((value & 0xff) << s); + break; + case 2: + s = ((where & 2) * 8); + data &= ~(0xffff << s); + data |= ((value & 0xffff) << s); + break; + case 4: + data = value; + break; + default: + spin_unlock_irqrestore(&apc->lock, flags); + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + __raw_writel(data, base + (where & ~3)); + /* flush write */ + __raw_readl(base + (where & ~3)); + spin_unlock_irqrestore(&apc->lock, flags); + + return PCIBIOS_SUCCESSFUL; +} + static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, uint32_t *value) { + struct ar724x_pci_controller *apc; unsigned long flags; void __iomem *base; u32 data; - if (!ar724x_pci_link_up) + apc = pci_bus_to_ar724x_controller(bus); + if (!apc->link_up) return PCIBIOS_DEVICE_NOT_FOUND; if (devfn) return PCIBIOS_DEVICE_NOT_FOUND; - base = ar724x_pci_devcfg_base; + base = apc->devcfg_base; - spin_lock_irqsave(&ar724x_pci_lock, flags); + spin_lock_irqsave(&apc->lock, flags); data = __raw_readl(base + (where & ~3)); switch (size) { @@ -85,17 +153,17 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, case 4: break; default: - spin_unlock_irqrestore(&ar724x_pci_lock, flags); + spin_unlock_irqrestore(&apc->lock, flags); return PCIBIOS_BAD_REGISTER_NUMBER; } - spin_unlock_irqrestore(&ar724x_pci_lock, flags); + spin_unlock_irqrestore(&apc->lock, flags); if (where == PCI_BASE_ADDRESS_0 && size == 4 && - ar724x_pci_bar0_is_cached) { + apc->bar0_is_cached) { /* use the cached value */ - *value = ar724x_pci_bar0_value; + *value = apc->bar0_value; } else { *value = data; } @@ -106,12 +174,14 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, uint32_t value) { + struct ar724x_pci_controller *apc; unsigned long flags; void __iomem *base; u32 data; int s; - if (!ar724x_pci_link_up) + apc = pci_bus_to_ar724x_controller(bus); + if (!apc->link_up) return PCIBIOS_DEVICE_NOT_FOUND; if (devfn) @@ -129,18 +199,18 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, * BAR0 register in order to make the device memory * accessible. */ - ar724x_pci_bar0_is_cached = true; - ar724x_pci_bar0_value = value; + apc->bar0_is_cached = true; + apc->bar0_value = value; value = AR7240_BAR0_WAR_VALUE; } else { - ar724x_pci_bar0_is_cached = false; + apc->bar0_is_cached = false; } } - base = ar724x_pci_devcfg_base; + base = apc->devcfg_base; - spin_lock_irqsave(&ar724x_pci_lock, flags); + spin_lock_irqsave(&apc->lock, flags); data = __raw_readl(base + (where & ~3)); switch (size) { @@ -158,7 +228,7 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, data = value; break; default: - spin_unlock_irqrestore(&ar724x_pci_lock, flags); + spin_unlock_irqrestore(&apc->lock, flags); return PCIBIOS_BAD_REGISTER_NUMBER; } @@ -166,7 +236,7 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, __raw_writel(data, base + (where & ~3)); /* flush write */ __raw_readl(base + (where & ~3)); - spin_unlock_irqrestore(&ar724x_pci_lock, flags); + spin_unlock_irqrestore(&apc->lock, flags); return PCIBIOS_SUCCESSFUL; } @@ -176,38 +246,20 @@ static struct pci_ops ar724x_pci_ops = { .write = ar724x_pci_write, }; -static struct resource ar724x_io_resource = { - .name = "PCI IO space", - .start = 0, - .end = 0, - .flags = IORESOURCE_IO, -}; - -static struct resource ar724x_mem_resource = { - .name = "PCI memory space", - .start = AR724X_PCI_MEM_BASE, - .end = AR724X_PCI_MEM_BASE + AR724X_PCI_MEM_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -static struct pci_controller ar724x_pci_controller = { - .pci_ops = &ar724x_pci_ops, - .io_resource = &ar724x_io_resource, - .mem_resource = &ar724x_mem_resource, -}; - static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc) { + struct ar724x_pci_controller *apc; void __iomem *base; u32 pending; - base = ar724x_pci_ctrl_base; + apc = irq_get_handler_data(irq); + base = apc->ctrl_base; pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) & __raw_readl(base + AR724X_PCI_REG_INT_MASK); if (pending & AR724X_PCI_INT_DEV0) - generic_handle_irq(ATH79_PCI_IRQ(0)); + generic_handle_irq(apc->irq_base + 0); else spurious_interrupt(); @@ -215,13 +267,17 @@ static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc) static void ar724x_pci_irq_unmask(struct irq_data *d) { + struct ar724x_pci_controller *apc; void __iomem *base; + int offset; u32 t; - base = ar724x_pci_ctrl_base; + apc = irq_data_get_irq_chip_data(d); + base = apc->ctrl_base; + offset = apc->irq_base - d->irq; - switch (d->irq) { - case ATH79_PCI_IRQ(0): + switch (offset) { + case 0: t = __raw_readl(base + AR724X_PCI_REG_INT_MASK); __raw_writel(t | AR724X_PCI_INT_DEV0, base + AR724X_PCI_REG_INT_MASK); @@ -232,13 +288,17 @@ static void ar724x_pci_irq_unmask(struct irq_data *d) static void ar724x_pci_irq_mask(struct irq_data *d) { + struct ar724x_pci_controller *apc; void __iomem *base; + int offset; u32 t; - base = ar724x_pci_ctrl_base; + apc = irq_data_get_irq_chip_data(d); + base = apc->ctrl_base; + offset = apc->irq_base - d->irq; - switch (d->irq) { - case ATH79_PCI_IRQ(0): + switch (offset) { + case 0: t = __raw_readl(base + AR724X_PCI_REG_INT_MASK); __raw_writel(t & ~AR724X_PCI_INT_DEV0, base + AR724X_PCI_REG_INT_MASK); @@ -262,53 +322,114 @@ static struct irq_chip ar724x_pci_irq_chip = { .irq_mask_ack = ar724x_pci_irq_mask, }; -static void __init ar724x_pci_irq_init(int irq) +static void ar724x_pci_irq_init(struct ar724x_pci_controller *apc, + int id) { void __iomem *base; int i; - base = ar724x_pci_ctrl_base; + base = apc->ctrl_base; __raw_writel(0, base + AR724X_PCI_REG_INT_MASK); __raw_writel(0, base + AR724X_PCI_REG_INT_STATUS); - BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR724X_PCI_IRQ_COUNT); + apc->irq_base = ATH79_PCI_IRQ_BASE + (id * AR724X_PCI_IRQ_COUNT); - for (i = ATH79_PCI_IRQ_BASE; - i < ATH79_PCI_IRQ_BASE + AR724X_PCI_IRQ_COUNT; i++) + for (i = apc->irq_base; + i < apc->irq_base + AR724X_PCI_IRQ_COUNT; i++) { irq_set_chip_and_handler(i, &ar724x_pci_irq_chip, handle_level_irq); + irq_set_chip_data(i, apc); + } - irq_set_chained_handler(irq, ar724x_pci_irq_handler); + irq_set_handler_data(apc->irq, apc); + irq_set_chained_handler(apc->irq, ar724x_pci_irq_handler); } -int __init ar724x_pcibios_init(int irq) +static int ar724x_pci_probe(struct platform_device *pdev) { - int ret; + struct ar724x_pci_controller *apc; + struct resource *res; + int id; - ret = -ENOMEM; + id = pdev->id; + if (id == -1) + id = 0; - ar724x_pci_devcfg_base = ioremap(AR724X_PCI_CFG_BASE, - AR724X_PCI_CFG_SIZE); - if (ar724x_pci_devcfg_base == NULL) - goto err; + apc = devm_kzalloc(&pdev->dev, sizeof(struct ar724x_pci_controller), + GFP_KERNEL); + if (!apc) + return -ENOMEM; - ar724x_pci_ctrl_base = ioremap(AR724X_PCI_CTRL_BASE, - AR724X_PCI_CTRL_SIZE); - if (ar724x_pci_ctrl_base == NULL) - goto err_unmap_devcfg; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl_base"); + apc->ctrl_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(apc->ctrl_base)) + return PTR_ERR(apc->ctrl_base); - ar724x_pci_link_up = ar724x_pci_check_link(); - if (!ar724x_pci_link_up) - pr_warn("ar724x: PCIe link is down\n"); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base"); + apc->devcfg_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(apc->devcfg_base)) + return PTR_ERR(apc->devcfg_base); - ar724x_pci_irq_init(irq); - register_pci_controller(&ar724x_pci_controller); + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "crp_base"); + apc->crp_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(apc->crp_base)) + return PTR_ERR(apc->crp_base); - return PCIBIOS_SUCCESSFUL; + apc->irq = platform_get_irq(pdev, 0); + if (apc->irq < 0) + return -EINVAL; + + spin_lock_init(&apc->lock); + + res = platform_get_resource_byname(pdev, IORESOURCE_IO, "io_base"); + if (!res) + return -EINVAL; + + apc->io_res.parent = res; + apc->io_res.name = "PCI IO space"; + apc->io_res.start = res->start; + apc->io_res.end = res->end; + apc->io_res.flags = IORESOURCE_IO; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem_base"); + if (!res) + return -EINVAL; + + apc->mem_res.parent = res; + apc->mem_res.name = "PCI memory space"; + apc->mem_res.start = res->start; + apc->mem_res.end = res->end; + apc->mem_res.flags = IORESOURCE_MEM; + + apc->pci_controller.pci_ops = &ar724x_pci_ops; + apc->pci_controller.io_resource = &apc->io_res; + apc->pci_controller.mem_resource = &apc->mem_res; + + apc->link_up = ar724x_pci_check_link(apc); + if (!apc->link_up) + dev_warn(&pdev->dev, "PCIe link is down\n"); -err_unmap_devcfg: - iounmap(ar724x_pci_devcfg_base); -err: - return ret; + ar724x_pci_irq_init(apc, id); + + ar724x_pci_local_write(apc, PCI_COMMAND, 4, AR724X_PCI_CMD_INIT); + + register_pci_controller(&apc->pci_controller); + + return 0; } + +static struct platform_driver ar724x_pci_driver = { + .probe = ar724x_pci_probe, + .driver = { + .name = "ar724x-pci", + .owner = THIS_MODULE, + }, +}; + +static int __init ar724x_pci_init(void) +{ + return platform_driver_register(&ar724x_pci_driver); +} + +postcore_initcall(ar724x_pci_init); diff --git a/arch/mips/pci/pci-bcm1480.c b/arch/mips/pci/pci-bcm1480.c index 37b52dc3d27..5ec2a7bae02 100644 --- a/arch/mips/pci/pci-bcm1480.c +++ b/arch/mips/pci/pci-bcm1480.c @@ -39,6 +39,7 @@ #include <linux/mm.h> #include <linux/console.h> #include <linux/tty.h> +#include <linux/vt.h> #include <asm/sibyte/bcm1480_regs.h> #include <asm/sibyte/bcm1480_scd.h> @@ -54,8 +55,8 @@ static void *cfg_space; -#define PCI_BUS_ENABLED 1 -#define PCI_DEVICE_MODE 2 +#define PCI_BUS_ENABLED 1 +#define PCI_DEVICE_MODE 2 static int bcm1480_bus_status; @@ -194,7 +195,7 @@ struct pci_controller bcm1480_controller = { .pci_ops = &bcm1480_pci_ops, .mem_resource = &bcm1480_mem_resource, .io_resource = &bcm1480_io_resource, - .io_offset = A_BCM1480_PHYS_PCI_IO_MATCH_BYTES, + .io_offset = A_BCM1480_PHYS_PCI_IO_MATCH_BYTES, }; @@ -227,7 +228,7 @@ static int __init bcm1480_pcibios_init(void) PCI_COMMAND)); if (!(cmdreg & PCI_COMMAND_MASTER)) { printk - ("PCI: Skipping PCI probe. Bus is not initialized.\n"); + ("PCI: Skipping PCI probe. Bus is not initialized.\n"); iounmap(cfg_space); return 1; /* XXX */ } @@ -257,7 +258,9 @@ static int __init bcm1480_pcibios_init(void) register_pci_controller(&bcm1480_controller); #ifdef CONFIG_VGA_CONSOLE - take_over_console(&vga_con, 0, MAX_NR_CONSOLES-1, 1); + console_lock(); + do_take_over_console(&vga_con, 0, MAX_NR_CONSOLES-1, 1); + console_unlock(); #endif return 0; } diff --git a/arch/mips/pci/pci-bcm1480ht.c b/arch/mips/pci/pci-bcm1480ht.c index 50cc6e9e824..1263c5e7dbe 100644 --- a/arch/mips/pci/pci-bcm1480ht.c +++ b/arch/mips/pci/pci-bcm1480ht.c @@ -53,8 +53,8 @@ static void *ht_cfg_space; -#define PCI_BUS_ENABLED 1 -#define PCI_DEVICE_MODE 2 +#define PCI_BUS_ENABLED 1 +#define PCI_DEVICE_MODE 2 static int bcm1480ht_bus_status; @@ -191,7 +191,7 @@ struct pci_controller bcm1480ht_controller = { .io_resource = &bcm1480ht_io_resource, .index = 1, .get_busno = bcm1480ht_pcibios_get_busno, - .io_offset = A_BCM1480_PHYS_HT_IO_MATCH_BYTES, + .io_offset = A_BCM1480_PHYS_HT_IO_MATCH_BYTES, }; static int __init bcm1480ht_pcibios_init(void) diff --git a/arch/mips/pci/pci-bcm47xx.c b/arch/mips/pci/pci-bcm47xx.c index c682468010c..76f16eaed0a 100644 --- a/arch/mips/pci/pci-bcm47xx.c +++ b/arch/mips/pci/pci-bcm47xx.c @@ -91,7 +91,7 @@ static int bcm47xx_pcibios_plat_dev_init_bcma(struct pci_dev *dev) int pcibios_plat_dev_init(struct pci_dev *dev) { #ifdef CONFIG_BCM47XX_SSB - if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_SSB) + if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_SSB) return bcm47xx_pcibios_plat_dev_init_ssb(dev); else #endif diff --git a/arch/mips/pci/pci-bcm63xx.c b/arch/mips/pci/pci-bcm63xx.c index ca179b6ff39..151d9b5870b 100644 --- a/arch/mips/pci/pci-bcm63xx.c +++ b/arch/mips/pci/pci-bcm63xx.c @@ -25,21 +25,21 @@ int bcm63xx_pci_enabled; static struct resource bcm_pci_mem_resource = { - .name = "bcm63xx PCI memory space", - .start = BCM_PCI_MEM_BASE_PA, - .end = BCM_PCI_MEM_END_PA, - .flags = IORESOURCE_MEM + .name = "bcm63xx PCI memory space", + .start = BCM_PCI_MEM_BASE_PA, + .end = BCM_PCI_MEM_END_PA, + .flags = IORESOURCE_MEM }; static struct resource bcm_pci_io_resource = { - .name = "bcm63xx PCI IO space", - .start = BCM_PCI_IO_BASE_PA, + .name = "bcm63xx PCI IO space", + .start = BCM_PCI_IO_BASE_PA, #ifdef CONFIG_CARDBUS - .end = BCM_PCI_IO_HALF_PA, + .end = BCM_PCI_IO_HALF_PA, #else - .end = BCM_PCI_IO_END_PA, + .end = BCM_PCI_IO_END_PA, #endif - .flags = IORESOURCE_IO + .flags = IORESOURCE_IO }; struct pci_controller bcm63xx_controller = { @@ -55,17 +55,17 @@ struct pci_controller bcm63xx_controller = { */ #ifdef CONFIG_CARDBUS static struct resource bcm_cb_mem_resource = { - .name = "bcm63xx Cardbus memory space", - .start = BCM_CB_MEM_BASE_PA, - .end = BCM_CB_MEM_END_PA, - .flags = IORESOURCE_MEM + .name = "bcm63xx Cardbus memory space", + .start = BCM_CB_MEM_BASE_PA, + .end = BCM_CB_MEM_END_PA, + .flags = IORESOURCE_MEM }; static struct resource bcm_cb_io_resource = { - .name = "bcm63xx Cardbus IO space", - .start = BCM_PCI_IO_HALF_PA + 1, - .end = BCM_PCI_IO_END_PA, - .flags = IORESOURCE_IO + .name = "bcm63xx Cardbus IO space", + .start = BCM_PCI_IO_HALF_PA + 1, + .end = BCM_PCI_IO_END_PA, + .flags = IORESOURCE_IO }; struct pci_controller bcm63xx_cb_controller = { @@ -76,17 +76,17 @@ struct pci_controller bcm63xx_cb_controller = { #endif static struct resource bcm_pcie_mem_resource = { - .name = "bcm63xx PCIe memory space", - .start = BCM_PCIE_MEM_BASE_PA, - .end = BCM_PCIE_MEM_END_PA, - .flags = IORESOURCE_MEM, + .name = "bcm63xx PCIe memory space", + .start = BCM_PCIE_MEM_BASE_PA, + .end = BCM_PCIE_MEM_END_PA, + .flags = IORESOURCE_MEM, }; static struct resource bcm_pcie_io_resource = { - .name = "bcm63xx PCIe IO space", - .start = 0, - .end = 0, - .flags = 0, + .name = "bcm63xx PCIe IO space", + .start = 0, + .end = 0, + .flags = 0, }; struct pci_controller bcm63xx_pcie_controller = { @@ -111,7 +111,7 @@ static void bcm63xx_int_cfg_writel(u32 val, u32 reg) u32 tmp; tmp = reg & MPI_PCICFGCTL_CFGADDR_MASK; - tmp |= MPI_PCICFGCTL_WRITEEN_MASK; + tmp |= MPI_PCICFGCTL_WRITEEN_MASK; bcm_mpi_writel(tmp, MPI_PCICFGCTL_REG); bcm_mpi_writel(val, MPI_PCICFGDATA_REG); } @@ -121,11 +121,17 @@ void __iomem *pci_iospace_start; static void __init bcm63xx_reset_pcie(void) { u32 val; + u32 reg; /* enable SERDES */ - val = bcm_misc_readl(MISC_SERDES_CTRL_REG); + if (BCMCPU_IS_6328()) + reg = MISC_SERDES_CTRL_6328_REG; + else + reg = MISC_SERDES_CTRL_6362_REG; + + val = bcm_misc_readl(reg); val |= SERDES_PCIE_EN | SERDES_PCIE_EXD_EN; - bcm_misc_writel(val, MISC_SERDES_CTRL_REG); + bcm_misc_writel(val, reg); /* reset the PCIe core */ bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 1); @@ -211,7 +217,7 @@ static int __init bcm63xx_register_pci(void) * first bytes to access it from CPU. * * this means that no io access from CPU should happen while - * we do a configuration cycle, but there's no way we can add + * we do a configuration cycle, but there's no way we can add * a spinlock for each io access, so this is currently kind of * broken on SMP. */ @@ -244,9 +250,9 @@ static int __init bcm63xx_register_pci(void) bcm_mpi_writel(0, MPI_L2PMEMREMAP2_REG); #endif - /* setup local bus to PCI access (IO memory), we have only 1 - * IO window for both PCI and cardbus, but it cannot handle - * both at the same time, assume standard PCI for now, if + /* setup local bus to PCI access (IO memory), we have only 1 + * IO window for both PCI and cardbus, but it cannot handle + * both at the same time, assume standard PCI for now, if * cardbus card has IO zone, PCI fixup will change window to * cardbus */ val = BCM_PCI_IO_BASE_PA & MPI_L2P_BASE_MASK; @@ -260,7 +266,7 @@ static int __init bcm63xx_register_pci(void) /* setup PCI to local bus access, used by PCI device to target * local RAM while bus mastering */ bcm63xx_int_cfg_writel(0, PCI_BASE_ADDRESS_3); - if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) + if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6368()) val = MPI_SP0_REMAP_ENABLE_MASK; else val = 0; @@ -284,7 +290,7 @@ static int __init bcm63xx_register_pci(void) bcm_mpi_writel(0, MPI_SP1_RANGE_REG); } - /* change host bridge retry counter to infinite number of + /* change host bridge retry counter to infinite number of * retry, needed for some broadcom wifi cards with Silicon * Backplane bus where access to srom seems very slow */ val = bcm63xx_int_cfg_readl(BCMPCI_REG_TIMERS); @@ -330,7 +336,9 @@ static int __init bcm63xx_pci_init(void) switch (bcm63xx_get_cpu_id()) { case BCM6328_CPU_ID: + case BCM6362_CPU_ID: return bcm63xx_register_pcie(); + case BCM3368_CPU_ID: case BCM6348_CPU_ID: case BCM6358_CPU_ID: case BCM6368_CPU_ID: diff --git a/arch/mips/pci/pci-bcm63xx.h b/arch/mips/pci/pci-bcm63xx.h index e6736d558ac..ffab4da7bd0 100644 --- a/arch/mips/pci/pci-bcm63xx.h +++ b/arch/mips/pci/pci-bcm63xx.h @@ -7,7 +7,7 @@ #include <bcm63xx_dev_pci.h> /* - * Cardbus shares the PCI bus, but has no IDSEL, so a special id is + * Cardbus shares the PCI bus, but has no IDSEL, so a special id is * reserved for it. If you have a standard PCI device at this id, you * need to change the following definition. */ diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index 7f4f49b09b5..0f09eafa5e3 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c @@ -7,7 +7,6 @@ * Copyright (C) 1999, 2000, 04 Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ -#include <linux/init.h> #include <linux/kernel.h> #include <linux/export.h> #include <linux/pci.h> @@ -30,7 +29,7 @@ /* * XXX: No kmalloc available when we do our crosstalk scan, - * we should try to move it later in the boot process. + * we should try to move it later in the boot process. */ static struct bridge_controller bridges[MAX_PCI_BUSSES]; @@ -42,7 +41,7 @@ int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; extern struct pci_ops bridge_pci_ops; -int __cpuinit bridge_probe(nasid_t nasid, int widget_id, int masterwid) +int bridge_probe(nasid_t nasid, int widget_id, int masterwid) { unsigned long offset = NODE_OFFSET(nasid); struct bridge_controller *bc; @@ -103,7 +102,7 @@ int __cpuinit bridge_probe(nasid_t nasid, int widget_id, int masterwid) * swap pio's to pci mem and io space (big windows) */ bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP | - BRIDGE_CTRL_MEM_SWAP; + BRIDGE_CTRL_MEM_SWAP; #ifdef CONFIG_PAGE_SIZE_4KB bridge->b_wid_control &= ~BRIDGE_CTRL_PAGE_SIZE; #else /* 16kB or larger */ @@ -123,7 +122,7 @@ int __cpuinit bridge_probe(nasid_t nasid, int widget_id, int masterwid) bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; bc->pci_int[slot] = -1; } - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ bc->base = bridge; @@ -184,7 +183,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev) } /* - * Device might live on a subordinate PCI bus. XXX Walk up the chain of buses + * Device might live on a subordinate PCI bus. XXX Walk up the chain of buses * to find the slot number in sense of the bridge device register. * XXX This also means multiple devices might rely on conflicting bridge * settings. @@ -217,6 +216,7 @@ static void pci_fixup_ioc3(struct pci_dev *d) pci_disable_swapping(d); } +#ifdef CONFIG_NUMA int pcibus_to_node(struct pci_bus *bus) { struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); @@ -224,6 +224,7 @@ int pcibus_to_node(struct pci_bus *bus) return bc->nasid; } EXPORT_SYMBOL(pcibus_to_node); +#endif /* CONFIG_NUMA */ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, pci_fixup_ioc3); diff --git a/arch/mips/pci/pci-ip32.c b/arch/mips/pci/pci-ip32.c index 532b561b444..b1e061f7fdc 100644 --- a/arch/mips/pci/pci-ip32.c +++ b/arch/mips/pci/pci-ip32.c @@ -18,9 +18,9 @@ /* * Handle errors from the bridge. This includes master and target aborts, - * various command and address errors, and the interrupt test. This gets - * registered on the bridge error irq. It's conceivable that some of these - * conditions warrant a panic. Anybody care to say which ones? + * various command and address errors, and the interrupt test. This gets + * registered on the bridge error irq. It's conceivable that some of these + * conditions warrant a panic. Anybody care to say which ones? */ static irqreturn_t macepci_error(int irq, void *dev) { diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c index 95681789b51..cb1ef998406 100644 --- a/arch/mips/pci/pci-lantiq.c +++ b/arch/mips/pci/pci-lantiq.c @@ -89,7 +89,7 @@ static inline u32 ltq_calc_bar11mask(void) u32 mem, bar11mask; /* BAR11MASK value depends on available memory on system. */ - mem = num_physpages * PAGE_SIZE; + mem = get_num_physpages() * PAGE_SIZE; bar11mask = (0x0ffffff0 & ~((1 << (fls(mem) - 1)) - 1)) | 8; return bar11mask; @@ -129,8 +129,16 @@ static int ltq_pci_startup(struct platform_device *pdev) /* setup reset gpio used by pci */ reset_gpio = of_get_named_gpio(node, "gpio-reset", 0); - if (gpio_is_valid(reset_gpio)) - devm_gpio_request(&pdev->dev, reset_gpio, "pci-reset"); + if (gpio_is_valid(reset_gpio)) { + int ret = devm_gpio_request(&pdev->dev, + reset_gpio, "pci-reset"); + if (ret) { + dev_err(&pdev->dev, + "failed to request gpio %d\n", reset_gpio); + return ret; + } + gpio_direction_output(reset_gpio, 1); + } /* enable auto-switching between PCI and EBU */ ltq_pci_w32(0xa, PCI_CR_CLK_CTRL); @@ -214,13 +222,13 @@ static int ltq_pci_probe(struct platform_device *pdev) return -EINVAL; } - ltq_pci_membase = devm_request_and_ioremap(&pdev->dev, res_bridge); - ltq_pci_mapped_cfg = devm_request_and_ioremap(&pdev->dev, res_cfg); + ltq_pci_membase = devm_ioremap_resource(&pdev->dev, res_bridge); + if (IS_ERR(ltq_pci_membase)) + return PTR_ERR(ltq_pci_membase); - if (!ltq_pci_membase || !ltq_pci_mapped_cfg) { - dev_err(&pdev->dev, "failed to remap resources\n"); - return -ENOMEM; - } + ltq_pci_mapped_cfg = devm_ioremap_resource(&pdev->dev, res_cfg); + if (IS_ERR(ltq_pci_mapped_cfg)) + return PTR_ERR(ltq_pci_mapped_cfg); ltq_pci_startup(pdev); diff --git a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c index a98e543a514..40d2797d2bc 100644 --- a/arch/mips/pci/pci-lasat.c +++ b/arch/mips/pci/pci-lasat.c @@ -51,15 +51,15 @@ static int __init lasat_pci_setup(void) arch_initcall(lasat_pci_setup); -#define LASAT_IRQ_ETH1 (LASAT_IRQ_BASE + 0) -#define LASAT_IRQ_ETH0 (LASAT_IRQ_BASE + 1) -#define LASAT_IRQ_HDC (LASAT_IRQ_BASE + 2) -#define LASAT_IRQ_COMP (LASAT_IRQ_BASE + 3) -#define LASAT_IRQ_HDLC (LASAT_IRQ_BASE + 4) -#define LASAT_IRQ_PCIA (LASAT_IRQ_BASE + 5) -#define LASAT_IRQ_PCIB (LASAT_IRQ_BASE + 6) -#define LASAT_IRQ_PCIC (LASAT_IRQ_BASE + 7) -#define LASAT_IRQ_PCID (LASAT_IRQ_BASE + 8) +#define LASAT_IRQ_ETH1 (LASAT_IRQ_BASE + 0) +#define LASAT_IRQ_ETH0 (LASAT_IRQ_BASE + 1) +#define LASAT_IRQ_HDC (LASAT_IRQ_BASE + 2) +#define LASAT_IRQ_COMP (LASAT_IRQ_BASE + 3) +#define LASAT_IRQ_HDLC (LASAT_IRQ_BASE + 4) +#define LASAT_IRQ_PCIA (LASAT_IRQ_BASE + 5) +#define LASAT_IRQ_PCIB (LASAT_IRQ_BASE + 6) +#define LASAT_IRQ_PCIC (LASAT_IRQ_BASE + 7) +#define LASAT_IRQ_PCID (LASAT_IRQ_BASE + 8) int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { @@ -69,13 +69,13 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) case 3: return LASAT_IRQ_PCIA + (((slot-1) + (pin-1)) % 4); case 4: - return LASAT_IRQ_ETH1; /* Ethernet 1 (LAN 2) */ + return LASAT_IRQ_ETH1; /* Ethernet 1 (LAN 2) */ case 5: - return LASAT_IRQ_ETH0; /* Ethernet 0 (LAN 1) */ + return LASAT_IRQ_ETH0; /* Ethernet 0 (LAN 1) */ case 6: - return LASAT_IRQ_HDC; /* IDE controller */ + return LASAT_IRQ_HDC; /* IDE controller */ default: - return 0xff; /* Illegal */ + return 0xff; /* Illegal */ } return -1; diff --git a/arch/mips/pci/pci-malta.c b/arch/mips/pci/pci-malta.c new file mode 100644 index 00000000000..cfbbc3e3e91 --- /dev/null +++ b/arch/mips/pci/pci-malta.c @@ -0,0 +1,254 @@ +/* + * Copyright (C) 1999, 2000, 2004, 2005 MIPS Technologies, Inc. + * All rights reserved. + * Authors: Carsten Langgaard <carstenl@mips.com> + * Maciej W. Rozycki <macro@mips.com> + * + * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * MIPS boards specific PCI support. + */ +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/kernel.h> +#include <linux/init.h> + +#include <asm/gt64120.h> +#include <asm/mips-cm.h> +#include <asm/mips-boards/generic.h> +#include <asm/mips-boards/bonito64.h> +#include <asm/mips-boards/msc01_pci.h> + +static struct resource bonito64_mem_resource = { + .name = "Bonito PCI MEM", + .flags = IORESOURCE_MEM, +}; + +static struct resource bonito64_io_resource = { + .name = "Bonito PCI I/O", + .start = 0x00000000UL, + .end = 0x000fffffUL, + .flags = IORESOURCE_IO, +}; + +static struct resource gt64120_mem_resource = { + .name = "GT-64120 PCI MEM", + .flags = IORESOURCE_MEM, +}; + +static struct resource gt64120_io_resource = { + .name = "GT-64120 PCI I/O", + .flags = IORESOURCE_IO, +}; + +static struct resource msc_mem_resource = { + .name = "MSC PCI MEM", + .flags = IORESOURCE_MEM, +}; + +static struct resource msc_io_resource = { + .name = "MSC PCI I/O", + .flags = IORESOURCE_IO, +}; + +extern struct pci_ops bonito64_pci_ops; +extern struct pci_ops gt64xxx_pci0_ops; +extern struct pci_ops msc_pci_ops; + +static struct pci_controller bonito64_controller = { + .pci_ops = &bonito64_pci_ops, + .io_resource = &bonito64_io_resource, + .mem_resource = &bonito64_mem_resource, + .io_offset = 0x00000000UL, +}; + +static struct pci_controller gt64120_controller = { + .pci_ops = >64xxx_pci0_ops, + .io_resource = >64120_io_resource, + .mem_resource = >64120_mem_resource, +}; + +static struct pci_controller msc_controller = { + .pci_ops = &msc_pci_ops, + .io_resource = &msc_io_resource, + .mem_resource = &msc_mem_resource, +}; + +void __init mips_pcibios_init(void) +{ + struct pci_controller *controller; + resource_size_t start, end, map, start1, end1, map1, map2, map3, mask; + + switch (mips_revision_sconid) { + case MIPS_REVISION_SCON_GT64120: + /* + * Due to a bug in the Galileo system controller, we need + * to setup the PCI BAR for the Galileo internal registers. + * This should be done in the bios/bootprom and will be + * fixed in a later revision of YAMON (the MIPS boards + * boot prom). + */ + GT_WRITE(GT_PCI0_CFGADDR_OFS, + (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */ + (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */ + (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/ + ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/ + GT_PCI0_CFGADDR_CONFIGEN_BIT); + + /* Perform the write */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE)); + + /* Set up resource ranges from the controller's registers. */ + start = GT_READ(GT_PCI0M0LD_OFS); + end = GT_READ(GT_PCI0M0HD_OFS); + map = GT_READ(GT_PCI0M0REMAP_OFS); + end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK); + start1 = GT_READ(GT_PCI0M1LD_OFS); + end1 = GT_READ(GT_PCI0M1HD_OFS); + map1 = GT_READ(GT_PCI0M1REMAP_OFS); + end1 = (end1 & GT_PCI_HD_MSK) | (start1 & ~GT_PCI_HD_MSK); + /* Cannot support multiple windows, use the wider. */ + if (end1 - start1 > end - start) { + start = start1; + end = end1; + map = map1; + } + mask = ~(start ^ end); + /* We don't support remapping with a discontiguous mask. */ + BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) && + mask != ~((mask & -mask) - 1)); + gt64120_mem_resource.start = start; + gt64120_mem_resource.end = end; + gt64120_controller.mem_offset = (start & mask) - (map & mask); + /* Addresses are 36-bit, so do shifts in the destinations. */ + gt64120_mem_resource.start <<= GT_PCI_DCRM_SHF; + gt64120_mem_resource.end <<= GT_PCI_DCRM_SHF; + gt64120_mem_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1; + gt64120_controller.mem_offset <<= GT_PCI_DCRM_SHF; + + start = GT_READ(GT_PCI0IOLD_OFS); + end = GT_READ(GT_PCI0IOHD_OFS); + map = GT_READ(GT_PCI0IOREMAP_OFS); + end = (end & GT_PCI_HD_MSK) | (start & ~GT_PCI_HD_MSK); + mask = ~(start ^ end); + /* We don't support remapping with a discontiguous mask. */ + BUG_ON((start & GT_PCI_HD_MSK) != (map & GT_PCI_HD_MSK) && + mask != ~((mask & -mask) - 1)); + gt64120_io_resource.start = map & mask; + gt64120_io_resource.end = (map & mask) | ~mask; + gt64120_controller.io_offset = 0; + /* Addresses are 36-bit, so do shifts in the destinations. */ + gt64120_io_resource.start <<= GT_PCI_DCRM_SHF; + gt64120_io_resource.end <<= GT_PCI_DCRM_SHF; + gt64120_io_resource.end |= (1 << GT_PCI_DCRM_SHF) - 1; + + controller = >64120_controller; + break; + + case MIPS_REVISION_SCON_BONITO: + /* Set up resource ranges from the controller's registers. */ + map = BONITO_PCIMAP; + map1 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO0) >> + BONITO_PCIMAP_PCIMAP_LO0_SHIFT; + map2 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO1) >> + BONITO_PCIMAP_PCIMAP_LO1_SHIFT; + map3 = (BONITO_PCIMAP & BONITO_PCIMAP_PCIMAP_LO2) >> + BONITO_PCIMAP_PCIMAP_LO2_SHIFT; + /* Combine as many adjacent windows as possible. */ + map = map1; + start = BONITO_PCILO0_BASE; + end = 1; + if (map3 == map2 + 1) { + map = map2; + start = BONITO_PCILO1_BASE; + end++; + } + if (map2 == map1 + 1) { + map = map1; + start = BONITO_PCILO0_BASE; + end++; + } + bonito64_mem_resource.start = start; + bonito64_mem_resource.end = start + + BONITO_PCIMAP_WINBASE(end) - 1; + bonito64_controller.mem_offset = start - + BONITO_PCIMAP_WINBASE(map); + + controller = &bonito64_controller; + break; + + case MIPS_REVISION_SCON_SOCIT: + case MIPS_REVISION_SCON_ROCIT: + case MIPS_REVISION_SCON_SOCITSC: + case MIPS_REVISION_SCON_SOCITSCP: + /* Set up resource ranges from the controller's registers. */ + MSC_READ(MSC01_PCI_SC2PMBASL, start); + MSC_READ(MSC01_PCI_SC2PMMSKL, mask); + MSC_READ(MSC01_PCI_SC2PMMAPL, map); + msc_mem_resource.start = start & mask; + msc_mem_resource.end = (start & mask) | ~mask; + msc_controller.mem_offset = (start & mask) - (map & mask); + if (mips_cm_numiocu()) { + write_gcr_reg0_base(start); + write_gcr_reg0_mask(mask | + CM_GCR_REGn_MASK_CMTGT_IOCU0); + } + MSC_READ(MSC01_PCI_SC2PIOBASL, start); + MSC_READ(MSC01_PCI_SC2PIOMSKL, mask); + MSC_READ(MSC01_PCI_SC2PIOMAPL, map); + msc_io_resource.start = map & mask; + msc_io_resource.end = (map & mask) | ~mask; + msc_controller.io_offset = 0; + ioport_resource.end = ~mask; + if (mips_cm_numiocu()) { + write_gcr_reg1_base(start); + write_gcr_reg1_mask(mask | + CM_GCR_REGn_MASK_CMTGT_IOCU0); + } + /* If ranges overlap I/O takes precedence. */ + start = start & mask; + end = start | ~mask; + if ((start >= msc_mem_resource.start && + start <= msc_mem_resource.end) || + (end >= msc_mem_resource.start && + end <= msc_mem_resource.end)) { + /* Use the larger space. */ + start = max(start, msc_mem_resource.start); + end = min(end, msc_mem_resource.end); + if (start - msc_mem_resource.start >= + msc_mem_resource.end - end) + msc_mem_resource.end = start - 1; + else + msc_mem_resource.start = end + 1; + } + + controller = &msc_controller; + break; + default: + return; + } + + /* PIIX4 ACPI starts at 0x1000 */ + if (controller->io_resource->start < 0x00001000UL) + controller->io_resource->start = 0x00001000UL; + + iomem_resource.end &= 0xfffffffffULL; /* 64 GB */ + ioport_resource.end = controller->io_resource->end; + + controller->io_map_base = mips_io_port_base; + + register_pci_controller(controller); +} diff --git a/arch/mips/pci/pci-octeon.c b/arch/mips/pci/pci-octeon.c index 5b5ed76c6f4..59cccd95688 100644 --- a/arch/mips/pci/pci-octeon.c +++ b/arch/mips/pci/pci-octeon.c @@ -30,8 +30,8 @@ * addresses. Use PCI endian swapping 1 so no address swapping is * necessary. The Linux io routines will endian swap the data. */ -#define OCTEON_PCI_IOSPACE_BASE 0x80011a0400000000ull -#define OCTEON_PCI_IOSPACE_SIZE (1ull<<32) +#define OCTEON_PCI_IOSPACE_BASE 0x80011a0400000000ull +#define OCTEON_PCI_IOSPACE_SIZE (1ull<<32) /* Octeon't PCI controller uses did=3, subdid=3 for PCI memory. */ #define OCTEON_PCI_MEMSPACE_OFFSET (0x00011b0000000000ull) @@ -68,10 +68,10 @@ enum octeon_dma_bar_type octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_INVALID; * * @dev: The Linux PCI device structure for the device to map * @slot: The slot number for this device on __BUS 0__. Linux - * enumerates through all the bridges and figures out the - * slot on Bus 0 where this device eventually hooks to. + * enumerates through all the bridges and figures out the + * slot on Bus 0 where this device eventually hooks to. * @pin: The PCI interrupt pin read from the device, then swizzled - * as it goes through each bridge. + * as it goes through each bridge. * Returns Interrupt number for the device */ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) @@ -120,8 +120,8 @@ int pcibios_plat_dev_init(struct pci_dev *dev) /* Enable the PCIe normal error reporting */ config = PCI_EXP_DEVCTL_CERE; /* Correctable Error Reporting */ config |= PCI_EXP_DEVCTL_NFERE; /* Non-Fatal Error Reporting */ - config |= PCI_EXP_DEVCTL_FERE; /* Fatal Error Reporting */ - config |= PCI_EXP_DEVCTL_URRE; /* Unsupported Request */ + config |= PCI_EXP_DEVCTL_FERE; /* Fatal Error Reporting */ + config |= PCI_EXP_DEVCTL_URRE; /* Unsupported Request */ pcie_capability_set_word(dev, PCI_EXP_DEVCTL, config); /* Find the Advanced Error Reporting capability */ @@ -226,10 +226,10 @@ const char *octeon_get_pci_interrupts(void) * * @dev: The Linux PCI device structure for the device to map * @slot: The slot number for this device on __BUS 0__. Linux - * enumerates through all the bridges and figures out the - * slot on Bus 0 where this device eventually hooks to. + * enumerates through all the bridges and figures out the + * slot on Bus 0 where this device eventually hooks to. * @pin: The PCI interrupt pin read from the device, then swizzled - * as it goes through each bridge. + * as it goes through each bridge. * Returns Interrupt number for the device */ int __init octeon_pci_pcibios_map_irq(const struct pci_dev *dev, @@ -404,8 +404,8 @@ static void octeon_pci_initialize(void) ctl_status_2.s.bb1_siz = 1; /* BAR1 is 2GB */ ctl_status_2.s.bb_ca = 1; /* Don't use L2 with big bars */ ctl_status_2.s.bb_es = 1; /* Big bar in byte swap mode */ - ctl_status_2.s.bb1 = 1; /* BAR1 is big */ - ctl_status_2.s.bb0 = 1; /* BAR0 is big */ + ctl_status_2.s.bb1 = 1; /* BAR1 is big */ + ctl_status_2.s.bb0 = 1; /* BAR0 is big */ } octeon_npi_write32(CVMX_NPI_PCI_CTL_STATUS_2, ctl_status_2.u32); @@ -446,7 +446,7 @@ static void octeon_pci_initialize(void) * count. [1..31] and 0=32. NOTE: If the user * programs these bits beyond the Designed Maximum * outstanding count, then the designed maximum table - * depth will be used instead. No additional + * depth will be used instead. No additional * Deferred/Split transactions will be accepted if * this outstanding maximum count is * reached. Furthermore, no additional deferred/split @@ -456,7 +456,7 @@ static void octeon_pci_initialize(void) cfg19.s.tdomc = 4; /* * Master Deferred Read Request Outstanding Max Count - * (PCI only). CR4C[26:24] Max SAC cycles MAX DAC + * (PCI only). CR4C[26:24] Max SAC cycles MAX DAC * cycles 000 8 4 001 1 0 010 2 1 011 3 1 100 4 2 101 * 5 2 110 6 3 111 7 3 For example, if these bits are * programmed to 100, the core can support 2 DAC @@ -550,7 +550,7 @@ static void octeon_pci_initialize(void) /* * Affects PCI performance when OCTEON services reads to its - * BAR1/BAR2. Refer to Section 10.6.1. The recommended values are + * BAR1/BAR2. Refer to Section 10.6.1. The recommended values are * 0x22, 0x33, and 0x33 for PCI_READ_CMD_6, PCI_READ_CMD_C, and * PCI_READ_CMD_E, respectively. Unfortunately due to errata DDR-700, * these values need to be changed so they won't possibly prefetch off @@ -586,15 +586,16 @@ static int __init octeon_pci_setup(void) else octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_BIG; - /* PCI I/O and PCI MEM values */ - set_io_port_base(OCTEON_PCI_IOSPACE_BASE); - ioport_resource.start = 0; - ioport_resource.end = OCTEON_PCI_IOSPACE_SIZE - 1; if (!octeon_is_pci_host()) { pr_notice("Not in host mode, PCI Controller not initialized\n"); return 0; } + /* PCI I/O and PCI MEM values */ + set_io_port_base(OCTEON_PCI_IOSPACE_BASE); + ioport_resource.start = 0; + ioport_resource.end = OCTEON_PCI_IOSPACE_SIZE - 1; + pr_notice("%s Octeon big bar support\n", (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_BIG) ? "Enabling" : "Disabling"); diff --git a/arch/mips/pci/pci-rc32434.c b/arch/mips/pci/pci-rc32434.c index 5f3a69cebad..7f6ce6d734c 100644 --- a/arch/mips/pci/pci-rc32434.c +++ b/arch/mips/pci/pci-rc32434.c @@ -33,7 +33,7 @@ #include <asm/mach-rc32434/rc32434.h> #include <asm/mach-rc32434/pci.h> -#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_READ 0 #define PCI_ACCESS_WRITE 1 /* define an unsigned array for the PCI registers */ @@ -53,7 +53,6 @@ static struct resource rc32434_res_pci_mem1 = { .start = 0x50000000, .end = 0x5FFFFFFF, .flags = IORESOURCE_MEM, - .parent = &rc32434_res_pci_mem1, .sibling = NULL, .child = &rc32434_res_pci_mem2 }; @@ -82,11 +81,11 @@ extern struct pci_ops rc32434_pci_ops; #define PCI_MEM2_START (PCI_ADDR_START + CPUTOPCI_MEM_WIN) #define PCI_MEM2_END (PCI_ADDR_START + (2 * CPUTOPCI_MEM_WIN) - 1) #define PCI_IO1_START (PCI_ADDR_START + (2 * CPUTOPCI_MEM_WIN)) -#define PCI_IO1_END \ +#define PCI_IO1_END \ (PCI_ADDR_START + (2 * CPUTOPCI_MEM_WIN) + CPUTOPCI_IO_WIN - 1) #define PCI_IO2_START \ (PCI_ADDR_START + (2 * CPUTOPCI_MEM_WIN) + CPUTOPCI_IO_WIN) -#define PCI_IO2_END \ +#define PCI_IO2_END \ (PCI_ADDR_START + (2 * CPUTOPCI_MEM_WIN) + (2 * CPUTOPCI_IO_WIN) - 1) struct pci_controller rc32434_controller2; diff --git a/arch/mips/pci/pci-rt3883.c b/arch/mips/pci/pci-rt3883.c new file mode 100644 index 00000000000..72919aeef42 --- /dev/null +++ b/arch/mips/pci/pci-rt3883.c @@ -0,0 +1,611 @@ +/* + * Ralink RT3662/RT3883 SoC PCI support + * + * Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org> + * + * Parts of this file are based on Ralink's 2.6.21 BSP + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include <linux/types.h> +#include <linux/pci.h> +#include <linux/io.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_irq.h> +#include <linux/of_pci.h> +#include <linux/platform_device.h> + +#include <asm/mach-ralink/rt3883.h> +#include <asm/mach-ralink/ralink_regs.h> + +#define RT3883_MEMORY_BASE 0x00000000 +#define RT3883_MEMORY_SIZE 0x02000000 + +#define RT3883_PCI_REG_PCICFG 0x00 +#define RT3883_PCICFG_P2P_BR_DEVNUM_M 0xf +#define RT3883_PCICFG_P2P_BR_DEVNUM_S 16 +#define RT3883_PCICFG_PCIRST BIT(1) +#define RT3883_PCI_REG_PCIRAW 0x04 +#define RT3883_PCI_REG_PCIINT 0x08 +#define RT3883_PCI_REG_PCIENA 0x0c + +#define RT3883_PCI_REG_CFGADDR 0x20 +#define RT3883_PCI_REG_CFGDATA 0x24 +#define RT3883_PCI_REG_MEMBASE 0x28 +#define RT3883_PCI_REG_IOBASE 0x2c +#define RT3883_PCI_REG_ARBCTL 0x80 + +#define RT3883_PCI_REG_BASE(_x) (0x1000 + (_x) * 0x1000) +#define RT3883_PCI_REG_BAR0SETUP(_x) (RT3883_PCI_REG_BASE((_x)) + 0x10) +#define RT3883_PCI_REG_IMBASEBAR0(_x) (RT3883_PCI_REG_BASE((_x)) + 0x18) +#define RT3883_PCI_REG_ID(_x) (RT3883_PCI_REG_BASE((_x)) + 0x30) +#define RT3883_PCI_REG_CLASS(_x) (RT3883_PCI_REG_BASE((_x)) + 0x34) +#define RT3883_PCI_REG_SUBID(_x) (RT3883_PCI_REG_BASE((_x)) + 0x38) +#define RT3883_PCI_REG_STATUS(_x) (RT3883_PCI_REG_BASE((_x)) + 0x50) + +#define RT3883_PCI_MODE_NONE 0 +#define RT3883_PCI_MODE_PCI BIT(0) +#define RT3883_PCI_MODE_PCIE BIT(1) +#define RT3883_PCI_MODE_BOTH (RT3883_PCI_MODE_PCI | RT3883_PCI_MODE_PCIE) + +#define RT3883_PCI_IRQ_COUNT 32 + +#define RT3883_P2P_BR_DEVNUM 1 + +struct rt3883_pci_controller { + void __iomem *base; + spinlock_t lock; + + struct device_node *intc_of_node; + struct irq_domain *irq_domain; + + struct pci_controller pci_controller; + struct resource io_res; + struct resource mem_res; + + bool pcie_ready; +}; + +static inline struct rt3883_pci_controller * +pci_bus_to_rt3883_controller(struct pci_bus *bus) +{ + struct pci_controller *hose; + + hose = (struct pci_controller *) bus->sysdata; + return container_of(hose, struct rt3883_pci_controller, pci_controller); +} + +static inline u32 rt3883_pci_r32(struct rt3883_pci_controller *rpc, + unsigned reg) +{ + return ioread32(rpc->base + reg); +} + +static inline void rt3883_pci_w32(struct rt3883_pci_controller *rpc, + u32 val, unsigned reg) +{ + iowrite32(val, rpc->base + reg); +} + +static inline u32 rt3883_pci_get_cfgaddr(unsigned int bus, unsigned int slot, + unsigned int func, unsigned int where) +{ + return (bus << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | + 0x80000000; +} + +static u32 rt3883_pci_read_cfg32(struct rt3883_pci_controller *rpc, + unsigned bus, unsigned slot, + unsigned func, unsigned reg) +{ + unsigned long flags; + u32 address; + u32 ret; + + address = rt3883_pci_get_cfgaddr(bus, slot, func, reg); + + spin_lock_irqsave(&rpc->lock, flags); + rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); + ret = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); + spin_unlock_irqrestore(&rpc->lock, flags); + + return ret; +} + +static void rt3883_pci_write_cfg32(struct rt3883_pci_controller *rpc, + unsigned bus, unsigned slot, + unsigned func, unsigned reg, u32 val) +{ + unsigned long flags; + u32 address; + + address = rt3883_pci_get_cfgaddr(bus, slot, func, reg); + + spin_lock_irqsave(&rpc->lock, flags); + rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); + rt3883_pci_w32(rpc, val, RT3883_PCI_REG_CFGDATA); + spin_unlock_irqrestore(&rpc->lock, flags); +} + +static void rt3883_pci_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + struct rt3883_pci_controller *rpc; + u32 pending; + + rpc = irq_get_handler_data(irq); + + pending = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIINT) & + rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); + + if (!pending) { + spurious_interrupt(); + return; + } + + while (pending) { + unsigned bit = __ffs(pending); + + irq = irq_find_mapping(rpc->irq_domain, bit); + generic_handle_irq(irq); + + pending &= ~BIT(bit); + } +} + +static void rt3883_pci_irq_unmask(struct irq_data *d) +{ + struct rt3883_pci_controller *rpc; + u32 t; + + rpc = irq_data_get_irq_chip_data(d); + + t = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); + rt3883_pci_w32(rpc, t | BIT(d->hwirq), RT3883_PCI_REG_PCIENA); + /* flush write */ + rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); +} + +static void rt3883_pci_irq_mask(struct irq_data *d) +{ + struct rt3883_pci_controller *rpc; + u32 t; + + rpc = irq_data_get_irq_chip_data(d); + + t = rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); + rt3883_pci_w32(rpc, t & ~BIT(d->hwirq), RT3883_PCI_REG_PCIENA); + /* flush write */ + rt3883_pci_r32(rpc, RT3883_PCI_REG_PCIENA); +} + +static struct irq_chip rt3883_pci_irq_chip = { + .name = "RT3883 PCI", + .irq_mask = rt3883_pci_irq_mask, + .irq_unmask = rt3883_pci_irq_unmask, + .irq_mask_ack = rt3883_pci_irq_mask, +}; + +static int rt3883_pci_irq_map(struct irq_domain *d, unsigned int irq, + irq_hw_number_t hw) +{ + irq_set_chip_and_handler(irq, &rt3883_pci_irq_chip, handle_level_irq); + irq_set_chip_data(irq, d->host_data); + + return 0; +} + +static const struct irq_domain_ops rt3883_pci_irq_domain_ops = { + .map = rt3883_pci_irq_map, + .xlate = irq_domain_xlate_onecell, +}; + +static int rt3883_pci_irq_init(struct device *dev, + struct rt3883_pci_controller *rpc) +{ + int irq; + + irq = irq_of_parse_and_map(rpc->intc_of_node, 0); + if (irq == 0) { + dev_err(dev, "%s has no IRQ", + of_node_full_name(rpc->intc_of_node)); + return -EINVAL; + } + + /* disable all interrupts */ + rt3883_pci_w32(rpc, 0, RT3883_PCI_REG_PCIENA); + + rpc->irq_domain = + irq_domain_add_linear(rpc->intc_of_node, RT3883_PCI_IRQ_COUNT, + &rt3883_pci_irq_domain_ops, + rpc); + if (!rpc->irq_domain) { + dev_err(dev, "unable to add IRQ domain\n"); + return -ENODEV; + } + + irq_set_handler_data(irq, rpc); + irq_set_chained_handler(irq, rt3883_pci_irq_handler); + + return 0; +} + +static int rt3883_pci_config_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) +{ + struct rt3883_pci_controller *rpc; + unsigned long flags; + u32 address; + u32 data; + + rpc = pci_bus_to_rt3883_controller(bus); + + if (!rpc->pcie_ready && bus->number == 1) + return PCIBIOS_DEVICE_NOT_FOUND; + + address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), + PCI_FUNC(devfn), where); + + spin_lock_irqsave(&rpc->lock, flags); + rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); + data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); + spin_unlock_irqrestore(&rpc->lock, flags); + + switch (size) { + case 1: + *val = (data >> ((where & 3) << 3)) & 0xff; + break; + case 2: + *val = (data >> ((where & 3) << 3)) & 0xffff; + break; + case 4: + *val = data; + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int rt3883_pci_config_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + struct rt3883_pci_controller *rpc; + unsigned long flags; + u32 address; + u32 data; + + rpc = pci_bus_to_rt3883_controller(bus); + + if (!rpc->pcie_ready && bus->number == 1) + return PCIBIOS_DEVICE_NOT_FOUND; + + address = rt3883_pci_get_cfgaddr(bus->number, PCI_SLOT(devfn), + PCI_FUNC(devfn), where); + + spin_lock_irqsave(&rpc->lock, flags); + rt3883_pci_w32(rpc, address, RT3883_PCI_REG_CFGADDR); + data = rt3883_pci_r32(rpc, RT3883_PCI_REG_CFGDATA); + + switch (size) { + case 1: + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + break; + case 2: + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + break; + case 4: + data = val; + break; + } + + rt3883_pci_w32(rpc, data, RT3883_PCI_REG_CFGDATA); + spin_unlock_irqrestore(&rpc->lock, flags); + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops rt3883_pci_ops = { + .read = rt3883_pci_config_read, + .write = rt3883_pci_config_write, +}; + +static void rt3883_pci_preinit(struct rt3883_pci_controller *rpc, unsigned mode) +{ + u32 syscfg1; + u32 rstctrl; + u32 clkcfg1; + u32 t; + + rstctrl = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL); + syscfg1 = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG1); + clkcfg1 = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1); + + if (mode & RT3883_PCI_MODE_PCIE) { + rstctrl |= RT3883_RSTCTRL_PCIE; + rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL); + + /* setup PCI PAD drive mode */ + syscfg1 &= ~(0x30); + syscfg1 |= (2 << 4); + rt_sysc_w32(syscfg1, RT3883_SYSC_REG_SYSCFG1); + + t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0); + t &= ~BIT(31); + rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0); + + t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN1); + t &= 0x80ffffff; + rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN1); + + t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN1); + t |= 0xa << 24; + rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN1); + + t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0); + t |= BIT(31); + rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0); + + msleep(50); + + rstctrl &= ~RT3883_RSTCTRL_PCIE; + rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL); + } + + syscfg1 |= (RT3883_SYSCFG1_PCIE_RC_MODE | RT3883_SYSCFG1_PCI_HOST_MODE); + + clkcfg1 &= ~(RT3883_CLKCFG1_PCI_CLK_EN | RT3883_CLKCFG1_PCIE_CLK_EN); + + if (mode & RT3883_PCI_MODE_PCI) { + clkcfg1 |= RT3883_CLKCFG1_PCI_CLK_EN; + rstctrl &= ~RT3883_RSTCTRL_PCI; + } + + if (mode & RT3883_PCI_MODE_PCIE) { + clkcfg1 |= RT3883_CLKCFG1_PCIE_CLK_EN; + rstctrl &= ~RT3883_RSTCTRL_PCIE; + } + + rt_sysc_w32(syscfg1, RT3883_SYSC_REG_SYSCFG1); + rt_sysc_w32(rstctrl, RT3883_SYSC_REG_RSTCTRL); + rt_sysc_w32(clkcfg1, RT3883_SYSC_REG_CLKCFG1); + + msleep(500); + + /* + * setup the device number of the P2P bridge + * and de-assert the reset line + */ + t = (RT3883_P2P_BR_DEVNUM << RT3883_PCICFG_P2P_BR_DEVNUM_S); + rt3883_pci_w32(rpc, t, RT3883_PCI_REG_PCICFG); + + /* flush write */ + rt3883_pci_r32(rpc, RT3883_PCI_REG_PCICFG); + msleep(500); + + if (mode & RT3883_PCI_MODE_PCIE) { + msleep(500); + + t = rt3883_pci_r32(rpc, RT3883_PCI_REG_STATUS(1)); + + rpc->pcie_ready = t & BIT(0); + + if (!rpc->pcie_ready) { + /* reset the PCIe block */ + t = rt_sysc_r32(RT3883_SYSC_REG_RSTCTRL); + t |= RT3883_RSTCTRL_PCIE; + rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL); + t &= ~RT3883_RSTCTRL_PCIE; + rt_sysc_w32(t, RT3883_SYSC_REG_RSTCTRL); + + /* turn off PCIe clock */ + t = rt_sysc_r32(RT3883_SYSC_REG_CLKCFG1); + t &= ~RT3883_CLKCFG1_PCIE_CLK_EN; + rt_sysc_w32(t, RT3883_SYSC_REG_CLKCFG1); + + t = rt_sysc_r32(RT3883_SYSC_REG_PCIE_CLK_GEN0); + t &= ~0xf000c080; + rt_sysc_w32(t, RT3883_SYSC_REG_PCIE_CLK_GEN0); + } + } + + /* enable PCI arbiter */ + rt3883_pci_w32(rpc, 0x79, RT3883_PCI_REG_ARBCTL); +} + +static int rt3883_pci_probe(struct platform_device *pdev) +{ + struct rt3883_pci_controller *rpc; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct resource *res; + struct device_node *child; + u32 val; + int err; + int mode; + + rpc = devm_kzalloc(dev, sizeof(*rpc), GFP_KERNEL); + if (!rpc) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + rpc->base = devm_ioremap_resource(dev, res); + if (IS_ERR(rpc->base)) + return PTR_ERR(rpc->base); + + /* find the interrupt controller child node */ + for_each_child_of_node(np, child) { + if (of_get_property(child, "interrupt-controller", NULL) && + of_node_get(child)) { + rpc->intc_of_node = child; + break; + } + } + + if (!rpc->intc_of_node) { + dev_err(dev, "%s has no %s child node", + of_node_full_name(rpc->intc_of_node), + "interrupt controller"); + return -EINVAL; + } + + /* find the PCI host bridge child node */ + for_each_child_of_node(np, child) { + if (child->type && + of_node_cmp(child->type, "pci") == 0 && + of_node_get(child)) { + rpc->pci_controller.of_node = child; + break; + } + } + + if (!rpc->pci_controller.of_node) { + dev_err(dev, "%s has no %s child node", + of_node_full_name(rpc->intc_of_node), + "PCI host bridge"); + err = -EINVAL; + goto err_put_intc_node; + } + + mode = RT3883_PCI_MODE_NONE; + for_each_available_child_of_node(rpc->pci_controller.of_node, child) { + int devfn; + + if (!child->type || + of_node_cmp(child->type, "pci") != 0) + continue; + + devfn = of_pci_get_devfn(child); + if (devfn < 0) + continue; + + switch (PCI_SLOT(devfn)) { + case 1: + mode |= RT3883_PCI_MODE_PCIE; + break; + + case 17: + case 18: + mode |= RT3883_PCI_MODE_PCI; + break; + } + } + + if (mode == RT3883_PCI_MODE_NONE) { + dev_err(dev, "unable to determine PCI mode\n"); + err = -EINVAL; + goto err_put_hb_node; + } + + dev_info(dev, "mode:%s%s\n", + (mode & RT3883_PCI_MODE_PCI) ? " PCI" : "", + (mode & RT3883_PCI_MODE_PCIE) ? " PCIe" : ""); + + rt3883_pci_preinit(rpc, mode); + + rpc->pci_controller.pci_ops = &rt3883_pci_ops; + rpc->pci_controller.io_resource = &rpc->io_res; + rpc->pci_controller.mem_resource = &rpc->mem_res; + + /* Load PCI I/O and memory resources from DT */ + pci_load_of_ranges(&rpc->pci_controller, + rpc->pci_controller.of_node); + + rt3883_pci_w32(rpc, rpc->mem_res.start, RT3883_PCI_REG_MEMBASE); + rt3883_pci_w32(rpc, rpc->io_res.start, RT3883_PCI_REG_IOBASE); + + ioport_resource.start = rpc->io_res.start; + ioport_resource.end = rpc->io_res.end; + + /* PCI */ + rt3883_pci_w32(rpc, 0x03ff0000, RT3883_PCI_REG_BAR0SETUP(0)); + rt3883_pci_w32(rpc, RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0(0)); + rt3883_pci_w32(rpc, 0x08021814, RT3883_PCI_REG_ID(0)); + rt3883_pci_w32(rpc, 0x00800001, RT3883_PCI_REG_CLASS(0)); + rt3883_pci_w32(rpc, 0x28801814, RT3883_PCI_REG_SUBID(0)); + + /* PCIe */ + rt3883_pci_w32(rpc, 0x03ff0000, RT3883_PCI_REG_BAR0SETUP(1)); + rt3883_pci_w32(rpc, RT3883_MEMORY_BASE, RT3883_PCI_REG_IMBASEBAR0(1)); + rt3883_pci_w32(rpc, 0x08021814, RT3883_PCI_REG_ID(1)); + rt3883_pci_w32(rpc, 0x06040001, RT3883_PCI_REG_CLASS(1)); + rt3883_pci_w32(rpc, 0x28801814, RT3883_PCI_REG_SUBID(1)); + + err = rt3883_pci_irq_init(dev, rpc); + if (err) + goto err_put_hb_node; + + /* PCIe */ + val = rt3883_pci_read_cfg32(rpc, 0, 0x01, 0, PCI_COMMAND); + val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + rt3883_pci_write_cfg32(rpc, 0, 0x01, 0, PCI_COMMAND, val); + + /* PCI */ + val = rt3883_pci_read_cfg32(rpc, 0, 0x00, 0, PCI_COMMAND); + val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; + rt3883_pci_write_cfg32(rpc, 0, 0x00, 0, PCI_COMMAND, val); + + if (mode == RT3883_PCI_MODE_PCIE) { + rt3883_pci_w32(rpc, 0x03ff0001, RT3883_PCI_REG_BAR0SETUP(0)); + rt3883_pci_w32(rpc, 0x03ff0001, RT3883_PCI_REG_BAR0SETUP(1)); + + rt3883_pci_write_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0, + PCI_BASE_ADDRESS_0, + RT3883_MEMORY_BASE); + /* flush write */ + rt3883_pci_read_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0, + PCI_BASE_ADDRESS_0); + } else { + rt3883_pci_write_cfg32(rpc, 0, RT3883_P2P_BR_DEVNUM, 0, + PCI_IO_BASE, 0x00000101); + } + + register_pci_controller(&rpc->pci_controller); + + return 0; + +err_put_hb_node: + of_node_put(rpc->pci_controller.of_node); +err_put_intc_node: + of_node_put(rpc->intc_of_node); + return err; +} + +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + return of_irq_parse_and_map_pci(dev, slot, pin); +} + +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} + +static const struct of_device_id rt3883_pci_ids[] = { + { .compatible = "ralink,rt3883-pci" }, + {}, +}; +MODULE_DEVICE_TABLE(of, rt3883_pci_ids); + +static struct platform_driver rt3883_pci_driver = { + .probe = rt3883_pci_probe, + .driver = { + .name = "rt3883-pci", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(rt3883_pci_ids), + }, +}; + +static int __init rt3883_pci_init(void) +{ + return platform_driver_register(&rt3883_pci_driver); +} + +postcore_initcall(rt3883_pci_init); diff --git a/arch/mips/pci/pci-sb1250.c b/arch/mips/pci/pci-sb1250.c index dd97f3a83ba..fc634aeda4a 100644 --- a/arch/mips/pci/pci-sb1250.c +++ b/arch/mips/pci/pci-sb1250.c @@ -55,9 +55,9 @@ static void *cfg_space; -#define PCI_BUS_ENABLED 1 -#define LDT_BUS_ENABLED 2 -#define PCI_DEVICE_MODE 4 +#define PCI_BUS_ENABLED 1 +#define LDT_BUS_ENABLED 2 +#define PCI_DEVICE_MODE 4 static int sb1250_bus_status; @@ -239,7 +239,7 @@ static int __init sb1250_pcibios_init(void) PCI_COMMAND)); if (!(cmdreg & PCI_COMMAND_MASTER)) { printk - ("PCI: Skipping PCI probe. Bus is not initialized.\n"); + ("PCI: Skipping PCI probe. Bus is not initialized.\n"); iounmap(cfg_space); return 0; } @@ -283,7 +283,9 @@ static int __init sb1250_pcibios_init(void) register_pci_controller(&sb1250_controller); #ifdef CONFIG_VGA_CONSOLE - take_over_console(&vga_con, 0, MAX_NR_CONSOLES - 1, 1); + console_lock(); + do_take_over_console(&vga_con, 0, MAX_NR_CONSOLES - 1, 1); + console_unlock(); #endif return 0; } diff --git a/arch/mips/pci/pci-virtio-guest.c b/arch/mips/pci/pci-virtio-guest.c new file mode 100644 index 00000000000..40a078bc461 --- /dev/null +++ b/arch/mips/pci/pci-virtio-guest.c @@ -0,0 +1,131 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2013 Cavium, Inc. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/pci.h> + +#include <uapi/asm/bitfield.h> +#include <asm/byteorder.h> +#include <asm/io.h> + +#define PCI_CONFIG_ADDRESS 0xcf8 +#define PCI_CONFIG_DATA 0xcfc + +union pci_config_address { + struct { + __BITFIELD_FIELD(unsigned enable_bit : 1, /* 31 */ + __BITFIELD_FIELD(unsigned reserved : 7, /* 30 .. 24 */ + __BITFIELD_FIELD(unsigned bus_number : 8, /* 23 .. 16 */ + __BITFIELD_FIELD(unsigned devfn_number : 8, /* 15 .. 8 */ + __BITFIELD_FIELD(unsigned register_number : 8, /* 7 .. 0 */ + ))))); + }; + u32 w; +}; + +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} + +int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + return ((pin + slot) % 4)+ MIPS_IRQ_PCIA; +} + +static void pci_virtio_guest_write_config_addr(struct pci_bus *bus, + unsigned int devfn, int reg) +{ + union pci_config_address pca = { .w = 0 }; + + pca.register_number = reg; + pca.devfn_number = devfn; + pca.bus_number = bus->number; + pca.enable_bit = 1; + + outl(pca.w, PCI_CONFIG_ADDRESS); +} + +static int pci_virtio_guest_write_config(struct pci_bus *bus, + unsigned int devfn, int reg, int size, u32 val) +{ + pci_virtio_guest_write_config_addr(bus, devfn, reg); + + switch (size) { + case 1: + outb(val, PCI_CONFIG_DATA + (reg & 3)); + break; + case 2: + outw(val, PCI_CONFIG_DATA + (reg & 2)); + break; + case 4: + outl(val, PCI_CONFIG_DATA); + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_virtio_guest_read_config(struct pci_bus *bus, unsigned int devfn, + int reg, int size, u32 *val) +{ + pci_virtio_guest_write_config_addr(bus, devfn, reg); + + switch (size) { + case 1: + *val = inb(PCI_CONFIG_DATA + (reg & 3)); + break; + case 2: + *val = inw(PCI_CONFIG_DATA + (reg & 2)); + break; + case 4: + *val = inl(PCI_CONFIG_DATA); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops pci_virtio_guest_ops = { + .read = pci_virtio_guest_read_config, + .write = pci_virtio_guest_write_config, +}; + +static struct resource pci_virtio_guest_mem_resource = { + .name = "Virtio MEM", + .flags = IORESOURCE_MEM, + .start = 0x10000000, + .end = 0x1dffffff +}; + +static struct resource pci_virtio_guest_io_resource = { + .name = "Virtio IO", + .flags = IORESOURCE_IO, + .start = 0, + .end = 0xffff +}; + +static struct pci_controller pci_virtio_guest_controller = { + .pci_ops = &pci_virtio_guest_ops, + .mem_resource = &pci_virtio_guest_mem_resource, + .io_resource = &pci_virtio_guest_io_resource, +}; + +static int __init pci_virtio_guest_setup(void) +{ + pr_err("pci_virtio_guest_setup\n"); + + /* Virtio comes pre-assigned */ + pci_set_flags(PCI_PROBE_ONLY); + + pci_virtio_guest_controller.io_map_base = mips_io_port_base; + register_pci_controller(&pci_virtio_guest_controller); + return 0; +} +arch_initcall(pci_virtio_guest_setup); diff --git a/arch/mips/pci/pci-vr41xx.c b/arch/mips/pci/pci-vr41xx.c index 444b8d8004a..157c7715b7c 100644 --- a/arch/mips/pci/pci-vr41xx.c +++ b/arch/mips/pci/pci-vr41xx.c @@ -69,17 +69,17 @@ static struct pci_target_address_window pci_target_window1 = { }; static struct resource pci_mem_resource = { - .name = "PCI Memory resources", - .start = PCI_MEM_RESOURCE_START, - .end = PCI_MEM_RESOURCE_END, - .flags = IORESOURCE_MEM, + .name = "PCI Memory resources", + .start = PCI_MEM_RESOURCE_START, + .end = PCI_MEM_RESOURCE_END, + .flags = IORESOURCE_MEM, }; static struct resource pci_io_resource = { - .name = "PCI I/O resources", - .start = PCI_IO_RESOURCE_START, - .end = PCI_IO_RESOURCE_END, - .flags = IORESOURCE_IO, + .name = "PCI I/O resources", + .start = PCI_IO_RESOURCE_START, + .end = PCI_IO_RESOURCE_END, + .flags = IORESOURCE_IO, }; static struct pci_controller_unit_setup vr41xx_pci_controller_unit_setup = { @@ -97,7 +97,7 @@ static struct pci_controller_unit_setup vr41xx_pci_controller_unit_setup = { }; static struct pci_controller vr41xx_pci_controller = { - .pci_ops = &vr41xx_pci_ops, + .pci_ops = &vr41xx_pci_ops, .mem_resource = &pci_mem_resource, .io_resource = &pci_io_resource, }; @@ -148,7 +148,7 @@ static int __init vr41xx_pciu_init(void) else if ((vtclock / 2) < pci_clock_max) pciu_write(PCICLKSELREG, HALF_VTCLOCK); else if (current_cpu_data.processor_id >= PRID_VR4131_REV2_1 && - (vtclock / 3) < pci_clock_max) + (vtclock / 3) < pci_clock_max) pciu_write(PCICLKSELREG, ONE_THIRD_VTCLOCK); else if ((vtclock / 4) < pci_clock_max) pciu_write(PCICLKSELREG, QUARTER_VTCLOCK); @@ -281,7 +281,7 @@ static int __init vr41xx_pciu_init(void) pciu_write(PCIAPCNTREG, val); pciu_write(COMMANDREG, PCI_COMMAND_IO | PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER | PCI_COMMAND_PARITY | + PCI_COMMAND_MASTER | PCI_COMMAND_PARITY | PCI_COMMAND_SERR); /* Clear bus error */ diff --git a/arch/mips/pci/pci-vr41xx.h b/arch/mips/pci/pci-vr41xx.h index 6b1ae2eb1c0..e6b4a1b969f 100644 --- a/arch/mips/pci/pci-vr41xx.h +++ b/arch/mips/pci/pci-vr41xx.h @@ -1,7 +1,7 @@ /* * pci-vr41xx.h, Include file for PCI Control Unit of the NEC VR4100 series. * - * Copyright (C) 2002 MontaVista Software Inc. + * Copyright (C) 2002 MontaVista Software Inc. * Author: Yoichi Yuasa <source@mvista.com> * Copyright (C) 2004-2005 Yoichi Yuasa <yuasa@linux-mips.org> * diff --git a/arch/mips/pci/pci-xlp.c b/arch/mips/pci/pci-xlp.c index 140557a2048..7babf01600c 100644 --- a/arch/mips/pci/pci-xlp.c +++ b/arch/mips/pci/pci-xlp.c @@ -46,16 +46,18 @@ #include <asm/netlogic/interrupt.h> #include <asm/netlogic/haldefs.h> +#include <asm/netlogic/common.h> +#include <asm/netlogic/mips-extns.h> #include <asm/netlogic/xlp-hal/iomap.h> -#include <asm/netlogic/xlp-hal/pic.h> #include <asm/netlogic/xlp-hal/xlp.h> +#include <asm/netlogic/xlp-hal/pic.h> #include <asm/netlogic/xlp-hal/pcibus.h> #include <asm/netlogic/xlp-hal/bridge.h> static void *pci_config_base; -#define pci_cfg_addr(bus, devfn, off) (((bus) << 20) | ((devfn) << 12) | (off)) +#define pci_cfg_addr(bus, devfn, off) (((bus) << 20) | ((devfn) << 12) | (off)) /* PCI ops */ static inline u32 pci_cfg_read_32bit(struct pci_bus *bus, unsigned int devfn, @@ -64,8 +66,25 @@ static inline u32 pci_cfg_read_32bit(struct pci_bus *bus, unsigned int devfn, u32 data; u32 *cfgaddr; + where &= ~3; + if (cpu_is_xlp9xx()) { + /* be very careful on SoC buses */ + if (bus->number == 0) { + /* Scan only existing nodes - uboot bug? */ + if (PCI_SLOT(devfn) != 0 || + !nlm_node_present(PCI_FUNC(devfn))) + return 0xffffffff; + } else if (bus->parent->number == 0) { /* SoC bus */ + if (PCI_SLOT(devfn) == 0) /* b.0.0 hangs */ + return 0xffffffff; + if (devfn == 44) /* b.5.4 hangs */ + return 0xffffffff; + } + } else if (bus->number == 0 && PCI_SLOT(devfn) == 1 && where == 0x954) { + return 0xffffffff; + } cfgaddr = (u32 *)(pci_config_base + - pci_cfg_addr(bus->number, devfn, where & ~3)); + pci_cfg_addr(bus->number, devfn, where)); data = *cfgaddr; return data; } @@ -135,54 +154,74 @@ struct pci_ops nlm_pci_ops = { }; static struct resource nlm_pci_mem_resource = { - .name = "XLP PCI MEM", - .start = 0xd0000000UL, /* 256MB PCI mem @ 0xd000_0000 */ - .end = 0xdfffffffUL, - .flags = IORESOURCE_MEM, + .name = "XLP PCI MEM", + .start = 0xd0000000UL, /* 256MB PCI mem @ 0xd000_0000 */ + .end = 0xdfffffffUL, + .flags = IORESOURCE_MEM, }; static struct resource nlm_pci_io_resource = { - .name = "XLP IO MEM", - .start = 0x14000000UL, /* 64MB PCI IO @ 0x1000_0000 */ - .end = 0x17ffffffUL, - .flags = IORESOURCE_IO, + .name = "XLP IO MEM", + .start = 0x14000000UL, /* 64MB PCI IO @ 0x1000_0000 */ + .end = 0x17ffffffUL, + .flags = IORESOURCE_IO, }; struct pci_controller nlm_pci_controller = { - .index = 0, - .pci_ops = &nlm_pci_ops, - .mem_resource = &nlm_pci_mem_resource, - .mem_offset = 0x00000000UL, - .io_resource = &nlm_pci_io_resource, - .io_offset = 0x00000000UL, + .index = 0, + .pci_ops = &nlm_pci_ops, + .mem_resource = &nlm_pci_mem_resource, + .mem_offset = 0x00000000UL, + .io_resource = &nlm_pci_io_resource, + .io_offset = 0x00000000UL, }; -static int get_irq_vector(const struct pci_dev *dev) +struct pci_dev *xlp_get_pcie_link(const struct pci_dev *dev) { + struct pci_bus *bus, *p; + + bus = dev->bus; + + if (cpu_is_xlp9xx()) { + /* find bus with grand parent number == 0 */ + for (p = bus->parent; p && p->parent && p->parent->number != 0; + p = p->parent) + bus = p; + return (p && p->parent) ? bus->self : NULL; + } else { + /* Find the bridge on bus 0 */ + for (p = bus->parent; p && p->number != 0; p = p->parent) + bus = p; + + return p ? bus->self : NULL; + } +} + +int xlp_socdev_to_node(const struct pci_dev *lnkdev) +{ + if (cpu_is_xlp9xx()) + return PCI_FUNC(lnkdev->bus->self->devfn); + else + return PCI_SLOT(lnkdev->devfn) / 8; +} + +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + struct pci_dev *lnkdev; + int lnkfunc, node; + /* * For XLP PCIe, there is an IRQ per Link, find out which * link the device is on to assign interrupts */ - if (dev->bus->self == NULL) + lnkdev = xlp_get_pcie_link(dev); + if (lnkdev == NULL) return 0; - switch (dev->bus->self->devfn) { - case 0x8: - return PIC_PCIE_LINK_0_IRQ; - case 0x9: - return PIC_PCIE_LINK_1_IRQ; - case 0xa: - return PIC_PCIE_LINK_2_IRQ; - case 0xb: - return PIC_PCIE_LINK_3_IRQ; - } - WARN(1, "Unexpected devfn %d\n", dev->bus->self->devfn); - return 0; -} + lnkfunc = PCI_FUNC(lnkdev->devfn); + node = xlp_socdev_to_node(lnkdev); -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -{ - return get_irq_vector(dev); + return nlm_irq_to_xirq(node, PIC_PCIE_LINK_LEGACY_IRQ(lnkfunc)); } /* Do platform specific device initialization at pci_enable_device() time */ @@ -191,51 +230,96 @@ int pcibios_plat_dev_init(struct pci_dev *dev) return 0; } -static int xlp_enable_pci_bswap(void) +/* + * If big-endian, enable hardware byteswap on the PCIe bridges. + * This will make both the SoC and PCIe devices behave consistently with + * readl/writel. + */ +#ifdef __BIG_ENDIAN +static void xlp_config_pci_bswap(int node, int link) { - uint64_t pciebase, sysbase; - int node, i; + uint64_t nbubase, lnkbase; u32 reg; - /* Chip-0 so node set to 0 */ - node = 0; - sysbase = nlm_get_bridge_regbase(node); + nbubase = nlm_get_bridge_regbase(node); + lnkbase = nlm_get_pcie_base(node, link); + /* * Enable byte swap in hardware. Program each link's PCIe SWAP regions * from the link's address ranges. */ - for (i = 0; i < 4; i++) { - pciebase = nlm_pcicfg_base(XLP_IO_PCIE_OFFSET(node, i)); - if (nlm_read_pci_reg(pciebase, 0) == 0xffffffff) - continue; - - reg = nlm_read_bridge_reg(sysbase, BRIDGE_PCIEMEM_BASE0 + i); - nlm_write_pci_reg(pciebase, PCIE_BYTE_SWAP_MEM_BASE, reg); - - reg = nlm_read_bridge_reg(sysbase, BRIDGE_PCIEMEM_LIMIT0 + i); - nlm_write_pci_reg(pciebase, PCIE_BYTE_SWAP_MEM_LIM, - reg | 0xfff); - - reg = nlm_read_bridge_reg(sysbase, BRIDGE_PCIEIO_BASE0 + i); - nlm_write_pci_reg(pciebase, PCIE_BYTE_SWAP_IO_BASE, reg); - - reg = nlm_read_bridge_reg(sysbase, BRIDGE_PCIEIO_LIMIT0 + i); - nlm_write_pci_reg(pciebase, PCIE_BYTE_SWAP_IO_LIM, reg | 0xfff); + if (cpu_is_xlp9xx()) { + reg = nlm_read_bridge_reg(nbubase, + BRIDGE_9XX_PCIEMEM_BASE0 + link); + nlm_write_pci_reg(lnkbase, PCIE_9XX_BYTE_SWAP_MEM_BASE, reg); + + reg = nlm_read_bridge_reg(nbubase, + BRIDGE_9XX_PCIEMEM_LIMIT0 + link); + nlm_write_pci_reg(lnkbase, + PCIE_9XX_BYTE_SWAP_MEM_LIM, reg | 0xfff); + + reg = nlm_read_bridge_reg(nbubase, + BRIDGE_9XX_PCIEIO_BASE0 + link); + nlm_write_pci_reg(lnkbase, PCIE_9XX_BYTE_SWAP_IO_BASE, reg); + + reg = nlm_read_bridge_reg(nbubase, + BRIDGE_9XX_PCIEIO_LIMIT0 + link); + nlm_write_pci_reg(lnkbase, + PCIE_9XX_BYTE_SWAP_IO_LIM, reg | 0xfff); + } else { + reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEMEM_BASE0 + link); + nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_BASE, reg); + + reg = nlm_read_bridge_reg(nbubase, + BRIDGE_PCIEMEM_LIMIT0 + link); + nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_LIM, reg | 0xfff); + + reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_BASE0 + link); + nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_BASE, reg); + + reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_LIMIT0 + link); + nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_LIM, reg | 0xfff); } - return 0; } +#else +/* Swap configuration not needed in little-endian mode */ +static inline void xlp_config_pci_bswap(int node, int link) {} +#endif /* __BIG_ENDIAN */ static int __init pcibios_init(void) { + uint64_t pciebase; + int link, n; + u32 reg; + /* Firmware assigns PCI resources */ pci_set_flags(PCI_PROBE_ONLY); pci_config_base = ioremap(XLP_DEFAULT_PCI_ECFG_BASE, 64 << 20); /* Extend IO port for memory mapped io */ - ioport_resource.start = 0; + ioport_resource.start = 0; ioport_resource.end = ~0; - xlp_enable_pci_bswap(); + for (n = 0; n < NLM_NR_NODES; n++) { + if (!nlm_node_present(n)) + continue; + + for (link = 0; link < PCIE_NLINKS; link++) { + pciebase = nlm_get_pcie_base(n, link); + if (nlm_read_pci_reg(pciebase, 0) == 0xffffffff) + continue; + xlp_config_pci_bswap(n, link); + xlp_init_node_msi_irqs(n, link); + + /* put in intpin and irq - u-boot does not */ + reg = nlm_read_pci_reg(pciebase, 0xf); + reg &= ~0x1ffu; + reg |= (1 << 8) | PIC_PCIE_LINK_LEGACY_IRQ(link); + nlm_write_pci_reg(pciebase, 0xf, reg); + pr_info("XLP PCIe: Link %d-%d initialized.\n", n, link); + } + } + set_io_port_base(CKSEG1); nlm_pci_controller.io_map_base = CKSEG1; diff --git a/arch/mips/pci/pci-xlr.c b/arch/mips/pci/pci-xlr.c index 0c18ccc7962..0dde80332d3 100644 --- a/arch/mips/pci/pci-xlr.c +++ b/arch/mips/pci/pci-xlr.c @@ -56,7 +56,7 @@ static void *pci_config_base; -#define pci_cfg_addr(bus, devfn, off) (((bus) << 16) | ((devfn) << 8) | (off)) +#define pci_cfg_addr(bus, devfn, off) (((bus) << 16) | ((devfn) << 8) | (off)) /* PCI ops */ static inline u32 pci_cfg_read_32bit(struct pci_bus *bus, unsigned int devfn, @@ -136,26 +136,26 @@ struct pci_ops nlm_pci_ops = { }; static struct resource nlm_pci_mem_resource = { - .name = "XLR PCI MEM", - .start = 0xd0000000UL, /* 256MB PCI mem @ 0xd000_0000 */ - .end = 0xdfffffffUL, - .flags = IORESOURCE_MEM, + .name = "XLR PCI MEM", + .start = 0xd0000000UL, /* 256MB PCI mem @ 0xd000_0000 */ + .end = 0xdfffffffUL, + .flags = IORESOURCE_MEM, }; static struct resource nlm_pci_io_resource = { - .name = "XLR IO MEM", - .start = 0x10000000UL, /* 16MB PCI IO @ 0x1000_0000 */ - .end = 0x100fffffUL, - .flags = IORESOURCE_IO, + .name = "XLR IO MEM", + .start = 0x10000000UL, /* 16MB PCI IO @ 0x1000_0000 */ + .end = 0x100fffffUL, + .flags = IORESOURCE_IO, }; struct pci_controller nlm_pci_controller = { - .index = 0, - .pci_ops = &nlm_pci_ops, - .mem_resource = &nlm_pci_mem_resource, - .mem_offset = 0x00000000UL, - .io_resource = &nlm_pci_io_resource, - .io_offset = 0x00000000UL, + .index = 0, + .pci_ops = &nlm_pci_ops, + .mem_resource = &nlm_pci_mem_resource, + .mem_offset = 0x00000000UL, + .io_resource = &nlm_pci_io_resource, + .io_offset = 0x00000000UL, }; /* @@ -214,14 +214,8 @@ static int get_irq_vector(const struct pci_dev *dev) } #ifdef CONFIG_PCI_MSI -void destroy_irq(unsigned int irq) -{ - /* nothing to do yet */ -} - void arch_teardown_msi_irq(unsigned int irq) { - destroy_irq(irq); } int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) @@ -259,14 +253,12 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc) MSI_ADDR_REDIRECTION_CPU; msg.data = MSI_DATA_TRIGGER_EDGE | - MSI_DATA_LEVEL_ASSERT | + MSI_DATA_LEVEL_ASSERT | MSI_DATA_DELIVERY_FIXED; ret = irq_set_msi_desc(irq, desc); - if (ret < 0) { - destroy_irq(irq); + if (ret < 0) return ret; - } write_msi_msg(irq, &msg); return 0; @@ -344,7 +336,7 @@ static int __init pcibios_init(void) pci_config_base = ioremap(DEFAULT_PCI_CONFIG_BASE, 16 << 20); /* Extend IO port for memory mapped io */ - ioport_resource.start = 0; + ioport_resource.start = 0; ioport_resource.end = ~0; set_io_port_base(CKSEG1); diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index a1843448fad..1bf60b12737 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -1,6 +1,6 @@ /* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * @@ -113,71 +113,73 @@ static void pcibios_scanbus(struct pci_controller *hose) if (!pci_has_flag(PCI_PROBE_ONLY)) { pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); - pci_enable_bridges(bus); } - bus->dev.of_node = hose->of_node; } } #ifdef CONFIG_OF void pci_load_of_ranges(struct pci_controller *hose, struct device_node *node) { - const __be32 *ranges; - int rlen; - int pna = of_n_addr_cells(node); - int np = pna + 5; + struct of_pci_range range; + struct of_pci_range_parser parser; pr_info("PCI host bridge %s ranges:\n", node->full_name); - ranges = of_get_property(node, "ranges", &rlen); - if (ranges == NULL) - return; hose->of_node = node; - while ((rlen -= np * 4) >= 0) { - u32 pci_space; + if (of_pci_range_parser_init(&parser, node)) + return; + + for_each_of_pci_range(&parser, &range) { struct resource *res = NULL; - u64 addr, size; - - pci_space = be32_to_cpup(&ranges[0]); - addr = of_translate_address(node, ranges + 3); - size = of_read_number(ranges + pna + 3, 2); - ranges += np; - switch ((pci_space >> 24) & 0x3) { - case 1: /* PCI IO space */ + + switch (range.flags & IORESOURCE_TYPE_BITS) { + case IORESOURCE_IO: pr_info(" IO 0x%016llx..0x%016llx\n", - addr, addr + size - 1); + range.cpu_addr, + range.cpu_addr + range.size - 1); hose->io_map_base = - (unsigned long)ioremap(addr, size); + (unsigned long)ioremap(range.cpu_addr, + range.size); res = hose->io_resource; - res->flags = IORESOURCE_IO; break; - case 2: /* PCI Memory space */ - case 3: /* PCI 64 bits Memory space */ + case IORESOURCE_MEM: pr_info(" MEM 0x%016llx..0x%016llx\n", - addr, addr + size - 1); + range.cpu_addr, + range.cpu_addr + range.size - 1); res = hose->mem_resource; - res->flags = IORESOURCE_MEM; break; } - if (res != NULL) { - res->start = addr; - res->name = node->full_name; - res->end = res->start + size - 1; - res->parent = NULL; - res->sibling = NULL; - res->child = NULL; - } + if (res != NULL) + of_pci_range_to_resource(&range, node, res); } } + +struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus) +{ + struct pci_controller *hose = bus->sysdata; + + return of_node_get(hose->of_node); +} #endif static DEFINE_MUTEX(pci_scan_mutex); void register_pci_controller(struct pci_controller *hose) { - if (request_resource(&iomem_resource, hose->mem_resource) < 0) + struct resource *parent; + + parent = hose->mem_resource->parent; + if (!parent) + parent = &iomem_resource; + + if (request_resource(parent, hose->mem_resource) < 0) goto out; - if (request_resource(&ioport_resource, hose->io_resource) < 0) { + + parent = hose->io_resource->parent; + if (!parent) + parent = &ioport_resource; + + if (request_resource(parent, hose->io_resource) < 0) { release_resource(hose->mem_resource); goto out; } diff --git a/arch/mips/pci/pcie-octeon.c b/arch/mips/pci/pcie-octeon.c index fdb4d558c0c..5e36c33e554 100644 --- a/arch/mips/pci/pcie-octeon.c +++ b/arch/mips/pci/pcie-octeon.c @@ -43,7 +43,7 @@ union cvmx_pcie_address { uint64_t upper:2; /* Normally 2 for XKPHYS */ uint64_t reserved_49_61:13; /* Must be zero */ uint64_t io:1; /* 1 for IO space access */ - uint64_t did:5; /* PCIe DID = 3 */ + uint64_t did:5; /* PCIe DID = 3 */ uint64_t subdid:3; /* PCIe SubDID = 1 */ uint64_t reserved_36_39:4; /* Must be zero */ uint64_t es:2; /* Endian swap = 1 */ @@ -74,7 +74,7 @@ union cvmx_pcie_address { uint64_t upper:2; /* Normally 2 for XKPHYS */ uint64_t reserved_49_61:13; /* Must be zero */ uint64_t io:1; /* 1 for IO space access */ - uint64_t did:5; /* PCIe DID = 3 */ + uint64_t did:5; /* PCIe DID = 3 */ uint64_t subdid:3; /* PCIe SubDID = 2 */ uint64_t reserved_36_39:4; /* Must be zero */ uint64_t es:2; /* Endian swap = 1 */ @@ -85,7 +85,7 @@ union cvmx_pcie_address { uint64_t upper:2; /* Normally 2 for XKPHYS */ uint64_t reserved_49_61:13; /* Must be zero */ uint64_t io:1; /* 1 for IO space access */ - uint64_t did:5; /* PCIe DID = 3 */ + uint64_t did:5; /* PCIe DID = 3 */ uint64_t subdid:3; /* PCIe SubDID = 3-6 */ uint64_t reserved_36_39:4; /* Must be zero */ uint64_t address:36; /* PCIe Mem address */ @@ -166,7 +166,7 @@ static inline uint64_t cvmx_pcie_get_mem_size(int pcie_port) * Read a PCIe config space register indirectly. This is used for * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. * - * @pcie_port: PCIe port to read from + * @pcie_port: PCIe port to read from * @cfg_offset: Address to read * * Returns Value read @@ -194,9 +194,9 @@ static uint32_t cvmx_pcie_cfgx_read(int pcie_port, uint32_t cfg_offset) * Write a PCIe config space register indirectly. This is used for * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. * - * @pcie_port: PCIe port to write to + * @pcie_port: PCIe port to write to * @cfg_offset: Address to write - * @val: Value to write + * @val: Value to write */ static void cvmx_pcie_cfgx_write(int pcie_port, uint32_t cfg_offset, uint32_t val) @@ -222,7 +222,7 @@ static void cvmx_pcie_cfgx_write(int pcie_port, uint32_t cfg_offset, * @pcie_port: PCIe port to access * @bus: Sub bus * @dev: Device ID - * @fn: Device sub function + * @fn: Device sub function * @reg: Register to access * * Returns 64bit Octeon IO address @@ -259,7 +259,7 @@ static inline uint64_t __cvmx_pcie_build_config_addr(int pcie_port, int bus, * @pcie_port: PCIe port the device is on * @bus: Sub bus * @dev: Device ID - * @fn: Device sub function + * @fn: Device sub function * @reg: Register to access * * Returns Result of the read @@ -281,7 +281,7 @@ static uint8_t cvmx_pcie_config_read8(int pcie_port, int bus, int dev, * @pcie_port: PCIe port the device is on * @bus: Sub bus * @dev: Device ID - * @fn: Device sub function + * @fn: Device sub function * @reg: Register to access * * Returns Result of the read @@ -303,7 +303,7 @@ static uint16_t cvmx_pcie_config_read16(int pcie_port, int bus, int dev, * @pcie_port: PCIe port the device is on * @bus: Sub bus * @dev: Device ID - * @fn: Device sub function + * @fn: Device sub function * @reg: Register to access * * Returns Result of the read @@ -325,7 +325,7 @@ static uint32_t cvmx_pcie_config_read32(int pcie_port, int bus, int dev, * @pcie_port: PCIe port the device is on * @bus: Sub bus * @dev: Device ID - * @fn: Device sub function + * @fn: Device sub function * @reg: Register to access * @val: Value to write */ @@ -344,7 +344,7 @@ static void cvmx_pcie_config_write8(int pcie_port, int bus, int dev, int fn, * @pcie_port: PCIe port the device is on * @bus: Sub bus * @dev: Device ID - * @fn: Device sub function + * @fn: Device sub function * @reg: Register to access * @val: Value to write */ @@ -363,7 +363,7 @@ static void cvmx_pcie_config_write16(int pcie_port, int bus, int dev, int fn, * @pcie_port: PCIe port the device is on * @bus: Sub bus * @dev: Device ID - * @fn: Device sub function + * @fn: Device sub function * @reg: Register to access * @val: Value to write */ @@ -883,14 +883,14 @@ retry: /* Store merge control (NPEI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */ npei_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL); - npei_mem_access_ctl.s.max_word = 0; /* Allow 16 words to combine */ - npei_mem_access_ctl.s.timer = 127; /* Wait up to 127 cycles for more data */ + npei_mem_access_ctl.s.max_word = 0; /* Allow 16 words to combine */ + npei_mem_access_ctl.s.timer = 127; /* Wait up to 127 cycles for more data */ cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL, npei_mem_access_ctl.u64); /* Setup Mem access SubDIDs */ mem_access_subid.u64 = 0; mem_access_subid.s.port = pcie_port; /* Port the request is sent to. */ - mem_access_subid.s.nmerge = 1; /* Due to an errata on pass 1 chips, no merging is allowed. */ + mem_access_subid.s.nmerge = 1; /* Due to an errata on pass 1 chips, no merging is allowed. */ mem_access_subid.s.esr = 1; /* Endian-swap for Reads. */ mem_access_subid.s.esw = 1; /* Endian-swap for Writes. */ mem_access_subid.s.nsr = 0; /* Enable Snooping for Reads. Octeon doesn't care, but devices might want this more conservative setting */ @@ -926,7 +926,7 @@ retry: bar1_index.u32 = 0; bar1_index.s.addr_idx = (CVMX_PCIE_BAR1_PHYS_BASE >> 22); - bar1_index.s.ca = 1; /* Not Cached */ + bar1_index.s.ca = 1; /* Not Cached */ bar1_index.s.end_swp = 1; /* Endian Swap mode */ bar1_index.s.addr_v = 1; /* Valid entry */ @@ -1342,11 +1342,11 @@ static int __cvmx_pcie_rc_initialize_gen2(int pcie_port) /* Setup Mem access SubDIDs */ mem_access_subid.u64 = 0; mem_access_subid.s.port = pcie_port; /* Port the request is sent to. */ - mem_access_subid.s.nmerge = 0; /* Allow merging as it works on CN6XXX. */ - mem_access_subid.s.esr = 1; /* Endian-swap for Reads. */ - mem_access_subid.s.esw = 1; /* Endian-swap for Writes. */ - mem_access_subid.s.wtype = 0; /* "No snoop" and "Relaxed ordering" are not set */ - mem_access_subid.s.rtype = 0; /* "No snoop" and "Relaxed ordering" are not set */ + mem_access_subid.s.nmerge = 0; /* Allow merging as it works on CN6XXX. */ + mem_access_subid.s.esr = 1; /* Endian-swap for Reads. */ + mem_access_subid.s.esw = 1; /* Endian-swap for Writes. */ + mem_access_subid.s.wtype = 0; /* "No snoop" and "Relaxed ordering" are not set */ + mem_access_subid.s.rtype = 0; /* "No snoop" and "Relaxed ordering" are not set */ /* PCIe Adddress Bits <63:34>. */ if (OCTEON_IS_MODEL(OCTEON_CN68XX)) mem_access_subid.cn68xx.ba = 0; @@ -1409,7 +1409,7 @@ static int __cvmx_pcie_rc_initialize_gen2(int pcie_port) bar1_index.u64 = 0; bar1_index.s.addr_idx = (CVMX_PCIE_BAR1_PHYS_BASE >> 22); - bar1_index.s.ca = 1; /* Not Cached */ + bar1_index.s.ca = 1; /* Not Cached */ bar1_index.s.end_swp = 1; /* Endian Swap mode */ bar1_index.s.addr_v = 1; /* Valid entry */ @@ -1458,10 +1458,10 @@ static int cvmx_pcie_rc_initialize(int pcie_port) * * @dev: The Linux PCI device structure for the device to map * @slot: The slot number for this device on __BUS 0__. Linux - * enumerates through all the bridges and figures out the - * slot on Bus 0 where this device eventually hooks to. + * enumerates through all the bridges and figures out the + * slot on Bus 0 where this device eventually hooks to. * @pin: The PCI interrupt pin read from the device, then swizzled - * as it goes through each bridge. + * as it goes through each bridge. * Returns Interrupt number for the device */ int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev, @@ -1503,7 +1503,7 @@ int __init octeon_pcie_pcibios_map_irq(const struct pci_dev *dev, return pin - 1 + OCTEON_IRQ_PCI_INT0; } -static void set_cfg_read_retry(u32 retry_cnt) +static void set_cfg_read_retry(u32 retry_cnt) { union cvmx_pemx_ctl_status pemx_ctl; pemx_ctl.u64 = cvmx_read_csr(CVMX_PEMX_CTL_STATUS(1)); @@ -1931,7 +1931,7 @@ static int __init octeon_pcie_setup(void) OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0)) { sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(0)); if (sriox_status_reg.s.srio) { - srio_war15205 += 1; /* Port is SRIO */ + srio_war15205 += 1; /* Port is SRIO */ port = 0; } } @@ -2004,7 +2004,7 @@ static int __init octeon_pcie_setup(void) OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0)) { sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(1)); if (sriox_status_reg.s.srio) { - srio_war15205 += 1; /* Port is SRIO */ + srio_war15205 += 1; /* Port is SRIO */ port = 1; } } |
