[PATCH 3/4] arch/arm/mach-kirkwood: add support for 2nd PCIe port on 88f6282.
saeed bishara
saeed.bishara at gmail.com
Thu Jun 10 11:29:15 EDT 2010
On Thu, Jun 10, 2010 at 4:59 PM, Benjamin Zores
<benjamin.zores at alcatel-lucent.com> wrote:
> Signed-off-by: Benjamin Zores <benjamin.zores at alcatel-lucent.com>
> ---
> arch/arm/mach-kirkwood/addr-map.c | 21 ++
> arch/arm/mach-kirkwood/common.c | 28 +++
> arch/arm/mach-kirkwood/common.h | 5 -
> arch/arm/mach-kirkwood/db88f6281-bp-setup.c | 2
> arch/arm/mach-kirkwood/include/mach/bridge-regs.h | 3
> arch/arm/mach-kirkwood/include/mach/irqs.h | 1
> arch/arm/mach-kirkwood/include/mach/kirkwood.h | 12 +
> arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c | 2
> arch/arm/mach-kirkwood/openrd-setup.c | 2
> arch/arm/mach-kirkwood/pcie.c | 202 ++++++++++++++++-----
> arch/arm/mach-kirkwood/rd88f6192-nas-setup.c | 2
> arch/arm/mach-kirkwood/rd88f6281-setup.c | 2
> arch/arm/mach-kirkwood/ts219-setup.c | 2
> arch/arm/mach-kirkwood/ts41x-setup.c | 2
> 14 files changed, 223 insertions(+), 63 deletions(-)
>
> diff --git a/arch/arm/mach-kirkwood/addr-map.c b/arch/arm/mach-kirkwood/addr-map.c
> index 2e69168..aa6bf38 100644
> --- a/arch/arm/mach-kirkwood/addr-map.c
> +++ b/arch/arm/mach-kirkwood/addr-map.c
> @@ -31,6 +31,8 @@
> #define ATTR_DEV_CS0 0x3e
> #define ATTR_PCIE_IO 0xe0
> #define ATTR_PCIE_MEM 0xe8
> +#define ATTR_PCIE1_IO 0xd0
> +#define ATTR_PCIE1_MEM 0xd8
> #define ATTR_SRAM 0x01
>
> /*
> @@ -84,6 +86,8 @@ void __init kirkwood_setup_cpu_mbus(void)
> void __iomem *addr;
> int i;
> int cs;
> + int id = 0;
> + u32 dev, rev;
>
> /*
> * First, disable and clear windows.
> @@ -102,21 +106,30 @@ void __init kirkwood_setup_cpu_mbus(void)
> /*
> * Setup windows for PCIe IO+MEM space.
> */
> - setup_cpu_win(0, KIRKWOOD_PCIE_IO_PHYS_BASE, KIRKWOOD_PCIE_IO_SIZE,
> + setup_cpu_win(id++, KIRKWOOD_PCIE_IO_PHYS_BASE, KIRKWOOD_PCIE_IO_SIZE,
> TARGET_PCIE, ATTR_PCIE_IO, KIRKWOOD_PCIE_IO_BUS_BASE);
> - setup_cpu_win(1, KIRKWOOD_PCIE_MEM_PHYS_BASE, KIRKWOOD_PCIE_MEM_SIZE,
> + setup_cpu_win(id++, KIRKWOOD_PCIE_MEM_PHYS_BASE, KIRKWOOD_PCIE_MEM_SIZE,
> TARGET_PCIE, ATTR_PCIE_MEM, KIRKWOOD_PCIE_MEM_BUS_BASE);
>
> + kirkwood_pcie_id(&dev, &rev);
> +
> + if (dev == MV88F6282_DEV_ID && (rev == MV88F6282_REV_A0)) {
> + setup_cpu_win(id++, KIRKWOOD_PCIE1_IO_PHYS_BASE, KIRKWOOD_PCIE1_IO_SIZE,
> + TARGET_PCIE, ATTR_PCIE1_IO, KIRKWOOD_PCIE1_IO_BUS_BASE);
> + setup_cpu_win(id++, KIRKWOOD_PCIE1_MEM_PHYS_BASE, KIRKWOOD_PCIE1_MEM_SIZE,
> + TARGET_PCIE, ATTR_PCIE1_MEM, KIRKWOOD_PCIE1_MEM_BUS_BASE);
> + }
> +
> /*
> * Setup window for NAND controller.
> */
> - setup_cpu_win(2, KIRKWOOD_NAND_MEM_PHYS_BASE, KIRKWOOD_NAND_MEM_SIZE,
> + setup_cpu_win(id++, KIRKWOOD_NAND_MEM_PHYS_BASE, KIRKWOOD_NAND_MEM_SIZE,
> TARGET_DEV_BUS, ATTR_DEV_NAND, -1);
>
> /*
> * Setup window for SRAM.
> */
> - setup_cpu_win(3, KIRKWOOD_SRAM_PHYS_BASE, KIRKWOOD_SRAM_SIZE,
> + setup_cpu_win(id++, KIRKWOOD_SRAM_PHYS_BASE, KIRKWOOD_SRAM_SIZE,
> TARGET_SRAM, ATTR_SRAM, -1);
>
> /*
> diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
> index 94f629d..473a1d0 100644
> --- a/arch/arm/mach-kirkwood/common.c
> +++ b/arch/arm/mach-kirkwood/common.c
> @@ -44,6 +44,11 @@ static struct map_desc kirkwood_io_desc[] __initdata = {
> .length = KIRKWOOD_PCIE_IO_SIZE,
> .type = MT_DEVICE,
> }, {
> + .virtual = KIRKWOOD_PCIE1_IO_VIRT_BASE,
> + .pfn = __phys_to_pfn(KIRKWOOD_PCIE1_IO_PHYS_BASE),
> + .length = KIRKWOOD_PCIE1_IO_SIZE,
> + .type = MT_DEVICE,
> + }, {
> .virtual = KIRKWOOD_REGS_VIRT_BASE,
> .pfn = __phys_to_pfn(KIRKWOOD_REGS_PHYS_BASE),
> .length = KIRKWOOD_REGS_SIZE,
> @@ -957,12 +962,20 @@ void __init kirkwood_init(void)
> static int __init kirkwood_clock_gate(void)
> {
> unsigned int curr = readl(CLOCK_GATING_CTRL);
> + u32 dev, rev;
> + int flags;
>
> printk(KERN_DEBUG "Gating clock of unused units\n");
> printk(KERN_DEBUG "before: 0x%08x\n", curr);
>
> + kirkwood_pcie_id(&dev, &rev);
> +
> /* Make sure those units are accessible */
> - writel(curr | CGC_SATA0 | CGC_SATA1 | CGC_PEX0, CLOCK_GATING_CTRL);
> + flags = curr | CGC_SATA0 | CGC_SATA1 | CGC_PEX0;
> +
> + if (dev == MV88F6282_DEV_ID && (rev == MV88F6282_REV_A0))
> + flags |= CGC_PEX1;
> + writel(flags, CLOCK_GATING_CTRL);
>
> /* For SATA: first shutdown the phy */
> if (!(kirkwood_clk_ctrl & CGC_SATA0)) {
> @@ -978,7 +991,7 @@ static int __init kirkwood_clock_gate(void)
> writel(readl(SATA1_IF_CTRL) | 0x200, SATA1_IF_CTRL);
> }
>
> - /* For PCIe: first shutdown the phy */
> + /* For PCIe #0: first shutdown the phy */
> if (!(kirkwood_clk_ctrl & CGC_PEX0)) {
> writel(readl(PCIE_LINK_CTRL) | 0x10, PCIE_LINK_CTRL);
> while (1)
> @@ -987,6 +1000,17 @@ static int __init kirkwood_clock_gate(void)
> writel(readl(PCIE_LINK_CTRL) & ~0x10, PCIE_LINK_CTRL);
> }
>
> + /* For PCIe #1: first shutdown the phy */
> + if (dev == MV88F6282_DEV_ID && (rev == MV88F6282_REV_A0)) {
> + if (!(kirkwood_clk_ctrl & CGC_PEX1)) {
> + writel(readl(PCIE1_LINK_CTRL) | 0x10, PCIE1_LINK_CTRL);
> + while (1)
> + if (readl(PCIE1_STATUS) & 0x1)
> + break;
> + writel(readl(PCIE1_LINK_CTRL) & ~0x10, PCIE1_LINK_CTRL);
> + }
> + }
> +
> /* Now gate clock the required units */
> writel(kirkwood_clk_ctrl, CLOCK_GATING_CTRL);
> printk(KERN_DEBUG " after: 0x%08x\n", readl(CLOCK_GATING_CTRL));
> diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
> index 05e8a8a..5b2c1c1 100644
> --- a/arch/arm/mach-kirkwood/common.h
> +++ b/arch/arm/mach-kirkwood/common.h
> @@ -18,6 +18,9 @@ struct mvsdio_platform_data;
> struct mtd_partition;
> struct mtd_info;
>
> +#define KW_PCIE0 (1 << 0)
> +#define KW_PCIE1 (1 << 1)
> +
> /*
> * Basic Kirkwood init functions used early by machine-setup.
> */
> @@ -34,7 +37,7 @@ void kirkwood_ehci_init(void);
> void kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data);
> void kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data);
> void kirkwood_ge00_switch_init(struct dsa_platform_data *d, int irq);
> -void kirkwood_pcie_init(void);
> +void kirkwood_pcie_init(unsigned int portmask);
> void kirkwood_sata_init(struct mv_sata_platform_data *sata_data);
> void kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data);
> void kirkwood_spi_init(void);
> diff --git a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
> index 39bdf4b..7550c4e 100644
> --- a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
> +++ b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
> @@ -75,7 +75,7 @@ static void __init db88f6281_init(void)
> static int __init db88f6281_pci_init(void)
> {
> if (machine_is_db88f6281_bp())
> - kirkwood_pcie_init();
> + kirkwood_pcie_init(KW_PCIE0);
>
> return 0;
> }
> diff --git a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
> index 418f501..aff0e13 100644
> --- a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
> +++ b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
> @@ -59,8 +59,9 @@
> #define CGC_SATA1 (1 << 15)
> #define CGC_XOR1 (1 << 16)
> #define CGC_CRYPTO (1 << 17)
> +#define CGC_PEX1 (1 << 18)
> #define CGC_GE1 (1 << 19)
> #define CGC_TDM (1 << 20)
> -#define CGC_RESERVED ((1 << 18) | (0x6 << 21))
> +#define CGC_RESERVED (0x6 << 21)
>
> #endif
> diff --git a/arch/arm/mach-kirkwood/include/mach/irqs.h b/arch/arm/mach-kirkwood/include/mach/irqs.h
> index f00a0a4..9da2eb5 100644
> --- a/arch/arm/mach-kirkwood/include/mach/irqs.h
> +++ b/arch/arm/mach-kirkwood/include/mach/irqs.h
> @@ -23,6 +23,7 @@
> #define IRQ_KIRKWOOD_XOR_10 7
> #define IRQ_KIRKWOOD_XOR_11 8
> #define IRQ_KIRKWOOD_PCIE 9
> +#define IRQ_KIRKWOOD_PCIE1 10
> #define IRQ_KIRKWOOD_GE00_SUM 11
> #define IRQ_KIRKWOOD_GE01_SUM 15
> #define IRQ_KIRKWOOD_USB 19
> diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
> index a571860..7f0b50a 100644
> --- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h
> +++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
> @@ -38,6 +38,11 @@
> #define KIRKWOOD_PCIE_IO_BUS_BASE 0x00000000
> #define KIRKWOOD_PCIE_IO_SIZE SZ_1M
>
> +#define KIRKWOOD_PCIE1_IO_PHYS_BASE 0xf5000000
> +#define KIRKWOOD_PCIE1_IO_VIRT_BASE 0xfed00000
> +#define KIRKWOOD_PCIE1_IO_BUS_BASE 0x00000000
> +#define KIRKWOOD_PCIE1_IO_SIZE SZ_1M
> +
you didn't updated the comment the describes the address map.
also, I suggest you to take this part from the patch I sent, in that
patch I made sure to make the pcie1 IO physical and virtual address
consecutive to pcie0, I think without this the IO access to pcie1 will
not work. please see the __io() macro at
mach-kirkwood/include/mach/io.h
> #define KIRKWOOD_REGS_PHYS_BASE 0xf1000000
> #define KIRKWOOD_REGS_VIRT_BASE 0xfee00000
> #define KIRKWOOD_REGS_SIZE SZ_1M
> @@ -46,6 +51,10 @@
> #define KIRKWOOD_PCIE_MEM_BUS_BASE 0xe0000000
> #define KIRKWOOD_PCIE_MEM_SIZE SZ_128M
>
> +#define KIRKWOOD_PCIE1_MEM_PHYS_BASE 0xd8000000
> +#define KIRKWOOD_PCIE1_MEM_BUS_BASE 0xd8000000
> +#define KIRKWOOD_PCIE1_MEM_SIZE SZ_128M
> +
> /*
> * Register Map
> */
> @@ -72,6 +81,9 @@
> #define PCIE_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x40000)
> #define PCIE_LINK_CTRL (PCIE_VIRT_BASE | 0x70)
> #define PCIE_STATUS (PCIE_VIRT_BASE | 0x1a04)
> +#define PCIE1_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x44000)
> +#define PCIE1_LINK_CTRL (PCIE1_VIRT_BASE | 0x70)
> +#define PCIE1_STATUS (PCIE1_VIRT_BASE | 0x1a04)
>
> #define USB_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x50000)
>
> diff --git a/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c b/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
> index 5e6f711..c6b92b4 100644
> --- a/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
> +++ b/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
> @@ -155,7 +155,7 @@ static void __init mv88f6281gtw_ge_init(void)
> static int __init mv88f6281gtw_ge_pci_init(void)
> {
> if (machine_is_mv88f6281gtw_ge())
> - kirkwood_pcie_init();
> + kirkwood_pcie_init(KW_PCIE0);
>
> return 0;
> }
> diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
> index ad3f1ec..2400207 100644
> --- a/arch/arm/mach-kirkwood/openrd-setup.c
> +++ b/arch/arm/mach-kirkwood/openrd-setup.c
> @@ -85,7 +85,7 @@ static void __init openrd_init(void)
> static int __init openrd_pci_init(void)
> {
> if (machine_is_openrd_base() || machine_is_openrd_client())
> - kirkwood_pcie_init();
> + kirkwood_pcie_init(KW_PCIE0);
>
> return 0;
> }
> diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c
> index dee1eff..dd1dc29 100644
> --- a/arch/arm/mach-kirkwood/pcie.c
> +++ b/arch/arm/mach-kirkwood/pcie.c
> @@ -18,29 +18,51 @@
> #include <mach/bridge-regs.h>
> #include "common.h"
>
> +void __init kirkwood_pcie_id(u32 *dev, u32 *rev)
> +{
> + *dev = orion_pcie_dev_id((void __iomem *)PCIE_VIRT_BASE);
> + *rev = orion_pcie_rev((void __iomem *)PCIE_VIRT_BASE);
> +}
>
> -#define PCIE_BASE ((void __iomem *)PCIE_VIRT_BASE)
> +struct pcie_port {
> + int index;
> + u8 root_bus_nr;
> + void __iomem *base;
> + spinlock_t conf_lock;
> + int irq;
> + struct resource res[2];
> +};
>
> -void __init kirkwood_pcie_id(u32 *dev, u32 *rev)
> +static struct pcie_port pcie_port[2];
> +static int num_pcie_ports;
> +
> +static inline struct pcie_port *bus_to_port(int bus)
> {
> - *dev = orion_pcie_dev_id(PCIE_BASE);
> - *rev = orion_pcie_rev(PCIE_BASE);
> + int i;
> +
> + for (i = num_pcie_ports - 1; i >= 0; i--) {
> + int rbus = pcie_port[i].root_bus_nr;
you're still using the pcie_port global structure. the patch I sent
removed it, can you take this part (changes to kirkwood/pcie.c) from
my patch?
> + if (rbus != -1 && rbus <= bus)
> + break;
> + }
> +
> + return i >= 0 ? pcie_port + i : NULL;
> }
>
> -static int pcie_valid_config(int bus, int dev)
> +static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
> {
> /*
> * Don't go out when trying to access --
> * 1. nonexisting device on local bus
> * 2. where there's no device connected (no link)
> */
> - if (bus == 0 && dev == 0)
> + if (bus == pp->root_bus_nr && dev == 0)
> return 1;
>
> - if (!orion_pcie_link_up(PCIE_BASE))
> + if (!orion_pcie_link_up(pp->base))
> return 0;
>
> - if (bus == 0 && dev != 1)
> + if (bus == pp->root_bus_nr && dev != 1)
> return 0;
>
> return 1;
> @@ -52,22 +74,22 @@ static int pcie_valid_config(int bus, int dev)
> * and then reading the PCIE_CONF_DATA register. Need to make sure these
> * transactions are atomic.
> */
> -static DEFINE_SPINLOCK(kirkwood_pcie_lock);
>
> static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> int size, u32 *val)
> {
> + struct pcie_port *pp = bus_to_port(bus->number);
> unsigned long flags;
> int ret;
>
> - if (pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0) {
> + if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
> *val = 0xffffffff;
> return PCIBIOS_DEVICE_NOT_FOUND;
> }
>
> - spin_lock_irqsave(&kirkwood_pcie_lock, flags);
> - ret = orion_pcie_rd_conf(PCIE_BASE, bus, devfn, where, size, val);
> - spin_unlock_irqrestore(&kirkwood_pcie_lock, flags);
> + spin_lock_irqsave(&pp->conf_lock, flags);
> + ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val);
> + spin_unlock_irqrestore(&pp->conf_lock, flags);
>
> return ret;
> }
> @@ -75,15 +97,16 @@ static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
> int where, int size, u32 val)
> {
> + struct pcie_port *pp = bus_to_port(bus->number);
> unsigned long flags;
> int ret;
>
> - if (pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0)
> + if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
> return PCIBIOS_DEVICE_NOT_FOUND;
>
> - spin_lock_irqsave(&kirkwood_pcie_lock, flags);
> - ret = orion_pcie_wr_conf(PCIE_BASE, bus, devfn, where, size, val);
> - spin_unlock_irqrestore(&kirkwood_pcie_lock, flags);
> + spin_lock_irqsave(&pp->conf_lock, flags);
> + ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val);
> + spin_unlock_irqrestore(&pp->conf_lock, flags);
>
> return ret;
> }
> @@ -93,50 +116,106 @@ static struct pci_ops pcie_ops = {
> .write = pcie_wr_conf,
> };
>
> -
> -static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
> +static int __init pcie0_ioresouces_setup(struct pcie_port *pp)
> {
> - struct resource *res;
> - extern unsigned int kirkwood_clk_ctrl;
> -
> /*
> - * Generic PCIe unit setup.
> + * IORESOURCE_IO
> */
> - orion_pcie_setup(PCIE_BASE, &kirkwood_mbus_dram_info);
> + pp->res[0].name = "PCIe 0 I/O Space";
> + pp->res[0].start = KIRKWOOD_PCIE_IO_PHYS_BASE;
> + pp->res[0].end = pp->res[0].start + KIRKWOOD_PCIE_IO_SIZE - 1;
> + pp->res[0].flags = IORESOURCE_IO;
> + if (request_resource(&ioport_resource, &pp->res[0]))
> + panic("Request PCIe 0 IO resource failed\n");
>
> /*
> - * Request resources.
> + * IORESOURCE_MEM
> */
> - res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
> - if (!res)
> - panic("pcie_setup unable to alloc resources");
> + pp->res[1].name = "PCIe 0 MEM";
> + pp->res[1].start = KIRKWOOD_PCIE_MEM_PHYS_BASE;
> + pp->res[1].end = pp->res[1].start + KIRKWOOD_PCIE_MEM_SIZE - 1;
> + pp->res[1].flags = IORESOURCE_MEM;
> + if (request_resource(&iomem_resource, &pp->res[1]))
> + panic("Request PCIe 0 Memory resource failed\n");
> +
> + return 1;
> +}
>
> +static int __init pcie1_ioresouces_setup(struct pcie_port *pp)
> +{
> /*
> * IORESOURCE_IO
> */
> - res[0].name = "PCIe I/O Space";
> - res[0].flags = IORESOURCE_IO;
> - res[0].start = KIRKWOOD_PCIE_IO_BUS_BASE;
> - res[0].end = res[0].start + KIRKWOOD_PCIE_IO_SIZE - 1;
> - if (request_resource(&ioport_resource, &res[0]))
> - panic("Request PCIe IO resource failed\n");
> - sys->resource[0] = &res[0];
> + pp->res[0].name = "PCIe 1 I/O Space";
> + pp->res[0].start = KIRKWOOD_PCIE1_IO_PHYS_BASE;
> + pp->res[0].end = pp->res[0].start + KIRKWOOD_PCIE1_IO_SIZE - 1;
> + pp->res[0].flags = IORESOURCE_IO;
> + if (request_resource(&ioport_resource, &pp->res[0]))
> + panic("Request PCIe 1 IO resource failed\n");
>
> /*
> * IORESOURCE_MEM
> */
> - res[1].name = "PCIe Memory Space";
> - res[1].flags = IORESOURCE_MEM;
> - res[1].start = KIRKWOOD_PCIE_MEM_BUS_BASE;
> - res[1].end = res[1].start + KIRKWOOD_PCIE_MEM_SIZE - 1;
> - if (request_resource(&iomem_resource, &res[1]))
> - panic("Request PCIe Memory resource failed\n");
> - sys->resource[1] = &res[1];
> + pp->res[1].name = "PCIe 1 MEM";
> + pp->res[1].start = KIRKWOOD_PCIE1_MEM_PHYS_BASE;
> + pp->res[1].end = pp->res[1].start + KIRKWOOD_PCIE1_MEM_SIZE - 1;
> + pp->res[1].flags = IORESOURCE_MEM;
> + if (request_resource(&iomem_resource, &pp->res[1]))
> + panic("Request PCIe 1 Memory resource failed\n");
>
> - sys->resource[2] = NULL;
> - sys->io_offset = 0;
> + return 1;
> +}
> +
> +static void __init kirkwood_pcie_preinit(void)
> +{
> + int i;
> +
> + for (i = 0; i < num_pcie_ports; i++) {
> + struct pcie_port *pp = pcie_port + i;
> + extern unsigned int kirkwood_clk_ctrl;
>
> + switch (pp->index) {
> + case 0:
> + pp->base = (void __iomem *)PCIE_VIRT_BASE;
> + pp->irq = IRQ_KIRKWOOD_PCIE;
> kirkwood_clk_ctrl |= CGC_PEX0;
> + pcie0_ioresouces_setup(pp);
> + break;
> + case 1:
> + pp->base = (void __iomem *)PCIE1_VIRT_BASE;
> + pp->irq = IRQ_KIRKWOOD_PCIE1;
> + kirkwood_clk_ctrl |= CGC_PEX1;
> + pcie1_ioresouces_setup(pp);
> + break;
> + default:
> + panic("PCIe setup: invalid controller");
> + }
> + }
> +}
> +
> +static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
> +{
> + struct pcie_port *pp;
> +
> + if (nr >= num_pcie_ports)
> + return 0;
> +
> + pp = &pcie_port[nr];
> + pp->root_bus_nr = sys->busnr;
> +
> + printk(KERN_INFO "PCI: bus%d uses PCIe port %d\n",
> + sys->busnr, pp->index);
> +
> + /*
> + * Generic PCIe unit setup.
> + */
> + orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
> + orion_pcie_setup(pp->base, &kirkwood_mbus_dram_info);
> +
> + sys->resource[0] = &pp->res[0];
> + sys->resource[1] = &pp->res[1];
> + sys->resource[2] = NULL;
> + sys->io_offset = 0;
>
> return 1;
> }
> @@ -163,7 +242,7 @@ kirkwood_pcie_scan_bus(int nr, struct pci_sys_data *sys)
> {
> struct pci_bus *bus;
>
> - if (nr == 0) {
> + if (nr < num_pcie_ports) {
> bus = pci_scan_bus(sys->busnr, &pcie_ops, sys);
> } else {
> bus = NULL;
> @@ -175,18 +254,45 @@ kirkwood_pcie_scan_bus(int nr, struct pci_sys_data *sys)
>
> static int __init kirkwood_pcie_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
> {
> - return IRQ_KIRKWOOD_PCIE;
> + struct pcie_port *pp = bus_to_port(dev->bus->number);
> +
> + return pp->irq;
> }
>
> static struct hw_pci kirkwood_pci __initdata = {
> - .nr_controllers = 1,
> + .preinit = kirkwood_pcie_preinit,
> .swizzle = pci_std_swizzle,
> .setup = kirkwood_pcie_setup,
> .scan = kirkwood_pcie_scan_bus,
> .map_irq = kirkwood_pcie_map_irq,
> };
>
> -void __init kirkwood_pcie_init(void)
> +static void __init add_pcie_port(int index, unsigned long base)
> +{
> + printk(KERN_INFO "Kirkwood PCIe port %d: ", index);
> +
> + if (orion_pcie_link_up((void __iomem *)base)) {
> + struct pcie_port *pp = &pcie_port[num_pcie_ports++];
> +
> + printk(KERN_INFO "link up\n");
> +
> + pp->index = index;
> + pp->root_bus_nr = -1;
> + pp->base = (void __iomem *)base;
> + spin_lock_init(&pp->conf_lock);
> + memset(pp->res, 0, sizeof(pp->res));
> + } else
> + printk(KERN_INFO "link down, ignoring\n");
> +}
> +
> +void __init kirkwood_pcie_init(unsigned int portmask)
> {
> + if (portmask & KW_PCIE0)
> + add_pcie_port(0, PCIE_VIRT_BASE);
> +
> + if (portmask & KW_PCIE1)
> + add_pcie_port(1, PCIE1_VIRT_BASE);
> +
> + kirkwood_pci.nr_controllers = num_pcie_ports;
> pci_common_init(&kirkwood_pci);
> }
> diff --git a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
> index 3bf6304..c34718c 100644
> --- a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
> +++ b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
> @@ -71,7 +71,7 @@ static void __init rd88f6192_init(void)
> static int __init rd88f6192_pci_init(void)
> {
> if (machine_is_rd88f6192_nas())
> - kirkwood_pcie_init();
> + kirkwood_pcie_init(KW_PCIE0);
>
> return 0;
> }
> diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c
> index 31708dd..3d14771 100644
> --- a/arch/arm/mach-kirkwood/rd88f6281-setup.c
> +++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c
> @@ -107,7 +107,7 @@ static void __init rd88f6281_init(void)
> static int __init rd88f6281_pci_init(void)
> {
> if (machine_is_rd88f6281())
> - kirkwood_pcie_init();
> + kirkwood_pcie_init(KW_PCIE0);
>
> return 0;
> }
> diff --git a/arch/arm/mach-kirkwood/ts219-setup.c b/arch/arm/mach-kirkwood/ts219-setup.c
> index d23aff9..5c7dd85 100644
> --- a/arch/arm/mach-kirkwood/ts219-setup.c
> +++ b/arch/arm/mach-kirkwood/ts219-setup.c
> @@ -111,7 +111,7 @@ static void __init qnap_ts219_init(void)
> static int __init ts219_pci_init(void)
> {
> if (machine_is_ts219())
> - kirkwood_pcie_init();
> + kirkwood_pcie_init(KW_PCIE0);
>
> return 0;
> }
> diff --git a/arch/arm/mach-kirkwood/ts41x-setup.c b/arch/arm/mach-kirkwood/ts41x-setup.c
> index ecd0d5f..a2c5f70 100644
> --- a/arch/arm/mach-kirkwood/ts41x-setup.c
> +++ b/arch/arm/mach-kirkwood/ts41x-setup.c
> @@ -136,7 +136,7 @@ static void __init qnap_ts41x_init(void)
> static int __init ts41x_pci_init(void)
> {
> if (machine_is_ts41x())
> - kirkwood_pcie_init();
> + kirkwood_pcie_init(KW_PCIE0);
>
> return 0;
> }
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
More information about the linux-arm-kernel
mailing list