aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-orion/pci.c
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2008-03-27 14:51:39 -0400
committerNicolas Pitre <nico@marvell.com>2008-03-27 14:51:39 -0400
commit1f2223b12b62a97d66e39199db50ed3fae9222c0 (patch)
tree580b67aac92cc85f3700235f080f597a0eb94a5a /arch/arm/mach-orion/pci.c
parent83b6d822e4237052371e771b1f994823615a5341 (diff)
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>
Diffstat (limited to 'arch/arm/mach-orion/pci.c')
-rw-r--r--arch/arm/mach-orion/pci.c171
1 files changed, 168 insertions, 3 deletions
diff --git a/arch/arm/mach-orion/pci.c b/arch/arm/mach-orion/pci.c
index b109bb46681e..cfd3d064c209 100644
--- a/arch/arm/mach-orion/pci.c
+++ b/arch/arm/mach-orion/pci.c
@@ -12,6 +12,7 @@
12 12
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/pci.h> 14#include <linux/pci.h>
15#include <linux/mbus.h>
15#include <asm/mach/pci.h> 16#include <asm/mach/pci.h>
16#include "common.h" 17#include "common.h"
17 18
@@ -59,6 +60,29 @@
59#define PCIE_CONF_ADDR_EN (1 << 31) 60#define PCIE_CONF_ADDR_EN (1 << 31)
60 61
61/* 62/*
63 * PCIE Address Decode Windows registers
64 */
65#define PCIE_BAR_CTRL(n) ORION_PCIE_REG(0x1804 + ((n - 1) * 4))
66#define PCIE_BAR_LO(n) ORION_PCIE_REG(0x0010 + ((n) * 8))
67#define PCIE_BAR_HI(n) ORION_PCIE_REG(0x0014 + ((n) * 8))
68#define PCIE_WIN_CTRL(n) (((n) < 5) ? \
69 ORION_PCIE_REG(0x1820 + ((n) << 4)) : \
70 ORION_PCIE_REG(0x1880))
71#define PCIE_WIN_BASE(n) (((n) < 5) ? \
72 ORION_PCIE_REG(0x1824 + ((n) << 4)) : \
73 ORION_PCIE_REG(0x1884))
74#define PCIE_WIN_REMAP(n) (((n) < 5) ? \
75 ORION_PCIE_REG(0x182c + ((n) << 4)) : \
76 ORION_PCIE_REG(0x188c))
77#define PCIE_MAX_BARS 3
78#define PCIE_MAX_WINS 6
79
80/*
81 * Use PCIE BAR '1' for all DDR banks
82 */
83#define PCIE_DRAM_BAR 1
84
85/*
62 * PCIE config cycles are done by programming the PCIE_CONF_ADDR register 86 * PCIE config cycles are done by programming the PCIE_CONF_ADDR register
63 * and then reading the PCIE_CONF_DATA register. Need to make sure these 87 * and then reading the PCIE_CONF_DATA register. Need to make sure these
64 * transactions are atomic. 88 * transactions are atomic.
@@ -95,6 +119,56 @@ static void orion_pcie_set_bus_nr(int nr)
95 orion_setbits(PCIE_STAT, nr << PCIE_STAT_BUS_OFFS); 119 orion_setbits(PCIE_STAT, nr << PCIE_STAT_BUS_OFFS);
96} 120}
97 121
122/*
123 * Setup PCIE BARs and Address Decode Wins:
124 * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
125 * WIN[0-3] -> DRAM bank[0-3]
126 */
127static void orion_setup_pcie_wins(struct mbus_dram_target_info *dram)
128{
129 u32 size;
130 int i;
131
132 /*
133 * First, disable and clear BARs and windows
134 */
135 for (i = 1; i < PCIE_MAX_BARS; i++) {
136 writel(0, PCIE_BAR_CTRL(i));
137 writel(0, PCIE_BAR_LO(i));
138 writel(0, PCIE_BAR_HI(i));
139 }
140
141 for (i = 0; i < PCIE_MAX_WINS; i++) {
142 writel(0, PCIE_WIN_CTRL(i));
143 writel(0, PCIE_WIN_BASE(i));
144 writel(0, PCIE_WIN_REMAP(i));
145 }
146
147 /*
148 * Setup windows for DDR banks. Count total DDR size on the fly.
149 */
150 size = 0;
151 for (i = 0; i < dram->num_cs; i++) {
152 struct mbus_dram_window *cs = dram->cs + i;
153
154 writel(cs->base & 0xffff0000, PCIE_WIN_BASE(i));
155 writel(0, PCIE_WIN_REMAP(i));
156 writel(((cs->size - 1) & 0xffff0000) |
157 (cs->mbus_attr << 8) |
158 (dram->mbus_dram_target_id << 4) |
159 (PCIE_DRAM_BAR << 1) | 1, PCIE_WIN_CTRL(i));
160
161 size += cs->size;
162 }
163
164 /*
165 * Setup BAR[1] to all DRAM banks
166 */
167 writel(dram->cs[0].base, PCIE_BAR_LO(PCIE_DRAM_BAR));
168 writel(0, PCIE_BAR_HI(PCIE_DRAM_BAR));
169 writel(((size - 1) & 0xffff0000) | 1, PCIE_BAR_CTRL(PCIE_DRAM_BAR));
170}
171
98static void orion_pcie_master_slave_enable(void) 172static void orion_pcie_master_slave_enable(void)
99{ 173{
100 orion_setbits(PCIE_CMD_STAT, PCI_COMMAND_MASTER | 174 orion_setbits(PCIE_CMD_STAT, PCI_COMMAND_MASTER |
@@ -220,6 +294,11 @@ static int orion_pcie_setup(struct pci_sys_data *sys)
220 struct resource *res; 294 struct resource *res;
221 295
222 /* 296 /*
297 * Point PCIe unit MBUS decode windows to DRAM space.
298 */
299 orion_setup_pcie_wins(&orion_mbus_dram_info);
300
301 /*
223 * Master + Slave enable 302 * Master + Slave enable
224 */ 303 */
225 orion_pcie_master_slave_enable(); 304 orion_pcie_master_slave_enable();
@@ -311,6 +390,27 @@ static int orion_pcie_setup(struct pci_sys_data *sys)
311#define PCIX_STAT_BUS_MASK (0xff << PCIX_STAT_BUS_OFFS) 390#define PCIX_STAT_BUS_MASK (0xff << PCIX_STAT_BUS_OFFS)
312 391
313/* 392/*
393 * PCI Address Decode Windows registers
394 */
395#define PCI_BAR_SIZE_DDR_CS(n) (((n) == 0) ? ORION_PCI_REG(0xc08) : \
396 ((n) == 1) ? ORION_PCI_REG(0xd08) : \
397 ((n) == 2) ? ORION_PCI_REG(0xc0c) : \
398 ((n) == 3) ? ORION_PCI_REG(0xd0c) : 0)
399#define PCI_BAR_REMAP_DDR_CS(n) (((n) ==0) ? ORION_PCI_REG(0xc48) : \
400 ((n) == 1) ? ORION_PCI_REG(0xd48) : \
401 ((n) == 2) ? ORION_PCI_REG(0xc4c) : \
402 ((n) == 3) ? ORION_PCI_REG(0xd4c) : 0)
403#define PCI_BAR_ENABLE ORION_PCI_REG(0xc3c)
404#define PCI_ADDR_DECODE_CTRL ORION_PCI_REG(0xd3c)
405
406/*
407 * PCI configuration helpers for BAR settings
408 */
409#define PCI_CONF_FUNC_BAR_CS(n) ((n) >> 1)
410#define PCI_CONF_REG_BAR_LO_CS(n) (((n) & 1) ? 0x18 : 0x10)
411#define PCI_CONF_REG_BAR_HI_CS(n) (((n) & 1) ? 0x1c : 0x14)
412
413/*
314 * PCI config cycles are done by programming the PCI_CONF_ADDR register 414 * PCI config cycles are done by programming the PCI_CONF_ADDR register
315 * and then reading the PCI_CONF_DATA register. Need to make sure these 415 * and then reading the PCI_CONF_DATA register. Need to make sure these
316 * transactions are atomic. 416 * transactions are atomic.
@@ -323,13 +423,13 @@ u32 orion_pci_local_bus_nr(void)
323 return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS); 423 return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS);
324} 424}
325 425
326u32 orion_pci_local_dev_nr(void) 426static u32 orion_pci_local_dev_nr(void)
327{ 427{
328 u32 conf = orion_read(PCI_P2P_CONF); 428 u32 conf = orion_read(PCI_P2P_CONF);
329 return((conf & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS); 429 return((conf & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS);
330} 430}
331 431
332int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func, 432static int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func,
333 u32 where, u32 size, u32 *val) 433 u32 where, u32 size, u32 *val)
334{ 434{
335 unsigned long flags; 435 unsigned long flags;
@@ -351,7 +451,7 @@ int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func,
351 return PCIBIOS_SUCCESSFUL; 451 return PCIBIOS_SUCCESSFUL;
352} 452}
353 453
354int orion_pci_hw_wr_conf(u32 bus, u32 dev, u32 func, 454static int orion_pci_hw_wr_conf(u32 bus, u32 dev, u32 func,
355 u32 where, u32 size, u32 val) 455 u32 where, u32 size, u32 val)
356{ 456{
357 unsigned long flags; 457 unsigned long flags;
@@ -451,11 +551,76 @@ static void orion_pci_master_slave_enable(void)
451 orion_pci_hw_wr_conf(bus_nr, dev_nr, func, reg, 4, val | 0x7); 551 orion_pci_hw_wr_conf(bus_nr, dev_nr, func, reg, 4, val | 0x7);
452} 552}
453 553
554static void orion_setup_pci_wins(struct mbus_dram_target_info *dram)
555{
556 u32 win_enable;
557 u32 bus;
558 u32 dev;
559 int i;
560
561 /*
562 * First, disable windows.
563 */
564 win_enable = 0xffffffff;
565 orion_write(PCI_BAR_ENABLE, win_enable);
566
567 /*
568 * Setup windows for DDR banks.
569 */
570 bus = orion_pci_local_bus_nr();
571 dev = orion_pci_local_dev_nr();
572
573 for (i = 0; i < dram->num_cs; i++) {
574 struct mbus_dram_window *cs = dram->cs + i;
575 u32 func = PCI_CONF_FUNC_BAR_CS(cs->cs_index);
576 u32 reg;
577 u32 val;
578
579 /*
580 * Write DRAM bank base address register.
581 */
582 reg = PCI_CONF_REG_BAR_LO_CS(cs->cs_index);
583 orion_pci_hw_rd_conf(bus, dev, func, reg, 4, &val);
584 val = (cs->base & 0xfffff000) | (val & 0xfff);
585 orion_pci_hw_wr_conf(bus, dev, func, reg, 4, val);
586
587 /*
588 * Write DRAM bank size register.
589 */
590 reg = PCI_CONF_REG_BAR_HI_CS(cs->cs_index);
591 orion_pci_hw_wr_conf(bus, dev, func, reg, 4, 0);
592 orion_write(PCI_BAR_SIZE_DDR_CS(cs->cs_index),
593 (cs->size - 1) & 0xfffff000);
594 orion_write(PCI_BAR_REMAP_DDR_CS(cs->cs_index),
595 cs->base & 0xfffff000);
596
597 /*
598 * Enable decode window for this chip select.
599 */
600 win_enable &= ~(1 << cs->cs_index);
601 }
602
603 /*
604 * Re-enable decode windows.
605 */
606 orion_write(PCI_BAR_ENABLE, win_enable);
607
608 /*
609 * Disable automatic update of address remaping when writing to BARs.
610 */
611 orion_setbits(PCI_ADDR_DECODE_CTRL, 1);
612}
613
454static int orion_pci_setup(struct pci_sys_data *sys) 614static int orion_pci_setup(struct pci_sys_data *sys)
455{ 615{
456 struct resource *res; 616 struct resource *res;
457 617
458 /* 618 /*
619 * Point PCI unit MBUS decode windows to DRAM space.
620 */
621 orion_setup_pci_wins(&orion_mbus_dram_info);
622
623 /*
459 * Master + Slave enable 624 * Master + Slave enable
460 */ 625 */
461 orion_pci_master_slave_enable(); 626 orion_pci_master_slave_enable();