You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2021/09/15 15:20:33 UTC

[incubator-nuttx] branch master updated: S32K1xx: added PM support

This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new b316c67  S32K1xx: added PM support
b316c67 is described below

commit b316c679c14156a5f3c3a0a5e30cbae6b4a817db
Author: Cis van Mierlo <ci...@nxp.com>
AuthorDate: Tue Sep 14 13:28:04 2021 +0200

    S32K1xx: added PM support
---
 arch/arm/src/s32k1xx/Make.defs              |    6 +-
 arch/arm/src/s32k1xx/hardware/s32k1xx_pmc.h |    1 +
 arch/arm/src/s32k1xx/hardware/s32k1xx_smc.h |   13 +-
 arch/arm/src/s32k1xx/s32k1xx_clockconfig.c  | 1037 ++++++++++++++++++++++++---
 arch/arm/src/s32k1xx/s32k1xx_clockconfig.h  |   42 ++
 arch/arm/src/s32k1xx/s32k1xx_lpspi.c        |  435 +++++++++++
 arch/arm/src/s32k1xx/s32k1xx_periphclocks.c |   61 +-
 arch/arm/src/s32k1xx/s32k1xx_periphclocks.h |   17 +
 arch/arm/src/s32k1xx/s32k1xx_pminitialize.c |   62 ++
 arch/arm/src/s32k1xx/s32k1xx_serial.c       |  446 +++++++++++-
 10 files changed, 1984 insertions(+), 136 deletions(-)

diff --git a/arch/arm/src/s32k1xx/Make.defs b/arch/arm/src/s32k1xx/Make.defs
index 9b34381..fb252ea 100644
--- a/arch/arm/src/s32k1xx/Make.defs
+++ b/arch/arm/src/s32k1xx/Make.defs
@@ -93,7 +93,11 @@ ifeq ($(CONFIG_S32K1XX_EEEPROM),y)
 CHIP_CSRCS += s32k1xx_eeeprom.c
 endif
 
-ifeq ($(CONFIG_RESET_CAUSE_PROC_FS), y) 
+ifneq ($(CONFIG_ARCH_CUSTOM_PMINIT),y)
+CHIP_CSRCS += s32k1xx_pminitialize.c
+endif
+
+ifeq ($(CONFIG_RESET_CAUSE_PROC_FS), y)
 CHIP_CSRCS += s32k1xx_resetcause.c
 endif
 
diff --git a/arch/arm/src/s32k1xx/hardware/s32k1xx_pmc.h b/arch/arm/src/s32k1xx/hardware/s32k1xx_pmc.h
index d3e2043..4c17c1a 100644
--- a/arch/arm/src/s32k1xx/hardware/s32k1xx_pmc.h
+++ b/arch/arm/src/s32k1xx/hardware/s32k1xx_pmc.h
@@ -63,6 +63,7 @@
 
 /* Regulator Status and Control Register */
 
+#define PMC_REGSC_BIASEN            (1 << 0)  /* Bit 0:  Bias Enable Bit */
 #define PMC_REGSC_CLKBIASDIS        (1 << 1)  /* Bit 1:  Clock Bias Disable Bit */
 #define PMC_REGSC_REGFPM            (1 << 2)  /* Bit 2:  Regulator in Full Performance Mode Status Bit */
 #define PMC_REGSC_LPOSTAT           (1 << 6)  /* Bit 6:  LPO Status Bit */
diff --git a/arch/arm/src/s32k1xx/hardware/s32k1xx_smc.h b/arch/arm/src/s32k1xx/hardware/s32k1xx_smc.h
index 5da2137..0d3c7b2 100644
--- a/arch/arm/src/s32k1xx/hardware/s32k1xx_smc.h
+++ b/arch/arm/src/s32k1xx/hardware/s32k1xx_smc.h
@@ -54,13 +54,12 @@
 
 /* SMC Version ID Register */
 
-#define SMC_VERID_FEATURE_SHIFT     (0)        /* Bits 0-15: Feature Identification Number */
+#define SMC_VERID_FEATURE_SHIFT     (0)                            /* Bits 0-15: Feature Identification Number */
 #define SMC_VERID_FEATURE_MASK      (0xffff << SMC_VERID_FEATURE_SHIFT)
 #  define SMC_VERID_FEATURE_STD     (1 << SMC_VERID_FEATURE_SHIFT) /* Standard feature set */
-
-#define SMC_VERID_MINOR_SHIFT       (16)       /* Bits 16-23: Minor Version Number */
+#define SMC_VERID_MINOR_SHIFT       (16)                           /* Bits 16-23: Minor Version Number */
 #define SMC_VERID_MINOR_MASK        (0xff << SMC_VERID_MINOR_SHIFT)
-#define SMC_VERID_MAJOR_SHIFT       (24)       /* Bits 24-31: Major Version Number */
+#define SMC_VERID_MAJOR_SHIFT       (24)                           /* Bits 24-31: Major Version Number */
 #define SMC_VERID_MAJOR_MASK        (0xff << SMC_VERID_MAJOR_SHIFT)
 
 /* SMC Parameter Register */
@@ -72,8 +71,10 @@
 
 /* SMC Power Mode Protection register */
 
-#define SMC_PMPROT_AVLP             (1 << 5)  /* Bit 5:  Allow Very-Low-Power Modes */
-#define SMC_PMPROT_AHSRUN           (1 << 7)  /* Bit 7:  Allow High Speed Run mode */
+#define SMC_PMPROT_AVLP_SHIFT       (5)  /* Bit 5:  Allow Very-Low-Power Modes */
+#define SMC_PMPROT_AVLP             (1 << SMC_PMPROT_AVLP_SHIFT)  
+#define SMC_PMPROT_AHSRUN_SHIFT     (7)  /* Bit 7:  Allow High Speed Run mode */
+#define SMC_PMPROT_AHSRUN           (1 << SMC_PMPROT_AHSRUN_SHIFT)  
 
 /* SMC Power Mode Control register */
 
diff --git a/arch/arm/src/s32k1xx/s32k1xx_clockconfig.c b/arch/arm/src/s32k1xx/s32k1xx_clockconfig.c
index 04e806e..880ee19 100644
--- a/arch/arm/src/s32k1xx/s32k1xx_clockconfig.c
+++ b/arch/arm/src/s32k1xx/s32k1xx_clockconfig.c
@@ -63,6 +63,7 @@
 #include <debug.h>
 
 #include <nuttx/arch.h>
+#include <nuttx/power/pm.h>
 
 #include "arm_arch.h"
 #include "arm_internal.h"
@@ -73,6 +74,7 @@
 #include "hardware/s32k1xx_pmc.h"
 #include "s32k1xx_periphclocks.h"
 #include "s32k1xx_clockconfig.h"
+#include "s32k1xx_start.h"
 
 #include <arch/board/board.h>  /* Include last.  May have dependencies */
 
@@ -120,18 +122,32 @@
 #define SCG_SPLL_REF_MIN 8000000
 #define SCG_SPLL_REF_MAX 32000000
 
+/* Power management definitions */
+
+#if defined(CONFIG_PM)
+#ifndef PM_IDLE_DOMAIN
+#  define PM_IDLE_DOMAIN      0 /* Revisit */
+#endif
+#endif
+
+#ifndef OK
+#define OK 0
+#endif
+
 /****************************************************************************
- * Private Types
+ * Private Function Declarations
  ****************************************************************************/
 
-enum scg_system_clock_mode_e
-{
-  SCG_SYSTEM_CLOCK_MODE_CURRENT = 0,  /* Current mode. */
-  SCG_SYSTEM_CLOCK_MODE_RUN     = 1,  /* Run mode. */
-  SCG_SYSTEM_CLOCK_MODE_VLPR    = 2,  /* Very Low Power Run mode. */
-  SCG_SYSTEM_CLOCK_MODE_HSRUN   = 3,  /* High Speed Run mode. */
-  SCG_SYSTEM_CLOCK_MODE_NONE          /* MAX value. */
-};
+#ifdef CONFIG_PM
+static void up_pm_notify(struct pm_callback_s *cb, int dowmin,
+                         enum pm_state_e pmstate);
+static int  up_pm_prepare(struct pm_callback_s *cb, int domain,
+                          enum pm_state_e pmstate);
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
 
 /****************************************************************************
  * Private Data
@@ -212,6 +228,14 @@ static uint32_t g_rtc_clkin;                 /* RTC CLKIN clock */
 static uint32_t g_tclkfreq[NUMBER_OF_TCLK_INPUTS];  /* TCLKx clocks */
 #endif
 
+#ifdef CONFIG_PM
+static  struct pm_callback_s g_clock_pmcb =
+{
+  .notify       = up_pm_notify,
+  .prepare      = up_pm_prepare,
+};
+#endif
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
@@ -237,59 +261,6 @@ static inline uint32_t s32k1xx_get_scgclk_source(void)
 }
 
 /****************************************************************************
- * Name: s32k1xx_get_runmode
- *
- * Description:
- *   Get the current running mode.
- *
- * Input Parameters:
- *   None
- *
- * Returned Value:
- *   The current running mode.
- *
- ****************************************************************************/
-
-static enum scg_system_clock_mode_e s32k1xx_get_runmode(void)
-{
-  enum scg_system_clock_mode_e mode;
-
-  /* Get the current running mode */
-
-  switch (getreg32(S32K1XX_SMC_PMSTAT) & SMC_PMSTAT_PMSTAT_MASK)
-    {
-      /* Run mode */
-
-      case SMC_PMSTAT_PMSTAT_RUN:
-        mode = SCG_SYSTEM_CLOCK_MODE_RUN;
-        break;
-
-      /* Very low power run mode */
-
-      case SMC_PMSTAT_PMSTAT_VLPR:
-        mode = SCG_SYSTEM_CLOCK_MODE_VLPR;
-        break;
-
-      /* High speed run mode */
-
-      case SMC_PMSTAT_PMSTAT_HSRUN:
-        mode = SCG_SYSTEM_CLOCK_MODE_HSRUN;
-        break;
-
-      /* This should never happen - core has to be in some run mode to
-       * execute code
-       */
-
-      case SMC_PMSTAT_PMSTAT_VLPS:
-      default:
-        mode = SCG_SYSTEM_CLOCK_MODE_NONE;
-        break;
-    }
-
-    return mode;
-}
-
-/****************************************************************************
  * Name: s32k1xx_get_soscfreq
  *
  * Description:
@@ -783,7 +754,7 @@ static int s32k1xx_firc_config(bool enable,
 }
 
 /****************************************************************************
- * Name: s32k11_firc_clocksource
+ * Name: s32k1xx_firc_clocksource
  *
  * Description:
  *   Configure to the FIRC clock source.
@@ -797,7 +768,7 @@ static int s32k1xx_firc_config(bool enable,
  *
  ****************************************************************************/
 
-static int s32k11_firc_clocksource(void)
+static int s32k1xx_firc_clocksource(void)
 {
   struct scg_system_clock_config_s firccfg;
   int ret = OK;
@@ -944,6 +915,61 @@ static int s32k1xx_sirc_config(bool enable,
   return ret;
 }
 
+#if defined(CONFIG_VLPR_STANDBY) || defined(CONFIG_VLPR_SLEEP)
+
+/****************************************************************************
+ * Name: s32k1xx_sirc_clocksource
+ *
+ * Description:
+ *   Configure to the SIRC clock source.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   Zero (OK) is returned a success;  A negated errno value is returned on
+ *   any failure.
+ *
+ ****************************************************************************/
+
+static int s32k1xx_sirc_clocksource(void)
+{
+  struct scg_system_clock_config_s sirccfg;
+  int ret = OK;
+
+  /* If the current system clock source is not SIRC:
+   * 1. Enable SIRC (if it's not enabled)
+   * 2. Switch to SIRC.
+   */
+
+  if (s32k1xx_get_scgclk_source() != SCG_SYSTEM_CLOCK_SRC_SIRC)
+    {
+      /* If SIRC is not on, then SIRC is configured with the default
+       * configuration
+       */
+
+      if (s32k1xx_get_sircfreq() == 0)
+        {
+          ret = s32k1xx_sirc_config(true, NULL);
+        }
+
+      /* SIRC is enabled, transition the system clock source to SIRC. */
+
+      if (ret == OK)
+        {
+          sirccfg.src     = SCG_SYSTEM_CLOCK_SRC_SIRC;
+          sirccfg.divcore = g_tmp_sysclk[TMP_SIRC_CLK][TMP_SYS_DIV];
+          sirccfg.divbus  = g_tmp_sysclk[TMP_SIRC_CLK][TMP_BUS_DIV];
+          sirccfg.divslow = g_tmp_sysclk[TMP_SIRC_CLK][TMP_SLOW_DIV];
+          ret             = s32k1xx_transition_systemclock(&sirccfg);
+        }
+    }
+
+  return ret;
+}
+
+#endif
+
 /****************************************************************************
  * Name: s32k1xx_sosc_config
  *
@@ -1394,9 +1420,10 @@ static int s32k1xx_scg_config(const struct scg_config_s *scgcfg)
 
   DEBUGASSERT(scgcfg != NULL);
 
-  /* Configure a temporary system clock source: FIRC */
+  /* Configure a temporary system clock source: FIRC if enabled */
+
+  ret = s32k1xx_firc_clocksource();
 
-  ret = s32k11_firc_clocksource();
   if (ret == OK)
     {
       /* Configure clock sources from SCG */
@@ -1654,6 +1681,10 @@ static void s32k1xx_pmc_config(const struct pmc_config_s *pmccfg)
           regval |= PMC_REGSC_LPODIS;
         }
 
+      /* Enable Biasing (needed for VLPR mode, no effect in RUN mode) */
+
+      regval |= PMC_REGSC_BIASEN;
+
       putreg8(regval, S32K1XX_PMC_REGSC);
 
       /* Write trimming value. */
@@ -1663,38 +1694,882 @@ static void s32k1xx_pmc_config(const struct pmc_config_s *pmccfg)
 }
 
 /****************************************************************************
- * Public Functions
+ * Name: s32k1xx_allow_vlprmode
+ *
+ * Description:
+ *   allow the very low power run mode.
+ *
+ * Input Parameters:
+ *   allow - true if allowed, false otherwise.
+ *
+ * Returned Value:
+ *   none.
+ *
  ****************************************************************************/
 
+void s32k1xx_allow_vlprmode(bool allow)
+{
+  uint32_t regval;
+
+  /* get the SMC_PMPROT register */
+
+  regval  =  getreg32(S32K1XX_SMC_PMPROT);
+
+  /* mask the AVLP bit */
+
+  regval &= ~SMC_PMPROT_AVLP;
+
+  /* set the new bit */
+
+  regval |= (allow << SMC_PMPROT_AVLP_SHIFT);
+
+  /* set the registervalue */
+
+  putreg32(regval, S32K1XX_SMC_PMPROT);
+}
+
 /****************************************************************************
- * Name: s32k1xx_clockconfig
+ * Name: up_pm_notify
  *
  * Description:
- *   Called to initialize the S32K1XX.  This does whatever setup is needed
- *   to put the MCU in a usable state.  This includes the initialization of
- *   clocking using the settings in board.h.  This function also performs
- *   other low-level chip as necessary.
+ *   Notify the driver of new power state. This callback is  called after
+ *   all drivers have had the opportunity to prepare for the new power state.
  *
  * Input Parameters:
- *   clkcfg - Describes the new clock configuration
+ *
+ *    cb - Returned to the driver. The driver version of the callback
+ *         structure may include additional, driver-specific state data at
+ *         the end of the structure.
+ *
+ *    pmstate - Identifies the new PM state
  *
  * Returned Value:
- *   Zero (OK) is returned a success;  A negated errno value is returned on
- *   any failure.
+ *   None - The driver already agreed to transition to the low power
+ *   consumption state when when it returned OK to the prepare() call.
  *
  ****************************************************************************/
 
-int s32k1xx_clockconfig(const struct clock_configuration_s *clkcfg)
+#ifdef CONFIG_PM
+static void up_pm_notify(struct pm_callback_s *cb, int domain,
+                         enum pm_state_e pmstate)
 {
-  int ret;
+  int return_value;
 
-  DEBUGASSERT(clkcfg != NULL);
+  /* check if the transition is from the IDLE domain to the NORMAL domain */
 
-  /* Set SCG configuration */
+  if (pm_querystate(PM_IDLE_DOMAIN) == PM_IDLE &&
+    pmstate == PM_NORMAL)
+    {
+      /* return */
 
-  ret = s32k1xx_scg_config(&clkcfg->scg);
-  if (ret >= 0)
+      return;
+    }
+
+  /* check what the new power state is */
+
+  switch (pmstate)
     {
+      /* if it needs to be set to RUN mode */
+
+      case(PM_NORMAL):
+        {
+          /* Logic for PM_NORMAL goes here */
+
+          /* change the microcontroller to RUN mode  */
+
+          /* and wait until in RUN mode */
+
+          return_value = (int)s32k1xx_set_runmode(SCG_SYSTEM_CLOCK_MODE_RUN);
+
+          /* check for debug assertion */
+
+          DEBUGASSERT(return_value != (int)SCG_SYSTEM_CLOCK_MODE_NONE);
+
+          /* enable all clock sources again if needed  */
+
+          /* these could be the FIRC, PPL, and SOSC */
+
+          /* check if the FIRC was enabled and
+           * it is not the system clock source
+           */
+
+          if (g_initial_clkconfig.scg.firc.initialize &&
+            (s32k1xx_get_scgclk_source() != SCG_SYSTEM_CLOCK_SRC_SIRC))
+          {
+            /* enable FIRC */
+
+            return_value = s32k1xx_firc_config(true,
+              &g_initial_clkconfig.scg.firc);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the FIRC needs to be disabled and if it is enabled */
+
+          else if ((!(g_initial_clkconfig.scg.firc.initialize)) &&
+            (s32k1xx_get_srcfreq(SCG_SYSTEM_CLOCK_SRC_FIRC)))
+          {
+            /* disable FIRC */
+
+            return_value = s32k1xx_firc_config(false,
+              &g_initial_clkconfig.scg.firc);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the SOSC was enabled and
+           * it is not the system clock source
+           */
+
+          if (g_initial_clkconfig.scg.sosc.initialize &&
+            (s32k1xx_get_scgclk_source() != SCG_SYSTEM_CLOCK_SRC_SYS_OSC) &&
+            (s32k1xx_get_scgclk_source() != SCG_SYSTEM_CLOCK_SRC_SYS_PLL))
+          {
+            /* enable SOSC */
+
+            return_value =
+              s32k1xx_sosc_config(true, &g_initial_clkconfig.scg.sosc);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the SOSC needs to be disabled and if it is enabled */
+
+          else if ((!(g_initial_clkconfig.scg.sosc.initialize)) &&
+            (s32k1xx_get_srcfreq(SCG_SYSTEM_CLOCK_SRC_SYS_OSC)))
+          {
+            /* disable SOSC */
+
+            return_value =
+              s32k1xx_sosc_config(false, &g_initial_clkconfig.scg.sosc);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the SPLL was enabled and
+           * it is not the system clock source
+           */
+
+          if (g_initial_clkconfig.scg.spll.initialize &&
+            (s32k1xx_get_scgclk_source() != SCG_SYSTEM_CLOCK_SRC_SYS_OSC) &&
+            (s32k1xx_get_scgclk_source() != SCG_SYSTEM_CLOCK_SRC_SYS_PLL))
+          {
+            /* enable SPLL */
+
+            return_value = s32k1xx_spll_config(true,
+              &g_initial_clkconfig.scg.spll);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the SPLL needs to be disabled and if it is enabled */
+
+          else if ((!(g_initial_clkconfig.scg.spll.initialize)) &&
+            (s32k1xx_get_srcfreq(SCG_SYSTEM_CLOCK_SRC_SYS_PLL)))
+          {
+            /* disable SPLL */
+
+            return_value = s32k1xx_spll_config(false,
+              &g_initial_clkconfig.scg.spll);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the RCCR clock source is enabled */
+
+          if (s32k1xx_get_srcfreq(g_initial_clkconfig.scg.clockmode.rccr.src)
+            != 0)
+          {
+            /* change the system clock back to the configured clock */
+
+            /* and wait until clock changed */
+
+            if (s32k1xx_transition_systemclock(
+              &g_initial_clkconfig.scg.clockmode.rccr))
+            {
+              /* error */
+
+              DEBUGASSERT(false);
+            }
+          }
+
+          /* if it is 0 */
+
+          else
+          {
+            /* error */
+
+            DEBUGASSERT(false);
+          }
+
+          /* calculate the new clock ticks */
+
+          up_timer_initialize();
+        }
+        break;
+
+      case(PM_IDLE):
+        {
+          /* Logic for PM_IDLE goes here */
+        }
+        break;
+
+      /* if it needs to be set to VLPR mode */
+
+      case(PM_STANDBY):
+        {
+          /* Logic for PM_STANDBY goes here */
+
+#ifdef CONFIG_RUN_STANDBY
+
+          /* change the microcontroller to RUN mode */
+
+          /* and wait until in RUN mode */
+
+          return_value =
+            (int)s32k1xx_set_runmode(SCG_SYSTEM_CLOCK_MODE_RUN);
+          DEBUGASSERT(return_value != (int)SCG_SYSTEM_CLOCK_MODE_NONE);
+
+          /* enable all clock sources again if needed  */
+
+          /* these could be the FIRC, PPL, and SOSC */
+
+          /* check if the FIRC was enabled and
+           * it is not the system clock source
+           */
+
+          if (g_initial_clkconfig.scg.firc.initialize &&
+            (s32k1xx_get_scgclk_source() != SCG_SYSTEM_CLOCK_SRC_SIRC))
+          {
+            /* enable FIRC */
+
+            return_value = s32k1xx_firc_config(true,
+              &g_initial_clkconfig.scg.firc);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the FIRC needs to be disabled and if it is enabled */
+
+          else if ((!(g_initial_clkconfig.scg.firc.initialize)) &&
+            (s32k1xx_get_srcfreq(SCG_SYSTEM_CLOCK_SRC_FIRC)))
+          {
+            /* disable FIRC */
+
+            return_value = s32k1xx_firc_config(false,
+              &g_initial_clkconfig.scg.firc);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the SOSC was enabled and
+           * it is not the system clock source
+           */
+
+          if (g_initial_clkconfig.scg.sosc.initialize &&
+            (s32k1xx_get_scgclk_source() != SCG_SYSTEM_CLOCK_SRC_SYS_OSC) &&
+            (s32k1xx_get_scgclk_source() != SCG_SYSTEM_CLOCK_SRC_SYS_PLL))
+          {
+            /* enable SOSC */
+
+            return_value =
+              s32k1xx_sosc_config(true, &g_initial_clkconfig.scg.sosc);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the SOSC needs to be disabled and if it is enabled */
+
+          else if ((!(g_initial_clkconfig.scg.sosc.initialize)) &&
+            (s32k1xx_get_srcfreq(SCG_SYSTEM_CLOCK_SRC_SYS_OSC)))
+          {
+            /* disable SOSC */
+
+            return_value =
+              s32k1xx_sosc_config(false, &g_initial_clkconfig.scg.sosc);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the SPLL was enabled and
+           * it is not the system clock source
+           */
+
+          if (g_initial_clkconfig.scg.spll.initialize &&
+            (s32k1xx_get_scgclk_source() != SCG_SYSTEM_CLOCK_SRC_SYS_OSC) &&
+            (s32k1xx_get_scgclk_source() != SCG_SYSTEM_CLOCK_SRC_SYS_PLL))
+          {
+            /* enable SPLL */
+
+            return_value = s32k1xx_spll_config(true,
+              &g_initial_clkconfig.scg.spll);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the SPLL needs to be disabled and if it is enabled */
+
+          else if ((!(g_initial_clkconfig.scg.spll.initialize)) &&
+            (s32k1xx_get_srcfreq(SCG_SYSTEM_CLOCK_SRC_SYS_PLL)))
+          {
+            /* disable SPLL */
+
+            return_value = s32k1xx_spll_config(false,
+              &g_initial_clkconfig.scg.spll);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the RCCR clock source is enabled */
+
+          if (s32k1xx_get_srcfreq(g_initial_clkconfig.scg.clockmode.rccr.src)
+            != 0)
+          {
+            /* change the system clock back to the configured clock */
+
+            /* and wait until clock changed */
+
+            if (s32k1xx_transition_systemclock(
+              &g_initial_clkconfig.scg.clockmode.rccr))
+            {
+              /* error */
+
+              DEBUGASSERT(false);
+            }
+          }
+
+          /* if it is 0 */
+
+          else
+          {
+            /* error */
+
+            DEBUGASSERT(false);
+          }
+
+#endif /* CONFIG_RUN_STANDBY */
+
+#ifdef CONFIG_VLPR_STANDBY
+
+          /* set the system clock to the SIRC 8MHz freq */
+
+          /* this freq will change to the predefined vccr settings
+           * when the mode change occures
+           */
+
+          /* and wait until system clock changed */
+
+          return_value = s32k1xx_sirc_clocksource();
+          DEBUGASSERT(!return_value);
+
+          /* disable the other clock sources if not already disabled */
+
+          /* these are the FIRC, PPL, and SOSC */
+
+          /* check if the SPLL is enabled */
+
+          if (s32k1xx_get_spllfreq() != 0)
+          {
+            /* disable SPLL */
+
+            return_value = s32k1xx_spll_config(false,
+              &g_initial_clkconfig.scg.spll);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the SOSC is enabled */
+
+          if (s32k1xx_get_soscfreq() != 0)
+          {
+            /* disable SOSC */
+
+            return_value =
+              s32k1xx_sosc_config(false, &g_initial_clkconfig.scg.sosc);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the FIRC is enabled */
+
+          if (s32k1xx_get_fircfreq() != 0)
+          {
+            /* disable FIRC */
+
+            return_value = s32k1xx_firc_config(false,
+              &g_initial_clkconfig.scg.firc);
+            DEBUGASSERT(!return_value);
+          }
+
+  #ifdef CONFIG_ARCH_CHIP_S32K11X
+            /* TODO make sure CMU is gated? (only for S32k11x) */
+
+            #error Make sure CMU is gated
+  #endif
+
+          /* change the microcontroller to VLPR mode */
+
+          /* and wait until it is in that runmode */
+
+          return_value =
+            (int)s32k1xx_set_runmode(SCG_SYSTEM_CLOCK_MODE_VLPR);
+          DEBUGASSERT(return_value != (int)SCG_SYSTEM_CLOCK_MODE_NONE);
+
+#endif /* CONFIG_VLPR_STANDBY */
+
+          /* calculate the new clock ticks */
+
+          up_timer_initialize();
+        }
+        break;
+
+      case(PM_SLEEP):
+        {
+          /* Logic for PM_SLEEP goes here */
+
+#ifdef CONFIG_RUN_SLEEP
+
+          /* change the microcontroller to RUN mode */
+
+          /* and wait until in RUN mode */
+
+          return_value = (int)s32k1xx_set_runmode(SCG_SYSTEM_CLOCK_MODE_RUN);
+          DEBUGASSERT(return_value != (int)SCG_SYSTEM_CLOCK_MODE_NONE);
+
+          /* enable all clock sources again if needed */
+
+          /* these could be the FIRC, PPL, and SOSC */
+
+          /* check if the FIRC was enabled
+           * and it is not the system clock source
+           */
+
+          if (g_initial_clkconfig.scg.firc.initialize &&
+            (s32k1xx_get_scgclk_source() != SCG_SYSTEM_CLOCK_SRC_SIRC))
+          {
+            /* enable FIRC */
+
+            return_value = s32k1xx_firc_config(true,
+              &g_initial_clkconfig.scg.firc);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the FIRC needs to be disabled and if it is enabled */
+
+          else if ((!(g_initial_clkconfig.scg.firc.initialize)) &&
+            (s32k1xx_get_srcfreq(SCG_SYSTEM_CLOCK_SRC_FIRC)))
+          {
+            /* disable FIRC */
+
+            return_value = s32k1xx_firc_config(false,
+              &g_initial_clkconfig.scg.firc);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the SOSC was enabled
+           * and it is not the system clock source
+           */
+
+          if (g_initial_clkconfig.scg.sosc.initialize &&
+            (s32k1xx_get_scgclk_source() != SCG_SYSTEM_CLOCK_SRC_SYS_OSC) &&
+            (s32k1xx_get_scgclk_source() != SCG_SYSTEM_CLOCK_SRC_SYS_PLL))
+          {
+            /* enable SOSC */
+
+            return_value =
+              s32k1xx_sosc_config(true, &g_initial_clkconfig.scg.sosc);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the SOSC needs to be disabled and if it is enabled */
+
+          else if ((!(g_initial_clkconfig.scg.sosc.initialize)) &&
+            (s32k1xx_get_srcfreq(SCG_SYSTEM_CLOCK_SRC_SYS_OSC)))
+          {
+            /* disable SOSC */
+
+            return_value =
+              s32k1xx_sosc_config(false, &g_initial_clkconfig.scg.sosc);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the SPLL was enabled
+           * and it is not the system clock source
+           */
+
+          if (g_initial_clkconfig.scg.spll.initialize &&
+            (s32k1xx_get_scgclk_source() != SCG_SYSTEM_CLOCK_SRC_SYS_OSC) &&
+            (s32k1xx_get_scgclk_source() != SCG_SYSTEM_CLOCK_SRC_SYS_PLL))
+          {
+            /* enable SPLL */
+
+            return_value = s32k1xx_spll_config(true,
+              &g_initial_clkconfig.scg.spll);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the SPLL needs to be disabled and if it is enabled */
+
+          else if ((!(g_initial_clkconfig.scg.spll.initialize)) &&
+            (s32k1xx_get_srcfreq(SCG_SYSTEM_CLOCK_SRC_SYS_PLL)))
+          {
+            /* disable SPLL */
+
+            return_value = s32k1xx_spll_config(false,
+              &g_initial_clkconfig.scg.spll);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the RCCR clock source is enabled */
+
+          if (s32k1xx_get_srcfreq(g_initial_clkconfig.scg.clockmode.rccr.src)
+            != 0)
+          {
+            /* change the system clock back to the configured clock */
+
+            /* and wait until clock changed */
+
+            if (s32k1xx_transition_systemclock(
+              &g_initial_clkconfig.scg.clockmode.rccr))
+            {
+              /* error */
+
+              DEBUGASSERT(false);
+            }
+          }
+
+          /* if it is 0 */
+
+          else
+          {
+            /* error */
+
+            DEBUGASSERT(false);
+          }
+
+#endif /* CONFIG_RUN_SLEEP */
+
+#ifdef CONFIG_VLPR_SLEEP
+
+          /* set the system clock to the SIRC 8MHz freq */
+
+          /* this freq will change to the predefined vccr settings
+           * when the mode change occures
+           */
+
+          /* and wait until system clock changed */
+
+          return_value = s32k1xx_sirc_clocksource();
+          DEBUGASSERT(!return_value);
+
+          /* disable the other clock sources if not already disabled */
+
+          /* these are the FIRC, PPL, and SOSC */
+
+          /* check if the SPLL is enabled */
+
+          if (s32k1xx_get_spllfreq() != 0)
+          {
+            /* disable SPLL */
+
+            return_value =
+            s32k1xx_spll_config(false, &g_initial_clkconfig.scg.spll);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the SOSC is enabled */
+
+          if (s32k1xx_get_soscfreq() != 0)
+          {
+            /* disable SOSC */
+
+            return_value =
+              s32k1xx_sosc_config(false, &g_initial_clkconfig.scg.sosc);
+            DEBUGASSERT(!return_value);
+          }
+
+          /* check if the FIRC is enabled */
+
+          if (s32k1xx_get_fircfreq() != 0)
+          {
+            /* disable FIRC */
+
+            return_value =
+            s32k1xx_firc_config(false, &g_initial_clkconfig.scg.firc);
+            DEBUGASSERT(!return_value);
+          }
+
+  #ifdef CONFIG_ARCH_CHIP_S32K11X
+            /* TODO make sure CMU is gated? (only for S32k11x) */
+
+            #error Make sure CMU is gated
+  #endif
+          /* change the microcontroller to VLPR mode */
+
+          /* and wait until it is in that runmode */
+
+          return_value =
+          (int)s32k1xx_set_runmode(SCG_SYSTEM_CLOCK_MODE_VLPR);
+          DEBUGASSERT(return_value != (int)SCG_SYSTEM_CLOCK_MODE_NONE);
+
+#endif /* CONFIG_VLPR_SLEEP */
+
+          /* calculate the new clock ticks */
+
+          up_timer_initialize();
+        }
+        break;
+
+      default:
+
+        /* Should not get here */
+
+        break;
+    }
+}
+#endif
+
+/****************************************************************************
+ * Name: up_pm_prepare
+ *
+ * Description:
+ *   Request the driver to prepare for a new power state. This is a warning
+ *   that the system is about to enter into a new power state. The driver
+ *   should begin whatever operations that may be required to enter power
+ *   state. The driver may abort the state change mode by returning a
+ *   non-zero value from the callback function.
+ *
+ * Input Parameters:
+ *
+ *    cb - Returned to the driver. The driver version of the callback
+ *         structure may include additional, driver-specific state data at
+ *         the end of the structure.
+ *
+ *    pmstate - Identifies the new PM state
+ *
+ * Returned Value:
+ *   Zero - (OK) means the event was successfully processed and that the
+ *          driver is prepared for the PM state change.
+ *
+ *   Non-zero - means that the driver is not prepared to perform the tasks
+ *              needed achieve this power setting and will cause the state
+ *              change to be aborted. NOTE: The prepare() method will also
+ *              be called when reverting from lower back to higher power
+ *              consumption modes (say because another driver refused a
+ *              lower power state change). Drivers are not permitted to
+ *              return non-zero values when reverting back to higher power
+ *              consumption modes!
+ *
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_PM
+static int up_pm_prepare(struct pm_callback_s *cb, int domain,
+                         enum pm_state_e pmstate)
+{
+  /* Logic to prepare for a reduced power state goes here. */
+
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: s32k1xx_get_runmode
+ *
+ * Description:
+ *   Get the current running mode.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   The current running mode.
+ *
+ ****************************************************************************/
+
+enum scg_system_clock_mode_e s32k1xx_get_runmode(void)
+{
+  enum scg_system_clock_mode_e mode;
+
+  /* Get the current running mode */
+
+  switch (getreg32(S32K1XX_SMC_PMSTAT) & SMC_PMSTAT_PMSTAT_MASK)
+    {
+      /* Run mode */
+
+      case SMC_PMSTAT_PMSTAT_RUN:
+        mode = SCG_SYSTEM_CLOCK_MODE_RUN;
+        break;
+
+      /* Very low power run mode */
+
+      case SMC_PMSTAT_PMSTAT_VLPR:
+        mode = SCG_SYSTEM_CLOCK_MODE_VLPR;
+        break;
+
+      /* High speed run mode */
+
+      case SMC_PMSTAT_PMSTAT_HSRUN:
+        mode = SCG_SYSTEM_CLOCK_MODE_HSRUN;
+        break;
+
+      /* This should never happen - core has to be in some run mode to
+       * execute code
+       */
+
+      case SMC_PMSTAT_PMSTAT_VLPS:
+      default:
+        mode = SCG_SYSTEM_CLOCK_MODE_NONE;
+        break;
+    }
+
+    return mode;
+}
+
+/****************************************************************************
+ * Name: s32k1xx_set_runmode
+ *
+ * Description:
+ *   Set the running mode.
+ *
+ * Input Parameters:
+ *   next_run_mode - The next running mode.
+ *
+ * Returned Value:
+ *   The current running mode.
+ *
+ ****************************************************************************/
+
+enum scg_system_clock_mode_e s32k1xx_set_runmode(enum scg_system_clock_mode_e
+  next_run_mode)
+{
+  enum scg_system_clock_mode_e mode;
+
+  /* get the current run mode */
+
+  mode = s32k1xx_get_runmode();
+  uint32_t regval;
+
+  /* check if the current runmode is not the same as the next runmode */
+
+  if (mode != next_run_mode)
+    {
+      /* check what the next mode is */
+
+      switch (next_run_mode)
+      {
+        /* in case of the RUN mode */
+
+        /* it will use the clock configuration from S32K1XX_SCG_RCCR */
+
+        case SCG_SYSTEM_CLOCK_MODE_RUN:
+
+          /* check if in VLPR mode */
+
+          if (mode == SCG_SYSTEM_CLOCK_MODE_VLPR)
+          {
+            /* get the SMC_PMCTRL register */
+
+            regval = getreg32(S32K1XX_SMC_PMCTRL);
+
+            /* mask the RUNM bits */
+
+            regval &= ~SMC_PMCTRL_RUNM_MASK;
+
+            /* change the mode to RUN mode */
+
+            regval |= SMC_PMCTRL_RUNM_RUN;
+
+            /* write the register */
+
+            putreg32(regval, S32K1XX_SMC_PMCTRL);
+
+            /* wait until it is in RUN mode */
+
+            while (s32k1xx_get_runmode() != SCG_SYSTEM_CLOCK_MODE_RUN);
+          }
+
+        break;
+
+        /* in case of the VLPR mode */
+
+        /* it will use the clock configuration from S32K1XX_SCG_VCCR */
+
+        case SCG_SYSTEM_CLOCK_MODE_VLPR:
+
+          /* check if in RUN mode and VLPR mode is allowed */
+
+          if ((mode == SCG_SYSTEM_CLOCK_MODE_RUN) &&
+            (getreg32(S32K1XX_SMC_PMPROT) & SMC_PMPROT_AVLP))
+          {
+            /* get the SMC_PMCTRL register */
+
+            regval = getreg32(S32K1XX_SMC_PMCTRL);
+
+            /* mask the RUNM bits */
+
+            regval &= ~SMC_PMCTRL_RUNM_MASK;
+
+            /* change the mode to VLPR mode */
+
+            regval |= SMC_PMCTRL_RUNM_VLPR;
+
+            /* write the register */
+
+            putreg32(regval, S32K1XX_SMC_PMCTRL);
+
+            /* wait until it is in VLPR mode */
+
+            while (s32k1xx_get_runmode() != SCG_SYSTEM_CLOCK_MODE_VLPR);
+          }
+        break;
+
+        /* others are not implemented */
+
+        default:
+        break;
+      }
+
+      /* get the current run mode */
+
+      mode = s32k1xx_get_runmode();
+    }
+
+  /* return the mode */
+
+  return mode;
+}
+
+/****************************************************************************
+ * Name: s32k1xx_clockconfig
+ *
+ * Description:
+ *   Called to initialize the S32K1XX.  This does whatever setup is needed
+ *   to put the MCU in a usable state.  This includes the initialization of
+ *   clocking using the settings in board.h.  This function also performs
+ *   other low-level chip as necessary.
+ *
+ * Input Parameters:
+ *   clkcfg - Describes the new clock configuration
+ *
+ * Returned Value:
+ *   Zero (OK) is returned a success;  A negated errno value is returned on
+ *   any failure.
+ *
+ ****************************************************************************/
+
+int s32k1xx_clockconfig(const struct clock_configuration_s *clkcfg)
+{
+  int ret;
+
+  DEBUGASSERT(clkcfg != NULL);
+
+#ifdef CONFIG_PM
+  /* Register to receive power management callbacks */
+
+  ret = pm_register(&g_clock_pmcb);
+  DEBUGASSERT(ret == OK);
+#endif
+
+  /* Set SCG configuration */
+
+  ret = s32k1xx_scg_config(&clkcfg->scg);
+  if (ret >= 0)
+    {
+      /* Allow the VLPR mode */
+
+      s32k1xx_allow_vlprmode(true);
+
       /* Set PCC configuration */
 
       s32k1xx_periphclocks(clkcfg->pcc.count, clkcfg->pcc.pclks);
diff --git a/arch/arm/src/s32k1xx/s32k1xx_clockconfig.h b/arch/arm/src/s32k1xx/s32k1xx_clockconfig.h
index 05fdf2e..9ed9d8e 100644
--- a/arch/arm/src/s32k1xx/s32k1xx_clockconfig.h
+++ b/arch/arm/src/s32k1xx/s32k1xx_clockconfig.h
@@ -440,6 +440,15 @@ struct clock_configuration_s
   struct pmc_config_s pmc;             /* PMC Clock configuration */
 };
 
+enum scg_system_clock_mode_e
+{
+  SCG_SYSTEM_CLOCK_MODE_CURRENT = 0,  /* Current mode. */
+  SCG_SYSTEM_CLOCK_MODE_RUN     = 1,  /* Run mode. */
+  SCG_SYSTEM_CLOCK_MODE_VLPR    = 2,  /* Very Low Power Run mode. */
+  SCG_SYSTEM_CLOCK_MODE_HSRUN   = 3,  /* High Speed Run mode. */
+  SCG_SYSTEM_CLOCK_MODE_NONE          /* MAX value. */
+};
+
 /****************************************************************************
  * Inline Functions
  ****************************************************************************/
@@ -464,6 +473,39 @@ extern "C"
  ****************************************************************************/
 
 /****************************************************************************
+ * Name: s32k1xx_get_runmode
+ *
+ * Description:
+ *   Get the current running mode.
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   The current running mode.
+ *
+ ****************************************************************************/
+
+enum scg_system_clock_mode_e s32k1xx_get_runmode(void);
+
+/****************************************************************************
+ * Name: s32k1xx_set_runmode
+ *
+ * Description:
+ *   Set the running mode.
+ *
+ * Input Parameters:
+ *   next_run_mode - The next running mode.
+ *
+ * Returned Value:
+ *   The current running mode.
+ *
+ ****************************************************************************/
+
+enum scg_system_clock_mode_e s32k1xx_set_runmode(enum scg_system_clock_mode_e
+  next_run_mode);
+
+/****************************************************************************
  * Name: s32k1xx_clockconfig
  *
  * Description:
diff --git a/arch/arm/src/s32k1xx/s32k1xx_lpspi.c b/arch/arm/src/s32k1xx/s32k1xx_lpspi.c
index 2f90004..60ea04d 100644
--- a/arch/arm/src/s32k1xx/s32k1xx_lpspi.c
+++ b/arch/arm/src/s32k1xx/s32k1xx_lpspi.c
@@ -100,6 +100,25 @@
 #  error "Cannot enable both interrupt mode and DMA mode for SPI"
 #endif
 
+/* Power management definitions */
+
+#if defined(CONFIG_PM) && !defined(CONFIG_S32K1XX_PM_SPI_ACTIVITY)
+#  define CONFIG_S32K1XX_PM_SPI_ACTIVITY 10
+#endif
+
+#if defined(CONFIG_PM)
+#ifndef PM_IDLE_DOMAIN
+#  define PM_IDLE_DOMAIN      0 /* Revisit */
+#endif
+#endif
+
+#if defined(CONFIG_PM_SPI0_STANDBY) || defined(CONFIG_PM_SPI0_SLEEP)
+#   define CONFIG_PM_SPI0
+#endif
+#if defined(CONFIG_PM_SPI1_STANDBY) || defined(CONFIG_PM_SPI1_SLEEP)
+#   define CONFIG_PM_SPI1
+#endif
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -177,6 +196,13 @@ static void s32k1xx_lpspi_recvblock(FAR struct spi_dev_s *dev,
                                     size_t nwords);
 #endif
 
+#ifdef CONFIG_PM
+static void up_pm_notify(struct pm_callback_s *cb, int dowmin,
+                         enum pm_state_e pmstate);
+static int  up_pm_prepare(struct pm_callback_s *cb, int domain,
+                          enum pm_state_e pmstate);
+#endif
+
 /* Initialization */
 
 static void
@@ -324,6 +350,14 @@ static struct s32k1xx_lpspidev_s g_lpspi2dev =
 };
 #endif
 
+#ifdef CONFIG_PM
+static  struct pm_callback_s g_spi1_pmcb =
+{
+  .notify       = up_pm_notify,
+  .prepare      = up_pm_prepare,
+};
+#endif
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
@@ -896,6 +930,8 @@ static int s32k1xx_lpspi_lock(FAR struct spi_dev_s *dev, bool lock)
   FAR struct s32k1xx_lpspidev_s *priv = (FAR struct s32k1xx_lpspidev_s *)dev;
   int ret;
 
+  /* It could be that this needs to be disabled for low level debugging */
+
   if (lock)
     {
       ret = nxsem_wait_uninterruptible(&priv->exclsem);
@@ -1376,6 +1412,12 @@ static void s32k1xx_lpspi_exchange_nodma(FAR struct spi_dev_s *dev,
 
   spiinfo("txbuffer=%p rxbuffer=%p nwords=%d\n", txbuffer, rxbuffer, nwords);
 
+#if defined(CONFIG_PM) && CONFIG_S32K1XX_PM_SPI_ACTIVITY > 0
+  /* Report serial activity to the power management logic */
+
+  pm_activity(PM_IDLE_DOMAIN, CONFIG_S32K1XX_PM_SPI_ACTIVITY);
+#endif
+
   /* bit mode? */
 
   framesize = s32k1xx_lpspi_9to16bitmode(priv);
@@ -1743,6 +1785,388 @@ static void s32k1xx_lpspi_bus_initialize(struct s32k1xx_lpspidev_s *priv)
 }
 
 /****************************************************************************
+ * Name: up_pm_notify
+ *
+ * Description:
+ *   Notify the driver of new power state. This callback is  called after
+ *   all drivers have had the opportunity to prepare for the new power state.
+ *
+ * Input Parameters:
+ *
+ *    cb - Returned to the driver. The driver version of the callback
+ *         structure may include additional, driver-specific state data at
+ *         the end of the structure.
+ *
+ *    pmstate - Identifies the new PM state
+ *
+ * Returned Value:
+ *   None - The driver already agreed to transition to the low power
+ *   consumption state when when it returned OK to the prepare() call.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_PM
+static void up_pm_notify(struct pm_callback_s *cb, int domain,
+                         enum pm_state_e pmstate)
+{
+# ifdef CONFIG_PM_SPI0
+
+  FAR struct s32k1xx_lpspidev_s *priv0 = NULL;
+
+  /* make the priv1ate struct for lpspi bus 0 */
+
+  priv0 = &g_lpspi0dev;
+
+# endif
+# ifdef CONFIG_PM_SPI1
+
+  FAR struct s32k1xx_lpspidev_s *priv1 = NULL;
+
+  /* make the priv1ate struct for lpspi bus 1  */
+
+  priv1 = &g_lpspi1dev;
+
+# endif
+
+  unsigned int count = 0;   /* the amount of peripheral clocks to change */
+
+  peripheral_clock_source_t clock_source;
+
+  /* check if the transition is from the IDLE domain to the NORMAL domain */
+
+  /* or the mode is already done */
+
+  if (((pm_querystate(PM_IDLE_DOMAIN) == PM_IDLE) &&
+    (pmstate == PM_NORMAL)) ||
+    (((pm_querystate(PM_IDLE_DOMAIN) == pmstate))))
+    {
+      /* return */
+
+      return;
+    }
+
+  /* check which PM it is  */
+
+  switch (pmstate)
+  {
+    /* in case it needs to change to the RUN mode */
+
+    case PM_NORMAL:
+    {
+      /* Logic for PM_NORMAL goes here */
+
+      /* set the right clock source to go back to RUN mode */
+
+      clock_source = CLK_SRC_SPLL_DIV2;
+
+# ifdef CONFIG_PM_SPI0
+
+      /* add 1 to count to do it for SPI0 */
+
+      count++;
+# endif
+
+# ifdef CONFIG_PM_SPI1
+
+      /* add 1 to count to do it for SPI1 */
+
+      count++;
+# endif
+    }
+    break;
+
+    default:
+    {
+      /* don't do anything, just return OK */
+    }
+    break;
+  }
+
+  /* check if the LPSPI needs to change */
+
+  if (count)
+  {
+    /* make the peripheral clock config struct */
+
+    const struct peripheral_clock_config_s clock_config[] =
+    {
+# ifdef CONFIG_PM_SPI0
+
+      {
+        .clkname  =   LPSPI0_CLK,
+        .clkgate  =   true,
+        .clksrc   =   clock_source,
+        .frac     =   MULTIPLY_BY_ONE,
+        .divider  =   1,
+      },
+# endif
+# ifdef CONFIG_PM_SPI1
+
+      {
+        .clkname  =   LPSPI1_CLK,
+        .clkgate  =   true,
+        .clksrc   =   clock_source,
+        .frac     =   MULTIPLY_BY_ONE,
+        .divider  =   1,
+      }
+# endif
+    };
+
+# ifdef CONFIG_PM_SPI0
+
+    /* disable LPSP0 */
+
+    s32k1xx_lpspi_modifyreg32(priv0, S32K1XX_LPSPI_CR_OFFSET, 0,
+                              !LPSPI_CR_MEN);
+
+# endif
+# ifdef CONFIG_PM_SPI1
+
+    /* disable LPSPI */
+
+    s32k1xx_lpspi_modifyreg32(priv1, S32K1XX_LPSPI_CR_OFFSET, 0,
+                              !LPSPI_CR_MEN);
+
+# endif
+
+    /* change the clock config for the new mode */
+
+    s32k1xx_periphclocks(count, clock_config);
+
+# ifdef CONFIG_PM_SPI0
+
+    /* Enable LPSP0 */
+
+    s32k1xx_lpspi_modifyreg32(priv0, S32K1XX_LPSPI_CR_OFFSET, 0,
+                              LPSPI_CR_MEN);
+
+# endif
+# ifdef CONFIG_PM_SPI1
+
+    /* Enable LPSPI */
+
+    s32k1xx_lpspi_modifyreg32(priv1, S32K1XX_LPSPI_CR_OFFSET, 0,
+                              LPSPI_CR_MEN);
+# endif
+
+    /* get the clock freq */
+  }
+
+  /* return */
+
+  return;
+}
+#endif
+
+/****************************************************************************
+ * Name: up_pm_prepare
+ *
+ * Description:
+ *   Request the driver to prepare for a new power state. This is a warning
+ *   that the system is about to enter into a new power state. The driver
+ *   should begin whatever operations that may be required to enter power
+ *   state. The driver may abort the state change mode by returning a
+ *   non-zero value from the callback function.
+ *
+ * Input Parameters:
+ *
+ *    cb - Returned to the driver. The driver version of the callback
+ *         structure may include additional, driver-specific state data at
+ *         the end of the structure.
+ *
+ *    pmstate - Identifies the new PM state
+ *
+ * Returned Value:
+ *   Zero - (OK) means the event was successfully processed and that the
+ *          driver is prepared for the PM state change.
+ *
+ *   Non-zero - means that the driver is not prepared to perform the tasks
+ *              needed achieve this power setting and will cause the state
+ *              change to be aborted. NOTE: The prepare() method will also
+ *              be called when reverting from lower back to higher power
+ *              consumption modes (say because another driver refused a
+ *              lower power state change). Drivers are not permitted to
+ *              return non-zero values when reverting back to higher power
+ *              consumption modes!
+ *
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_PM
+static int up_pm_prepare(struct pm_callback_s *cb, int domain,
+                         enum pm_state_e pmstate)
+{
+  /* Logic to prepare for a reduced power state goes here. */
+
+# ifdef CONFIG_PM_SPI0
+  FAR struct s32k1xx_lpspidev_s *priv0 = NULL;
+
+  /* make the private struct for lpspi bus 0 */
+
+  priv0 = &g_lpspi0dev;
+# endif
+# ifdef CONFIG_PM_SPI1
+  FAR struct s32k1xx_lpspidev_s *priv1 = NULL;
+
+  /* make the private struct for lpspi bus 1  */
+
+  priv1 = &g_lpspi1dev;
+# endif
+
+  unsigned int count = 0;   /* the amount of peripheral clocks to change */
+
+  peripheral_clock_source_t clock_source;
+
+  /* check if the transition to the mode is already done */
+
+  if (pm_querystate(PM_IDLE_DOMAIN) == pmstate)
+    {
+      /* return */
+
+      return OK;
+    }
+
+  /* check which PM it is  */
+
+  switch (pmstate)
+  {
+    /* in case it needs to prepare for VLPR mode */
+
+    case PM_STANDBY:
+    {
+      /* Logic for PM_STANDBY goes here */
+
+       /* set the right clock source */
+
+      clock_source = CLK_SRC_SIRC_DIV2;
+
+# ifdef CONFIG_PM_SPI0_STANDBY
+
+      /* increase count to change the SPI0  */
+
+      count++;
+
+# endif
+# ifdef CONFIG_PM_SPI1_STANDBY
+
+      /* increase count to change the SPI1 */
+
+      count++;
+
+# endif
+    }
+    break;
+
+    /* in case it needs to prepare for VLPR mode */
+
+    case PM_SLEEP:
+    {
+      /* Logic for PM_STANDBY goes here */
+
+      /* set the right clock source */
+
+      clock_source = CLK_SRC_SIRC_DIV2;
+
+# ifdef CONFIG_PM_SPI0_SLEEP
+
+      /* increase count to change the SPI0  */
+
+      count++;
+
+# endif
+# ifdef CONFIG_PM_SPI1_SLEEP
+
+      /* increase count to change the SPI1 */
+
+      count++;
+
+# endif     
+    }
+    break;
+
+    default:
+    {
+      /* don't do anything, just return OK */
+    }
+    break;
+  }
+
+  /* check if you need to change something */
+
+  if (count)
+  {
+    /* make the peripheral clock config struct */
+
+    const struct peripheral_clock_config_s clock_config[] =
+    {
+# ifdef CONFIG_PM_SPI0
+      {
+        .clkname  =   LPSPI0_CLK,
+        .clkgate  =   true,
+        .clksrc   =   clock_source,
+        .frac     =   MULTIPLY_BY_ONE,
+        .divider  =   1,
+      },
+# endif
+# ifdef CONFIG_PM_SPI1
+      {
+        .clkname  =   LPSPI1_CLK,
+        .clkgate  =   true,
+        .clksrc   =   clock_source,
+        .frac     =   MULTIPLY_BY_ONE,
+        .divider  =   1,
+      }
+# endif
+    };
+
+# ifdef CONFIG_PM_SPI0
+
+    /* disable LPSPI0 */
+
+    s32k1xx_lpspi_modifyreg32(priv0, S32K1XX_LPSPI_CR_OFFSET, 0,
+                                     !LPSPI_CR_MEN);
+
+# endif
+# ifdef CONFIG_PM_SPI1
+
+    /* disable LPSPI1 */
+
+    s32k1xx_lpspi_modifyreg32(priv1, S32K1XX_LPSPI_CR_OFFSET, 0,
+                              !LPSPI_CR_MEN);
+
+# endif
+
+    /* change the clock config for the new mode */
+
+    s32k1xx_periphclocks(count, clock_config);
+
+# ifdef CONFIG_PM_SPI0
+
+    /* Enable LPSPI */
+
+    s32k1xx_lpspi_modifyreg32(priv0, S32K1XX_LPSPI_CR_OFFSET, 0,
+                              LPSPI_CR_MEN);
+
+# endif
+# ifdef CONFIG_PM_SPI1
+
+    /* Enable LPSPI */
+
+    s32k1xx_lpspi_modifyreg32(priv1, S32K1XX_LPSPI_CR_OFFSET, 0,
+                              LPSPI_CR_MEN);
+
+# endif
+  }
+
+  /* get the clock freq */
+
+  /* return OK */
+
+  return OK;
+}
+#endif
+
+/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
@@ -1794,6 +2218,17 @@ FAR struct spi_dev_s *s32k1xx_lpspibus_initialize(int bus)
 #ifdef CONFIG_S32K1XX_LPSPI1
   if (bus == 1)
     {
+      #ifdef CONFIG_PM
+        #if defined(CONFIG_PM_SPI_STANDBY) || defined(CONFIG_PM_SPI_SLEEP) 
+          int ret;
+
+          /* Register to receive power management callbacks */
+
+          ret = pm_register(&g_spi1_pmcb);
+          DEBUGASSERT(ret == OK);
+          UNUSED(ret);
+        #endif
+      #endif
       /* Select SPI1 */
 
       priv = &g_lpspi1dev;
diff --git a/arch/arm/src/s32k1xx/s32k1xx_periphclocks.c b/arch/arm/src/s32k1xx/s32k1xx_periphclocks.c
index c05b618..c5c0d15 100644
--- a/arch/arm/src/s32k1xx/s32k1xx_periphclocks.c
+++ b/arch/arm/src/s32k1xx/s32k1xx_periphclocks.c
@@ -107,29 +107,6 @@ static uint32_t *s32k1xx_get_pclkctrl(enum clock_names_e clkname)
 }
 
 /****************************************************************************
- * Name: s32k1xx_pclk_disable
- *
- * Description:
- *   This function enables/disables the clock for a given peripheral.
- *
- * Input Parameters:
- *   clkname - The name of the peripheral clock to be disabled
- *   enable  - true:  Enable the peripheral clock.
- *
- * Returned Value:
- *   None
- *
- ****************************************************************************/
-
-static void s32k1xx_pclk_disable(enum clock_names_e clkname)
-{
-  uint32_t *ctrlp = s32k1xx_get_pclkctrl(clkname);
-  DEBUGASSERT(ctrlp != NULL);
-
-  *ctrlp &= ~PCC_CGC;
-}
-
-/****************************************************************************
  * Name: s32k1xx_set_pclkctrl
  *
  * Description:
@@ -279,7 +256,7 @@ void s32k1xx_periphclocks(unsigned int count,
     {
       /* Disable the peripheral clock */
 
-      s32k1xx_pclk_disable(pclks->clkname);
+      s32k1xx_pclk_enable(pclks->clkname, false);
 
       /* Set peripheral clock control */
 
@@ -398,3 +375,39 @@ int s32k1xx_get_pclkfreq(enum clock_names_e clkname, uint32_t *frequency)
 
   return ret;
 }
+
+/****************************************************************************
+ * Name: s32k1xx_pclk_enable
+ *
+ * Description:
+ *   This function enables/disables the clock for a given peripheral.
+ *
+ * Input Parameters:
+ *   clkname - The name of the peripheral clock to be disabled
+ *   enable  - true:  Enable the peripheral clock.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void s32k1xx_pclk_enable(enum clock_names_e clkname, bool enable)
+{
+  uint32_t *ctrlp = s32k1xx_get_pclkctrl(clkname);
+  DEBUGASSERT(ctrlp != NULL);
+
+  /* check if it needs to be enabled */
+
+  if (enable)
+    {
+      /* enable it */
+
+      *ctrlp |= PCC_CGC;
+    }
+  else
+    {
+      /* disable it */
+
+      *ctrlp &= ~PCC_CGC;
+    }
+}
diff --git a/arch/arm/src/s32k1xx/s32k1xx_periphclocks.h b/arch/arm/src/s32k1xx/s32k1xx_periphclocks.h
index 028a99a..604414e 100644
--- a/arch/arm/src/s32k1xx/s32k1xx_periphclocks.h
+++ b/arch/arm/src/s32k1xx/s32k1xx_periphclocks.h
@@ -267,6 +267,23 @@ void s32k1xx_periphclocks(unsigned int count,
 
 int s32k1xx_get_pclkfreq(enum clock_names_e clkname, uint32_t *frequency);
 
+/****************************************************************************
+ * Name: s32k1xx_pclk_enable
+ *
+ * Description:
+ *   This function enables/disables the clock for a given peripheral.
+ *
+ * Input Parameters:
+ *   clkname - The name of the peripheral clock to be disabled
+ *   enable  - true:  Enable the peripheral clock.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+void s32k1xx_pclk_enable(enum clock_names_e clkname, bool enable);
+
 #undef EXTERN
 #if defined(__cplusplus)
 }
diff --git a/arch/arm/src/s32k1xx/s32k1xx_pminitialize.c b/arch/arm/src/s32k1xx/s32k1xx_pminitialize.c
new file mode 100644
index 0000000..096d6bb
--- /dev/null
+++ b/arch/arm/src/s32k1xx/s32k1xx_pminitialize.c
@@ -0,0 +1,62 @@
+/****************************************************************************
+ * arch/arm/src/s32k1xx/s32k1xx_pminitialize.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/power/pm.h>
+
+#include "arm_internal.h"
+
+#ifdef CONFIG_PM
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: arm_pminitialize
+ *
+ * Description:
+ *   This function is called by MCU-specific logic at power-on reset in
+ *   order to provide one-time initialization the power management subsystem.
+ *   This function must be called *very* early in the initialization sequence
+ *   *before* any other device drivers are initialized (since they may
+ *   attempt to register with the power management subsystem).
+ *
+ * Input Parameters:
+ *   None.
+ *
+ * Returned Value:
+ *   None.
+ *
+ ****************************************************************************/
+
+void arm_pminitialize(void)
+{
+  /* Then initialize the NuttX power management subsystem proper */
+
+  pm_initialize();
+}
+
+#endif /* CONFIG_PM */
diff --git a/arch/arm/src/s32k1xx/s32k1xx_serial.c b/arch/arm/src/s32k1xx/s32k1xx_serial.c
index 6f8c379..63724a6 100644
--- a/arch/arm/src/s32k1xx/s32k1xx_serial.c
+++ b/arch/arm/src/s32k1xx/s32k1xx_serial.c
@@ -57,6 +57,8 @@
 #include "s32k1xx_pin.h"
 #include "s32k1xx_lowputc.h"
 
+#include "s32k1xx_periphclocks.h"
+
 #ifdef USE_SERIALDRIVER
 
 /****************************************************************************
@@ -132,9 +134,20 @@
 #endif
 
 #if defined(CONFIG_PM)
+#ifndef PM_IDLE_DOMAIN
 #  define PM_IDLE_DOMAIN      0 /* Revisit */
 #endif
+#endif
 
+#if defined(CONFIG_PM_SERIAL0_STANDBY) || defined(CONFIG_PM_SERIAL0_SLEEP)
+#   define CONFIG_PM_SERIAL0
+#endif
+#if defined(CONFIG_PM_SERIAL1_STANDBY) || defined(CONFIG_PM_SERIAL1_SLEEP)
+#   define CONFIG_PM_SERIAL1
+#endif
+#if defined(CONFIG_PM_SERIAL2_STANDBY) || defined(CONFIG_PM_SERIAL2_SLEEP)
+#   define CONFIG_PM_SERIAL2
+#endif
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -508,8 +521,14 @@ static int s32k1xx_setup(struct uart_dev_s *dev)
   config.invrts     = priv->inviflow;   /* Inversion of outbound flow control */
 #endif
 
+  /* configure the LPUART */
+
   ret = s32k1xx_lpuart_configure(priv->uartbase, &config);
 
+  /* get the current interrupt bits and place them in ie */
+
+  /* (used to use the interrupts)  */
+
   priv->ie = s32k1xx_serialin(priv, S32K1XX_LPUART_CTRL_OFFSET) & \
              LPUART_ALL_INTS;
   return ret;
@@ -536,7 +555,13 @@ static void s32k1xx_shutdown(struct uart_dev_s *dev)
 
   /* Disable the UART */
 
+  /* set the reset bit  */
+
   s32k1xx_serialout(priv, S32K1XX_LPUART_GLOBAL_OFFSET, LPUART_GLOBAL_RST);
+
+  /* clear the reset bit again */
+
+  s32k1xx_serialout(priv, S32K1XX_LPUART_GLOBAL_OFFSET, 0);
 }
 
 /****************************************************************************
@@ -1114,38 +1139,205 @@ static bool s32k1xx_txempty(struct uart_dev_s *dev)
 static void up_pm_notify(struct pm_callback_s *cb, int domain,
                          enum pm_state_e pmstate)
 {
-  switch (pmstate)
+  unsigned int count = 0;   /* the amount of peripheral clocks to change */
+
+  peripheral_clock_source_t clock_source;
+
+  #ifdef CONFIG_PM_SERIAL0
+    struct s32k1xx_uart_s *priv0 = g_uart0port.priv;
+  #endif
+  #ifdef CONFIG_PM_SERIAL1
+    struct s32k1xx_uart_s *priv1 = g_uart1port.priv;
+  #endif
+  #ifdef CONFIG_PM_SERIAL2
+    struct s32k1xx_uart_s *priv2 = g_uart2port.priv;
+  #endif
+
+  uint32_t ret_reg = 0;
+
+  /* check if the transition is from the IDLE domain to the NORMAL domain */
+
+  /* or the mode is already done */
+
+  if (((pm_querystate(PM_IDLE_DOMAIN) == PM_IDLE) &&
+    (pmstate == PM_NORMAL)) ||
+    (((pm_querystate(PM_IDLE_DOMAIN) == pmstate))))
     {
-      case(PM_NORMAL):
-        {
-          /* Logic for PM_NORMAL goes here */
-        }
-        break;
+      /* return */
 
-      case(PM_IDLE):
-        {
-          /* Logic for PM_IDLE goes here */
-        }
-        break;
+      return;
+    }
 
-      case(PM_STANDBY):
-        {
-          /* Logic for PM_STANDBY goes here */
-        }
-        break;
+  /* check which PM it is  */
 
-      case(PM_SLEEP):
-        {
-          /* Logic for PM_SLEEP goes here */
-        }
-        break;
+  switch (pmstate)
+  {
+    /* in case it needs to change to the RUN mode */
+
+    case PM_NORMAL:
+    {
+      /* Logic for PM_NORMAL goes here */
 
-      default:
+      /* set the right clock source to go back to RUN mode */
 
-        /* Should not get here */
+      clock_source = CLK_SRC_SPLL_DIV2;
 
-        break;
+      count = 1;
+    }
+    break;
+    default:
+    {
+      /* don't do anything, just return OK */
     }
+    break;
+  }
+
+  /* check if something needs to change */
+
+  if (count)
+  {
+    #ifdef CONFIG_PM_SERIAL0
+
+      /* make the peripheral clock config struct */
+
+      const struct peripheral_clock_config_s clock_config0 =
+      {
+        .clkname  =   LPUART0_CLK,
+        .clkgate  =   true,
+        .clksrc   =   clock_source,
+        .frac     =   MULTIPLY_BY_ONE,
+        .divider  =   1,
+      };
+
+      /* read the FIFO register */
+
+      ret_reg = getreg32(priv0->uartbase + S32K1XX_LPUART_FIFO_OFFSET);
+
+      /* make the value */
+
+      ret_reg |= (LPUART_FIFO_RXFLUSH + LPUART_FIFO_TXFLUSH);
+
+      /* write the new value */
+
+      putreg32(ret_reg, priv0->uartbase + S32K1XX_LPUART_FIFO_OFFSET);
+
+      /* shutdown the LPUART1 (soft reset) */
+
+      s32k1xx_shutdown(&g_uart0port);
+
+      /* change the clock config for the new mode */
+
+      s32k1xx_periphclocks(count, &clock_config0);
+
+      /* shutdown the LPUART1 (soft reset) */
+
+      s32k1xx_shutdown(&g_uart0port);
+
+      /* set up the LPUART1 again for the new mode */
+
+      s32k1xx_setup(&g_uart0port);
+
+      /* enable the interrupts */
+
+      s32k1xx_rxint(&g_uart0port, true);
+      s32k1xx_txint(&g_uart0port, true);
+
+    #endif
+    #ifdef CONFIG_PM_SERIAL1
+
+      /* make the peripheral clock config struct */
+
+      const struct peripheral_clock_config_s clock_config1 =
+      {
+        .clkname  =   LPUART1_CLK,
+        .clkgate  =   true,
+        .clksrc   =   clock_source,
+        .frac     =   MULTIPLY_BY_ONE,
+        .divider  =   1,
+      };
+
+      /* read the FIFO register */
+
+      ret_reg = getreg32(priv1->uartbase + S32K1XX_LPUART_FIFO_OFFSET);
+
+      /* make the value */
+
+      ret_reg |= (LPUART_FIFO_RXFLUSH + LPUART_FIFO_TXFLUSH);
+
+      /* write the new value */
+
+      putreg32(ret_reg, priv1->uartbase + S32K1XX_LPUART_FIFO_OFFSET);
+
+      /* shutdown the LPUART1 (soft reset) */
+
+      s32k1xx_shutdown(&g_uart1port);
+
+      /* change the clock config for the new mode */
+
+      s32k1xx_periphclocks(count, &clock_config1);
+
+      /* shutdown the LPUART1 (soft reset) */
+
+      s32k1xx_shutdown(&g_uart1port);
+
+      /* set up the LPUART1 again for the new mode */
+
+      s32k1xx_setup(&g_uart1port);
+
+      /* enable the interrupts */
+
+      s32k1xx_rxint(&g_uart1port, true);
+      s32k1xx_txint(&g_uart1port, true);
+
+    #endif
+    #ifdef CONFIG_PM_SERIAL2
+
+      /* make the peripheral clock config struct */
+
+      const struct peripheral_clock_config_s clock_config2 =
+      {
+        .clkname  =   LPUART2_CLK,
+        .clkgate  =   true,
+        .clksrc   =   clock_source,
+        .frac     =   MULTIPLY_BY_ONE,
+        .divider  =   1,
+      };
+
+      /* read the FIFO register */
+
+      ret_reg = getreg32(priv2->uartbase + S32K1XX_LPUART_FIFO_OFFSET);
+
+      /* make the value */
+
+      ret_reg |= (LPUART_FIFO_RXFLUSH + LPUART_FIFO_TXFLUSH);
+
+      /* write the new value */
+
+      putreg32(ret_reg, priv2->uartbase + S32K1XX_LPUART_FIFO_OFFSET);
+
+      /* shutdown the LPUART1 (soft reset) */
+
+      s32k1xx_shutdown(&g_uart2port);
+
+      /* change the clock config for the new mode */
+
+      s32k1xx_periphclocks(count, &clock_config2);
+
+      /* shutdown the LPUART1 (soft reset) */
+
+      s32k1xx_shutdown(&g_uart2port);
+
+      /* set up the LPUART1 again for the new mode */
+
+      s32k1xx_setup(&g_uart2port);
+
+      /* enable the interrupts */
+
+      s32k1xx_rxint(&g_uart2port, true);
+      s32k1xx_txint(&g_uart2port, true);
+
+    #endif
+  }
 }
 #endif
 
@@ -1189,6 +1381,209 @@ static int up_pm_prepare(struct pm_callback_s *cb, int domain,
 {
   /* Logic to prepare for a reduced power state goes here. */
 
+  unsigned int count = 1;   /* the amount of peripheral clocks to change */
+
+  peripheral_clock_source_t clock_source;
+
+  #ifdef CONFIG_PM_SERIAL0
+    struct s32k1xx_uart_s *priv0 = (struct s32k1xx_uart_s *)g_uart0port.priv;
+  #endif
+  #ifdef CONFIG_PM_SERIAL1
+    struct s32k1xx_uart_s *priv1 = (struct s32k1xx_uart_s *)g_uart1port.priv;
+  #endif
+  #ifdef CONFIG_PM_SERIAL2
+    struct s32k1xx_uart_s *priv2 = (struct s32k1xx_uart_s *)g_uart2port.priv;
+  #endif
+
+  uint32_t ret_reg = 0;
+
+  /* check if the transition to the mode is already done */
+
+  if (pm_querystate(PM_IDLE_DOMAIN) == pmstate)
+    {
+      /* return */
+
+      return OK;
+    }
+
+  /* check which PM it is  */
+
+  switch (pmstate)
+  {
+    /* in case it needs to prepare for VLPR mode */
+
+    case PM_STANDBY:
+    {
+      /* Logic for PM_STANDBY goes here */
+
+      /* set the right clock source */
+
+      clock_source = CLK_SRC_SIRC_DIV2;
+    }
+    break;
+
+    /* in case it needs to prepare for sleep mode */
+
+    case PM_SLEEP:
+    {
+      /* Logic for PM_SLEEP goes here */
+
+      /* set the right clock source */
+
+      clock_source = CLK_SRC_SIRC_DIV2;
+    }
+    break;
+    default:
+    {
+      /* don't do anything, just return OK */
+
+      return OK;
+    }
+    break;
+  }
+
+  #ifdef CONFIG_PM_SERIAL0
+
+    /* make the peripheral clock config struct */
+
+    const struct peripheral_clock_config_s clock_config0 =
+    {
+      .clkname  =   LPUART0_CLK,
+      .clkgate  =   true,
+      .clksrc   =   clock_source,
+      .frac     =   MULTIPLY_BY_ONE,
+      .divider  =   1,
+    };
+
+    /* read the FIFO register */
+
+    ret_reg = getreg32(priv0->uartbase + S32K1XX_LPUART_FIFO_OFFSET);
+
+    /* make the value */
+
+    ret_reg |= (LPUART_FIFO_RXFLUSH + LPUART_FIFO_TXFLUSH);
+
+    /* write the new value */
+
+    putreg32(ret_reg, priv0->uartbase + S32K1XX_LPUART_FIFO_OFFSET);
+
+    /* shutdown the LPUART1 (soft reset) */
+
+    s32k1xx_shutdown(&g_uart0port);
+
+    /* change the clock config for the new mode */
+
+    s32k1xx_periphclocks(count, &clock_config0);
+
+    /* shutdown the LPUART1 (soft reset) */
+
+    s32k1xx_shutdown(&g_uart0port);
+
+    /* set up the LPUART1 again for the new mode */
+
+    s32k1xx_setup(&g_uart0port);
+
+    /* enable the interrupts */
+
+    s32k1xx_rxint(&g_uart0port, true);
+    s32k1xx_txint(&g_uart0port, true);
+
+  #endif
+  #ifdef CONFIG_PM_SERIAL1
+
+    /* make the peripheral clock config struct */
+
+    const struct peripheral_clock_config_s clock_config1 =
+    {
+      .clkname  =   LPUART1_CLK,
+      .clkgate  =   true,
+      .clksrc   =   clock_source,
+      .frac     =   MULTIPLY_BY_ONE,
+      .divider  =   1,
+    };
+
+    /* read the FIFO register */
+
+    ret_reg = getreg32(priv1->uartbase + S32K1XX_LPUART_FIFO_OFFSET);
+
+    /* make the value */
+
+    ret_reg |= (LPUART_FIFO_RXFLUSH + LPUART_FIFO_TXFLUSH);
+
+    /* write the new value */
+
+    putreg32(ret_reg, priv1->uartbase + S32K1XX_LPUART_FIFO_OFFSET);
+
+    /* shutdown the LPUART1 (soft reset) */
+
+    s32k1xx_shutdown(&g_uart1port);
+
+    /* change the clock config for the new mode */
+
+    s32k1xx_periphclocks(count, &clock_config1);
+
+    /* shutdown the LPUART1 (soft reset) */
+
+    s32k1xx_shutdown(&g_uart1port);
+
+    /* set up the LPUART1 again for the new mode */
+
+    s32k1xx_setup(&g_uart1port);
+
+    /* enable the interrupts */
+
+    s32k1xx_rxint(&g_uart1port, true);
+    s32k1xx_txint(&g_uart1port, true);
+
+  #endif
+  #ifdef CONFIG_PM_SERIAL2
+
+    /* make the peripheral clock config struct */
+
+    const struct peripheral_clock_config_s clock_config2 =
+    {
+      .clkname  =   LPUART2_CLK,
+      .clkgate  =   true,
+      .clksrc   =   clock_source,
+      .frac     =   MULTIPLY_BY_ONE,
+      .divider  =   1,
+    };
+
+    /* read the FIFO register */
+
+    ret_reg = getreg32(priv2->uartbase + S32K1XX_LPUART_FIFO_OFFSET);
+
+    /* make the value */
+
+    ret_reg |= (LPUART_FIFO_RXFLUSH + LPUART_FIFO_TXFLUSH);
+
+    /* write the new value */
+
+    putreg32(ret_reg, priv2->uartbase + S32K1XX_LPUART_FIFO_OFFSET);
+
+    /* shutdown the LPUART1 (soft reset) */
+
+    s32k1xx_shutdown(&g_uart2port);
+
+    /* change the clock config for the new mode */
+
+    s32k1xx_periphclocks(count, &clock_config2);
+
+    /* shutdown the LPUART1 (soft reset) */
+
+    s32k1xx_shutdown(&g_uart2port);
+
+    /* set up the LPUART1 again for the new mode */
+
+    s32k1xx_setup(&g_uart2port);
+
+    /* enable the interrupts */
+
+    s32k1xx_rxint(&g_uart2port, true);
+    s32k1xx_txint(&g_uart2port, true);
+
+  #endif
+
   return OK;
 }
 #endif
@@ -1236,6 +1631,8 @@ void s32k1xx_earlyserialinit(void)
 void arm_serialinit(void)
 {
 #ifdef CONFIG_PM
+  #if defined(CONFIG_PM_SERIAL_STANDBY) || defined(CONFIG_PM_SERIAL_SLEEP) 
+
   int ret;
 
   /* Register to receive power management callbacks */
@@ -1243,6 +1640,7 @@ void arm_serialinit(void)
   ret = pm_register(&g_serial_pmcb);
   DEBUGASSERT(ret == OK);
   UNUSED(ret);
+  #endif
 #endif
 
 #ifdef CONSOLE_DEV