diff --git a/boards/nxp/mr_canhubk3/mr_canhubk3.dts b/boards/nxp/mr_canhubk3/mr_canhubk3.dts index 66f7939340e..aa0ffb61691 100644 --- a/boards/nxp/mr_canhubk3/mr_canhubk3.dts +++ b/boards/nxp/mr_canhubk3/mr_canhubk3.dts @@ -201,6 +201,10 @@ }; }; +&pmc { + lm-reg; +}; + &flash0 { partitions { compatible = "fixed-partitions"; diff --git a/dts/arm/nxp/nxp_s32k344_m7.dtsi b/dts/arm/nxp/nxp_s32k344_m7.dtsi index 040207968de..1c186475941 100644 --- a/dts/arm/nxp/nxp_s32k344_m7.dtsi +++ b/dts/arm/nxp/nxp_s32k344_m7.dtsi @@ -857,6 +857,23 @@ reg = <0x40080000 0x4000>; status = "disabled"; }; + + pmc: pmc@402e8000 { + compatible = "nxp,s32k3-pmc"; + reg = <0x402e8000 0x4000>; + }; + + mc_me: mc_me@402dc000 { + compatible = "nxp,s32-mc-me"; + reg = <0x402dc000 0x4000>; + }; + + mc_rgm: mc_rgm@4028c000 { + compatible = "nxp,s32-mc-rgm"; + reg = <0x4028c000 0x4000>; + func-reset-threshold = <0>; + dest-reset-threshold = <0>; + }; }; }; diff --git a/dts/bindings/power/nxp,s32-mc-me.yaml b/dts/bindings/power/nxp,s32-mc-me.yaml new file mode 100644 index 00000000000..d519214da39 --- /dev/null +++ b/dts/bindings/power/nxp,s32-mc-me.yaml @@ -0,0 +1,12 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP S32 Module Entry (MC_ME) + +compatible: "nxp,s32-mc-me" + +include: base.yaml + +properties: + reg: + required: true diff --git a/dts/bindings/power/nxp,s32-mc-rgm.yaml b/dts/bindings/power/nxp,s32-mc-rgm.yaml new file mode 100644 index 00000000000..bd1e903a4de --- /dev/null +++ b/dts/bindings/power/nxp,s32-mc-rgm.yaml @@ -0,0 +1,37 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP S32 Module Reset Generation (MC_RGM) + +compatible: "nxp,s32-mc-rgm" + +include: base.yaml + +properties: + reg: + required: true + + func-reset-threshold: + type: int + enum: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + default: 15 + description: | + Functional Reset Escalation threshold. + If the value of this property is 0, the Functional reset escalation + function is disabled. Any other value is the number of Functional + resets that causes a Destructive reset, if the FRET register isn't + written to beforehand. + Default to maximum threshold (hardware reset value). + + dest-reset-threshold: + type: int + enum: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + default: 0 + description: | + Destructive Reset Escalation threshold. + If the value of this property is 0, the Destructive reset escalation + function is disabled. Any other value is the number of Destructive + resets which keeps the chip in the reset state until the next power-on + reset triggers a new reset sequence, if the DRET register isn't + written to beforehand. + Default to disabled (hardware reset value). diff --git a/dts/bindings/power/nxp,s32k3-pmc.yaml b/dts/bindings/power/nxp,s32k3-pmc.yaml new file mode 100644 index 00000000000..38deea32d54 --- /dev/null +++ b/dts/bindings/power/nxp,s32k3-pmc.yaml @@ -0,0 +1,36 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP S32K3xx Power Management Controller (PMC) + +compatible: "nxp,s32k3-pmc" + +include: base.yaml + +properties: + reg: + required: true + + lm-reg: + type: boolean + description: | + Enables the Last Mile regulator, which regulates an external 1.5V + voltage on V15 down to the core and logic supply (V11 power domain), + which is typically 1.1V. + When enabling PLL as system clock, the PMC Last Mile regulator should + be enabled. + + lm-reg-auto: + type: boolean + description: | + Enables to turn over automatically from Boot Regulator Mode to Last Mile + regulator mode and vice versa, depending on the V15 voltage status. + When configuring system clocks higher than FIRC clock frequency, + lm-reg should be also enabled. + + lm-reg-base-control: + type: boolean + description: | + Enable this if an external BJT between VDD_HV_A and V15 is used on the + PCB. The base of this BJT must be connected to the VRC_CTRL pin and is + controlled by the PMC to regulate a voltage of 1.5V on V15 pin. diff --git a/soc/nxp/s32/Kconfig b/soc/nxp/s32/Kconfig index 9b608588e21..e8a67cf405c 100644 --- a/soc/nxp/s32/Kconfig +++ b/soc/nxp/s32/Kconfig @@ -3,29 +3,6 @@ if SOC_FAMILY_NXP_S32 -config NXP_S32_FUNC_RESET_THRESHOLD - int "Functional Reset Escalation threshold" - default 15 - range 0 15 - help - If the value of this option is 0, the Functional reset escalation - function is disabled. Any other value is the number of Functional - resets that causes a Destructive reset, if the FRET register isn't - written to beforehand. - Default to maximum threshold (hardware reset value). - -config NXP_S32_DEST_RESET_THRESHOLD - int "Destructive Reset Escalation threshold" - default 0 - range 0 15 - help - If the value of this field is 0, the Destructive reset escalation - function is disabled. Any other value is the number of Destructive - resets which keeps the chip in the reset state until the next power-on - reset triggers a new reset sequence, if the DRET register isn't - written to beforehand. - Default to disabled (hardware reset value). - rsource "*/Kconfig" endif # SOC_FAMILY_NXP_S32 diff --git a/soc/nxp/s32/common/CMakeLists.txt b/soc/nxp/s32/common/CMakeLists.txt index 7b98b446338..a12a9dadd73 100644 --- a/soc/nxp/s32/common/CMakeLists.txt +++ b/soc/nxp/s32/common/CMakeLists.txt @@ -3,4 +3,5 @@ zephyr_include_directories(.) zephyr_sources(osif.c) -zephyr_sources_ifdef(CONFIG_SOC_SERIES_S32K3 power_soc.c) +zephyr_library_sources_ifdef(CONFIG_DT_HAS_NXP_S32_MC_RGM_ENABLED mc_rgm.c) +zephyr_library_sources_ifdef(CONFIG_DT_HAS_NXP_S32_MC_ME_ENABLED mc_me.c) diff --git a/soc/nxp/s32/common/mc_me.c b/soc/nxp/s32/common/mc_me.c new file mode 100644 index 00000000000..7b220eccfce --- /dev/null +++ b/soc/nxp/s32/common/mc_me.c @@ -0,0 +1,158 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_s32_mc_me + +#include +#if defined(CONFIG_REBOOT) +#include +#endif /* CONFIG_REBOOT */ + +/* Control Key Register */ +#define MC_ME_CTL_KEY 0x0 +#define MC_ME_CTL_KEY_KEY_MASK GENMASK(15, 0) +#define MC_ME_CTL_KEY_KEY(v) FIELD_PREP(MC_ME_CTL_KEY_KEY_MASK, (v)) +/* Mode Configuration Register */ +#define MC_ME_MODE_CONF 0x4 +#define MC_ME_MODE_CONF_DEST_RST_MASK BIT(0) +#define MC_ME_MODE_CONF_DEST_RST(v) FIELD_PREP(MC_ME_MODE_CONF_DEST_RST_MASK, (v)) +#define MC_ME_MODE_CONF_FUNC_RST_MASK BIT(1) +#define MC_ME_MODE_CONF_FUNC_RST(v) FIELD_PREP(MC_ME_MODE_CONF_FUNC_RST_MASK, (v)) +#define MC_ME_MODE_CONF_STANDBY_MASK BIT(15) +#define MC_ME_MODE_CONF_STANDBY(v) FIELD_PREP(MC_ME_MODE_CONF_STANDBY_MASK, (v)) +/* Mode Update Register */ +#define MC_ME_MODE_UPD 0x8 +#define MC_ME_MODE_UPD_MODE_UPD_MASK BIT(0) +#define MC_ME_MODE_UPD_MODE_UPD(v) FIELD_PREP(MC_ME_MODE_UPD_MODE_UPD_MASK, (v)) +/* Mode Status Register */ +#define MC_ME_MODE_STAT 0xc +#define MC_ME_MODE_STAT_PREV_MODE_MASK BIT(0) +#define MC_ME_MODE_STAT_PREV_MODE(v) FIELD_PREP(MC_ME_MODE_STAT_PREV_MODE_MASK, (v)) +/* Main Core ID Register */ +#define MC_ME_MAIN_COREID 0x10 +#define MC_ME_MAIN_COREID_CIDX_MASK GENMASK(2, 0) +#define MC_ME_MAIN_COREID_CIDX(v) FIELD_PREP(MC_ME_MAIN_COREID_CIDX_MASK, (v)) +#define MC_ME_MAIN_COREID_PIDX_MASK GENMASK(12, 8) +#define MC_ME_MAIN_COREID_PIDX(v) FIELD_PREP(MC_ME_MAIN_COREID_PIDX_MASK, (v)) +/* Partition p Process Configuration Register */ +#define MC_ME_PRTN_PCONF(p) (0x100 + 0x200 * (p)) +#define MC_ME_PRTN_PCONF_PCE_MASK BIT(0) +#define MC_ME_PRTN_PCONF_PCE(v) FIELD_PREP(MC_ME_PRTN_PCONF_PCE_MASK, (v)) +/* Partition p Process Update Register */ +#define MC_ME_PRTN_PUPD(p) (0x104 + 0x200 * (p)) +#define MC_ME_PRTN_PUPD_PCUD_MASK BIT(0) +#define MC_ME_PRTN_PUPD_PCUD(v) FIELD_PREP(MC_ME_PRTN_PUPD_PCUD_MASK, (v)) +/* Partition p Status Register */ +#define MC_ME_PRTN_STAT(p) (0x108 + 0x200 * (p)) +#define MC_ME_PRTN_STAT_PCS_MASK BIT(0) +#define MC_ME_PRTN_STAT_PCS(v) FIELD_PREP(MC_ME_PRTN_STAT_PCS_MASK, (v)) +/* Partition p COFB c Clock Status Register */ +#define MC_ME_PRTN_COFB_STAT(p, c) (0x110 + 0x200 * (p) + 0x4 * (c)) +/* Partition p COFB c Clock Enable Register */ +#define MC_ME_PRTN_COFB_CLKEN(p, c) (0x130 + 0x200 * (p) + 0x4 * (c)) +/* Partition p Core c Process Configuration Register */ +#define MC_ME_PRTN_CORE_PCONF(p, c) (0x140 + 0x200 * (p) + 0x20 * (c)) +#define MC_ME_PRTN_CORE_PCONF_CCE_MASK BIT(0) +#define MC_ME_PRTN_CORE_PCONF_CCE(v) FIELD_PREP(MC_ME_PRTN_CORE_PCONF_CCE_MASK, (v)) +/* Partition n Core c Process Update Register */ +#define MC_ME_PRTN_CORE_PUPD(p, c) (0x144 + 0x200 * (p) + 0x20 * (c)) +#define MC_ME_PRTN_CORE_PUPD_CCUPD_MASK BIT(0) +#define MC_ME_PRTN_CORE_PUPD_CCUPD(v) FIELD_PREP(MC_ME_PRTN_CORE_PUPD_CCUPD_MASK, (v)) +/* Partition n Core c Status Register */ +#define MC_ME_PRTN_CORE_STAT(p, c) (0x148 + 0x200 * (p) + 0x20 * (c)) +#define MC_ME_PRTN_CORE_STAT_CCS_MASK BIT(0) +#define MC_ME_PRTN_CORE_STAT_CCS(v) FIELD_PREP(MC_ME_PRTN_CORE_STAT_CCS_MASK, (v)) +#define MC_ME_PRTN_CORE_STAT_WFI_MASK BIT(31) +#define MC_ME_PRTN_CORE_STAT_WFI(v) FIELD_PREP(MC_ME_PRTN_CORE_STAT_WFI_MASK, (v)) +/* Partition n Core c Address Register */ +#define MC_ME_PRTN_CORE_ADDR(p, c) (0x14c + 0x200 * (p) + 0x20 * (c)) +#define MC_ME_PRTN_CORE_ADDR_ADDR_MASK GENMASK(31, 2) +#define MC_ME_PRTN_CORE_ADDR_ADDR(v) FIELD_PREP(MC_ME_PRTN_CORE_ADDR_ADDR_MASK, (v)) + +#define MC_ME_CTL_KEY_DIRECT_KEY 0x00005af0U +#define MC_ME_CTL_KEY_INVERTED_KEY 0x0000a50fU + +/* Handy accessors */ +#define REG_READ(r) sys_read32((mem_addr_t)(DT_INST_REG_ADDR(0) + (r))) +#define REG_WRITE(r, v) sys_write32((v), (mem_addr_t)(DT_INST_REG_ADDR(0) + (r))) + +/** MC_ME power mode */ +enum mc_me_power_mode { + /** Destructive Reset Mode */ + MC_ME_DEST_RESET_MODE, + /** Functional Reset Mode */ + MC_ME_FUNC_RESET_MODE, +}; + +#if defined(CONFIG_REBOOT) +static inline void mc_me_write_ctl_key(void) +{ + REG_WRITE(MC_ME_CTL_KEY, MC_ME_CTL_KEY_KEY(MC_ME_CTL_KEY_DIRECT_KEY)); + REG_WRITE(MC_ME_CTL_KEY, MC_ME_CTL_KEY_KEY(MC_ME_CTL_KEY_INVERTED_KEY)); +} + +static inline void mc_me_trigger_mode_update(void) +{ + REG_WRITE(MC_ME_MODE_UPD, MC_ME_MODE_UPD_MODE_UPD(1U)); + mc_me_write_ctl_key(); +} + +static int mc_me_set_mode(enum mc_me_power_mode mode) +{ + int err = 0; + + switch (mode) { + case MC_ME_DEST_RESET_MODE: + REG_WRITE(MC_ME_MODE_CONF, MC_ME_MODE_CONF_DEST_RST(1U)); + mc_me_trigger_mode_update(); + break; + case MC_ME_FUNC_RESET_MODE: + REG_WRITE(MC_ME_MODE_CONF, MC_ME_MODE_CONF_FUNC_RST(1U)); + mc_me_trigger_mode_update(); + break; + default: + err = -ENOTSUP; + break; + } + + return err; +} + +/* + * Overrides default weak implementation of system reboot. + * + * SYS_REBOOT_COLD (Destructive Reset): + * - Leads most parts of the chip, except a few modules, to reset. SRAM content + * is lost after this reset event. + * - Flash is always reset, so an updated value of the option bits is reloaded + * in volatile registers outside of the Flash array. + * - Trimming is lost. + * - STCU is reset and configured BISTs are executed. + * + * SYS_REBOOT_WARM (Functional Reset): + * - Leads all the communication peripherals and cores to reset. The communication + * protocols' sanity is not guaranteed and they are assumed to be reinitialized + * after reset. The SRAM content, and the functionality of certain modules, is + * preserved across functional reset. + * - The volatile registers are not reset; in case of a reset event, the + * trimming is maintained. + * - No BISTs are executed after functional reset. + */ +void sys_arch_reboot(int type) +{ + switch (type) { + case SYS_REBOOT_COLD: + mc_me_set_mode(MC_ME_DEST_RESET_MODE); + break; + case SYS_REBOOT_WARM: + mc_me_set_mode(MC_ME_FUNC_RESET_MODE); + break; + default: + /* Do nothing */ + break; + } +} +#endif /* CONFIG_REBOOT */ diff --git a/soc/nxp/s32/common/mc_rgm.c b/soc/nxp/s32/common/mc_rgm.c new file mode 100644 index 00000000000..d7ada34d6ec --- /dev/null +++ b/soc/nxp/s32/common/mc_rgm.c @@ -0,0 +1,122 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_s32_mc_rgm + +#include +#include + +/* Destructive Event Status Register */ +#define MC_RGM_DES 0x0 +#define MC_RGM_DES_F_POR_MASK BIT(0) +#define MC_RGM_DES_F_POR(v) FIELD_PREP(MC_RGM_DES_F_POR_MASK, (v)) +/* Functional / External Reset Status Register */ +#define MC_RGM_FES 0x8 +#define MC_RGM_FES_F_EXR_MASK BIT(0) +#define MC_RGM_FES_F_EXR(v) FIELD_PREP(MC_RGM_FES_F_EXR_MASK, (v)) +/* Functional Event Reset Disable Register */ +#define MC_RGM_FERD 0xc +/* Functional Bidirectional Reset Enable Register */ +#define MC_RGM_FBRE 0x10 +/* Functional Reset Escalation Counter Register */ +#define MC_RGM_FREC 0x14 +#define MC_RGM_FREC_FREC_MASK GENMASK(3, 0) +#define MC_RGM_FREC_FREC(v) FIELD_PREP(MC_RGM_FREC_FREC_MASK, (v)) +/* Functional Reset Escalation Threshold Register */ +#define MC_RGM_FRET 0x18 +#define MC_RGM_FRET_FRET_MASK GENMASK(3, 0) +#define MC_RGM_FRET_FRET(v) FIELD_PREP(MC_RGM_FRET_FRET_MASK, (v)) +/* Destructive Reset Escalation Threshold Register */ +#define MC_RGM_DRET 0x1c +#define MC_RGM_DRET_DRET_MASK GENMASK(3, 0) +#define MC_RGM_DRET_DRET(v) FIELD_PREP(MC_RGM_DRET_DRET_MASK, (v)) +/* External Reset Control Register */ +#define MC_RGM_ERCTRL 0x20 +#define MC_RGM_ERCTRL_ERASSERT_MASK BIT(0) +#define MC_RGM_ERCTRL_ERASSERT(v) FIELD_PREP(MC_RGM_ERCTRL_ERASSERT_MASK, (v)) +/* Reset During Standby Status Register */ +#define MC_RGM_RDSS 0x24 +#define MC_RGM_RDSS_DES_RES_MASK BIT(0) +#define MC_RGM_RDSS_DES_RES(v) FIELD_PREP(MC_RGM_RDSS_DES_RES_MASK, (v)) +#define MC_RGM_RDSS_FES_RES_MASK BIT(1) +#define MC_RGM_RDSS_FES_RES(v) FIELD_PREP(MC_RGM_RDSS_FES_RES_MASK, (v)) +/* Functional Reset Entry Timeout Control Register */ +#define MC_RGM_FRENTC 0x28 +#define MC_RGM_FRENTC_FRET_EN_MASK BIT(0) +#define MC_RGM_FRENTC_FRET_EN(v) FIELD_PREP(MC_RGM_FRENTC_FRET_EN_MASK, (v)) +#define MC_RGM_FRENTC_FRET_TIMEOUT_MASK GENMASK(31, 1) +#define MC_RGM_FRENTC_FRET_TIMEOUT(v) FIELD_PREP(MC_RGM_FRENTC_FRET_TIMEOUT_MASK, (v)) +/* Low Power Debug Control Register */ +#define MC_RGM_LPDEBUG 0x2c +#define MC_RGM_LPDEBUG_LP_DBG_EN_MASK BIT(0) +#define MC_RGM_LPDEBUG_LP_DBG_EN(v) FIELD_PREP(MC_RGM_LPDEBUG_LP_DBG_EN_MASK, (v)) + +#define MC_RGM_TIMEOUT_US 50000U + +/* Handy accessors */ +#define REG_READ(r) sys_read32((mem_addr_t)(DT_INST_REG_ADDR(0) + (r))) +#define REG_WRITE(r, v) sys_write32((v), (mem_addr_t)(DT_INST_REG_ADDR(0) + (r))) + +static int mc_rgm_clear_reset_status(uint32_t reg) +{ + bool timeout; + + /* + * Register bits are cleared on write 1 if the triggering event has already + * been cleared at the source + */ + timeout = !WAIT_FOR(REG_READ(reg) == 0U, MC_RGM_TIMEOUT_US, REG_WRITE(reg, 0xffffffff)); + return timeout ? -ETIMEDOUT : 0U; +} + +static int mc_rgm_init(const struct device *dev) +{ + int err = 0; + uint32_t rst_status; + + ARG_UNUSED(dev); + + /* + * MC_RGM_FES must be cleared before writing 1 to any of the fields in MC_RGM_FERD, + * otherwise an interrupt request may occur + */ + rst_status = REG_READ(MC_RGM_FES); + if (rst_status != 0U) { + err = mc_rgm_clear_reset_status(MC_RGM_FES); + if (err) { + return err; + } + } + + /* All functional reset sources generate a reset event */ + REG_WRITE(MC_RGM_FERD, 0U); + + rst_status = REG_READ(MC_RGM_DES); + if ((DT_INST_PROP(0, func_reset_threshold) != 0U) && (rst_status != 0U)) { + /* MC_RGM_FRET value is reset on power-on and any destructive reset */ + REG_WRITE(MC_RGM_FRET, MC_RGM_FRET_FRET(DT_INST_PROP(0, func_reset_threshold))); + } else { + REG_WRITE(MC_RGM_FRET, MC_RGM_FRET_FRET(0U)); + } + + if ((DT_INST_PROP(0, dest_reset_threshold) != 0U) && + (FIELD_GET(MC_RGM_DES_F_POR_MASK, rst_status) != 0U)) { + /* MC_RGM_DRET value is reset only on power-on reset */ + REG_WRITE(MC_RGM_DRET, MC_RGM_DRET_DRET(DT_INST_PROP(0, dest_reset_threshold))); + } else { + REG_WRITE(MC_RGM_DRET, MC_RGM_DRET_DRET(0U)); + } + + /* Clear destructive reset status to avoid persisting it across resets */ + err = mc_rgm_clear_reset_status(MC_RGM_DES); + if (err) { + return err; + } + + return err; +} + +DEVICE_DT_INST_DEFINE(0, mc_rgm_init, NULL, NULL, 0, PRE_KERNEL_1, 1, NULL); diff --git a/soc/nxp/s32/common/power_soc.c b/soc/nxp/s32/common/power_soc.c deleted file mode 100644 index 86414354200..00000000000 --- a/soc/nxp/s32/common/power_soc.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2023 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#ifdef CONFIG_REBOOT -#include -#endif - -#include - -#ifdef CONFIG_REBOOT -BUILD_ASSERT(POWER_IP_PERFORM_RESET_API == STD_ON, "Power Reset API must be enabled"); - -/* - * Overrides default weak implementation of system reboot. - * - * SYS_REBOOT_COLD (Destructive Reset): - * - Leads most parts of the chip, except a few modules, to reset. SRAM content - * is lost after this reset event. - * - Flash is always reset, so an updated value of the option bits is reloaded - * in volatile registers outside of the Flash array. - * - Trimming is lost. - * - STCU is reset and configured BISTs are executed. - * - * SYS_REBOOT_WARM (Functional Reset): - * - Leads all the communication peripherals and cores to reset. The communication - * protocols' sanity is not guaranteed and they are assumed to be reinitialized - * after reset. The SRAM content, and the functionality of certain modules, is - * preserved across functional reset. - * - The volatile registers are not reset; in case of a reset event, the - * trimming is maintained. - * - No BISTs are executed after functional reset. - */ -void sys_arch_reboot(int type) -{ - Power_Ip_MC_RGM_ConfigType mc_rgm_cfg = { 0 }; - - const Power_Ip_HwIPsConfigType power_cfg = { - .McRgmConfigPtr = (const Power_Ip_MC_RGM_ConfigType *)&mc_rgm_cfg, - .PMCConfigPtr = NULL - }; - - switch (type) { - case SYS_REBOOT_COLD: - /* Destructive reset */ - mc_rgm_cfg.ResetType = MCU_DEST_RESET; - Power_Ip_PerformReset(&power_cfg); - break; - case SYS_REBOOT_WARM: - /* Functional reset */ - mc_rgm_cfg.ResetType = MCU_FUNC_RESET; - Power_Ip_PerformReset(&power_cfg); - break; - default: - /* Do nothing */ - break; - } -} -#endif /* CONFIG_REBOOT */ - -static int nxp_s32_power_init(void) -{ - const Power_Ip_MC_RGM_ConfigType mc_rgm_cfg = { - .FuncResetOpt = 0U, /* All functional reset sources enabled */ - .FesThresholdReset = MC_RGM_FRET_FRET(CONFIG_NXP_S32_FUNC_RESET_THRESHOLD), - .DesThresholdReset = MC_RGM_DRET_DRET(CONFIG_NXP_S32_DEST_RESET_THRESHOLD) - }; - - const Power_Ip_PMC_ConfigType pmc_cfg = { -#ifdef CONFIG_SOC_SERIES_S32K3 - /* PMC Configuration Register (CONFIG) */ - .ConfigRegister = PMC_CONFIG_LMEN(IS_ENABLED(CONFIG_NXP_S32_PMC_LMEN)) - | PMC_CONFIG_LMBCTLEN(IS_ENABLED(CONFIG_NXP_S32_PMC_LMBCTLEN)), -#else -#error "SoC not supported" -#endif - }; - - const Power_Ip_HwIPsConfigType power_cfg = { - .McRgmConfigPtr = &mc_rgm_cfg, - .PMCConfigPtr = &pmc_cfg - }; - - Power_Ip_Init(&power_cfg); - - /* Read and clear the reset reason to avoid persisting it across resets */ - (void)Power_Ip_GetResetReason(); - - return 0; -} - -SYS_INIT(nxp_s32_power_init, PRE_KERNEL_1, 1); diff --git a/soc/nxp/s32/s32k3/CMakeLists.txt b/soc/nxp/s32/s32k3/CMakeLists.txt index 4d18223a61c..dda4a9833cf 100644 --- a/soc/nxp/s32/s32k3/CMakeLists.txt +++ b/soc/nxp/s32/s32k3/CMakeLists.txt @@ -6,6 +6,8 @@ zephyr_library() zephyr_include_directories(.) zephyr_library_sources(soc.c) +zephyr_library_sources_ifdef(CONFIG_DT_HAS_NXP_S32K3_PMC_ENABLED pmc.c) + zephyr_library_sources_ifdef(CONFIG_CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS mpu_regions.c) zephyr_linker_sources(SECTIONS sections.ld) zephyr_library_sources_ifdef(CONFIG_PLATFORM_SPECIFIC_INIT s32k3xx_startup.S) diff --git a/soc/nxp/s32/s32k3/Kconfig b/soc/nxp/s32/s32k3/Kconfig index 0ca5882062c..dd0cf6ea5c5 100644 --- a/soc/nxp/s32/s32k3/Kconfig +++ b/soc/nxp/s32/s32k3/Kconfig @@ -38,23 +38,4 @@ config IVT_HEADER_SIZE help Size of ivt header region -config NXP_S32_PMC_LMEN - bool "Last Mile regulator" - default y if CLOCK_CONTROL - help - Enables the Last Mile regulator, which regulates an external 1.5V - voltage on V15 down to the core and logic supply (V11 power domain), - which is typically 1.1V. - When enabling PLL as system clock, the PMC last mile regulator should - be enabled. - -config NXP_S32_PMC_LMBCTLEN - bool "External BCTL regulator for V15" - depends on NXP_S32_PMC_LMEN - help - This option must be selected if an external BJT between VDD_HV_A and - V15 is used on the PCB. The base of this BJT must be connected to the - VRC_CTRL pin and is controlled by the PMC to regulate a voltage of - 1.5V on V15 pin. - endif # SOC_SERIES_S32K3 diff --git a/soc/nxp/s32/s32k3/pmc.c b/soc/nxp/s32/s32k3/pmc.c new file mode 100644 index 00000000000..28933d97e74 --- /dev/null +++ b/soc/nxp/s32/s32k3/pmc.c @@ -0,0 +1,136 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_s32k3_pmc + +#include +#include + +/* Low Voltage Status and Control Register */ +#define PMC_LVSC 0x0 +#define PMC_LVSC_HVDAF_MASK BIT(0) +#define PMC_LVSC_HVDAF(v) FIELD_PREP(PMC_LVSC_HVDAF_MASK, (v)) +#define PMC_LVSC_HVDBF_MASK BIT(1) +#define PMC_LVSC_HVDBF(v) FIELD_PREP(PMC_LVSC_HVDBF_MASK, (v)) +#define PMC_LVSC_HVD25F_MASK BIT(2) +#define PMC_LVSC_HVD25F(v) FIELD_PREP(PMC_LVSC_HVD25F_MASK, (v)) +#define PMC_LVSC_HVD11F_MASK BIT(3) +#define PMC_LVSC_HVD11F(v) FIELD_PREP(PMC_LVSC_HVD11F_MASK, (v)) +#define PMC_LVSC_LVD5AF_MASK BIT(4) +#define PMC_LVSC_LVD5AF(v) FIELD_PREP(PMC_LVSC_LVD5AF_MASK, (v)) +#define PMC_LVSC_LVD15F_MASK BIT(5) +#define PMC_LVSC_LVD15F(v) FIELD_PREP(PMC_LVSC_LVD15F_MASK, (v)) +#define PMC_LVSC_HVDAS_MASK BIT(8) +#define PMC_LVSC_HVDAS(v) FIELD_PREP(PMC_LVSC_HVDAS_MASK, (v)) +#define PMC_LVSC_HVDBS_MASK BIT(9) +#define PMC_LVSC_HVDBS(v) FIELD_PREP(PMC_LVSC_HVDBS_MASK, (v)) +#define PMC_LVSC_HVD25S_MASK BIT(10) +#define PMC_LVSC_HVD25S(v) FIELD_PREP(PMC_LVSC_HVD25S_MASK, (v)) +#define PMC_LVSC_HVD11S_MASK BIT(11) +#define PMC_LVSC_HVD11S(v) FIELD_PREP(PMC_LVSC_HVD11S_MASK, (v)) +#define PMC_LVSC_LVD5AS_MASK BIT(12) +#define PMC_LVSC_LVD5AS(v) FIELD_PREP(PMC_LVSC_LVD5AS_MASK, (v)) +#define PMC_LVSC_LVD15S_MASK BIT(13) +#define PMC_LVSC_LVD15S(v) FIELD_PREP(PMC_LVSC_LVD15S_MASK, (v)) +#define PMC_LVSC_LVRAF_MASK BIT(16) +#define PMC_LVSC_LVRAF(v) FIELD_PREP(PMC_LVSC_LVRAF_MASK, (v)) +#define PMC_LVSC_LVRALPF_MASK BIT(17) +#define PMC_LVSC_LVRALPF(v) FIELD_PREP(PMC_LVSC_LVRALPF_MASK, (v)) +#define PMC_LVSC_LVRBF_MASK BIT(18) +#define PMC_LVSC_LVRBF(v) FIELD_PREP(PMC_LVSC_LVRBF_MASK, (v)) +#define PMC_LVSC_LVRBLPF_MASK BIT(19) +#define PMC_LVSC_LVRBLPF(v) FIELD_PREP(PMC_LVSC_LVRBLPF_MASK, (v)) +#define PMC_LVSC_LVR25F_MASK BIT(20) +#define PMC_LVSC_LVR25F(v) FIELD_PREP(PMC_LVSC_LVR25F_MASK, (v)) +#define PMC_LVSC_LVR25LPF_MASK BIT(21) +#define PMC_LVSC_LVR25LPF(v) FIELD_PREP(PMC_LVSC_LVR25LPF_MASK, (v)) +#define PMC_LVSC_LVR11F_MASK BIT(22) +#define PMC_LVSC_LVR11F(v) FIELD_PREP(PMC_LVSC_LVR11F_MASK, (v)) +#define PMC_LVSC_LVR11LPF_MASK BIT(23) +#define PMC_LVSC_LVR11LPF(v) FIELD_PREP(PMC_LVSC_LVR11LPF_MASK, (v)) +#define PMC_LVSC_GNG25OSCF_MASK BIT(24) +#define PMC_LVSC_GNG25OSCF(v) FIELD_PREP(PMC_LVSC_GNG25OSCF_MASK, (v)) +#define PMC_LVSC_GNG11OSCF_MASK BIT(25) +#define PMC_LVSC_GNG11OSCF(v) FIELD_PREP(PMC_LVSC_GNG11OSCF_MASK, (v)) +#define PMC_LVSC_PORF_MASK BIT(31) +#define PMC_LVSC_PORF(v) FIELD_PREP(PMC_LVSC_PORF_MASK, (v)) +/* PMC Configuration Register */ +#define PMC_CONFIG 0x4 +#define PMC_CONFIG_LMEN_MASK BIT(0) +#define PMC_CONFIG_LMEN(v) FIELD_PREP(PMC_CONFIG_LMEN_MASK, (v)) +#define PMC_CONFIG_LMBCTLEN_MASK BIT(1) +#define PMC_CONFIG_LMBCTLEN(v) FIELD_PREP(PMC_CONFIG_LMBCTLEN_MASK, (v)) +#define PMC_CONFIG_FASTREC_MASK BIT(2) +#define PMC_CONFIG_FASTREC(v) FIELD_PREP(PMC_CONFIG_FASTREC_MASK, (v)) +#define PMC_CONFIG_LPM25EN_MASK BIT(3) +#define PMC_CONFIG_LPM25EN(v) FIELD_PREP(PMC_CONFIG_LPM25EN_MASK, (v)) +#define PMC_CONFIG_LVRBLPEN_MASK BIT(4) +#define PMC_CONFIG_LVRBLPEN(v) FIELD_PREP(PMC_CONFIG_LVRBLPEN_MASK, (v)) +#define PMC_CONFIG_HVDIE_MASK BIT(8) +#define PMC_CONFIG_HVDIE(v) FIELD_PREP(PMC_CONFIG_HVDIE_MASK, (v)) +#define PMC_CONFIG_LVDIE_MASK BIT(9) +#define PMC_CONFIG_LVDIE(v) FIELD_PREP(PMC_CONFIG_LVDIE_MASK, (v)) +#define PMC_CONFIG_LMAUTOEN_MASK BIT(16) +#define PMC_CONFIG_LMAUTOEN(v) FIELD_PREP(PMC_CONFIG_LMAUTOEN_MASK, (v)) +#define PMC_CONFIG_LMSTAT_MASK BIT(17) +#define PMC_CONFIG_LMSTAT(v) FIELD_PREP(PMC_CONFIG_LMSTAT_MASK, (v)) +/* Version ID register */ +#define PMC_VERID 0xc +#define PMC_VERID_LMFEAT_MASK BIT(0) +#define PMC_VERID_LMFEAT(v) FIELD_PREP(PMC_VERID_LMFEAT_MASK, (v)) +#define PMC_VERID_MINOR_MASK GENMASK(23, 16) +#define PMC_VERID_MINOR(v) FIELD_PREP(PMC_VERID_MINOR_MASK, (v)) +#define PMC_VERID_MAJOR_MASK GENMASK(31, 24) +#define PMC_VERID_MAJOR(v) FIELD_PREP(PMC_VERID_MAJOR_MASK, (v)) + +/* Handy accessors */ +#define REG_READ(r) sys_read32((mem_addr_t)(DT_INST_REG_ADDR(0) + (r))) +#define REG_WRITE(r, v) sys_write32((v), (mem_addr_t)(DT_INST_REG_ADDR(0) + (r))) + +#define PMC_TIMEOUT_US 10000U + +static int pmc_init(const struct device *dev) +{ + uint32_t reg_val; + + ARG_UNUSED(dev); + + /* Clear Low Voltage Status flags after initial power ramp-up */ + REG_WRITE(PMC_LVSC, 0xffffffffU); + + /* Last Mile regulator initialization */ + reg_val = PMC_CONFIG_LMEN(DT_INST_PROP(0, lm_reg)) | + PMC_CONFIG_LMAUTOEN(DT_INST_PROP(0, lm_reg_auto)) | + PMC_CONFIG_LMBCTLEN(DT_INST_PROP(0, lm_reg_base_control)); + + if (DT_INST_PROP(0, lm_reg)) { + REG_WRITE(PMC_CONFIG, reg_val & ~PMC_CONFIG_LMEN_MASK); + /* + * If external BJT is using on the PCB board, wait for the LVD15 to go above + * low-voltage detect threshold before enabling LMEN + */ + if (DT_INST_PROP(0, lm_reg_base_control)) { + if (!WAIT_FOR(FIELD_GET(PMC_LVSC_LVD15S_MASK, REG_READ(PMC_LVSC)) == 0U, + PMC_TIMEOUT_US, k_busy_wait(10U))) { + return -ETIMEDOUT; + } + } + REG_WRITE(PMC_CONFIG, REG_READ(PMC_CONFIG) | PMC_CONFIG_LMEN(1U)); + } else { + REG_WRITE(PMC_CONFIG, reg_val); + if (DT_INST_PROP(0, lm_reg_auto)) { + /* Wait for Last Mile regulator to be turned on */ + if (!WAIT_FOR(FIELD_GET(PMC_CONFIG_LMSTAT_MASK, REG_READ(PMC_CONFIG)) == 1U, + PMC_TIMEOUT_US, k_busy_wait(10U))) { + return -ETIMEDOUT; + } + } + } + + return 0; +} + +DEVICE_DT_INST_DEFINE(0, pmc_init, NULL, NULL, 0, PRE_KERNEL_1, 1, NULL); diff --git a/west.yml b/west.yml index 5013d92773d..3962532dfbb 100644 --- a/west.yml +++ b/west.yml @@ -198,7 +198,7 @@ manifest: groups: - hal - name: hal_nxp - revision: 220a4b285d226483a846e41d95abf8ab415b83e3 + revision: 4f9ef3bc4e9ff1a2a57c8add2ab2a02b2162989b path: modules/hal/nxp groups: - hal