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