rt-thread/bsp/imxrt/libraries/MIMXRT1170/MIMXRT1176/drivers/fsl_pgmc.c

462 lines
17 KiB
C

/*
* 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;
}
}