]>
Commit | Line | Data |
---|---|---|
c67de5b3 TP |
1 | /* |
2 | * arch/arm/mach-orion/addr-map.c | |
3 | * | |
4 | * Address map functions for Marvell Orion System On Chip | |
5 | * | |
6 | * Maintainer: Tzachi Perelstein <tzachi@marvell.com> | |
7 | * | |
159ffb3a LB |
8 | * This file is licensed under the terms of the GNU General Public |
9 | * License version 2. This program is licensed "as is" without any | |
c67de5b3 TP |
10 | * warranty of any kind, whether express or implied. |
11 | */ | |
12 | ||
13 | #include <linux/kernel.h> | |
14 | #include <linux/init.h> | |
83b6d822 | 15 | #include <linux/mbus.h> |
c67de5b3 | 16 | #include <asm/hardware.h> |
b590bc5c | 17 | #include <asm/io.h> |
c67de5b3 TP |
18 | #include "common.h" |
19 | ||
20 | /* | |
21 | * The Orion has fully programable address map. There's a separate address | |
22 | * map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIE, USB, | |
23 | * Gigabit Ethernet, DMA/XOR engines, etc. Each interface has its own | |
24 | * address decode windows that allow it to access any of the Orion resources. | |
25 | * | |
26 | * CPU address decoding -- | |
27 | * Linux assumes that it is the boot loader that already setup the access to | |
28 | * DDR and internal registers. | |
98f79d1e | 29 | * Setup access to PCI and PCI-E IO/MEM space is issued by this file. |
c67de5b3 TP |
30 | * Setup access to various devices located on the device bus interface (e.g. |
31 | * flashes, RTC, etc) should be issued by machine-setup.c according to | |
98f79d1e | 32 | * specific board population (by using orion_setup_*_win()). |
c67de5b3 TP |
33 | * |
34 | * Non-CPU Masters address decoding -- | |
35 | * Unlike the CPU, we setup the access from Orion's master interfaces to DDR | |
36 | * banks only (the typical use case). | |
37 | * Setup access for each master to DDR is issued by common.c. | |
38 | * | |
39 | * Note: although orion_setbits() and orion_clrbits() are not atomic | |
40 | * no locking is necessary here since code in this file is only called | |
41 | * at boot time when there is no concurrency issues. | |
42 | */ | |
43 | ||
44 | /* | |
45 | * Generic Address Decode Windows bit settings | |
46 | */ | |
47 | #define TARGET_DDR 0 | |
159ffb3a | 48 | #define TARGET_DEV_BUS 1 |
c67de5b3 TP |
49 | #define TARGET_PCI 3 |
50 | #define TARGET_PCIE 4 | |
c67de5b3 TP |
51 | #define ATTR_DDR_CS(n) (((n) ==0) ? 0xe : \ |
52 | ((n) == 1) ? 0xd : \ | |
53 | ((n) == 2) ? 0xb : \ | |
54 | ((n) == 3) ? 0x7 : 0xf) | |
55 | #define ATTR_PCIE_MEM 0x59 | |
56 | #define ATTR_PCIE_IO 0x51 | |
98f79d1e | 57 | #define ATTR_PCIE_WA 0x79 |
c67de5b3 TP |
58 | #define ATTR_PCI_MEM 0x59 |
59 | #define ATTR_PCI_IO 0x51 | |
60 | #define ATTR_DEV_CS0 0x1e | |
61 | #define ATTR_DEV_CS1 0x1d | |
62 | #define ATTR_DEV_CS2 0x1b | |
63 | #define ATTR_DEV_BOOT 0xf | |
64 | #define WIN_EN 1 | |
65 | ||
66 | /* | |
159ffb3a | 67 | * Helpers to get DDR bank info |
c67de5b3 TP |
68 | */ |
69 | #define DDR_BASE_CS(n) ORION_DDR_REG(0x1500 + ((n) * 8)) | |
70 | #define DDR_SIZE_CS(n) ORION_DDR_REG(0x1504 + ((n) * 8)) | |
71 | #define DDR_MAX_CS 4 | |
72 | #define DDR_REG_TO_SIZE(reg) (((reg) | 0xffffff) + 1) | |
73 | #define DDR_REG_TO_BASE(reg) ((reg) & 0xff000000) | |
74 | #define DDR_BANK_EN 1 | |
75 | ||
76 | /* | |
77 | * CPU Address Decode Windows registers | |
78 | */ | |
79 | #define CPU_WIN_CTRL(n) ORION_BRIDGE_REG(0x000 | ((n) << 4)) | |
80 | #define CPU_WIN_BASE(n) ORION_BRIDGE_REG(0x004 | ((n) << 4)) | |
81 | #define CPU_WIN_REMAP_LO(n) ORION_BRIDGE_REG(0x008 | ((n) << 4)) | |
82 | #define CPU_WIN_REMAP_HI(n) ORION_BRIDGE_REG(0x00c | ((n) << 4)) | |
c67de5b3 | 83 | |
c67de5b3 TP |
84 | /* |
85 | * Gigabit Ethernet Address Decode Windows registers | |
86 | */ | |
87 | #define ETH_WIN_BASE(win) ORION_ETH_REG(0x200 + ((win) * 8)) | |
88 | #define ETH_WIN_SIZE(win) ORION_ETH_REG(0x204 + ((win) * 8)) | |
89 | #define ETH_WIN_REMAP(win) ORION_ETH_REG(0x280 + ((win) * 4)) | |
90 | #define ETH_WIN_EN ORION_ETH_REG(0x290) | |
91 | #define ETH_WIN_PROT ORION_ETH_REG(0x294) | |
92 | #define ETH_MAX_WIN 6 | |
93 | #define ETH_MAX_REMAP_WIN 4 | |
94 | ||
83b6d822 LB |
95 | |
96 | struct mbus_dram_target_info orion_mbus_dram_info; | |
97 | ||
98f79d1e | 98 | static int __init orion_cpu_win_can_remap(int win) |
c67de5b3 TP |
99 | { |
100 | u32 dev, rev; | |
101 | ||
102 | orion_pcie_id(&dev, &rev); | |
c9e3de94 HVR |
103 | if ((dev == MV88F5281_DEV_ID && win < 4) |
104 | || (dev == MV88F5182_DEV_ID && win < 2) | |
105 | || (dev == MV88F5181_DEV_ID && win < 2)) | |
c67de5b3 TP |
106 | return 1; |
107 | ||
108 | return 0; | |
109 | } | |
110 | ||
98f79d1e LB |
111 | static void __init setup_cpu_win(int win, u32 base, u32 size, |
112 | u8 target, u8 attr, int remap) | |
c67de5b3 | 113 | { |
98f79d1e LB |
114 | orion_write(CPU_WIN_BASE(win), base & 0xffff0000); |
115 | orion_write(CPU_WIN_CTRL(win), | |
116 | ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | 1); | |
c67de5b3 TP |
117 | |
118 | if (orion_cpu_win_can_remap(win)) { | |
98f79d1e LB |
119 | if (remap < 0) |
120 | remap = base; | |
121 | ||
122 | orion_write(CPU_WIN_REMAP_LO(win), remap & 0xffff0000); | |
123 | orion_write(CPU_WIN_REMAP_HI(win), 0); | |
c67de5b3 TP |
124 | } |
125 | } | |
126 | ||
98f79d1e | 127 | void __init orion_setup_cpu_mbus_bridge(void) |
c67de5b3 TP |
128 | { |
129 | int i; | |
83b6d822 | 130 | int cs; |
c67de5b3 TP |
131 | |
132 | /* | |
98f79d1e | 133 | * First, disable and clear windows. |
c67de5b3 | 134 | */ |
98f79d1e | 135 | for (i = 0; i < 8; i++) { |
c67de5b3 TP |
136 | orion_write(CPU_WIN_BASE(i), 0); |
137 | orion_write(CPU_WIN_CTRL(i), 0); | |
138 | if (orion_cpu_win_can_remap(i)) { | |
139 | orion_write(CPU_WIN_REMAP_LO(i), 0); | |
140 | orion_write(CPU_WIN_REMAP_HI(i), 0); | |
141 | } | |
142 | } | |
143 | ||
144 | /* | |
7f74c2c7 | 145 | * Setup windows for PCI+PCIe IO+MEM space. |
c67de5b3 | 146 | */ |
98f79d1e LB |
147 | setup_cpu_win(0, ORION_PCIE_IO_PHYS_BASE, ORION_PCIE_IO_SIZE, |
148 | TARGET_PCIE, ATTR_PCIE_IO, ORION_PCIE_IO_BUS_BASE); | |
149 | setup_cpu_win(1, ORION_PCI_IO_PHYS_BASE, ORION_PCI_IO_SIZE, | |
150 | TARGET_PCI, ATTR_PCI_IO, ORION_PCI_IO_BUS_BASE); | |
151 | setup_cpu_win(2, ORION_PCIE_MEM_PHYS_BASE, ORION_PCIE_MEM_SIZE, | |
152 | TARGET_PCIE, ATTR_PCIE_MEM, -1); | |
153 | setup_cpu_win(3, ORION_PCI_MEM_PHYS_BASE, ORION_PCI_MEM_SIZE, | |
154 | TARGET_PCI, ATTR_PCI_MEM, -1); | |
83b6d822 LB |
155 | |
156 | /* | |
157 | * Setup MBUS dram target info. | |
158 | */ | |
159 | orion_mbus_dram_info.mbus_dram_target_id = TARGET_DDR; | |
160 | ||
161 | for (i = 0, cs = 0; i < 4; i++) { | |
162 | u32 base = readl(DDR_BASE_CS(i)); | |
163 | u32 size = readl(DDR_SIZE_CS(i)); | |
164 | ||
165 | /* | |
166 | * Chip select enabled? | |
167 | */ | |
168 | if (size & 1) { | |
169 | struct mbus_dram_window *w; | |
170 | ||
171 | w = &orion_mbus_dram_info.cs[cs++]; | |
172 | w->cs_index = i; | |
173 | w->mbus_attr = 0xf & ~(1 << i); | |
174 | w->base = base & 0xff000000; | |
175 | w->size = (size | 0x00ffffff) + 1; | |
176 | } | |
177 | } | |
178 | orion_mbus_dram_info.num_cs = cs; | |
c67de5b3 TP |
179 | } |
180 | ||
98f79d1e LB |
181 | void __init orion_setup_dev_boot_win(u32 base, u32 size) |
182 | { | |
183 | setup_cpu_win(4, base, size, TARGET_DEV_BUS, ATTR_DEV_BOOT, -1); | |
184 | } | |
185 | ||
186 | void __init orion_setup_dev0_win(u32 base, u32 size) | |
187 | { | |
188 | setup_cpu_win(5, base, size, TARGET_DEV_BUS, ATTR_DEV_CS0, -1); | |
189 | } | |
190 | ||
191 | void __init orion_setup_dev1_win(u32 base, u32 size) | |
192 | { | |
193 | setup_cpu_win(6, base, size, TARGET_DEV_BUS, ATTR_DEV_CS1, -1); | |
194 | } | |
195 | ||
196 | void __init orion_setup_dev2_win(u32 base, u32 size) | |
197 | { | |
198 | setup_cpu_win(7, base, size, TARGET_DEV_BUS, ATTR_DEV_CS2, -1); | |
199 | } | |
200 | ||
201 | void __init orion_setup_pcie_wa_win(u32 base, u32 size) | |
202 | { | |
203 | setup_cpu_win(7, base, size, TARGET_PCIE, ATTR_PCIE_WA, -1); | |
204 | } | |
205 | ||
c67de5b3 TP |
206 | void __init orion_setup_eth_wins(void) |
207 | { | |
208 | int i; | |
209 | ||
210 | /* | |
211 | * First, disable and clear windows | |
212 | */ | |
213 | for (i = 0; i < ETH_MAX_WIN; i++) { | |
214 | orion_write(ETH_WIN_BASE(i), 0); | |
215 | orion_write(ETH_WIN_SIZE(i), 0); | |
216 | orion_setbits(ETH_WIN_EN, 1 << i); | |
217 | orion_clrbits(ETH_WIN_PROT, 0x3 << (i * 2)); | |
218 | if (i < ETH_MAX_REMAP_WIN) | |
219 | orion_write(ETH_WIN_REMAP(i), 0); | |
220 | } | |
221 | ||
222 | /* | |
223 | * Setup windows for DDR banks. | |
224 | */ | |
225 | for (i = 0; i < DDR_MAX_CS; i++) { | |
226 | u32 base, size; | |
227 | size = orion_read(DDR_SIZE_CS(i)); | |
228 | base = orion_read(DDR_BASE_CS(i)); | |
229 | if (size & DDR_BANK_EN) { | |
230 | base = DDR_REG_TO_BASE(base); | |
231 | size = DDR_REG_TO_SIZE(size); | |
232 | orion_write(ETH_WIN_SIZE(i), (size-1) & 0xffff0000); | |
233 | orion_write(ETH_WIN_BASE(i), (base & 0xffff0000) | | |
234 | (ATTR_DDR_CS(i) << 8) | | |
235 | TARGET_DDR); | |
236 | orion_clrbits(ETH_WIN_EN, 1 << i); | |
237 | orion_setbits(ETH_WIN_PROT, 0x3 << (i * 2)); | |
238 | } | |
239 | } | |
240 | } |