soc: rt11xx: Enable power management for RT11xx series SOCs
Enables basic power management for the RT11xx series SOCs. The following power saving measures are currently implemented: - system reduces core voltage during sleep - core clock can be gated in deep sleep Signed-off-by: Daniel DeGrasse <daniel.degrasse@nxp.com>
This commit is contained in:
parent
59f9dfae58
commit
19bb8e2ec8
|
@ -15,7 +15,7 @@
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
cpu0: cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-m7";
|
||||
reg = <0>;
|
||||
|
@ -29,7 +29,7 @@
|
|||
arm,num-mpu-regions = <16>;
|
||||
};
|
||||
};
|
||||
cpu@1 {
|
||||
cpu1: cpu@1 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-m4f";
|
||||
reg = <1>;
|
||||
|
|
118
include/dt-bindings/pm/imx_spc.h
Normal file
118
include/dt-bindings/pm/imx_spc.h
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright (c) 2021, NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Setpoint definitions for IMX Set point controller. The SPC uses a series
|
||||
* of set points to determine the clock speeds and states of cores, as well
|
||||
* as which peripherals to gate clocks to. Higher values correspond to more
|
||||
* power saving. See your SOC's datasheet for specifics of what peripherals
|
||||
* have their clocks gated at each set point.
|
||||
*
|
||||
* Set point control is implemented at the soc level (see pm_power_state_set())
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PM_IMX_SPC_H_
|
||||
#define ZEPHYR_INCLUDE_DT_BINDINGS_PM_IMX_SPC_H_
|
||||
|
||||
#define IMX_GPC_RUN 0x0
|
||||
#define IMX_GPC_WAIT 0x1
|
||||
#define IMX_GPC_STOP 0x2
|
||||
#define IMX_GPC_SUSPEND 0x3
|
||||
|
||||
|
||||
#define IMX_SPC_MASK 0xF0
|
||||
#define IMX_SPC_SHIFT 4
|
||||
#define IMX_GPC_MODE_MASK 0xF
|
||||
|
||||
#define IMX_SPC(x) ((x & IMX_SPC_MASK) >> IMX_SPC_SHIFT)
|
||||
#define IMX_GPC_MODE(x) (x & IMX_GPC_MODE_MASK)
|
||||
|
||||
#define IMX_SPC_0 0x00
|
||||
#define IMX_SPC_1 0x10
|
||||
#define IMX_SPC_2 0x20
|
||||
#define IMX_SPC_3 0x30
|
||||
#define IMX_SPC_4 0x40
|
||||
#define IMX_SPC_5 0x50
|
||||
#define IMX_SPC_6 0x60
|
||||
#define IMX_SPC_7 0x70
|
||||
#define IMX_SPC_8 0x80
|
||||
#define IMX_SPC_9 0x90
|
||||
#define IMX_SPC_10 0xA0
|
||||
#define IMX_SPC_11 0xB0
|
||||
#define IMX_SPC_12 0xC0
|
||||
#define IMX_SPC_13 0xD0
|
||||
#define IMX_SPC_14 0xE0
|
||||
#define IMX_SPC_15 0xF0
|
||||
|
||||
|
||||
#define IMX_SPC_SET_POINT_0_RUN (IMX_SPC_0 | IMX_GPC_RUN)
|
||||
#define IMX_SPC_SET_POINT_0_WAIT (IMX_SPC_0 | IMX_GPC_WAIT)
|
||||
#define IMX_SPC_SET_POINT_0_STOP (IMX_SPC_0 | IMX_GPC_STOP)
|
||||
#define IMX_SPC_SET_POINT_0_SUSPEND (IMX_SPC_0 | IMX_GPC_SUSPEND)
|
||||
#define IMX_SPC_SET_POINT_1_RUN (IMX_SPC_1 | IMX_GPC_RUN)
|
||||
#define IMX_SPC_SET_POINT_1_WAIT (IMX_SPC_1 | IMX_GPC_WAIT)
|
||||
#define IMX_SPC_SET_POINT_1_STOP (IMX_SPC_1 | IMX_GPC_STOP)
|
||||
#define IMX_SPC_SET_POINT_1_SUSPEND (IMX_SPC_1 | IMX_GPC_SUSPEND)
|
||||
#define IMX_SPC_SET_POINT_2_RUN (IMX_SPC_2 | IMX_GPC_RUN)
|
||||
#define IMX_SPC_SET_POINT_2_WAIT (IMX_SPC_2 | IMX_GPC_WAIT)
|
||||
#define IMX_SPC_SET_POINT_2_STOP (IMX_SPC_2 | IMX_GPC_STOP)
|
||||
#define IMX_SPC_SET_POINT_2_SUSPEND (IMX_SPC_2 | IMX_GPC_SUSPEND)
|
||||
#define IMX_SPC_SET_POINT_3_RUN (IMX_SPC_3 | IMX_GPC_RUN)
|
||||
#define IMX_SPC_SET_POINT_3_WAIT (IMX_SPC_3 | IMX_GPC_WAIT)
|
||||
#define IMX_SPC_SET_POINT_3_STOP (IMX_SPC_3 | IMX_GPC_STOP)
|
||||
#define IMX_SPC_SET_POINT_3_SUSPEND (IMX_SPC_3 | IMX_GPC_SUSPEND)
|
||||
#define IMX_SPC_SET_POINT_4_RUN (IMX_SPC_4 | IMX_GPC_RUN)
|
||||
#define IMX_SPC_SET_POINT_4_WAIT (IMX_SPC_4 | IMX_GPC_WAIT)
|
||||
#define IMX_SPC_SET_POINT_4_STOP (IMX_SPC_4 | IMX_GPC_STOP)
|
||||
#define IMX_SPC_SET_POINT_4_SUSPEND (IMX_SPC_4 | IMX_GPC_SUSPEND)
|
||||
#define IMX_SPC_SET_POINT_5_RUN (IMX_SPC_5 | IMX_GPC_RUN)
|
||||
#define IMX_SPC_SET_POINT_5_WAIT (IMX_SPC_5 | IMX_GPC_WAIT)
|
||||
#define IMX_SPC_SET_POINT_5_STOP (IMX_SPC_5 | IMX_GPC_STOP)
|
||||
#define IMX_SPC_SET_POINT_5_SUSPEND (IMX_SPC_5 | IMX_GPC_SUSPEND)
|
||||
#define IMX_SPC_SET_POINT_6_RUN (IMX_SPC_6 | IMX_GPC_RUN)
|
||||
#define IMX_SPC_SET_POINT_6_WAIT (IMX_SPC_6 | IMX_GPC_WAIT)
|
||||
#define IMX_SPC_SET_POINT_6_STOP (IMX_SPC_6 | IMX_GPC_STOP)
|
||||
#define IMX_SPC_SET_POINT_6_SUSPEND (IMX_SPC_6 | IMX_GPC_SUSPEND)
|
||||
#define IMX_SPC_SET_POINT_7_RUN (IMX_SPC_7 | IMX_GPC_RUN)
|
||||
#define IMX_SPC_SET_POINT_7_WAIT (IMX_SPC_7 | IMX_GPC_WAIT)
|
||||
#define IMX_SPC_SET_POINT_7_STOP (IMX_SPC_7 | IMX_GPC_STOP)
|
||||
#define IMX_SPC_SET_POINT_7_SUSPEND (IMX_SPC_7 | IMX_GPC_SUSPEND)
|
||||
#define IMX_SPC_SET_POINT_8_RUN (IMX_SPC_8 | IMX_GPC_RUN)
|
||||
#define IMX_SPC_SET_POINT_8_WAIT (IMX_SPC_8 | IMX_GPC_WAIT)
|
||||
#define IMX_SPC_SET_POINT_8_STOP (IMX_SPC_8 | IMX_GPC_STOP)
|
||||
#define IMX_SPC_SET_POINT_8_SUSPEND (IMX_SPC_8 | IMX_GPC_SUSPEND)
|
||||
#define IMX_SPC_SET_POINT_9_RUN (IMX_SPC_9 | IMX_GPC_RUN)
|
||||
#define IMX_SPC_SET_POINT_9_WAIT (IMX_SPC_9 | IMX_GPC_WAIT)
|
||||
#define IMX_SPC_SET_POINT_9_STOP (IMX_SPC_9 | IMX_GPC_STOP)
|
||||
#define IMX_SPC_SET_POINT_9_SUSPEND (IMX_SPC_9 | IMX_GPC_SUSPEND)
|
||||
#define IMX_SPC_SET_POINT_10_RUN (IMX_SPC_10 | IMX_GPC_RUN)
|
||||
#define IMX_SPC_SET_POINT_10_WAIT (IMX_SPC_10 | IMX_GPC_WAIT)
|
||||
#define IMX_SPC_SET_POINT_10_STOP (IMX_SPC_10 | IMX_GPC_STOP)
|
||||
#define IMX_SPC_SET_POINT_10_SUSPEND (IMX_SPC_10 | IMX_GPC_SUSPEND)
|
||||
#define IMX_SPC_SET_POINT_11_RUN (IMX_SPC_11 | IMX_GPC_RUN)
|
||||
#define IMX_SPC_SET_POINT_11_WAIT (IMX_SPC_11 | IMX_GPC_WAIT)
|
||||
#define IMX_SPC_SET_POINT_11_STOP (IMX_SPC_11 | IMX_GPC_STOP)
|
||||
#define IMX_SPC_SET_POINT_11_SUSPEND (IMX_SPC_11 | IMX_GPC_SUSPEND)
|
||||
#define IMX_SPC_SET_POINT_12_RUN (IMX_SPC_12 | IMX_GPC_RUN)
|
||||
#define IMX_SPC_SET_POINT_12_WAIT (IMX_SPC_12 | IMX_GPC_WAIT)
|
||||
#define IMX_SPC_SET_POINT_12_STOP (IMX_SPC_12 | IMX_GPC_STOP)
|
||||
#define IMX_SPC_SET_POINT_12_SUSPEND (IMX_SPC_12 | IMX_GPC_SUSPEND)
|
||||
#define IMX_SPC_SET_POINT_13_RUN (IMX_SPC_13 | IMX_GPC_RUN)
|
||||
#define IMX_SPC_SET_POINT_13_WAIT (IMX_SPC_13 | IMX_GPC_WAIT)
|
||||
#define IMX_SPC_SET_POINT_13_STOP (IMX_SPC_13 | IMX_GPC_STOP)
|
||||
#define IMX_SPC_SET_POINT_13_SUSPEND (IMX_SPC_13 | IMX_GPC_SUSPEND)
|
||||
#define IMX_SPC_SET_POINT_14_RUN (IMX_SPC_14 | IMX_GPC_RUN)
|
||||
#define IMX_SPC_SET_POINT_14_WAIT (IMX_SPC_14 | IMX_GPC_WAIT)
|
||||
#define IMX_SPC_SET_POINT_14_STOP (IMX_SPC_14 | IMX_GPC_STOP)
|
||||
#define IMX_SPC_SET_POINT_14_SUSPEND (IMX_SPC_14 | IMX_GPC_SUSPEND)
|
||||
#define IMX_SPC_SET_POINT_15_RUN (IMX_SPC_15 | IMX_GPC_RUN)
|
||||
#define IMX_SPC_SET_POINT_15_WAIT (IMX_SPC_15 | IMX_GPC_WAIT)
|
||||
#define IMX_SPC_SET_POINT_15_STOP (IMX_SPC_15 | IMX_GPC_STOP)
|
||||
#define IMX_SPC_SET_POINT_15_SUSPEND (IMX_SPC_15 | IMX_GPC_SUSPEND)
|
||||
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PM_IMX_SPC_H_ */
|
|
@ -21,6 +21,10 @@ if(CONFIG_DEVICE_CONFIGURATION_DATA)
|
|||
set(boot_hdr_dcd_data_section ".boot_hdr.dcd_data")
|
||||
endif()
|
||||
|
||||
if(CONFIG_PM)
|
||||
zephyr_sources_ifdef(CONFIG_SOC_SERIES_IMX_RT11XX power_rt11xx.c)
|
||||
endif()
|
||||
|
||||
zephyr_linker_section_configure(
|
||||
SECTION .rom_start
|
||||
INPUT ".boot_hdr.ivt"
|
||||
|
|
331
soc/arm/nxp_imx/rt/power_rt11xx.c
Normal file
331
soc/arm/nxp_imx/rt/power_rt11xx.c
Normal file
|
@ -0,0 +1,331 @@
|
|||
/*
|
||||
* Copyright (c) 2021, NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <zephyr.h>
|
||||
#include <device.h>
|
||||
#include <pm/pm.h>
|
||||
#include <fsl_dcdc.h>
|
||||
#include <fsl_gpc.h>
|
||||
#include <dt-bindings/pm/imx_spc.h>
|
||||
#include "power_rt11xx.h"
|
||||
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL);
|
||||
|
||||
/*
|
||||
* NOTE: When multicore support in RT1170/1160 is properly implemented,
|
||||
* power saving will improve when both cores request a transition to a low
|
||||
* power mode
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_CPU_CORTEX_M7
|
||||
#define GPC_CPU_MODE_CTRL GPC_CPU_MODE_CTRL_0
|
||||
#elif CONFIG_CPU_CORTEX_M4
|
||||
#define GPC_CPU_MODE_CTRL GPC_CPU_MODE_CTRL_1
|
||||
#else
|
||||
#error "RT11xx power code supports M4 and M7 cores only"
|
||||
#endif
|
||||
|
||||
/* Configure the set point mappings for Cortex M4 and M7 cores */
|
||||
static void gpc_set_core_mappings(void)
|
||||
{
|
||||
uint8_t i, j;
|
||||
uint32_t tmp;
|
||||
|
||||
#ifdef CONFIG_CPU_CORTEX_M7
|
||||
uint8_t mapping[SET_POINT_COUNT][SET_POINT_COUNT] = CPU0_COMPATIBLE_SP_TABLE;
|
||||
#elif CONFIG_CPU_CORTEX_M4
|
||||
uint8_t mapping[SET_POINT_COUNT][SET_POINT_COUNT] = CPU1_COMPATIBLE_SP_TABLE;
|
||||
#else
|
||||
#error "RT11xx power code supports M4 and M7 cores only"
|
||||
#endif
|
||||
/* Cortex Set point mappings */
|
||||
for (i = 0; i < SET_POINT_COUNT; i++) {
|
||||
tmp = 0x0;
|
||||
for (j = 0; j < SET_POINT_COUNT; j++) {
|
||||
tmp |= mapping[i][j] << mapping[0][j];
|
||||
}
|
||||
GPC_CM_SetSetPointMapping(GPC_CPU_MODE_CTRL, mapping[i][0], tmp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure GPC transition steps to enabled */
|
||||
static void gpc_set_transition_flow(void)
|
||||
{
|
||||
gpc_tran_step_config_t step_cfg;
|
||||
|
||||
step_cfg.enableStep = true;
|
||||
step_cfg.cntMode = kGPC_StepCounterDisableMode;
|
||||
|
||||
/* Cortex M7 */
|
||||
GPC_CM_ConfigCpuModeTransitionStep(GPC_CPU_MODE_CTRL,
|
||||
kGPC_CM_SleepSsar, &step_cfg);
|
||||
GPC_CM_ConfigCpuModeTransitionStep(GPC_CPU_MODE_CTRL,
|
||||
kGPC_CM_SleepLpcg, &step_cfg);
|
||||
GPC_CM_ConfigCpuModeTransitionStep(GPC_CPU_MODE_CTRL,
|
||||
kGPC_CM_SleepPll, &step_cfg);
|
||||
GPC_CM_ConfigCpuModeTransitionStep(GPC_CPU_MODE_CTRL,
|
||||
kGPC_CM_SleepIso, &step_cfg);
|
||||
GPC_CM_ConfigCpuModeTransitionStep(GPC_CPU_MODE_CTRL,
|
||||
kGPC_CM_SleepReset, &step_cfg);
|
||||
GPC_CM_ConfigCpuModeTransitionStep(GPC_CPU_MODE_CTRL,
|
||||
kGPC_CM_SleepPower, &step_cfg);
|
||||
GPC_CM_ConfigCpuModeTransitionStep(GPC_CPU_MODE_CTRL,
|
||||
kGPC_CM_WakeupPower, &step_cfg);
|
||||
GPC_CM_ConfigCpuModeTransitionStep(GPC_CPU_MODE_CTRL,
|
||||
kGPC_CM_WakeupReset, &step_cfg);
|
||||
GPC_CM_ConfigCpuModeTransitionStep(GPC_CPU_MODE_CTRL,
|
||||
kGPC_CM_WakeupIso, &step_cfg);
|
||||
GPC_CM_ConfigCpuModeTransitionStep(GPC_CPU_MODE_CTRL,
|
||||
kGPC_CM_WakeupPll, &step_cfg);
|
||||
GPC_CM_ConfigCpuModeTransitionStep(GPC_CPU_MODE_CTRL,
|
||||
kGPC_CM_WakeupLpcg, &step_cfg);
|
||||
GPC_CM_ConfigCpuModeTransitionStep(GPC_CPU_MODE_CTRL,
|
||||
kGPC_CM_WakeupSsar, &step_cfg);
|
||||
|
||||
/* Enable all steps in flow of set point transition */
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_SsarSave, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_LpcgOff, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_GroupDown, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_RootDown, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_PllOff, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_IsoOn, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_ResetEarly, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_PowerOff, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_BiasOff, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_BandgapPllLdoOff, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_LdoPre, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_DcdcDown, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_DcdcUp, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_LdoPost, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_BandgapPllLdoOn, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_BiasOn, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_PowerOn, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_ResetLate, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_IsoOff, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_PllOn, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_RootUp, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_GroupUp, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_LpcgOn, &step_cfg);
|
||||
GPC_SP_ConfigSetPointTransitionStep(GPC_SET_POINT_CTRL,
|
||||
kGPC_SP_SsarRestore, &step_cfg);
|
||||
|
||||
/* Enable all steps in standby transition */
|
||||
GPC_STBY_ConfigStandbyTransitionStep(GPC_STBY_CTRL,
|
||||
kGPC_STBY_LpcgIn, &step_cfg);
|
||||
GPC_STBY_ConfigStandbyTransitionStep(GPC_STBY_CTRL,
|
||||
kGPC_STBY_PllIn, &step_cfg);
|
||||
GPC_STBY_ConfigStandbyTransitionStep(GPC_STBY_CTRL,
|
||||
kGPC_STBY_BiasIn, &step_cfg);
|
||||
GPC_STBY_ConfigStandbyTransitionStep(GPC_STBY_CTRL,
|
||||
kGPC_STBY_PldoIn, &step_cfg);
|
||||
GPC_STBY_ConfigStandbyTransitionStep(GPC_STBY_CTRL,
|
||||
kGPC_STBY_BandgapIn, &step_cfg);
|
||||
GPC_STBY_ConfigStandbyTransitionStep(GPC_STBY_CTRL,
|
||||
kGPC_STBY_LdoIn, &step_cfg);
|
||||
GPC_STBY_ConfigStandbyTransitionStep(GPC_STBY_CTRL,
|
||||
kGPC_STBY_DcdcIn, &step_cfg);
|
||||
GPC_STBY_ConfigStandbyTransitionStep(GPC_STBY_CTRL,
|
||||
kGPC_STBY_PmicIn, &step_cfg);
|
||||
GPC_STBY_ConfigStandbyTransitionStep(GPC_STBY_CTRL,
|
||||
kGPC_STBY_PmicOut, &step_cfg);
|
||||
GPC_STBY_ConfigStandbyTransitionStep(GPC_STBY_CTRL,
|
||||
kGPC_STBY_DcdcOut, &step_cfg);
|
||||
GPC_STBY_ConfigStandbyTransitionStep(GPC_STBY_CTRL,
|
||||
kGPC_STBY_LdoOut, &step_cfg);
|
||||
GPC_STBY_ConfigStandbyTransitionStep(GPC_STBY_CTRL,
|
||||
kGPC_STBY_BandgapOut, &step_cfg);
|
||||
GPC_STBY_ConfigStandbyTransitionStep(GPC_STBY_CTRL,
|
||||
kGPC_STBY_PldoOut, &step_cfg);
|
||||
GPC_STBY_ConfigStandbyTransitionStep(GPC_STBY_CTRL,
|
||||
kGPC_STBY_BiasOut, &step_cfg);
|
||||
GPC_STBY_ConfigStandbyTransitionStep(GPC_STBY_CTRL,
|
||||
kGPC_STBY_PllOut, &step_cfg);
|
||||
GPC_STBY_ConfigStandbyTransitionStep(GPC_STBY_CTRL,
|
||||
kGPC_STBY_LpcgOut, &step_cfg);
|
||||
}
|
||||
|
||||
static void gpc_configure_interrupts(void)
|
||||
{
|
||||
uint8_t i;
|
||||
uint32_t irq = DT_IRQN(DT_INST(0, nxp_gpt_hw_timer));
|
||||
|
||||
/* Disable all GPC interrupt sources */
|
||||
for (i = 0; i < GPC_CPU_MODE_CTRL_CM_IRQ_WAKEUP_MASK_COUNT; i++) {
|
||||
GPC_CPU_MODE_CTRL->CM_IRQ_WAKEUP_MASK[i] |= 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* Enable GPT interrupt source for GPC- this is system timer */
|
||||
GPC_CM_EnableIrqWakeup(GPC_CPU_MODE_CTRL, irq, true);
|
||||
}
|
||||
|
||||
/* Initializes configuration for the GPC */
|
||||
static void gpc_init(void)
|
||||
{
|
||||
/* Setup GPC set point mappings */
|
||||
gpc_set_core_mappings();
|
||||
/* Setup GPC set point transition flow */
|
||||
gpc_set_transition_flow();
|
||||
/* Allow GPC to disable ROSC */
|
||||
GPC_SET_POINT_CTRL->SP_ROSC_CTRL = ~OSC_RC_16M_STBY_VAL;
|
||||
/* Setup GPC interrupts */
|
||||
gpc_configure_interrupts();
|
||||
}
|
||||
|
||||
/* Initializes DCDC converter with power saving settings */
|
||||
static void dcdc_init(void)
|
||||
{
|
||||
dcdc_config_t dcdc_config;
|
||||
dcdc_setpoint_config_t dcdc_setpoint_config;
|
||||
|
||||
dcdc_buck_mode_1P8_target_vol_t buck1_8_voltage[16] =
|
||||
DCDC_1P8_BUCK_MODE_CONFIGURATION_TABLE;
|
||||
dcdc_buck_mode_1P0_target_vol_t buck1_0_voltage[16] =
|
||||
DCDC_1P0_BUCK_MODE_CONFIGURATION_TABLE;
|
||||
dcdc_standby_mode_1P8_target_vol_t standby1_8_voltage[16] =
|
||||
DCDC_1P8_STANDBY_MODE_CONFIGURATION_TABLE;
|
||||
dcdc_standby_mode_1P0_target_vol_t standby1_0_voltage[16] =
|
||||
DCDC_1P0_STANDBY_MODE_CONFIGURATION_TABLE;
|
||||
|
||||
|
||||
DCDC_BootIntoDCM(DCDC);
|
||||
|
||||
dcdc_setpoint_config.enableDCDCMap = DCDC_ONOFF_SP_VAL;
|
||||
dcdc_setpoint_config.enableDigLogicMap = DCDC_DIG_ONOFF_SP_VAL;
|
||||
dcdc_setpoint_config.lowpowerMap = DCDC_LP_MODE_SP_VAL;
|
||||
dcdc_setpoint_config.standbyMap = DCDC_ONOFF_STBY_VAL;
|
||||
dcdc_setpoint_config.standbyLowpowerMap = DCDC_LP_MODE_STBY_VAL;
|
||||
dcdc_setpoint_config.buckVDD1P8TargetVoltage = buck1_8_voltage;
|
||||
dcdc_setpoint_config.buckVDD1P0TargetVoltage = buck1_0_voltage;
|
||||
dcdc_setpoint_config.standbyVDD1P8TargetVoltage = standby1_8_voltage;
|
||||
dcdc_setpoint_config.standbyVDD1P0TargetVoltage = standby1_0_voltage;
|
||||
DCDC_SetPointInit(DCDC, &dcdc_setpoint_config);
|
||||
|
||||
DCDC_GetDefaultConfig(&dcdc_config);
|
||||
dcdc_config.controlMode = kDCDC_SetPointControl;
|
||||
DCDC_Init(DCDC, &dcdc_config);
|
||||
}
|
||||
|
||||
static void system_enter_sleep(gpc_cpu_mode_t gpc_mode)
|
||||
{
|
||||
__ASSERT_NO_MSG(gpc_mode != kGPC_RunMode);
|
||||
|
||||
if (gpc_mode == kGPC_WaitMode) {
|
||||
/* Clear SLEEPDEEP bit to enter WAIT mode*/
|
||||
SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
|
||||
} else {
|
||||
/* Set SLEEPDEEP bit to enter STOP mode */
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
||||
}
|
||||
/* When this function is entered the Kernel has disabled
|
||||
* interrupts using BASEPRI register. We will clear BASEPRI, and use PRIMASK
|
||||
* to disable interrupts, so that the WFI instruction works correctly.
|
||||
*/
|
||||
|
||||
/* Set PRIMASK */
|
||||
__disable_irq();
|
||||
/* Set BASEPRI to 0 */
|
||||
irq_unlock(0);
|
||||
|
||||
/* WFI instruction will start entry into WAIT/STOP mode */
|
||||
LOG_DBG("Entering LPM via WFI");
|
||||
__WFI();
|
||||
}
|
||||
|
||||
void cpu_mode_transition(gpc_cpu_mode_t mode, bool enable_standby)
|
||||
{
|
||||
GPC_CM_SetNextCpuMode(GPC_CPU_MODE_CTRL, mode);
|
||||
GPC_CM_EnableCpuSleepHold(GPC_CPU_MODE_CTRL, true);
|
||||
|
||||
/* Mask debugger wakeup */
|
||||
GPC_CPU_MODE_CTRL->CM_NON_IRQ_WAKEUP_MASK |=
|
||||
GPC_CPU_MODE_CTRL_CM_NON_IRQ_WAKEUP_MASK_EVENT_WAKEUP_MASK_MASK |
|
||||
GPC_CPU_MODE_CTRL_CM_NON_IRQ_WAKEUP_MASK_DEBUG_WAKEUP_MASK_MASK;
|
||||
|
||||
if (enable_standby) {
|
||||
/* Set standby request */
|
||||
GPC_CM_RequestStandbyMode(GPC_CPU_MODE_CTRL, mode);
|
||||
} else {
|
||||
/* Clear standby request */
|
||||
GPC_CM_ClearStandbyModeRequest(GPC_CPU_MODE_CTRL, mode);
|
||||
}
|
||||
|
||||
/* Execute WFI- GPC will receive sleep request from CPU */
|
||||
system_enter_sleep(mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* SOC specific low power mode implementation
|
||||
* Drop to lowest power state possible given system's request
|
||||
*/
|
||||
__weak void pm_power_state_set(struct pm_state_info info)
|
||||
{
|
||||
/* Extract set point and GPC mode from the substate ID */
|
||||
uint8_t set_point = IMX_SPC(info.substate_id);
|
||||
gpc_cpu_mode_t gpc_mode = IMX_GPC_MODE(info.substate_id);
|
||||
uint8_t current_set_point = GPC_SP_GetCurrentSetPoint(GPC_SET_POINT_CTRL);
|
||||
|
||||
LOG_DBG("Switch to Set Point %d, GPC Mode %d requested", set_point, gpc_mode);
|
||||
if (gpc_mode != kGPC_RunMode && (current_set_point != set_point)) {
|
||||
/* Request set point transition at sleep */
|
||||
GPC_CM_RequestSleepModeSetPointTransition(GPC_CPU_MODE_CTRL,
|
||||
set_point, set_point, kGPC_CM_RequestPreviousSetpoint);
|
||||
cpu_mode_transition(gpc_mode, true);
|
||||
} else if (gpc_mode != kGPC_RunMode) {
|
||||
/* Request CPU mode transition without set mode transition */
|
||||
GPC_CM_RequestRunModeSetPointTransition(GPC_CPU_MODE_CTRL,
|
||||
current_set_point);
|
||||
cpu_mode_transition(gpc_mode, true);
|
||||
}
|
||||
}
|
||||
|
||||
__weak void pm_power_state_exit_post_ops(struct pm_state_info info)
|
||||
{
|
||||
ARG_UNUSED(info);
|
||||
/* Clear PRIMASK */
|
||||
__enable_irq();
|
||||
LOG_DBG("Exiting LPM");
|
||||
LOG_DBG("CM7 mode was %d", GPC_CM_GetPreviousCpuMode(GPC_CPU_MODE_CTRL_0));
|
||||
LOG_DBG("CM4 mode was %d", GPC_CM_GetPreviousCpuMode(GPC_CPU_MODE_CTRL_1));
|
||||
LOG_DBG("Previous set point was %d", GPC_SP_GetPreviousSetPoint(GPC_SET_POINT_CTRL));
|
||||
}
|
||||
|
||||
/* Initialize RT11xx Power */
|
||||
static int rt11xx_power_init(const struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
/* Drop SOC target voltage to 1.0 V */
|
||||
DCDC_SetVDD1P0BuckModeTargetVoltage(DCDC, kDCDC_1P0BuckTarget1P0V);
|
||||
/* Initialize general power controller */
|
||||
gpc_init();
|
||||
/* Initialize dcdc */
|
||||
dcdc_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(rt11xx_power_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
|
179
soc/arm/nxp_imx/rt/power_rt11xx.h
Normal file
179
soc/arm/nxp_imx/rt/power_rt11xx.h
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Copyright (c) 2021, NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _SOC_ARM_NXP_IMX_RT_POWER_RT11XX_H_
|
||||
#define _SOC_ARM_NXP_IMX_RT_POWER_RT11XX_H_
|
||||
|
||||
/*
|
||||
* Set point configurations. These are kept in a seprate file for readability.
|
||||
*/
|
||||
|
||||
#define SP0 0
|
||||
#define SP1 1
|
||||
#define SP2 2
|
||||
#define SP3 3
|
||||
#define SP4 4
|
||||
#define SP5 5
|
||||
#define SP6 6
|
||||
#define SP7 7
|
||||
#define SP8 8
|
||||
#define SP9 9
|
||||
#define SP10 10
|
||||
#define SP11 11
|
||||
#define SP12 12
|
||||
#define SP13 13
|
||||
#define SP14 14
|
||||
#define SP15 15
|
||||
|
||||
|
||||
/* ================= GPC configuration ==================== */
|
||||
|
||||
#define SET_POINT_COUNT 16
|
||||
|
||||
/*
|
||||
* SOC set point mappings
|
||||
* This matrix defines what set points are allowed for a given core.
|
||||
* For example, when SP2 is requested, SP1 or SP2 are allowed set points
|
||||
*/
|
||||
#define CPU0_COMPATIBLE_SP_TABLE \
|
||||
/* NA, SP1, SP2, SP3, SP0, SP4, SP5, SP6, SP7, SP8, SP9, SP10, SP11, SP12, SP13, SP14, SP15 */ \
|
||||
/* SP1*/{{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
|
||||
/* SP2 */{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
|
||||
/* SP3 */{ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
|
||||
/* SP0 */{ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
|
||||
/* SP4 */{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
|
||||
/* SP5 */{ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
|
||||
/* SP6 */{ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
|
||||
/* SP7 */{ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, \
|
||||
/* SP8 */{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}, \
|
||||
/* SP9 */{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0}, \
|
||||
/* SP10 */{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}, \
|
||||
/* SP11 */{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, \
|
||||
/* SP12 */{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, \
|
||||
/* SP13 */{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, \
|
||||
/* SP14 */{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, \
|
||||
/* SP15 */{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}
|
||||
|
||||
#define CPU1_COMPATIBLE_SP_TABLE \
|
||||
/* NA, SP1, SP2, SP3, SP0, SP4, SP5, SP6, SP7, SP8, SP9, SP10, SP11, SP12, SP13, SP14, SP15 */ \
|
||||
/* SP1*/{{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
|
||||
/* SP2 */{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
|
||||
/* SP3 */{ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, \
|
||||
/* SP0 */{ 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
|
||||
/* SP4 */{ 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, \
|
||||
/* SP5 */{ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, \
|
||||
/* SP6 */{ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0}, \
|
||||
/* SP7 */{ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0}, \
|
||||
/* SP8 */{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0}, \
|
||||
/* SP9 */{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0}, \
|
||||
/* SP10 */{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, \
|
||||
/* SP11 */{ 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, \
|
||||
/* SP12 */{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0}, \
|
||||
/* SP13 */{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, \
|
||||
/* SP14 */{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, \
|
||||
/* SP15 */{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}}
|
||||
|
||||
/* Allows GPC to control RC16M on/off */
|
||||
#define OSC_RC_16M_STBY_VAL 0x0000
|
||||
|
||||
|
||||
/* ================== DCDC configuration ======================= */
|
||||
#define PD_WKUP_SP_VAL 0xf800 /* Off at SP11 - SP 15 */
|
||||
|
||||
#define DCDC_ONOFF_SP_VAL (~PD_WKUP_SP_VAL)
|
||||
#define DCDC_DIG_ONOFF_SP_VAL DCDC_ONOFF_SP_VAL
|
||||
#define DCDC_LP_MODE_SP_VAL 0x0000
|
||||
#define DCDC_ONOFF_STBY_VAL DCDC_ONOFF_SP_VAL
|
||||
#define DCDC_LP_MODE_STBY_VAL 0x0000
|
||||
|
||||
|
||||
/* DCDC 1.8V buck mode target voltage in set points 0-15 */
|
||||
#define DCDC_1P8_BUCK_MODE_CONFIGURATION_TABLE \
|
||||
{ \
|
||||
kDCDC_1P8BuckTarget1P8V, \
|
||||
kDCDC_1P8BuckTarget1P8V, \
|
||||
kDCDC_1P8BuckTarget1P8V, \
|
||||
kDCDC_1P8BuckTarget1P8V, \
|
||||
kDCDC_1P8BuckTarget1P8V, \
|
||||
kDCDC_1P8BuckTarget1P8V, \
|
||||
kDCDC_1P8BuckTarget1P8V, \
|
||||
kDCDC_1P8BuckTarget1P8V, \
|
||||
kDCDC_1P8BuckTarget1P8V, \
|
||||
kDCDC_1P8BuckTarget1P8V, \
|
||||
kDCDC_1P8BuckTarget1P8V, \
|
||||
kDCDC_1P8BuckTarget1P8V, \
|
||||
kDCDC_1P8BuckTarget1P8V, \
|
||||
kDCDC_1P8BuckTarget1P8V, \
|
||||
kDCDC_1P8BuckTarget1P8V, \
|
||||
kDCDC_1P8BuckTarget1P8V, \
|
||||
}
|
||||
|
||||
/* DCDC 1.0V buck mode target voltage in set points 0-15 */
|
||||
#define DCDC_1P0_BUCK_MODE_CONFIGURATION_TABLE \
|
||||
{ \
|
||||
kDCDC_1P0BuckTarget1P0V, \
|
||||
kDCDC_1P0BuckTarget1P1V, \
|
||||
kDCDC_1P0BuckTarget1P1V, \
|
||||
kDCDC_1P0BuckTarget1P1V, \
|
||||
kDCDC_1P0BuckTarget1P0V, \
|
||||
kDCDC_1P0BuckTarget0P9V, \
|
||||
kDCDC_1P0BuckTarget0P9V, \
|
||||
kDCDC_1P0BuckTarget0P9V, \
|
||||
kDCDC_1P0BuckTarget0P9V, \
|
||||
kDCDC_1P0BuckTarget0P9V, \
|
||||
kDCDC_1P0BuckTarget0P8V, \
|
||||
kDCDC_1P0BuckTarget0P9V, \
|
||||
kDCDC_1P0BuckTarget0P9V, \
|
||||
kDCDC_1P0BuckTarget0P9V, \
|
||||
kDCDC_1P0BuckTarget0P9V, \
|
||||
kDCDC_1P0BuckTarget0P9V, \
|
||||
}
|
||||
|
||||
|
||||
/* DCDC 1.8V standby mode target voltage in set points 0-15 */
|
||||
#define DCDC_1P8_STANDBY_MODE_CONFIGURATION_TABLE \
|
||||
{ \
|
||||
kDCDC_1P8StbyTarget1P8V, \
|
||||
kDCDC_1P8StbyTarget1P8V, \
|
||||
kDCDC_1P8StbyTarget1P8V, \
|
||||
kDCDC_1P8StbyTarget1P8V, \
|
||||
kDCDC_1P8StbyTarget1P8V, \
|
||||
kDCDC_1P8StbyTarget1P8V, \
|
||||
kDCDC_1P8StbyTarget1P8V, \
|
||||
kDCDC_1P8StbyTarget1P8V, \
|
||||
kDCDC_1P8StbyTarget1P8V, \
|
||||
kDCDC_1P8StbyTarget1P8V, \
|
||||
kDCDC_1P8StbyTarget1P8V, \
|
||||
kDCDC_1P8StbyTarget1P8V, \
|
||||
kDCDC_1P8StbyTarget1P8V, \
|
||||
kDCDC_1P8StbyTarget1P8V, \
|
||||
kDCDC_1P8StbyTarget1P8V, \
|
||||
kDCDC_1P8StbyTarget1P8V, \
|
||||
}
|
||||
|
||||
/* DCDC 1.0V standby mode target voltage in set points 0-15 */
|
||||
#define DCDC_1P0_STANDBY_MODE_CONFIGURATION_TABLE \
|
||||
{ \
|
||||
kDCDC_1P0StbyTarget1P0V, \
|
||||
kDCDC_1P0StbyTarget1P1V, \
|
||||
kDCDC_1P0StbyTarget1P1V, \
|
||||
kDCDC_1P0StbyTarget1P1V, \
|
||||
kDCDC_1P0StbyTarget1P0V, \
|
||||
kDCDC_1P0StbyTarget0P9V, \
|
||||
kDCDC_1P0StbyTarget0P9V, \
|
||||
kDCDC_1P0StbyTarget0P9V, \
|
||||
kDCDC_1P0StbyTarget0P9V, \
|
||||
kDCDC_1P0StbyTarget0P9V, \
|
||||
kDCDC_1P0StbyTarget0P8V, \
|
||||
kDCDC_1P0StbyTarget0P9V, \
|
||||
kDCDC_1P0StbyTarget0P9V, \
|
||||
kDCDC_1P0StbyTarget0P9V, \
|
||||
kDCDC_1P0StbyTarget0P9V, \
|
||||
kDCDC_1P0StbyTarget0P9V, \
|
||||
}
|
||||
|
||||
#endif /* _SOC_ARM_NXP_IMX_RT_POWER_RT11XX_H_ */
|
Loading…
Reference in a new issue