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