xref: /arm-trusted-firmware/plat/marvell/armada/a3k/common/io_addr_dec.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (C) 2016 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 <common/debug.h>
9*91f16700Schasinglulu #include <lib/mmio.h>
10*91f16700Schasinglulu 
11*91f16700Schasinglulu #include <io_addr_dec.h>
12*91f16700Schasinglulu #include <plat_marvell.h>
13*91f16700Schasinglulu 
14*91f16700Schasinglulu #define MVEBU_DEC_WIN_CTRL_REG(base, win, off)	(MVEBU_REGS_BASE + (base) + \
15*91f16700Schasinglulu 						(win) * (off))
16*91f16700Schasinglulu #define MVEBU_DEC_WIN_BASE_REG(base, win, off)	(MVEBU_REGS_BASE + (base) + \
17*91f16700Schasinglulu 						(win) * (off) + 0x4)
18*91f16700Schasinglulu #define MVEBU_DEC_WIN_REMAP_REG(base, win, off)	(MVEBU_REGS_BASE + (base) + \
19*91f16700Schasinglulu 						(win) * (off) + 0x8)
20*91f16700Schasinglulu 
21*91f16700Schasinglulu #define MVEBU_DEC_WIN_CTRL_SIZE_OFF		(16)
22*91f16700Schasinglulu #define MVEBU_DEC_WIN_ENABLE			(0x1)
23*91f16700Schasinglulu #define MVEBU_DEC_WIN_CTRL_ATTR_OFF		(8)
24*91f16700Schasinglulu #define MVEBU_DEC_WIN_CTRL_TARGET_OFF		(4)
25*91f16700Schasinglulu #define MVEBU_DEC_WIN_CTRL_EN_OFF		(0)
26*91f16700Schasinglulu #define MVEBU_DEC_WIN_BASE_OFF			(16)
27*91f16700Schasinglulu 
28*91f16700Schasinglulu #define MVEBU_WIN_BASE_SIZE_ALIGNMENT		(0x10000)
29*91f16700Schasinglulu 
30*91f16700Schasinglulu /* There are up to 14 IO unit which need address decode in Armada-3700 */
31*91f16700Schasinglulu #define IO_UNIT_NUM_MAX				(14)
32*91f16700Schasinglulu 
33*91f16700Schasinglulu #define MVEBU_MAX_ADDRSS_4GB			(0x100000000ULL)
34*91f16700Schasinglulu 
35*91f16700Schasinglulu 
36*91f16700Schasinglulu static void set_io_addr_dec_win(int win_id, uintptr_t base_addr,
37*91f16700Schasinglulu 				uintptr_t win_size,
38*91f16700Schasinglulu 				struct dec_win_config *dec_win)
39*91f16700Schasinglulu {
40*91f16700Schasinglulu 	uint32_t ctrl = 0;
41*91f16700Schasinglulu 	uint32_t base = 0;
42*91f16700Schasinglulu 
43*91f16700Schasinglulu 	/* set size */
44*91f16700Schasinglulu 	ctrl = ((win_size / MVEBU_WIN_BASE_SIZE_ALIGNMENT) - 1) <<
45*91f16700Schasinglulu 	       MVEBU_DEC_WIN_CTRL_SIZE_OFF;
46*91f16700Schasinglulu 	/* set attr according to IO decode window */
47*91f16700Schasinglulu 	ctrl |= dec_win->win_attr << MVEBU_DEC_WIN_CTRL_ATTR_OFF;
48*91f16700Schasinglulu 	/* set target */
49*91f16700Schasinglulu 	ctrl |= DRAM_CPU_DEC_TARGET_NUM << MVEBU_DEC_WIN_CTRL_TARGET_OFF;
50*91f16700Schasinglulu 	/* set base */
51*91f16700Schasinglulu 	base = (base_addr / MVEBU_WIN_BASE_SIZE_ALIGNMENT) <<
52*91f16700Schasinglulu 	       MVEBU_DEC_WIN_BASE_OFF;
53*91f16700Schasinglulu 
54*91f16700Schasinglulu 	/* set base address*/
55*91f16700Schasinglulu 	mmio_write_32(MVEBU_DEC_WIN_BASE_REG(dec_win->dec_reg_base,
56*91f16700Schasinglulu 		      win_id, dec_win->win_offset),
57*91f16700Schasinglulu 		      base);
58*91f16700Schasinglulu 	/* set remap window, some unit does not have remap window */
59*91f16700Schasinglulu 	if (win_id < dec_win->max_remap)
60*91f16700Schasinglulu 		mmio_write_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base,
61*91f16700Schasinglulu 			      win_id, dec_win->win_offset), base);
62*91f16700Schasinglulu 	/* set control register */
63*91f16700Schasinglulu 	mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
64*91f16700Schasinglulu 		      win_id, dec_win->win_offset), ctrl);
65*91f16700Schasinglulu 	/* enable the address decode window at last to make it effective */
66*91f16700Schasinglulu 	ctrl |= MVEBU_DEC_WIN_ENABLE << MVEBU_DEC_WIN_CTRL_EN_OFF;
67*91f16700Schasinglulu 	mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
68*91f16700Schasinglulu 		      win_id, dec_win->win_offset), ctrl);
69*91f16700Schasinglulu 
70*91f16700Schasinglulu 	INFO("set_io_addr_dec %d result: ctrl(0x%x) base(0x%x) remap(0x%x)\n",
71*91f16700Schasinglulu 	     win_id, mmio_read_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base,
72*91f16700Schasinglulu 	     win_id, dec_win->win_offset)),
73*91f16700Schasinglulu 	     mmio_read_32(MVEBU_DEC_WIN_BASE_REG(dec_win->dec_reg_base,
74*91f16700Schasinglulu 			  win_id, dec_win->win_offset)),
75*91f16700Schasinglulu 	     (win_id < dec_win->max_remap) ?
76*91f16700Schasinglulu 		mmio_read_32(MVEBU_DEC_WIN_REMAP_REG(dec_win->dec_reg_base,
77*91f16700Schasinglulu 			     win_id, dec_win->win_offset)) : 0);
78*91f16700Schasinglulu }
79*91f16700Schasinglulu 
80*91f16700Schasinglulu /* Set io decode window */
81*91f16700Schasinglulu static int set_io_addr_dec(struct dram_win_map *win_map,
82*91f16700Schasinglulu 			   struct dec_win_config *dec_win)
83*91f16700Schasinglulu {
84*91f16700Schasinglulu 	struct dram_win *win;
85*91f16700Schasinglulu 	int id;
86*91f16700Schasinglulu 
87*91f16700Schasinglulu 	/* disable all windows first */
88*91f16700Schasinglulu 	for (id = 0; id < dec_win->max_dram_win; id++)
89*91f16700Schasinglulu 		mmio_write_32(MVEBU_DEC_WIN_CTRL_REG(dec_win->dec_reg_base, id,
90*91f16700Schasinglulu 			      dec_win->win_offset), 0);
91*91f16700Schasinglulu 
92*91f16700Schasinglulu 	/* configure IO decode windows for DRAM, inheritate DRAM size,
93*91f16700Schasinglulu 	 * base and target from CPU-DRAM decode window and others
94*91f16700Schasinglulu 	 * from hard coded IO decode window settings array.
95*91f16700Schasinglulu 	 */
96*91f16700Schasinglulu 	if (win_map->dram_win_num > dec_win->max_dram_win) {
97*91f16700Schasinglulu 		/*
98*91f16700Schasinglulu 		 * If cpu dram windows number exceeds the io decode windows
99*91f16700Schasinglulu 		 * max number, then fill the first io decode window
100*91f16700Schasinglulu 		 * with base(0) and size(4GB).
101*91f16700Schasinglulu 		 */
102*91f16700Schasinglulu 		set_io_addr_dec_win(0, 0, MVEBU_MAX_ADDRSS_4GB, dec_win);
103*91f16700Schasinglulu 
104*91f16700Schasinglulu 		return 0;
105*91f16700Schasinglulu 	}
106*91f16700Schasinglulu 
107*91f16700Schasinglulu 	for (id = 0; id < win_map->dram_win_num; id++, win++) {
108*91f16700Schasinglulu 		win = &win_map->dram_windows[id];
109*91f16700Schasinglulu 		set_io_addr_dec_win(id, win->base_addr, win->win_size, dec_win);
110*91f16700Schasinglulu 	}
111*91f16700Schasinglulu 
112*91f16700Schasinglulu 	return 0;
113*91f16700Schasinglulu }
114*91f16700Schasinglulu 
115*91f16700Schasinglulu /*
116*91f16700Schasinglulu  * init_io_addr_dec
117*91f16700Schasinglulu  *
118*91f16700Schasinglulu  * This function initializes io address decoder windows by
119*91f16700Schasinglulu  * cpu dram window mapping information
120*91f16700Schasinglulu  *
121*91f16700Schasinglulu  * @input: N/A
122*91f16700Schasinglulu  *     - dram_wins_map: cpu dram windows mapping
123*91f16700Schasinglulu  *     - io_dec_config: io address decoder windows configuration
124*91f16700Schasinglulu  *     - io_unit_num: io address decoder unit number
125*91f16700Schasinglulu  * @output: N/A
126*91f16700Schasinglulu  *
127*91f16700Schasinglulu  * @return:  0 on success and others on failure
128*91f16700Schasinglulu  */
129*91f16700Schasinglulu int init_io_addr_dec(struct dram_win_map *dram_wins_map,
130*91f16700Schasinglulu 		     struct dec_win_config *io_dec_config, uint32_t io_unit_num)
131*91f16700Schasinglulu {
132*91f16700Schasinglulu 	int32_t index;
133*91f16700Schasinglulu 	struct dec_win_config *io_dec_win;
134*91f16700Schasinglulu 	int32_t ret;
135*91f16700Schasinglulu 
136*91f16700Schasinglulu 	INFO("Initializing IO address decode windows\n");
137*91f16700Schasinglulu 
138*91f16700Schasinglulu 	if (io_dec_config == NULL || io_unit_num == 0) {
139*91f16700Schasinglulu 		ERROR("No IO address decoder windows configurations!\n");
140*91f16700Schasinglulu 		return -1;
141*91f16700Schasinglulu 	}
142*91f16700Schasinglulu 
143*91f16700Schasinglulu 	if (io_unit_num > IO_UNIT_NUM_MAX) {
144*91f16700Schasinglulu 		ERROR("IO address decoder windows number %d is over max %d\n",
145*91f16700Schasinglulu 		      io_unit_num, IO_UNIT_NUM_MAX);
146*91f16700Schasinglulu 		return -1;
147*91f16700Schasinglulu 	}
148*91f16700Schasinglulu 
149*91f16700Schasinglulu 	if (dram_wins_map == NULL) {
150*91f16700Schasinglulu 		ERROR("No cpu dram decoder windows map!\n");
151*91f16700Schasinglulu 		return -1;
152*91f16700Schasinglulu 	}
153*91f16700Schasinglulu 
154*91f16700Schasinglulu 	for (index = 0; index < dram_wins_map->dram_win_num; index++)
155*91f16700Schasinglulu 		INFO("DRAM mapping %d base(0x%lx) size(0x%lx)\n",
156*91f16700Schasinglulu 		     index, dram_wins_map->dram_windows[index].base_addr,
157*91f16700Schasinglulu 		     dram_wins_map->dram_windows[index].win_size);
158*91f16700Schasinglulu 
159*91f16700Schasinglulu 	/* Set address decode window for each IO */
160*91f16700Schasinglulu 	for (index = 0; index < io_unit_num; index++) {
161*91f16700Schasinglulu 		io_dec_win = io_dec_config + index;
162*91f16700Schasinglulu 		ret = set_io_addr_dec(dram_wins_map, io_dec_win);
163*91f16700Schasinglulu 		if (ret) {
164*91f16700Schasinglulu 			ERROR("Failed to set IO address decode\n");
165*91f16700Schasinglulu 			return -1;
166*91f16700Schasinglulu 		}
167*91f16700Schasinglulu 		INFO("Set IO decode window successfully, base(0x%x)"
168*91f16700Schasinglulu 		     " win_attr(%x) max_dram_win(%d) max_remap(%d)"
169*91f16700Schasinglulu 		     " win_offset(%d)\n", io_dec_win->dec_reg_base,
170*91f16700Schasinglulu 		     io_dec_win->win_attr, io_dec_win->max_dram_win,
171*91f16700Schasinglulu 		     io_dec_win->max_remap, io_dec_win->win_offset);
172*91f16700Schasinglulu 	}
173*91f16700Schasinglulu 
174*91f16700Schasinglulu 	return 0;
175*91f16700Schasinglulu }
176