Skip to content

Commit

Permalink
soc: nxp: Add Power Management support for RT5xx
Browse files Browse the repository at this point in the history
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
mmahadevan108 authored and dleach02 committed Jan 4, 2023
1 parent db7deda commit 0eb3c15
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 0 deletions.
2 changes: 2 additions & 0 deletions soc/arm/nxp_imx/rt5xx/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ zephyr_sources(
flash_clock_setup.c
)

zephyr_sources_ifdef(CONFIG_PM power.c)

zephyr_library_include_directories(
${ZEPHYR_BASE}/kernel/include
${ZEPHYR_BASE}/arch/${ARCH}/include
Expand Down
11 changes: 11 additions & 0 deletions soc/arm/nxp_imx/rt5xx/Kconfig.defconfig.mimxrt595_cm33
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,15 @@ choice USB_MCUX_CONTROLLER_TYPE
default USB_DC_NXP_LPCIP3511
endchoice

# 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.
config MEMC
default y if PM_DEVICE
select MEMC_MCUX_FLEXSPI

endif # SOC_MIMXRT685S_CM33
112 changes: 112 additions & 0 deletions soc/arm/nxp_imx/rt5xx/power.c
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);

0 comments on commit 0eb3c15

Please sign in to comment.