1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (C) 2018 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 /* CCU unit device driver for Marvell AP807, AP807 and AP810 SoCs */ 9*91f16700Schasinglulu 10*91f16700Schasinglulu #include <inttypes.h> 11*91f16700Schasinglulu #include <stdint.h> 12*91f16700Schasinglulu 13*91f16700Schasinglulu #include <common/debug.h> 14*91f16700Schasinglulu #include <drivers/marvell/ccu.h> 15*91f16700Schasinglulu #include <lib/mmio.h> 16*91f16700Schasinglulu 17*91f16700Schasinglulu #include <armada_common.h> 18*91f16700Schasinglulu #include <mvebu.h> 19*91f16700Schasinglulu #include <mvebu_def.h> 20*91f16700Schasinglulu 21*91f16700Schasinglulu #if LOG_LEVEL >= LOG_LEVEL_INFO 22*91f16700Schasinglulu #define DEBUG_ADDR_MAP 23*91f16700Schasinglulu #endif 24*91f16700Schasinglulu 25*91f16700Schasinglulu /* common defines */ 26*91f16700Schasinglulu #define WIN_ENABLE_BIT (0x1) 27*91f16700Schasinglulu /* Physical address of the base of the window = {AddrLow[19:0],20'h0} */ 28*91f16700Schasinglulu #define ADDRESS_SHIFT (20 - 4) 29*91f16700Schasinglulu #define ADDRESS_MASK (0xFFFFFFF0) 30*91f16700Schasinglulu #define CCU_WIN_ALIGNMENT (0x100000) 31*91f16700Schasinglulu 32*91f16700Schasinglulu /* 33*91f16700Schasinglulu * Physical address of the highest address of window bits[31:19] = 0x6FF 34*91f16700Schasinglulu * Physical address of the lowest address of window bits[18:6] = 0x6E0 35*91f16700Schasinglulu * Unit Id bits [5:2] = 2 36*91f16700Schasinglulu * RGF Window Enable bit[0] = 1 37*91f16700Schasinglulu * 0x37f9b809 - 11011111111 0011011100000 0010 0 1 38*91f16700Schasinglulu */ 39*91f16700Schasinglulu #define ERRATA_WA_CCU_WIN4 0x37f9b809U 40*91f16700Schasinglulu 41*91f16700Schasinglulu /* 42*91f16700Schasinglulu * Physical address of the highest address of window bits[31:19] = 0xFFF 43*91f16700Schasinglulu * Physical address of the lowest address of window bits[18:6] = 0x800 44*91f16700Schasinglulu * Unit Id bits [5:2] = 2 45*91f16700Schasinglulu * RGF Window Enable bit[0] = 1 46*91f16700Schasinglulu * 0x7ffa0009 - 111111111111 0100000000000 0010 0 1 47*91f16700Schasinglulu */ 48*91f16700Schasinglulu #define ERRATA_WA_CCU_WIN5 0x7ffa0009U 49*91f16700Schasinglulu 50*91f16700Schasinglulu /* 51*91f16700Schasinglulu * Physical address of the highest address of window bits[31:19] = 0x1FFF 52*91f16700Schasinglulu * Physical address of the lowest address of window bits[18:6] = 0x1000 53*91f16700Schasinglulu * Unit Id bits [5:2] = 2 54*91f16700Schasinglulu * RGF Window Enable bit[0] = 1 55*91f16700Schasinglulu * 0xfffc000d - 1111111111111 1000000000000 0011 0 1 56*91f16700Schasinglulu */ 57*91f16700Schasinglulu #define ERRATA_WA_CCU_WIN6 0xfffc000dU 58*91f16700Schasinglulu 59*91f16700Schasinglulu #define IS_DRAM_TARGET(tgt) ((((tgt) == DRAM_0_TID) || \ 60*91f16700Schasinglulu ((tgt) == DRAM_1_TID) || \ 61*91f16700Schasinglulu ((tgt) == RAR_TID)) ? 1 : 0) 62*91f16700Schasinglulu 63*91f16700Schasinglulu #define CCU_RGF(win) (MVEBU_CCU_BASE(MVEBU_AP0) + \ 64*91f16700Schasinglulu 0x90 + 4 * (win)) 65*91f16700Schasinglulu 66*91f16700Schasinglulu /* For storage of CR, SCR, ALR, AHR abd GCR */ 67*91f16700Schasinglulu static uint32_t ccu_regs_save[MVEBU_CCU_MAX_WINS * 4 + 1]; 68*91f16700Schasinglulu 69*91f16700Schasinglulu #ifdef DEBUG_ADDR_MAP 70*91f16700Schasinglulu static void dump_ccu(int ap_index) 71*91f16700Schasinglulu { 72*91f16700Schasinglulu uint32_t win_id, win_cr, alr, ahr; 73*91f16700Schasinglulu uint8_t target_id; 74*91f16700Schasinglulu uint64_t start, end; 75*91f16700Schasinglulu 76*91f16700Schasinglulu /* Dump all AP windows */ 77*91f16700Schasinglulu printf("\tbank target start end\n"); 78*91f16700Schasinglulu printf("\t----------------------------------------------------\n"); 79*91f16700Schasinglulu for (win_id = 0; win_id < MVEBU_CCU_MAX_WINS; win_id++) { 80*91f16700Schasinglulu win_cr = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)); 81*91f16700Schasinglulu if (win_cr & WIN_ENABLE_BIT) { 82*91f16700Schasinglulu target_id = (win_cr >> CCU_TARGET_ID_OFFSET) & 83*91f16700Schasinglulu CCU_TARGET_ID_MASK; 84*91f16700Schasinglulu alr = mmio_read_32(CCU_WIN_ALR_OFFSET(ap_index, 85*91f16700Schasinglulu win_id)); 86*91f16700Schasinglulu ahr = mmio_read_32(CCU_WIN_AHR_OFFSET(ap_index, 87*91f16700Schasinglulu win_id)); 88*91f16700Schasinglulu start = ((uint64_t)alr << ADDRESS_SHIFT); 89*91f16700Schasinglulu end = (((uint64_t)ahr + 0x10) << ADDRESS_SHIFT); 90*91f16700Schasinglulu printf("\tccu%d %02x 0x%016" PRIx64 " 0x%016" PRIx64 "\n", 91*91f16700Schasinglulu win_id, target_id, start, end); 92*91f16700Schasinglulu } 93*91f16700Schasinglulu } 94*91f16700Schasinglulu win_cr = mmio_read_32(CCU_WIN_GCR_OFFSET(ap_index)); 95*91f16700Schasinglulu target_id = (win_cr >> CCU_GCR_TARGET_OFFSET) & CCU_GCR_TARGET_MASK; 96*91f16700Schasinglulu printf("\tccu GCR %d - all other transactions\n", target_id); 97*91f16700Schasinglulu } 98*91f16700Schasinglulu #endif 99*91f16700Schasinglulu 100*91f16700Schasinglulu void ccu_win_check(struct addr_map_win *win) 101*91f16700Schasinglulu { 102*91f16700Schasinglulu /* check if address is aligned to 1M */ 103*91f16700Schasinglulu if (IS_NOT_ALIGN(win->base_addr, CCU_WIN_ALIGNMENT)) { 104*91f16700Schasinglulu win->base_addr = ALIGN_UP(win->base_addr, CCU_WIN_ALIGNMENT); 105*91f16700Schasinglulu NOTICE("%s: Align up the base address to 0x%" PRIx64 "\n", 106*91f16700Schasinglulu __func__, win->base_addr); 107*91f16700Schasinglulu } 108*91f16700Schasinglulu 109*91f16700Schasinglulu /* size parameter validity check */ 110*91f16700Schasinglulu if (IS_NOT_ALIGN(win->win_size, CCU_WIN_ALIGNMENT)) { 111*91f16700Schasinglulu win->win_size = ALIGN_UP(win->win_size, CCU_WIN_ALIGNMENT); 112*91f16700Schasinglulu NOTICE("%s: Aligning size to 0x%" PRIx64 "\n", 113*91f16700Schasinglulu __func__, win->win_size); 114*91f16700Schasinglulu } 115*91f16700Schasinglulu } 116*91f16700Schasinglulu 117*91f16700Schasinglulu int ccu_is_win_enabled(int ap_index, uint32_t win_id) 118*91f16700Schasinglulu { 119*91f16700Schasinglulu return mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)) & 120*91f16700Schasinglulu WIN_ENABLE_BIT; 121*91f16700Schasinglulu } 122*91f16700Schasinglulu 123*91f16700Schasinglulu void ccu_enable_win(int ap_index, struct addr_map_win *win, uint32_t win_id) 124*91f16700Schasinglulu { 125*91f16700Schasinglulu uint32_t ccu_win_reg; 126*91f16700Schasinglulu uint32_t alr, ahr; 127*91f16700Schasinglulu uint64_t end_addr; 128*91f16700Schasinglulu 129*91f16700Schasinglulu if ((win_id == 0) || (win_id > MVEBU_CCU_MAX_WINS)) { 130*91f16700Schasinglulu ERROR("Enabling wrong CCU window %d!\n", win_id); 131*91f16700Schasinglulu return; 132*91f16700Schasinglulu } 133*91f16700Schasinglulu 134*91f16700Schasinglulu end_addr = (win->base_addr + win->win_size - 1); 135*91f16700Schasinglulu alr = (uint32_t)((win->base_addr >> ADDRESS_SHIFT) & ADDRESS_MASK); 136*91f16700Schasinglulu ahr = (uint32_t)((end_addr >> ADDRESS_SHIFT) & ADDRESS_MASK); 137*91f16700Schasinglulu 138*91f16700Schasinglulu mmio_write_32(CCU_WIN_ALR_OFFSET(ap_index, win_id), alr); 139*91f16700Schasinglulu mmio_write_32(CCU_WIN_AHR_OFFSET(ap_index, win_id), ahr); 140*91f16700Schasinglulu 141*91f16700Schasinglulu ccu_win_reg = WIN_ENABLE_BIT; 142*91f16700Schasinglulu ccu_win_reg |= (win->target_id & CCU_TARGET_ID_MASK) 143*91f16700Schasinglulu << CCU_TARGET_ID_OFFSET; 144*91f16700Schasinglulu mmio_write_32(CCU_WIN_CR_OFFSET(ap_index, win_id), ccu_win_reg); 145*91f16700Schasinglulu } 146*91f16700Schasinglulu 147*91f16700Schasinglulu static void ccu_disable_win(int ap_index, uint32_t win_id) 148*91f16700Schasinglulu { 149*91f16700Schasinglulu uint32_t win_reg; 150*91f16700Schasinglulu 151*91f16700Schasinglulu if ((win_id == 0) || (win_id > MVEBU_CCU_MAX_WINS)) { 152*91f16700Schasinglulu ERROR("Disabling wrong CCU window %d!\n", win_id); 153*91f16700Schasinglulu return; 154*91f16700Schasinglulu } 155*91f16700Schasinglulu 156*91f16700Schasinglulu win_reg = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)); 157*91f16700Schasinglulu win_reg &= ~WIN_ENABLE_BIT; 158*91f16700Schasinglulu mmio_write_32(CCU_WIN_CR_OFFSET(ap_index, win_id), win_reg); 159*91f16700Schasinglulu } 160*91f16700Schasinglulu 161*91f16700Schasinglulu /* Insert/Remove temporary window for using the out-of reset default 162*91f16700Schasinglulu * CPx base address to access the CP configuration space prior to 163*91f16700Schasinglulu * the further base address update in accordance with address mapping 164*91f16700Schasinglulu * design. 165*91f16700Schasinglulu * 166*91f16700Schasinglulu * NOTE: Use the same window array for insertion and removal of 167*91f16700Schasinglulu * temporary windows. 168*91f16700Schasinglulu */ 169*91f16700Schasinglulu void ccu_temp_win_insert(int ap_index, struct addr_map_win *win, int size) 170*91f16700Schasinglulu { 171*91f16700Schasinglulu uint32_t win_id; 172*91f16700Schasinglulu 173*91f16700Schasinglulu for (int i = 0; i < size; i++) { 174*91f16700Schasinglulu win_id = MVEBU_CCU_MAX_WINS - 1 - i; 175*91f16700Schasinglulu ccu_win_check(win); 176*91f16700Schasinglulu ccu_enable_win(ap_index, win, win_id); 177*91f16700Schasinglulu win++; 178*91f16700Schasinglulu } 179*91f16700Schasinglulu } 180*91f16700Schasinglulu 181*91f16700Schasinglulu /* 182*91f16700Schasinglulu * NOTE: Use the same window array for insertion and removal of 183*91f16700Schasinglulu * temporary windows. 184*91f16700Schasinglulu */ 185*91f16700Schasinglulu void ccu_temp_win_remove(int ap_index, struct addr_map_win *win, int size) 186*91f16700Schasinglulu { 187*91f16700Schasinglulu uint32_t win_id; 188*91f16700Schasinglulu 189*91f16700Schasinglulu for (int i = 0; i < size; i++) { 190*91f16700Schasinglulu uint64_t base; 191*91f16700Schasinglulu uint32_t target; 192*91f16700Schasinglulu 193*91f16700Schasinglulu win_id = MVEBU_CCU_MAX_WINS - 1 - i; 194*91f16700Schasinglulu 195*91f16700Schasinglulu target = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)); 196*91f16700Schasinglulu target >>= CCU_TARGET_ID_OFFSET; 197*91f16700Schasinglulu target &= CCU_TARGET_ID_MASK; 198*91f16700Schasinglulu 199*91f16700Schasinglulu base = mmio_read_32(CCU_WIN_ALR_OFFSET(ap_index, win_id)); 200*91f16700Schasinglulu base <<= ADDRESS_SHIFT; 201*91f16700Schasinglulu 202*91f16700Schasinglulu if ((win->target_id != target) || (win->base_addr != base)) { 203*91f16700Schasinglulu ERROR("%s: Trying to remove bad window-%d!\n", 204*91f16700Schasinglulu __func__, win_id); 205*91f16700Schasinglulu continue; 206*91f16700Schasinglulu } 207*91f16700Schasinglulu ccu_disable_win(ap_index, win_id); 208*91f16700Schasinglulu win++; 209*91f16700Schasinglulu } 210*91f16700Schasinglulu } 211*91f16700Schasinglulu 212*91f16700Schasinglulu /* Returns current DRAM window target (DRAM_0_TID, DRAM_1_TID, RAR_TID) 213*91f16700Schasinglulu * NOTE: Call only once for each AP. 214*91f16700Schasinglulu * The AP0 DRAM window is located at index 2 only at the BL31 execution start. 215*91f16700Schasinglulu * Then it relocated to index 1 for matching the rest of APs DRAM settings. 216*91f16700Schasinglulu * Calling this function after relocation will produce wrong results on AP0 217*91f16700Schasinglulu */ 218*91f16700Schasinglulu static uint32_t ccu_dram_target_get(int ap_index) 219*91f16700Schasinglulu { 220*91f16700Schasinglulu /* On BLE stage the AP0 DRAM window is opened by the BootROM at index 2. 221*91f16700Schasinglulu * All the rest of detected APs will use window at index 1. 222*91f16700Schasinglulu * The AP0 DRAM window is moved from index 2 to 1 during 223*91f16700Schasinglulu * init_ccu() execution. 224*91f16700Schasinglulu */ 225*91f16700Schasinglulu const uint32_t win_id = (ap_index == 0) ? 2 : 1; 226*91f16700Schasinglulu uint32_t target; 227*91f16700Schasinglulu 228*91f16700Schasinglulu target = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)); 229*91f16700Schasinglulu target >>= CCU_TARGET_ID_OFFSET; 230*91f16700Schasinglulu target &= CCU_TARGET_ID_MASK; 231*91f16700Schasinglulu 232*91f16700Schasinglulu return target; 233*91f16700Schasinglulu } 234*91f16700Schasinglulu 235*91f16700Schasinglulu void ccu_dram_target_set(int ap_index, uint32_t target) 236*91f16700Schasinglulu { 237*91f16700Schasinglulu /* On BLE stage the AP0 DRAM window is opened by the BootROM at index 2. 238*91f16700Schasinglulu * All the rest of detected APs will use window at index 1. 239*91f16700Schasinglulu * The AP0 DRAM window is moved from index 2 to 1 240*91f16700Schasinglulu * during init_ccu() execution. 241*91f16700Schasinglulu */ 242*91f16700Schasinglulu const uint32_t win_id = (ap_index == 0) ? 2 : 1; 243*91f16700Schasinglulu uint32_t dram_cr; 244*91f16700Schasinglulu 245*91f16700Schasinglulu dram_cr = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)); 246*91f16700Schasinglulu dram_cr &= ~(CCU_TARGET_ID_MASK << CCU_TARGET_ID_OFFSET); 247*91f16700Schasinglulu dram_cr |= (target & CCU_TARGET_ID_MASK) << CCU_TARGET_ID_OFFSET; 248*91f16700Schasinglulu mmio_write_32(CCU_WIN_CR_OFFSET(ap_index, win_id), dram_cr); 249*91f16700Schasinglulu } 250*91f16700Schasinglulu 251*91f16700Schasinglulu /* Setup CCU DRAM window and enable it */ 252*91f16700Schasinglulu void ccu_dram_win_config(int ap_index, struct addr_map_win *win) 253*91f16700Schasinglulu { 254*91f16700Schasinglulu #if IMAGE_BLE /* BLE */ 255*91f16700Schasinglulu /* On BLE stage the AP0 DRAM window is opened by the BootROM at index 2. 256*91f16700Schasinglulu * Since the BootROM is not accessing DRAM at BLE stage, 257*91f16700Schasinglulu * the DRAM window can be temporarely disabled. 258*91f16700Schasinglulu */ 259*91f16700Schasinglulu const uint32_t win_id = (ap_index == 0) ? 2 : 1; 260*91f16700Schasinglulu #else /* end of BLE */ 261*91f16700Schasinglulu /* At the ccu_init() execution stage, DRAM windows of all APs 262*91f16700Schasinglulu * are arranged at index 1. 263*91f16700Schasinglulu * The AP0 still has the old window BootROM DRAM at index 2, so 264*91f16700Schasinglulu * the window-1 can be safely disabled without breaking the DRAM access. 265*91f16700Schasinglulu */ 266*91f16700Schasinglulu const uint32_t win_id = 1; 267*91f16700Schasinglulu #endif 268*91f16700Schasinglulu 269*91f16700Schasinglulu ccu_disable_win(ap_index, win_id); 270*91f16700Schasinglulu /* enable write secure (and clear read secure) */ 271*91f16700Schasinglulu mmio_write_32(CCU_WIN_SCR_OFFSET(ap_index, win_id), 272*91f16700Schasinglulu CCU_WIN_ENA_WRITE_SECURE); 273*91f16700Schasinglulu ccu_win_check(win); 274*91f16700Schasinglulu ccu_enable_win(ap_index, win, win_id); 275*91f16700Schasinglulu } 276*91f16700Schasinglulu 277*91f16700Schasinglulu /* Save content of CCU window + GCR */ 278*91f16700Schasinglulu static void ccu_save_win_range(int ap_id, int win_first, 279*91f16700Schasinglulu int win_last, uint32_t *buffer) 280*91f16700Schasinglulu { 281*91f16700Schasinglulu int win_id, idx; 282*91f16700Schasinglulu /* Save CCU */ 283*91f16700Schasinglulu for (idx = 0, win_id = win_first; win_id <= win_last; win_id++) { 284*91f16700Schasinglulu buffer[idx++] = mmio_read_32(CCU_WIN_CR_OFFSET(ap_id, win_id)); 285*91f16700Schasinglulu buffer[idx++] = mmio_read_32(CCU_WIN_SCR_OFFSET(ap_id, win_id)); 286*91f16700Schasinglulu buffer[idx++] = mmio_read_32(CCU_WIN_ALR_OFFSET(ap_id, win_id)); 287*91f16700Schasinglulu buffer[idx++] = mmio_read_32(CCU_WIN_AHR_OFFSET(ap_id, win_id)); 288*91f16700Schasinglulu } 289*91f16700Schasinglulu buffer[idx] = mmio_read_32(CCU_WIN_GCR_OFFSET(ap_id)); 290*91f16700Schasinglulu } 291*91f16700Schasinglulu 292*91f16700Schasinglulu /* Restore content of CCU window + GCR */ 293*91f16700Schasinglulu static void ccu_restore_win_range(int ap_id, int win_first, 294*91f16700Schasinglulu int win_last, uint32_t *buffer) 295*91f16700Schasinglulu { 296*91f16700Schasinglulu int win_id, idx; 297*91f16700Schasinglulu /* Restore CCU */ 298*91f16700Schasinglulu for (idx = 0, win_id = win_first; win_id <= win_last; win_id++) { 299*91f16700Schasinglulu mmio_write_32(CCU_WIN_CR_OFFSET(ap_id, win_id), buffer[idx++]); 300*91f16700Schasinglulu mmio_write_32(CCU_WIN_SCR_OFFSET(ap_id, win_id), buffer[idx++]); 301*91f16700Schasinglulu mmio_write_32(CCU_WIN_ALR_OFFSET(ap_id, win_id), buffer[idx++]); 302*91f16700Schasinglulu mmio_write_32(CCU_WIN_AHR_OFFSET(ap_id, win_id), buffer[idx++]); 303*91f16700Schasinglulu } 304*91f16700Schasinglulu mmio_write_32(CCU_WIN_GCR_OFFSET(ap_id), buffer[idx]); 305*91f16700Schasinglulu } 306*91f16700Schasinglulu 307*91f16700Schasinglulu void ccu_save_win_all(int ap_id) 308*91f16700Schasinglulu { 309*91f16700Schasinglulu ccu_save_win_range(ap_id, 0, MVEBU_CCU_MAX_WINS - 1, ccu_regs_save); 310*91f16700Schasinglulu } 311*91f16700Schasinglulu 312*91f16700Schasinglulu void ccu_restore_win_all(int ap_id) 313*91f16700Schasinglulu { 314*91f16700Schasinglulu ccu_restore_win_range(ap_id, 0, MVEBU_CCU_MAX_WINS - 1, ccu_regs_save); 315*91f16700Schasinglulu } 316*91f16700Schasinglulu 317*91f16700Schasinglulu int init_ccu(int ap_index) 318*91f16700Schasinglulu { 319*91f16700Schasinglulu struct addr_map_win *win, *dram_win; 320*91f16700Schasinglulu uint32_t win_id, win_reg; 321*91f16700Schasinglulu uint32_t win_count, array_id; 322*91f16700Schasinglulu uint32_t dram_target; 323*91f16700Schasinglulu #if IMAGE_BLE 324*91f16700Schasinglulu /* In BootROM context CCU Window-1 325*91f16700Schasinglulu * has SRAM_TID target and should not be disabled 326*91f16700Schasinglulu */ 327*91f16700Schasinglulu const uint32_t win_start = 2; 328*91f16700Schasinglulu #else 329*91f16700Schasinglulu const uint32_t win_start = 1; 330*91f16700Schasinglulu #endif 331*91f16700Schasinglulu 332*91f16700Schasinglulu INFO("Initializing CCU Address decoding\n"); 333*91f16700Schasinglulu 334*91f16700Schasinglulu /* Get the array of the windows and fill the map data */ 335*91f16700Schasinglulu marvell_get_ccu_memory_map(ap_index, &win, &win_count); 336*91f16700Schasinglulu if (win_count <= 0) { 337*91f16700Schasinglulu INFO("No windows configurations found\n"); 338*91f16700Schasinglulu } else if (win_count > (MVEBU_CCU_MAX_WINS - 1)) { 339*91f16700Schasinglulu ERROR("CCU mem map array > than max available windows (%d)\n", 340*91f16700Schasinglulu MVEBU_CCU_MAX_WINS); 341*91f16700Schasinglulu win_count = MVEBU_CCU_MAX_WINS; 342*91f16700Schasinglulu } 343*91f16700Schasinglulu 344*91f16700Schasinglulu /* Need to set GCR to DRAM before all CCU windows are disabled for 345*91f16700Schasinglulu * securing the normal access to DRAM location, which the ATF is running 346*91f16700Schasinglulu * from. Once all CCU windows are set, which have to include the 347*91f16700Schasinglulu * dedicated DRAM window as well, the GCR can be switched to the target 348*91f16700Schasinglulu * defined by the platform configuration. 349*91f16700Schasinglulu */ 350*91f16700Schasinglulu dram_target = ccu_dram_target_get(ap_index); 351*91f16700Schasinglulu win_reg = (dram_target & CCU_GCR_TARGET_MASK) << CCU_GCR_TARGET_OFFSET; 352*91f16700Schasinglulu mmio_write_32(CCU_WIN_GCR_OFFSET(ap_index), win_reg); 353*91f16700Schasinglulu 354*91f16700Schasinglulu /* If the DRAM window was already configured at the BLE stage, 355*91f16700Schasinglulu * only the window target considered valid, the address range should be 356*91f16700Schasinglulu * updated according to the platform configuration. 357*91f16700Schasinglulu */ 358*91f16700Schasinglulu for (dram_win = win, array_id = 0; array_id < win_count; 359*91f16700Schasinglulu array_id++, dram_win++) { 360*91f16700Schasinglulu if (IS_DRAM_TARGET(dram_win->target_id)) { 361*91f16700Schasinglulu dram_win->target_id = dram_target; 362*91f16700Schasinglulu break; 363*91f16700Schasinglulu } 364*91f16700Schasinglulu } 365*91f16700Schasinglulu 366*91f16700Schasinglulu /* Disable all AP CCU windows 367*91f16700Schasinglulu * Window-0 is always bypassed since it already contains 368*91f16700Schasinglulu * data allowing the internal configuration space access 369*91f16700Schasinglulu */ 370*91f16700Schasinglulu for (win_id = win_start; win_id < MVEBU_CCU_MAX_WINS; win_id++) { 371*91f16700Schasinglulu ccu_disable_win(ap_index, win_id); 372*91f16700Schasinglulu /* enable write secure (and clear read secure) */ 373*91f16700Schasinglulu mmio_write_32(CCU_WIN_SCR_OFFSET(ap_index, win_id), 374*91f16700Schasinglulu CCU_WIN_ENA_WRITE_SECURE); 375*91f16700Schasinglulu } 376*91f16700Schasinglulu 377*91f16700Schasinglulu /* win_id is the index of the current ccu window 378*91f16700Schasinglulu * array_id is the index of the current memory map window entry 379*91f16700Schasinglulu */ 380*91f16700Schasinglulu for (win_id = win_start, array_id = 0; 381*91f16700Schasinglulu ((win_id < MVEBU_CCU_MAX_WINS) && (array_id < win_count)); 382*91f16700Schasinglulu win_id++) { 383*91f16700Schasinglulu ccu_win_check(win); 384*91f16700Schasinglulu ccu_enable_win(ap_index, win, win_id); 385*91f16700Schasinglulu win++; 386*91f16700Schasinglulu array_id++; 387*91f16700Schasinglulu } 388*91f16700Schasinglulu 389*91f16700Schasinglulu /* Get & set the default target according to board topology */ 390*91f16700Schasinglulu win_reg = (marvell_get_ccu_gcr_target(ap_index) & CCU_GCR_TARGET_MASK) 391*91f16700Schasinglulu << CCU_GCR_TARGET_OFFSET; 392*91f16700Schasinglulu mmio_write_32(CCU_WIN_GCR_OFFSET(ap_index), win_reg); 393*91f16700Schasinglulu 394*91f16700Schasinglulu #ifdef DEBUG_ADDR_MAP 395*91f16700Schasinglulu dump_ccu(ap_index); 396*91f16700Schasinglulu #endif 397*91f16700Schasinglulu 398*91f16700Schasinglulu INFO("Done CCU Address decoding Initializing\n"); 399*91f16700Schasinglulu 400*91f16700Schasinglulu return 0; 401*91f16700Schasinglulu } 402*91f16700Schasinglulu 403*91f16700Schasinglulu void errata_wa_init(void) 404*91f16700Schasinglulu { 405*91f16700Schasinglulu /* 406*91f16700Schasinglulu * EERATA ID: RES-3033912 - Internal Address Space Init state causes 407*91f16700Schasinglulu * a hang upon accesses to [0xf070_0000, 0xf07f_ffff] 408*91f16700Schasinglulu * Workaround: Boot Firmware (ATF) should configure CCU_RGF_WIN(4) to 409*91f16700Schasinglulu * split [0x6e_0000, 0x1ff_ffff] to values [0x6e_0000, 0x6f_ffff] and 410*91f16700Schasinglulu * [0x80_0000, 0xff_ffff] and [0x100_0000, 0x1ff_ffff],that cause 411*91f16700Schasinglulu * accesses to the segment of [0xf070_0000, 0xf1ff_ffff] 412*91f16700Schasinglulu * to act as RAZWI. 413*91f16700Schasinglulu */ 414*91f16700Schasinglulu mmio_write_32(CCU_RGF(4), ERRATA_WA_CCU_WIN4); 415*91f16700Schasinglulu mmio_write_32(CCU_RGF(5), ERRATA_WA_CCU_WIN5); 416*91f16700Schasinglulu mmio_write_32(CCU_RGF(6), ERRATA_WA_CCU_WIN6); 417*91f16700Schasinglulu } 418