diff options
Diffstat (limited to 'bsps/arm/imxrt/mcux-sdk/devices/MIMXRT1166/drivers/fsl_pgmc.c')
-rw-r--r-- | bsps/arm/imxrt/mcux-sdk/devices/MIMXRT1166/drivers/fsl_pgmc.c | 461 |
1 files changed, 461 insertions, 0 deletions
diff --git a/bsps/arm/imxrt/mcux-sdk/devices/MIMXRT1166/drivers/fsl_pgmc.c b/bsps/arm/imxrt/mcux-sdk/devices/MIMXRT1166/drivers/fsl_pgmc.c new file mode 100644 index 0000000000..03488ee4b1 --- /dev/null +++ b/bsps/arm/imxrt/mcux-sdk/devices/MIMXRT1166/drivers/fsl_pgmc.c @@ -0,0 +1,461 @@ +/* + * Copyright 2019-2021, NXP + * All rights reserved. + * + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "fsl_pgmc.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.pgmc" +#endif + +/*! + * @brief The structure of MIF signal. + */ +typedef struct +{ + __IO uint32_t SIGNAL; /*!< MIF MLPL control of each signal. */ + __IO uint32_t DELAY; /*!< MIF Delay of each signal */ + uint32_t RESERVED[2]; +} PGMC_MIF_SIGNAL_Type; + +/******************************************************************************* + * Variables + ******************************************************************************/ + +/******************************************************************************* + * Code + ******************************************************************************/ + +/*! + * brief Makes the BPC module controlled by the target CPU power mode(Such as Wait mode). + * + * This function makes the module controlled by four typical CPU power modes, It also configs the resource domain and + * set memory low power level. + * + * param base PGMC basic power controller base address. + * param mode Target CPU power mode. + * param option The pointer of @ref pgmc_bpc_cpu_power_mode_option_t structure. + */ +void PGMC_BPC_ControlPowerDomainByCpuPowerMode(PGMC_BPC_Type *base, + pgmc_cpu_mode_t mode, + const pgmc_bpc_cpu_power_mode_option_t *option) +{ + assert(option != NULL); + + uint32_t tmp32 = base->BPC_SSAR_SAVE_CTRL; + + base->BPC_MODE = PGMC_BPC_BPC_MODE_DOMAIN_ASSIGN(option->assignDomain) | + PGMC_BPC_BPC_MODE_CTRL_MODE(kPGMC_ControlledByCpuPowerMode); + switch (mode) + { + case kPGMC_RunMode: + tmp32 |= PGMC_BPC_BPC_SSAR_SAVE_CTRL_SAVE_AT_RUN_MASK; + break; + case kPGMC_WaitMode: + if (option->powerOff) + { + base->BPC_POWER_CTRL |= PGMC_BPC_BPC_POWER_CTRL_PWR_OFF_AT_WAIT_MASK; + } + tmp32 |= PGMC_BPC_BPC_SSAR_SAVE_CTRL_SAVE_AT_WAIT_MASK; + break; + case kPGMC_StopMode: + if (option->powerOff) + { + base->BPC_POWER_CTRL |= PGMC_BPC_BPC_POWER_CTRL_PWR_OFF_AT_STOP_MASK; + } + tmp32 |= PGMC_BPC_BPC_SSAR_SAVE_CTRL_SAVE_AT_SUSPEND_MASK; + break; + case kPGMC_SuspendMode: + if (option->powerOff) + { + base->BPC_POWER_CTRL |= PGMC_BPC_BPC_POWER_CTRL_PWR_OFF_AT_SUSPEND_MASK; + } + tmp32 |= PGMC_BPC_BPC_SSAR_SAVE_CTRL_SAVE_AT_SUSPEND_MASK; + break; + default: + assert(false); + break; + } + + if (option->stateSave) + { + base->BPC_SSAR_SAVE_CTRL = tmp32; + } +} + +/*! + * brief Makes the BPC module controlled by the target set points. + * + * This function makes the module controlled by specific set point, It also supports set memory lowe power level. + * + * note When setting more than one set point, use "|" between the map values in @ref _pgmc_setpoint_map. + * + * param base PGMC basic power controller base address. + * param setPointMap Should be the OR'ed value of @ref _pgmc_setpoint_map. + * param option The pointer of @ref pgmc_bpc_setpoint_mode_option_t structure. + */ +void PGMC_BPC_ControlPowerDomainBySetPointMode(PGMC_BPC_Type *base, + uint32_t setPointMap, + const pgmc_bpc_setpoint_mode_option_t *option) +{ + assert(option != NULL); + + setPointMap &= 0xFFFFU; + + base->BPC_MODE = PGMC_BPC_BPC_MODE_CTRL_MODE(kPGMC_ControlledBySetPoint); + if (option->powerOff) + { + base->BPC_POWER_CTRL |= PGMC_BPC_BPC_POWER_CTRL_PWR_OFF_AT_SP(setPointMap); + } + + if (option->stateSave) + { + base->BPC_SSAR_SAVE_CTRL = PGMC_BPC_BPC_SSAR_SAVE_CTRL_SAVE_AT_SP(setPointMap); + } +} + +/*! + * brief Controls the selected power domain by software mode. + * + * note The function is used to control power domain when the CPU is in RUN mode. + * + * param base PGMC basic power controller base address. + * param powerOff Power On/Off power domain in software mode. + * - \b true Power off the power domain in software mode. + * - \b false Power on the power domain in software mode. + */ +void PGMC_BPC_ControlPowerDomainBySoftwareMode(PGMC_BPC_Type *base, bool powerOff) +{ + if (powerOff) + { + base->BPC_POWER_CTRL |= (PGMC_BPC_BPC_POWER_CTRL_PSW_OFF_SOFT_MASK | PGMC_BPC_BPC_POWER_CTRL_ISO_ON_SOFT_MASK); + } + else + { + base->BPC_POWER_CTRL |= (PGMC_BPC_BPC_POWER_CTRL_PSW_ON_SOFT_MASK | PGMC_BPC_BPC_POWER_CTRL_ISO_OFF_SOFT_MASK); + } +} + +/*! + * brief Powers off the CPC core module by the target CPU power mode(Such as Wait mode). + * + * param base CPC CORE module base address. + * param mode Target CPU power mode. + */ +void PGMC_CPC_CORE_PowerOffByCpuPowerMode(PGMC_CPC_Type *base, pgmc_cpu_mode_t mode) +{ + base->CPC_CORE_MODE = PGMC_CPC_CPC_CORE_MODE_CTRL_MODE(kPGMC_ControlledByCpuPowerMode); + switch (mode) + { + case kPGMC_RunMode: + break; + case kPGMC_WaitMode: + base->CPC_CORE_POWER_CTRL |= PGMC_CPC_CPC_CORE_POWER_CTRL_PWR_OFF_AT_WAIT_MASK; + break; + case kPGMC_StopMode: + base->CPC_CORE_POWER_CTRL |= PGMC_CPC_CPC_CORE_POWER_CTRL_PWR_OFF_AT_STOP_MASK; + break; + case kPGMC_SuspendMode: + base->CPC_CORE_POWER_CTRL |= PGMC_CPC_CPC_CORE_POWER_CTRL_PWR_OFF_AT_SUSPEND_MASK; + break; + default: + assert(false); + break; + } +} + +/*! + * brief Makes the CPC CACHE module controlled by the target CPU power mode(Such as Wait mode). + * + * This function makes the module controlled by four typical CPU power modes, it also can set memory low power level. + * + * param base CPC CACHE module base address. + * param mode Target CPU power mode. + * param memoryLowPowerLevel Memory low power level. + */ +void PGMC_CPC_CACHE_ControlByCpuPowerMode(PGMC_CPC_Type *base, + pgmc_cpu_mode_t mode, + pgmc_memory_low_power_level_t memoryLowPowerLevel) +{ + uint32_t temp32; + + base->CPC_CACHE_MODE = PGMC_CPC_CPC_CACHE_MODE_CTRL_MODE(kPGMC_ControlledByCpuPowerMode); + temp32 = base->CPC_CACHE_CM_CTRL; + switch (mode) + { + case kPGMC_RunMode: + temp32 &= ~PGMC_CPC_CPC_CACHE_CM_CTRL_MLPL_AT_RUN_MASK; + base->CPC_CACHE_CM_CTRL = temp32 | PGMC_CPC_CPC_CACHE_CM_CTRL_MLPL_AT_RUN(memoryLowPowerLevel); + break; + case kPGMC_WaitMode: + temp32 &= ~PGMC_CPC_CPC_CACHE_CM_CTRL_MLPL_AT_WAIT_MASK; + base->CPC_CACHE_CM_CTRL = temp32 | PGMC_CPC_CPC_CACHE_CM_CTRL_MLPL_AT_WAIT(memoryLowPowerLevel); + break; + case kPGMC_StopMode: + temp32 &= ~PGMC_CPC_CPC_CACHE_CM_CTRL_MLPL_AT_STOP_MASK; + base->CPC_CACHE_CM_CTRL = temp32 | PGMC_CPC_CPC_CACHE_CM_CTRL_MLPL_AT_STOP(memoryLowPowerLevel); + break; + case kPGMC_SuspendMode: + temp32 &= ~PGMC_CPC_CPC_CACHE_CM_CTRL_MLPL_AT_SUSPEND_MASK; + base->CPC_CACHE_CM_CTRL = temp32 | PGMC_CPC_CPC_CACHE_CM_CTRL_MLPL_AT_SUSPEND(memoryLowPowerLevel); + break; + default: + assert(false); + break; + } +} + +/*! + * brief Makes the CPC CACHE module controlled by the target set points. + * + * This function makes the module controlled by specific set point, It also supports set memory lowe power level. + * + * note When setting more than one set point, use "|" between the map values in @ref _pgmc_setpoint_map. + * + * param base CPC CACHE module base address. + * param setPointMap Should be the OR'ed value of @ref _pgmc_setpoint_map. + * param memoryLowPowerLevel Memory low power level. + */ +void PGMC_CPC_CACHE_ControlBySetPointMode(PGMC_CPC_Type *base, + uint32_t setPointMap, + pgmc_memory_low_power_level_t memoryLowPowerLevel) +{ + uint32_t setPointIndex = 0UL; + uint32_t tmp32 = 0UL; + uint32_t regIndex = 0UL; + volatile uint32_t *ptrMemSpCtrlReg = NULL; + + setPointMap &= 0xFFFFU; + + base->CPC_CACHE_MODE = PGMC_CPC_CPC_CACHE_MODE_CTRL_MODE(kPGMC_ControlledBySetPoint); + + ptrMemSpCtrlReg = &(base->CPC_CACHE_SP_CTRL_0); + for (regIndex = 0UL; regIndex < 2UL; regIndex++) + { + ptrMemSpCtrlReg += regIndex; + tmp32 = *ptrMemSpCtrlReg; + for (setPointIndex = 0UL; setPointIndex < 8UL; setPointIndex++) + { + if (0UL != (setPointMap & (1UL << ((regIndex * 8UL) + setPointIndex)))) + { + tmp32 &= ~((uint32_t)PGMC_CPC_CPC_CACHE_SP_CTRL_0_MLPL_AT_SP0_MASK << (setPointIndex * 4U)); + tmp32 |= ((uint32_t)memoryLowPowerLevel << (setPointIndex * 4U)); + } + } + *ptrMemSpCtrlReg = tmp32; + } +} + +/*! + * brief Requests CPC cache module's memory low power level change by software mode. + * + * note If request memory low power level change, must wait the MLPL transition complete. + * + * param base CPC LMEM module base address. + */ +void PGMC_CPC_CACHE_TriggerMLPLSoftwareChange(PGMC_CPC_Type *base) +{ + base->CPC_CACHE_CM_CTRL |= PGMC_CPC_CPC_CACHE_CM_CTRL_MLPL_SOFT_MASK; + + /* If request software change, check the MLPL transition status. */ + while (0UL != ((base->CPC_CACHE_CM_CTRL) & PGMC_CPC_CPC_CACHE_CM_CTRL_MLPL_SOFT_MASK)) + { + } +} + +/*! + * brief Makes the CPC LMEM module controlled by the target CPU power mode(Such as Wait mode). + * + * This function makes the module controlled by four typical CPU power modes, it also can set memory low power level. + * + * param base CPC LMEM module base address. + * param mode Target CPU power mode. + * param memoryLowPowerLevel Memory low power level. + */ +void PGMC_CPC_LMEM_ControlByCpuPowerMode(PGMC_CPC_Type *base, + pgmc_cpu_mode_t mode, + pgmc_memory_low_power_level_t memoryLowPowerLevel) +{ + uint32_t temp32; + + base->CPC_LMEM_MODE = PGMC_CPC_CPC_LMEM_MODE_CTRL_MODE(kPGMC_ControlledByCpuPowerMode); + + temp32 = base->CPC_LMEM_CM_CTRL; + switch (mode) + { + case kPGMC_RunMode: + temp32 &= ~PGMC_CPC_CPC_LMEM_CM_CTRL_MLPL_AT_RUN_MASK; + base->CPC_LMEM_CM_CTRL = temp32 | PGMC_CPC_CPC_LMEM_CM_CTRL_MLPL_AT_RUN(memoryLowPowerLevel); + break; + case kPGMC_WaitMode: + temp32 &= ~PGMC_CPC_CPC_LMEM_CM_CTRL_MLPL_AT_WAIT_MASK; + base->CPC_LMEM_CM_CTRL = temp32 | PGMC_CPC_CPC_LMEM_CM_CTRL_MLPL_AT_WAIT(memoryLowPowerLevel); + break; + case kPGMC_StopMode: + temp32 &= ~PGMC_CPC_CPC_LMEM_CM_CTRL_MLPL_AT_STOP_MASK; + base->CPC_LMEM_CM_CTRL = temp32 | PGMC_CPC_CPC_LMEM_CM_CTRL_MLPL_AT_STOP(memoryLowPowerLevel); + break; + case kPGMC_SuspendMode: + temp32 &= ~PGMC_CPC_CPC_LMEM_CM_CTRL_MLPL_AT_SUSPEND_MASK; + base->CPC_LMEM_CM_CTRL = temp32 | PGMC_CPC_CPC_LMEM_CM_CTRL_MLPL_AT_SUSPEND(memoryLowPowerLevel); + break; + default: + assert(false); + break; + } +} + +/*! + * brief Makes the CPC LMEM module controlled by the target set points. + * + * This function makes the module controlled by specific set point, It also supports set memory lowe power level. + * + * note When setting more than one set point, use "|" between the map values in @ref _pgmc_setpoint_map. + * + * param base CPC LMEM module base address. + * param setPointMap Should be the OR'ed value of @ref _pgmc_setpoint_map. + * param memoryLowPowerLevel Memory low power level. + */ +void PGMC_CPC_LMEM_ControlBySetPointMode(PGMC_CPC_Type *base, + uint32_t setPointMap, + pgmc_memory_low_power_level_t memoryLowPowerLevel) +{ + uint32_t setPointIndex = 0UL; + uint32_t tmp32 = 0UL; + uint32_t regIndex = 0UL; + volatile uint32_t *ptrMemSpCtrlReg = NULL; + + setPointMap &= 0xFFFFU; + + base->CPC_LMEM_MODE = PGMC_CPC_CPC_LMEM_MODE_CTRL_MODE(kPGMC_ControlledBySetPoint); + + ptrMemSpCtrlReg = &(base->CPC_LMEM_SP_CTRL_0); + for (regIndex = 0UL; regIndex < 2UL; regIndex++) + { + ptrMemSpCtrlReg += regIndex; + tmp32 = *ptrMemSpCtrlReg; + for (setPointIndex = 0UL; setPointIndex < 8UL; setPointIndex++) + { + if (0UL != (setPointMap & (1UL << ((regIndex * 8UL) + setPointIndex)))) + { + tmp32 &= ~((uint32_t)PGMC_CPC_CPC_LMEM_SP_CTRL_0_MLPL_AT_SP0_MASK << (setPointIndex * 4U)); + tmp32 |= ((uint32_t)memoryLowPowerLevel << (setPointIndex * 4U)); + } + } + *ptrMemSpCtrlReg = tmp32; + } +} + +/*! + * brief Requests CPC LMEM module's memory low power level change in software mode. + * + * note If request memory low power level change, must wait the MLPL transition complete. + * + * param base CPC LMEM module base address. + */ +void PGMC_CPC_LMEM_TriggerMLPLSoftwareChange(PGMC_CPC_Type *base) +{ + base->CPC_LMEM_CM_CTRL |= PGMC_CPC_CPC_LMEM_CM_CTRL_MLPL_SOFT_MASK; + + /* If request software change, check the MLPL transition status. */ + while (0UL != ((base->CPC_LMEM_CM_CTRL) & PGMC_CPC_CPC_LMEM_CM_CTRL_MLPL_SOFT_MASK)) + { + } +} + +/*! + * brief Sets the behaviour of each signal(Such as Sleep signal) in MIF. + * + * note To control the memory low power operation, this function must be invoked after selecting the + * memory low power level. + * Use case: + * code + * PGMC_BPC_ControlPowerDomainByCpuPowerMode(PGMC_BPC0_BASE, kPGMC_WaitMode, kPGMC_CM7Core, + * kPGMC_MLPLSleep, false); + * PGMC_MIF_SetSignalBehaviour(PGMC_BPC0_MIF_BASE, kPGMC_MLPLSleep, kPGMC_AssertSleepSignal); + * endcode + * + * param base PGMC MIF peripheral base address. + * param memoryLevel The selected memory low power level. For details please refer to @ref + * pgmc_memory_low_power_level_t. + * param mask The mask of MIF signal behaviour. Should be the OR'ed value of @ref _pgmc_mif_signal_behaviour + */ +void PGMC_MIF_SetSignalBehaviour(PGMC_MIF_Type *base, pgmc_memory_low_power_level_t memoryLevel, uint32_t mask) +{ + uint8_t signalIndex = 0U; + uint32_t temp32 = 0U; + PGMC_MIF_SIGNAL_Type *MIF_SIG = (PGMC_MIF_SIGNAL_Type *)(uint32_t)(&(base->MIF_MLPL_SLEEP)); + + for (signalIndex = 0U; signalIndex < 11U; signalIndex++) + { + temp32 = MIF_SIG[signalIndex].SIGNAL; + temp32 &= ~(1UL << (uint32_t)memoryLevel); + temp32 |= ((uint32_t)(mask & (1UL << signalIndex)) << (uint32_t)memoryLevel); + MIF_SIG[signalIndex].SIGNAL = temp32; + } +} + +/*! + * brief Makes the PMIC module controlled by the target CPU power mode(Such as Wait mode). + * + * param base PMIC module base address. + * param mode Target CPU power mode. + */ +void PGMC_PPC_ControlByCpuPowerMode(PGMC_PPC_Type *base, pgmc_cpu_mode_t mode) +{ + base->PPC_MODE = PGMC_PPC_PPC_MODE_CTRL_MODE(kPGMC_ControlledByCpuPowerMode); + switch (mode) + { + case kPGMC_RunMode: + break; + case kPGMC_WaitMode: + base->PPC_STBY_CM_CTRL |= PGMC_PPC_PPC_STBY_CM_CTRL_STBY_ON_AT_WAIT_MASK; + break; + case kPGMC_StopMode: + base->PPC_STBY_CM_CTRL |= PGMC_PPC_PPC_STBY_CM_CTRL_STBY_ON_AT_STOP_MASK; + break; + case kPGMC_SuspendMode: + base->PPC_STBY_CM_CTRL |= PGMC_PPC_PPC_STBY_CM_CTRL_STBY_ON_AT_SUSPEND_MASK; + break; + default: + assert(false); + break; + } +} + +/*! + * brief Makes the PMIC module controlled by the target set points. + * + * This function makes the module controlled by specific set point, It also supports PMIC standby on. + * + * note When setting more than one set point, use "|" between the map values in @ref _pgmc_setpoint_map. + * + * param base PMIC module base address. + * param setPointMap Should be the OR'ed value of @ref _pgmc_setpoint_map. + * param enableStandby true: PMIC standby on when system enters set point number and system is in standby mode. + * false: PMIC standby on when system enters set point number + */ +void PGMC_PPC_ControlBySetPointMode(PGMC_PPC_Type *base, uint32_t setPointMap, bool enableStandby) +{ + setPointMap &= 0xFFFFU; + + base->PPC_MODE = PGMC_PPC_PPC_MODE_CTRL_MODE(kPGMC_ControlledBySetPoint); + + if (enableStandby) + { + base->PPC_STBY_SP_CTRL = (setPointMap << PGMC_PPC_PPC_STBY_SP_CTRL_STBY_ON_AT_SP_SLEEP_SHIFT); + } + else + { + base->PPC_STBY_SP_CTRL = setPointMap; + } +} |