[ARM] Kirkwood: add support for PCIe1
This patch extends the kirkwood's PCIe support up to 2 controllers as in the 6282 devices. Signed-off-by: Saeed Bishara <saeed@marvell.com> Signed-off-by: Nicolas Pitre <nico@fluxnic.net>
This commit is contained in:
Родитель
35fe2fc44a
Коммит
ffd58bd2e4
|
@ -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
|
||||
|
||||
/*
|
||||
|
@ -106,17 +108,21 @@ void __init kirkwood_setup_cpu_mbus(void)
|
|||
TARGET_PCIE, ATTR_PCIE_IO, KIRKWOOD_PCIE_IO_BUS_BASE);
|
||||
setup_cpu_win(1, KIRKWOOD_PCIE_MEM_PHYS_BASE, KIRKWOOD_PCIE_MEM_SIZE,
|
||||
TARGET_PCIE, ATTR_PCIE_MEM, KIRKWOOD_PCIE_MEM_BUS_BASE);
|
||||
setup_cpu_win(2, KIRKWOOD_PCIE1_IO_PHYS_BASE, KIRKWOOD_PCIE1_IO_SIZE,
|
||||
TARGET_PCIE, ATTR_PCIE1_IO, KIRKWOOD_PCIE1_IO_BUS_BASE);
|
||||
setup_cpu_win(3, 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(4, 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(5, KIRKWOOD_SRAM_PHYS_BASE, KIRKWOOD_SRAM_SIZE,
|
||||
TARGET_SRAM, ATTR_SRAM, -1);
|
||||
|
||||
/*
|
||||
|
|
|
@ -43,6 +43,11 @@ static struct map_desc kirkwood_io_desc[] __initdata = {
|
|||
.pfn = __phys_to_pfn(KIRKWOOD_PCIE_IO_PHYS_BASE),
|
||||
.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),
|
||||
|
@ -960,12 +965,14 @@ void __init kirkwood_init(void)
|
|||
static int __init kirkwood_clock_gate(void)
|
||||
{
|
||||
unsigned int curr = readl(CLOCK_GATING_CTRL);
|
||||
u32 dev, rev;
|
||||
|
||||
kirkwood_pcie_id(&dev, &rev);
|
||||
printk(KERN_DEBUG "Gating clock of unused units\n");
|
||||
printk(KERN_DEBUG "before: 0x%08x\n", curr);
|
||||
|
||||
/* Make sure those units are accessible */
|
||||
writel(curr | CGC_SATA0 | CGC_SATA1 | CGC_PEX0, CLOCK_GATING_CTRL);
|
||||
writel(curr | CGC_SATA0 | CGC_SATA1 | CGC_PEX0 | CGC_PEX1, CLOCK_GATING_CTRL);
|
||||
|
||||
/* For SATA: first shutdown the phy */
|
||||
if (!(kirkwood_clk_ctrl & CGC_SATA0)) {
|
||||
|
@ -990,6 +997,18 @@ 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) {
|
||||
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);
|
||||
}
|
||||
} else /* keep this bit set for devices that don't have PCIe1 */
|
||||
kirkwood_clk_ctrl |= CGC_PEX1;
|
||||
|
||||
/* Now gate clock the required units */
|
||||
writel(kirkwood_clk_ctrl, CLOCK_GATING_CTRL);
|
||||
printk(KERN_DEBUG " after: 0x%08x\n", readl(CLOCK_GATING_CTRL));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -82,9 +82,15 @@ static void __init db88f6281_init(void)
|
|||
|
||||
static int __init db88f6281_pci_init(void)
|
||||
{
|
||||
if (machine_is_db88f6281_bp())
|
||||
kirkwood_pcie_init();
|
||||
if (machine_is_db88f6281_bp()) {
|
||||
u32 dev, rev;
|
||||
|
||||
kirkwood_pcie_id(&dev, &rev);
|
||||
if (dev == MV88F6282_DEV_ID)
|
||||
kirkwood_pcie_init(KW_PCIE1 | KW_PCIE0);
|
||||
else
|
||||
kirkwood_pcie_init(KW_PCIE0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
subsys_initcall(db88f6281_pci_init);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -16,36 +16,48 @@
|
|||
* Marvell Kirkwood address maps.
|
||||
*
|
||||
* phys
|
||||
* e0000000 PCIe Memory space
|
||||
* e0000000 PCIe #0 Memory space
|
||||
* e8000000 PCIe #1 Memory space
|
||||
* f1000000 on-chip peripheral registers
|
||||
* f2000000 PCIe I/O space
|
||||
* f3000000 NAND controller address window
|
||||
* f4000000 Security Accelerator SRAM
|
||||
* f2000000 PCIe #0 I/O space
|
||||
* f3000000 PCIe #1 I/O space
|
||||
* f4000000 NAND controller address window
|
||||
* f5000000 Security Accelerator SRAM
|
||||
*
|
||||
* virt phys size
|
||||
* fee00000 f1000000 1M on-chip peripheral registers
|
||||
* fef00000 f2000000 1M PCIe I/O space
|
||||
* fed00000 f1000000 1M on-chip peripheral registers
|
||||
* fee00000 f2000000 1M PCIe #0 I/O space
|
||||
* fef00000 f3000000 1M PCIe #1 I/O space
|
||||
*/
|
||||
|
||||
#define KIRKWOOD_SRAM_PHYS_BASE 0xf4000000
|
||||
#define KIRKWOOD_SRAM_PHYS_BASE 0xf5000000
|
||||
#define KIRKWOOD_SRAM_SIZE SZ_2K
|
||||
|
||||
#define KIRKWOOD_NAND_MEM_PHYS_BASE 0xf3000000
|
||||
#define KIRKWOOD_NAND_MEM_PHYS_BASE 0xf4000000
|
||||
#define KIRKWOOD_NAND_MEM_SIZE SZ_1K
|
||||
|
||||
#define KIRKWOOD_PCIE1_IO_PHYS_BASE 0xf3000000
|
||||
#define KIRKWOOD_PCIE1_IO_VIRT_BASE 0xfef00000
|
||||
#define KIRKWOOD_PCIE1_IO_BUS_BASE 0x00000000
|
||||
#define KIRKWOOD_PCIE1_IO_SIZE SZ_1M
|
||||
|
||||
#define KIRKWOOD_PCIE_IO_PHYS_BASE 0xf2000000
|
||||
#define KIRKWOOD_PCIE_IO_VIRT_BASE 0xfef00000
|
||||
#define KIRKWOOD_PCIE_IO_VIRT_BASE 0xfee00000
|
||||
#define KIRKWOOD_PCIE_IO_BUS_BASE 0x00000000
|
||||
#define KIRKWOOD_PCIE_IO_SIZE SZ_1M
|
||||
|
||||
#define KIRKWOOD_REGS_PHYS_BASE 0xf1000000
|
||||
#define KIRKWOOD_REGS_VIRT_BASE 0xfee00000
|
||||
#define KIRKWOOD_REGS_VIRT_BASE 0xfed00000
|
||||
#define KIRKWOOD_REGS_SIZE SZ_1M
|
||||
|
||||
#define KIRKWOOD_PCIE_MEM_PHYS_BASE 0xe0000000
|
||||
#define KIRKWOOD_PCIE_MEM_BUS_BASE 0xe0000000
|
||||
#define KIRKWOOD_PCIE_MEM_SIZE SZ_128M
|
||||
|
||||
#define KIRKWOOD_PCIE1_MEM_PHYS_BASE 0xe8000000
|
||||
#define KIRKWOOD_PCIE1_MEM_BUS_BASE 0xe8000000
|
||||
#define KIRKWOOD_PCIE1_MEM_SIZE SZ_128M
|
||||
|
||||
/*
|
||||
* Register Map
|
||||
*/
|
||||
|
@ -72,6 +84,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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ static int __init openrd_pci_init(void)
|
|||
if (machine_is_openrd_base() ||
|
||||
machine_is_openrd_client() ||
|
||||
machine_is_openrd_ultimate())
|
||||
kirkwood_pcie_init();
|
||||
kirkwood_pcie_init(KW_PCIE0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -18,29 +18,43 @@
|
|||
#include <mach/bridge-regs.h>
|
||||
#include "common.h"
|
||||
|
||||
|
||||
#define PCIE_BASE ((void __iomem *)PCIE_VIRT_BASE)
|
||||
|
||||
void __init kirkwood_pcie_id(u32 *dev, u32 *rev)
|
||||
{
|
||||
*dev = orion_pcie_dev_id(PCIE_BASE);
|
||||
*rev = orion_pcie_rev(PCIE_BASE);
|
||||
*dev = orion_pcie_dev_id((void __iomem *)PCIE_VIRT_BASE);
|
||||
*rev = orion_pcie_rev((void __iomem *)PCIE_VIRT_BASE);
|
||||
}
|
||||
|
||||
static int pcie_valid_config(int bus, int dev)
|
||||
struct pcie_port {
|
||||
u8 root_bus_nr;
|
||||
void __iomem *base;
|
||||
spinlock_t conf_lock;
|
||||
int irq;
|
||||
struct resource res[2];
|
||||
};
|
||||
|
||||
static int pcie_port_map[2];
|
||||
static int num_pcie_ports;
|
||||
|
||||
static inline struct pcie_port *bus_to_port(struct pci_bus *bus)
|
||||
{
|
||||
struct pci_sys_data *sys = bus->sysdata;
|
||||
return sys->private_data;
|
||||
}
|
||||
|
||||
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 +66,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);
|
||||
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 +89,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);
|
||||
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 +108,112 @@ 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_ioresources_setup(struct pci_sys_data *sys)
|
||||
{
|
||||
struct resource *res;
|
||||
extern unsigned int kirkwood_clk_ctrl;
|
||||
|
||||
/*
|
||||
* Generic PCIe unit setup.
|
||||
*/
|
||||
orion_pcie_setup(PCIE_BASE, &kirkwood_mbus_dram_info);
|
||||
|
||||
/*
|
||||
* Request resources.
|
||||
*/
|
||||
res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
|
||||
if (!res)
|
||||
panic("pcie_setup unable to alloc resources");
|
||||
struct pcie_port *pp = (struct pcie_port *)sys->private_data;
|
||||
|
||||
/*
|
||||
* 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 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");
|
||||
sys->resource[0] = &pp->res[0];
|
||||
|
||||
/*
|
||||
* 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 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");
|
||||
sys->resource[1] = &pp->res[1];
|
||||
|
||||
sys->resource[2] = NULL;
|
||||
sys->io_offset = 0;
|
||||
|
||||
kirkwood_clk_ctrl |= CGC_PEX0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init pcie1_ioresources_setup(struct pci_sys_data *sys)
|
||||
{
|
||||
struct pcie_port *pp = (struct pcie_port *)sys->private_data;
|
||||
|
||||
/*
|
||||
* IORESOURCE_IO
|
||||
*/
|
||||
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");
|
||||
sys->resource[0] = &pp->res[0];
|
||||
|
||||
/*
|
||||
* IORESOURCE_MEM
|
||||
*/
|
||||
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[1] = &pp->res[1];
|
||||
|
||||
sys->resource[2] = NULL;
|
||||
sys->io_offset = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
|
||||
{
|
||||
extern unsigned int kirkwood_clk_ctrl;
|
||||
struct pcie_port *pp;
|
||||
int index;
|
||||
|
||||
if (nr >= num_pcie_ports)
|
||||
return 0;
|
||||
|
||||
index = pcie_port_map[nr];
|
||||
printk(KERN_INFO "PCI: bus%d uses PCIe port %d\n", sys->busnr, index);
|
||||
|
||||
pp = kzalloc(sizeof(*pp), GFP_KERNEL);
|
||||
if (!pp)
|
||||
panic("PCIe: failed to allocate pcie_port data");
|
||||
sys->private_data = pp;
|
||||
pp->root_bus_nr = sys->busnr;
|
||||
spin_lock_init(&pp->conf_lock);
|
||||
|
||||
switch (index) {
|
||||
case 0:
|
||||
pp->base = (void __iomem *)PCIE_VIRT_BASE;
|
||||
pp->irq = IRQ_KIRKWOOD_PCIE;
|
||||
kirkwood_clk_ctrl |= CGC_PEX0;
|
||||
pcie0_ioresources_setup(sys);
|
||||
break;
|
||||
case 1:
|
||||
pp->base = (void __iomem *)PCIE1_VIRT_BASE;
|
||||
pp->irq = IRQ_KIRKWOOD_PCIE1;
|
||||
kirkwood_clk_ctrl |= CGC_PEX1;
|
||||
pcie1_ioresources_setup(sys);
|
||||
break;
|
||||
default:
|
||||
panic("PCIe setup: invalid controller");
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic PCIe unit setup.
|
||||
*/
|
||||
orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
|
||||
|
||||
orion_pcie_setup(pp->base, &kirkwood_mbus_dram_info);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -163,7 +240,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 +252,37 @@ 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);
|
||||
|
||||
return pp->irq;
|
||||
}
|
||||
|
||||
static struct hw_pci kirkwood_pci __initdata = {
|
||||
.nr_controllers = 1,
|
||||
.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)) {
|
||||
printk(KERN_INFO "link up\n");
|
||||
pcie_port_map[num_pcie_ports++] = index;
|
||||
} 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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ static void __init hp_t5325_init(void)
|
|||
static int __init hp_t5325_pci_init(void)
|
||||
{
|
||||
if (machine_is_t5325())
|
||||
kirkwood_pcie_init();
|
||||
kirkwood_pcie_init(KW_PCIE0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -111,10 +111,10 @@ static void __init qnap_ts219_init(void)
|
|||
|
||||
static int __init ts219_pci_init(void)
|
||||
{
|
||||
if (machine_is_ts219())
|
||||
kirkwood_pcie_init();
|
||||
if (machine_is_ts219())
|
||||
kirkwood_pcie_init(KW_PCIE0);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
subsys_initcall(ts219_pci_init);
|
||||
|
||||
|
|
|
@ -141,7 +141,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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче