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