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 #include <platform_def.h> 9*91f16700Schasinglulu 10*91f16700Schasinglulu #include <common/bl_common.h> 11*91f16700Schasinglulu #include <common/debug.h> 12*91f16700Schasinglulu #include <drivers/marvell/ccu.h> 13*91f16700Schasinglulu #include <drivers/marvell/mochi/ap_setup.h> 14*91f16700Schasinglulu #include <drivers/marvell/mochi/cp110_setup.h> 15*91f16700Schasinglulu #include <lib/mmio.h> 16*91f16700Schasinglulu 17*91f16700Schasinglulu #include <armada_common.h> 18*91f16700Schasinglulu #include <marvell_plat_priv.h> /* timer functionality */ 19*91f16700Schasinglulu #include "mss_defs.h" 20*91f16700Schasinglulu #include "mss_scp_bootloader.h" 21*91f16700Schasinglulu 22*91f16700Schasinglulu /* MSS windows configuration */ 23*91f16700Schasinglulu #define MSS_AEBR(base) (base + 0x160) 24*91f16700Schasinglulu #define MSS_AIBR(base) (base + 0x164) 25*91f16700Schasinglulu #define MSS_AEBR_MASK 0xFFF 26*91f16700Schasinglulu #define MSS_AIBR_MASK 0xFFF 27*91f16700Schasinglulu 28*91f16700Schasinglulu #define MSS_EXTERNAL_SPACE 0x50000000 29*91f16700Schasinglulu #define MSS_EXTERNAL_ACCESS_BIT 28 30*91f16700Schasinglulu #define MSS_EXTERNAL_ADDR_MASK 0xfffffff 31*91f16700Schasinglulu #define MSS_INTERNAL_ACCESS_BIT 28 32*91f16700Schasinglulu 33*91f16700Schasinglulu struct addr_map_win ccu_mem_map[] = { 34*91f16700Schasinglulu {MVEBU_CP_REGS_BASE(0), 0x4000000, IO_0_TID} 35*91f16700Schasinglulu }; 36*91f16700Schasinglulu 37*91f16700Schasinglulu /* Since the scp_bl2 image can contain firmware for cp1 and cp0 coprocessors, 38*91f16700Schasinglulu * the access to cp0 and cp1 need to be provided. More precisely it is 39*91f16700Schasinglulu * required to: 40*91f16700Schasinglulu * - get the information about device id which is stored in CP0 registers 41*91f16700Schasinglulu * (to distinguish between cases where we have cp0 and cp1 or standalone cp0) 42*91f16700Schasinglulu * - get the access to cp which is needed for loading fw for cp0/cp1 43*91f16700Schasinglulu * coprocessors 44*91f16700Schasinglulu * This function configures ccu windows accordingly. 45*91f16700Schasinglulu * 46*91f16700Schasinglulu * Note: there is no need to restore previous ccu configuration, since in next 47*91f16700Schasinglulu * phase (BL31) the init_ccu will be called (via apn806_init/ 48*91f16700Schasinglulu * bl31_plat_arch_setu) and therefore the ccu configuration will be overwritten. 49*91f16700Schasinglulu */ 50*91f16700Schasinglulu static int bl2_plat_mmap_init(void) 51*91f16700Schasinglulu { 52*91f16700Schasinglulu int cfg_num, win_id, cfg_idx, cp; 53*91f16700Schasinglulu 54*91f16700Schasinglulu cfg_num = ARRAY_SIZE(ccu_mem_map); 55*91f16700Schasinglulu 56*91f16700Schasinglulu /* CCU window-0 should not be counted - it's already used */ 57*91f16700Schasinglulu if (cfg_num > (MVEBU_CCU_MAX_WINS - 1)) { 58*91f16700Schasinglulu ERROR("BL2: %s: trying to open too many windows\n", __func__); 59*91f16700Schasinglulu return -1; 60*91f16700Schasinglulu } 61*91f16700Schasinglulu 62*91f16700Schasinglulu /* Enable required CCU windows 63*91f16700Schasinglulu * Do not touch CCU window 0, 64*91f16700Schasinglulu * it's used for the internal registers access 65*91f16700Schasinglulu */ 66*91f16700Schasinglulu for (cfg_idx = 0, win_id = 1; 67*91f16700Schasinglulu (win_id < MVEBU_CCU_MAX_WINS) && (cfg_idx < cfg_num); win_id++) { 68*91f16700Schasinglulu /* Skip already enabled CCU windows */ 69*91f16700Schasinglulu if (ccu_is_win_enabled(MVEBU_AP0, win_id)) 70*91f16700Schasinglulu continue; 71*91f16700Schasinglulu /* Enable required CCU windows */ 72*91f16700Schasinglulu ccu_win_check(&ccu_mem_map[cfg_idx]); 73*91f16700Schasinglulu ccu_enable_win(MVEBU_AP0, &ccu_mem_map[cfg_idx], win_id); 74*91f16700Schasinglulu cfg_idx++; 75*91f16700Schasinglulu } 76*91f16700Schasinglulu 77*91f16700Schasinglulu /* Config address for each cp other than cp0 */ 78*91f16700Schasinglulu for (cp = 1; cp < CP_COUNT; cp++) 79*91f16700Schasinglulu update_cp110_default_win(cp); 80*91f16700Schasinglulu 81*91f16700Schasinglulu /* There is need to configure IO_WIN windows again to overwrite 82*91f16700Schasinglulu * temporary configuration done during update_cp110_default_win 83*91f16700Schasinglulu */ 84*91f16700Schasinglulu init_io_win(MVEBU_AP0); 85*91f16700Schasinglulu 86*91f16700Schasinglulu /* Open AMB bridge required for MG access */ 87*91f16700Schasinglulu for (cp = 0; cp < CP_COUNT; cp++) 88*91f16700Schasinglulu cp110_amb_init(MVEBU_CP_REGS_BASE(cp)); 89*91f16700Schasinglulu 90*91f16700Schasinglulu return 0; 91*91f16700Schasinglulu } 92*91f16700Schasinglulu 93*91f16700Schasinglulu /***************************************************************************** 94*91f16700Schasinglulu * Transfer SCP_BL2 from Trusted RAM using the SCP Download protocol. 95*91f16700Schasinglulu * Return 0 on success, -1 otherwise. 96*91f16700Schasinglulu ***************************************************************************** 97*91f16700Schasinglulu */ 98*91f16700Schasinglulu int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info) 99*91f16700Schasinglulu { 100*91f16700Schasinglulu int ret; 101*91f16700Schasinglulu 102*91f16700Schasinglulu INFO("BL2: Initiating SCP_BL2 transfer to SCP\n"); 103*91f16700Schasinglulu 104*91f16700Schasinglulu /* initialize time (for delay functionality) */ 105*91f16700Schasinglulu plat_delay_timer_init(); 106*91f16700Schasinglulu 107*91f16700Schasinglulu ret = bl2_plat_mmap_init(); 108*91f16700Schasinglulu if (ret != 0) 109*91f16700Schasinglulu return ret; 110*91f16700Schasinglulu 111*91f16700Schasinglulu ret = scp_bootloader_transfer((void *)scp_bl2_image_info->image_base, 112*91f16700Schasinglulu scp_bl2_image_info->image_size); 113*91f16700Schasinglulu 114*91f16700Schasinglulu if (ret == 0) 115*91f16700Schasinglulu INFO("BL2: SCP_BL2 transferred to SCP\n"); 116*91f16700Schasinglulu else 117*91f16700Schasinglulu ERROR("BL2: SCP_BL2 transfer failure\n"); 118*91f16700Schasinglulu 119*91f16700Schasinglulu return ret; 120*91f16700Schasinglulu } 121*91f16700Schasinglulu 122*91f16700Schasinglulu uintptr_t bl2_plat_get_cp_mss_regs(int ap_idx, int cp_idx) 123*91f16700Schasinglulu { 124*91f16700Schasinglulu return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_REGS_OFFSET; 125*91f16700Schasinglulu } 126*91f16700Schasinglulu 127*91f16700Schasinglulu uintptr_t bl2_plat_get_cp_mss_sram(int ap_idx, int cp_idx) 128*91f16700Schasinglulu { 129*91f16700Schasinglulu return MVEBU_CP_REGS_BASE(cp_idx) + MSS_CP_SRAM_OFFSET; 130*91f16700Schasinglulu } 131*91f16700Schasinglulu 132*91f16700Schasinglulu uintptr_t bl2_plat_get_ap_mss_regs(int ap_idx) 133*91f16700Schasinglulu { 134*91f16700Schasinglulu return MVEBU_REGS_BASE + MSS_AP_REGS_OFFSET; 135*91f16700Schasinglulu } 136*91f16700Schasinglulu 137*91f16700Schasinglulu uint32_t bl2_plat_get_cp_count(int ap_idx) 138*91f16700Schasinglulu { 139*91f16700Schasinglulu uint32_t revision = cp110_device_id_get(MVEBU_CP_REGS_BASE(0)); 140*91f16700Schasinglulu /* A8040: two CPs. 141*91f16700Schasinglulu * A7040: one CP. 142*91f16700Schasinglulu */ 143*91f16700Schasinglulu if (revision == MVEBU_80X0_DEV_ID || 144*91f16700Schasinglulu revision == MVEBU_80X0_CP115_DEV_ID) 145*91f16700Schasinglulu return 2; 146*91f16700Schasinglulu else if (revision == MVEBU_CN9130_DEV_ID) 147*91f16700Schasinglulu return CP_COUNT; 148*91f16700Schasinglulu else 149*91f16700Schasinglulu return 1; 150*91f16700Schasinglulu } 151*91f16700Schasinglulu 152*91f16700Schasinglulu uint32_t bl2_plat_get_ap_count(void) 153*91f16700Schasinglulu { 154*91f16700Schasinglulu /* A8040 and A7040 have only one AP */ 155*91f16700Schasinglulu return 1; 156*91f16700Schasinglulu } 157*91f16700Schasinglulu 158*91f16700Schasinglulu void bl2_plat_configure_mss_windows(uintptr_t mss_regs) 159*91f16700Schasinglulu { 160*91f16700Schasinglulu /* set AXI External and Internal Address Bus extension */ 161*91f16700Schasinglulu mmio_write_32(MSS_AEBR(mss_regs), 162*91f16700Schasinglulu ((0x0 >> MSS_EXTERNAL_ACCESS_BIT) & MSS_AEBR_MASK)); 163*91f16700Schasinglulu mmio_write_32(MSS_AIBR(mss_regs), 164*91f16700Schasinglulu ((mss_regs >> MSS_INTERNAL_ACCESS_BIT) & MSS_AIBR_MASK)); 165*91f16700Schasinglulu } 166