|
| 1 | +/* |
| 2 | + * Copyright (c) 2025 Realtek Semiconductor Corporation, SIBG-SD7 |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: Apache-2.0 |
| 5 | + */ |
| 6 | + |
| 7 | +#include <zephyr/kernel.h> |
| 8 | +#include <zephyr/device.h> |
| 9 | +#include <zephyr/drivers/gpio.h> |
| 10 | +#include <zephyr/devicetree.h> |
| 11 | + |
| 12 | +#include "rts5912_ulpm.h" |
| 13 | +#include "reg/reg_system.h" |
| 14 | +#include "reg/reg_gpio.h" |
| 15 | +#include <zephyr/logging/log.h> |
| 16 | + |
| 17 | +LOG_MODULE_REGISTER(ulpm, CONFIG_SOC_LOG_LEVEL); |
| 18 | + |
| 19 | +#define DT_DRV_COMPAT realtek_rts5912_ulpm |
| 20 | + |
| 21 | +BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) <= 1, "Unsupported number of instances"); |
| 22 | + |
| 23 | +#define ULPM_SLEEP(x) k_msleep(x) |
| 24 | + |
| 25 | +#define RTS5912_ULPM_NODE DT_DRV_INST(0) |
| 26 | + |
| 27 | +#define ULPM_RTS5912_MAX_NB_WKUP_PINS DT_INST_PROP(0, wkup_pins_max) |
| 28 | + |
| 29 | +#define RTS5912_VIN_GPIO_INDEX 112 |
| 30 | +#define RTS5912_SCCON_REG_BASE ((SYSTEM_Type *)(DT_REG_ADDR(DT_NODELABEL(sccon)))) |
| 31 | +/** @cond INTERNAL_HIDDEN */ |
| 32 | + |
| 33 | +/** |
| 34 | + * @brief flags for wake-up pin polarity configuration |
| 35 | + * @{ |
| 36 | + */ |
| 37 | +#define RTS5912_ULPM_WKUP_PIN_MODE_VIN 0 |
| 38 | +#define RTS5912_ULPM_WKUP_PIN_MODE_GPIO 1 |
| 39 | +/* detection of wake-up event on the high level : rising edge */ |
| 40 | +#define RTS5912_ULPM_WKUP_PIN_POL_RISING 0 |
| 41 | +/* detection of wake-up event on the low level : falling edge */ |
| 42 | +#define RTS5912_ULPM_WKUP_PIN_POL_FALLING 1 |
| 43 | +/** @} */ |
| 44 | + |
| 45 | +/** |
| 46 | + * @brief Structure for storing the devicetree configuration of a wake-up pin. |
| 47 | + */ |
| 48 | +struct wkup_pin_dt_cfg_t { |
| 49 | + /* starts from 0 */ |
| 50 | + uint32_t wkup_pin_id; |
| 51 | + /* wake up polarity */ |
| 52 | + uint8_t wkup_pin_pol; |
| 53 | + /* wake up polarity auto detect and set */ |
| 54 | + bool wkup_pin_pol_auto; |
| 55 | + /* wake up pin mode, VIN / GPIO */ |
| 56 | + uint8_t wkup_pin_mode; |
| 57 | +}; |
| 58 | + |
| 59 | +#define WKUP_PIN_NODE_LABEL(i) wkup_pin_##i |
| 60 | + |
| 61 | +#define WKUP_PIN_NODE_ID_BY_IDX(idx) DT_CHILD(STM32_PWR_NODE, WKUP_PIN_NODE_LABEL(idx)) |
| 62 | + |
| 63 | +/** |
| 64 | + * @brief Get wake-up pin configuration from a given devicetree node. |
| 65 | + * |
| 66 | + * This returns a static initializer for a <tt>struct wkup_pin_dt_cfg_t</tt> |
| 67 | + * filled with data from a given devicetree node. |
| 68 | + * |
| 69 | + * @param node_id Devicetree node identifier. |
| 70 | + * |
| 71 | + * @return Static initializer for a wkup_pin_dt_cfg_t structure. |
| 72 | + */ |
| 73 | +#define WKUP_PIN_CFG_DT(node_id) \ |
| 74 | + { \ |
| 75 | + .wkup_pin_id = DT_REG_ADDR(node_id), \ |
| 76 | + .wkup_pin_pol = (uint8_t)DT_ENUM_IDX(node_id, wkup_pin_pol), \ |
| 77 | + .wkup_pin_mode = (uint8_t)DT_ENUM_IDX(node_id, wkup_pin_mode), \ |
| 78 | + } |
| 79 | + |
| 80 | +/* wkup_pin idx starts from 0 */ |
| 81 | +#define WKUP_PIN_CFG_DT_COMMA(wkup_pin_id) WKUP_PIN_CFG_DT(wkup_pin_id), |
| 82 | + |
| 83 | +/** @endcond */ |
| 84 | + |
| 85 | +static struct wkup_pin_dt_cfg_t wkup_pins_cfgs[] = { |
| 86 | + DT_INST_FOREACH_CHILD(0, WKUP_PIN_CFG_DT_COMMA)}; |
| 87 | + |
| 88 | +#define WKUP_PIN_SIZE ARRAY_SIZE(wkup_pins_cfgs) |
| 89 | +/** |
| 90 | + * @brief Enable VOUT function and set the VOUT default value. |
| 91 | + */ |
| 92 | +void ulpm_start(void) |
| 93 | +{ |
| 94 | + SYSTEM_Type *sys_reg = RTS5912_SCCON_REG_BASE; |
| 95 | + /* enable VOUT */ |
| 96 | + sys_reg->VIVOCTRL &= ~(SYSTEM_VIVOCTRL_VOUTMD_Msk); |
| 97 | + ULPM_SLEEP(10); |
| 98 | + /* Set the VOUT to low */ |
| 99 | + sys_reg->VIVOCTRL &= ~(SYSTEM_VIVOCTRL_VODEF_Msk); |
| 100 | + ULPM_SLEEP(10); |
| 101 | + /* update to ULPM */ |
| 102 | + sys_reg->VIVOCTRL |= SYSTEM_VIVOCTRL_REGWREN_Msk; |
| 103 | + ULPM_SLEEP(10); |
| 104 | +} |
| 105 | +/** |
| 106 | + * @brief Update register value to ULPM IP |
| 107 | + */ |
| 108 | +void update_vivo_register(void) |
| 109 | +{ |
| 110 | + SYSTEM_Type *sys_reg = RTS5912_SCCON_REG_BASE; |
| 111 | + /* Update Register & reset bit */ |
| 112 | + ULPM_SLEEP(10); |
| 113 | + sys_reg->VIVOCTRL |= SYSTEM_VIVOCTRL_REGWREN_Msk; |
| 114 | + ULPM_SLEEP(10); |
| 115 | + sys_reg->VIVOCTRL &= ~(SYSTEM_VIVOCTRL_REGWREN_Msk); |
| 116 | + ULPM_SLEEP(10); |
| 117 | +} |
| 118 | + |
| 119 | +/** |
| 120 | + * @brief Configure & enable a wake-up pin. |
| 121 | + * |
| 122 | + * @param wakeup_pin_cfg wake-up pin runtime configuration. |
| 123 | + * |
| 124 | + */ |
| 125 | +void rts5912_ulpm_enable(void) |
| 126 | +{ |
| 127 | + SYSTEM_Type *sys_reg = RTS5912_SCCON_REG_BASE; |
| 128 | + int i, id; |
| 129 | + |
| 130 | + LOG_INF("rts5912 ULPM enabled\n"); |
| 131 | + /* VoutEnable, Keep VOUT output default value as bit 16 */ |
| 132 | + sys_reg->VIVOCTRL |= SYSTEM_VIVOCTRL_VODEF_Msk; |
| 133 | + ULPM_SLEEP(10); |
| 134 | + |
| 135 | + /* set to GPIO mode to clear status and aviod mis-trigger */ |
| 136 | + sys_reg->VIVOCTRL |= (SYSTEM_VIVOCTRL_VIN0MD_Msk | SYSTEM_VIVOCTRL_VIN1MD_Msk | |
| 137 | + SYSTEM_VIVOCTRL_VIN2MD_Msk | SYSTEM_VIVOCTRL_VIN3MD_Msk | |
| 138 | + SYSTEM_VIVOCTRL_VIN4MD_Msk | SYSTEM_VIVOCTRL_VIN5MD_Msk); |
| 139 | + |
| 140 | + /* Update Status Bit to ULPM IP */ |
| 141 | + update_vivo_register(); |
| 142 | + /* Configure Mode (VIN/GPIO) and Edge (Falling/Rising) */ |
| 143 | + for (i = 0; i < WKUP_PIN_SIZE; i++) { |
| 144 | + id = wkup_pins_cfgs[i].wkup_pin_id; |
| 145 | + /* corner case test */ |
| 146 | + if ((id < 0) || (id >= ULPM_RTS5912_MAX_NB_WKUP_PINS)) { |
| 147 | + continue; |
| 148 | + } |
| 149 | + |
| 150 | + /* Configure Mode */ |
| 151 | + if (wkup_pins_cfgs[i].wkup_pin_mode == RTS5912_ULPM_WKUP_PIN_MODE_VIN) { |
| 152 | + LOG_DBG("setup VIN%d in ", id); |
| 153 | + /* Configure Polarity */ |
| 154 | + if (wkup_pins_cfgs[i].wkup_pin_pol == RTS5912_ULPM_WKUP_PIN_POL_RISING) { |
| 155 | + /* Falling Edge */ |
| 156 | + sys_reg->VIVOCTRL |= BIT(SYSTEM_VIVOCTRL_VIN0POL_Pos + id); |
| 157 | + LOG_DBG("Falling Edge\n"); |
| 158 | + } else { |
| 159 | + /* Rising Edge */ |
| 160 | + sys_reg->VIVOCTRL &= ~BIT(SYSTEM_VIVOCTRL_VIN0POL_Pos + id); |
| 161 | + LOG_DBG("Rising Edge\n"); |
| 162 | + } |
| 163 | + /* VIN Mode */ |
| 164 | + sys_reg->VIVOCTRL &= ~BIT(SYSTEM_VIVOCTRL_VIN0MD_Pos + id); |
| 165 | + } |
| 166 | + } |
| 167 | + |
| 168 | + /* Update Status Bit to ULPM IP */ |
| 169 | + update_vivo_register(); |
| 170 | + |
| 171 | + /* Disable LDO 2 power. */ |
| 172 | + sys_reg->LDOCTRL &= ~(SYSTEM_LDOCTRL_LDO2EN_Msk); |
| 173 | + |
| 174 | + /* ULPM Start */ |
| 175 | + ulpm_start(); |
| 176 | +} |
0 commit comments