185 lines
4.9 KiB
C
185 lines
4.9 KiB
C
/*
|
|
* Copyright (c) 2024 STMicroelectronics
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* @brief System/hardware module for STM32WB0 processor
|
|
*/
|
|
|
|
#include <zephyr/device.h>
|
|
#include <zephyr/init.h>
|
|
#include <stm32_ll_bus.h>
|
|
#include <stm32_ll_pwr.h>
|
|
#include <stm32_ll_system.h>
|
|
#include <stm32_ll_radio.h>
|
|
#include <zephyr/logging/log.h>
|
|
#include <zephyr/toolchain.h>
|
|
#include <cmsis_core.h>
|
|
#include <stdint.h>
|
|
|
|
#include <system_stm32wb0x.h>
|
|
|
|
#define LOG_LEVEL CONFIG_SOC_LOG_LEVEL
|
|
LOG_MODULE_REGISTER(soc);
|
|
|
|
/**
|
|
* CMSIS System Core Clock: global variable holding the system core clock,
|
|
* which is the frequency supplied to the SysTick timer and processor core.
|
|
*
|
|
* On STM32WB0 series, after RESET, the system clock frequency is 16MHz.
|
|
*/
|
|
uint32_t SystemCoreClock = 16000000U;
|
|
|
|
/**
|
|
* RAM Virtual Register: special structure located at the start
|
|
* of SRAM0; used by the UART bootloader and the Low Power Manager.
|
|
* Data type definition comes from @ref system_stm32wb0xx.h
|
|
*/
|
|
Z_GENERIC_SECTION("stm32wb0_RAM_VR")
|
|
__used RAM_VR_TypeDef RAM_VR;
|
|
|
|
/** Power Controller node */
|
|
#define PWRC DT_INST(0, st_stm32wb0_pwr)
|
|
|
|
/** SMPS modes */
|
|
#define STM32WB0_SMPS_MODE_OFF 0
|
|
#define STM32WB0_SMPS_MODE_PRECHARGE 1
|
|
#define STM32WB0_SMPS_MODE_RUN 2
|
|
|
|
#define SMPS_MODE _CONCAT(STM32WB0_SMPS_MODE_, DT_STRING_UNQUOTED(PWRC, smps_mode))
|
|
|
|
/* Convert DTS properties to LL macros */
|
|
#define SMPS_PRESCALER _CONCAT(LL_RCC_SMPS_DIV_, DT_PROP(PWRC, smps_clock_prescaler))
|
|
|
|
#if SMPS_MODE != STM32WB0_SMPS_MODE_OFF
|
|
BUILD_ASSERT(DT_NODE_HAS_PROP(PWRC, smps_bom),
|
|
"smps-bom must be specified");
|
|
|
|
#define SMPS_BOM \
|
|
_CONCAT(LL_PWR_SMPS_BOM, DT_PROP(PWRC, smps_bom))
|
|
|
|
#define SMPS_LP_MODE \
|
|
COND_CODE_1( \
|
|
DT_PROP(PWRC, smps_lp_floating), \
|
|
(LL_PWR_SMPS_LPOPEN), \
|
|
(LL_PWR_NO_SMPS_LPOPEN))
|
|
|
|
#if defined(PWR_CR5_SMPS_PRECH_CUR_SEL)
|
|
#define SMPS_CURRENT_LIMIT \
|
|
_CONCAT(LL_PWR_SMPS_PRECH_LIMIT_CUR_, \
|
|
DT_STRING_UNQUOTED(PWRC, smps_current_limit))
|
|
#endif /* PWR_CR5_SMPS_PRECH_CUR_SEL */
|
|
|
|
#define SMPS_OUTPUT_VOLTAGE \
|
|
_CONCAT(LL_PWR_SMPS_OUTPUT_VOLTAGE_, \
|
|
DT_STRING_UNQUOTED(PWRC, smps_output_voltage))
|
|
#endif /* SMPS_MODE != STM32WB0_SMPS_MODE_OFF */
|
|
|
|
static void configure_smps(void)
|
|
{
|
|
/* Configure SMPS clock prescaler */
|
|
LL_RCC_SetSMPSPrescaler(SMPS_PRESCALER);
|
|
|
|
#if SMPS_MODE == STM32WB0_SMPS_MODE_OFF
|
|
/* Disable SMPS */
|
|
LL_PWR_SetSMPSMode(LL_PWR_NO_SMPS);
|
|
|
|
while (LL_PWR_IsSMPSReady()) {
|
|
/* Wait for SMPS to turn off */
|
|
}
|
|
#else
|
|
/* Select correct BOM */
|
|
LL_PWR_SetSMPSBOM(SMPS_BOM);
|
|
|
|
/* Configure low-power mode */
|
|
LL_PWR_SetSMPSOpenMode(SMPS_LP_MODE);
|
|
|
|
/* Enable SMPS */
|
|
LL_PWR_SetSMPSMode(LL_PWR_SMPS);
|
|
|
|
while (!LL_PWR_IsSMPSReady()) {
|
|
/* Wait for SMPS to turn on */
|
|
}
|
|
|
|
/* Place SMPS in PRECHARGE (BYPASS) mode.
|
|
* This is required to change SMPS output voltage,
|
|
* so we can do it unconditionally.
|
|
*/
|
|
LL_PWR_SetSMPSPrechargeMode(LL_PWR_SMPS_PRECHARGE);
|
|
while (LL_PWR_IsSMPSinRUNMode()) {
|
|
/* Wait for SMPS to enter PRECHARGE mode */
|
|
}
|
|
|
|
if (SMPS_MODE == STM32WB0_SMPS_MODE_PRECHARGE) {
|
|
#if defined(PWR_CR5_SMPS_PRECH_CUR_SEL)
|
|
/**
|
|
* SMPS should remain in PRECHARGE mode.
|
|
* We still have to configure the output current
|
|
* limit specified in Device Tree, though this
|
|
* can only be done if this SoC supports it.
|
|
*/
|
|
LL_PWR_SetSMPSPrechargeLimitCurrent(SMPS_CURRENT_LIMIT);
|
|
#endif /* PWR_CR5_SMPS_PRECH_CUR_SEL */
|
|
} else {
|
|
/**
|
|
* SMPS mode requested is RUN mode. Configure the output
|
|
* voltage to the desired value then exit PRECHARGE mode.
|
|
*/
|
|
LL_PWR_SMPS_SetOutputVoltageLevel(SMPS_OUTPUT_VOLTAGE);
|
|
|
|
/* Exit PRECHARGE mode (returns in RUN mode) */
|
|
LL_PWR_SetSMPSPrechargeMode(LL_PWR_NO_SMPS_PRECHARGE);
|
|
while (!LL_PWR_IsSMPSinRUNMode()) {
|
|
/* Wait for SMPS to enter RUN mode */
|
|
}
|
|
}
|
|
#endif /* SMPS_MODE == STM32WB0_SMPS_MODE_OFF */
|
|
}
|
|
|
|
/**
|
|
* @brief Perform basic hardware initialization at boot.
|
|
*
|
|
* This needs to be run from the very beginning,
|
|
* so the init priority has to be 0 (zero).
|
|
*
|
|
* @return 0
|
|
*/
|
|
static int stm32wb0_init(void)
|
|
{
|
|
/* Update CMSIS SystemCoreClock variable (CLK_SYS) */
|
|
/* On reset, the 64MHz HSI is selected as input to
|
|
* the SYSCLKPRE prescaler, set to 4, resulting in
|
|
* CLK_SYS being equal to 16MHz.
|
|
*/
|
|
SystemCoreClock = 16000000U;
|
|
|
|
/* Remap address 0 to user flash memory */
|
|
LL_SYSCFG_SetRemapMemory(LL_SYSCFG_REMAP_FLASH);
|
|
|
|
/**
|
|
* Save application exception vector address in RAM_VR.
|
|
* By now, SCB->VTOR should point to _vector_table,
|
|
* so use that value instead of _vector_table directly.
|
|
*/
|
|
RAM_VR.AppBase = SCB->VTOR;
|
|
|
|
/* Enable retention of all RAM banks in Deepstop */
|
|
LL_PWR_EnableRAMBankRet(LL_PWR_RAMRET_1);
|
|
#if defined(LL_PWR_RAMRET_2)
|
|
LL_PWR_EnableRAMBankRet(LL_PWR_RAMRET_2);
|
|
#endif
|
|
#if defined(LL_PWR_RAMRET_3)
|
|
LL_PWR_EnableRAMBankRet(LL_PWR_RAMRET_3);
|
|
#endif
|
|
|
|
/* Configure SMPS step-down converter */
|
|
configure_smps();
|
|
|
|
return 0;
|
|
}
|
|
|
|
SYS_INIT(stm32wb0_init, PRE_KERNEL_1, 0);
|