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