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 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 */ 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 */ 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