From e6bb7fc6cf2aedd64d7acdd03c403e6d4e742dfe Mon Sep 17 00:00:00 2001 From: Titan Chen Date: Thu, 6 Mar 2025 19:22:44 +0800 Subject: [PATCH] soc : realtek: ec: rts5912: add support ULPM Port rts5912 ULPM on Zephyr Signed-off-by: Titan Chen --- dts/arm/realtek/ec/rts5912.dtsi | 39 +++++ dts/bindings/power/realtek,rts5912-ulpm.yaml | 45 +++++ soc/realtek/ec/rts5912/CMakeLists.txt | 2 + soc/realtek/ec/rts5912/Kconfig | 8 + soc/realtek/ec/rts5912/poweroff.c | 23 +++ soc/realtek/ec/rts5912/reg/reg_system.h | 6 +- soc/realtek/ec/rts5912/rts5912_ulpm.c | 171 +++++++++++++++++++ soc/realtek/ec/rts5912/rts5912_ulpm.h | 20 +++ 8 files changed, 312 insertions(+), 2 deletions(-) create mode 100644 dts/bindings/power/realtek,rts5912-ulpm.yaml create mode 100644 soc/realtek/ec/rts5912/poweroff.c create mode 100644 soc/realtek/ec/rts5912/rts5912_ulpm.c create mode 100644 soc/realtek/ec/rts5912/rts5912_ulpm.h diff --git a/dts/arm/realtek/ec/rts5912.dtsi b/dts/arm/realtek/ec/rts5912.dtsi index 771bddf3803..0231ce9ea79 100644 --- a/dts/arm/realtek/ec/rts5912.dtsi +++ b/dts/arm/realtek/ec/rts5912.dtsi @@ -372,6 +372,45 @@ &jtag_clk_gpio90 &jtag_tms_gpio91>; pinctrl-names = "default"; }; + + ulpm: ulpm { + compatible = "realtek,rts5912-ulpm"; + wkup-pins-max = <6>; /* 6 system wake-up pins */ + status = "disabled"; + + #address-cells = <1>; + #size-cells = <0>; + + wkup-pin@0 { + reg = <0x0>; + wkup-pin-mode = "gpio"; + }; + + wkup-pin@1 { + reg = <0x1>; + wkup-pin-mode = "gpio"; + }; + + wkup-pin@2 { + reg = <0x2>; + wkup-pin-mode = "gpio"; + }; + + wkup-pin@3 { + reg = <0x3>; + wkup-pin-mode = "gpio"; + }; + + wkup-pin@4 { + reg = <0x4>; + wkup-pin-mode = "gpio"; + }; + + wkup-pin@5 { + reg = <0x5>; + wkup-pin-mode = "gpio"; + }; + }; }; &nvic { diff --git a/dts/bindings/power/realtek,rts5912-ulpm.yaml b/dts/bindings/power/realtek,rts5912-ulpm.yaml new file mode 100644 index 00000000000..32c5f492346 --- /dev/null +++ b/dts/bindings/power/realtek,rts5912-ulpm.yaml @@ -0,0 +1,45 @@ +# Copyright (c) 2025 Realtek Semiconductor Corporation, SIBG-SD7 +# SPDX-License-Identifier: Apache-2.0 + +description: RTS5912 ULPM power controller + +compatible: "realtek,rts5912-ulpm" + +include: base.yaml + +properties: + wkup-pins-max: + type: int + description: | + Max nbr of system wake-up pins. + For example wkup-pins-nb = <5>; on the rts5912 + +child-binding: + description: | + RTS5912 wake-up pin node. + + All nodes using this binding must be named "wkup-pin@[index]" + index starts from 0 + + properties: + reg: + type: array + required: true + description: Wake-up pin identifier, same as "index" in node name + + wkup-pin-pol: + type: string + default: rising + description: indicates a wakeup polarity + enum: + - rising + - falling + + wkup-pin-mode: + type: string + default: vin + required: true + description: indicates a wakeup pin mode selection + enum: + - vin + - gpio diff --git a/soc/realtek/ec/rts5912/CMakeLists.txt b/soc/realtek/ec/rts5912/CMakeLists.txt index a9e58c970ac..b10306f1768 100644 --- a/soc/realtek/ec/rts5912/CMakeLists.txt +++ b/soc/realtek/ec/rts5912/CMakeLists.txt @@ -13,5 +13,7 @@ zephyr_sources_ifdef(CONFIG_PM ) zephyr_sources_ifdef(CONFIG_RTS5912_DEBUG_SWJ debug_swj.c) +zephyr_sources_ifdef(CONFIG_POWEROFF poweroff.c) +zephyr_sources_ifdef(CONFIG_SOC_RTS5912_ULPM rts5912_ulpm.c) set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/realtek/ec/rts5912/Kconfig b/soc/realtek/ec/rts5912/Kconfig index c3a86e9b8e1..6673b017207 100644 --- a/soc/realtek/ec/rts5912/Kconfig +++ b/soc/realtek/ec/rts5912/Kconfig @@ -29,4 +29,12 @@ config RTS5912_DEBUG_SWJ help Enables the serial wire JTAG connection on the RTS5912 EC. +config SOC_RTS5912_ULPM + bool "Realtek RTS5912 ULPM (Ultra Low Power Mode)" + default y + depends on DT_HAS_REALTEK_RTS5912_ULPM_ENABLED + select HAS_POWEROFF + help + Enable support for RTS5912 ULPM PWR wake-up pins. + endif # SOC_SERIES_RTS5912 diff --git a/soc/realtek/ec/rts5912/poweroff.c b/soc/realtek/ec/rts5912/poweroff.c new file mode 100644 index 00000000000..e95e95574da --- /dev/null +++ b/soc/realtek/ec/rts5912/poweroff.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 Realtek Semiconductor Corporation, SIBG-SD7 + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "rts5912_ulpm.h" + +void z_sys_poweroff(void) +{ + if (IS_ENABLED(CONFIG_SOC_RTS5912_ULPM)) { + rts5912_ulpm_enable(); + + /* Spin and wait for ULPM */ + while (1) { + ; + } + CODE_UNREACHABLE; + } +} diff --git a/soc/realtek/ec/rts5912/reg/reg_system.h b/soc/realtek/ec/rts5912/reg/reg_system.h index 673baf4ac35..745d6319674 100644 --- a/soc/realtek/ec/rts5912/reg/reg_system.h +++ b/soc/realtek/ec/rts5912/reg/reg_system.h @@ -294,8 +294,8 @@ typedef struct { #define SYSTEM_VIVOCTRL_VIN2POL_Msk BIT(SYSTEM_VIVOCTRL_VIN2POL_Pos) #define SYSTEM_VIVOCTRL_VIN3POL_Pos (15UL) #define SYSTEM_VIVOCTRL_VIN3POL_Msk BIT(SYSTEM_VIVOCTRL_VIN3POL_Pos) -#define SYSTEM_VIVOCTRL_VIN4POL_Pos (16UL) -#define SYSTEM_VIVOCTRL_VIN4POL_Msk BIT(SYSTEM_VIVOCTRL_VIN4POL_Pos) +#define SYSTEM_VIVOCTRL_VODEF_Pos (16UL) +#define SYSTEM_VIVOCTRL_VODEF_Msk BIT(SYSTEM_VIVOCTRL_VODEF_Pos) #define SYSTEM_VIVOCTRL_VIN5POL_Pos (17UL) #define SYSTEM_VIVOCTRL_VIN5POL_Msk BIT(SYSTEM_VIVOCTRL_VIN5POL_Pos) #define SYSTEM_VIVOCTRL_REGWREN_Pos (30UL) @@ -332,4 +332,6 @@ typedef struct { #define SYSTEM_PERICLKPWR2_RC32KSRC_Pos (30UL) #define SYSTEM_PERICLKPWR2_RC32KSRC_Msk GENMASK(31, 30) +#define RTS5912_SCCON_REG_BASE ((SYSTEM_Type *)(DT_REG_ADDR(DT_NODELABEL(sccon)))) + #endif /* ZEPHYR_SOC_REALTEK_RTS5912_REG_SYSTEM_H */ diff --git a/soc/realtek/ec/rts5912/rts5912_ulpm.c b/soc/realtek/ec/rts5912/rts5912_ulpm.c new file mode 100644 index 00000000000..64ec787b7b3 --- /dev/null +++ b/soc/realtek/ec/rts5912/rts5912_ulpm.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2025 Realtek Semiconductor Corporation, SIBG-SD7 + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "rts5912_ulpm.h" +#include "reg/reg_system.h" +#include "reg/reg_gpio.h" +#include + +LOG_MODULE_REGISTER(ulpm, CONFIG_SOC_LOG_LEVEL); + +#define DT_DRV_COMPAT realtek_rts5912_ulpm + +BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) <= 1, "Unsupported number of instances"); + +#define RTS5912_ULPM_NODE DT_DRV_INST(0) + +#define ULPM_RTS5912_MAX_NB_WKUP_PINS DT_INST_PROP(0, wkup_pins_max) + +/** @cond INTERNAL_HIDDEN */ + +/** + * @brief flags for wake-up pin polarity configuration + * @{ + */ +enum wkup_pin_mode { + RTS5912_ULPM_WKUP_PIN_MODE_VIN = 0, + RTS5912_ULPM_WKUP_PIN_MODE_GPIO = 1, +}; + +enum wkup_pin_pol { + /* detection of wake-up event on the high level : rising edge */ + RTS5912_ULPM_WKUP_PIN_POL_RISING = 0, + /* detection of wake-up event on the low level : falling edge */ + RTS5912_ULPM_WKUP_PIN_POL_FALLING = 1, +}; +/** @} */ + +/** + * @brief Structure for storing the devicetree configuration of a wake-up pin. + */ +struct wkup_pin_dt_cfg_t { + /* starts from 0 */ + uint32_t wkup_pin_id; + /* wake up polarity */ + enum wkup_pin_pol pin_pol; + /* wake up pin mode, VIN / GPIO */ + enum wkup_pin_mode pin_mode; +}; + +/** + * @brief Get wake-up pin configuration from a given devicetree node. + * + * This returns a static initializer for a struct wkup_pin_dt_cfg_t + * filled with data from a given devicetree node. + * + * @param node_id Devicetree node identifier. + * + * @return Static initializer for a wkup_pin_dt_cfg_t structure. + */ +#define WKUP_PIN_CFG_DT(node_id) \ + { \ + .wkup_pin_id = DT_REG_ADDR(node_id), \ + .pin_pol = (uint8_t)DT_ENUM_IDX(node_id, wkup_pin_pol), \ + .pin_mode = (uint8_t)DT_ENUM_IDX(node_id, wkup_pin_mode), \ + } + +/* wkup_pin idx starts from 0 */ +#define WKUP_PIN_CFG_DT_COMMA(wkup_pin_id) WKUP_PIN_CFG_DT(wkup_pin_id), + +/** @endcond */ + +static struct wkup_pin_dt_cfg_t wkup_pins_cfgs[] = { + DT_INST_FOREACH_CHILD(0, WKUP_PIN_CFG_DT_COMMA)}; + +#define WKUP_PIN_SIZE ARRAY_SIZE(wkup_pins_cfgs) +/** + * @brief Enable VOUT function and set the VOUT default value. + */ +void ulpm_start(void) +{ + SYSTEM_Type *sys_reg = RTS5912_SCCON_REG_BASE; + /* enable VOUT */ + sys_reg->VIVOCTRL &= ~(SYSTEM_VIVOCTRL_VOUTMD_Msk); + k_msleep(10); + /* Set the VOUT to low */ + sys_reg->VIVOCTRL &= ~(SYSTEM_VIVOCTRL_VODEF_Msk); + k_msleep(10); + /* update to ULPM */ + sys_reg->VIVOCTRL |= SYSTEM_VIVOCTRL_REGWREN_Msk; + k_msleep(10); +} +/** + * @brief Update register value to ULPM IP + */ +void update_vivo_register(void) +{ + SYSTEM_Type *sys_reg = RTS5912_SCCON_REG_BASE; + /* Update Register & reset bit */ + k_msleep(10); + sys_reg->VIVOCTRL |= SYSTEM_VIVOCTRL_REGWREN_Msk; + k_msleep(10); + sys_reg->VIVOCTRL &= ~(SYSTEM_VIVOCTRL_REGWREN_Msk); + k_msleep(10); +} + +/** + * @brief Configure & enable a wake-up pin. + * + * @param wakeup_pin_cfg wake-up pin runtime configuration. + * + */ +void rts5912_ulpm_enable(void) +{ + SYSTEM_Type *sys_reg = RTS5912_SCCON_REG_BASE; + int i, id; + + LOG_INF("rts5912 ULPM enabled\n"); + /* VoutEnable, Keep VOUT output default value as bit 16 */ + sys_reg->VIVOCTRL |= SYSTEM_VIVOCTRL_VODEF_Msk; + k_msleep(10); + + /* set to GPIO mode to clear status and aviod mis-trigger */ + sys_reg->VIVOCTRL |= (SYSTEM_VIVOCTRL_VIN0MD_Msk | SYSTEM_VIVOCTRL_VIN1MD_Msk | + SYSTEM_VIVOCTRL_VIN2MD_Msk | SYSTEM_VIVOCTRL_VIN3MD_Msk | + SYSTEM_VIVOCTRL_VIN4MD_Msk | SYSTEM_VIVOCTRL_VIN5MD_Msk); + + /* Update Status Bit to ULPM IP */ + update_vivo_register(); + /* Configure Mode (VIN/GPIO) and Edge (Falling/Rising) */ + for (i = 0; i < WKUP_PIN_SIZE; i++) { + id = wkup_pins_cfgs[i].wkup_pin_id; + /* corner case test */ + if ((id < 0) || (id >= ULPM_RTS5912_MAX_NB_WKUP_PINS)) { + continue; + } + + /* Configure Mode */ + if (wkup_pins_cfgs[i].pin_mode == RTS5912_ULPM_WKUP_PIN_MODE_VIN) { + LOG_DBG("setup VIN%d in ", id); + /* Configure Polarity */ + if (wkup_pins_cfgs[i].pin_pol == RTS5912_ULPM_WKUP_PIN_POL_RISING) { + /* Falling Edge */ + sys_reg->VIVOCTRL |= BIT(SYSTEM_VIVOCTRL_VIN0POL_Pos + id); + LOG_DBG("Falling Edge\n"); + } else { + /* Rising Edge */ + sys_reg->VIVOCTRL &= ~BIT(SYSTEM_VIVOCTRL_VIN0POL_Pos + id); + LOG_DBG("Rising Edge\n"); + } + /* VIN Mode */ + sys_reg->VIVOCTRL &= ~BIT(SYSTEM_VIVOCTRL_VIN0MD_Pos + id); + } + } + + /* Update Status Bit to ULPM IP */ + update_vivo_register(); + + /* Disable LDO 2 power. */ + sys_reg->LDOCTRL &= ~(SYSTEM_LDOCTRL_LDO2EN_Msk); + + /* ULPM Start */ + ulpm_start(); +} diff --git a/soc/realtek/ec/rts5912/rts5912_ulpm.h b/soc/realtek/ec/rts5912/rts5912_ulpm.h new file mode 100644 index 00000000000..daabffb60ed --- /dev/null +++ b/soc/realtek/ec/rts5912/rts5912_ulpm.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Realtek Semiconductor Corporation, SIBG-SD7 + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_REALTEK_RTS5912_ULPM_H_ +#define ZEPHYR_SOC_REALTEK_RTS5912_ULPM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void rts5912_ulpm_enable(void); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_SOC_REALTEK_RTS5912_ULPM_H_ */