forked from zephyrproject-rtos/zephyr
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
soc: nxp: Add Power Management support for RT5xx
1. Support Sleep, Deep Sleep and Deep Power down modes 2. Enable the MEMC FlexSPI driver when using device power management so we can reconfigure the FlexSPI pins to save power. The MEMC FlexSPI driver is enabled when we enable the Flash subsystem, however we would like to reconfigure the FlexSPI pins even when the Flash driver is disabled, hence MEMC is selected when PM_DEVICE is turned on. Signed-off-by: Mahesh Mahadevan <[email protected]>
- Loading branch information
1 parent
db7deda
commit 0eb3c15
Showing
3 changed files
with
125 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
/* | ||
* Copyright 2022, NXP | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
#include <zephyr/kernel.h> | ||
#include <zephyr/device.h> | ||
#include <zephyr/pm/pm.h> | ||
#include "fsl_power.h" | ||
|
||
#include <zephyr/logging/log.h> | ||
LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL); | ||
|
||
/*!< Power down all unnecessary blocks */ | ||
#define NODE_ID DT_INST(0, nxp_pdcfg_power) | ||
#define EXCLUDE_FROM_DEEPSLEEP ((const uint32_t[]) \ | ||
DT_PROP_OR(NODE_ID, deep_sleep_config, {})) | ||
|
||
#define EXCLUDE_FROM_DEEP_POWERDOWN ((const uint32_t[]){0, 0, 0, 0}) | ||
|
||
static uint32_t isp_pin[3]; | ||
|
||
/* System clock frequency. */ | ||
extern uint32_t SystemCoreClock; | ||
|
||
__ramfunc void set_deepsleep_pin_config(void) | ||
{ | ||
/* Backup Pin configuration. */ | ||
isp_pin[0] = IOPCTL->PIO[1][15]; | ||
isp_pin[1] = IOPCTL->PIO[3][28]; | ||
isp_pin[2] = IOPCTL->PIO[3][29]; | ||
|
||
/* Disable ISP Pin pull-ups and input buffers to avoid current leakage */ | ||
IOPCTL->PIO[1][15] = 0; | ||
IOPCTL->PIO[3][28] = 0; | ||
IOPCTL->PIO[3][29] = 0; | ||
} | ||
|
||
__ramfunc void restore_deepsleep_pin_config(void) | ||
{ | ||
/* Restore the Pin configuration. */ | ||
IOPCTL->PIO[1][15] = isp_pin[0]; | ||
IOPCTL->PIO[3][28] = isp_pin[1]; | ||
IOPCTL->PIO[3][29] = isp_pin[2]; | ||
} | ||
|
||
/* Invoke Low Power/System Off specific Tasks */ | ||
__weak void pm_state_set(enum pm_state state, uint8_t substate_id) | ||
{ | ||
ARG_UNUSED(substate_id); | ||
|
||
/* FIXME: When this function is entered the Kernel has disabled | ||
* interrupts using BASEPRI register. This is incorrect as it prevents | ||
* waking up from any interrupt which priority is not 0. Work around the | ||
* issue and disable interrupts using PRIMASK register as recommended | ||
* by ARM. | ||
*/ | ||
|
||
/* Set PRIMASK */ | ||
__disable_irq(); | ||
|
||
/* Set BASEPRI to 0 */ | ||
irq_unlock(0); | ||
|
||
switch (state) { | ||
case PM_STATE_RUNTIME_IDLE: | ||
POWER_EnterSleep(); | ||
break; | ||
case PM_STATE_SUSPEND_TO_IDLE: | ||
set_deepsleep_pin_config(); | ||
POWER_EnterDeepSleep(EXCLUDE_FROM_DEEPSLEEP); | ||
restore_deepsleep_pin_config(); | ||
break; | ||
case PM_STATE_SOFT_OFF: | ||
set_deepsleep_pin_config(); | ||
POWER_EnterDeepPowerDown(EXCLUDE_FROM_DEEP_POWERDOWN); | ||
break; | ||
default: | ||
LOG_DBG("Unsupported power state %u", state); | ||
break; | ||
} | ||
} | ||
|
||
/* Handle SOC specific activity after Low Power Mode Exit */ | ||
__weak void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) | ||
{ | ||
ARG_UNUSED(state); | ||
ARG_UNUSED(substate_id); | ||
|
||
/* Clear PRIMASK */ | ||
__enable_irq(); | ||
} | ||
|
||
/* Initialize power system */ | ||
static int rt5xx_power_init(const struct device *dev) | ||
{ | ||
int ret = 0; | ||
|
||
/* This function is called to set vddcore low voltage detection | ||
* falling trip voltage, this is not impacting the voltage in anyway. | ||
*/ | ||
POWER_SetLdoVoltageForFreq(SystemCoreClock, 0); | ||
|
||
#if CONFIG_REGULATOR | ||
/* Indicate to power library that PMIC is used. */ | ||
POWER_UpdatePmicRecoveryTime(1); | ||
#endif | ||
|
||
return ret; | ||
} | ||
|
||
SYS_INIT(rt5xx_power_init, PRE_KERNEL_2, 0); |