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