soc : realtek: ec: rts5912: add support ULPM

Port rts5912 ULPM on Zephyr

Signed-off-by: Titan Chen <titan.chen@realtek.com>
This commit is contained in:
Titan Chen 2025-03-06 19:22:44 +08:00 committed by Benjamin Cabé
commit e6bb7fc6cf
8 changed files with 312 additions and 2 deletions

View file

@ -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 {

View file

@ -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

View file

@ -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 "")

View file

@ -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

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2025 Realtek Semiconductor Corporation, SIBG-SD7
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/sys/poweroff.h>
#include <zephyr/toolchain.h>
#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;
}
}

View file

@ -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 */

View file

@ -0,0 +1,171 @@
/*
* Copyright (c) 2025 Realtek Semiconductor Corporation, SIBG-SD7
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/devicetree.h>
#include "rts5912_ulpm.h"
#include "reg/reg_system.h"
#include "reg/reg_gpio.h"
#include <zephyr/logging/log.h>
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 <tt>struct wkup_pin_dt_cfg_t</tt>
* 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();
}

View file

@ -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_ */