462 lines
17 KiB
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;
|
|
}
|
|
}
|