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