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