blob: b38bbaea53ae075869e7b63c5047d4f6eb4e91f4 [file] [log] [blame]
/*
* Copyright (c) 2025 Nuvoton Technology Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/devicetree.h>
#include <zephyr/init.h>
#include <zephyr/cache.h>
#include <zephyr/drivers/clock_control/clock_control_numaker.h>
/* Hardware and starter kit includes. */
#include <NuMicro.h>
static void memory_setup(void)
{
/* Enable SRAM1/2 functions are only available in secure mode. */
if (SCU_IS_CPU_NS(SCU_NS) == 0) {
uint32_t wait_cnt;
/* To assign __HIRC value directly before BSS initialization. */
SystemCoreClock = __HIRC;
wait_cnt = SystemCoreClock;
/* Unlock protected registers */
do {
SYS->REGLCTL = 0x59UL;
SYS->REGLCTL = 0x16UL;
SYS->REGLCTL = 0x88UL;
} while (SYS->REGLCTL == 0UL);
/* Switch SRAM1 to normal power mode */
if (PMC->SYSRB1PC != 0) {
PMC->SYSRB1PC = 0;
}
/* Switch SRAM2 to normal power mode */
if (PMC->SYSRB2PC != 0) {
PMC->SYSRB2PC = 0;
}
/* Wait SRAM1/2 power mode change finish */
while (1) {
if ((PMC->SYSRB1PC & PMC_SYSRB1PC_PCBUSY_Msk) == 0 &&
(PMC->SYSRB2PC & PMC_SYSRB2PC_PCBUSY_Msk) == 0) {
break;
}
if (wait_cnt-- == 0) {
break;
}
}
/* Enable SRAM1/2 clock */
CLK->SRAMCTL |= (CLK_SRAMCTL_SRAM1CKEN_Msk | CLK_SRAMCTL_SRAM2CKEN_Msk);
}
#if (defined(__FPU_PRESENT) && (__FPU_PRESENT == 1U))
/* Enable CP10 & CP11 Full Access */
SCB->CPACR |= ((3U << 10U * 2U) | (3U << 11U * 2U));
/* Set low-power state for PDEPU
* 0b00 | ON, PDEPU is not in low-power state
* 0b01 | ON, but the clock is off
* 0b10 | RET(ention)
* 0b11 | OFF
* Clear ELPSTATE, value is 0b11 on Cold reset
*/
PWRMODCTL->CPDLPSTATE &= ~(PWRMODCTL_CPDLPSTATE_ELPSTATE_Msk <<
PWRMODCTL_CPDLPSTATE_ELPSTATE_Pos);
/* PDEPU ON with clock off, value is 0b01 */
PWRMODCTL->CPDLPSTATE |= 0x1 << PWRMODCTL_CPDLPSTATE_ELPSTATE_Pos;
#endif
/* Enable only if configured to do so. */
SCB_InvalidateICache();
sys_cache_instr_enable();
/* Enable d-cache only if configured to do so. */
SCB_InvalidateDCache();
sys_cache_data_enable();
}
void soc_early_init_hook(void)
{
/* To ensure H/W I/O buffer with correct init data in SRAM,
* to clean D-Cache here to let all .bss & .data flush to SRAM.
*/
#ifdef CONFIG_DCACHE
SCB_CleanDCache();
#endif
SystemInit();
}
void soc_reset_hook(void)
{
memory_setup();
/* Unlock protected registers */
SYS_UnlockReg();
/* Release GPIO hold status */
PMC_RELEASE_GPIO();
/*
* -------------------
* Init System Clock
* -------------------
*/
#if DT_NODE_HAS_PROP(DT_NODELABEL(scc), hxt)
/* Enable/disable 4~24 MHz external crystal oscillator (HXT) */
if (DT_ENUM_IDX(DT_NODELABEL(scc), hxt) == NUMAKER_SCC_CLKSW_ENABLE) {
CLK_EnableXtalRC(CLK_SRCCTL_HXTEN_Msk);
/* Wait for HXT clock ready */
CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk);
} else if (DT_ENUM_IDX(DT_NODELABEL(scc), hxt) == NUMAKER_SCC_CLKSW_DISABLE) {
CLK_DisableXtalRC(CLK_SRCCTL_HXTEN_Msk);
}
#endif
#if DT_NODE_HAS_PROP(DT_NODELABEL(scc), lxt)
/* Enable/disable 32.768 kHz low-speed external crystal oscillator (LXT) */
if (DT_ENUM_IDX(DT_NODELABEL(scc), lxt) == NUMAKER_SCC_CLKSW_ENABLE) {
CLK_EnableXtalRC(CLK_SRCCTL_LXTEN_Msk);
/* Wait for LXT clock ready */
CLK_WaitClockReady(CLK_STATUS_LXTSTB_Msk);
} else if (DT_ENUM_IDX(DT_NODELABEL(scc), lxt) == NUMAKER_SCC_CLKSW_DISABLE) {
CLK_DisableXtalRC(CLK_SRCCTL_LXTEN_Msk);
}
#endif
/* Enable 12 MHz high-speed internal RC oscillator (HIRC) */
CLK_EnableXtalRC(CLK_SRCCTL_HIRCEN_Msk);
/* Wait for HIRC clock ready */
CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);
/* Enable 32 KHz low-speed internal RC oscillator (LIRC) */
CLK_EnableXtalRC(CLK_SRCCTL_LIRCEN_Msk);
/* Wait for LIRC clock ready */
CLK_WaitClockReady(CLK_STATUS_LIRCSTB_Msk);
#if DT_NODE_HAS_PROP(DT_NODELABEL(scc), hirc48m)
/* Enable/disable 48 MHz high-speed internal RC oscillator (HIRC48M) */
if (DT_ENUM_IDX(DT_NODELABEL(scc), hirc48m) == NUMAKER_SCC_CLKSW_ENABLE) {
CLK_EnableXtalRC(CLK_SRCCTL_HIRC48MEN_Msk);
/* Wait for HIRC48M clock ready */
CLK_WaitClockReady(CLK_STATUS_HIRC48MSTB_Msk);
} else if (DT_ENUM_IDX(DT_NODELABEL(scc), hirc48m) == NUMAKER_SCC_CLKSW_DISABLE) {
CLK_DisableXtalRC(CLK_SRCCTL_HIRC48MEN_Msk);
}
#endif
#if DT_NODE_HAS_PROP(DT_NODELABEL(scc), clk_pclkdiv)
/* Set CLK_PCLKDIV register on request */
CLK->PCLKDIV = DT_PROP(DT_NODELABEL(scc), clk_pclkdiv);
#endif
#if DT_NODE_HAS_PROP(DT_NODELABEL(scc), core_clock)
/* Set core clock (HCLK) on request */
CLK_SetCoreClock(DT_PROP(DT_NODELABEL(scc), core_clock));
#endif
/*
* Update System Core Clock
* User can use SystemCoreClockUpdate() to calculate SystemCoreClock.
*/
SystemCoreClockUpdate();
/* Lock protected registers */
SYS_LockReg();
}