blob: fb236d82d69d28c52c3d1b104f12f046bf76621b [file] [log] [blame]
Konstantin Porotchkine7be6e22018-10-08 16:53:09 +03001/*
2 * Copyright (C) 2018 Marvell International Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 * https://spdx.org/licenses
6 */
7
8#include <dram_win.h>
9#include <marvell_plat_priv.h>
10#include <mmio.h>
11#include <mvebu.h>
12#include <plat_marvell.h>
13#include <string.h>
14
15/* Armada 3700 has 5 configurable windows */
16#define MV_CPU_WIN_NUM 5
17
18#define CPU_WIN_DISABLED 0
19#define CPU_WIN_ENABLED 1
20
21/*
22 * There are 2 different cpu decode window configuration cases:
23 * - DRAM size is not over 2GB;
24 * - DRAM size is 4GB.
25 */
26enum cpu_win_config_num {
27 CPU_WIN_CONFIG_DRAM_NOT_OVER_2GB = 0,
28 CPU_WIN_CONFIG_DRAM_4GB,
29 CPU_WIN_CONFIG_MAX
30};
31
32enum cpu_win_target {
33 CPU_WIN_TARGET_DRAM = 0,
34 CPU_WIN_TARGET_INTERNAL_REG,
35 CPU_WIN_TARGET_PCIE,
36 CPU_WIN_TARGET_PCIE_OVER_MCI,
37 CPU_WIN_TARGET_BOOT_ROM,
38 CPU_WIN_TARGET_MCI_EXTERNAL,
39 CPU_WIN_TARGET_RWTM_RAM = 7,
40 CPU_WIN_TARGET_CCI400_REG
41};
42
43struct cpu_win_configuration {
44 uint32_t enabled;
45 enum cpu_win_target target;
46 uint64_t base_addr;
47 uint64_t size;
48 uint64_t remap_addr;
49};
50
51struct cpu_win_configuration mv_cpu_wins[CPU_WIN_CONFIG_MAX][MV_CPU_WIN_NUM] = {
52 /*
53 * When total dram size is not over 2GB:
54 * DDR window 0 is configured in tim header, its size may be not 512MB,
55 * but the actual dram size, no need to configure it again;
56 * other cpu windows are kept as default.
57 */
58 {
59 /* enabled
60 * target
61 * base
62 * size
63 * remap
64 */
65 {CPU_WIN_ENABLED,
66 CPU_WIN_TARGET_DRAM,
67 0x0,
68 0x08000000,
69 0x0},
70 {CPU_WIN_ENABLED,
71 CPU_WIN_TARGET_MCI_EXTERNAL,
72 0xe0000000,
73 0x08000000,
74 0xe0000000},
75 {CPU_WIN_ENABLED,
76 CPU_WIN_TARGET_PCIE,
77 0xe8000000,
78 0x08000000,
79 0xe8000000},
80 {CPU_WIN_ENABLED,
81 CPU_WIN_TARGET_RWTM_RAM,
82 0xf0000000,
83 0x00020000,
84 0x1fff0000},
85 {CPU_WIN_ENABLED,
86 CPU_WIN_TARGET_PCIE_OVER_MCI,
87 0x80000000,
88 0x10000000,
89 0x80000000},
90 },
91
92 /*
93 * If total dram size is more than 2GB, now there is only one case - 4GB
94 * dram; we will use below cpu windows configurations:
95 * - Internal Regs, CCI-400, Boot Rom and PCIe windows are kept as
96 * default;
97 * - Use 4 CPU decode windows for DRAM, which cover 3.375GB DRAM;
98 * DDR window 0 is configured in tim header with 2GB size, no need to
99 * configure it again here;
100 *
101 * 0xFFFFFFFF ---> |-----------------------|
102 * | Boot ROM | 64KB
103 * 0xFFF00000 ---> +-----------------------+
104 * : :
105 * 0xF0000000 ---> |-----------------------|
106 * | PCIE | 128 MB
107 * 0xE8000000 ---> |-----------------------|
108 * | DDR window 3 | 128 MB
109 * 0xE0000000 ---> +-----------------------+
110 * : :
111 * 0xD8010000 ---> |-----------------------|
112 * | CCI Regs | 64 KB
113 * 0xD8000000 ---> +-----------------------+
114 * : :
115 * : :
116 * 0xD2000000 ---> +-----------------------+
117 * | Internal Regs | 32MB
118 * 0xD0000000 ---> |-----------------------|
119 * | DDR window 2 | 256 MB
120 * 0xC0000000 ---> |-----------------------|
121 * | |
122 * | DDR window 1 | 1 GB
123 * | |
124 * 0x80000000 ---> |-----------------------|
125 * | |
126 * | |
127 * | DDR window 0 | 2 GB
128 * | |
129 * | |
130 * 0x00000000 ---> +-----------------------+
131 */
132 {
133 /* win_id
134 * target
135 * base
136 * size
137 * remap
138 */
139 {CPU_WIN_ENABLED,
140 CPU_WIN_TARGET_DRAM,
141 0x0,
142 0x80000000,
143 0x0},
144 {CPU_WIN_ENABLED,
145 CPU_WIN_TARGET_DRAM,
146 0x80000000,
147 0x40000000,
148 0x80000000},
149 {CPU_WIN_ENABLED,
150 CPU_WIN_TARGET_DRAM,
151 0xc0000000,
152 0x10000000,
153 0xc0000000},
154 {CPU_WIN_ENABLED,
155 CPU_WIN_TARGET_DRAM,
156 0xe0000000,
157 0x08000000,
158 0xe0000000},
159 {CPU_WIN_ENABLED,
160 CPU_WIN_TARGET_PCIE,
161 0xe8000000,
162 0x08000000,
163 0xe8000000},
164 },
165};
166
167/*
168 * dram_win_map_build
169 *
170 * This function builds cpu dram windows mapping
171 * which includes base address and window size by
172 * reading cpu dram decode windows registers.
173 *
174 * @input: N/A
175 *
176 * @output:
177 * - win_map: cpu dram windows mapping
178 *
179 * @return: N/A
180 */
181void dram_win_map_build(struct dram_win_map *win_map)
182{
183 int32_t win_id;
184 struct dram_win *win;
185 uint32_t base_reg, ctrl_reg, size_reg, enabled, target;
186
187 memset(win_map, 0, sizeof(struct dram_win_map));
188 for (win_id = 0; win_id < DRAM_WIN_MAP_NUM_MAX; win_id++) {
189 ctrl_reg = mmio_read_32(CPU_DEC_WIN_CTRL_REG(win_id));
190 target = (ctrl_reg & CPU_DEC_CR_WIN_TARGET_MASK) >>
191 CPU_DEC_CR_WIN_TARGET_OFFS;
192 enabled = ctrl_reg & CPU_DEC_CR_WIN_ENABLE;
193 /* Ignore invalid and non-dram windows*/
194 if ((enabled == 0) || (target != DRAM_CPU_DEC_TARGET_NUM))
195 continue;
196
197 win = win_map->dram_windows + win_map->dram_win_num;
198 base_reg = mmio_read_32(CPU_DEC_WIN_BASE_REG(win_id));
199 size_reg = mmio_read_32(CPU_DEC_WIN_SIZE_REG(win_id));
200 /* Base reg [15:0] corresponds to transaction address [39:16] */
201 win->base_addr = (base_reg & CPU_DEC_BR_BASE_MASK) >>
202 CPU_DEC_BR_BASE_OFFS;
203 win->base_addr *= CPU_DEC_CR_WIN_SIZE_ALIGNMENT;
204 /*
205 * Size reg [15:0] is programmed from LSB to MSB as a sequence
206 * of 1s followed by a sequence of 0s and the number of 1s
207 * specifies the size of the window in 64 KB granularity,
208 * for example, a value of 00FFh specifies 256 x 64 KB = 16 MB
209 */
210 win->win_size = (size_reg & CPU_DEC_CR_WIN_SIZE_MASK) >>
211 CPU_DEC_CR_WIN_SIZE_OFFS;
212 win->win_size = (win->win_size + 1) *
213 CPU_DEC_CR_WIN_SIZE_ALIGNMENT;
214
215 win_map->dram_win_num++;
216 }
217}
218
219static void cpu_win_set(uint32_t win_id, struct cpu_win_configuration *win_cfg)
220{
221 uint32_t base_reg, ctrl_reg, size_reg, remap_reg;
222
223 /* Disable window */
224 ctrl_reg = mmio_read_32(CPU_DEC_WIN_CTRL_REG(win_id));
225 ctrl_reg &= ~CPU_DEC_CR_WIN_ENABLE;
226 mmio_write_32(CPU_DEC_WIN_CTRL_REG(win_id), ctrl_reg);
227
228 /* For an disabled window, only disable it. */
229 if (!win_cfg->enabled)
230 return;
231
232 /* Set Base Register */
233 base_reg = (uint32_t)(win_cfg->base_addr /
234 CPU_DEC_CR_WIN_SIZE_ALIGNMENT);
235 base_reg <<= CPU_DEC_BR_BASE_OFFS;
236 base_reg &= CPU_DEC_BR_BASE_MASK;
237 mmio_write_32(CPU_DEC_WIN_BASE_REG(win_id), base_reg);
238
239 /* Set Remap Register with the same value
240 * as the <Base> field in Base Register
241 */
242 remap_reg = (uint32_t)(win_cfg->remap_addr /
243 CPU_DEC_CR_WIN_SIZE_ALIGNMENT);
244 remap_reg <<= CPU_DEC_RLR_REMAP_LOW_OFFS;
245 remap_reg &= CPU_DEC_RLR_REMAP_LOW_MASK;
246 mmio_write_32(CPU_DEC_REMAP_LOW_REG(win_id), remap_reg);
247
248 /* Set Size Register */
249 size_reg = (win_cfg->size / CPU_DEC_CR_WIN_SIZE_ALIGNMENT) - 1;
250 size_reg <<= CPU_DEC_CR_WIN_SIZE_OFFS;
251 size_reg &= CPU_DEC_CR_WIN_SIZE_MASK;
252 mmio_write_32(CPU_DEC_WIN_SIZE_REG(win_id), size_reg);
253
254 /* Set Control Register - set target id and enable window */
255 ctrl_reg &= ~CPU_DEC_CR_WIN_TARGET_MASK;
256 ctrl_reg |= (win_cfg->target << CPU_DEC_CR_WIN_TARGET_OFFS);
257 ctrl_reg |= CPU_DEC_CR_WIN_ENABLE;
258 mmio_write_32(CPU_DEC_WIN_CTRL_REG(win_id), ctrl_reg);
259}
260
261void cpu_wins_init(void)
262{
263 uint32_t cfg_idx, win_id;
264
265 if (mvebu_get_dram_size(MVEBU_REGS_BASE) <= _2GB_)
266 cfg_idx = CPU_WIN_CONFIG_DRAM_NOT_OVER_2GB;
267 else
268 cfg_idx = CPU_WIN_CONFIG_DRAM_4GB;
269
270 /* Window 0 is configured always for DRAM in tim header
271 * already, no need to configure it again here
272 */
273 for (win_id = 1; win_id < MV_CPU_WIN_NUM; win_id++)
274 cpu_win_set(win_id, &mv_cpu_wins[cfg_idx][win_id]);
275}
276