]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/pdk.git/blob - packages/ti/boot/sbl/soc/tpr12/sbl_slave_core_boot.c
sbl: tpr12 fixes for Soc reset in release mode
[processor-sdk/pdk.git] / packages / ti / boot / sbl / soc / tpr12 / sbl_slave_core_boot.c
1 /**
2  *  \file   sbl_slave_core_boot.c
3  *
4  *  \brief  This file contain functions related to slave core boot-up.
5  *
6  */
8 /*
9  * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * Redistributions of source code must retain the above copyright
16  * notice, this list of conditions and the following disclaimer.
17  *
18  * Redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the
21  * distribution.
22  *
23  * Neither the name of Texas Instruments Incorporated nor the names of
24  * its contributors may be used to endorse or promote products derived
25  * from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38  *
39  */
41 /* ========================================================================== */
42 /*                             Include Files                                  */
43 /* ========================================================================== */
45 #include <stdint.h>
46 #include <string.h>
47 #include <ti/csl/csl_types.h>
48 #include <ti/csl/cslr_device.h>
49 #include <ti/csl/hw_types.h>
50 #include <ti/csl/arch/csl_arch.h>
51 #include <ti/csl/soc.h>
52 #include <ti/drv/uart/UART_stdio.h>
54 #include "sbl_soc.h"
55 #include "sbl_log.h"
56 #include "sbl_soc_cfg.h"
57 #include "sbl_profile.h"
58 #include "sbl_err_trap.h"
59 #include "sbl_slave_core_boot.h"
60 #include "sbl_rcm.h"
61 #include "sbl_utils_addrxlate.h"
63 #if defined(BOOT_UART)
64 #include "sbl_uart.h"
65 #endif
67 #if defined(BOOT_QSPI)
68 #include "sbl_qspi.h"
69 #endif
71 /* ========================================================================== */
72 /*                           Macros & Typedefs                                */
73 /* ========================================================================== */
74 #define SBL_DISABLE_MCU_LOCKSTEP    (0)
75 #define SBL_ENABLE_MCU_LOCKSTEP     (1)
77 /* Entry address for DSP1 applications in the memory region where trampolene is located */
78 #define DSP_ENTRY_ADDR         (CSL_DSP_L2_U_BASE)
80 /*
81  * DSP instructions to be copied to the Trampolene to avoid the alignment
82  * requirement.
83  */
84 uint32_t dspInstruction[10] =
85 {
86     0x0500002a, /* MVK.S2  destAddr, B10      */
87     0x0500006a, /* MVKH.S2 destAddr, B10      */
88     0x00280362, /* B.S2    B10                */
89     0x00006000, /* NOP     4                  */
90     0x00000000, /* NOP                        */
91     0x00000000  /* NOP                        */
92 };
94 /* ========================================================================== */
95 /*                           Internal Functions                               */
96 /* ========================================================================== */
97 static void SBL_c66xWakeup(void)
98 {
99     CSL_dss_rcmRegs *dssRcmRegs = (CSL_dss_rcmRegs *)CSL_DSS_RCM_U_BASE;
100     Rcm_Return retVal;
102     /* GEL reset RST CTRL before DSS PLL config. Changing order here. Revert if not functional */
103     /* WR_MEM_32(CSL_DSS_RCM_U_BASE+CSL_DSS_RCM_DSS_DSP_RST_CTRL, 0x0); //DSS_DSP_RST_CTRL */
104     //HW_WR_REG32(CSL_DSS_RCM_U_BASE+DSS_DSP_CLK_DIV_VAL, 0x000);  //DSS_WDT_CLK_DIV_VAL_CLKDIVR   = 0x000;  450/1
105     //HW_WR_REG32(CSL_DSS_RCM_U_BASE+DSS_DSP_CLK_SRC_SEL, 0x222);  //DSS_WDT_CLK_SRC_SEL_CLKSRCSEL = 0x222;
106     retVal = SBL_RcmSetDspCoreClock(Rcm_DSPClockSource_DPLL_DSP_HSDIV0_CLKOUT1, SBL_DSP1_C66X_FREQ_HZ);
107     DebugP_assert(retVal == Rcm_Return_SUCCESS);
109     CSL_FINS(dssRcmRegs->DSS_DSP_RST_CTRL, DSS_RCM_DSS_DSP_RST_CTRL_DSS_DSP_RST_CTRL_ASSERT_POR, 0x0);
110     CSL_FINS(dssRcmRegs->DSS_DSP_RST_CTRL, DSS_RCM_DSS_DSP_RST_CTRL_DSS_DSP_RST_CTRL_ASSERT_GLOBAL, 0x0);
111     CSL_FINS(dssRcmRegs->DSS_DSP_RST_CTRL, DSS_RCM_DSS_DSP_RST_CTRL_DSS_DSP_RST_CTRL_ASSERT_LOCAL, 0x0);
113     CSL_FINS(dssRcmRegs->DSS_DSP_CLK_GATE, DSS_RCM_DSS_DSP_CLK_GATE_DSS_DSP_CLK_GATE_GATED, 0x0);
115     CSL_FINS(dssRcmRegs->DSP_PD_WAKEUP_MASK0, DSS_RCM_DSP_PD_WAKEUP_MASK0_DSP_PD_WAKEUP_MASK0_WAKEUP_MASK0, 0xFFFEFFFF);
116     CSL_FINS(dssRcmRegs->DSP_PD_TRIGGER_WAKUP,DSS_RCM_DSP_PD_TRIGGER_WAKUP_DSP_PD_TRIGGER_WAKUP_WAKEUP_TRIGGER, 0x1);
118     while((CSL_FEXT(dssRcmRegs->DSP_PD_STATUS, DSS_RCM_DSP_PD_STATUS_DSP_PD_STATUS_PD_STATUS) & 0x1) != 1U);
119     (void)Osal_delay(1);
122 static void SBL_c66xStart(void)
124     CSL_dss_rcmRegs *dssRcmRegs = (CSL_dss_rcmRegs *)CSL_DSS_RCM_U_BASE;
126     CSL_FINS(dssRcmRegs->DSP_PD_CTRL, DSS_RCM_DSP_PD_CTRL_DSP_PD_CTRL_INTERRUPT_MASK, 0x1);
127     CSL_FINS(dssRcmRegs->DSP_PD_CTRL, DSS_RCM_DSP_PD_CTRL_DSP_PD_CTRL_INTERRUPT_MASK, 0x0);
128     CSL_FINS(dssRcmRegs->DSP_PD_CTRL, DSS_RCM_DSP_PD_CTRL_DSP_PD_CTRL_PROC_HALT, 0x0);
131 static void SBL_memInitc66x(void)
133     SBL_RcmStartMeminitDSSL2(RCM_MEMINIT_DSSL2_MEMBANK_ALL);
134     SBL_RcmStartMeminitDSSL3(RCM_MEMINIT_DSSL3_MEMBANK_ALL);
135     SBL_RcmWaitMeminitDSSL2(RCM_MEMINIT_DSSL2_MEMBANK_ALL);
136     SBL_RcmWaitMeminitDSSL3(RCM_MEMINIT_DSSL3_MEMBANK_ALL);
139 static void SBL_memInitTCMACR5(void)
141     SBL_RcmStartMeminitTCMA();
142     SBL_RcmWaitMeminitTCMA();
145 static void SBL_memInitTCMBCR5(void)
147     SBL_RcmStartMeminitTCMB();
148     SBL_RcmWaitMeminitTCMB();
151 void SBL_cr5AUnhalt(CSL_mss_ctrlRegs *mssCtrl)
153     //Core A unhalt
154     CSL_FINS(mssCtrl->R5_COREA_HALT, MSS_CTRL_R5_COREA_HALT_R5_COREA_HALT_HALT, 0x0U);
157 void SBL_cr5BUnhalt(CSL_mss_ctrlRegs *mssCtrl)
159     //Core B unhalt
160     CSL_FINS(mssCtrl->R5_COREB_HALT, MSS_CTRL_R5_COREB_HALT_R5_COREB_HALT_HALT, 0x0);
163 void SBL_localR5CoreTriggerReset(void)
165     CSL_mss_ctrlRegs *mssCtrl = (CSL_mss_ctrlRegs *)CSL_MSS_CTRL_U_BASE;
166     CSL_FINS(mssCtrl->R5_CONTROL, MSS_CTRL_R5_CONTROL_R5_CONTROL_RESET_FSM_TRIGGER, 0x7);
167     asm(" wfi ");
171 static void SBL_dualCoreBoot(CSL_mss_ctrlRegs *mssCtrl, CSL_mss_rcmRegs *rcmRegs)
173     uint32_t regVal;
175     regVal = rcmRegs->RST2ASSERTDLY;
176     CSL_FINS(regVal, MSS_RCM_RST2ASSERTDLY_RST2ASSERTDLY_R5SSA, 0x0);
177     CSL_FINS(regVal, MSS_RCM_RST2ASSERTDLY_RST2ASSERTDLY_R5SSB, 0x0);
178     CSL_FINS(regVal, MSS_RCM_RST2ASSERTDLY_RST2ASSERTDLY_R5A, 0x0);
179     CSL_FINS(regVal, MSS_RCM_RST2ASSERTDLY_RST2ASSERTDLY_R5B, 0x0);
180     rcmRegs->RST2ASSERTDLY = regVal;
182     regVal = rcmRegs->RST_WFICHECK;
183     CSL_FINS(regVal, MSS_RCM_RST_WFICHECK_RST_WFICHECK_R5SSA, 0x7);
184     CSL_FINS(regVal, MSS_RCM_RST_WFICHECK_RST_WFICHECK_R5SSB, 0x7);
185     CSL_FINS(regVal, MSS_RCM_RST_WFICHECK_RST_WFICHECK_R5A, 0x7);
186     CSL_FINS(regVal, MSS_RCM_RST_WFICHECK_RST_WFICHECK_R5B, 0x7);
187     rcmRegs->RST_WFICHECK = regVal;
189     regVal = mssCtrl->R5_CONTROL;
190     CSL_FINS(regVal, MSS_CTRL_R5_CONTROL_R5_CONTROL_LOCK_STEP, 0x0);
191     CSL_FINS(regVal, MSS_CTRL_R5_CONTROL_R5_CONTROL_LOCK_STEP_SWITCH_WAIT, 0x7);
192     mssCtrl->R5_CONTROL = regVal;
197 static void SBL_lockStepBoot(CSL_mss_ctrlRegs *mssCtrl, CSL_mss_rcmRegs *rcmRegs)
199     uint32_t regVal;
201     /* WR_MEM_32(MSS_RCM_U_BASE+RST2ASSERTDLY, 0x0);  */ //RST2ASSERTDLY
202     regVal = rcmRegs->RST2ASSERTDLY;
203     CSL_FINS(regVal, MSS_RCM_RST2ASSERTDLY_RST2ASSERTDLY_R5SSA, 0x0);
204     CSL_FINS(regVal, MSS_RCM_RST2ASSERTDLY_RST2ASSERTDLY_R5SSB, 0x0);
205     CSL_FINS(regVal, MSS_RCM_RST2ASSERTDLY_RST2ASSERTDLY_R5A, 0x0);
206     CSL_FINS(regVal, MSS_RCM_RST2ASSERTDLY_RST2ASSERTDLY_R5B, 0x0);
207     rcmRegs->RST2ASSERTDLY = regVal;
209     /* WR_MEM_32(MSS_RCM_U_BASE+RST_WFICHECK, 0x00000707); */ //RSTWFI CHECK
210     regVal = rcmRegs->RST_WFICHECK;
211     CSL_FINS(regVal, MSS_RCM_RST_WFICHECK_RST_WFICHECK_R5SSA, 0x7);
212     CSL_FINS(regVal, MSS_RCM_RST_WFICHECK_RST_WFICHECK_R5SSB, 0x7);
213     CSL_FINS(regVal, MSS_RCM_RST_WFICHECK_RST_WFICHECK_R5A, 0x7);
214     CSL_FINS(regVal, MSS_RCM_RST_WFICHECK_RST_WFICHECK_R5B, 0x7);
215     rcmRegs->RST_WFICHECK = regVal;
217     regVal = mssCtrl->R5_CONTROL;
218     CSL_FINS(regVal, MSS_CTRL_R5_CONTROL_R5_CONTROL_LOCK_STEP, 0x7);
219     CSL_FINS(regVal, MSS_CTRL_R5_CONTROL_R5_CONTROL_LOCK_STEP_SWITCH_WAIT, 0x7);
220     mssCtrl->R5_CONTROL = regVal;
224 static void SBL_ConfigMcuLockStep(uint8_t enableLockStep)
227     SBL_ADD_PROFILE_POINT;
230     if (enableLockStep)
231     {
232         SBL_log(SBL_LOG_MAX, "SBL_procBootSetProcessorCfg, ProcId 0x%x, enabling Lockstep mode...\n");
233         SBL_lockStepBoot((CSL_mss_ctrlRegs *) CSL_MSS_CTRL_U_BASE , (CSL_mss_rcmRegs *)CSL_MSS_RCM_U_BASE);
235     }
236     else
237     {
238         SBL_log(SBL_LOG_MAX, "SBL_procBootSetProcessorCfg, ProcId 0x%x, enabling split mode...\n");
239         SBL_dualCoreBoot((CSL_mss_ctrlRegs *) CSL_MSS_CTRL_U_BASE , (CSL_mss_rcmRegs *)CSL_MSS_RCM_U_BASE);
240     }
242     SBL_ADD_PROFILE_POINT;
244     return;
247 int32_t SBL_ImageCopy(sblEntryPoint_t *pEntry)
249     int32_t retval = 0;
250     cpu_core_id_t core_id;
252     SBL_ADD_PROFILE_POINT;
254     /* Initialize the entry point array to 0. */
255     for (core_id = SBL_FIRST_CORE_ID; core_id < NUM_CORES; core_id ++)
256         pEntry->CpuEntryPoint[core_id] = SBL_INVALID_ENTRY_ADDR;
258     SBL_ADD_PROFILE_POINT;
260 #if defined(BOOT_UART)
261     if (SBL_UARTBootImage(pEntry) != E_PASS)
262 #elif defined(BOOT_QSPI)
263     if (SBL_QSPIBootImage(pEntry) != E_PASS)
264 #endif
265     {
266         retval = E_FAIL;
267     }
269     SBL_ADD_PROFILE_POINT;
271     return retval;
274 /**
275  * \brief        SBL_SetupCoreMem function sets up the CPUs internal memory
276  *
277  * \param[in]    core_id - CPU ID
278  * \param[in]    pAppEntry - Core info struct
279  *
280  * \return   none
281  */
282 void SBL_SetupCoreMem(uint32_t core_id)
284     uint8_t runLockStep = 0;
286     SBL_ADD_PROFILE_POINT;
288     /* Remap virtual core-ids if needed */
289     switch (core_id)
290     {
291         case MCU1_SMP_ID:
292             runLockStep = 1;
293             core_id = MCU1_CPU0_ID;
294             break;
295         default:
296             break;
297     }
299     if(runLockStep)
300     {
301         SBL_log(SBL_LOG_MAX, "Detected locktep for core_id %d\n", core_id);
302         SBL_ConfigMcuLockStep(SBL_ENABLE_MCU_LOCKSTEP);
303     }
305     switch (core_id)
306     {
307         case DSP1_C66X_ID:
308             SBL_log(SBL_LOG_MAX, "DSP Wakeup... \n");
309             SBL_c66xWakeup();
310             SBL_log(SBL_LOG_MAX, "DSP Meminit... \n");
311             SBL_memInitc66x();
312             break;
313         case MCU1_CPU1_ID:
314             SBL_log(SBL_LOG_MAX, "Switching core id %d to split mode... \n", core_id-1);
315             /* Image for second MCU core present, disable lock step for the cluster */
316             SBL_ConfigMcuLockStep(SBL_DISABLE_MCU_LOCKSTEP);
317             /* DOnt break, fall through for enabling TCMs */
318         case MCU1_CPU0_ID:
319             SBL_memInitTCMACR5();
320             SBL_memInitTCMBCR5();
321             break;
322         default:
323             /* No special memory setup needed */
324             break;
325     }
327     SBL_ADD_PROFILE_POINT;
329     return;
332 /**
333  * \brief    SBL_SlaveCoreBoot function sets the entry point, sets up clocks
334  *           and enable to core to start executing from entry point.
335  *
336  * \param    core_id = Selects a core on the SOC, refer to cpu_core_id_t enum
337  *           freqHz = Speed of core at boot up, 0 indicates use SBL default freqs.
338  *           pAppEntry = SBL entry point struct
339  *
340  **/
341 void SBL_SlaveCoreBoot(cpu_core_id_t core_id, uint32_t freqHz, sblEntryPoint_t *pAppEntry)
343     SBL_ADD_PROFILE_POINT;
345 #if defined(SBL_SKIP_MCU_RESET)
346     /* Finished processing images for all cores, start MCU_0 */
347     if ((core_id == MCU1_CPU1_ID) &&
348         (pAppEntry->CpuEntryPoint[core_id] >=  SBL_INVALID_ENTRY_ADDR))
349     {
350             /* Display profile logs */
351             SBL_printProfileLog();
353             SBL_log(SBL_LOG_MAX, "Starting app, branching to 0x0 \n");
354             /* Branch to start of ATCM */
355             ((void(*)(void))0x0)();
356     }
357 #endif
359     /* Power down and then power up each core*/
360     switch (core_id)
361     {
362         case MCU1_CPU1_ID:
363             /* Display profile logs */
364             SBL_printProfileLog();
366 #ifdef SBL_SKIP_MCU_RESET
367             SBL_log(SBL_LOG_MAX, "Starting app, branching to 0x0 \n");
368             /* Branch to start of ATCM */
369             ((void(*)(void))0x0)();
370 #else
372 #endif
373             break;
375         case MCU1_CPU0_ID:
377             break;
378         case DSP1_C66X_ID:
379             SBL_log(SBL_LOG_MAX, "SBL_procBootReleaseProcessor, ProcId 0x%x...\n", core_id);
380             SBL_c66xStart();
381             SBL_ADD_PROFILE_POINT;
382             break;
383     }
387 cpu_core_id_t SBL_getLocalCoreId(void)
389 #ifndef BUILD_MCU1_0
390 #error "Self Core address assumes SBL runs on MCU1_0"
391 #endif
392     return MCU1_CPU0_ID;
395 static void SBL_DspEntryPointSet(uint32_t entryPoint, uint32_t *pDspInstr)
397     uint32_t entryVal = 0U;
398     uint32_t dspOpcode = 0U;
400     entryVal = (entryPoint & 0x0000FFFF);
401     dspOpcode = *pDspInstr;
402     /*
403     ** Mask and update the lower 16 bits of entry address within the MVK
404     ** instruction opcode.
405     */
406     *pDspInstr = (((dspOpcode) & ~(0x007FFF80)) | (( (entryVal) << 0x7) & 0x007FFF80));
408     entryVal = ((entryPoint & 0xFFFF0000) >> 16);
409     dspOpcode = *(pDspInstr + 1);
410     /*
411     ** Mask and update the upper 16 bits of entry address within the MVK
412     ** instruction opcode.
413     */
414     *(pDspInstr + 1) = (((dspOpcode) & ~(0x007FFF80)) | (( (entryVal) << 0x7) & 0x007FFF80));
417 void SBL_SetDSPResetVec(uint8_t core, uint32_t entry)
419     CSL_dss_ctrlRegs * ptrDSSCTRLRegs = (CSL_dss_ctrlRegs *)CSL_DSS_CTRL_U_BASE;
420     /* TODO Local module reset assert */
422     SBL_DspEntryPointSet(entry, dspInstruction);
424     memcpy((void *) Utils_xlate2LocalAddr(DSP_ENTRY_ADDR, DSP1_C66X_ID), (void *)dspInstruction,
425         sizeof(dspInstruction));
427     CacheP_wbInv((void *) Utils_xlate2LocalAddr(DSP_ENTRY_ADDR, DSP1_C66X_ID), sizeof(dspInstruction));
428     /* Set DSP boot address to trampoline for both Secure and NS mode */
429     CSL_FINS(ptrDSSCTRLRegs->DSS_DSP_BOOTCFG , DSS_CTRL_DSS_DSP_BOOTCFG_DSS_DSP_BOOTCFG_ISTP_RST_VAL, (DSP_ENTRY_ADDR >> 10));
431     /* TODO Local module reset deassert */