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