Orion: make PCIe/PCI support use mbus DRAM info

Make the Orion PCIe/PCI code initialise MBUS decode windows based on
mbus_dram_target_info instead of reading the info from the Orion DDR
unit decode registers directly, and move the window code with the other
PCI code, where it can be called as part of the generic PCIe/PCI init
process.

Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Reviewed-by: Tzachi Perelstein <tzachi@marvell.com>
Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Nicolas Pitre <nico@marvell.com>
This commit is contained in:
Lennert Buytenhek 2008-03-27 14:51:39 -04:00 committed by Nicolas Pitre
parent 83b6d822e4
commit 1f2223b12b
4 changed files with 168 additions and 158 deletions

View File

@ -92,56 +92,6 @@
#define CPU_WIN_DEV_CS1 6 #define CPU_WIN_DEV_CS1 6
#define CPU_WIN_DEV_CS2 7 #define CPU_WIN_DEV_CS2 7
/*
* PCIE Address Decode Windows registers
*/
#define PCIE_BAR_CTRL(n) ORION_PCIE_REG(0x1804 + ((n - 1) * 4))
#define PCIE_BAR_LO(n) ORION_PCIE_REG(0x0010 + ((n) * 8))
#define PCIE_BAR_HI(n) ORION_PCIE_REG(0x0014 + ((n) * 8))
#define PCIE_WIN_CTRL(n) (((n) < 5) ? \
ORION_PCIE_REG(0x1820 + ((n) << 4)) : \
ORION_PCIE_REG(0x1880))
#define PCIE_WIN_BASE(n) (((n) < 5) ? \
ORION_PCIE_REG(0x1824 + ((n) << 4)) : \
ORION_PCIE_REG(0x1884))
#define PCIE_WIN_REMAP(n) (((n) < 5) ? \
ORION_PCIE_REG(0x182c + ((n) << 4)) : \
ORION_PCIE_REG(0x188c))
#define PCIE_DEFWIN_CTRL ORION_PCIE_REG(0x18b0)
#define PCIE_EXPROM_WIN_CTRL ORION_PCIE_REG(0x18c0)
#define PCIE_EXPROM_WIN_REMP ORION_PCIE_REG(0x18c4)
#define PCIE_MAX_BARS 3
#define PCIE_MAX_WINS 6
/*
* Use PCIE BAR '1' for all DDR banks
*/
#define PCIE_DRAM_BAR 1
/*
* PCI Address Decode Windows registers
*/
#define PCI_BAR_SIZE_DDR_CS(n) (((n) == 0) ? ORION_PCI_REG(0xc08) : \
((n) == 1) ? ORION_PCI_REG(0xd08) : \
((n) == 2) ? ORION_PCI_REG(0xc0c) : \
((n) == 3) ? ORION_PCI_REG(0xd0c) : 0)
#define PCI_BAR_REMAP_DDR_CS(n) (((n) ==0) ? ORION_PCI_REG(0xc48) : \
((n) == 1) ? ORION_PCI_REG(0xd48) : \
((n) == 2) ? ORION_PCI_REG(0xc4c) : \
((n) == 3) ? ORION_PCI_REG(0xd4c) : 0)
#define PCI_BAR_ENABLE ORION_PCI_REG(0xc3c)
#define PCI_CTRL_BASE_LO(n) ORION_PCI_REG(0x1e00 | ((n) << 4))
#define PCI_CTRL_BASE_HI(n) ORION_PCI_REG(0x1e04 | ((n) << 4))
#define PCI_CTRL_SIZE(n) ORION_PCI_REG(0x1e08 | ((n) << 4))
#define PCI_ADDR_DECODE_CTRL ORION_PCI_REG(0xd3c)
/*
* PCI configuration heleprs for BAR settings
*/
#define PCI_CONF_FUNC_BAR_CS(n) ((n) >> 1)
#define PCI_CONF_REG_BAR_LO_CS(n) (((n) & 1) ? 0x18 : 0x10)
#define PCI_CONF_REG_BAR_HI_CS(n) (((n) & 1) ? 0x1c : 0x14)
/* /*
* Gigabit Ethernet Address Decode Windows registers * Gigabit Ethernet Address Decode Windows registers
*/ */
@ -312,104 +262,6 @@ void __init orion_setup_cpu_wins(void)
orion_mbus_dram_info.num_cs = cs; orion_mbus_dram_info.num_cs = cs;
} }
/*
* Setup PCIE BARs and Address Decode Wins:
* BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
* WIN[0-3] -> DRAM bank[0-3]
*/
void __init orion_setup_pcie_wins(void)
{
u32 base, size, i;
/*
* First, disable and clear BARs and windows
*/
for (i = 1; i < PCIE_MAX_BARS; i++) {
orion_write(PCIE_BAR_CTRL(i), 0);
orion_write(PCIE_BAR_LO(i), 0);
orion_write(PCIE_BAR_HI(i), 0);
}
for (i = 0; i < PCIE_MAX_WINS; i++) {
orion_write(PCIE_WIN_CTRL(i), 0);
orion_write(PCIE_WIN_BASE(i), 0);
orion_write(PCIE_WIN_REMAP(i), 0);
}
/*
* Setup windows for DDR banks. Count total DDR size on the fly.
*/
base = DDR_REG_TO_BASE(orion_read(DDR_BASE_CS(0)));
size = 0;
for (i = 0; i < DDR_MAX_CS; i++) {
u32 bank_base, bank_size;
bank_size = orion_read(DDR_SIZE_CS(i));
bank_base = orion_read(DDR_BASE_CS(i));
if (bank_size & DDR_BANK_EN) {
bank_size = DDR_REG_TO_SIZE(bank_size);
bank_base = DDR_REG_TO_BASE(bank_base);
orion_write(PCIE_WIN_BASE(i), bank_base & 0xffff0000);
orion_write(PCIE_WIN_REMAP(i), 0);
orion_write(PCIE_WIN_CTRL(i),
((bank_size-1) & 0xffff0000) |
(ATTR_DDR_CS(i) << 8) |
(TARGET_DDR << 4) |
(PCIE_DRAM_BAR << 1) | WIN_EN);
size += bank_size;
}
}
/*
* Setup BAR[1] to all DRAM banks
*/
orion_write(PCIE_BAR_LO(PCIE_DRAM_BAR), base & 0xffff0000);
orion_write(PCIE_BAR_HI(PCIE_DRAM_BAR), 0);
orion_write(PCIE_BAR_CTRL(PCIE_DRAM_BAR),
((size - 1) & 0xffff0000) | WIN_EN);
}
void __init orion_setup_pci_wins(void)
{
u32 base, size, i;
/*
* First, disable windows
*/
orion_write(PCI_BAR_ENABLE, 0xffffffff);
/*
* Setup windows for DDR banks.
*/
for (i = 0; i < DDR_MAX_CS; i++) {
base = orion_read(DDR_BASE_CS(i));
size = orion_read(DDR_SIZE_CS(i));
if (size & DDR_BANK_EN) {
u32 bus, dev, func, reg, val;
size = DDR_REG_TO_SIZE(size);
base = DDR_REG_TO_BASE(base);
bus = orion_pci_local_bus_nr();
dev = orion_pci_local_dev_nr();
func = PCI_CONF_FUNC_BAR_CS(i);
reg = PCI_CONF_REG_BAR_LO_CS(i);
orion_pci_hw_rd_conf(bus, dev, func, reg, 4, &val);
orion_pci_hw_wr_conf(bus, dev, func, reg, 4,
(base & 0xfffff000) | (val & 0xfff));
reg = PCI_CONF_REG_BAR_HI_CS(i);
orion_pci_hw_wr_conf(bus, dev, func, reg, 4, 0);
orion_write(PCI_BAR_SIZE_DDR_CS(i),
(size - 1) & 0xfffff000);
orion_write(PCI_BAR_REMAP_DDR_CS(i),
base & 0xfffff000);
orion_clrbits(PCI_BAR_ENABLE, (1 << i));
}
}
/*
* Disable automatic update of address remaping when writing to BARs
*/
orion_setbits(PCI_ADDR_DECODE_CTRL, 1);
}
void __init orion_setup_usb_wins(void) void __init orion_setup_usb_wins(void)
{ {
int i; int i;

View File

@ -336,8 +336,6 @@ void __init orion_init(void)
orion_setup_cpu_wins(); orion_setup_cpu_wins();
orion_setup_usb_wins(); orion_setup_usb_wins();
orion_setup_eth_wins(); orion_setup_eth_wins();
orion_setup_pci_wins();
orion_setup_pcie_wins();
if (dev == MV88F5182_DEV_ID) if (dev == MV88F5182_DEV_ID)
orion_setup_sata_wins(); orion_setup_sata_wins();

View File

@ -34,8 +34,6 @@ void orion_setup_cpu_win(enum orion_target target, u32 base, u32 size, int remap
void orion_setup_cpu_wins(void); void orion_setup_cpu_wins(void);
void orion_setup_eth_wins(void); void orion_setup_eth_wins(void);
void orion_setup_usb_wins(void); void orion_setup_usb_wins(void);
void orion_setup_pci_wins(void);
void orion_setup_pcie_wins(void);
void orion_setup_sata_wins(void); void orion_setup_sata_wins(void);
/* /*
@ -49,11 +47,8 @@ struct pci_bus;
void orion_pcie_id(u32 *dev, u32 *rev); void orion_pcie_id(u32 *dev, u32 *rev);
u32 orion_pcie_local_bus_nr(void); u32 orion_pcie_local_bus_nr(void);
u32 orion_pci_local_bus_nr(void); u32 orion_pci_local_bus_nr(void);
u32 orion_pci_local_dev_nr(void);
int orion_pci_sys_setup(int nr, struct pci_sys_data *sys); int orion_pci_sys_setup(int nr, struct pci_sys_data *sys);
struct pci_bus *orion_pci_sys_scan_bus(int nr, struct pci_sys_data *sys); struct pci_bus *orion_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func, u32 where, u32 size, u32 *val);
int orion_pci_hw_wr_conf(u32 bus, u32 dev, u32 func, u32 where, u32 size, u32 val);
/* /*
* Valid GPIO pins according to MPP setup, used by machine-setup. * Valid GPIO pins according to MPP setup, used by machine-setup.

View File

@ -12,6 +12,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/mbus.h>
#include <asm/mach/pci.h> #include <asm/mach/pci.h>
#include "common.h" #include "common.h"
@ -58,6 +59,29 @@
#define PCIE_CONF_BUS(b) (((b) & 0xff) << 16) #define PCIE_CONF_BUS(b) (((b) & 0xff) << 16)
#define PCIE_CONF_ADDR_EN (1 << 31) #define PCIE_CONF_ADDR_EN (1 << 31)
/*
* PCIE Address Decode Windows registers
*/
#define PCIE_BAR_CTRL(n) ORION_PCIE_REG(0x1804 + ((n - 1) * 4))
#define PCIE_BAR_LO(n) ORION_PCIE_REG(0x0010 + ((n) * 8))
#define PCIE_BAR_HI(n) ORION_PCIE_REG(0x0014 + ((n) * 8))
#define PCIE_WIN_CTRL(n) (((n) < 5) ? \
ORION_PCIE_REG(0x1820 + ((n) << 4)) : \
ORION_PCIE_REG(0x1880))
#define PCIE_WIN_BASE(n) (((n) < 5) ? \
ORION_PCIE_REG(0x1824 + ((n) << 4)) : \
ORION_PCIE_REG(0x1884))
#define PCIE_WIN_REMAP(n) (((n) < 5) ? \
ORION_PCIE_REG(0x182c + ((n) << 4)) : \
ORION_PCIE_REG(0x188c))
#define PCIE_MAX_BARS 3
#define PCIE_MAX_WINS 6
/*
* Use PCIE BAR '1' for all DDR banks
*/
#define PCIE_DRAM_BAR 1
/* /*
* PCIE config cycles are done by programming the PCIE_CONF_ADDR register * PCIE config cycles are done by programming the PCIE_CONF_ADDR register
* and then reading the PCIE_CONF_DATA register. Need to make sure these * and then reading the PCIE_CONF_DATA register. Need to make sure these
@ -95,6 +119,56 @@ static void orion_pcie_set_bus_nr(int nr)
orion_setbits(PCIE_STAT, nr << PCIE_STAT_BUS_OFFS); orion_setbits(PCIE_STAT, nr << PCIE_STAT_BUS_OFFS);
} }
/*
* Setup PCIE BARs and Address Decode Wins:
* BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
* WIN[0-3] -> DRAM bank[0-3]
*/
static void orion_setup_pcie_wins(struct mbus_dram_target_info *dram)
{
u32 size;
int i;
/*
* First, disable and clear BARs and windows
*/
for (i = 1; i < PCIE_MAX_BARS; i++) {
writel(0, PCIE_BAR_CTRL(i));
writel(0, PCIE_BAR_LO(i));
writel(0, PCIE_BAR_HI(i));
}
for (i = 0; i < PCIE_MAX_WINS; i++) {
writel(0, PCIE_WIN_CTRL(i));
writel(0, PCIE_WIN_BASE(i));
writel(0, PCIE_WIN_REMAP(i));
}
/*
* Setup windows for DDR banks. Count total DDR size on the fly.
*/
size = 0;
for (i = 0; i < dram->num_cs; i++) {
struct mbus_dram_window *cs = dram->cs + i;
writel(cs->base & 0xffff0000, PCIE_WIN_BASE(i));
writel(0, PCIE_WIN_REMAP(i));
writel(((cs->size - 1) & 0xffff0000) |
(cs->mbus_attr << 8) |
(dram->mbus_dram_target_id << 4) |
(PCIE_DRAM_BAR << 1) | 1, PCIE_WIN_CTRL(i));
size += cs->size;
}
/*
* Setup BAR[1] to all DRAM banks
*/
writel(dram->cs[0].base, PCIE_BAR_LO(PCIE_DRAM_BAR));
writel(0, PCIE_BAR_HI(PCIE_DRAM_BAR));
writel(((size - 1) & 0xffff0000) | 1, PCIE_BAR_CTRL(PCIE_DRAM_BAR));
}
static void orion_pcie_master_slave_enable(void) static void orion_pcie_master_slave_enable(void)
{ {
orion_setbits(PCIE_CMD_STAT, PCI_COMMAND_MASTER | orion_setbits(PCIE_CMD_STAT, PCI_COMMAND_MASTER |
@ -219,6 +293,11 @@ static int orion_pcie_setup(struct pci_sys_data *sys)
{ {
struct resource *res; struct resource *res;
/*
* Point PCIe unit MBUS decode windows to DRAM space.
*/
orion_setup_pcie_wins(&orion_mbus_dram_info);
/* /*
* Master + Slave enable * Master + Slave enable
*/ */
@ -310,6 +389,27 @@ static int orion_pcie_setup(struct pci_sys_data *sys)
#define PCIX_STAT_BUS_OFFS 8 #define PCIX_STAT_BUS_OFFS 8
#define PCIX_STAT_BUS_MASK (0xff << PCIX_STAT_BUS_OFFS) #define PCIX_STAT_BUS_MASK (0xff << PCIX_STAT_BUS_OFFS)
/*
* PCI Address Decode Windows registers
*/
#define PCI_BAR_SIZE_DDR_CS(n) (((n) == 0) ? ORION_PCI_REG(0xc08) : \
((n) == 1) ? ORION_PCI_REG(0xd08) : \
((n) == 2) ? ORION_PCI_REG(0xc0c) : \
((n) == 3) ? ORION_PCI_REG(0xd0c) : 0)
#define PCI_BAR_REMAP_DDR_CS(n) (((n) ==0) ? ORION_PCI_REG(0xc48) : \
((n) == 1) ? ORION_PCI_REG(0xd48) : \
((n) == 2) ? ORION_PCI_REG(0xc4c) : \
((n) == 3) ? ORION_PCI_REG(0xd4c) : 0)
#define PCI_BAR_ENABLE ORION_PCI_REG(0xc3c)
#define PCI_ADDR_DECODE_CTRL ORION_PCI_REG(0xd3c)
/*
* PCI configuration helpers for BAR settings
*/
#define PCI_CONF_FUNC_BAR_CS(n) ((n) >> 1)
#define PCI_CONF_REG_BAR_LO_CS(n) (((n) & 1) ? 0x18 : 0x10)
#define PCI_CONF_REG_BAR_HI_CS(n) (((n) & 1) ? 0x1c : 0x14)
/* /*
* PCI config cycles are done by programming the PCI_CONF_ADDR register * PCI config cycles are done by programming the PCI_CONF_ADDR register
* and then reading the PCI_CONF_DATA register. Need to make sure these * and then reading the PCI_CONF_DATA register. Need to make sure these
@ -323,13 +423,13 @@ u32 orion_pci_local_bus_nr(void)
return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS); return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS);
} }
u32 orion_pci_local_dev_nr(void) static u32 orion_pci_local_dev_nr(void)
{ {
u32 conf = orion_read(PCI_P2P_CONF); u32 conf = orion_read(PCI_P2P_CONF);
return((conf & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS); return((conf & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS);
} }
int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func, static int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func,
u32 where, u32 size, u32 *val) u32 where, u32 size, u32 *val)
{ {
unsigned long flags; unsigned long flags;
@ -351,7 +451,7 @@ int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func,
return PCIBIOS_SUCCESSFUL; return PCIBIOS_SUCCESSFUL;
} }
int orion_pci_hw_wr_conf(u32 bus, u32 dev, u32 func, static int orion_pci_hw_wr_conf(u32 bus, u32 dev, u32 func,
u32 where, u32 size, u32 val) u32 where, u32 size, u32 val)
{ {
unsigned long flags; unsigned long flags;
@ -451,10 +551,75 @@ static void orion_pci_master_slave_enable(void)
orion_pci_hw_wr_conf(bus_nr, dev_nr, func, reg, 4, val | 0x7); orion_pci_hw_wr_conf(bus_nr, dev_nr, func, reg, 4, val | 0x7);
} }
static void orion_setup_pci_wins(struct mbus_dram_target_info *dram)
{
u32 win_enable;
u32 bus;
u32 dev;
int i;
/*
* First, disable windows.
*/
win_enable = 0xffffffff;
orion_write(PCI_BAR_ENABLE, win_enable);
/*
* Setup windows for DDR banks.
*/
bus = orion_pci_local_bus_nr();
dev = orion_pci_local_dev_nr();
for (i = 0; i < dram->num_cs; i++) {
struct mbus_dram_window *cs = dram->cs + i;
u32 func = PCI_CONF_FUNC_BAR_CS(cs->cs_index);
u32 reg;
u32 val;
/*
* Write DRAM bank base address register.
*/
reg = PCI_CONF_REG_BAR_LO_CS(cs->cs_index);
orion_pci_hw_rd_conf(bus, dev, func, reg, 4, &val);
val = (cs->base & 0xfffff000) | (val & 0xfff);
orion_pci_hw_wr_conf(bus, dev, func, reg, 4, val);
/*
* Write DRAM bank size register.
*/
reg = PCI_CONF_REG_BAR_HI_CS(cs->cs_index);
orion_pci_hw_wr_conf(bus, dev, func, reg, 4, 0);
orion_write(PCI_BAR_SIZE_DDR_CS(cs->cs_index),
(cs->size - 1) & 0xfffff000);
orion_write(PCI_BAR_REMAP_DDR_CS(cs->cs_index),
cs->base & 0xfffff000);
/*
* Enable decode window for this chip select.
*/
win_enable &= ~(1 << cs->cs_index);
}
/*
* Re-enable decode windows.
*/
orion_write(PCI_BAR_ENABLE, win_enable);
/*
* Disable automatic update of address remaping when writing to BARs.
*/
orion_setbits(PCI_ADDR_DECODE_CTRL, 1);
}
static int orion_pci_setup(struct pci_sys_data *sys) static int orion_pci_setup(struct pci_sys_data *sys)
{ {
struct resource *res; struct resource *res;
/*
* Point PCI unit MBUS decode windows to DRAM space.
*/
orion_setup_pci_wins(&orion_mbus_dram_info);
/* /*
* Master + Slave enable * Master + Slave enable
*/ */