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