diff options
Diffstat (limited to 'bsps/arm/imxrt/mcux-sdk/drivers/snvs_hp')
-rw-r--r-- | bsps/arm/imxrt/mcux-sdk/drivers/snvs_hp/fsl_snvs_hp.c | 565 | ||||
-rw-r--r-- | bsps/arm/imxrt/mcux-sdk/drivers/snvs_hp/fsl_snvs_hp.h | 649 |
2 files changed, 1214 insertions, 0 deletions
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/snvs_hp/fsl_snvs_hp.c b/bsps/arm/imxrt/mcux-sdk/drivers/snvs_hp/fsl_snvs_hp.c new file mode 100644 index 0000000000..485ba01b58 --- /dev/null +++ b/bsps/arm/imxrt/mcux-sdk/drivers/snvs_hp/fsl_snvs_hp.c @@ -0,0 +1,565 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2017-2022 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "fsl_snvs_hp.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.snvs_hp" +#endif + +#define SECONDS_IN_A_DAY (86400U) +#define SECONDS_IN_A_HOUR (3600U) +#define SECONDS_IN_A_MINUTE (60U) +#define DAYS_IN_A_YEAR (365U) +#define YEAR_RANGE_START (1970U) +#define YEAR_RANGE_END (2099U) + +#if !(defined(SNVS_HPSR_PI_MASK)) +#define SNVS_HPSR_PI_MASK (0x2U) +#endif +#if !(defined(SNVS_HPSR_HPTA_MASK)) +#define SNVS_HPSR_HPTA_MASK (0x1U) +#endif + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +/*! + * @brief Checks whether the date and time passed in is valid + * + * @param datetime Pointer to structure where the date and time details are stored + * + * @return Returns false if the date & time details are out of range; true if in range + */ +static bool SNVS_HP_CheckDatetimeFormat(const snvs_hp_rtc_datetime_t *datetime); + +/*! + * @brief Converts time data from datetime to seconds + * + * @param datetime Pointer to datetime structure where the date and time details are stored + * + * @return The result of the conversion in seconds + */ +static uint32_t SNVS_HP_ConvertDatetimeToSeconds(const snvs_hp_rtc_datetime_t *datetime); + +/*! + * @brief Converts time data from seconds to a datetime structure + * + * @param seconds Seconds value that needs to be converted to datetime format + * @param datetime Pointer to the datetime structure where the result of the conversion is stored + */ +static void SNVS_HP_ConvertSecondsToDatetime(uint32_t seconds, snvs_hp_rtc_datetime_t *datetime); + +/*! + * @brief Returns RTC time in seconds. + * + * This function is used internally to get actual RTC time in seconds. + * + * @param base SNVS peripheral base address + * + * @return RTC time in seconds + */ +static uint32_t SNVS_HP_RTC_GetSeconds(SNVS_Type *base); + +#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \ + defined(SNVS_HP_CLOCKS)) +/*! + * @brief Get the SNVS instance from peripheral base address. + * + * @param base SNVS peripheral base address. + * + * @return SNVS instance. + */ +static uint32_t SNVS_HP_GetInstance(SNVS_Type *base); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +/******************************************************************************* + * Variables + ******************************************************************************/ +#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \ + defined(SNVS_HP_CLOCKS)) +/*! @brief Pointer to snvs_hp clock. */ +static const clock_ip_name_t s_snvsHpClock[] = SNVS_HP_CLOCKS; +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +/******************************************************************************* + * Code + ******************************************************************************/ +static bool SNVS_HP_CheckDatetimeFormat(const snvs_hp_rtc_datetime_t *datetime) +{ + assert(datetime != NULL); + + /* Table of days in a month for a non leap year. First entry in the table is not used, + * valid months start from 1 + */ + uint8_t daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U}; + + /* Check year, month, hour, minute, seconds */ + if ((datetime->year < YEAR_RANGE_START) || (datetime->year > YEAR_RANGE_END) || (datetime->month > 12U) || + (datetime->month < 1U) || (datetime->hour >= 24U) || (datetime->minute >= 60U) || (datetime->second >= 60U)) + { + /* If not correct then error*/ + return false; + } + + /* Adjust the days in February for a leap year */ + if ((((datetime->year & 3U) == 0U) && (datetime->year % 100U != 0U)) || (datetime->year % 400U == 0U)) + { + daysPerMonth[2] = 29U; + } + + /* Check the validity of the day */ + if ((datetime->day > daysPerMonth[datetime->month]) || (datetime->day < 1U)) + { + return false; + } + + return true; +} + +static uint32_t SNVS_HP_ConvertDatetimeToSeconds(const snvs_hp_rtc_datetime_t *datetime) +{ + assert(datetime != NULL); + + /* Number of days from begin of the non Leap-year*/ + /* Number of days from begin of the non Leap-year*/ + uint16_t monthDays[] = {0U, 0U, 31U, 59U, 90U, 120U, 151U, 181U, 212U, 243U, 273U, 304U, 334U}; + uint32_t seconds; + + /* Compute number of days from 1970 till given year*/ + seconds = (((uint32_t)datetime->year - 1970U) * DAYS_IN_A_YEAR); + /* Add leap year days */ + seconds += (((uint32_t)datetime->year / 4U) - (1970U / 4U)); + /* Add number of days till given month*/ + seconds += monthDays[datetime->month]; + /* Add days in given month. We subtract the current day as it is + * represented in the hours, minutes and seconds field*/ + seconds += ((uint32_t)datetime->day - 1U); + /* For leap year if month less than or equal to Febraury, decrement day counter*/ + if ((0U == (datetime->year & 3U)) && (datetime->month <= 2U)) + { + seconds--; + } + + seconds = (seconds * SECONDS_IN_A_DAY) + (datetime->hour * SECONDS_IN_A_HOUR) + + (datetime->minute * SECONDS_IN_A_MINUTE) + datetime->second; + + return seconds; +} + +static void SNVS_HP_ConvertSecondsToDatetime(uint32_t seconds, snvs_hp_rtc_datetime_t *datetime) +{ + assert(datetime != NULL); + + uint32_t x; + uint32_t secondsRemaining, days; + uint16_t daysInYear; + /* Table of days in a month for a non leap year. First entry in the table is not used, + * valid months start from 1 + */ + uint8_t daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U}; + + /* Start with the seconds value that is passed in to be converted to date time format */ + secondsRemaining = seconds; + + /* Calcuate the number of days, we add 1 for the current day which is represented in the + * hours and seconds field + */ + days = secondsRemaining / SECONDS_IN_A_DAY + 1U; + + /* Update seconds left*/ + secondsRemaining = secondsRemaining % SECONDS_IN_A_DAY; + + /* Calculate the datetime hour, minute and second fields */ + datetime->hour = (uint8_t)(secondsRemaining / SECONDS_IN_A_HOUR); + secondsRemaining = secondsRemaining % SECONDS_IN_A_HOUR; + datetime->minute = (uint8_t)(secondsRemaining / 60U); + datetime->second = (uint8_t)(secondsRemaining % SECONDS_IN_A_MINUTE); + + /* Calculate year */ + daysInYear = DAYS_IN_A_YEAR; + datetime->year = YEAR_RANGE_START; + while (days > daysInYear) + { + /* Decrease day count by a year and increment year by 1 */ + days -= daysInYear; + datetime->year++; + + /* Adjust the number of days for a leap year */ + if ((datetime->year & 3U) != 0U) + { + daysInYear = DAYS_IN_A_YEAR; + } + else + { + daysInYear = DAYS_IN_A_YEAR + 1U; + } + } + + /* Adjust the days in February for a leap year */ + if (0U == (datetime->year & 3U)) + { + daysPerMonth[2] = 29U; + } + + for (x = 1U; x <= 12U; x++) + { + if (days <= daysPerMonth[x]) + { + datetime->month = (uint8_t)x; + break; + } + else + { + days -= daysPerMonth[x]; + } + } + + datetime->day = (uint8_t)days; +} + +#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \ + defined(SNVS_HP_CLOCKS)) +static uint32_t SNVS_HP_GetInstance(SNVS_Type *base) +{ + return 0U; +} +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ + +/*! + * brief Initialize the SNVS. + * + * note This API should be called at the beginning of the application using the SNVS driver. + * + * param base SNVS peripheral base address + */ +void SNVS_HP_Init(SNVS_Type *base) +{ +#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \ + defined(SNVS_HP_CLOCKS)) + uint32_t instance = SNVS_HP_GetInstance(base); + CLOCK_EnableClock(s_snvsHpClock[instance]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ +} + +/*! + * brief Deinitialize the SNVS. + * + * param base SNVS peripheral base address + */ +void SNVS_HP_Deinit(SNVS_Type *base) +{ +#if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && \ + defined(SNVS_HP_CLOCKS)) + uint32_t instance = SNVS_HP_GetInstance(base); + CLOCK_DisableClock(s_snvsHpClock[instance]); +#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ +} + +/*! + * brief Ungates the SNVS clock and configures the peripheral for basic operation. + * + * note This API should be called at the beginning of the application using the SNVS driver. + * + * param base SNVS peripheral base address + * param config Pointer to the user's SNVS configuration structure. + */ +void SNVS_HP_RTC_Init(SNVS_Type *base, const snvs_hp_rtc_config_t *config) +{ + assert(config != NULL); + + SNVS_HP_Init(base); + + base->HPCOMR |= SNVS_HPCOMR_NPSWA_EN_MASK; + + base->HPCR = (base->HPCR & ~SNVS_HPCR_PI_FREQ_MASK) | SNVS_HPCR_PI_FREQ(config->periodicInterruptFreq); + + if (config->rtcCalEnable) + { + base->HPCR = (base->HPCR & ~SNVS_HPCR_HPCALB_VAL_MASK) | SNVS_HPCR_HPCALB_VAL(config->rtcCalValue); + base->HPCR |= SNVS_HPCR_HPCALB_EN_MASK; + } +} + +/*! + * brief Stops the RTC and SRTC timers. + * + * param base SNVS peripheral base address + */ +void SNVS_HP_RTC_Deinit(SNVS_Type *base) +{ + base->HPCR &= ~SNVS_HPCR_RTC_EN_MASK; + + SNVS_HP_Deinit(base); +} + +/*! + * brief Fills in the SNVS config struct with the default settings. + * + * The default values are as follows. + * code + * config->rtccalenable = false; + * config->rtccalvalue = 0U; + * config->PIFreq = 0U; + * endcode + * param config Pointer to the user's SNVS configuration structure. + */ +void SNVS_HP_RTC_GetDefaultConfig(snvs_hp_rtc_config_t *config) +{ + assert(config != NULL); + + /* Initializes the configure structure to zero. */ + (void)memset(config, 0, sizeof(*config)); + + config->rtcCalEnable = false; + config->rtcCalValue = 0U; + config->periodicInterruptFreq = 0U; +} + +static uint32_t SNVS_HP_RTC_GetSeconds(SNVS_Type *base) +{ + uint32_t seconds = 0; + uint32_t tmp = 0; + + /* Do consecutive reads until value is correct */ + do + { + seconds = tmp; + tmp = (base->HPRTCMR << 17U); + tmp |= (base->HPRTCLR >> 15U); + } while (tmp != seconds); + + return seconds; +} + +/*! + * brief Sets the SNVS RTC date and time according to the given time structure. + * + * param base SNVS peripheral base address + * param datetime Pointer to the structure where the date and time details are stored. + * + * return kStatus_Success: Success in setting the time and starting the SNVS RTC + * kStatus_InvalidArgument: Error because the datetime format is incorrect + */ +status_t SNVS_HP_RTC_SetDatetime(SNVS_Type *base, const snvs_hp_rtc_datetime_t *datetime) +{ + assert(datetime != NULL); + + uint32_t seconds = 0U; + uint32_t tmp = base->HPCR; + + /* disable RTC */ + SNVS_HP_RTC_StopTimer(base); + + /* Return error if the time provided is not valid */ + if (!(SNVS_HP_CheckDatetimeFormat(datetime))) + { + return kStatus_InvalidArgument; + } + + /* Set time in seconds */ + seconds = SNVS_HP_ConvertDatetimeToSeconds(datetime); + + base->HPRTCMR = (uint32_t)(seconds >> 17U); + base->HPRTCLR = (uint32_t)(seconds << 15U); + + /* reenable RTC in case that it was enabled before */ + if ((tmp & SNVS_HPCR_RTC_EN_MASK) != 0U) + { + SNVS_HP_RTC_StartTimer(base); + } + + return kStatus_Success; +} + +/*! + * brief Gets the SNVS RTC time and stores it in the given time structure. + * + * param base SNVS peripheral base address + * param datetime Pointer to the structure where the date and time details are stored. + */ +void SNVS_HP_RTC_GetDatetime(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime) +{ + assert(datetime != NULL); + + SNVS_HP_ConvertSecondsToDatetime(SNVS_HP_RTC_GetSeconds(base), datetime); +} + +/*! + * brief Sets the SNVS RTC alarm time. + * + * The function sets the RTC alarm. It also checks whether the specified alarm time + * is greater than the present time. If not, the function does not set the alarm + * and returns an error. + * + * param base SNVS peripheral base address + * param alarmTime Pointer to the structure where the alarm time is stored. + * + * return kStatus_Success: success in setting the SNVS RTC alarm + * kStatus_InvalidArgument: Error because the alarm datetime format is incorrect + * kStatus_Fail: Error because the alarm time has already passed + */ +status_t SNVS_HP_RTC_SetAlarm(SNVS_Type *base, const snvs_hp_rtc_datetime_t *alarmTime) +{ + assert(alarmTime != NULL); + + uint32_t alarmSeconds = 0U; + uint32_t currSeconds = 0U; + uint32_t tmp = base->HPCR; + + /* Return error if the alarm time provided is not valid */ + if (!(SNVS_HP_CheckDatetimeFormat(alarmTime))) + { + return kStatus_InvalidArgument; + } + + alarmSeconds = SNVS_HP_ConvertDatetimeToSeconds(alarmTime); + currSeconds = SNVS_HP_RTC_GetSeconds(base); + + /* Return error if the alarm time has passed */ + if (alarmSeconds < currSeconds) + { + return kStatus_Fail; + } + + /* disable RTC alarm interrupt */ + base->HPCR &= ~SNVS_HPCR_HPTA_EN_MASK; + while ((base->HPCR & SNVS_HPCR_HPTA_EN_MASK) != 0U) + { + } + + /* Set alarm in seconds*/ + base->HPTAMR = (uint32_t)(alarmSeconds >> 17U); + base->HPTALR = (uint32_t)(alarmSeconds << 15U); + + /* reenable RTC alarm interrupt in case that it was enabled before */ + base->HPCR = tmp; + + return kStatus_Success; +} + +/*! + * brief Returns the SNVS RTC alarm time. + * + * param base SNVS peripheral base address + * param datetime Pointer to the structure where the alarm date and time details are stored. + */ +void SNVS_HP_RTC_GetAlarm(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime) +{ + assert(datetime != NULL); + + uint32_t alarmSeconds = 0U; + + /* Get alarm in seconds */ + alarmSeconds = (base->HPTAMR << 17U); + alarmSeconds |= (base->HPTALR >> 15U); + + SNVS_HP_ConvertSecondsToDatetime(alarmSeconds, datetime); +} + +#if (defined(FSL_FEATURE_SNVS_HAS_SRTC) && (FSL_FEATURE_SNVS_HAS_SRTC > 0)) +/*! + * brief The function synchronizes RTC counter value with SRTC. + * + * param base SNVS peripheral base address + */ +void SNVS_HP_RTC_TimeSynchronize(SNVS_Type *base) +{ + uint32_t tmp = base->HPCR; + + /* disable RTC */ + SNVS_HP_RTC_StopTimer(base); + + base->HPCR |= SNVS_HPCR_HP_TS_MASK; + + /* reenable RTC in case that it was enabled before */ + if ((tmp & SNVS_HPCR_RTC_EN_MASK) != 0U) + { + SNVS_HP_RTC_StartTimer(base); + } +} +#endif /* FSL_FEATURE_SNVS_HAS_SRTC */ + +/*! + * brief Gets the SNVS status flags. + * + * param base SNVS peripheral base address + * + * return The status flags. This is the logical OR of members of the + * enumeration ::snvs_status_flags_t + */ +uint32_t SNVS_HP_RTC_GetStatusFlags(SNVS_Type *base) +{ + uint32_t flags = 0U; + + if ((base->HPSR & SNVS_HPSR_PI_MASK) != 0U) + { + flags |= (uint32_t)kSNVS_RTC_PeriodicInterruptFlag; + } + + if ((base->HPSR & SNVS_HPSR_HPTA_MASK) != 0U) + { + flags |= (uint32_t)kSNVS_RTC_AlarmInterruptFlag; + } + + return flags; +} + +/*! + * brief Gets the enabled SNVS interrupts. + * + * param base SNVS peripheral base address + * + * return The enabled interrupts. This is the logical OR of members of the + * enumeration ::snvs_interrupt_enable_t + */ +uint32_t SNVS_HP_RTC_GetEnabledInterrupts(SNVS_Type *base) +{ + uint32_t val = 0U; + + if ((base->HPCR & SNVS_HPCR_PI_EN_MASK) != 0U) + { + val |= (uint32_t)kSNVS_RTC_PeriodicInterrupt; + } + + if ((base->HPCR & SNVS_HPCR_HPTA_EN_MASK) != 0U) + { + val |= (uint32_t)kSNVS_RTC_AlarmInterrupt; + } + + return val; +} + +#if defined(FSL_FEATURE_SNVS_HAS_SET_LOCK) && (FSL_FEATURE_SNVS_HAS_SET_LOCK > 0) +/*! + * brief Set SNVS HP Set locks. + * + * param base SNVS peripheral base address + * + */ +void SNVS_HP_SetLocks(SNVS_Type *base) +{ + uint32_t sec_config = ((OCOTP_CTRL->HW_OCOTP_OTFAD_CFG3 & OCOTP_CTRL_HW_OCOTP_SEC_CONFIG1_MASK) >> + OCOTP_CTRL_HW_OCOTP_SEC_CONFIG1_SHIFT); + + if (sec_config == SEC_CONFIG_OPEN) + { + /* Enable non-secure SW access */ + base->HPCOMR |= SNVS_HPCOMR_NPSWA_EN(1); + } + + /* Set LP Software Reset Disable lock and ZMK Write Soft Lock */ + base->HPCOMR |= SNVS_HPCOMR_LP_SWR_DIS(1); + base->HPLR |= SNVS_HPLR_ZMK_WSL(1); +} +#endif /* FSL_FEATURE_SNVS_HAS_SET_LOCK */ diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/snvs_hp/fsl_snvs_hp.h b/bsps/arm/imxrt/mcux-sdk/drivers/snvs_hp/fsl_snvs_hp.h new file mode 100644 index 0000000000..713f16b037 --- /dev/null +++ b/bsps/arm/imxrt/mcux-sdk/drivers/snvs_hp/fsl_snvs_hp.h @@ -0,0 +1,649 @@ +/* + * Copyright (c) 2016, Freescale Semiconductor, Inc. + * Copyright 2017-2022, NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FSL_SNVS_HP_H_ +#define _FSL_SNVS_HP_H_ + +#include "fsl_common.h" + +/*! + * @addtogroup snvs_hp + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @name Driver version */ +/*@{*/ +#define FSL_SNVS_HP_DRIVER_VERSION (MAKE_VERSION(2, 3, 2)) /*!< Version 2.3.2 */ +/*@}*/ + +/*! @brief List of SNVS interrupts */ +typedef enum _snvs_hp_interrupts +{ + kSNVS_RTC_AlarmInterrupt = SNVS_HPCR_HPTA_EN_MASK, /*!< RTC time alarm */ + kSNVS_RTC_PeriodicInterrupt = SNVS_HPCR_PI_EN_MASK, /*!< RTC periodic interrupt */ +} snvs_hp_interrupts_t; + +/*! @brief List of SNVS flags */ +typedef enum _snvs_hp_status_flags +{ + kSNVS_RTC_AlarmInterruptFlag = SNVS_HPSR_HPTA_MASK, /*!< RTC time alarm flag */ + kSNVS_RTC_PeriodicInterruptFlag = SNVS_HPSR_PI_MASK, /*!< RTC periodic interrupt flag */ + kSNVS_ZMK_ZeroFlag = (int)SNVS_HPSR_ZMK_ZERO_MASK, /*!< The ZMK is zero */ + kSNVS_OTPMK_ZeroFlag = SNVS_HPSR_OTPMK_ZERO_MASK, /*!< The OTPMK is zero */ +} snvs_hp_status_flags_t; + +/* Re-map Security Violation for RT11xx specific violation*/ +#ifndef SNVS_HPSVSR_SV0_MASK +#define SNVS_HPSVSR_SV0_MASK SNVS_HPSVSR_CAAM_MASK +#endif + +#ifndef SNVS_HPSVSR_SV1_MASK +#define SNVS_HPSVSR_SV1_MASK SNVS_HPSVSR_JTAGC_MASK +#endif + +#ifndef SNVS_HPSVSR_SV2_MASK +#define SNVS_HPSVSR_SV2_MASK SNVS_HPSVSR_WDOG2_MASK +#endif + +#ifndef SNVS_HPSVSR_SV4_MASK +#define SNVS_HPSVSR_SV4_MASK SNVS_HPSVSR_SRC_MASK +#endif + +#ifndef SNVS_HPSVSR_SV5_MASK +#define SNVS_HPSVSR_SV5_MASK SNVS_HPSVSR_OCOTP_MASK +#endif + +/*! @brief List of SNVS security violation flags */ +typedef enum _snvs_hp_sv_status_flags +{ + kSNVS_LP_ViolationFlag = SNVS_HPSVSR_SW_LPSV_MASK, /*!< Low Power section Security Violation */ + kSNVS_ZMK_EccFailFlag = SNVS_HPSVSR_ZMK_ECC_FAIL_MASK, /*!< Zeroizable Master Key Error Correcting Code Check + Failure */ + kSNVS_LP_SoftwareViolationFlag = SNVS_HPSVSR_SW_LPSV_MASK, /*!< LP Software Security Violation */ + kSNVS_FatalSoftwareViolationFlag = SNVS_HPSVSR_SW_FSV_MASK, /*!< Software Fatal Security Violation */ + kSNVS_SoftwareViolationFlag = SNVS_HPSVSR_SW_SV_MASK, /*!< Software Security Violation */ + kSNVS_Violation0Flag = SNVS_HPSVSR_SV0_MASK, /*!< Security Violation 0 */ + kSNVS_Violation1Flag = SNVS_HPSVSR_SV1_MASK, /*!< Security Violation 1 */ + kSNVS_Violation2Flag = SNVS_HPSVSR_SV2_MASK, /*!< Security Violation 2 */ +#if defined(SNVS_HPSVSR_SV3_MASK) + kSNVS_Violation3Flag = SNVS_HPSVSR_SV3_MASK, /*!< Security Violation 3 */ +#endif /* SNVS_HPSVSR_SV3_MASK */ + kSNVS_Violation4Flag = SNVS_HPSVSR_SV4_MASK, /*!< Security Violation 4 */ + kSNVS_Violation5Flag = SNVS_HPSVSR_SV5_MASK, /*!< Security Violation 5 */ +} snvs_hp_sv_status_flags_t; + +/*! + * @brief Macro to make security violation flag + * + * Macro help to make security violation flag kSNVS_Violation0Flag to kSNVS_Violation5Flag, + * For example, SNVS_MAKE_HP_SV_FLAG(0) is kSNVS_Violation0Flag. + */ +#define SNVS_MAKE_HP_SV_FLAG(x) (1U << (SNVS_HPSVSR_SV0_SHIFT + (x))) + +/*! @brief Structure is used to hold the date and time */ +typedef struct _snvs_hp_rtc_datetime +{ + uint16_t year; /*!< Range from 1970 to 2099.*/ + uint8_t month; /*!< Range from 1 to 12.*/ + uint8_t day; /*!< Range from 1 to 31 (depending on month).*/ + uint8_t hour; /*!< Range from 0 to 23.*/ + uint8_t minute; /*!< Range from 0 to 59.*/ + uint8_t second; /*!< Range from 0 to 59.*/ +} snvs_hp_rtc_datetime_t; + +/*! + * @brief SNVS config structure + * + * This structure holds the configuration settings for the SNVS peripheral. To initialize this + * structure to reasonable defaults, call the SNVS_GetDefaultConfig() function and pass a + * pointer to your config structure instance. + * + * The config struct can be made const so it resides in flash + */ +typedef struct _snvs_hp_rtc_config +{ + bool rtcCalEnable; /*!< true: RTC calibration mechanism is enabled; + false:No calibration is used */ + uint32_t rtcCalValue; /*!< Defines signed calibration value for nonsecure RTC; + This is a 5-bit 2's complement value, range from -16 to +15 */ + uint32_t periodicInterruptFreq; /*!< Defines frequency of the periodic interrupt; + Range from 0 to 15 */ +} snvs_hp_rtc_config_t; + +/*! @brief List of SNVS Security State Machine State */ +typedef enum _snvs_hp_ssm_state +{ + kSNVS_SSMInit = 0x00, /*!< Init */ + kSNVS_SSMHardFail = 0x01, /*!< Hard Fail */ + kSNVS_SSMSoftFail = 0x03, /*!< Soft Fail */ + kSNVS_SSMInitInter = 0x08, /*!< Init Intermediate (transition state between Init and Check) */ + kSNVS_SSMCheck = 0x09, /*!< Check */ + kSNVS_SSMNonSecure = 0x0B, /*!< Non-Secure */ + kSNVS_SSMTrusted = 0x0D, /*!< Trusted */ + kSNVS_SSMSecure = 0x0F, /*!< Secure */ +} snvs_hp_ssm_state_t; + +/******************************************************************************* + * API + ******************************************************************************/ + +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @name Initialization and deinitialization + * @{ + */ + +/*! + * @brief Initialize the SNVS. + * + * @note This API should be called at the beginning of the application using the SNVS driver. + * + * @param base SNVS peripheral base address + */ +void SNVS_HP_Init(SNVS_Type *base); + +/*! + * @brief Deinitialize the SNVS. + * + * @param base SNVS peripheral base address + */ +void SNVS_HP_Deinit(SNVS_Type *base); + +/*! + * @brief Ungates the SNVS clock and configures the peripheral for basic operation. + * + * @note This API should be called at the beginning of the application using the SNVS driver. + * + * @param base SNVS peripheral base address + * @param config Pointer to the user's SNVS configuration structure. + */ +void SNVS_HP_RTC_Init(SNVS_Type *base, const snvs_hp_rtc_config_t *config); + +/*! + * @brief Stops the RTC and SRTC timers. + * + * @param base SNVS peripheral base address + */ +void SNVS_HP_RTC_Deinit(SNVS_Type *base); + +/*! + * @brief Fills in the SNVS config struct with the default settings. + * + * The default values are as follows. + * @code + * config->rtccalenable = false; + * config->rtccalvalue = 0U; + * config->PIFreq = 0U; + * @endcode + * @param config Pointer to the user's SNVS configuration structure. + */ +void SNVS_HP_RTC_GetDefaultConfig(snvs_hp_rtc_config_t *config); + +/*! @}*/ + +/*! + * @name Non secure RTC current Time & Alarm + * @{ + */ + +/*! + * @brief Sets the SNVS RTC date and time according to the given time structure. + * + * @param base SNVS peripheral base address + * @param datetime Pointer to the structure where the date and time details are stored. + * + * @return kStatus_Success: Success in setting the time and starting the SNVS RTC + * kStatus_InvalidArgument: Error because the datetime format is incorrect + */ +status_t SNVS_HP_RTC_SetDatetime(SNVS_Type *base, const snvs_hp_rtc_datetime_t *datetime); + +/*! + * @brief Gets the SNVS RTC time and stores it in the given time structure. + * + * @param base SNVS peripheral base address + * @param datetime Pointer to the structure where the date and time details are stored. + */ +void SNVS_HP_RTC_GetDatetime(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime); + +/*! + * @brief Sets the SNVS RTC alarm time. + * + * The function sets the RTC alarm. It also checks whether the specified alarm time + * is greater than the present time. If not, the function does not set the alarm + * and returns an error. + * + * @param base SNVS peripheral base address + * @param alarmTime Pointer to the structure where the alarm time is stored. + * + * @return kStatus_Success: success in setting the SNVS RTC alarm + * kStatus_InvalidArgument: Error because the alarm datetime format is incorrect + * kStatus_Fail: Error because the alarm time has already passed + */ +status_t SNVS_HP_RTC_SetAlarm(SNVS_Type *base, const snvs_hp_rtc_datetime_t *alarmTime); + +/*! + * @brief Returns the SNVS RTC alarm time. + * + * @param base SNVS peripheral base address + * @param datetime Pointer to the structure where the alarm date and time details are stored. + */ +void SNVS_HP_RTC_GetAlarm(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime); + +#if (defined(FSL_FEATURE_SNVS_HAS_SRTC) && (FSL_FEATURE_SNVS_HAS_SRTC > 0)) +/*! + * @brief The function synchronizes RTC counter value with SRTC. + * + * @param base SNVS peripheral base address + */ +void SNVS_HP_RTC_TimeSynchronize(SNVS_Type *base); +#endif /* FSL_FEATURE_SNVS_HAS_SRTC */ + +/*! @}*/ + +/*! + * @name Interrupt Interface + * @{ + */ + +/*! + * @brief Enables the selected SNVS interrupts. + * + * @param base SNVS peripheral base address + * @param mask The interrupts to enable. This is a logical OR of members of the + * enumeration :: _snvs_hp_interrupts_t + */ +static inline void SNVS_HP_RTC_EnableInterrupts(SNVS_Type *base, uint32_t mask) +{ + base->HPCR |= mask; +} + +/*! + * @brief Disables the selected SNVS interrupts. + * + * @param base SNVS peripheral base address + * @param mask The interrupts to disable. This is a logical OR of members of the + * enumeration :: _snvs_hp_interrupts_t + */ +static inline void SNVS_HP_RTC_DisableInterrupts(SNVS_Type *base, uint32_t mask) +{ + base->HPCR &= ~mask; +} + +/*! + * @brief Gets the enabled SNVS interrupts. + * + * @param base SNVS peripheral base address + * + * @return The enabled interrupts. This is the logical OR of members of the + * enumeration :: _snvs_hp_interrupts_t + */ +uint32_t SNVS_HP_RTC_GetEnabledInterrupts(SNVS_Type *base); + +/*! @}*/ + +/*! + * @name Status Interface + * @{ + */ + +/*! + * @brief Gets the SNVS status flags. + * + * @param base SNVS peripheral base address + * + * @return The status flags. This is the logical OR of members of the + * enumeration :: _snvs_hp_status_flags_t + */ +uint32_t SNVS_HP_RTC_GetStatusFlags(SNVS_Type *base); + +/*! + * @brief Clears the SNVS status flags. + * + * @param base SNVS peripheral base address + * @param mask The status flags to clear. This is a logical OR of members of the + * enumeration :: _snvs_hp_status_flags_t + */ +static inline void SNVS_HP_RTC_ClearStatusFlags(SNVS_Type *base, uint32_t mask) +{ + base->HPSR |= mask; +} + +/*! @}*/ + +/*! + * @name Timer Start and Stop + * @{ + */ + +/*! + * @brief Starts the SNVS RTC time counter. + * + * @param base SNVS peripheral base address + */ +static inline void SNVS_HP_RTC_StartTimer(SNVS_Type *base) +{ + base->HPCR |= SNVS_HPCR_RTC_EN_MASK; + while (0U == (base->HPCR & SNVS_HPCR_RTC_EN_MASK)) + { + } +} + +/*! + * @brief Stops the SNVS RTC time counter. + * + * @param base SNVS peripheral base address + */ +static inline void SNVS_HP_RTC_StopTimer(SNVS_Type *base) +{ + base->HPCR &= ~SNVS_HPCR_RTC_EN_MASK; + while ((base->HPCR & SNVS_HPCR_RTC_EN_MASK) != 0U) + { + } +} + +/*! @}*/ + +/*! + * @brief Enable or disable master key selection. + * + * @param base SNVS peripheral base address + * @param enable Pass true to enable, false to disable. + */ +static inline void SNVS_HP_EnableMasterKeySelection(SNVS_Type *base, bool enable) +{ + if (enable) + { + base->HPCOMR |= SNVS_HPCOMR_MKS_EN_MASK; + } + else + { + base->HPCOMR &= (~SNVS_HPCOMR_MKS_EN_MASK); + } +} + +/*! + * @brief Trigger to program Zeroizable Master Key. + * + * @param base SNVS peripheral base address + */ +static inline void SNVS_HP_ProgramZeroizableMasterKey(SNVS_Type *base) +{ + base->HPCOMR |= SNVS_HPCOMR_PROG_ZMK_MASK; +} + +/*! + * @brief Trigger SSM State Transition + * + * Trigger state transition of the system security monitor (SSM). It results only + * the following transitions of the SSM: + * - Check State -> Non-Secure (when Non-Secure Boot and not in Fab Configuration) + * - Check State --> Trusted (when Secure Boot or in Fab Configuration ) + * - Trusted State --> Secure + * - Secure State --> Trusted + * - Soft Fail --> Non-Secure + * + * @param base SNVS peripheral base address + */ +static inline void SNVS_HP_ChangeSSMState(SNVS_Type *base) +{ + base->HPCOMR |= SNVS_HPCOMR_SSM_ST_MASK; +} + +/*! + * @brief Trigger Software Fatal Security Violation + * + * The result SSM state transition is: + * - Check State -> Soft Fail + * - Non-Secure State -> Soft Fail + * - Trusted State -> Soft Fail + * - Secure State -> Soft Fail + * + * @param base SNVS peripheral base address + */ +static inline void SNVS_HP_SetSoftwareFatalSecurityViolation(SNVS_Type *base) +{ + base->HPCOMR |= SNVS_HPCOMR_SW_FSV_MASK; +} + +/*! + * @brief Trigger Software Security Violation + * + * The result SSM state transition is: + * - Check -> Non-Secure + * - Trusted -> Soft Fail + * - Secure -> Soft Fail + * + * @param base SNVS peripheral base address + */ +static inline void SNVS_HP_SetSoftwareSecurityViolation(SNVS_Type *base) +{ + base->HPCOMR |= SNVS_HPCOMR_SW_SV_MASK; +} + +/*! + * @brief Get current SSM State + * + * @param base SNVS peripheral base address + * @return Current SSM state + */ +static inline snvs_hp_ssm_state_t SNVS_HP_GetSSMState(SNVS_Type *base) +{ + return (snvs_hp_ssm_state_t)((uint32_t)((base->HPSR & SNVS_HPSR_SSM_STATE_MASK) >> SNVS_HPSR_SSM_STATE_SHIFT)); +} + +/*! + * @brief Reset the SNVS LP section. + * + * Reset the LP section except SRTC and Time alarm. + * + * @param base SNVS peripheral base address + */ +static inline void SNVS_HP_ResetLP(SNVS_Type *base) +{ + base->HPCOMR |= SNVS_HPCOMR_LP_SWR_MASK; +} + +/*! + * @name High Assurance Counter (HAC) + * @{ + */ + +/*! + * @brief Enable or disable the High Assurance Counter (HAC) + * + * @param base SNVS peripheral base address + * @param enable Pass true to enable, false to disable. + */ +static inline void SNVS_HP_EnableHighAssuranceCounter(SNVS_Type *base, bool enable) +{ + if (enable) + { + base->HPCOMR |= SNVS_HPCOMR_HAC_EN_MASK; + } + else + { + base->HPCOMR &= (~SNVS_HPCOMR_HAC_EN_MASK); + } +} + +/*! + * @brief Start or stop the High Assurance Counter (HAC) + * + * @param base SNVS peripheral base address + * @param start Pass true to start, false to stop. + */ +static inline void SNVS_HP_StartHighAssuranceCounter(SNVS_Type *base, bool start) +{ + if (start) + { + base->HPCOMR &= (~SNVS_HPCOMR_HAC_STOP_MASK); + } + else + { + base->HPCOMR |= SNVS_HPCOMR_HAC_STOP_MASK; + } +} + +/*! + * @brief Set the High Assurance Counter (HAC) initialize value. + * + * @param base SNVS peripheral base address + * @param value The initial value to set. + */ +static inline void SNVS_HP_SetHighAssuranceCounterInitialValue(SNVS_Type *base, uint32_t value) +{ + base->HPHACIVR = value; +} + +/*! + * @brief Load the High Assurance Counter (HAC) + * + * This function loads the HAC initialize value to counter register. + * + * @param base SNVS peripheral base address + */ +static inline void SNVS_HP_LoadHighAssuranceCounter(SNVS_Type *base) +{ + base->HPCOMR |= SNVS_HPCOMR_HAC_LOAD_MASK; +} + +/*! + * @brief Get the current High Assurance Counter (HAC) value + * + * @param base SNVS peripheral base address + * @return HAC currnet value. + */ +static inline uint32_t SNVS_HP_GetHighAssuranceCounter(SNVS_Type *base) +{ + return base->HPHACR; +} + +/*! + * @brief Clear the High Assurance Counter (HAC) + * + * This function can be called in a functional or soft fail state. When the HAC + * is enabled: + * - If the HAC is cleared in the soft fail state, the SSM transitions to the + * hard fail state immediately; + * - If the HAC is cleared in functional state, the SSM will transition to + * hard fail immediately after transitioning to soft fail. + * + * @param base SNVS peripheral base address + */ +static inline void SNVS_HP_ClearHighAssuranceCounter(SNVS_Type *base) +{ + base->HPCOMR |= SNVS_HPCOMR_HAC_CLEAR_MASK; +} + +/*! + * @brief Lock the High Assurance Counter (HAC) + * + * Once locked, the HAC initialize value could not be changed, the HAC enable + * status could not be changed. This could only be unlocked by system reset. + * + * @param base SNVS peripheral base address + */ +static inline void SNVS_HP_LockHighAssuranceCounter(SNVS_Type *base) +{ + base->HPLR |= SNVS_HPLR_HAC_L_MASK; +} + +/*! @}*/ + +/*! + * @brief Get the SNVS HP status flags. + * + * The flags are returned as the OR'ed value f the + * enumeration :: _snvs_hp_status_flags_t. + * + * @param base SNVS peripheral base address + * @return The OR'ed value of status flags. + */ +static inline uint32_t SNVS_HP_GetStatusFlags(SNVS_Type *base) +{ + return base->HPSR; +} + +/*! + * @brief Clear the SNVS HP status flags. + * + * The flags to clear are passed in as the OR'ed value of the + * enumeration :: _snvs_hp_status_flags_t. + * Only these flags could be cleared using this API. + * - @ref kSNVS_RTC_PeriodicInterruptFlag + * - @ref kSNVS_RTC_AlarmInterruptFlag + * + * @param base SNVS peripheral base address + * @param mask OR'ed value of the flags to clear. + */ +static inline void SNVS_HP_ClearStatusFlags(SNVS_Type *base, uint32_t mask) +{ + base->HPSR = mask; +} + +/*! + * @brief Get the SNVS HP security violation status flags. + * + * The flags are returned as the OR'ed value of the + * enumeration :: _snvs_hp_sv_status_flags_t. + * + * @param base SNVS peripheral base address + * @return The OR'ed value of security violation status flags. + */ +static inline uint32_t SNVS_HP_GetSecurityViolationStatusFlags(SNVS_Type *base) +{ + return base->HPSVSR; +} + +/*! + * @brief Clear the SNVS HP security violation status flags. + * + * The flags to clear are passed in as the OR'ed value of the + * enumeration :: _snvs_hp_sv_status_flags_t. + * Only these flags could be cleared using this API. + * + * - @ref kSNVS_ZMK_EccFailFlag + * - @ref kSNVS_Violation0Flag + * - @ref kSNVS_Violation1Flag + * - @ref kSNVS_Violation2Flag + * - kSNVS_Violation3Flag + * - @ref kSNVS_Violation4Flag + * - @ref kSNVS_Violation5Flag + * + * @param base SNVS peripheral base address + * @param mask OR'ed value of the flags to clear. + */ +static inline void SNVS_HP_ClearSecurityViolationStatusFlags(SNVS_Type *base, uint32_t mask) +{ + base->HPSVSR = mask; +} + +#if defined(FSL_FEATURE_SNVS_HAS_SET_LOCK) && (FSL_FEATURE_SNVS_HAS_SET_LOCK > 0) +/*! + * brief Set SNVS HP Set locks. + * + * param base SNVS peripheral base address + * + */ +void SNVS_HP_SetLocks(SNVS_Type *base); +#endif /* FSL_FEATURE_SNVS_HAS_SET_LOCK */ + +#if defined(__cplusplus) +} +#endif + +/*! @}*/ + +#endif /* _FSL_SNVS_HP_H_ */ |