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