diff options
Diffstat (limited to 'arch/mips/pci')
32 files changed, 1058 insertions, 170 deletions
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index 719e4557e22..ff8a5539b36 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -21,7 +21,7 @@ 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.  # @@ -29,6 +29,7 @@ obj-$(CONFIG_LASAT)		+= pci-lasat.o  obj-$(CONFIG_MIPS_COBALT)	+= fixup-cobalt.o  obj-$(CONFIG_LEMOTE_FULOONG2E)	+= fixup-fuloong2e.o ops-loongson2.o  obj-$(CONFIG_LEMOTE_MACH2F)	+= fixup-lemote2f.o ops-loongson2.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 @@ -60,4 +61,5 @@ obj-$(CONFIG_CPU_XLP)		+= pci-xlp.o  ifdef CONFIG_PCI_MSI  obj-$(CONFIG_CAVIUM_OCTEON_SOC) += msi-octeon.o +obj-$(CONFIG_CPU_XLP)		+= msi-xlp.o  endif 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-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 07ada7f8441..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 @@ -50,10 +51,26 @@ 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 */ +	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, @@ -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-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/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 6144bb337e4..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> diff --git a/arch/mips/pci/ops-bonito64.c b/arch/mips/pci/ops-bonito64.c index 830352e3aed..c06205a8734 100644 --- a/arch/mips/pci/ops-bonito64.c +++ b/arch/mips/pci/ops-bonito64.c @@ -22,7 +22,6 @@  #include <linux/types.h>  #include <linux/pci.h>  #include <linux/kernel.h> -#include <linux/init.h>  #include <asm/mips-boards/bonito64.h> diff --git a/arch/mips/pci/ops-lantiq.c b/arch/mips/pci/ops-lantiq.c index 16e7c2526d7..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> diff --git a/arch/mips/pci/ops-loongson2.c b/arch/mips/pci/ops-loongson2.c index 98254afa028..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> 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 92a8543361b..dbbf3657896 100644 --- a/arch/mips/pci/ops-msc.c +++ b/arch/mips/pci/ops-msc.c @@ -24,7 +24,6 @@  #include <linux/types.h>  #include <linux/pci.h>  #include <linux/kernel.h> -#include <linux/init.h>  #include <asm/mips-boards/msc01_pci.h> diff --git a/arch/mips/pci/ops-nile4.c b/arch/mips/pci/ops-nile4.c index 499e35c3eb3..a1a7c9f4096 100644 --- a/arch/mips/pci/ops-nile4.c +++ b/arch/mips/pci/ops-nile4.c @@ -1,5 +1,4 @@  #include <linux/kernel.h> -#include <linux/init.h>  #include <linux/pci.h>  #include <asm/bootinfo.h> diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c index 3d27800edba..50034f985be 100644 --- a/arch/mips/pci/ops-pmcmsp.c +++ b/arch/mips/pci/ops-pmcmsp.c @@ -7,7 +7,7 @@   * 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 diff --git a/arch/mips/pci/ops-rc32434.c b/arch/mips/pci/ops-rc32434.c index 7c7182e2350..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> 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 3d5df514d02..0e046d82e4e 100644 --- a/arch/mips/pci/ops-tx4927.c +++ b/arch/mips/pci/ops-tx4927.c @@ -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/pci-alchemy.c b/arch/mips/pci/pci-alchemy.c index d1faece21b6..563d1f61d6e 100644 --- a/arch/mips/pci/pci-alchemy.c +++ b/arch/mips/pci/pci-alchemy.c @@ -16,6 +16,7 @@  #include <linux/syscore_ops.h>  #include <linux/vmalloc.h> +#include <asm/dma-coherence.h>  #include <asm/mach-au1x00/au1000.h>  #include <asm/tlbmisc.h> @@ -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; diff --git a/arch/mips/pci/pci-ar71xx.c b/arch/mips/pci/pci-ar71xx.c index 18517dd0f70..d471a26dd5f 100644 --- a/arch/mips/pci/pci-ar71xx.c +++ b/arch/mips/pci/pci-ar71xx.c @@ -363,9 +363,6 @@ static int ar71xx_pci_probe(struct platform_device *pdev)  	spin_lock_init(&apc->lock);  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base"); -	if (!res) -		return -EINVAL; -  	apc->cfg_base = devm_ioremap_resource(&pdev->dev, res);  	if (IS_ERR(apc->cfg_base))  		return PTR_ERR(apc->cfg_base); diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c index 65ec032fa0b..785b2659b51 100644 --- a/arch/mips/pci/pci-ar724x.c +++ b/arch/mips/pci/pci-ar724x.c @@ -362,25 +362,16 @@ static int ar724x_pci_probe(struct platform_device *pdev)  		return -ENOMEM;  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl_base"); -	if (!res) -		return -EINVAL; -  	apc->ctrl_base = devm_ioremap_resource(&pdev->dev, res);  	if (IS_ERR(apc->ctrl_base))  		return PTR_ERR(apc->ctrl_base);  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg_base"); -	if (!res) -		return -EINVAL; -  	apc->devcfg_base = devm_ioremap_resource(&pdev->dev, res);  	if (IS_ERR(apc->devcfg_base))  		return PTR_ERR(apc->devcfg_base);  	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "crp_base"); -	if (!res) -		return -EINVAL; -  	apc->crp_base = devm_ioremap_resource(&pdev->dev, res);  	if (IS_ERR(apc->crp_base))  		return PTR_ERR(apc->crp_base); diff --git a/arch/mips/pci/pci-bcm1480.c b/arch/mips/pci/pci-bcm1480.c index 44dd5aa2e36..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> diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index 162b4cb29db..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> diff --git a/arch/mips/pci/pci-malta.c b/arch/mips/pci/pci-malta.c index 37134ddfeaa..cfbbc3e3e91 100644 --- a/arch/mips/pci/pci-malta.c +++ b/arch/mips/pci/pci-malta.c @@ -27,7 +27,7 @@  #include <linux/init.h>  #include <asm/gt64120.h> -#include <asm/gcmpregs.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> @@ -201,11 +201,11 @@ void __init mips_pcibios_init(void)  		msc_mem_resource.start = start & mask;  		msc_mem_resource.end = (start & mask) | ~mask;  		msc_controller.mem_offset = (start & mask) - (map & mask); -#ifdef CONFIG_MIPS_CMP -		if (gcmp_niocu()) -			gcmp_setregion(0, start, mask, -				GCMP_GCB_GCMPB_CMDEFTGT_IOCU1); -#endif +		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); @@ -213,11 +213,11 @@ void __init mips_pcibios_init(void)  		msc_io_resource.end = (map & mask) | ~mask;  		msc_controller.io_offset = 0;  		ioport_resource.end = ~mask; -#ifdef CONFIG_MIPS_CMP -		if (gcmp_niocu()) -			gcmp_setregion(1, start, mask, -				GCMP_GCB_GCMPB_CMDEFTGT_IOCU1); -#endif +		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; @@ -241,9 +241,9 @@ void __init mips_pcibios_init(void)  		return;  	} -	/* Change start address to avoid conflicts with ACPI and SMB devices */ -	if (controller->io_resource->start < 0x00002000UL) -		controller->io_resource->start = 0x00002000UL; +	/* 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; diff --git a/arch/mips/pci/pci-rc32434.c b/arch/mips/pci/pci-rc32434.c index b128cb973eb..7f6ce6d734c 100644 --- a/arch/mips/pci/pci-rc32434.c +++ b/arch/mips/pci/pci-rc32434.c @@ -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  }; diff --git a/arch/mips/pci/pci-rt3883.c b/arch/mips/pci/pci-rt3883.c index 95c9d41382e..72919aeef42 100644 --- a/arch/mips/pci/pci-rt3883.c +++ b/arch/mips/pci/pci-rt3883.c @@ -436,9 +436,6 @@ static int rt3883_pci_probe(struct platform_device *pdev)  		return -ENOMEM;  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) -		return -EINVAL; -  	rpc->base = devm_ioremap_resource(dev, res);  	if (IS_ERR(rpc->base))  		return PTR_ERR(rpc->base); @@ -583,29 +580,7 @@ err_put_intc_node:  int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)  { -	struct of_irq dev_irq; -	int err; -	int irq; - -	err = of_irq_map_pci(dev, &dev_irq); -	if (err) { -		pr_err("pci %s: unable to get irq map, err=%d\n", -		       pci_name((struct pci_dev *) dev), err); -		return 0; -	} - -	irq = irq_create_of_mapping(dev_irq.controller, -				    dev_irq.specifier, -				    dev_irq.size); - -	if (irq == 0) -		pr_crit("pci %s: no irq found for pin %u\n", -			pci_name((struct pci_dev *) dev), pin); -	else -		pr_info("pci %s: using irq %d for pin %u\n", -			pci_name((struct pci_dev *) dev), irq, pin); - -	return irq; +	return of_irq_parse_and_map_pci(dev, slot, pin);  }  int pcibios_plat_dev_init(struct pci_dev *dev) 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-xlp.c b/arch/mips/pci/pci-xlp.c index 653d2db9e0c..7babf01600c 100644 --- a/arch/mips/pci/pci-xlp.c +++ b/arch/mips/pci/pci-xlp.c @@ -47,10 +47,11 @@  #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> @@ -66,9 +67,22 @@ static inline u32 pci_cfg_read_32bit(struct pci_bus *bus, unsigned int devfn,  	u32 *cfgaddr;  	where &= ~3; -	if (bus->number == 0 && PCI_SLOT(devfn) == 1 && where == 0x954) +	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));  	data = *cfgaddr; @@ -162,27 +176,39 @@ struct pci_controller nlm_pci_controller = {  	.io_offset	= 0x00000000UL,  }; -static struct pci_dev *xlp_get_pcie_link(const struct pci_dev *dev) +struct pci_dev *xlp_get_pcie_link(const struct pci_dev *dev)  {  	struct pci_bus *bus, *p; -	/* Find the bridge on bus 0 */  	bus = dev->bus; -	for (p = bus->parent; p && p->number != 0; p = p->parent) -		bus = p; -	return p ? bus->self : NULL; +	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; +	}  } -static inline int nlm_pci_link_to_irq(int link) +int xlp_socdev_to_node(const struct pci_dev *lnkdev)  { -	return PIC_PCIE_LINK_0_IRQ + link; +	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 lnkslot, lnkfunc; +	int lnkfunc, node;  	/*  	 * For XLP PCIe, there is an IRQ per Link, find out which @@ -191,9 +217,11 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)  	lnkdev = xlp_get_pcie_link(dev);  	if (lnkdev == NULL)  		return 0; +  	lnkfunc = PCI_FUNC(lnkdev->devfn); -	lnkslot = PCI_SLOT(lnkdev->devfn); -	return nlm_irq_to_xirq(lnkslot / 8, nlm_pci_link_to_irq(lnkfunc)); +	node = xlp_socdev_to_node(lnkdev); + +	return nlm_irq_to_xirq(node, PIC_PCIE_LINK_LEGACY_IRQ(lnkfunc));  }  /* Do platform specific device initialization at pci_enable_device() time */ @@ -220,17 +248,38 @@ static void xlp_config_pci_bswap(int node, int link)  	 *  Enable byte swap in hardware. Program each link's PCIe SWAP regions  	 * from the link's address ranges.  	 */ -	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); +	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); +	}  }  #else  /* Swap configuration not needed in little-endian mode */ @@ -239,7 +288,6 @@ static inline void xlp_config_pci_bswap(int node, int link) {}  static int __init pcibios_init(void)  { -	struct nlm_soc_info *nodep;  	uint64_t pciebase;  	int link, n;  	u32 reg; @@ -253,20 +301,20 @@ static int __init pcibios_init(void)  	ioport_resource.end   = ~0;  	for (n = 0; n < NLM_NR_NODES; n++) { -		nodep = nlm_get_node(n); -		if (!nodep->coremask) -			continue;	/* node does not exist */ +		if (!nlm_node_present(n)) +			continue; -		for (link = 0; link < 4; link++) { +		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 &= ~0x1fu; -			reg |= (1 << 8) | nlm_pci_link_to_irq(link); +			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);  		} diff --git a/arch/mips/pci/pci-xlr.c b/arch/mips/pci/pci-xlr.c index 4427abbd48b..0dde80332d3 100644 --- a/arch/mips/pci/pci-xlr.c +++ b/arch/mips/pci/pci-xlr.c @@ -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) @@ -263,10 +257,8 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)  		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; diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 33e7aa52d9c..1bf60b12737 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -120,51 +120,37 @@ static void pcibios_scanbus(struct pci_controller *hose)  #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);  	}  }  | 
