1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2017-2020, Broadcom 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <string.h> 8*91f16700Schasinglulu 9*91f16700Schasinglulu #include <arch_helpers.h> 10*91f16700Schasinglulu #include <common/bl_common.h> 11*91f16700Schasinglulu #include <common/debug.h> 12*91f16700Schasinglulu #include <drivers/delay_timer.h> 13*91f16700Schasinglulu 14*91f16700Schasinglulu #include <bcm_elog_ddr.h> 15*91f16700Schasinglulu #include <brcm_mhu.h> 16*91f16700Schasinglulu #include <brcm_scpi.h> 17*91f16700Schasinglulu #include <chimp.h> 18*91f16700Schasinglulu #include <cmn_plat_util.h> 19*91f16700Schasinglulu #include <ddr_init.h> 20*91f16700Schasinglulu #include <scp.h> 21*91f16700Schasinglulu #include <scp_cmd.h> 22*91f16700Schasinglulu #include <scp_utils.h> 23*91f16700Schasinglulu 24*91f16700Schasinglulu #include "m0_cfg.h" 25*91f16700Schasinglulu #include "m0_ipc.h" 26*91f16700Schasinglulu 27*91f16700Schasinglulu #ifdef BCM_ELOG 28*91f16700Schasinglulu static void prepare_elog(void) 29*91f16700Schasinglulu { 30*91f16700Schasinglulu #if (CLEAN_DDR && !defined(MMU_DISABLED)) 31*91f16700Schasinglulu /* 32*91f16700Schasinglulu * Now DDR has been initialized. We want to copy all the logs in SRAM 33*91f16700Schasinglulu * into DDR so we will have much more space to store the logs in the 34*91f16700Schasinglulu * next boot stage 35*91f16700Schasinglulu */ 36*91f16700Schasinglulu bcm_elog_copy_log((void *)BCM_ELOG_BL31_BASE, 37*91f16700Schasinglulu MIN(BCM_ELOG_BL2_SIZE, BCM_ELOG_BL31_SIZE) 38*91f16700Schasinglulu ); 39*91f16700Schasinglulu 40*91f16700Schasinglulu /* 41*91f16700Schasinglulu * We are almost at the end of BL2, and we can stop log here so we do 42*91f16700Schasinglulu * not need to add 'bcm_elog_exit' to the standard BL2 code. The 43*91f16700Schasinglulu * benefit of capturing BL2 logs after this is very minimal in a 44*91f16700Schasinglulu * production system. 45*91f16700Schasinglulu */ 46*91f16700Schasinglulu bcm_elog_exit(); 47*91f16700Schasinglulu #endif 48*91f16700Schasinglulu 49*91f16700Schasinglulu /* 50*91f16700Schasinglulu * Notify CRMU that now it should pull logs from DDR instead of from 51*91f16700Schasinglulu * FS4 SRAM. 52*91f16700Schasinglulu */ 53*91f16700Schasinglulu SCP_WRITE_CFG(flash_log.can_use_ddr, 1); 54*91f16700Schasinglulu } 55*91f16700Schasinglulu #endif 56*91f16700Schasinglulu 57*91f16700Schasinglulu bool is_crmu_alive(void) 58*91f16700Schasinglulu { 59*91f16700Schasinglulu return (scp_send_cmd(MCU_IPC_MCU_CMD_NOP, 0, SCP_CMD_DEFAULT_TIMEOUT_US) 60*91f16700Schasinglulu == 0); 61*91f16700Schasinglulu } 62*91f16700Schasinglulu 63*91f16700Schasinglulu bool bcm_scp_issue_sys_reset(void) 64*91f16700Schasinglulu { 65*91f16700Schasinglulu return (scp_send_cmd(MCU_IPC_MCU_CMD_L1_RESET, 0, 66*91f16700Schasinglulu SCP_CMD_DEFAULT_TIMEOUT_US)); 67*91f16700Schasinglulu } 68*91f16700Schasinglulu 69*91f16700Schasinglulu /* 70*91f16700Schasinglulu * Note that this is just a temporary implementation until 71*91f16700Schasinglulu * channels are introduced 72*91f16700Schasinglulu */ 73*91f16700Schasinglulu 74*91f16700Schasinglulu int plat_bcm_bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info) 75*91f16700Schasinglulu { 76*91f16700Schasinglulu int scp_patch_activated, scp_patch_version; 77*91f16700Schasinglulu #ifndef EMULATION_SETUP 78*91f16700Schasinglulu uint8_t active_ch_bitmap, i; 79*91f16700Schasinglulu #endif 80*91f16700Schasinglulu uint32_t reset_state = 0; 81*91f16700Schasinglulu uint32_t mcu_ap_init_param = 0; 82*91f16700Schasinglulu 83*91f16700Schasinglulu /* 84*91f16700Schasinglulu * First check if SCP patch has already been loaded 85*91f16700Schasinglulu * Send NOP command and see if there is a valid response 86*91f16700Schasinglulu */ 87*91f16700Schasinglulu scp_patch_activated = 88*91f16700Schasinglulu (scp_send_cmd(MCU_IPC_MCU_CMD_NOP, 0, 89*91f16700Schasinglulu SCP_CMD_DEFAULT_TIMEOUT_US) == 0); 90*91f16700Schasinglulu if (scp_patch_activated) { 91*91f16700Schasinglulu INFO("SCP Patch is already active.\n"); 92*91f16700Schasinglulu 93*91f16700Schasinglulu reset_state = SCP_READ_CFG(board_cfg.reset_state); 94*91f16700Schasinglulu mcu_ap_init_param = SCP_READ_CFG(board_cfg.mcu_init_param); 95*91f16700Schasinglulu 96*91f16700Schasinglulu /* Clear reset state, it's been already read */ 97*91f16700Schasinglulu SCP_WRITE_CFG(board_cfg.reset_state, 0); 98*91f16700Schasinglulu 99*91f16700Schasinglulu if (mcu_ap_init_param & MCU_PATCH_LOADED_BY_NITRO) { 100*91f16700Schasinglulu /* 101*91f16700Schasinglulu * Reset "MCU_PATCH_LOADED_BY_NITRO" flag, but 102*91f16700Schasinglulu * Preserve any other flags we don't deal with here 103*91f16700Schasinglulu */ 104*91f16700Schasinglulu INFO("AP booted by Nitro\n"); 105*91f16700Schasinglulu SCP_WRITE_CFG( 106*91f16700Schasinglulu board_cfg.mcu_init_param, 107*91f16700Schasinglulu mcu_ap_init_param & 108*91f16700Schasinglulu ~MCU_PATCH_LOADED_BY_NITRO 109*91f16700Schasinglulu ); 110*91f16700Schasinglulu } 111*91f16700Schasinglulu } else { 112*91f16700Schasinglulu /* 113*91f16700Schasinglulu * MCU Patch not loaded, so load it. 114*91f16700Schasinglulu * MCU patch stamps critical points in REG9 (debug test-point) 115*91f16700Schasinglulu * Display its last content here. This helps to locate 116*91f16700Schasinglulu * where crash occurred if a CRMU watchdog kicked in. 117*91f16700Schasinglulu */ 118*91f16700Schasinglulu int ret; 119*91f16700Schasinglulu 120*91f16700Schasinglulu INFO("MCU Patch Point: 0x%x\n", 121*91f16700Schasinglulu mmio_read_32(CRMU_IHOST_SW_PERSISTENT_REG9)); 122*91f16700Schasinglulu 123*91f16700Schasinglulu ret = download_scp_patch((void *)scp_bl2_image_info->image_base, 124*91f16700Schasinglulu scp_bl2_image_info->image_size); 125*91f16700Schasinglulu if (ret != 0) 126*91f16700Schasinglulu return ret; 127*91f16700Schasinglulu 128*91f16700Schasinglulu VERBOSE("SCP Patch loaded OK.\n"); 129*91f16700Schasinglulu 130*91f16700Schasinglulu ret = scp_send_cmd(MCU_IPC_MCU_CMD_INIT, 131*91f16700Schasinglulu MCU_PATCH_LOADED_BY_AP, 132*91f16700Schasinglulu SCP_CMD_SCP_BOOT_TIMEOUT_US); 133*91f16700Schasinglulu if (ret) { 134*91f16700Schasinglulu ERROR("SCP Patch could not initialize; error %d\n", 135*91f16700Schasinglulu ret); 136*91f16700Schasinglulu return ret; 137*91f16700Schasinglulu } 138*91f16700Schasinglulu 139*91f16700Schasinglulu INFO("SCP Patch successfully initialized.\n"); 140*91f16700Schasinglulu } 141*91f16700Schasinglulu 142*91f16700Schasinglulu scp_patch_version = scp_send_cmd(MCU_IPC_MCU_CMD_GET_FW_VERSION, 0, 143*91f16700Schasinglulu SCP_CMD_DEFAULT_TIMEOUT_US); 144*91f16700Schasinglulu INFO("SCP Patch version :0x%x\n", scp_patch_version); 145*91f16700Schasinglulu 146*91f16700Schasinglulu /* Next block just reports current AVS voltages (if applicable) */ 147*91f16700Schasinglulu { 148*91f16700Schasinglulu uint16_t vcore_mv, ihost03_mv, ihost12_mv; 149*91f16700Schasinglulu 150*91f16700Schasinglulu vcore_mv = SCP_READ_CFG16(vcore.millivolts) + 151*91f16700Schasinglulu SCP_READ_CFG8(vcore.avs_cfg.additive_margin); 152*91f16700Schasinglulu ihost03_mv = SCP_READ_CFG16(ihost03.millivolts) + 153*91f16700Schasinglulu SCP_READ_CFG8(ihost03.avs_cfg.additive_margin); 154*91f16700Schasinglulu ihost12_mv = SCP_READ_CFG16(ihost12.millivolts) + 155*91f16700Schasinglulu SCP_READ_CFG8(ihost12.avs_cfg.additive_margin); 156*91f16700Schasinglulu 157*91f16700Schasinglulu if (vcore_mv || ihost03_mv || ihost12_mv) { 158*91f16700Schasinglulu INFO("AVS voltages from cfg (including margin)\n"); 159*91f16700Schasinglulu if (vcore_mv > 0) 160*91f16700Schasinglulu INFO("%s\tVCORE: %dmv\n", 161*91f16700Schasinglulu SCP_READ_CFG8(vcore.avs_cfg.avs_set) ? 162*91f16700Schasinglulu "*" : "n/a", vcore_mv); 163*91f16700Schasinglulu if (ihost03_mv > 0) 164*91f16700Schasinglulu INFO("%s\tIHOST03: %dmv\n", 165*91f16700Schasinglulu SCP_READ_CFG8(ihost03.avs_cfg.avs_set) ? 166*91f16700Schasinglulu "*" : "n/a", ihost03_mv); 167*91f16700Schasinglulu if (ihost12_mv > 0) 168*91f16700Schasinglulu INFO("%s\tIHOST12: %dmv\n", 169*91f16700Schasinglulu SCP_READ_CFG8(ihost12.avs_cfg.avs_set) ? 170*91f16700Schasinglulu "*" : "n/a", ihost12_mv); 171*91f16700Schasinglulu } else { 172*91f16700Schasinglulu INFO("AVS settings not applicable\n"); 173*91f16700Schasinglulu } 174*91f16700Schasinglulu } 175*91f16700Schasinglulu 176*91f16700Schasinglulu #if (CLEAN_DDR && !defined(MMU_DISABLED) && !defined(EMULATION_SETUP)) 177*91f16700Schasinglulu /* This will clean the DDR and enable ECC if set */ 178*91f16700Schasinglulu check_ddr_clean(); 179*91f16700Schasinglulu #endif 180*91f16700Schasinglulu 181*91f16700Schasinglulu #if (WARMBOOT_DDR_S3_SUPPORT && ELOG_STORE_MEDIA_DDR) 182*91f16700Schasinglulu elog_init_ddr_log(); 183*91f16700Schasinglulu #endif 184*91f16700Schasinglulu 185*91f16700Schasinglulu #ifdef BCM_ELOG 186*91f16700Schasinglulu /* Prepare ELOG to use DDR */ 187*91f16700Schasinglulu prepare_elog(); 188*91f16700Schasinglulu #endif 189*91f16700Schasinglulu 190*91f16700Schasinglulu #ifndef EMULATION_SETUP 191*91f16700Schasinglulu /* Ask ddr_init to save obtained DDR information into DDR */ 192*91f16700Schasinglulu ddr_info_save(); 193*91f16700Schasinglulu #endif 194*91f16700Schasinglulu 195*91f16700Schasinglulu /* 196*91f16700Schasinglulu * Configure TMON DDR address. 197*91f16700Schasinglulu * This cfg is common for all cases 198*91f16700Schasinglulu */ 199*91f16700Schasinglulu SCP_WRITE_CFG(tmon_cfg.ddr_desc, TMON_SHARED_DDR_ADDRESS); 200*91f16700Schasinglulu 201*91f16700Schasinglulu if (reset_state == SOFT_RESET_L3 && !mcu_ap_init_param) { 202*91f16700Schasinglulu INFO("SCP configuration after L3 RESET done.\n"); 203*91f16700Schasinglulu return 0; 204*91f16700Schasinglulu } 205*91f16700Schasinglulu 206*91f16700Schasinglulu if (bcm_chimp_is_nic_mode()) 207*91f16700Schasinglulu /* Configure AP WDT to not reset the NIC interface */ 208*91f16700Schasinglulu SCP_WRITE_CFG(board_cfg.apwdt_reset_type, SOFT_RESET_L3); 209*91f16700Schasinglulu 210*91f16700Schasinglulu #if (WARMBOOT_DDR_S3_SUPPORT && ELOG_STORE_MEDIA_DDR) 211*91f16700Schasinglulu /* When AP WDog triggers perform L3 reset if DDR err logging enabled */ 212*91f16700Schasinglulu SCP_WRITE_CFG(board_cfg.apwdt_reset_type, SOFT_RESET_L3); 213*91f16700Schasinglulu #endif 214*91f16700Schasinglulu 215*91f16700Schasinglulu #ifndef EMULATION_SETUP 216*91f16700Schasinglulu 217*91f16700Schasinglulu #ifdef DDR_SCRUB_ENA 218*91f16700Schasinglulu ddr_scrub_enable(); 219*91f16700Schasinglulu #endif 220*91f16700Schasinglulu /* Fill the Active channel information */ 221*91f16700Schasinglulu active_ch_bitmap = get_active_ddr_channel(); 222*91f16700Schasinglulu for (i = 0; i < MAX_NR_DDR_CH; i++) 223*91f16700Schasinglulu SCP_WRITE_CFG(ddr_cfg.ddr_cfg[i], 224*91f16700Schasinglulu (active_ch_bitmap & BIT(i)) ? 1 : 0); 225*91f16700Schasinglulu #endif 226*91f16700Schasinglulu return 0; 227*91f16700Schasinglulu } 228