From 4e2a32d9b34bafb00916017fb0867a3569bbf121 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Tue, 17 Jan 2023 18:49:02 +0800 Subject: [PATCH 01/16] soc_cap: add SOC_PM_SUPPORT_VDDSDIO_PD soc_caps soc_cap: add SOC_PM_CPU_RETENTION_BY_SW/REGDMA soc caps: add SOC_PMU_SUPPORTED --- .../soc/esp32/include/soc/Kconfig.soc_caps.in | 4 +++ components/soc/esp32/include/soc/soc_caps.h | 1 + .../esp32c2/include/soc/Kconfig.soc_caps.in | 4 +++ components/soc/esp32c2/include/soc/soc_caps.h | 1 + .../esp32c3/include/soc/Kconfig.soc_caps.in | 8 +++++ components/soc/esp32c3/include/soc/soc_caps.h | 3 ++ .../esp32c6/include/soc/Kconfig.soc_caps.in | 34 ++++++++++++------- components/soc/esp32c6/include/soc/soc_caps.h | 32 +++++++---------- .../esp32h2/include/soc/Kconfig.soc_caps.in | 8 +++++ components/soc/esp32h2/include/soc/soc_caps.h | 3 +- .../esp32s2/include/soc/Kconfig.soc_caps.in | 4 +++ components/soc/esp32s2/include/soc/soc_caps.h | 1 + .../esp32s3/include/soc/Kconfig.soc_caps.in | 8 +++++ components/soc/esp32s3/include/soc/soc_caps.h | 3 ++ 14 files changed, 81 insertions(+), 33 deletions(-) diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index fdba1a66e4..2f0f687b25 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -743,6 +743,10 @@ config SOC_PM_SUPPORT_RC_FAST_PD bool default y +config SOC_PM_SUPPORT_VDDSDIO_PD + bool + default y + config SOC_CLK_APLL_SUPPORTED bool default y diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index f0c8ceed68..cded5d102d 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -373,6 +373,7 @@ #define SOC_PM_SUPPORT_RTC_FAST_MEM_PD (1) #define SOC_PM_SUPPORT_RTC_SLOW_MEM_PD (1) #define SOC_PM_SUPPORT_RC_FAST_PD (1) +#define SOC_PM_SUPPORT_VDDSDIO_PD (1) /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ #define SOC_CLK_APLL_SUPPORTED (1) diff --git a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in index beb59bbec8..63a076c011 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -607,6 +607,10 @@ config SOC_PM_SUPPORT_RC_FAST_PD bool default y +config SOC_PM_SUPPORT_VDDSDIO_PD + bool + default y + config SOC_CLK_RC_FAST_D256_SUPPORTED bool default y diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index ff1e37c06e..a7fdb1db60 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -289,6 +289,7 @@ #define SOC_PM_SUPPORT_WIFI_PD (0) #define SOC_PM_SUPPORT_BT_PD (0) #define SOC_PM_SUPPORT_RC_FAST_PD (1) +#define SOC_PM_SUPPORT_VDDSDIO_PD (1) /*--------------------------- CLOCK SUBSYSTEM CAPS -------------------------- */ #define SOC_CLK_RC_FAST_D256_SUPPORTED (1) diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index db80787dc3..ec92b0171e 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -863,6 +863,14 @@ config SOC_PM_SUPPORT_RC_FAST_PD bool default y +config SOC_PM_SUPPORT_VDDSDIO_PD + bool + default y + +config SOC_PM_CPU_RETENTION_BY_RTCCNTL + bool + default y + config SOC_CLK_RC_FAST_D256_SUPPORTED bool default y diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index d68a455cdf..eb5d1ef03e 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -383,6 +383,9 @@ #define SOC_PM_SUPPORT_WIFI_PD (1) #define SOC_PM_SUPPORT_BT_PD (1) #define SOC_PM_SUPPORT_RC_FAST_PD (1) +#define SOC_PM_SUPPORT_VDDSDIO_PD (1) + +#define SOC_PM_CPU_RETENTION_BY_RTCCNTL (1) /*--------------------------- CLOCK SUBSYSTEM CAPS -------------------------- */ #define SOC_CLK_RC_FAST_D256_SUPPORTED (1) diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index e29c80be02..f7ffb86ce6 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -147,6 +147,14 @@ config SOC_APM_SUPPORTED bool default y +config SOC_PMU_SUPPORTED + bool + default y + +config SOC_LP_TIMER_SUPPORTED + bool + default y + config SOC_XTAL_SUPPORT_40M bool default y @@ -659,14 +667,6 @@ config SOC_MCPWM_CLK_SUPPORT_XTAL bool default y -config SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH - int - default 128 - -config SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM - int - default 108 - config SOC_RSA_MAX_BIT_LEN int default 3072 @@ -963,6 +963,10 @@ config SOC_UART_SUPPORT_XTAL_CLK bool default y +config SOC_UART_SUPPORT_WAKEUP_INT + bool + default y + config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND bool default y @@ -991,11 +995,7 @@ config SOC_PM_SUPPORT_CPU_PD bool default y -config SOC_PM_SUPPORT_WIFI_PD - bool - default y - -config SOC_PM_SUPPORT_BT_PD +config SOC_PM_SUPPORT_MODEM_PD bool default y @@ -1011,10 +1011,18 @@ config SOC_PM_SUPPORT_RC_FAST_PD bool default y +config SOC_PM_SUPPORT_VDDSDIO_PD + bool + default y + config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY bool default y +config SOC_PM_CPU_RETENTION_BY_SW + bool + default y + config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION bool default y diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index dc40251e6c..66d625c26a 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -63,6 +63,8 @@ #define SOC_SDIO_SLAVE_SUPPORTED 1 #define SOC_BOD_SUPPORTED 1 #define SOC_APM_SUPPORTED 1 +#define SOC_PMU_SUPPORTED 1 +#define SOC_LP_TIMER_SUPPORTED 1 /*-------------------------- XTAL CAPS ---------------------------------------*/ #define SOC_XTAL_SUPPORT_40M 1 @@ -281,15 +283,6 @@ #define SOC_MCPWM_CLK_SUPPORT_PLL160M (1) ///< Support PLL160M as clock source #define SOC_MCPWM_CLK_SUPPORT_XTAL (1) ///< Support XTAL as clock source -// TODO: IDF-5348 (Copy from esp32c3, need check) -/*-------------------------- RTC CAPS --------------------------------------*/ -#define SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH (128) -#define SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM (108) -#define SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3) -#define SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3) - -#define SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE (SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM * (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3)) - // TODO: IDF-5359 (Copy from esp32c3, need check) /*--------------------------- RSA CAPS ---------------------------------------*/ #define SOC_RSA_MAX_BIT_LEN (3072) @@ -410,14 +403,13 @@ // TODO: IDF-5338 (Copy from esp32c3, need check) /*-------------------------- UART CAPS ---------------------------------------*/ // ESP32-C6 has 2 UARTs -#define SOC_UART_NUM (2) -#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */ -#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */ - -#define SOC_UART_SUPPORT_PLL_F80M_CLK (1) /*!< Support PLL_DIV as the clock source */ -#define SOC_UART_SUPPORT_RTC_CLK (1) /*!< Support RTC clock as the clock source */ -#define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */ -// #define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */ // TODO: Test UART wakeup while supporting sleep +#define SOC_UART_NUM (2) +#define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */ +#define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */ +#define SOC_UART_SUPPORT_PLL_F80M_CLK (1) /*!< Support PLL_DIV as the clock source */ +#define SOC_UART_SUPPORT_RTC_CLK (1) /*!< Support RTC clock as the clock source */ +#define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */ +#define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */ // TODO: Test UART wakeup while supporting sleep // UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled #define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1) @@ -438,14 +430,16 @@ #define SOC_PM_SUPPORT_WIFI_WAKEUP (1) #define SOC_PM_SUPPORT_BT_WAKEUP (1) #define SOC_PM_SUPPORT_CPU_PD (1) -#define SOC_PM_SUPPORT_WIFI_PD (1) -#define SOC_PM_SUPPORT_BT_PD (1) +#define SOC_PM_SUPPORT_MODEM_PD (1) #define SOC_PM_SUPPORT_XTAL32K_PD (1) #define SOC_PM_SUPPORT_RC32K_PD (1) #define SOC_PM_SUPPORT_RC_FAST_PD (1) +#define SOC_PM_SUPPORT_VDDSDIO_PD (1) #define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*! Date: Tue, 17 Jan 2023 18:49:37 +0800 Subject: [PATCH 02/16] pmu: pmu register address mapping structure redefinition --- .../hal/esp32c6/include/hal/rtc_io_ll.h | 4 +- .../soc/esp32c6/include/soc/pmu_struct.h | 2988 +++-------------- 2 files changed, 465 insertions(+), 2527 deletions(-) diff --git a/components/hal/esp32c6/include/hal/rtc_io_ll.h b/components/hal/esp32c6/include/hal/rtc_io_ll.h index 46a5503162..8d081f90ad 100644 --- a/components/hal/esp32c6/include/hal/rtc_io_ll.h +++ b/components/hal/esp32c6/include/hal/rtc_io_ll.h @@ -247,7 +247,7 @@ static inline void rtcio_ll_force_hold_disable(int rtcio_num) */ static inline void rtcio_ll_deep_sleep_hold_en_all(void) { - PMU.imm_pad_hold_all.tie_high_lp_pad_hold_all = 1; + PMU.imm.pad_hold_all.tie_high_lp_pad_hold_all = 1; } /** @@ -255,7 +255,7 @@ static inline void rtcio_ll_deep_sleep_hold_en_all(void) */ static inline void rtcio_ll_deep_sleep_hold_dis_all(void) { - PMU.imm_pad_hold_all.tie_low_lp_pad_hold_all = 1; + PMU.imm.pad_hold_all.tie_low_lp_pad_hold_all = 1; } /** diff --git a/components/soc/esp32c6/include/soc/pmu_struct.h b/components/soc/esp32c6/include/soc/pmu_struct.h index f265b8fd00..db1c3869e0 100644 --- a/components/soc/esp32c6/include/soc/pmu_struct.h +++ b/components/soc/esp32c6/include/soc/pmu_struct.h @@ -1,2816 +1,754 @@ /** - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once #include +#include #ifdef __cplusplus extern "C" { #endif -/** Group: configure_register */ -/** Type of hp_active_dig_power register - * need_des - */ +#include "soc.h" +#include "soc/pmu_reg.h" + typedef union { struct { - uint32_t reserved_0:21; - /** hp_active_vdd_spi_pd_en : R/W; bitpos: [21]; default: 0; - * need_des - */ - uint32_t hp_active_vdd_spi_pd_en:1; - /** hp_active_hp_mem_dslp : R/W; bitpos: [22]; default: 0; - * need_des - */ - uint32_t hp_active_hp_mem_dslp:1; - /** hp_active_pd_hp_mem_pd_en : R/W; bitpos: [26:23]; default: 0; - * need_des - */ - uint32_t hp_active_pd_hp_mem_pd_en:4; - /** hp_active_pd_hp_wifi_pd_en : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_active_pd_hp_wifi_pd_en:1; - uint32_t reserved_28:1; - /** hp_active_pd_hp_cpu_pd_en : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_active_pd_hp_cpu_pd_en:1; - /** hp_active_pd_hp_aon_pd_en : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_active_pd_hp_aon_pd_en:1; - /** hp_active_pd_top_pd_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_active_pd_top_pd_en:1; + uint32_t reserved0 : 21; + uint32_t vdd_spi_pd_en: 1; + uint32_t mem_dslp : 1; + uint32_t mem_pd_en : 4; + uint32_t wifi_pd_en : 1; + uint32_t reserved1 : 1; + uint32_t cpu_pd_en : 1; + uint32_t aon_pd_en : 1; + uint32_t top_pd_en : 1; }; uint32_t val; -} pmu_hp_active_dig_power_reg_t; +} pmu_hp_dig_power_reg_t; -/** Type of hp_active_icg_hp_func register - * need_des - */ typedef union { struct { - /** hp_active_dig_icg_func_en : R/W; bitpos: [31:0]; default: 4294967295; - * need_des - */ - uint32_t hp_active_dig_icg_func_en:32; + uint32_t reserved0: 30; + uint32_t code : 2; }; uint32_t val; -} pmu_hp_active_icg_hp_func_reg_t; +} pmu_hp_icg_modem_reg_t; -/** Type of hp_active_icg_hp_apb register - * need_des - */ typedef union { struct { - /** hp_active_dig_icg_apb_en : R/W; bitpos: [31:0]; default: 4294967295; - * need_des - */ - uint32_t hp_active_dig_icg_apb_en:32; + uint32_t reserved0 : 24; + uint32_t uart_wakeup_en : 1; + uint32_t lp_pad_hold_all: 1; + uint32_t hp_pad_hold_all: 1; + uint32_t dig_pad_slp_sel: 1; + uint32_t dig_pause_wdt : 1; + uint32_t dig_cpu_stall : 1; + uint32_t reserved1 : 2; }; uint32_t val; -} pmu_hp_active_icg_hp_apb_reg_t; +} pmu_hp_sys_cntl_reg_t; -/** Type of hp_active_icg_modem register - * need_des - */ typedef union { struct { - uint32_t reserved_0:30; - /** hp_active_dig_icg_modem_code : R/W; bitpos: [31:30]; default: 0; - * need_des - */ - uint32_t hp_active_dig_icg_modem_code:2; + uint32_t reserved0 : 26; + uint32_t i2c_iso_en : 1; + uint32_t i2c_retention: 1; + uint32_t xpd_bb_i2c : 1; + uint32_t xpd_bbpll_i2c: 1; + uint32_t xpd_bbpll : 1; + uint32_t reserved1 : 1; }; uint32_t val; -} pmu_hp_active_icg_modem_reg_t; +} pmu_hp_clk_power_reg_t; -/** Type of hp_active_hp_sys_cntl register - * need_des - */ typedef union { struct { - uint32_t reserved_0:24; - /** hp_active_uart_wakeup_en : R/W; bitpos: [24]; default: 0; - * need_des - */ - uint32_t hp_active_uart_wakeup_en:1; - /** hp_active_lp_pad_hold_all : R/W; bitpos: [25]; default: 0; - * need_des - */ - uint32_t hp_active_lp_pad_hold_all:1; - /** hp_active_hp_pad_hold_all : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t hp_active_hp_pad_hold_all:1; - /** hp_active_dig_pad_slp_sel : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_active_dig_pad_slp_sel:1; - /** hp_active_dig_pause_wdt : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t hp_active_dig_pause_wdt:1; - /** hp_active_dig_cpu_stall : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_active_dig_cpu_stall:1; - uint32_t reserved_30:2; + uint32_t reserved0 : 25; + uint32_t xpd_bias : 1; + uint32_t dbg_atten : 4; + uint32_t pd_cur : 1; + uint32_t bias_sleep: 1; }; uint32_t val; -} pmu_hp_active_hp_sys_cntl_reg_t; +} pmu_hp_bias_reg_t; -/** Type of hp_active_hp_ck_power register - * need_des - */ typedef union { - struct { - uint32_t reserved_0:26; - /** hp_active_i2c_iso_en : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t hp_active_i2c_iso_en:1; - /** hp_active_i2c_retention : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_active_i2c_retention:1; - /** hp_active_xpd_bb_i2c : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t hp_active_xpd_bb_i2c:1; - /** hp_active_xpd_bbpll_i2c : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_active_xpd_bbpll_i2c:1; - /** hp_active_xpd_bbpll : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_active_xpd_bbpll:1; - uint32_t reserved_31:1; + struct { /* HP: Active State */ + uint32_t reserved0 : 4; + uint32_t hp_sleep2active_backup_modem_clk_code: 2; + uint32_t hp_modem2active_backup_modem_clk_code: 2; + uint32_t reserved1 : 2; + uint32_t hp_active_retention_mode : 1; + uint32_t hp_sleep2active_retention_en : 1; + uint32_t hp_modem2active_retention_en : 1; + uint32_t reserved2 : 1; + uint32_t hp_sleep2active_backup_clk_sel : 2; + uint32_t hp_modem2active_backup_clk_sel : 2; + uint32_t reserved3 : 2; + uint32_t hp_sleep2active_backup_mode : 3; + uint32_t hp_modem2active_backup_mode : 3; + uint32_t reserved4 : 3; + uint32_t hp_sleep2active_backup_en : 1; + uint32_t hp_modem2active_backup_en : 1; + uint32_t reserved5 : 1; + }; + struct { /* HP: Modem State */ + uint32_t reserved6 : 4; + uint32_t hp_sleep2modem_backup_modem_clk_code : 2; + uint32_t reserved7 : 4; + uint32_t hp_modem_retention_mode : 1; + uint32_t hp_sleep2modem_retention_en : 1; + uint32_t reserved8 : 2; + uint32_t hp_sleep2modem_backup_clk_sel : 2; + uint32_t reserved9 : 4; + uint32_t hp_sleep2modem_backup_mode : 3; + uint32_t reserved10 : 6; + uint32_t hp_sleep2modem_backup_en : 1; + uint32_t reserved11 : 2; + }; + struct { /* HP: Sleep State */ + uint32_t reserved12 : 6; + uint32_t hp_modem2sleep_backup_modem_clk_code : 2; + uint32_t hp_active2sleep_backup_modem_clk_code: 2; + uint32_t hp_sleep_retention_mode : 1; + uint32_t reserved13 : 1; + uint32_t hp_modem2sleep_retention_en : 1; + uint32_t hp_active2sleep_retention_en : 1; + uint32_t reserved14 : 2; + uint32_t hp_modem2sleep_backup_clk_sel : 2; + uint32_t hp_active2sleep_backup_clk_sel : 2; + uint32_t reserved15 : 3; + uint32_t hp_modem2sleep_backup_mode : 3; + uint32_t hp_active2sleep_backup_mode : 3; + uint32_t reserved16 : 1; + uint32_t hp_modem2sleep_backup_en : 1; + uint32_t hp_active2sleep_backup_en : 1; }; uint32_t val; -} pmu_hp_active_hp_ck_power_reg_t; +} pmu_hp_backup_reg_t; -/** Type of hp_active_bias register - * need_des - */ typedef union { struct { - uint32_t reserved_0:25; - /** hp_active_xpd_bias : R/W; bitpos: [25]; default: 0; - * need_des - */ - uint32_t hp_active_xpd_bias:1; - /** hp_active_dbg_atten : R/W; bitpos: [29:26]; default: 0; - * need_des - */ - uint32_t hp_active_dbg_atten:4; - /** hp_active_pd_cur : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_active_pd_cur:1; - /** hp_active_bias_sleep : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_active_bias_sleep:1; + uint32_t reserved0 : 26; + uint32_t dig_sysclk_nodiv: 1; + uint32_t icg_sysclk_en : 1; + uint32_t sysclk_slp_sel : 1; + uint32_t icg_slp_sel : 1; + uint32_t dig_sysclk_sel : 2; }; uint32_t val; -} pmu_hp_active_bias_reg_t; +} pmu_hp_sysclk_reg_t; -/** Type of hp_active_backup register - * need_des - */ typedef union { struct { - uint32_t reserved_0:4; - /** hp_sleep2active_backup_modem_clk_code : R/W; bitpos: [5:4]; default: 0; - * need_des - */ - uint32_t hp_sleep2active_backup_modem_clk_code:2; - /** hp_modem2active_backup_modem_clk_code : R/W; bitpos: [7:6]; default: 0; - * need_des - */ - uint32_t hp_modem2active_backup_modem_clk_code:2; - uint32_t reserved_8:2; - /** hp_active_retention_mode : R/W; bitpos: [10]; default: 0; - * need_des - */ - uint32_t hp_active_retention_mode:1; - /** hp_sleep2active_retention_en : R/W; bitpos: [11]; default: 0; - * need_des - */ - uint32_t hp_sleep2active_retention_en:1; - /** hp_modem2active_retention_en : R/W; bitpos: [12]; default: 0; - * need_des - */ - uint32_t hp_modem2active_retention_en:1; - uint32_t reserved_13:1; - /** hp_sleep2active_backup_clk_sel : R/W; bitpos: [15:14]; default: 0; - * need_des - */ - uint32_t hp_sleep2active_backup_clk_sel:2; - /** hp_modem2active_backup_clk_sel : R/W; bitpos: [17:16]; default: 0; - * need_des - */ - uint32_t hp_modem2active_backup_clk_sel:2; - uint32_t reserved_18:2; - /** hp_sleep2active_backup_mode : R/W; bitpos: [22:20]; default: 0; - * need_des - */ - uint32_t hp_sleep2active_backup_mode:3; - /** hp_modem2active_backup_mode : R/W; bitpos: [25:23]; default: 0; - * need_des - */ - uint32_t hp_modem2active_backup_mode:3; - uint32_t reserved_26:3; - /** hp_sleep2active_backup_en : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_sleep2active_backup_en:1; - /** hp_modem2active_backup_en : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_modem2active_backup_en:1; - uint32_t reserved_31:1; + uint32_t reserved0 : 4; /* Only HP_ACTIVE modem under hp system is valid */ + uint32_t lp_dbias_vol : 5; /* Only HP_ACTIVE modem under hp system is valid */ + uint32_t hp_dbias_vol : 5; /* Only HP_ACTIVE modem under hp system is valid */ + uint32_t dbias_sel : 1; /* Only HP_ACTIVE modem under hp system is valid */ + uint32_t dbias_init : 1; /* Only HP_ACTIVE modem under hp system is valid */ + uint32_t slp_mem_xpd : 1; + uint32_t slp_logic_xpd : 1; + uint32_t xpd : 1; + uint32_t slp_mem_dbias : 4; + uint32_t slp_logic_dbias: 4; + uint32_t dbias : 5; }; uint32_t val; -} pmu_hp_active_backup_reg_t; +} pmu_hp_regulator0_reg_t; -/** Type of hp_active_backup_clk register - * need_des - */ typedef union { struct { - /** hp_active_backup_icg_func_en : R/W; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t hp_active_backup_icg_func_en:32; + uint32_t reserved0: 8; + uint32_t drv_b : 24; }; uint32_t val; -} pmu_hp_active_backup_clk_reg_t; +} pmu_hp_regulator1_reg_t; -/** Type of hp_active_sysclk register - * need_des - */ typedef union { struct { - uint32_t reserved_0:26; - /** hp_active_dig_sys_clk_no_div : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t hp_active_dig_sys_clk_no_div:1; - /** hp_active_icg_sys_clock_en : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_active_icg_sys_clock_en:1; - /** hp_active_sys_clk_slp_sel : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t hp_active_sys_clk_slp_sel:1; - /** hp_active_icg_slp_sel : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_active_icg_slp_sel:1; - /** hp_active_dig_sys_clk_sel : R/W; bitpos: [31:30]; default: 0; - * need_des - */ - uint32_t hp_active_dig_sys_clk_sel:2; + uint32_t reserved0: 31; + uint32_t xpd_xtal : 1; }; uint32_t val; -} pmu_hp_active_sysclk_reg_t; +} pmu_hp_xtal_reg_t; -/** Type of hp_active_hp_regulator0 register - * need_des - */ +typedef volatile struct pmu_hp_hw_regmap_t{ + pmu_hp_dig_power_reg_t dig_power; + uint32_t icg_func; + uint32_t icg_apb; + pmu_hp_icg_modem_reg_t icg_modem; + pmu_hp_sys_cntl_reg_t syscntl; + pmu_hp_clk_power_reg_t clk_power; + pmu_hp_bias_reg_t bias; + pmu_hp_backup_reg_t backup; + uint32_t backup_clk; + pmu_hp_sysclk_reg_t sysclk; + pmu_hp_regulator0_reg_t regulator0; + pmu_hp_regulator1_reg_t regulator1; + pmu_hp_xtal_reg_t xtal; +} pmu_hp_hw_regmap_t; + +/** */ typedef union { struct { - uint32_t reserved_0:4; - /** lp_dbias_vol : RO; bitpos: [8:4]; default: 24; - * need_des - */ - uint32_t lp_dbias_vol:5; - /** hp_dbias_vol : RO; bitpos: [13:9]; default: 24; - * need_des - */ - uint32_t hp_dbias_vol:5; - /** dig_regulator0_dbias_sel : R/W; bitpos: [14]; default: 1; - * need_des - */ - uint32_t dig_regulator0_dbias_sel:1; - /** dig_dbias_init : WT; bitpos: [15]; default: 0; - * need_des - */ - uint32_t dig_dbias_init:1; - /** hp_active_hp_regulator_slp_mem_xpd : R/W; bitpos: [16]; default: 1; - * need_des - */ - uint32_t hp_active_hp_regulator_slp_mem_xpd:1; - /** hp_active_hp_regulator_slp_logic_xpd : R/W; bitpos: [17]; default: 1; - * need_des - */ - uint32_t hp_active_hp_regulator_slp_logic_xpd:1; - /** hp_active_hp_regulator_xpd : R/W; bitpos: [18]; default: 1; - * need_des - */ - uint32_t hp_active_hp_regulator_xpd:1; - /** hp_active_hp_regulator_slp_mem_dbias : R/W; bitpos: [22:19]; default: 12; - * need_des - */ - uint32_t hp_active_hp_regulator_slp_mem_dbias:4; - /** hp_active_hp_regulator_slp_logic_dbias : R/W; bitpos: [26:23]; default: 12; - * need_des - */ - uint32_t hp_active_hp_regulator_slp_logic_dbias:4; - /** hp_active_hp_regulator_dbias : R/W; bitpos: [31:27]; default: 24; - * need_des - */ - uint32_t hp_active_hp_regulator_dbias:5; + uint32_t reserved0: 21; + uint32_t slp_xpd : 1; + uint32_t xpd : 1; + uint32_t slp_dbias: 4; + uint32_t dbias : 5; }; uint32_t val; -} pmu_hp_active_hp_regulator0_reg_t; +} pmu_lp_regulator0_reg_t; -/** Type of hp_active_hp_regulator1 register - * need_des - */ typedef union { struct { - uint32_t reserved_0:8; - /** hp_active_hp_regulator_drv_b : R/W; bitpos: [31:8]; default: 0; - * need_des - */ - uint32_t hp_active_hp_regulator_drv_b:24; + uint32_t reserved0: 28; + uint32_t drv_b : 4; }; uint32_t val; -} pmu_hp_active_hp_regulator1_reg_t; +} pmu_lp_regulator1_reg_t; -/** Type of hp_active_xtal register - * need_des - */ typedef union { struct { - uint32_t reserved_0:31; - /** hp_active_xpd_xtal : R/W; bitpos: [31]; default: 1; - * need_des - */ - uint32_t hp_active_xpd_xtal:1; + uint32_t reserved0: 31; + uint32_t xpd_xtal : 1; }; uint32_t val; -} pmu_hp_active_xtal_reg_t; +} pmu_lp_xtal_reg_t; -/** Type of hp_modem_dig_power register - * need_des - */ typedef union { struct { - uint32_t reserved_0:21; - /** hp_modem_vdd_spi_pd_en : R/W; bitpos: [21]; default: 0; - * need_des - */ - uint32_t hp_modem_vdd_spi_pd_en:1; - /** hp_modem_hp_mem_dslp : R/W; bitpos: [22]; default: 0; - * need_des - */ - uint32_t hp_modem_hp_mem_dslp:1; - /** hp_modem_pd_hp_mem_pd_en : R/W; bitpos: [26:23]; default: 0; - * need_des - */ - uint32_t hp_modem_pd_hp_mem_pd_en:4; - /** hp_modem_pd_hp_wifi_pd_en : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_modem_pd_hp_wifi_pd_en:1; - uint32_t reserved_28:1; - /** hp_modem_pd_hp_cpu_pd_en : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_modem_pd_hp_cpu_pd_en:1; - /** hp_modem_pd_hp_aon_pd_en : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_modem_pd_hp_aon_pd_en:1; - /** hp_modem_pd_top_pd_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_modem_pd_top_pd_en:1; + uint32_t reserved0 : 30; + uint32_t mem_dslp : 1; + uint32_t peri_pd_en: 1; }; uint32_t val; -} pmu_hp_modem_dig_power_reg_t; +} pmu_lp_dig_power_reg_t; -/** Type of hp_modem_icg_hp_func register - * need_des - */ typedef union { struct { - /** hp_modem_dig_icg_func_en : R/W; bitpos: [31:0]; default: 4294967295; - * need_des - */ - uint32_t hp_modem_dig_icg_func_en:32; + uint32_t reserved0 : 28; + uint32_t xpd_xtal32k: 1; + uint32_t xpd_rc32k : 1; + uint32_t xpd_fosc : 1; + uint32_t pd_osc : 1; }; uint32_t val; -} pmu_hp_modem_icg_hp_func_reg_t; +} pmu_lp_clk_power_reg_t; -/** Type of hp_modem_icg_hp_apb register - * need_des - */ typedef union { struct { - /** hp_modem_dig_icg_apb_en : R/W; bitpos: [31:0]; default: 4294967295; - * need_des - */ - uint32_t hp_modem_dig_icg_apb_en:32; + uint32_t reserved0 : 25; + uint32_t xpd_bias : 1; + uint32_t dbg_atten : 4; + uint32_t pd_cur : 1; + uint32_t bias_sleep: 1; }; uint32_t val; -} pmu_hp_modem_icg_hp_apb_reg_t; +} pmu_lp_bias_reg_t; + +typedef volatile struct pmu_lp_hw_regmap_t{ + pmu_lp_regulator0_reg_t regulator0; + pmu_lp_regulator1_reg_t regulator1; + pmu_lp_xtal_reg_t xtal; /* Only LP_SLEEP mode under lp system is valid */ + pmu_lp_dig_power_reg_t dig_power; + pmu_lp_clk_power_reg_t clk_power; + pmu_lp_bias_reg_t bias; /* Only LP_SLEEP mode under lp system is valid */ +} pmu_lp_hw_regmap_t; + -/** Type of hp_modem_icg_modem register - * need_des - */ typedef union { struct { - uint32_t reserved_0:30; - /** hp_modem_dig_icg_modem_code : R/W; bitpos: [31:30]; default: 0; - * need_des - */ - uint32_t hp_modem_dig_icg_modem_code:2; + uint32_t tie_low_global_bbpll_icg : 1; + uint32_t tie_low_global_xtal_icg : 1; + uint32_t tie_low_i2c_retention : 1; + uint32_t tie_low_xpd_bb_i2c : 1; + uint32_t tie_low_xpd_bbpll_i2c : 1; + uint32_t tie_low_xpd_bbpll : 1; + uint32_t tie_low_xpd_xtal : 1; + uint32_t reserved0 : 18; + uint32_t tie_high_global_bbpll_icg: 1; + uint32_t tie_high_global_xtal_icg : 1; + uint32_t tie_high_i2c_retention : 1; + uint32_t tie_high_xpd_bb_i2c : 1; + uint32_t tie_high_xpd_bbpll_i2c : 1; + uint32_t tie_high_xpd_bbpll : 1; + uint32_t tie_high_xpd_xtal : 1; }; uint32_t val; -} pmu_hp_modem_icg_modem_reg_t; +} pmu_imm_hp_clk_power_reg_t; -/** Type of hp_modem_hp_sys_cntl register - * need_des - */ typedef union { struct { - uint32_t reserved_0:24; - /** hp_modem_uart_wakeup_en : R/W; bitpos: [24]; default: 0; - * need_des - */ - uint32_t hp_modem_uart_wakeup_en:1; - /** hp_modem_lp_pad_hold_all : R/W; bitpos: [25]; default: 0; - * need_des - */ - uint32_t hp_modem_lp_pad_hold_all:1; - /** hp_modem_hp_pad_hold_all : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t hp_modem_hp_pad_hold_all:1; - /** hp_modem_dig_pad_slp_sel : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_modem_dig_pad_slp_sel:1; - /** hp_modem_dig_pause_wdt : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t hp_modem_dig_pause_wdt:1; - /** hp_modem_dig_cpu_stall : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_modem_dig_cpu_stall:1; - uint32_t reserved_30:2; - }; - uint32_t val; -} pmu_hp_modem_hp_sys_cntl_reg_t; - -/** Type of hp_modem_hp_ck_power register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:26; - /** hp_modem_i2c_iso_en : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t hp_modem_i2c_iso_en:1; - /** hp_modem_i2c_retention : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_modem_i2c_retention:1; - /** hp_modem_xpd_bb_i2c : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t hp_modem_xpd_bb_i2c:1; - /** hp_modem_xpd_bbpll_i2c : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_modem_xpd_bbpll_i2c:1; - /** hp_modem_xpd_bbpll : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_modem_xpd_bbpll:1; - uint32_t reserved_31:1; - }; - uint32_t val; -} pmu_hp_modem_hp_ck_power_reg_t; - -/** Type of hp_modem_bias register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:25; - /** hp_modem_xpd_bias : R/W; bitpos: [25]; default: 0; - * need_des - */ - uint32_t hp_modem_xpd_bias:1; - /** hp_modem_dbg_atten : R/W; bitpos: [29:26]; default: 0; - * need_des - */ - uint32_t hp_modem_dbg_atten:4; - /** hp_modem_pd_cur : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_modem_pd_cur:1; - /** hp_modem_bias_sleep : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_modem_bias_sleep:1; - }; - uint32_t val; -} pmu_hp_modem_bias_reg_t; - -/** Type of hp_modem_backup register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:4; - /** hp_sleep2modem_backup_modem_clk_code : R/W; bitpos: [5:4]; default: 0; - * need_des - */ - uint32_t hp_sleep2modem_backup_modem_clk_code:2; - uint32_t reserved_6:4; - /** hp_modem_retention_mode : R/W; bitpos: [10]; default: 0; - * need_des - */ - uint32_t hp_modem_retention_mode:1; - /** hp_sleep2modem_retention_en : R/W; bitpos: [11]; default: 0; - * need_des - */ - uint32_t hp_sleep2modem_retention_en:1; - uint32_t reserved_12:2; - /** hp_sleep2modem_backup_clk_sel : R/W; bitpos: [15:14]; default: 0; - * need_des - */ - uint32_t hp_sleep2modem_backup_clk_sel:2; - uint32_t reserved_16:4; - /** hp_sleep2modem_backup_mode : R/W; bitpos: [22:20]; default: 0; - * need_des - */ - uint32_t hp_sleep2modem_backup_mode:3; - uint32_t reserved_23:6; - /** hp_sleep2modem_backup_en : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_sleep2modem_backup_en:1; - uint32_t reserved_30:2; - }; - uint32_t val; -} pmu_hp_modem_backup_reg_t; - -/** Type of hp_modem_backup_clk register - * need_des - */ -typedef union { - struct { - /** hp_modem_backup_icg_func_en : R/W; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t hp_modem_backup_icg_func_en:32; - }; - uint32_t val; -} pmu_hp_modem_backup_clk_reg_t; - -/** Type of hp_modem_sysclk register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:26; - /** hp_modem_dig_sys_clk_no_div : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t hp_modem_dig_sys_clk_no_div:1; - /** hp_modem_icg_sys_clock_en : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_modem_icg_sys_clock_en:1; - /** hp_modem_sys_clk_slp_sel : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t hp_modem_sys_clk_slp_sel:1; - /** hp_modem_icg_slp_sel : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_modem_icg_slp_sel:1; - /** hp_modem_dig_sys_clk_sel : R/W; bitpos: [31:30]; default: 0; - * need_des - */ - uint32_t hp_modem_dig_sys_clk_sel:2; - }; - uint32_t val; -} pmu_hp_modem_sysclk_reg_t; - -/** Type of hp_modem_hp_regulator0 register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:16; - /** hp_modem_hp_regulator_slp_mem_xpd : R/W; bitpos: [16]; default: 1; - * need_des - */ - uint32_t hp_modem_hp_regulator_slp_mem_xpd:1; - /** hp_modem_hp_regulator_slp_logic_xpd : R/W; bitpos: [17]; default: 1; - * need_des - */ - uint32_t hp_modem_hp_regulator_slp_logic_xpd:1; - /** hp_modem_hp_regulator_xpd : R/W; bitpos: [18]; default: 1; - * need_des - */ - uint32_t hp_modem_hp_regulator_xpd:1; - /** hp_modem_hp_regulator_slp_mem_dbias : R/W; bitpos: [22:19]; default: 12; - * need_des - */ - uint32_t hp_modem_hp_regulator_slp_mem_dbias:4; - /** hp_modem_hp_regulator_slp_logic_dbias : R/W; bitpos: [26:23]; default: 12; - * need_des - */ - uint32_t hp_modem_hp_regulator_slp_logic_dbias:4; - /** hp_modem_hp_regulator_dbias : R/W; bitpos: [31:27]; default: 24; - * need_des - */ - uint32_t hp_modem_hp_regulator_dbias:5; - }; - uint32_t val; -} pmu_hp_modem_hp_regulator0_reg_t; - -/** Type of hp_modem_hp_regulator1 register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:8; - /** hp_modem_hp_regulator_drv_b : R/W; bitpos: [31:8]; default: 0; - * need_des - */ - uint32_t hp_modem_hp_regulator_drv_b:24; - }; - uint32_t val; -} pmu_hp_modem_hp_regulator1_reg_t; - -/** Type of hp_modem_xtal register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** hp_modem_xpd_xtal : R/W; bitpos: [31]; default: 1; - * need_des - */ - uint32_t hp_modem_xpd_xtal:1; - }; - uint32_t val; -} pmu_hp_modem_xtal_reg_t; - -/** Type of hp_sleep_dig_power register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:21; - /** hp_sleep_vdd_spi_pd_en : R/W; bitpos: [21]; default: 0; - * need_des - */ - uint32_t hp_sleep_vdd_spi_pd_en:1; - /** hp_sleep_hp_mem_dslp : R/W; bitpos: [22]; default: 0; - * need_des - */ - uint32_t hp_sleep_hp_mem_dslp:1; - /** hp_sleep_pd_hp_mem_pd_en : R/W; bitpos: [26:23]; default: 0; - * need_des - */ - uint32_t hp_sleep_pd_hp_mem_pd_en:4; - /** hp_sleep_pd_hp_wifi_pd_en : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_sleep_pd_hp_wifi_pd_en:1; - uint32_t reserved_28:1; - /** hp_sleep_pd_hp_cpu_pd_en : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_sleep_pd_hp_cpu_pd_en:1; - /** hp_sleep_pd_hp_aon_pd_en : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_sleep_pd_hp_aon_pd_en:1; - /** hp_sleep_pd_top_pd_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_sleep_pd_top_pd_en:1; - }; - uint32_t val; -} pmu_hp_sleep_dig_power_reg_t; - -/** Type of hp_sleep_icg_hp_func register - * need_des - */ -typedef union { - struct { - /** hp_sleep_dig_icg_func_en : R/W; bitpos: [31:0]; default: 4294967295; - * need_des - */ - uint32_t hp_sleep_dig_icg_func_en:32; - }; - uint32_t val; -} pmu_hp_sleep_icg_hp_func_reg_t; - -/** Type of hp_sleep_icg_hp_apb register - * need_des - */ -typedef union { - struct { - /** hp_sleep_dig_icg_apb_en : R/W; bitpos: [31:0]; default: 4294967295; - * need_des - */ - uint32_t hp_sleep_dig_icg_apb_en:32; - }; - uint32_t val; -} pmu_hp_sleep_icg_hp_apb_reg_t; - -/** Type of hp_sleep_icg_modem register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** hp_sleep_dig_icg_modem_code : R/W; bitpos: [31:30]; default: 0; - * need_des - */ - uint32_t hp_sleep_dig_icg_modem_code:2; - }; - uint32_t val; -} pmu_hp_sleep_icg_modem_reg_t; - -/** Type of hp_sleep_hp_sys_cntl register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:24; - /** hp_sleep_uart_wakeup_en : R/W; bitpos: [24]; default: 0; - * need_des - */ - uint32_t hp_sleep_uart_wakeup_en:1; - /** hp_sleep_lp_pad_hold_all : R/W; bitpos: [25]; default: 0; - * need_des - */ - uint32_t hp_sleep_lp_pad_hold_all:1; - /** hp_sleep_hp_pad_hold_all : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t hp_sleep_hp_pad_hold_all:1; - /** hp_sleep_dig_pad_slp_sel : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_sleep_dig_pad_slp_sel:1; - /** hp_sleep_dig_pause_wdt : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t hp_sleep_dig_pause_wdt:1; - /** hp_sleep_dig_cpu_stall : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_sleep_dig_cpu_stall:1; - uint32_t reserved_30:2; - }; - uint32_t val; -} pmu_hp_sleep_hp_sys_cntl_reg_t; - -/** Type of hp_sleep_hp_ck_power register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:26; - /** hp_sleep_i2c_iso_en : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t hp_sleep_i2c_iso_en:1; - /** hp_sleep_i2c_retention : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_sleep_i2c_retention:1; - /** hp_sleep_xpd_bb_i2c : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t hp_sleep_xpd_bb_i2c:1; - /** hp_sleep_xpd_bbpll_i2c : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_sleep_xpd_bbpll_i2c:1; - /** hp_sleep_xpd_bbpll : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_sleep_xpd_bbpll:1; - uint32_t reserved_31:1; - }; - uint32_t val; -} pmu_hp_sleep_hp_ck_power_reg_t; - -/** Type of hp_sleep_bias register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:25; - /** hp_sleep_xpd_bias : R/W; bitpos: [25]; default: 0; - * need_des - */ - uint32_t hp_sleep_xpd_bias:1; - /** hp_sleep_dbg_atten : R/W; bitpos: [29:26]; default: 0; - * need_des - */ - uint32_t hp_sleep_dbg_atten:4; - /** hp_sleep_pd_cur : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_sleep_pd_cur:1; - /** hp_sleep_bias_sleep : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_sleep_bias_sleep:1; - }; - uint32_t val; -} pmu_hp_sleep_bias_reg_t; - -/** Type of hp_sleep_backup register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:6; - /** hp_modem2sleep_backup_modem_clk_code : R/W; bitpos: [7:6]; default: 0; - * need_des - */ - uint32_t hp_modem2sleep_backup_modem_clk_code:2; - /** hp_active2sleep_backup_modem_clk_code : R/W; bitpos: [9:8]; default: 0; - * need_des - */ - uint32_t hp_active2sleep_backup_modem_clk_code:2; - /** hp_sleep_retention_mode : R/W; bitpos: [10]; default: 0; - * need_des - */ - uint32_t hp_sleep_retention_mode:1; - uint32_t reserved_11:1; - /** hp_modem2sleep_retention_en : R/W; bitpos: [12]; default: 0; - * need_des - */ - uint32_t hp_modem2sleep_retention_en:1; - /** hp_active2sleep_retention_en : R/W; bitpos: [13]; default: 0; - * need_des - */ - uint32_t hp_active2sleep_retention_en:1; - uint32_t reserved_14:2; - /** hp_modem2sleep_backup_clk_sel : R/W; bitpos: [17:16]; default: 0; - * need_des - */ - uint32_t hp_modem2sleep_backup_clk_sel:2; - /** hp_active2sleep_backup_clk_sel : R/W; bitpos: [19:18]; default: 0; - * need_des - */ - uint32_t hp_active2sleep_backup_clk_sel:2; - uint32_t reserved_20:3; - /** hp_modem2sleep_backup_mode : R/W; bitpos: [25:23]; default: 0; - * need_des - */ - uint32_t hp_modem2sleep_backup_mode:3; - /** hp_active2sleep_backup_mode : R/W; bitpos: [28:26]; default: 0; - * need_des - */ - uint32_t hp_active2sleep_backup_mode:3; - uint32_t reserved_29:1; - /** hp_modem2sleep_backup_en : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_modem2sleep_backup_en:1; - /** hp_active2sleep_backup_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_active2sleep_backup_en:1; - }; - uint32_t val; -} pmu_hp_sleep_backup_reg_t; - -/** Type of hp_sleep_backup_clk register - * need_des - */ -typedef union { - struct { - /** hp_sleep_backup_icg_func_en : R/W; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t hp_sleep_backup_icg_func_en:32; - }; - uint32_t val; -} pmu_hp_sleep_backup_clk_reg_t; - -/** Type of hp_sleep_sysclk register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:26; - /** hp_sleep_dig_sys_clk_no_div : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t hp_sleep_dig_sys_clk_no_div:1; - /** hp_sleep_icg_sys_clock_en : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t hp_sleep_icg_sys_clock_en:1; - /** hp_sleep_sys_clk_slp_sel : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t hp_sleep_sys_clk_slp_sel:1; - /** hp_sleep_icg_slp_sel : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_sleep_icg_slp_sel:1; - /** hp_sleep_dig_sys_clk_sel : R/W; bitpos: [31:30]; default: 0; - * need_des - */ - uint32_t hp_sleep_dig_sys_clk_sel:2; - }; - uint32_t val; -} pmu_hp_sleep_sysclk_reg_t; - -/** Type of hp_sleep_hp_regulator0 register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:16; - /** hp_sleep_hp_regulator_slp_mem_xpd : R/W; bitpos: [16]; default: 1; - * need_des - */ - uint32_t hp_sleep_hp_regulator_slp_mem_xpd:1; - /** hp_sleep_hp_regulator_slp_logic_xpd : R/W; bitpos: [17]; default: 1; - * need_des - */ - uint32_t hp_sleep_hp_regulator_slp_logic_xpd:1; - /** hp_sleep_hp_regulator_xpd : R/W; bitpos: [18]; default: 1; - * need_des - */ - uint32_t hp_sleep_hp_regulator_xpd:1; - /** hp_sleep_hp_regulator_slp_mem_dbias : R/W; bitpos: [22:19]; default: 12; - * need_des - */ - uint32_t hp_sleep_hp_regulator_slp_mem_dbias:4; - /** hp_sleep_hp_regulator_slp_logic_dbias : R/W; bitpos: [26:23]; default: 12; - * need_des - */ - uint32_t hp_sleep_hp_regulator_slp_logic_dbias:4; - /** hp_sleep_hp_regulator_dbias : R/W; bitpos: [31:27]; default: 24; - * need_des - */ - uint32_t hp_sleep_hp_regulator_dbias:5; - }; - uint32_t val; -} pmu_hp_sleep_hp_regulator0_reg_t; - -/** Type of hp_sleep_hp_regulator1 register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:8; - /** hp_sleep_hp_regulator_drv_b : R/W; bitpos: [31:8]; default: 0; - * need_des - */ - uint32_t hp_sleep_hp_regulator_drv_b:24; - }; - uint32_t val; -} pmu_hp_sleep_hp_regulator1_reg_t; - -/** Type of hp_sleep_xtal register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** hp_sleep_xpd_xtal : R/W; bitpos: [31]; default: 1; - * need_des - */ - uint32_t hp_sleep_xpd_xtal:1; - }; - uint32_t val; -} pmu_hp_sleep_xtal_reg_t; - -/** Type of hp_sleep_lp_regulator0 register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:21; - /** hp_sleep_lp_regulator_slp_xpd : R/W; bitpos: [21]; default: 1; - * need_des - */ - uint32_t hp_sleep_lp_regulator_slp_xpd:1; - /** hp_sleep_lp_regulator_xpd : R/W; bitpos: [22]; default: 1; - * need_des - */ - uint32_t hp_sleep_lp_regulator_xpd:1; - /** hp_sleep_lp_regulator_slp_dbias : R/W; bitpos: [26:23]; default: 12; - * need_des - */ - uint32_t hp_sleep_lp_regulator_slp_dbias:4; - /** hp_sleep_lp_regulator_dbias : R/W; bitpos: [31:27]; default: 24; - * need_des - */ - uint32_t hp_sleep_lp_regulator_dbias:5; - }; - uint32_t val; -} pmu_hp_sleep_lp_regulator0_reg_t; - -/** Type of hp_sleep_lp_regulator1 register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:28; - /** hp_sleep_lp_regulator_drv_b : R/W; bitpos: [31:28]; default: 0; - * need_des - */ - uint32_t hp_sleep_lp_regulator_drv_b:4; - }; - uint32_t val; -} pmu_hp_sleep_lp_regulator1_reg_t; - -/** Type of hp_sleep_lp_dcdc_reserve register - * need_des - */ -typedef union { - struct { - /** hp_sleep_lp_dcdc_reserve : WT; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t hp_sleep_lp_dcdc_reserve:32; - }; - uint32_t val; -} pmu_hp_sleep_lp_dcdc_reserve_reg_t; - -/** Type of hp_sleep_lp_dig_power register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** hp_sleep_lp_mem_dslp : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t hp_sleep_lp_mem_dslp:1; - /** hp_sleep_pd_lp_peri_pd_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_sleep_pd_lp_peri_pd_en:1; - }; - uint32_t val; -} pmu_hp_sleep_lp_dig_power_reg_t; - -/** Type of hp_sleep_lp_ck_power register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:28; - /** hp_sleep_xpd_xtal32k : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t hp_sleep_xpd_xtal32k:1; - /** hp_sleep_xpd_rc32k : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t hp_sleep_xpd_rc32k:1; - /** hp_sleep_xpd_fosc_clk : R/W; bitpos: [30]; default: 1; - * need_des - */ - uint32_t hp_sleep_xpd_fosc_clk:1; - /** hp_sleep_pd_osc_clk : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_sleep_pd_osc_clk:1; - }; - uint32_t val; -} pmu_hp_sleep_lp_ck_power_reg_t; - -/** Type of lp_sleep_lp_bias_reserve register - * need_des - */ -typedef union { - struct { - /** lp_sleep_lp_bias_reserve : WT; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t lp_sleep_lp_bias_reserve:32; - }; - uint32_t val; -} pmu_lp_sleep_lp_bias_reserve_reg_t; - -/** Type of lp_sleep_lp_regulator0 register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:21; - /** lp_sleep_lp_regulator_slp_xpd : R/W; bitpos: [21]; default: 1; - * need_des - */ - uint32_t lp_sleep_lp_regulator_slp_xpd:1; - /** lp_sleep_lp_regulator_xpd : R/W; bitpos: [22]; default: 1; - * need_des - */ - uint32_t lp_sleep_lp_regulator_xpd:1; - /** lp_sleep_lp_regulator_slp_dbias : R/W; bitpos: [26:23]; default: 12; - * need_des - */ - uint32_t lp_sleep_lp_regulator_slp_dbias:4; - /** lp_sleep_lp_regulator_dbias : R/W; bitpos: [31:27]; default: 24; - * need_des - */ - uint32_t lp_sleep_lp_regulator_dbias:5; - }; - uint32_t val; -} pmu_lp_sleep_lp_regulator0_reg_t; - -/** Type of lp_sleep_lp_regulator1 register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:28; - /** lp_sleep_lp_regulator_drv_b : R/W; bitpos: [31:28]; default: 0; - * need_des - */ - uint32_t lp_sleep_lp_regulator_drv_b:4; - }; - uint32_t val; -} pmu_lp_sleep_lp_regulator1_reg_t; - -/** Type of lp_sleep_xtal register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** lp_sleep_xpd_xtal : R/W; bitpos: [31]; default: 1; - * need_des - */ - uint32_t lp_sleep_xpd_xtal:1; - }; - uint32_t val; -} pmu_lp_sleep_xtal_reg_t; - -/** Type of lp_sleep_lp_dig_power register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** lp_sleep_lp_mem_dslp : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t lp_sleep_lp_mem_dslp:1; - /** lp_sleep_pd_lp_peri_pd_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t lp_sleep_pd_lp_peri_pd_en:1; - }; - uint32_t val; -} pmu_lp_sleep_lp_dig_power_reg_t; - -/** Type of lp_sleep_lp_ck_power register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:28; - /** lp_sleep_xpd_xtal32k : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t lp_sleep_xpd_xtal32k:1; - /** lp_sleep_xpd_rc32k : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t lp_sleep_xpd_rc32k:1; - /** lp_sleep_xpd_fosc_clk : R/W; bitpos: [30]; default: 1; - * need_des - */ - uint32_t lp_sleep_xpd_fosc_clk:1; - /** lp_sleep_pd_osc_clk : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t lp_sleep_pd_osc_clk:1; - }; - uint32_t val; -} pmu_lp_sleep_lp_ck_power_reg_t; - -/** Type of lp_sleep_bias register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:25; - /** lp_sleep_xpd_bias : R/W; bitpos: [25]; default: 0; - * need_des - */ - uint32_t lp_sleep_xpd_bias:1; - /** lp_sleep_dbg_atten : R/W; bitpos: [29:26]; default: 0; - * need_des - */ - uint32_t lp_sleep_dbg_atten:4; - /** lp_sleep_pd_cur : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t lp_sleep_pd_cur:1; - /** lp_sleep_bias_sleep : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t lp_sleep_bias_sleep:1; - }; - uint32_t val; -} pmu_lp_sleep_bias_reg_t; - -/** Type of imm_hp_ck_power register - * need_des - */ -typedef union { - struct { - /** tie_low_global_bbpll_icg : WT; bitpos: [0]; default: 0; - * need_des - */ - uint32_t tie_low_global_bbpll_icg:1; - /** tie_low_global_xtal_icg : WT; bitpos: [1]; default: 0; - * need_des - */ - uint32_t tie_low_global_xtal_icg:1; - /** tie_low_i2c_retention : WT; bitpos: [2]; default: 0; - * need_des - */ - uint32_t tie_low_i2c_retention:1; - /** tie_low_xpd_bb_i2c : WT; bitpos: [3]; default: 0; - * need_des - */ - uint32_t tie_low_xpd_bb_i2c:1; - /** tie_low_xpd_bbpll_i2c : WT; bitpos: [4]; default: 0; - * need_des - */ - uint32_t tie_low_xpd_bbpll_i2c:1; - /** tie_low_xpd_bbpll : WT; bitpos: [5]; default: 0; - * need_des - */ - uint32_t tie_low_xpd_bbpll:1; - /** tie_low_xpd_xtal : WT; bitpos: [6]; default: 0; - * need_des - */ - uint32_t tie_low_xpd_xtal:1; - uint32_t reserved_7:18; - /** tie_high_global_bbpll_icg : WT; bitpos: [25]; default: 0; - * need_des - */ - uint32_t tie_high_global_bbpll_icg:1; - /** tie_high_global_xtal_icg : WT; bitpos: [26]; default: 0; - * need_des - */ - uint32_t tie_high_global_xtal_icg:1; - /** tie_high_i2c_retention : WT; bitpos: [27]; default: 0; - * need_des - */ - uint32_t tie_high_i2c_retention:1; - /** tie_high_xpd_bb_i2c : WT; bitpos: [28]; default: 0; - * need_des - */ - uint32_t tie_high_xpd_bb_i2c:1; - /** tie_high_xpd_bbpll_i2c : WT; bitpos: [29]; default: 0; - * need_des - */ - uint32_t tie_high_xpd_bbpll_i2c:1; - /** tie_high_xpd_bbpll : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t tie_high_xpd_bbpll:1; - /** tie_high_xpd_xtal : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t tie_high_xpd_xtal:1; - }; - uint32_t val; -} pmu_imm_hp_ck_power_reg_t; - -/** Type of imm_sleep_sysclk register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:28; - /** update_dig_icg_switch : WT; bitpos: [28]; default: 0; - * need_des - */ - uint32_t update_dig_icg_switch:1; - /** tie_low_icg_slp_sel : WT; bitpos: [29]; default: 0; - * need_des - */ - uint32_t tie_low_icg_slp_sel:1; - /** tie_high_icg_slp_sel : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t tie_high_icg_slp_sel:1; - /** update_dig_sys_clk_sel : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t update_dig_sys_clk_sel:1; + uint32_t reserved0 : 28; + uint32_t update_dig_icg_switch: 1; + uint32_t tie_low_icg_slp_sel : 1; + uint32_t tie_high_icg_slp_sel : 1; + uint32_t update_dig_sysclk_sel: 1; }; uint32_t val; } pmu_imm_sleep_sysclk_reg_t; -/** Type of imm_hp_func_icg register - * need_des - */ typedef union { struct { - uint32_t reserved_0:31; - /** update_dig_icg_func_en : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t update_dig_icg_func_en:1; + uint32_t reserved0 : 31; + uint32_t update_dig_icg_func_en: 1; }; uint32_t val; } pmu_imm_hp_func_icg_reg_t; -/** Type of imm_hp_apb_icg register - * need_des - */ typedef union { struct { - uint32_t reserved_0:31; - /** update_dig_icg_apb_en : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t update_dig_icg_apb_en:1; + uint32_t reserved0 : 31; + uint32_t update_dig_icg_apb_en: 1; }; uint32_t val; } pmu_imm_hp_apb_icg_reg_t; -/** Type of imm_modem_icg register - * need_des - */ typedef union { struct { - uint32_t reserved_0:31; - /** update_dig_icg_modem_en : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t update_dig_icg_modem_en:1; + uint32_t reserved0 : 31; + uint32_t update_dig_icg_modem_en: 1; }; uint32_t val; } pmu_imm_modem_icg_reg_t; -/** Type of imm_lp_icg register - * need_des - */ typedef union { struct { - uint32_t reserved_0:30; - /** tie_low_lp_rootclk_sel : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t tie_low_lp_rootclk_sel:1; - /** tie_high_lp_rootclk_sel : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t tie_high_lp_rootclk_sel:1; + uint32_t reserved0 : 30; + uint32_t tie_low_lp_rootclk_sel : 1; + uint32_t tie_high_lp_rootclk_sel: 1; }; uint32_t val; } pmu_imm_lp_icg_reg_t; -/** Type of imm_pad_hold_all register - * need_des - */ typedef union { struct { - uint32_t reserved_0:28; - /** tie_high_lp_pad_hold_all : WT; bitpos: [28]; default: 0; - * need_des - */ - uint32_t tie_high_lp_pad_hold_all:1; - /** tie_low_lp_pad_hold_all : WT; bitpos: [29]; default: 0; - * need_des - */ - uint32_t tie_low_lp_pad_hold_all:1; - /** tie_high_hp_pad_hold_all : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t tie_high_hp_pad_hold_all:1; - /** tie_low_hp_pad_hold_all : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t tie_low_hp_pad_hold_all:1; + uint32_t reserved0 : 28; + uint32_t tie_high_lp_pad_hold_all: 1; + uint32_t tie_low_lp_pad_hold_all : 1; + uint32_t tie_high_hp_pad_hold_all: 1; + uint32_t tie_low_hp_pad_hold_all : 1; }; uint32_t val; } pmu_imm_pad_hold_all_reg_t; -/** Type of imm_i2c_iso register - * need_des - */ typedef union { struct { - uint32_t reserved_0:30; - /** tie_high_i2c_iso_en : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t tie_high_i2c_iso_en:1; - /** tie_low_i2c_iso_en : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t tie_low_i2c_iso_en:1; + uint32_t reserved0 : 30; + uint32_t tie_high_i2c_iso_en: 1; + uint32_t tie_low_i2c_iso_en : 1; }; uint32_t val; -} pmu_imm_i2c_iso_reg_t; +} pmu_imm_i2c_isolate_reg_t; + +typedef volatile struct pmu_imm_hw_regmap_t{ + pmu_imm_hp_clk_power_reg_t clk_power; + pmu_imm_sleep_sysclk_reg_t sleep_sysclk; + pmu_imm_hp_func_icg_reg_t hp_func_icg; + pmu_imm_hp_apb_icg_reg_t hp_apb_icg; + pmu_imm_modem_icg_reg_t modem_icg; + pmu_imm_lp_icg_reg_t lp_icg; + pmu_imm_pad_hold_all_reg_t pad_hold_all; + pmu_imm_i2c_isolate_reg_t i2c_iso; +} pmu_imm_hw_regmap_t; -/** Type of power_wait_timer0 register - * need_des - */ typedef union { struct { - uint32_t reserved_0:5; - /** dg_hp_powerdown_timer : R/W; bitpos: [13:5]; default: 255; - * need_des - */ - uint32_t dg_hp_powerdown_timer:9; - /** dg_hp_powerup_timer : R/W; bitpos: [22:14]; default: 255; - * need_des - */ - uint32_t dg_hp_powerup_timer:9; - /** dg_hp_wait_timer : R/W; bitpos: [31:23]; default: 255; - * need_des - */ - uint32_t dg_hp_wait_timer:9; + uint32_t reserved0 : 5; + uint32_t powerdown_timer: 9; + uint32_t powerup_timer : 9; + uint32_t wait_timer : 9; }; uint32_t val; } pmu_power_wait_timer0_reg_t; -/** Type of power_wait_timer1 register - * need_des - */ typedef union { struct { - uint32_t reserved_0:9; - /** dg_lp_powerdown_timer : R/W; bitpos: [15:9]; default: 255; - * need_des - */ - uint32_t dg_lp_powerdown_timer:7; - /** dg_lp_powerup_timer : R/W; bitpos: [22:16]; default: 255; - * need_des - */ - uint32_t dg_lp_powerup_timer:7; - /** dg_lp_wait_timer : R/W; bitpos: [31:23]; default: 255; - * need_des - */ - uint32_t dg_lp_wait_timer:9; + uint32_t reserved0 : 9; + uint32_t powerdown_timer: 7; + uint32_t powerup_timer : 7; + uint32_t wait_timer : 9; }; uint32_t val; } pmu_power_wait_timer1_reg_t; -/** Type of power_pd_top_cntl register - * need_des - */ typedef union { struct { - /** force_top_reset : R/W; bitpos: [0]; default: 0; - * need_des - */ - uint32_t force_top_reset:1; - /** force_top_iso : R/W; bitpos: [1]; default: 0; - * need_des - */ - uint32_t force_top_iso:1; - /** force_top_pu : R/W; bitpos: [2]; default: 1; - * need_des - */ - uint32_t force_top_pu:1; - /** force_top_no_reset : R/W; bitpos: [3]; default: 1; - * need_des - */ - uint32_t force_top_no_reset:1; - /** force_top_no_iso : R/W; bitpos: [4]; default: 1; - * need_des - */ - uint32_t force_top_no_iso:1; - /** force_top_pd : R/W; bitpos: [5]; default: 0; - * need_des - */ - uint32_t force_top_pd:1; - /** pd_top_mask : R/W; bitpos: [10:6]; default: 0; - * need_des - */ - uint32_t pd_top_mask:5; - uint32_t reserved_11:16; - /** pd_top_pd_mask : R/W; bitpos: [31:27]; default: 0; - * need_des - */ - uint32_t pd_top_pd_mask:5; + uint32_t force_reset : 1; + uint32_t force_iso : 1; + uint32_t force_pu : 1; + uint32_t force_no_reset: 1; + uint32_t force_no_iso : 1; + uint32_t force_pd : 1; + uint32_t mask : 5; /* Invalid of lp peripherals */ + uint32_t reserved0 : 16; /* Invalid of lp peripherals */ + uint32_t pd_mask : 5; /* Invalid of lp peripherals */ }; uint32_t val; -} pmu_power_pd_top_cntl_reg_t; +} pmu_power_domain_cntl_reg_t; -/** Type of power_pd_hpaon_cntl register - * need_des - */ typedef union { struct { - /** force_hp_aon_reset : R/W; bitpos: [0]; default: 0; - * need_des - */ - uint32_t force_hp_aon_reset:1; - /** force_hp_aon_iso : R/W; bitpos: [1]; default: 0; - * need_des - */ - uint32_t force_hp_aon_iso:1; - /** force_hp_aon_pu : R/W; bitpos: [2]; default: 1; - * need_des - */ - uint32_t force_hp_aon_pu:1; - /** force_hp_aon_no_reset : R/W; bitpos: [3]; default: 1; - * need_des - */ - uint32_t force_hp_aon_no_reset:1; - /** force_hp_aon_no_iso : R/W; bitpos: [4]; default: 1; - * need_des - */ - uint32_t force_hp_aon_no_iso:1; - /** force_hp_aon_pd : R/W; bitpos: [5]; default: 0; - * need_des - */ - uint32_t force_hp_aon_pd:1; - /** pd_hp_aon_mask : R/W; bitpos: [10:6]; default: 0; - * need_des - */ - uint32_t pd_hp_aon_mask:5; - uint32_t reserved_11:16; - /** pd_hp_aon_pd_mask : R/W; bitpos: [31:27]; default: 0; - * need_des - */ - uint32_t pd_hp_aon_pd_mask:5; + uint32_t force_hp_mem_iso : 4; + uint32_t force_hp_mem_pd : 4; + uint32_t reserved0 : 16; + uint32_t force_hp_mem_no_iso: 4; + uint32_t force_hp_mem_pu : 4; }; uint32_t val; -} pmu_power_pd_hpaon_cntl_reg_t; +} pmu_power_memory_cntl_reg_t; -/** Type of power_pd_hpcpu_cntl register - * need_des - */ typedef union { struct { - /** force_hp_cpu_reset : R/W; bitpos: [0]; default: 0; - * need_des - */ - uint32_t force_hp_cpu_reset:1; - /** force_hp_cpu_iso : R/W; bitpos: [1]; default: 0; - * need_des - */ - uint32_t force_hp_cpu_iso:1; - /** force_hp_cpu_pu : R/W; bitpos: [2]; default: 1; - * need_des - */ - uint32_t force_hp_cpu_pu:1; - /** force_hp_cpu_no_reset : R/W; bitpos: [3]; default: 1; - * need_des - */ - uint32_t force_hp_cpu_no_reset:1; - /** force_hp_cpu_no_iso : R/W; bitpos: [4]; default: 1; - * need_des - */ - uint32_t force_hp_cpu_no_iso:1; - /** force_hp_cpu_pd : R/W; bitpos: [5]; default: 0; - * need_des - */ - uint32_t force_hp_cpu_pd:1; - /** pd_hp_cpu_mask : R/W; bitpos: [10:6]; default: 0; - * need_des - */ - uint32_t pd_hp_cpu_mask:5; - uint32_t reserved_11:16; - /** pd_hp_cpu_pd_mask : R/W; bitpos: [31:27]; default: 0; - * need_des - */ - uint32_t pd_hp_cpu_pd_mask:5; + uint32_t mem2_pd_mask: 5; + uint32_t mem1_pd_mask: 5; + uint32_t mem0_pd_mask: 5; + uint32_t reserved0 : 2; + uint32_t mem2_mask : 5; + uint32_t mem1_mask : 5; + uint32_t mem0_mask : 5; }; uint32_t val; -} pmu_power_pd_hpcpu_cntl_reg_t; +} pmu_power_memory_mask_reg_t; -/** Type of power_pd_hpperi_reserve register - * need_des - */ typedef union { struct { - /** hp_peri_reserve : WT; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t hp_peri_reserve:32; - }; - uint32_t val; -} pmu_power_pd_hpperi_reserve_reg_t; - -/** Type of power_pd_hpwifi_cntl register - * need_des - */ -typedef union { - struct { - /** force_hp_wifi_reset : R/W; bitpos: [0]; default: 0; - * need_des - */ - uint32_t force_hp_wifi_reset:1; - /** force_hp_wifi_iso : R/W; bitpos: [1]; default: 0; - * need_des - */ - uint32_t force_hp_wifi_iso:1; - /** force_hp_wifi_pu : R/W; bitpos: [2]; default: 1; - * need_des - */ - uint32_t force_hp_wifi_pu:1; - /** force_hp_wifi_no_reset : R/W; bitpos: [3]; default: 1; - * need_des - */ - uint32_t force_hp_wifi_no_reset:1; - /** force_hp_wifi_no_iso : R/W; bitpos: [4]; default: 1; - * need_des - */ - uint32_t force_hp_wifi_no_iso:1; - /** force_hp_wifi_pd : R/W; bitpos: [5]; default: 0; - * need_des - */ - uint32_t force_hp_wifi_pd:1; - /** pd_hp_wifi_mask : R/W; bitpos: [10:6]; default: 0; - * need_des - */ - uint32_t pd_hp_wifi_mask:5; - uint32_t reserved_11:16; - /** pd_hp_wifi_pd_mask : R/W; bitpos: [31:27]; default: 0; - * need_des - */ - uint32_t pd_hp_wifi_pd_mask:5; - }; - uint32_t val; -} pmu_power_pd_hpwifi_cntl_reg_t; - -/** Type of power_pd_lpperi_cntl register - * need_des - */ -typedef union { - struct { - /** force_lp_peri_reset : R/W; bitpos: [0]; default: 0; - * need_des - */ - uint32_t force_lp_peri_reset:1; - /** force_lp_peri_iso : R/W; bitpos: [1]; default: 0; - * need_des - */ - uint32_t force_lp_peri_iso:1; - /** force_lp_peri_pu : R/W; bitpos: [2]; default: 1; - * need_des - */ - uint32_t force_lp_peri_pu:1; - /** force_lp_peri_no_reset : R/W; bitpos: [3]; default: 1; - * need_des - */ - uint32_t force_lp_peri_no_reset:1; - /** force_lp_peri_no_iso : R/W; bitpos: [4]; default: 1; - * need_des - */ - uint32_t force_lp_peri_no_iso:1; - /** force_lp_peri_pd : R/W; bitpos: [5]; default: 0; - * need_des - */ - uint32_t force_lp_peri_pd:1; - uint32_t reserved_6:26; - }; - uint32_t val; -} pmu_power_pd_lpperi_cntl_reg_t; - -/** Type of power_pd_mem_cntl register - * need_des - */ -typedef union { - struct { - /** force_hp_mem_iso : R/W; bitpos: [3:0]; default: 0; - * need_des - */ - uint32_t force_hp_mem_iso:4; - /** force_hp_mem_pd : R/W; bitpos: [7:4]; default: 0; - * need_des - */ - uint32_t force_hp_mem_pd:4; - uint32_t reserved_8:16; - /** force_hp_mem_no_iso : R/W; bitpos: [27:24]; default: 15; - * need_des - */ - uint32_t force_hp_mem_no_iso:4; - /** force_hp_mem_pu : R/W; bitpos: [31:28]; default: 15; - * need_des - */ - uint32_t force_hp_mem_pu:4; - }; - uint32_t val; -} pmu_power_pd_mem_cntl_reg_t; - -/** Type of power_pd_mem_mask register - * need_des - */ -typedef union { - struct { - /** pd_hp_mem2_pd_mask : R/W; bitpos: [4:0]; default: 0; - * need_des - */ - uint32_t pd_hp_mem2_pd_mask:5; - /** pd_hp_mem1_pd_mask : R/W; bitpos: [9:5]; default: 0; - * need_des - */ - uint32_t pd_hp_mem1_pd_mask:5; - /** pd_hp_mem0_pd_mask : R/W; bitpos: [14:10]; default: 0; - * need_des - */ - uint32_t pd_hp_mem0_pd_mask:5; - uint32_t reserved_15:2; - /** pd_hp_mem2_mask : R/W; bitpos: [21:17]; default: 0; - * need_des - */ - uint32_t pd_hp_mem2_mask:5; - /** pd_hp_mem1_mask : R/W; bitpos: [26:22]; default: 0; - * need_des - */ - uint32_t pd_hp_mem1_mask:5; - /** pd_hp_mem0_mask : R/W; bitpos: [31:27]; default: 0; - * need_des - */ - uint32_t pd_hp_mem0_mask:5; - }; - uint32_t val; -} pmu_power_pd_mem_mask_reg_t; - -/** Type of power_hp_pad register - * need_des - */ -typedef union { - struct { - /** force_hp_pad_no_iso_all : R/W; bitpos: [0]; default: 0; - * need_des - */ - uint32_t force_hp_pad_no_iso_all:1; - /** force_hp_pad_iso_all : R/W; bitpos: [1]; default: 0; - * need_des - */ - uint32_t force_hp_pad_iso_all:1; - uint32_t reserved_2:30; + uint32_t force_hp_pad_no_iso_all: 1; + uint32_t force_hp_pad_iso_all : 1; + uint32_t reserved0 : 30; }; uint32_t val; } pmu_power_hp_pad_reg_t; -/** Type of power_vdd_spi_cntl register - * need_des - */ typedef union { struct { - uint32_t reserved_0:18; - /** vdd_spi_pwr_wait : R/W; bitpos: [28:18]; default: 255; - * need_des - */ - uint32_t vdd_spi_pwr_wait:11; - /** vdd_spi_pwr_sw : R/W; bitpos: [30:29]; default: 3; - * need_des - */ - uint32_t vdd_spi_pwr_sw:2; - /** vdd_spi_pwr_sel_sw : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t vdd_spi_pwr_sel_sw:1; + uint32_t reserved0 : 18; + uint32_t pwr_wait : 11; + uint32_t pwr_sw : 2; + uint32_t pwr_sel_sw: 1; }; uint32_t val; } pmu_power_vdd_spi_cntl_reg_t; -/** Type of power_ck_wait_cntl register - * need_des - */ typedef union { struct { - /** wait_xtl_stable : R/W; bitpos: [15:0]; default: 256; - * need_des - */ - uint32_t wait_xtl_stable:16; - /** wait_pll_stable : R/W; bitpos: [31:16]; default: 256; - * need_des - */ - uint32_t wait_pll_stable:16; + uint32_t wait_xtal_stable: 16; + uint32_t wait_pll_stable : 16; }; uint32_t val; -} pmu_power_ck_wait_cntl_reg_t; +} pmu_power_clk_wait_cntl_reg_t; + +typedef volatile struct pmu_power_hw_regmap_t{ + pmu_power_wait_timer0_reg_t wait_timer0; + pmu_power_wait_timer1_reg_t wait_timer1; + pmu_power_domain_cntl_reg_t hp_pd[5]; + pmu_power_domain_cntl_reg_t lp_peri; + pmu_power_memory_cntl_reg_t mem_cntl; + pmu_power_memory_mask_reg_t mem_mask; + pmu_power_hp_pad_reg_t hp_pad; + pmu_power_vdd_spi_cntl_reg_t vdd_spi; + pmu_power_clk_wait_cntl_reg_t clk_wait; +} pmu_power_hw_regmap_t; -/** Type of slp_wakeup_cntl0 register - * need_des - */ typedef union { struct { - uint32_t reserved_0:31; - /** sleep_req : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t sleep_req:1; + uint32_t reserved0: 31; + uint32_t sleep_req: 1; }; uint32_t val; } pmu_slp_wakeup_cntl0_reg_t; -/** Type of slp_wakeup_cntl1 register - * need_des - */ typedef union { struct { - /** sleep_reject_ena : R/W; bitpos: [30:0]; default: 0; - * need_des - */ - uint32_t sleep_reject_ena:31; - /** slp_reject_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t slp_reject_en:1; + uint32_t sleep_reject_ena: 31; + uint32_t slp_reject_en : 1; }; uint32_t val; } pmu_slp_wakeup_cntl1_reg_t; -/** Type of slp_wakeup_cntl2 register - * need_des - */ typedef union { struct { - /** wakeup_ena : R/W; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t wakeup_ena:32; - }; - uint32_t val; -} pmu_slp_wakeup_cntl2_reg_t; - -/** Type of slp_wakeup_cntl3 register - * need_des - */ -typedef union { - struct { - /** lp_min_slp_val : R/W; bitpos: [7:0]; default: 0; - * need_des - */ - uint32_t lp_min_slp_val:8; - /** hp_min_slp_val : R/W; bitpos: [15:8]; default: 0; - * need_des - */ - uint32_t hp_min_slp_val:8; - /** sleep_prt_sel : R/W; bitpos: [17:16]; default: 0; - * need_des - */ - uint32_t sleep_prt_sel:2; - uint32_t reserved_18:14; + uint32_t lp_min_slp_val: 8; + uint32_t hp_min_slp_val: 8; + uint32_t sleep_prt_sel : 2; + uint32_t reserved0 : 14; }; uint32_t val; } pmu_slp_wakeup_cntl3_reg_t; -/** Type of slp_wakeup_cntl4 register - * need_des - */ typedef union { struct { - uint32_t reserved_0:31; - /** slp_reject_cause_clr : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t slp_reject_cause_clr:1; + uint32_t reserved0 : 31; + uint32_t slp_reject_cause_clr: 1; }; uint32_t val; } pmu_slp_wakeup_cntl4_reg_t; -/** Type of slp_wakeup_cntl5 register - * need_des - */ typedef union { struct { - /** modem_wait_target : R/W; bitpos: [19:0]; default: 128; - * need_des - */ - uint32_t modem_wait_target:20; - uint32_t reserved_20:4; - /** lp_ana_wait_target : R/W; bitpos: [31:24]; default: 1; - * need_des - */ - uint32_t lp_ana_wait_target:8; + uint32_t modem_wait_target : 20; + uint32_t reserved0 : 4; + uint32_t lp_ana_wait_target: 8; }; uint32_t val; } pmu_slp_wakeup_cntl5_reg_t; -/** Type of slp_wakeup_cntl6 register - * need_des - */ typedef union { struct { - /** soc_wakeup_wait : R/W; bitpos: [19:0]; default: 128; - * need_des - */ - uint32_t soc_wakeup_wait:20; - uint32_t reserved_20:10; - /** soc_wakeup_wait_cfg : R/W; bitpos: [31:30]; default: 0; - * need_des - */ - uint32_t soc_wakeup_wait_cfg:2; + uint32_t soc_wakeup_wait : 20; + uint32_t reserved0 : 10; + uint32_t soc_wakeup_wait_cfg: 2; }; uint32_t val; } pmu_slp_wakeup_cntl6_reg_t; -/** Type of slp_wakeup_cntl7 register - * need_des - */ typedef union { struct { - uint32_t reserved_0:16; - /** ana_wait_target : R/W; bitpos: [31:16]; default: 1; - * need_des - */ - uint32_t ana_wait_target:16; + uint32_t reserved0 : 16; + uint32_t ana_wait_target: 16; }; uint32_t val; } pmu_slp_wakeup_cntl7_reg_t; -/** Type of slp_wakeup_status0 register - * need_des - */ +typedef volatile struct pmu_wakeup_hw_regmap_t{ + pmu_slp_wakeup_cntl0_reg_t cntl0; + pmu_slp_wakeup_cntl1_reg_t cntl1; + uint32_t cntl2; + pmu_slp_wakeup_cntl3_reg_t cntl3; + pmu_slp_wakeup_cntl4_reg_t cntl4; + pmu_slp_wakeup_cntl5_reg_t cntl5; + pmu_slp_wakeup_cntl6_reg_t cntl6; + pmu_slp_wakeup_cntl7_reg_t cntl7; + uint32_t status0; + uint32_t status1; +} pmu_wakeup_hw_regmap_t; + typedef union { struct { - /** wakeup_cause : RO; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t wakeup_cause:32; + uint32_t i2c_por_wait_target: 8; + uint32_t reserved0 : 24; }; uint32_t val; -} pmu_slp_wakeup_status0_reg_t; +} pmu_hp_clk_poweron_reg_t; -/** Type of slp_wakeup_status1 register - * need_des - */ typedef union { struct { - /** reject_cause : RO; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t reject_cause:32; + uint32_t modify_icg_cntl_wait: 8; + uint32_t switch_icg_cntl_wait: 8; + uint32_t reserved0 : 16; }; uint32_t val; -} pmu_slp_wakeup_status1_reg_t; +} pmu_hp_clk_cntl_reg_t; -/** Type of hp_ck_poweron register - * need_des - */ typedef union { struct { - /** i2c_por_wait_target : R/W; bitpos: [7:0]; default: 50; - * need_des - */ - uint32_t i2c_por_wait_target:8; - uint32_t reserved_8:24; - }; - uint32_t val; -} pmu_hp_ck_poweron_reg_t; - -/** Type of hp_ck_cntl register - * need_des - */ -typedef union { - struct { - /** modify_icg_cntl_wait : R/W; bitpos: [7:0]; default: 10; - * need_des - */ - uint32_t modify_icg_cntl_wait:8; - /** switch_icg_cntl_wait : R/W; bitpos: [15:8]; default: 10; - * need_des - */ - uint32_t switch_icg_cntl_wait:8; - uint32_t reserved_16:16; - }; - uint32_t val; -} pmu_hp_ck_cntl_reg_t; - -/** Type of por_status register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** por_done : RO; bitpos: [31]; default: 1; - * need_des - */ - uint32_t por_done:1; + uint32_t reserved0: 31; + uint32_t por_done : 1; }; uint32_t val; } pmu_por_status_reg_t; -/** Type of rf_pwc register - * need_des - */ typedef union { struct { - uint32_t reserved_0:26; - /** perif_i2c_rstb : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t perif_i2c_rstb:1; - /** xpd_perif_i2c : R/W; bitpos: [27]; default: 1; - * need_des - */ - uint32_t xpd_perif_i2c:1; - /** xpd_txrf_i2c : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t xpd_txrf_i2c:1; - /** xpd_rfrx_pbus : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t xpd_rfrx_pbus:1; - /** xpd_ckgen_i2c : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t xpd_ckgen_i2c:1; - /** xpd_pll_i2c : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t xpd_pll_i2c:1; + uint32_t reserved0 : 26; + uint32_t perif_i2c_rstb: 1; + uint32_t xpd_perif_i2c : 1; + uint32_t xpd_txrf_i2c : 1; + uint32_t xpd_rfrx_pbus : 1; + uint32_t xpd_ckgen_i2c : 1; + uint32_t xpd_pll_i2c : 1; }; uint32_t val; } pmu_rf_pwc_reg_t; -/** Type of backup_cfg register - * need_des - */ typedef union { struct { - uint32_t reserved_0:31; - /** backup_sys_clk_no_div : R/W; bitpos: [31]; default: 1; - * need_des - */ - uint32_t backup_sys_clk_no_div:1; + uint32_t reserved0 : 31; + uint32_t backup_sysclk_nodiv: 1; }; uint32_t val; } pmu_backup_cfg_reg_t; -/** Type of int_raw register - * need_des - */ typedef union { struct { - uint32_t reserved_0:27; - /** lp_cpu_exc_int_raw : R/WTC/SS; bitpos: [27]; default: 0; - * need_des - */ - uint32_t lp_cpu_exc_int_raw:1; - /** sdio_idle_int_raw : R/WTC/SS; bitpos: [28]; default: 0; - * need_des - */ - uint32_t sdio_idle_int_raw:1; - /** sw_int_raw : R/WTC/SS; bitpos: [29]; default: 0; - * need_des - */ - uint32_t sw_int_raw:1; - /** soc_sleep_reject_int_raw : R/WTC/SS; bitpos: [30]; default: 0; - * need_des - */ - uint32_t soc_sleep_reject_int_raw:1; - /** soc_wakeup_int_raw : R/WTC/SS; bitpos: [31]; default: 0; - * need_des - */ - uint32_t soc_wakeup_int_raw:1; + uint32_t reserved0 : 27; + uint32_t lp_cpu_exc: 1; + uint32_t sdio_idle : 1; + uint32_t sw : 1; + uint32_t reject : 1; + uint32_t wakeup : 1; }; uint32_t val; -} pmu_int_raw_reg_t; +} pmu_hp_intr_reg_t; + +typedef volatile struct pmu_hp_ext_hw_regmap_t{ + pmu_hp_clk_poweron_reg_t clk_poweron; + pmu_hp_clk_cntl_reg_t clk_cntl; + pmu_por_status_reg_t por_status; + pmu_rf_pwc_reg_t rf_pwc; + pmu_backup_cfg_reg_t backup_cfg; + pmu_hp_intr_reg_t int_raw; + pmu_hp_intr_reg_t int_st; + pmu_hp_intr_reg_t int_ena; + pmu_hp_intr_reg_t int_clr; +} pmu_hp_ext_hw_regmap_t; -/** Type of hp_int_st register - * need_des - */ typedef union { struct { - uint32_t reserved_0:27; - /** lp_cpu_exc_int_st : RO; bitpos: [27]; default: 0; - * need_des - */ - uint32_t lp_cpu_exc_int_st:1; - /** sdio_idle_int_st : RO; bitpos: [28]; default: 0; - * need_des - */ - uint32_t sdio_idle_int_st:1; - /** sw_int_st : RO; bitpos: [29]; default: 0; - * need_des - */ - uint32_t sw_int_st:1; - /** soc_sleep_reject_int_st : RO; bitpos: [30]; default: 0; - * need_des - */ - uint32_t soc_sleep_reject_int_st:1; - /** soc_wakeup_int_st : RO; bitpos: [31]; default: 0; - * need_des - */ - uint32_t soc_wakeup_int_st:1; + uint32_t reserved0 : 20; + uint32_t lp_cpu_wakeup : 1; + uint32_t modem_switch_active_end : 1; + uint32_t sleep_switch_active_end : 1; + uint32_t sleep_switch_modem_end : 1; + uint32_t modem_switch_sleep_end : 1; + uint32_t active_swtich_sleep_end : 1; + uint32_t modem_switch_active_start: 1; + uint32_t sleep_switch_active_start: 1; + uint32_t sleep_switch_modem_start : 1; + uint32_t modem_switch_sleep_start : 1; + uint32_t active_switch_sleep_start: 1; + uint32_t sw_trigger : 1; }; uint32_t val; -} pmu_hp_int_st_reg_t; +} pmu_lp_intr_reg_t; -/** Type of hp_int_ena register - * need_des - */ typedef union { struct { - uint32_t reserved_0:27; - /** lp_cpu_exc_int_ena : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t lp_cpu_exc_int_ena:1; - /** sdio_idle_int_ena : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t sdio_idle_int_ena:1; - /** sw_int_ena : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t sw_int_ena:1; - /** soc_sleep_reject_int_ena : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t soc_sleep_reject_int_ena:1; - /** soc_wakeup_int_ena : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t soc_wakeup_int_ena:1; - }; - uint32_t val; -} pmu_hp_int_ena_reg_t; - -/** Type of hp_int_clr register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:27; - /** lp_cpu_exc_int_clr : WT; bitpos: [27]; default: 0; - * need_des - */ - uint32_t lp_cpu_exc_int_clr:1; - /** sdio_idle_int_clr : WT; bitpos: [28]; default: 0; - * need_des - */ - uint32_t sdio_idle_int_clr:1; - /** sw_int_clr : WT; bitpos: [29]; default: 0; - * need_des - */ - uint32_t sw_int_clr:1; - /** soc_sleep_reject_int_clr : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t soc_sleep_reject_int_clr:1; - /** soc_wakeup_int_clr : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t soc_wakeup_int_clr:1; - }; - uint32_t val; -} pmu_hp_int_clr_reg_t; - -/** Type of lp_int_raw register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:20; - /** lp_cpu_wakeup_int_raw : R/WTC/SS; bitpos: [20]; default: 0; - * need_des - */ - uint32_t lp_cpu_wakeup_int_raw:1; - /** modem_switch_active_end_int_raw : R/WTC/SS; bitpos: [21]; default: 0; - * need_des - */ - uint32_t modem_switch_active_end_int_raw:1; - /** sleep_switch_active_end_int_raw : R/WTC/SS; bitpos: [22]; default: 0; - * need_des - */ - uint32_t sleep_switch_active_end_int_raw:1; - /** sleep_switch_modem_end_int_raw : R/WTC/SS; bitpos: [23]; default: 0; - * need_des - */ - uint32_t sleep_switch_modem_end_int_raw:1; - /** modem_switch_sleep_end_int_raw : R/WTC/SS; bitpos: [24]; default: 0; - * need_des - */ - uint32_t modem_switch_sleep_end_int_raw:1; - /** active_switch_sleep_end_int_raw : R/WTC/SS; bitpos: [25]; default: 0; - * need_des - */ - uint32_t active_switch_sleep_end_int_raw:1; - /** modem_switch_active_start_int_raw : R/WTC/SS; bitpos: [26]; default: 0; - * need_des - */ - uint32_t modem_switch_active_start_int_raw:1; - /** sleep_switch_active_start_int_raw : R/WTC/SS; bitpos: [27]; default: 0; - * need_des - */ - uint32_t sleep_switch_active_start_int_raw:1; - /** sleep_switch_modem_start_int_raw : R/WTC/SS; bitpos: [28]; default: 0; - * need_des - */ - uint32_t sleep_switch_modem_start_int_raw:1; - /** modem_switch_sleep_start_int_raw : R/WTC/SS; bitpos: [29]; default: 0; - * need_des - */ - uint32_t modem_switch_sleep_start_int_raw:1; - /** active_switch_sleep_start_int_raw : R/WTC/SS; bitpos: [30]; default: 0; - * need_des - */ - uint32_t active_switch_sleep_start_int_raw:1; - /** hp_sw_trigger_int_raw : R/WTC/SS; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_sw_trigger_int_raw:1; - }; - uint32_t val; -} pmu_lp_int_raw_reg_t; - -/** Type of lp_int_st register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:20; - /** lp_cpu_wakeup_int_st : RO; bitpos: [20]; default: 0; - * need_des - */ - uint32_t lp_cpu_wakeup_int_st:1; - /** modem_switch_active_end_int_st : RO; bitpos: [21]; default: 0; - * need_des - */ - uint32_t modem_switch_active_end_int_st:1; - /** sleep_switch_active_end_int_st : RO; bitpos: [22]; default: 0; - * need_des - */ - uint32_t sleep_switch_active_end_int_st:1; - /** sleep_switch_modem_end_int_st : RO; bitpos: [23]; default: 0; - * need_des - */ - uint32_t sleep_switch_modem_end_int_st:1; - /** modem_switch_sleep_end_int_st : RO; bitpos: [24]; default: 0; - * need_des - */ - uint32_t modem_switch_sleep_end_int_st:1; - /** active_switch_sleep_end_int_st : RO; bitpos: [25]; default: 0; - * need_des - */ - uint32_t active_switch_sleep_end_int_st:1; - /** modem_switch_active_start_int_st : RO; bitpos: [26]; default: 0; - * need_des - */ - uint32_t modem_switch_active_start_int_st:1; - /** sleep_switch_active_start_int_st : RO; bitpos: [27]; default: 0; - * need_des - */ - uint32_t sleep_switch_active_start_int_st:1; - /** sleep_switch_modem_start_int_st : RO; bitpos: [28]; default: 0; - * need_des - */ - uint32_t sleep_switch_modem_start_int_st:1; - /** modem_switch_sleep_start_int_st : RO; bitpos: [29]; default: 0; - * need_des - */ - uint32_t modem_switch_sleep_start_int_st:1; - /** active_switch_sleep_start_int_st : RO; bitpos: [30]; default: 0; - * need_des - */ - uint32_t active_switch_sleep_start_int_st:1; - /** hp_sw_trigger_int_st : RO; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_sw_trigger_int_st:1; - }; - uint32_t val; -} pmu_lp_int_st_reg_t; - -/** Type of lp_int_ena register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:20; - /** lp_cpu_wakeup_int_ena : R/W; bitpos: [20]; default: 0; - * need_des - */ - uint32_t lp_cpu_wakeup_int_ena:1; - /** modem_switch_active_end_int_ena : R/W; bitpos: [21]; default: 0; - * need_des - */ - uint32_t modem_switch_active_end_int_ena:1; - /** sleep_switch_active_end_int_ena : R/W; bitpos: [22]; default: 0; - * need_des - */ - uint32_t sleep_switch_active_end_int_ena:1; - /** sleep_switch_modem_end_int_ena : R/W; bitpos: [23]; default: 0; - * need_des - */ - uint32_t sleep_switch_modem_end_int_ena:1; - /** modem_switch_sleep_end_int_ena : R/W; bitpos: [24]; default: 0; - * need_des - */ - uint32_t modem_switch_sleep_end_int_ena:1; - /** active_switch_sleep_end_int_ena : R/W; bitpos: [25]; default: 0; - * need_des - */ - uint32_t active_switch_sleep_end_int_ena:1; - /** modem_switch_active_start_int_ena : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t modem_switch_active_start_int_ena:1; - /** sleep_switch_active_start_int_ena : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t sleep_switch_active_start_int_ena:1; - /** sleep_switch_modem_start_int_ena : R/W; bitpos: [28]; default: 0; - * need_des - */ - uint32_t sleep_switch_modem_start_int_ena:1; - /** modem_switch_sleep_start_int_ena : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t modem_switch_sleep_start_int_ena:1; - /** active_switch_sleep_start_int_ena : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t active_switch_sleep_start_int_ena:1; - /** hp_sw_trigger_int_ena : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_sw_trigger_int_ena:1; - }; - uint32_t val; -} pmu_lp_int_ena_reg_t; - -/** Type of lp_int_clr register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:20; - /** lp_cpu_wakeup_int_clr : WT; bitpos: [20]; default: 0; - * need_des - */ - uint32_t lp_cpu_wakeup_int_clr:1; - /** modem_switch_active_end_int_clr : WT; bitpos: [21]; default: 0; - * need_des - */ - uint32_t modem_switch_active_end_int_clr:1; - /** sleep_switch_active_end_int_clr : WT; bitpos: [22]; default: 0; - * need_des - */ - uint32_t sleep_switch_active_end_int_clr:1; - /** sleep_switch_modem_end_int_clr : WT; bitpos: [23]; default: 0; - * need_des - */ - uint32_t sleep_switch_modem_end_int_clr:1; - /** modem_switch_sleep_end_int_clr : WT; bitpos: [24]; default: 0; - * need_des - */ - uint32_t modem_switch_sleep_end_int_clr:1; - /** active_switch_sleep_end_int_clr : WT; bitpos: [25]; default: 0; - * need_des - */ - uint32_t active_switch_sleep_end_int_clr:1; - /** modem_switch_active_start_int_clr : WT; bitpos: [26]; default: 0; - * need_des - */ - uint32_t modem_switch_active_start_int_clr:1; - /** sleep_switch_active_start_int_clr : WT; bitpos: [27]; default: 0; - * need_des - */ - uint32_t sleep_switch_active_start_int_clr:1; - /** sleep_switch_modem_start_int_clr : WT; bitpos: [28]; default: 0; - * need_des - */ - uint32_t sleep_switch_modem_start_int_clr:1; - /** modem_switch_sleep_start_int_clr : WT; bitpos: [29]; default: 0; - * need_des - */ - uint32_t modem_switch_sleep_start_int_clr:1; - /** active_switch_sleep_start_int_clr : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t active_switch_sleep_start_int_clr:1; - /** hp_sw_trigger_int_clr : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_sw_trigger_int_clr:1; - }; - uint32_t val; -} pmu_lp_int_clr_reg_t; - -/** Type of lp_cpu_pwr0 register - * need_des - */ -typedef union { - struct { - /** lp_cpu_waiti_rdy : RO; bitpos: [0]; default: 0; - * need_des - */ - uint32_t lp_cpu_waiti_rdy:1; - /** lp_cpu_stall_rdy : RO; bitpos: [1]; default: 0; - * need_des - */ - uint32_t lp_cpu_stall_rdy:1; - uint32_t reserved_2:16; - /** lp_cpu_force_stall : R/W; bitpos: [18]; default: 0; - * need_des - */ - uint32_t lp_cpu_force_stall:1; - /** lp_cpu_slp_waiti_flag_en : R/W; bitpos: [19]; default: 0; - * need_des - */ - uint32_t lp_cpu_slp_waiti_flag_en:1; - /** lp_cpu_slp_stall_flag_en : R/W; bitpos: [20]; default: 1; - * need_des - */ - uint32_t lp_cpu_slp_stall_flag_en:1; - /** lp_cpu_slp_stall_wait : R/W; bitpos: [28:21]; default: 255; - * need_des - */ - uint32_t lp_cpu_slp_stall_wait:8; - /** lp_cpu_slp_stall_en : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t lp_cpu_slp_stall_en:1; - /** lp_cpu_slp_reset_en : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t lp_cpu_slp_reset_en:1; - /** lp_cpu_slp_bypass_intr_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t lp_cpu_slp_bypass_intr_en:1; + uint32_t waiti_rdy : 1; + uint32_t stall_rdy : 1; + uint32_t reserved0 : 16; + uint32_t force_stall : 1; + uint32_t slp_waiti_flag_en : 1; + uint32_t slp_stall_flag_en : 1; + uint32_t slp_stall_wait : 8; + uint32_t slp_stall_en : 1; + uint32_t slp_reset_en : 1; + uint32_t slp_bypass_intr_en: 1; }; uint32_t val; } pmu_lp_cpu_pwr0_reg_t; -/** Type of lp_cpu_pwr1 register - * need_des - */ typedef union { struct { - /** lp_cpu_wakeup_en : R/W; bitpos: [15:0]; default: 0; - * need_des - */ - uint32_t lp_cpu_wakeup_en:16; - uint32_t reserved_16:15; - /** lp_cpu_sleep_req : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t lp_cpu_sleep_req:1; + uint32_t wakeup_en: 16; + uint32_t reserved0: 15; + uint32_t sleep_req: 1; }; uint32_t val; } pmu_lp_cpu_pwr1_reg_t; -/** Type of hp_lp_cpu_comm register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** lp_trigger_hp : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t lp_trigger_hp:1; - /** hp_trigger_lp : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t hp_trigger_lp:1; - }; - uint32_t val; -} pmu_hp_lp_cpu_comm_reg_t; +typedef volatile struct pmu_lp_ext_hw_regmap_t{ + pmu_lp_intr_reg_t int_raw; + pmu_lp_intr_reg_t int_st; + pmu_lp_intr_reg_t int_ena; + pmu_lp_intr_reg_t int_clr; + pmu_lp_cpu_pwr0_reg_t pwr0; + pmu_lp_cpu_pwr1_reg_t pwr1; +} pmu_lp_ext_hw_regmap_t; -/** Type of hp_regulator_cfg register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** dig_regulator_en_cal : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t dig_regulator_en_cal:1; - }; - uint32_t val; -} pmu_hp_regulator_cfg_reg_t; +typedef volatile struct pmu_dev_t{ + pmu_hp_hw_regmap_t hp_sys[3]; + pmu_lp_hw_regmap_t lp_sys[2]; + pmu_imm_hw_regmap_t imm; + pmu_power_hw_regmap_t power; + pmu_wakeup_hw_regmap_t wakeup; + pmu_hp_ext_hw_regmap_t hp_ext; + pmu_lp_ext_hw_regmap_t lp_ext; -/** Type of main_state register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:11; - /** main_last_st_state : RO; bitpos: [17:11]; default: 1; - * need_des - */ - uint32_t main_last_st_state:7; - /** main_tar_st_state : RO; bitpos: [24:18]; default: 4; - * need_des - */ - uint32_t main_tar_st_state:7; - /** main_cur_st_state : RO; bitpos: [31:25]; default: 4; - * need_des - */ - uint32_t main_cur_st_state:7; - }; - uint32_t val; -} pmu_main_state_reg_t; + union { + struct { + uint32_t reserved0 : 30; + uint32_t lp_trigger_hp: 1; + uint32_t hp_trigger_lp: 1; + }; + uint32_t val; + } hp_lp_cpu_comm; -/** Type of pwr_state register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:13; - /** backup_st_state : RO; bitpos: [17:13]; default: 1; - * need_des - */ - uint32_t backup_st_state:5; - /** lp_pwr_st_state : RO; bitpos: [22:18]; default: 0; - * need_des - */ - uint32_t lp_pwr_st_state:5; - /** hp_pwr_st_state : RO; bitpos: [31:23]; default: 1; - * need_des - */ - uint32_t hp_pwr_st_state:9; - }; - uint32_t val; -} pmu_pwr_state_reg_t; + union { + struct { + uint32_t reserved0 : 31; + uint32_t dig_regulator_en_cal: 1; + }; + uint32_t val; + } hp_regulator_cfg; -/** Type of date register - * need_des - */ -typedef union { - struct { - /** pmu_date : R/W; bitpos: [30:0]; default: 35676752; - * need_des - */ - uint32_t pmu_date:31; - /** clk_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t clk_en:1; - }; - uint32_t val; -} pmu_date_reg_t; + union { + struct { + uint32_t reserved0 : 11; + uint32_t last_st : 7; + uint32_t target_st : 7; + uint32_t current_st: 7; + }; + uint32_t val; + } main_state; + union { + struct { + uint32_t reserved0: 13; + uint32_t backup_st: 5; + uint32_t lp_pwr_st: 5; + uint32_t hp_pwr_st: 9; + }; + uint32_t val; + } pwr_state; -/** Group: status_register */ -/** Type of clk_state0 register - * need_des - */ -typedef union { - struct { - /** stable_xpd_bbpll_state : RO; bitpos: [0]; default: 1; - * need_des - */ - uint32_t stable_xpd_bbpll_state:1; - /** stable_xpd_xtal_state : RO; bitpos: [1]; default: 1; - * need_des - */ - uint32_t stable_xpd_xtal_state:1; - uint32_t reserved_2:13; - /** sys_clk_slp_sel_state : RO; bitpos: [15]; default: 0; - * need_des - */ - uint32_t sys_clk_slp_sel_state:1; - /** sys_clk_sel_state : RO; bitpos: [17:16]; default: 0; - * need_des - */ - uint32_t sys_clk_sel_state:2; - /** sys_clk_no_div_state : RO; bitpos: [18]; default: 0; - * need_des - */ - uint32_t sys_clk_no_div_state:1; - /** icg_sys_clk_en_state : RO; bitpos: [19]; default: 0; - * need_des - */ - uint32_t icg_sys_clk_en_state:1; - /** icg_modem_switch_state : RO; bitpos: [20]; default: 0; - * need_des - */ - uint32_t icg_modem_switch_state:1; - /** icg_modem_code_state : RO; bitpos: [22:21]; default: 0; - * need_des - */ - uint32_t icg_modem_code_state:2; - /** icg_slp_sel_state : RO; bitpos: [23]; default: 0; - * need_des - */ - uint32_t icg_slp_sel_state:1; - /** icg_global_xtal_state : RO; bitpos: [24]; default: 0; - * need_des - */ - uint32_t icg_global_xtal_state:1; - /** icg_global_pll_state : RO; bitpos: [25]; default: 0; - * need_des - */ - uint32_t icg_global_pll_state:1; - /** ana_i2c_iso_en_state : RO; bitpos: [26]; default: 0; - * need_des - */ - uint32_t ana_i2c_iso_en_state:1; - /** ana_i2c_retention_state : RO; bitpos: [27]; default: 0; - * need_des - */ - uint32_t ana_i2c_retention_state:1; - /** ana_xpd_bb_i2c_state : RO; bitpos: [28]; default: 0; - * need_des - */ - uint32_t ana_xpd_bb_i2c_state:1; - /** ana_xpd_bbpll_i2c_state : RO; bitpos: [29]; default: 0; - * need_des - */ - uint32_t ana_xpd_bbpll_i2c_state:1; - /** ana_xpd_bbpll_state : RO; bitpos: [30]; default: 0; - * need_des - */ - uint32_t ana_xpd_bbpll_state:1; - /** ana_xpd_xtal_state : RO; bitpos: [31]; default: 0; - * need_des - */ - uint32_t ana_xpd_xtal_state:1; - }; - uint32_t val; -} pmu_clk_state0_reg_t; + union { + struct { + uint32_t stable_xpd_bbpll : 1; + uint32_t stable_xpd_xtal : 1; + uint32_t reserved0 : 13; + uint32_t sysclk_slp_sel : 1; + uint32_t sysclk_sel : 2; + uint32_t sysclk_nodiv : 1; + uint32_t icg_sysclk_en : 1; + uint32_t icg_modem_switch : 1; + uint32_t icg_modem_code : 2; + uint32_t icg_slp_sel : 1; + uint32_t icg_global_xtal : 1; + uint32_t icg_global_pll : 1; + uint32_t ana_i2c_iso_en : 1; + uint32_t ana_i2c_retention: 1; + uint32_t ana_xpd_bb_i2c : 1; + uint32_t ana_xpd_bbpll_i2c: 1; + uint32_t ana_xpd_bbpll : 1; + uint32_t ana_xpd_xtal : 1; + }; + uint32_t val; + } clk_state0; -/** Type of clk_state1 register - * need_des - */ -typedef union { - struct { - /** icg_func_en_state : RO; bitpos: [31:0]; default: 4294967295; - * need_des - */ - uint32_t icg_func_en_state:32; - }; - uint32_t val; -} pmu_clk_state1_reg_t; + uint32_t clk_state1; + uint32_t clk_state2; -/** Type of clk_state2 register - * need_des - */ -typedef union { - struct { - /** icg_apb_en_state : RO; bitpos: [31:0]; default: 4294967295; - * need_des - */ - uint32_t icg_apb_en_state:32; - }; - uint32_t val; -} pmu_clk_state2_reg_t; + union { + struct { + uint32_t reserved0 : 31; + uint32_t stable_vdd_spi_pwr_drv: 1; + }; + uint32_t val; + } vdd_spi_status; -/** Type of vdd_spi_status register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** stable_vdd_spi_pwr_drv : RO; bitpos: [31]; default: 0; - * need_des - */ - uint32_t stable_vdd_spi_pwr_drv:1; - }; - uint32_t val; -} pmu_vdd_spi_status_reg_t; + uint32_t reserved[150]; - -typedef struct pmu_dev_t { - volatile pmu_hp_active_dig_power_reg_t hp_active_dig_power; - volatile pmu_hp_active_icg_hp_func_reg_t hp_active_icg_hp_func; - volatile pmu_hp_active_icg_hp_apb_reg_t hp_active_icg_hp_apb; - volatile pmu_hp_active_icg_modem_reg_t hp_active_icg_modem; - volatile pmu_hp_active_hp_sys_cntl_reg_t hp_active_hp_sys_cntl; - volatile pmu_hp_active_hp_ck_power_reg_t hp_active_hp_ck_power; - volatile pmu_hp_active_bias_reg_t hp_active_bias; - volatile pmu_hp_active_backup_reg_t hp_active_backup; - volatile pmu_hp_active_backup_clk_reg_t hp_active_backup_clk; - volatile pmu_hp_active_sysclk_reg_t hp_active_sysclk; - volatile pmu_hp_active_hp_regulator0_reg_t hp_active_hp_regulator0; - volatile pmu_hp_active_hp_regulator1_reg_t hp_active_hp_regulator1; - volatile pmu_hp_active_xtal_reg_t hp_active_xtal; - volatile pmu_hp_modem_dig_power_reg_t hp_modem_dig_power; - volatile pmu_hp_modem_icg_hp_func_reg_t hp_modem_icg_hp_func; - volatile pmu_hp_modem_icg_hp_apb_reg_t hp_modem_icg_hp_apb; - volatile pmu_hp_modem_icg_modem_reg_t hp_modem_icg_modem; - volatile pmu_hp_modem_hp_sys_cntl_reg_t hp_modem_hp_sys_cntl; - volatile pmu_hp_modem_hp_ck_power_reg_t hp_modem_hp_ck_power; - volatile pmu_hp_modem_bias_reg_t hp_modem_bias; - volatile pmu_hp_modem_backup_reg_t hp_modem_backup; - volatile pmu_hp_modem_backup_clk_reg_t hp_modem_backup_clk; - volatile pmu_hp_modem_sysclk_reg_t hp_modem_sysclk; - volatile pmu_hp_modem_hp_regulator0_reg_t hp_modem_hp_regulator0; - volatile pmu_hp_modem_hp_regulator1_reg_t hp_modem_hp_regulator1; - volatile pmu_hp_modem_xtal_reg_t hp_modem_xtal; - volatile pmu_hp_sleep_dig_power_reg_t hp_sleep_dig_power; - volatile pmu_hp_sleep_icg_hp_func_reg_t hp_sleep_icg_hp_func; - volatile pmu_hp_sleep_icg_hp_apb_reg_t hp_sleep_icg_hp_apb; - volatile pmu_hp_sleep_icg_modem_reg_t hp_sleep_icg_modem; - volatile pmu_hp_sleep_hp_sys_cntl_reg_t hp_sleep_hp_sys_cntl; - volatile pmu_hp_sleep_hp_ck_power_reg_t hp_sleep_hp_ck_power; - volatile pmu_hp_sleep_bias_reg_t hp_sleep_bias; - volatile pmu_hp_sleep_backup_reg_t hp_sleep_backup; - volatile pmu_hp_sleep_backup_clk_reg_t hp_sleep_backup_clk; - volatile pmu_hp_sleep_sysclk_reg_t hp_sleep_sysclk; - volatile pmu_hp_sleep_hp_regulator0_reg_t hp_sleep_hp_regulator0; - volatile pmu_hp_sleep_hp_regulator1_reg_t hp_sleep_hp_regulator1; - volatile pmu_hp_sleep_xtal_reg_t hp_sleep_xtal; - volatile pmu_hp_sleep_lp_regulator0_reg_t hp_sleep_lp_regulator0; - volatile pmu_hp_sleep_lp_regulator1_reg_t hp_sleep_lp_regulator1; - volatile pmu_hp_sleep_lp_dcdc_reserve_reg_t hp_sleep_lp_dcdc_reserve; - volatile pmu_hp_sleep_lp_dig_power_reg_t hp_sleep_lp_dig_power; - volatile pmu_hp_sleep_lp_ck_power_reg_t hp_sleep_lp_ck_power; - volatile pmu_lp_sleep_lp_bias_reserve_reg_t lp_sleep_lp_bias_reserve; - volatile pmu_lp_sleep_lp_regulator0_reg_t lp_sleep_lp_regulator0; - volatile pmu_lp_sleep_lp_regulator1_reg_t lp_sleep_lp_regulator1; - volatile pmu_lp_sleep_xtal_reg_t lp_sleep_xtal; - volatile pmu_lp_sleep_lp_dig_power_reg_t lp_sleep_lp_dig_power; - volatile pmu_lp_sleep_lp_ck_power_reg_t lp_sleep_lp_ck_power; - volatile pmu_lp_sleep_bias_reg_t lp_sleep_bias; - volatile pmu_imm_hp_ck_power_reg_t imm_hp_ck_power; - volatile pmu_imm_sleep_sysclk_reg_t imm_sleep_sysclk; - volatile pmu_imm_hp_func_icg_reg_t imm_hp_func_icg; - volatile pmu_imm_hp_apb_icg_reg_t imm_hp_apb_icg; - volatile pmu_imm_modem_icg_reg_t imm_modem_icg; - volatile pmu_imm_lp_icg_reg_t imm_lp_icg; - volatile pmu_imm_pad_hold_all_reg_t imm_pad_hold_all; - volatile pmu_imm_i2c_iso_reg_t imm_i2c_iso; - volatile pmu_power_wait_timer0_reg_t power_wait_timer0; - volatile pmu_power_wait_timer1_reg_t power_wait_timer1; - volatile pmu_power_pd_top_cntl_reg_t power_pd_top_cntl; - volatile pmu_power_pd_hpaon_cntl_reg_t power_pd_hpaon_cntl; - volatile pmu_power_pd_hpcpu_cntl_reg_t power_pd_hpcpu_cntl; - volatile pmu_power_pd_hpperi_reserve_reg_t power_pd_hpperi_reserve; - volatile pmu_power_pd_hpwifi_cntl_reg_t power_pd_hpwifi_cntl; - volatile pmu_power_pd_lpperi_cntl_reg_t power_pd_lpperi_cntl; - volatile pmu_power_pd_mem_cntl_reg_t power_pd_mem_cntl; - volatile pmu_power_pd_mem_mask_reg_t power_pd_mem_mask; - volatile pmu_power_hp_pad_reg_t power_hp_pad; - volatile pmu_power_vdd_spi_cntl_reg_t power_vdd_spi_cntl; - volatile pmu_power_ck_wait_cntl_reg_t power_ck_wait_cntl; - volatile pmu_slp_wakeup_cntl0_reg_t slp_wakeup_cntl0; - volatile pmu_slp_wakeup_cntl1_reg_t slp_wakeup_cntl1; - volatile pmu_slp_wakeup_cntl2_reg_t slp_wakeup_cntl2; - volatile pmu_slp_wakeup_cntl3_reg_t slp_wakeup_cntl3; - volatile pmu_slp_wakeup_cntl4_reg_t slp_wakeup_cntl4; - volatile pmu_slp_wakeup_cntl5_reg_t slp_wakeup_cntl5; - volatile pmu_slp_wakeup_cntl6_reg_t slp_wakeup_cntl6; - volatile pmu_slp_wakeup_cntl7_reg_t slp_wakeup_cntl7; - volatile pmu_slp_wakeup_status0_reg_t slp_wakeup_status0; - volatile pmu_slp_wakeup_status1_reg_t slp_wakeup_status1; - volatile pmu_hp_ck_poweron_reg_t hp_ck_poweron; - volatile pmu_hp_ck_cntl_reg_t hp_ck_cntl; - volatile pmu_por_status_reg_t por_status; - volatile pmu_rf_pwc_reg_t rf_pwc; - volatile pmu_backup_cfg_reg_t backup_cfg; - volatile pmu_int_raw_reg_t int_raw; - volatile pmu_hp_int_st_reg_t hp_int_st; - volatile pmu_hp_int_ena_reg_t hp_int_ena; - volatile pmu_hp_int_clr_reg_t hp_int_clr; - volatile pmu_lp_int_raw_reg_t lp_int_raw; - volatile pmu_lp_int_st_reg_t lp_int_st; - volatile pmu_lp_int_ena_reg_t lp_int_ena; - volatile pmu_lp_int_clr_reg_t lp_int_clr; - volatile pmu_lp_cpu_pwr0_reg_t lp_cpu_pwr0; - volatile pmu_lp_cpu_pwr1_reg_t lp_cpu_pwr1; - volatile pmu_hp_lp_cpu_comm_reg_t hp_lp_cpu_comm; - volatile pmu_hp_regulator_cfg_reg_t hp_regulator_cfg; - volatile pmu_main_state_reg_t main_state; - volatile pmu_pwr_state_reg_t pwr_state; - volatile pmu_clk_state0_reg_t clk_state0; - volatile pmu_clk_state1_reg_t clk_state1; - volatile pmu_clk_state2_reg_t clk_state2; - volatile pmu_vdd_spi_status_reg_t vdd_spi_status; - uint32_t reserved_1a4[150]; - volatile pmu_date_reg_t date; + union { + struct { + uint32_t pmu_date: 31; + uint32_t clk_en : 1; + }; + uint32_t val; + } date; } pmu_dev_t; extern pmu_dev_t PMU; #ifndef __cplusplus _Static_assert(sizeof(pmu_dev_t) == 0x400, "Invalid size of pmu_dev_t structure"); + +_Static_assert(offsetof(pmu_dev_t, reserved) == (PMU_VDD_SPI_STATUS_REG - DR_REG_PMU_BASE) + 4, "Invalid size of pmu_dev_t structure"); + #endif #ifdef __cplusplus From 6c1f58f1357bad3ceb7fa8147395bc953dd5ada9 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Thu, 12 Jan 2023 18:00:58 +0800 Subject: [PATCH 03/16] pmu: add hal layer codes for esp32c6 --- components/hal/CMakeLists.txt | 5 +- components/hal/esp32c6/include/hal/pmu_hal.h | 45 ++ components/hal/esp32c6/include/hal/pmu_ll.h | 666 +++++++++++++++++++ components/hal/esp32c6/pmu_hal.c | 70 ++ components/hal/include/hal/pmu_types.h | 166 +++++ 5 files changed, 951 insertions(+), 1 deletion(-) create mode 100644 components/hal/esp32c6/include/hal/pmu_hal.h create mode 100644 components/hal/esp32c6/include/hal/pmu_ll.h create mode 100644 components/hal/esp32c6/pmu_hal.c create mode 100644 components/hal/include/hal/pmu_types.h diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index 095233343e..4ed06a0139 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -138,6 +138,10 @@ if(NOT BOOTLOADER_BUILD) list(APPEND srcs "sdio_slave_hal.c") endif() + if(CONFIG_SOC_PMU_SUPPORTED) + list(APPEND srcs "${target}/pmu_hal.c") + endif() + if(${target} STREQUAL "esp32") list(APPEND srcs "touch_sensor_hal.c" @@ -198,7 +202,6 @@ if(NOT BOOTLOADER_BUILD) if(${target} STREQUAL "esp32c6") list(APPEND srcs "spi_flash_hal_gpspi.c" - "esp32c6/rtc_cntl_hal.c" "hmac_hal.c" "ds_hal.c") diff --git a/components/hal/esp32c6/include/hal/pmu_hal.h b/components/hal/esp32c6/include/hal/pmu_hal.h new file mode 100644 index 0000000000..f4ca27e9e8 --- /dev/null +++ b/components/hal/esp32c6/include/hal/pmu_hal.h @@ -0,0 +1,45 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The HAL layer for PMU + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "soc/soc_caps.h" +#include "hal/pmu_ll.h" +#include "hal/pmu_types.h" + +typedef struct { + pmu_dev_t *dev; +} pmu_hal_context_t; + +void pmu_hal_hp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle); + +uint32_t pmu_hal_hp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal); + +void pmu_hal_lp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle); + +uint32_t pmu_hal_lp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal); + +void pmu_hal_hp_set_sleep_active_backup_enable(pmu_hal_context_t *hal); + +void pmu_hal_hp_set_sleep_active_backup_disable(pmu_hal_context_t *hal); + +void pmu_hal_hp_set_sleep_modem_backup_enable(pmu_hal_context_t *hal); + +void pmu_hal_hp_set_sleep_modem_backup_disable(pmu_hal_context_t *hal); + +void pmu_hal_hp_set_modem_active_backup_enable(pmu_hal_context_t *hal); + +void pmu_hal_hp_set_modem_active_backup_disable(pmu_hal_context_t *hal); + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c6/include/hal/pmu_ll.h b/components/hal/esp32c6/include/hal/pmu_ll.h new file mode 100644 index 0000000000..6e74944f48 --- /dev/null +++ b/components/hal/esp32c6/include/hal/pmu_ll.h @@ -0,0 +1,666 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for ESP32-C6 PMU register operations + +#pragma once + +#include +#include +#include "soc/soc.h" +#include "esp_attr.h" +#include "hal/assert.h" +#include "soc/pmu_struct.h" +#include "hal/pmu_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Set the power domain that needs to be powered down in the digital power + * + * @param hw Beginning address of the peripheral registers. + * @param mode The pmu mode + * @param flag Digital power domain flag + * + * @return None + */ +FORCE_INLINE_ATTR void pmu_ll_hp_set_dig_power(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t flag) +{ + hw->hp_sys[mode].dig_power.val = flag; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_func(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t icg_func) +{ + hw->hp_sys[mode].icg_func = icg_func; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_apb(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t bitmap) +{ + hw->hp_sys[mode].icg_apb = bitmap; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_modem(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t code) +{ + hw->hp_sys[mode].icg_modem.code = code; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_uart_wakeup_enable(pmu_dev_t *hw, pmu_hp_mode_t mode, bool wakeup_en) +{ + hw->hp_sys[mode].syscntl.uart_wakeup_en = wakeup_en; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_hold_all_lp_pad(pmu_dev_t *hw, pmu_hp_mode_t mode, bool hold_all) +{ + hw->hp_sys[mode].syscntl.lp_pad_hold_all = hold_all; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_hold_all_hp_pad(pmu_dev_t *hw, pmu_hp_mode_t mode, bool hold_all) +{ + hw->hp_sys[mode].syscntl.hp_pad_hold_all = hold_all; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_dig_pad_slp_sel(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_sel) +{ + hw->hp_sys[mode].syscntl.dig_pad_slp_sel = slp_sel; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_pause_watchdog(pmu_dev_t *hw, pmu_hp_mode_t mode, bool pause_wdt) +{ + hw->hp_sys[mode].syscntl.dig_pause_wdt = pause_wdt; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_cpu_stall(pmu_dev_t *hw, pmu_hp_mode_t mode, bool cpu_stall) +{ + hw->hp_sys[mode].syscntl.dig_cpu_stall = cpu_stall; +} + +/** + * @brief Set the power domain that needs to be powered down in the clock power + * + * @param hw Beginning address of the peripheral registers. + * @param mode The pmu mode + * @param flag Clock power domain flag + * + * @return None + */ +FORCE_INLINE_ATTR void pmu_ll_hp_set_clk_power(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t xpd_flag) +{ + hw->hp_sys[mode].clk_power.val = xpd_flag; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_xtal_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool xpd_xtal) +{ + hw->hp_sys[mode].xtal.xpd_xtal = xpd_xtal; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_bias_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool xpd_bias) +{ + hw->hp_sys[mode].bias.xpd_bias = xpd_bias; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_dbg_atten(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t value) +{ + hw->hp_sys[mode].bias.dbg_atten = value; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_current_power_off(pmu_dev_t *hw, pmu_hp_mode_t mode, bool off) +{ + hw->hp_sys[mode].bias.pd_cur = off; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_bias_sleep_enable(pmu_dev_t *hw, pmu_hp_mode_t mode, bool en) +{ + hw->hp_sys[mode].bias.bias_sleep = en; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_retention_param(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t param) +{ + hw->hp_sys[mode].backup.val = param; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_to_active_backup_enable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_ACTIVE].backup.hp_sleep2active_backup_en = 1; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_to_active_backup_disable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_ACTIVE].backup.hp_sleep2active_backup_en = 0; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_modem_to_active_backup_enable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_ACTIVE].backup.hp_modem2active_backup_en = 1; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_modem_to_active_backup_disable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_ACTIVE].backup.hp_modem2active_backup_en = 0; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_to_modem_backup_enable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_MODEM].backup.hp_sleep2modem_backup_en = 1; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_to_modem_backup_disable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_MODEM].backup.hp_sleep2modem_backup_en = 0; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_active_to_sleep_backup_enable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_SLEEP].backup.hp_active2sleep_backup_en = 1; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_active_to_sleep_backup_disable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_SLEEP].backup.hp_active2sleep_backup_en = 0; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_modem_to_sleep_backup_enable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_SLEEP].backup.hp_modem2sleep_backup_en = 1; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_modem_to_sleep_backup_disable(pmu_dev_t *hw) +{ + hw->hp_sys[PMU_MODE_HP_SLEEP].backup.hp_modem2sleep_backup_en = 0; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_backup_icg_func(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t icg_func) +{ + hw->hp_sys[mode].backup_clk = icg_func; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_sysclk_nodiv(pmu_dev_t *hw, pmu_hp_mode_t mode, bool sysclk_nodiv) +{ + hw->hp_sys[mode].sysclk.dig_sysclk_nodiv = sysclk_nodiv; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_sysclk_enable(pmu_dev_t *hw, pmu_hp_mode_t mode, bool icg_sysclk_en) +{ + hw->hp_sys[mode].sysclk.icg_sysclk_en = icg_sysclk_en; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_sysclk_slp_sel(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_sel) +{ + hw->hp_sys[mode].sysclk.sysclk_slp_sel = slp_sel; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_icg_sysclk_slp_sel(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_sel) +{ + hw->hp_sys[mode].sysclk.icg_slp_sel = slp_sel; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_dig_sysclk(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t sysclk_sel) +{ + hw->hp_sys[mode].sysclk.dig_sysclk_sel = sysclk_sel; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_logic_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_xpd) +{ + hw->hp_sys[mode].regulator0.slp_logic_xpd = slp_xpd; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_memory_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool slp_xpd) +{ + hw->hp_sys[mode].regulator0.slp_mem_xpd = slp_xpd; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_xpd(pmu_dev_t *hw, pmu_hp_mode_t mode, bool xpd) +{ + hw->hp_sys[mode].regulator0.xpd = xpd; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_logic_dbias(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t slp_dbias) +{ + hw->hp_sys[mode].regulator0.slp_logic_dbias = slp_dbias; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_sleep_memory_dbias(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t slp_dbias) +{ + hw->hp_sys[mode].regulator0.slp_mem_dbias = slp_dbias; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_dbias(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t dbias) +{ + hw->hp_sys[mode].regulator0.dbias = dbias; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_regulator_driver_bar(pmu_dev_t *hw, pmu_hp_mode_t mode, uint32_t drv_b) +{ + hw->hp_sys[mode].regulator1.drv_b = drv_b; +} + + +FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_slp_xpd(pmu_dev_t *hw, pmu_lp_mode_t mode, bool slp_xpd) +{ + hw->lp_sys[mode].regulator0.slp_xpd = slp_xpd; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_xpd(pmu_dev_t *hw, pmu_lp_mode_t mode, bool xpd) +{ + hw->lp_sys[mode].regulator0.xpd = xpd; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_sleep_dbias(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t slp_dbias) +{ + hw->lp_sys[mode].regulator0.slp_dbias = slp_dbias; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_dbias(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t dbias) +{ + hw->lp_sys[mode].regulator0.dbias = dbias; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_regulator_driver_bar(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t drv_b) +{ + hw->lp_sys[mode].regulator1.drv_b = drv_b; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_xtal_xpd(pmu_dev_t *hw, pmu_lp_mode_t mode, bool xpd_xtal) +{ + HAL_ASSERT(mode == PMU_MODE_LP_SLEEP); + hw->lp_sys[mode].xtal.xpd_xtal = xpd_xtal; +} + + +FORCE_INLINE_ATTR void pmu_ll_lp_set_dig_power(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t flag) +{ + hw->lp_sys[mode].dig_power.val = flag; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_clk_power(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t xpd_flag) +{ + hw->lp_sys[mode].clk_power.val = xpd_flag; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_clk_power(pmu_dev_t *hw, pmu_lp_mode_t mode) +{ + return hw->lp_sys[mode].clk_power.val; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_bias_xpd(pmu_dev_t *hw, pmu_lp_mode_t mode, bool xpd_bias) +{ + HAL_ASSERT(mode == PMU_MODE_LP_SLEEP); + hw->lp_sys[mode].bias.xpd_bias = xpd_bias; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_dbg_atten(pmu_dev_t *hw, pmu_lp_mode_t mode, uint32_t value) +{ + HAL_ASSERT(mode == PMU_MODE_LP_SLEEP); + hw->lp_sys[mode].bias.dbg_atten = value; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_current_power_off(pmu_dev_t *hw, pmu_lp_mode_t mode, bool off) +{ + HAL_ASSERT(mode == PMU_MODE_LP_SLEEP); + hw->lp_sys[mode].bias.pd_cur = off; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_bias_sleep_enable(pmu_dev_t *hw, pmu_lp_mode_t mode, bool en) +{ + HAL_ASSERT(mode == PMU_MODE_LP_SLEEP); + hw->lp_sys[mode].bias.bias_sleep = en; +} + + +/****/ +FORCE_INLINE_ATTR void pmu_ll_imm_set_clk_power(pmu_dev_t *hw, uint32_t flag) +{ + hw->imm.clk_power.val = flag; +} + +FORCE_INLINE_ATTR void pmu_ll_imm_set_icg_slp_sel(pmu_dev_t *hw, bool slp_sel) +{ + if (slp_sel) { + hw->imm.sleep_sysclk.tie_high_icg_slp_sel = 1; + } else { + hw->imm.sleep_sysclk.tie_low_icg_slp_sel = 1; + } +} + +FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_sysclk_sel(pmu_dev_t *hw, bool update) +{ + hw->imm.sleep_sysclk.update_dig_sysclk_sel = update; +} + +FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_icg_switch(pmu_dev_t *hw, bool update) +{ + hw->imm.sleep_sysclk.update_dig_icg_switch = update; +} + +FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_icg_func(pmu_dev_t *hw, bool icg_func_update) +{ + hw->imm.hp_func_icg.update_dig_icg_func_en = icg_func_update; +} + +FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_icg_apb(pmu_dev_t *hw, bool icg_apb_update) +{ + hw->imm.hp_apb_icg.update_dig_icg_apb_en = icg_apb_update; +} + +FORCE_INLINE_ATTR void pmu_ll_imm_update_dig_icg_modem_code(pmu_dev_t *hw, bool icg_modem_update) +{ + hw->imm.modem_icg.update_dig_icg_modem_en = icg_modem_update; +} + +FORCE_INLINE_ATTR void pmu_ll_imm_set_lp_rootclk_sel(pmu_dev_t *hw, bool rootclk_sel) +{ + if (rootclk_sel) { + hw->imm.lp_icg.tie_high_lp_rootclk_sel = 1; + } else { + hw->imm.lp_icg.tie_low_lp_rootclk_sel = 1; + } +} + +FORCE_INLINE_ATTR void pmu_ll_imm_set_hp_pad_hold_all(pmu_dev_t *hw, bool hold_all) +{ + if (hold_all) { + hw->imm.pad_hold_all.tie_high_hp_pad_hold_all = 1; + } else { + hw->imm.pad_hold_all.tie_low_hp_pad_hold_all = 1; + } +} + +FORCE_INLINE_ATTR void pmu_ll_imm_set_lp_pad_hold_all(pmu_dev_t *hw, bool hold_all) +{ + if (hold_all) { + hw->imm.pad_hold_all.tie_high_lp_pad_hold_all = 1; + } else { + hw->imm.pad_hold_all.tie_low_lp_pad_hold_all = 1; + } +} + +/*** */ +FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_reset(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool rst) +{ + hw->power.hp_pd[domain].force_reset = rst; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_isolate(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool iso) +{ + hw->power.hp_pd[domain].force_iso = iso; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_power_up(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool fpu) +{ + hw->power.hp_pd[domain].force_pu = fpu; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_no_reset(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool no_rst) +{ + hw->power.hp_pd[domain].force_no_reset = no_rst; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_no_isolate(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool no_iso) +{ + hw->power.hp_pd[domain].force_no_iso = no_iso; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_power_force_power_down(pmu_dev_t *hw, pmu_hp_power_domain_t domain, bool fpd) +{ + hw->power.hp_pd[domain].force_pd = fpd; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_reset(pmu_dev_t *hw, bool rst) +{ + hw->power.lp_peri.force_reset = rst; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_isolate(pmu_dev_t *hw, bool iso) +{ + hw->power.lp_peri.force_iso = iso; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_power_up(pmu_dev_t *hw, bool fpu) +{ + hw->power.lp_peri.force_pu = fpu; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_no_reset(pmu_dev_t *hw, bool no_rst) +{ + hw->power.lp_peri.force_no_reset = no_rst; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_no_isolate(pmu_dev_t *hw, bool no_iso) +{ + hw->power.lp_peri.force_no_iso = no_iso; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_power_force_power_down(pmu_dev_t *hw, bool fpd) +{ + hw->power.lp_peri.force_pd = fpd; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_isolate(pmu_dev_t *hw, uint32_t iso) +{ + hw->power.mem_cntl.force_hp_mem_iso = iso; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_power_down(pmu_dev_t *hw, uint32_t fpd) +{ + hw->power.mem_cntl.force_hp_mem_pd = fpd; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_no_isolate(pmu_dev_t *hw, uint32_t no_iso) +{ + hw->power.mem_cntl.force_hp_mem_no_iso = no_iso; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_memory_power_up(pmu_dev_t *hw, uint32_t fpu) +{ + hw->power.mem_cntl.force_hp_mem_pu = fpu; +} + +/*** */ +FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_enable(pmu_dev_t *hw) +{ + hw->wakeup.cntl0.sleep_req = 1; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_reject_enable(pmu_dev_t *hw, uint32_t reject) +{ + hw->wakeup.cntl1.sleep_reject_ena = reject; + hw->wakeup.cntl1.slp_reject_en = 1; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_reject_disable(pmu_dev_t *hw) +{ + hw->wakeup.cntl1.slp_reject_en = 0; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_wakeup_enable(pmu_dev_t *hw, uint32_t wakeup) +{ + hw->wakeup.cntl2 = wakeup; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_sleep_protect_mode(pmu_dev_t *hw, int mode) +{ + hw->wakeup.cntl3.sleep_prt_sel = mode; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_min_sleep_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle) +{ + hw->wakeup.cntl3.hp_min_slp_val = slow_clk_cycle; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_clear_reject_cause(pmu_dev_t *hw) +{ + hw->wakeup.cntl4.slp_reject_cause_clr = 1; +} + +FORCE_INLINE_ATTR bool pmu_ll_hp_is_sleep_wakeup(pmu_dev_t *hw) +{ + return (hw->hp_ext.int_raw.wakeup == 1); +} + +FORCE_INLINE_ATTR bool pmu_ll_hp_is_sleep_reject(pmu_dev_t *hw) +{ + return (hw->hp_ext.int_raw.reject == 1); +} + +FORCE_INLINE_ATTR void pmu_ll_hp_clear_wakeup_intr_status(pmu_dev_t *hw) +{ + hw->hp_ext.int_clr.wakeup = 1; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_clear_reject_intr_status(pmu_dev_t *hw) +{ + hw->hp_ext.int_clr.reject = 1; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_wakeup_cause(pmu_dev_t *hw) +{ + return hw->wakeup.status0; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_reject_cause(pmu_dev_t *hw) +{ + return hw->wakeup.status1; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_min_sleep_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle) +{ + hw->wakeup.cntl3.lp_min_slp_val = slow_clk_cycle; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_modify_icg_cntl_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->hp_ext.clk_cntl.modify_icg_cntl_wait = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_modify_icg_cntl_wait_cycle(pmu_dev_t *hw) +{ + return hw->hp_ext.clk_cntl.modify_icg_cntl_wait; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_switch_icg_cntl_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->hp_ext.clk_cntl.switch_icg_cntl_wait = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_switch_icg_cntl_wait_cycle(pmu_dev_t *hw) +{ + return hw->hp_ext.clk_cntl.switch_icg_cntl_wait; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_digital_power_down_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.wait_timer0.powerdown_timer = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_digital_power_down_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.wait_timer0.powerdown_timer; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_digital_power_down_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.wait_timer1.powerdown_timer = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_digital_power_down_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.wait_timer1.powerdown_timer; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_analog_wait_target_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle) +{ + hw->wakeup.cntl5.lp_ana_wait_target = slow_clk_cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_analog_wait_target_cycle(pmu_dev_t *hw) +{ + return hw->wakeup.cntl5.lp_ana_wait_target; +} + +FORCE_INLINE_ATTR void pmu_ll_set_modem_wait_target_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->wakeup.cntl5.modem_wait_target = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_get_modem_wait_target_cycle(pmu_dev_t *hw) +{ + return hw->wakeup.cntl5.modem_wait_target; +} + +FORCE_INLINE_ATTR void pmu_ll_set_xtal_stable_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.clk_wait.wait_xtal_stable = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_get_xtal_stable_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.clk_wait.wait_xtal_stable; +} + +FORCE_INLINE_ATTR void pmu_ll_set_pll_stable_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.clk_wait.wait_pll_stable = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_get_pll_stable_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.clk_wait.wait_pll_stable; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_digital_power_supply_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.wait_timer1.wait_timer = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_digital_power_supply_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.wait_timer1.wait_timer; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_set_digital_power_up_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.wait_timer1.powerup_timer = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_digital_power_up_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.wait_timer1.powerup_timer; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_analog_wait_target_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->wakeup.cntl7.ana_wait_target = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_analog_wait_target_cycle(pmu_dev_t *hw) +{ + return hw->wakeup.cntl7.ana_wait_target; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_digital_power_supply_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.wait_timer0.wait_timer = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_digital_power_supply_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.wait_timer0.wait_timer; +} + +FORCE_INLINE_ATTR void pmu_ll_hp_set_digital_power_up_wait_cycle(pmu_dev_t *hw, uint32_t cycle) +{ + hw->power.wait_timer0.powerup_timer = cycle; +} + +FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_digital_power_up_wait_cycle(pmu_dev_t *hw) +{ + return hw->power.wait_timer0.powerup_timer; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c6/pmu_hal.c b/components/hal/esp32c6/pmu_hal.c new file mode 100644 index 0000000000..4997eacce6 --- /dev/null +++ b/components/hal/esp32c6/pmu_hal.c @@ -0,0 +1,70 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The HAL layer for PMU (ESP32-C6 specific part) + +#include "soc/soc.h" +#include "esp_attr.h" +#include "hal/pmu_hal.h" +#include "hal/pmu_types.h" + +void IRAM_ATTR pmu_hal_hp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle) +{ + pmu_ll_hp_set_digital_power_supply_wait_cycle(hal->dev, power_supply_wait_cycle); + pmu_ll_hp_set_digital_power_up_wait_cycle(hal->dev, power_up_wait_cycle); +} + +uint32_t IRAM_ATTR pmu_hal_hp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal) +{ + uint32_t power_supply_wait_cycle = pmu_ll_hp_get_digital_power_supply_wait_cycle(hal->dev); + uint32_t power_up_wait_cycle = pmu_ll_hp_get_digital_power_up_wait_cycle(hal->dev); + return power_supply_wait_cycle + power_up_wait_cycle; +} + +void IRAM_ATTR pmu_hal_lp_set_digital_power_up_wait_cycle(pmu_hal_context_t *hal, uint32_t power_supply_wait_cycle, uint32_t power_up_wait_cycle) +{ + pmu_ll_lp_set_digital_power_supply_wait_cycle(hal->dev, power_supply_wait_cycle); + pmu_ll_lp_set_digital_power_up_wait_cycle(hal->dev, power_up_wait_cycle); +} + +uint32_t IRAM_ATTR pmu_hal_lp_get_digital_power_up_wait_cycle(pmu_hal_context_t *hal) +{ + uint32_t power_supply_wait_cycle = pmu_ll_lp_get_digital_power_supply_wait_cycle(hal->dev); + uint32_t power_up_wait_cycle = pmu_ll_lp_get_digital_power_up_wait_cycle(hal->dev); + return power_supply_wait_cycle + power_up_wait_cycle; +} + +void pmu_hal_hp_set_sleep_active_backup_enable(pmu_hal_context_t *hal) +{ + pmu_ll_hp_set_active_to_sleep_backup_enable(hal->dev); + pmu_ll_hp_set_sleep_to_active_backup_enable(hal->dev); +} + +void pmu_hal_hp_set_sleep_active_backup_disable(pmu_hal_context_t *hal) +{ + pmu_ll_hp_set_sleep_to_active_backup_disable(hal->dev); + pmu_ll_hp_set_active_to_sleep_backup_disable(hal->dev); +} + +void pmu_hal_hp_set_sleep_modem_backup_enable(pmu_hal_context_t *hal) +{ + pmu_ll_hp_set_sleep_to_modem_backup_enable(hal->dev); +} + +void pmu_hal_hp_set_sleep_modem_backup_disable(pmu_hal_context_t *hal) +{ + pmu_ll_hp_set_sleep_to_modem_backup_disable(hal->dev); +} + +void pmu_hal_hp_set_modem_active_backup_enable(pmu_hal_context_t *hal) +{ + pmu_ll_hp_set_modem_to_active_backup_enable(hal->dev); +} + +void pmu_hal_hp_set_modem_active_backup_disable(pmu_hal_context_t *hal) +{ + pmu_ll_hp_set_modem_to_active_backup_disable(hal->dev); +} diff --git a/components/hal/include/hal/pmu_types.h b/components/hal/include/hal/pmu_types.h new file mode 100644 index 0000000000..75aacbd101 --- /dev/null +++ b/components/hal/include/hal/pmu_types.h @@ -0,0 +1,166 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** + * @brief PMU modes of HP system + */ +typedef enum { + PMU_MODE_HP_ACTIVE = 0, /*!< PMU in HP_ACTIVE mode */ + PMU_MODE_HP_MODEM, /*!< PMU in HP_MODEM mode */ + PMU_MODE_HP_SLEEP, /*!< PMU in HP_SLEEP mode */ + PMU_MODE_HP_MAX, +} pmu_hp_mode_t; + +/** + * @brief PMU modes of LP system + */ +typedef enum { + PMU_MODE_LP_ACTIVE = 0, /*!< PMU in LP_ACTIVE mode */ + PMU_MODE_LP_SLEEP, /*!< PMU in LP_SLEEP mode */ + PMU_MODE_LP_MAX, +} pmu_lp_mode_t; + +typedef enum { + PMU_HP_PD_TOP = 0, /* Power domain of digital top */ + PMU_HP_PD_AON, /* Power domain of always-on */ + PMU_HP_PD_CPU, /* Power domain of HP CPU */ + PMU_HP_PD_RESERVED, /* Reserved power domain*/ + PMU_HP_PD_WIFI, /* Power domain of WIFI */ + PMU_HP_PD_MAX +} pmu_hp_power_domain_t; + + +/* Software configuration instance type from pmu_struct.h */ +typedef union { + struct { + uint32_t reserved0 : 21; + uint32_t vdd_spi_pd_en: 1; + uint32_t mem_dslp : 1; + uint32_t mem_pd_en : 4; + uint32_t wifi_pd_en : 1; + uint32_t reserved1 : 1; + uint32_t cpu_pd_en : 1; + uint32_t aon_pd_en : 1; + uint32_t top_pd_en : 1; + }; + struct { + uint32_t reserved2 : 26; + uint32_t i2c_iso_en : 1; + uint32_t i2c_retention: 1; + uint32_t xpd_bb_i2c : 1; + uint32_t xpd_bbpll_i2c: 1; + uint32_t xpd_bbpll : 1; + uint32_t reserved3 : 1; + }; + struct { + uint32_t reserved4 : 31; + uint32_t xpd_xtal : 1; + }; + uint32_t val; +} pmu_hp_power_t; + +typedef union { + struct { + uint32_t reserved0 : 30; + uint32_t mem_dslp : 1; + uint32_t peri_pd_en: 1; + }; + struct { + uint32_t reserved1 : 28; + uint32_t xpd_xtal32k: 1; + uint32_t xpd_rc32k : 1; + uint32_t xpd_fosc : 1; + uint32_t pd_osc : 1; + }; + struct { + uint32_t reserved2 : 31; + uint32_t xpd_xtal : 1; + }; + uint32_t val; +} pmu_lp_power_t; + +typedef struct { + struct { + uint32_t reserved0 : 25; + uint32_t xpd_bias : 1; + uint32_t dbg_atten : 4; + uint32_t pd_cur : 1; + uint32_t bias_sleep: 1; + }; + struct { + uint32_t reserved1 : 16; + uint32_t slp_mem_xpd : 1; + uint32_t slp_logic_xpd : 1; + uint32_t xpd : 1; + uint32_t slp_mem_dbias : 4; + uint32_t slp_logic_dbias: 4; + uint32_t dbias : 5; + }; + struct { + uint32_t reserved2: 8; + uint32_t drv_b : 24; + }; +} pmu_hp_analog_t; + +typedef struct { + struct { + uint32_t reserved0 : 25; + uint32_t xpd_bias : 1; + uint32_t dbg_atten : 4; + uint32_t pd_cur : 1; + uint32_t bias_sleep: 1; + }; + struct { + uint32_t reserved1: 21; + uint32_t slp_xpd : 1; + uint32_t xpd : 1; + uint32_t slp_dbias: 4; + uint32_t dbias : 5; + }; + struct { + uint32_t reserved2: 28; + uint32_t drv_b : 4; + }; +} pmu_lp_analog_t; + +typedef struct { + uint32_t modem_wakeup_wait_cycle; + uint16_t analog_wait_target_cycle; + uint16_t digital_power_down_wait_cycle; + uint16_t digital_power_supply_wait_cycle; + uint16_t digital_power_up_wait_cycle; + uint16_t pll_stable_wait_cycle; + uint8_t modify_icg_cntl_wait_cycle; + uint8_t switch_icg_cntl_wait_cycle; + uint8_t min_slp_slow_clk_cycle; +} pmu_hp_param_t; + +typedef struct { + uint16_t digital_power_supply_wait_cycle; + uint8_t min_slp_slow_clk_cycle; + uint8_t analog_wait_target_cycle; + uint8_t digital_power_down_wait_cycle; + uint8_t digital_power_up_wait_cycle; +} pmu_lp_param_t; + +typedef struct { + union { + uint16_t xtal_stable_wait_slow_clk_cycle; + uint16_t xtal_stable_wait_cycle; + }; +} pmu_hp_lp_param_t; + +#ifdef __cplusplus +} +#endif From 59cf87fe7dfae6a7300aa7c12c753e7bcbb273b2 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Mon, 30 Jan 2023 16:37:20 +0800 Subject: [PATCH 04/16] pmu: sleep initialization and sleep start support for esp32c6 Initialize the pmu sleep machine constant when pmu is initialized, and calculate the pmu sleep time adjustment value and hardware configuration value according to the machine constant during system sleep. Calibrate fast OSC before each sleep and use the calibration value to calculate PMU hardware wait cycles when use the fast OSC as the work clock. --- .../include/esp_private/esp_pmu.h | 212 +++++++++ components/esp_hw_support/include/esp_sleep.h | 6 +- components/esp_hw_support/linker.lf | 2 + .../port/esp32c6/CMakeLists.txt | 6 +- .../esp_hw_support/port/esp32c6/pmu_init.c | 207 ++++++++ .../esp_hw_support/port/esp32c6/pmu_param.c | 441 ++++++++++++++++++ .../esp_hw_support/port/esp32c6/pmu_sleep.c | 256 ++++++++++ .../port/esp32c6/private_include/pmu_param.h | 336 +++++++++++++ .../esp_hw_support/port/esp32c6/rtc_init.c | 26 -- components/esp_hw_support/sleep_modes.c | 100 ++-- components/esp_system/fpga_overrides.c | 4 + components/esp_system/port/soc/esp32c6/clk.c | 11 +- components/hal/esp32c6/rtc_cntl_hal.c | 53 --- components/soc/esp32c6/include/soc/rtc.h | 40 -- 14 files changed, 1542 insertions(+), 158 deletions(-) create mode 100644 components/esp_hw_support/include/esp_private/esp_pmu.h create mode 100644 components/esp_hw_support/port/esp32c6/pmu_init.c create mode 100644 components/esp_hw_support/port/esp32c6/pmu_param.c create mode 100644 components/esp_hw_support/port/esp32c6/pmu_sleep.c create mode 100644 components/esp_hw_support/port/esp32c6/private_include/pmu_param.h delete mode 100644 components/esp_hw_support/port/esp32c6/rtc_init.c delete mode 100644 components/hal/esp32c6/rtc_cntl_hal.c diff --git a/components/esp_hw_support/include/esp_private/esp_pmu.h b/components/esp_hw_support/include/esp_private/esp_pmu.h new file mode 100644 index 0000000000..ce04a4bb32 --- /dev/null +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -0,0 +1,212 @@ +/* + * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include + +#include "soc/soc_caps.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if SOC_PMU_SUPPORTED +#include "hal/pmu_hal.h" +#include "pmu_param.h" + +#define RTC_SLEEP_PD_DIG PMU_SLEEP_PD_TOP //!< Deep sleep (power down digital domain) +#define RTC_SLEEP_PD_RTC_PERIPH PMU_SLEEP_PD_LP_PERIPH //!< Power down RTC peripherals +// #define RTC_SLEEP_PD_RTC_SLOW_MEM BIT(2) //!< Power down RTC SLOW memory +// #define RTC_SLEEP_PD_RTC_FAST_MEM BIT(3) //!< Power down RTC FAST memory +// #define RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU BIT(4) //!< RTC FAST and SLOW memories are automatically powered up and down along with the CPU +#define RTC_SLEEP_PD_VDDSDIO PMU_SLEEP_PD_VDDSDIO //!< Power down VDDSDIO regulator +#define RTC_SLEEP_PD_CPU PMU_SLEEP_PD_CPU //!< Power down CPU when in lightsleep, but not restart +#define RTC_SLEEP_PD_DIG_PERIPH PMU_SLEEP_PD_HP_PERIPH //!< Power down DIG peripherals +#define RTC_SLEEP_PD_INT_8M PMU_SLEEP_PD_RC_FAST //!< Power down Internal 20M oscillator +#define RTC_SLEEP_PD_XTAL PMU_SLEEP_PD_XTAL //!< Power down main XTAL + +//These flags are not power domains, but will affect some sleep parameters +#define RTC_SLEEP_DIG_USE_8M BIT(16) +#define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17) +#define RTC_SLEEP_NO_ULTRA_LOW BIT(18) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature + +#define RTC_GPIO_TRIG_EN PMU_GPIO_WAKEUP_EN //!< GPIO wakeup +#define RTC_TIMER_TRIG_EN PMU_LP_TIMER_WAKEUP_EN //!< Timer wakeup +#define RTC_WIFI_TRIG_EN PMU_WIFI_SOC_WAKEUP_EN //!< WIFI wakeup (light sleep only) +#define RTC_UART0_TRIG_EN PMU_UART0_WAKEUP_EN //!< UART0 wakeup (light sleep only) +#define RTC_UART1_TRIG_EN PMU_UART1_WAKEUP_EN //!< UART1 wakeup (light sleep only) +#define RTC_BT_TRIG_EN PMU_BLE_SOC_WAKEUP_EN //!< BT wakeup (light sleep only) +#define RTC_USB_TRIG_EN PMU_USB_WAKEUP_EN +#define RTC_XTAL32K_DEAD_TRIG_EN 0 // TODO +#define RTC_BROWNOUT_DET_TRIG_EN 0 // TODO + +/** + * RTC_SLEEP_REJECT_MASK records sleep reject sources supported by chip + */ +#define RTC_SLEEP_REJECT_MASK (RTC_GPIO_TRIG_EN | \ + RTC_TIMER_TRIG_EN | \ + RTC_WIFI_TRIG_EN | \ + RTC_UART0_TRIG_EN | \ + RTC_UART1_TRIG_EN | \ + RTC_BT_TRIG_EN | \ + RTC_XTAL32K_DEAD_TRIG_EN | \ + RTC_USB_TRIG_EN | \ + RTC_BROWNOUT_DET_TRIG_EN) + + +#define PMU_GPIO_WAKEUP_EN BIT(2) +#define PMU_WIFI_BEACON_WAKEUP_EN BIT(3) +#define PMU_LP_TIMER_WAKEUP_EN BIT(4) +#define PMU_WIFI_SOC_WAKEUP_EN BIT(5) +#define PMU_UART0_WAKEUP_EN BIT(6) +#define PMU_UART1_WAKEUP_EN BIT(7) +#define PMU_SDIO_WAKEUP_EN BIT(8) +#define PMU_BLE_SOC_WAKEUP_EN BIT(10) +#define PMU_USB_WAKEUP_EN BIT(14) + + +#define PMU_SLEEP_PD_TOP BIT(0) +#define PMU_SLEEP_PD_VDDSDIO BIT(1) +#define PMU_SLEEP_PD_MODEM BIT(2) +#define PMU_SLEEP_PD_HP_PERIPH BIT(3) +#define PMU_SLEEP_PD_CPU BIT(4) +#define PMU_SLEEP_PD_AON BIT(5) +#define PMU_SLEEP_PD_MEM_G0 BIT(6) +#define PMU_SLEEP_PD_MEM_G1 BIT(7) +#define PMU_SLEEP_PD_MEM_G2 BIT(8) +#define PMU_SLEEP_PD_MEM_G3 BIT(9) +#define PMU_SLEEP_PD_XTAL BIT(10) +#define PMU_SLEEP_PD_RC_FAST BIT(11) +#define PMU_SLEEP_PD_XTAL32K BIT(12) +#define PMU_SLEEP_PD_RC32K BIT(13) +#define PMU_SLEEP_PD_LP_PERIPH BIT(14) + +typedef struct { + pmu_hal_context_t *hal; + void *mc; +} pmu_context_t; + +pmu_context_t * PMU_instance(void); + +typedef enum pmu_hp_sysclk_src { + PMU_HP_SYSCLK_XTAL = 0, + PMU_HP_SYSCLK_PLL, + PMU_HP_SYSCLK_FOSC +} pmu_hp_sysclk_src_t; + +typedef enum pmu_sleep_protect_mode { + PMU_SLEEP_PROTECT_HP_SLEEP = 0, + PMU_SLEEP_PROTECT_XTAL, + PMU_SLEEP_PROTECT_HP_LP_SLEEP, + PMU_SLEEP_PROTECT_DISABLE +} pmu_sleep_protect_mode_t; + +typedef enum pmu_sleep_regdma_entry { + PMU_SLEEP_REGDMA_ENTRY_0 = 0, + PMU_SLEEP_REGDMA_ENTRY_1, + PMU_SLEEP_REGDMA_ENTRY_2, + PMU_SLEEP_REGDMA_ENTRY_3, + PMU_SLEEP_REGDMA_ENTRY_MAX +} pmu_sleep_regdma_entry_t; + + + +/** + * @brief Enable_regdma_backup. + */ +void pmu_sleep_enable_regdma_backup(void); + +/** + * @brief Disable_regdma_backup. + */ +void pmu_sleep_disable_regdma_backup(void); + +/** + * @brief Calculate the hardware time overhead during sleep to compensate for sleep time + * + * @param pd_flags flags indicates the power domain that will be powered down + * @param slowclk_period re-calibrated slow clock period + * @param fastclk_period re-calibrated fast clock period + * + * @return hardware time overhead in us + */ +uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_period, uint32_t fastclk_period); + +/** + * @brief Get default sleep configuration + * @param config pmu_sleep_config instance + * @param pd_flags flags indicates the power domain that will be powered down + * @param adjustment total software and hardware time overhead + * @param slowclk_period re-calibrated slow clock period in microseconds, + * Q13.19 fixed point format + * @param fastclk_period re-calibrated fast clock period in microseconds, + * Q13.19 fixed point format + * @param dslp configuration for deep sleep mode + + * @return hardware time overhead in us + */ +const pmu_sleep_config_t* pmu_sleep_config_default(pmu_sleep_config_t *config, uint32_t pd_flags, uint32_t adjustment, uint32_t slowclk_period, uint32_t fastclk_period, bool dslp); + +/** + * @brief Prepare the chip to enter sleep mode + * + * This function configures various power/analog parameters and lp/lp system configuration + * used in sleep state machines + * + * This function does not actually enter sleep mode; this is done using + * pmu_sleep_start function. Software may do some other actions between + * pmu_sleep_init and pmu_sleep_start, such as set wakeup timer and configure + * wakeup sources. + * + * @param config sleep mode configuration + * + * @param dslp is initialize for deep sleep mode + */ +void pmu_sleep_init(const pmu_sleep_config_t *config, bool dslp); + +/** + * @brief Enter deep or light sleep mode + * + * This function enters the sleep mode previously configured using pmu_sleep_init + * function. Before entering sleep, software should configure wake up sources + * appropriately (set up GPIO wakeup registers, timer wakeup registers, + * and so on). + * + * If deep sleep mode was configured using pmu_sleep_init, and sleep is not + * rejected by hardware (based on reject_opt flags), this function never returns. + * When the chip wakes up from deep sleep, CPU is reset and execution starts + * from ROM bootloader. + * + * If light sleep mode was configured using pmu_sleep_init, this function + * returns on wakeup, or if sleep is rejected by hardware. + * + * @param wakeup_opt bit mask wake up reasons to enable (RTC_xxx_TRIG_EN flags + * combined with OR) + * @param reject_opt bit mask of sleep reject reasons, used to + * prevent wakeup source set before the sleep request) + * @param lslp_mem_inf_fpu If non-zero then the low power config is restored + * immediately on wake. Recommended for light sleep, + * has no effect if the system goes into deep sleep. + * + * @return non-zero if sleep was rejected by hardware + */ +uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp); + +/** + * @brief Initialize PMU related power/clock/digital parameters and functions + */ +void pmu_init(void); + + +#endif //#if SOC_PMU_SUPPORTED + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index 17550d8aab..25d24aaeab 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -48,10 +48,10 @@ typedef enum { #endif ESP_PD_DOMAIN_XTAL, //!< XTAL oscillator #if SOC_PM_SUPPORT_XTAL32K_PD - ESP_PD_DOMAIN_XTAL32K, + ESP_PD_DOMAIN_XTAL32K, //!< External 32 kHz XTAL oscillator #endif #if SOC_PM_SUPPORT_RC32K_PD - ESP_PD_DOMAIN_RC32K, + ESP_PD_DOMAIN_RC32K, //!< Internal 32 kHz RC oscillator #endif #if SOC_PM_SUPPORT_RC_FAST_PD ESP_PD_DOMAIN_RC_FAST, //!< Internal Fast oscillator @@ -59,7 +59,9 @@ typedef enum { #if SOC_PM_SUPPORT_CPU_PD ESP_PD_DOMAIN_CPU, //!< CPU core #endif +#if SOC_PM_SUPPORT_VDDSDIO_PD ESP_PD_DOMAIN_VDDSDIO, //!< VDD_SDIO +#endif ESP_PD_DOMAIN_MAX //!< Number of domains } esp_sleep_pd_domain_t; diff --git a/components/esp_hw_support/linker.lf b/components/esp_hw_support/linker.lf index 1c1a0bf464..7f093b2e06 100644 --- a/components/esp_hw_support/linker.lf +++ b/components/esp_hw_support/linker.lf @@ -18,6 +18,8 @@ entries: rtc_pm (noflash_text) rtc_sleep (noflash_text) rtc_time (noflash_text) + if SOC_PMU_SUPPORTED = y: + pmu_sleep (noflash) if IDF_TARGET_ESP32 = y || IDF_TARGET_ESP32S2 = y: rtc_wdt (noflash_text) if PERIPH_CTRL_FUNC_IN_IRAM = y: diff --git a/components/esp_hw_support/port/esp32c6/CMakeLists.txt b/components/esp_hw_support/port/esp32c6/CMakeLists.txt index fed30227f3..33047b7052 100644 --- a/components/esp_hw_support/port/esp32c6/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32c6/CMakeLists.txt @@ -1,8 +1,8 @@ set(srcs "rtc_clk_init.c" "rtc_clk.c" - "rtc_init.c" - # "rtc_pm.c" // TODO: IDF-5645 - # "rtc_sleep.c" // TODO: IDF-5645 + "pmu_param.c" + "pmu_init.c" + "pmu_sleep.c" "rtc_time.c" "chip_info.c") diff --git a/components/esp_hw_support/port/esp32c6/pmu_init.c b/components/esp_hw_support/port/esp32c6/pmu_init.c new file mode 100644 index 0000000000..b99e6e639d --- /dev/null +++ b/components/esp_hw_support/port/esp32c6/pmu_init.c @@ -0,0 +1,207 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "sdkconfig.h" +#include "esp_attr.h" +#include "soc/soc.h" +#include "soc/pmu_struct.h" +#include "hal/pmu_hal.h" +#include "pmu_param.h" +#include "esp_private/esp_pmu.h" +#include "soc/regi2c_dig_reg.h" +#include "regi2c_ctrl.h" + +static __attribute__((unused)) const char *TAG = "pmu_init"; + +typedef struct { + const pmu_hp_system_power_param_t *power; + const pmu_hp_system_clock_param_t *clock; + const pmu_hp_system_digital_param_t *digital; + const pmu_hp_system_analog_param_t *analog; + const pmu_hp_system_retention_param_t *retent; +} pmu_hp_system_param_t; + +typedef struct { + const pmu_lp_system_power_param_t *power; + const pmu_lp_system_analog_param_t *analog; +} pmu_lp_system_param_t; + +pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void) +{ + /* It should be explicitly defined in the internal RAM, because this + * instance will be used in pmu_sleep.c */ + static DRAM_ATTR pmu_hal_context_t pmu_hal = { .dev = &PMU }; + static DRAM_ATTR pmu_sleep_machine_constant_t pmu_mc = PMU_SLEEP_MC_DEFAULT(); + static DRAM_ATTR pmu_context_t pmu_context = { .hal = &pmu_hal, .mc = (void *)&pmu_mc }; + return &pmu_context; +} + +void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, pmu_hp_system_param_t *param) +{ + const pmu_hp_system_power_param_t *power = param->power; + const pmu_hp_system_clock_param_t *clock = param->clock; + const pmu_hp_system_digital_param_t *dig = param->digital; + const pmu_hp_system_analog_param_t *anlg = param->analog; + const pmu_hp_system_retention_param_t *ret = param->retent; + + assert(ctx->hal); + /* Default configuration of hp-system power in active, modem and sleep modes */ + pmu_ll_hp_set_dig_power(ctx->hal->dev, mode, power->dig_power.val); + pmu_ll_hp_set_clk_power(ctx->hal->dev, mode, power->clk_power.val); + pmu_ll_hp_set_xtal_xpd (ctx->hal->dev, mode, power->xtal.xpd_xtal); + + /* Default configuration of hp-system clock in active, modem and sleep modes */ + pmu_ll_hp_set_icg_func (ctx->hal->dev, mode, clock->icg_func); + pmu_ll_hp_set_icg_apb (ctx->hal->dev, mode, clock->icg_apb); + pmu_ll_hp_set_icg_modem (ctx->hal->dev, mode, clock->icg_modem.code); + pmu_ll_hp_set_sysclk_nodiv (ctx->hal->dev, mode, clock->sysclk.dig_sysclk_nodiv); + pmu_ll_hp_set_icg_sysclk_enable (ctx->hal->dev, mode, clock->sysclk.icg_sysclk_en); + pmu_ll_hp_set_sysclk_slp_sel (ctx->hal->dev, mode, clock->sysclk.sysclk_slp_sel); + pmu_ll_hp_set_icg_sysclk_slp_sel(ctx->hal->dev, mode, clock->sysclk.icg_slp_sel); + pmu_ll_hp_set_dig_sysclk (ctx->hal->dev, mode, clock->sysclk.dig_sysclk_sel); + + /* Default configuration of hp-system digital sub-system in active, modem + * and sleep modes */ + pmu_ll_hp_set_uart_wakeup_enable(ctx->hal->dev, mode, dig->syscntl.uart_wakeup_en); + pmu_ll_hp_set_hold_all_lp_pad (ctx->hal->dev, mode, dig->syscntl.lp_pad_hold_all); + pmu_ll_hp_set_hold_all_hp_pad (ctx->hal->dev, mode, dig->syscntl.hp_pad_hold_all); + pmu_ll_hp_set_dig_pad_slp_sel (ctx->hal->dev, mode, dig->syscntl.dig_pad_slp_sel); + pmu_ll_hp_set_pause_watchdog (ctx->hal->dev, mode, dig->syscntl.dig_pause_wdt); + pmu_ll_hp_set_cpu_stall (ctx->hal->dev, mode, dig->syscntl.dig_cpu_stall); + + /* Default configuration of hp-system analog sub-system in active, modem and + * sleep modes */ + pmu_ll_hp_set_bias_xpd (ctx->hal->dev, mode, anlg->bias.xpd_bias); + pmu_ll_hp_set_dbg_atten (ctx->hal->dev, mode, anlg->bias.dbg_atten); + pmu_ll_hp_set_current_power_off (ctx->hal->dev, mode, anlg->bias.pd_cur); + pmu_ll_hp_set_bias_sleep_enable (ctx->hal->dev, mode, anlg->bias.bias_sleep); + pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_mem_xpd); + pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_logic_xpd); + pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, mode, anlg->regulator0.xpd); + pmu_ll_hp_set_regulator_sleep_memory_dbias(ctx->hal->dev, mode, anlg->regulator0.slp_mem_dbias); + pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, mode, anlg->regulator0.slp_logic_dbias); + pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, mode, anlg->regulator0.dbias); + pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, mode, anlg->regulator1.drv_b); + + /* Default configuration of hp-system retention sub-system in active, modem + * and sleep modes */ + pmu_ll_hp_set_retention_param(ctx->hal->dev, mode, ret->retention.val); + pmu_ll_hp_set_backup_icg_func(ctx->hal->dev, mode, ret->backup_clk); + + /* Some PMU initial parameter configuration */ + pmu_ll_imm_update_dig_icg_modem_code(ctx->hal->dev, true); + pmu_ll_imm_update_dig_icg_switch(ctx->hal->dev, true); + + pmu_ll_hp_set_sleep_protect_mode(ctx->hal->dev, PMU_SLEEP_PROTECT_HP_LP_SLEEP); +} + +void pmu_lp_system_init(pmu_context_t *ctx, pmu_lp_mode_t mode, pmu_lp_system_param_t *param) +{ + const pmu_lp_system_power_param_t *power = param->power; + const pmu_lp_system_analog_param_t *anlg = param->analog; + + assert(ctx->hal); + /* Default configuration of lp-system power in active and sleep modes */ + pmu_ll_lp_set_dig_power(ctx->hal->dev, mode, power->dig_power.val); + pmu_ll_lp_set_clk_power(ctx->hal->dev, mode, power->clk_power.val); + pmu_ll_lp_set_xtal_xpd (ctx->hal->dev, PMU_MODE_LP_SLEEP, power->xtal.xpd_xtal); + + /* Default configuration of lp-system analog sub-system in active and + * sleep modes */ + pmu_ll_lp_set_bias_xpd (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.xpd_bias); + pmu_ll_lp_set_dbg_atten (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.dbg_atten); + pmu_ll_lp_set_current_power_off (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.pd_cur); + pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, PMU_MODE_LP_SLEEP, anlg->bias.bias_sleep); + pmu_ll_lp_set_regulator_slp_xpd (ctx->hal->dev, mode, anlg->regulator0.slp_xpd); + pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, mode, anlg->regulator0.xpd); + pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, mode, anlg->regulator0.slp_dbias); + pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, mode, anlg->regulator0.dbias); + pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, mode, anlg->regulator1.drv_b); +} + +static inline void pmu_power_domain_force_default(pmu_context_t *ctx) +{ + assert(ctx); + // for bypass reserved power domain + const pmu_hp_power_domain_t pmu_hp_domains[] = { + PMU_HP_PD_TOP, + PMU_HP_PD_AON, + PMU_HP_PD_CPU, + PMU_HP_PD_WIFI + }; + + for (uint8_t idx = 0; idx < (sizeof(pmu_hp_domains) / sizeof(pmu_hp_power_domain_t)); idx++) { + pmu_ll_hp_set_power_force_reset (ctx->hal->dev, pmu_hp_domains[idx], false); + pmu_ll_hp_set_power_force_isolate (ctx->hal->dev, pmu_hp_domains[idx], false); + pmu_ll_hp_set_power_force_power_up (ctx->hal->dev, pmu_hp_domains[idx], false); + pmu_ll_hp_set_power_force_no_reset (ctx->hal->dev, pmu_hp_domains[idx], false); + pmu_ll_hp_set_power_force_no_isolate(ctx->hal->dev, pmu_hp_domains[idx], false); + pmu_ll_hp_set_power_force_power_down(ctx->hal->dev, pmu_hp_domains[idx], false); + } + /* Isolate all memory banks while sleeping, avoid memory leakage current */ + pmu_ll_hp_set_memory_no_isolate (ctx->hal->dev, 0); + + pmu_ll_lp_set_power_force_reset (ctx->hal->dev, false); + pmu_ll_lp_set_power_force_isolate (ctx->hal->dev, false); + pmu_ll_lp_set_power_force_power_up (ctx->hal->dev, false); + pmu_ll_lp_set_power_force_no_reset (ctx->hal->dev, false); + pmu_ll_lp_set_power_force_no_isolate(ctx->hal->dev, false); + pmu_ll_lp_set_power_force_power_down(ctx->hal->dev, false); +} + +static inline void pmu_hp_system_param_default(pmu_hp_mode_t mode, pmu_hp_system_param_t *param) +{ + param->power = pmu_hp_system_power_param_default(mode); + param->clock = pmu_hp_system_clock_param_default(mode); + param->digital = pmu_hp_system_digital_param_default(mode); + param->analog = pmu_hp_system_analog_param_default(mode); + param->retent = pmu_hp_system_retention_param_default(mode); +} + +static void pmu_hp_system_init_default(pmu_context_t *ctx) +{ + assert(ctx); + pmu_hp_system_param_t param = { 0 }; + for (pmu_hp_mode_t mode = PMU_MODE_HP_ACTIVE; mode < PMU_MODE_HP_MAX; mode++) { + pmu_hp_system_param_default(mode, ¶m); + pmu_hp_system_init(ctx, mode, ¶m); + } +} + +static inline void pmu_lp_system_param_default(pmu_lp_mode_t mode, pmu_lp_system_param_t *param) +{ + param->power = pmu_lp_system_power_param_default(mode); + param->analog = pmu_lp_system_analog_param_default(mode); +} + +static void pmu_lp_system_init_default(pmu_context_t *ctx) +{ + assert(ctx); + pmu_lp_system_param_t param; + for (pmu_lp_mode_t mode = PMU_MODE_LP_ACTIVE; mode < PMU_MODE_LP_MAX; mode++) { + pmu_lp_system_param_default(mode, ¶m); + pmu_lp_system_init(ctx, mode, ¶m); + } +} + +void pmu_init(void) +{ + /* Peripheral reg i2c power up */ + SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB); + SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); + + pmu_hp_system_init_default(PMU_instance()); + pmu_lp_system_init_default(PMU_instance()); + + pmu_power_domain_force_default(PMU_instance()); +} diff --git a/components/esp_hw_support/port/esp32c6/pmu_param.c b/components/esp_hw_support/port/esp32c6/pmu_param.c new file mode 100644 index 0000000000..0cd70d4985 --- /dev/null +++ b/components/esp_hw_support/port/esp32c6/pmu_param.c @@ -0,0 +1,441 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "sdkconfig.h" +#include "soc/soc.h" +#include "pmu_param.h" +#include "soc/pmu_icg_mapping.h" +#include "esp_private/esp_pmu.h" + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#endif + +#define PMU_HP_ACTIVE_POWER_CONFIG_DEFAULT() { \ + .dig_power = { \ + .vdd_spi_pd_en = 0, \ + .mem_dslp = 0, \ + .mem_pd_en = 0, \ + .wifi_pd_en = 0, \ + .cpu_pd_en = 0, \ + .aon_pd_en = 0, \ + .top_pd_en = 0 \ + }, \ + .clk_power = { \ + .i2c_iso_en = 0, \ + .i2c_retention = 0, \ + .xpd_bb_i2c = 1, \ + .xpd_bbpll_i2c = 1, \ + .xpd_bbpll = 1 \ + }, \ + .xtal = { \ + .xpd_xtal = 1 \ + } \ +} + +#define PMU_HP_MODEM_POWER_CONFIG_DEFAULT() { \ + .dig_power = { \ + .vdd_spi_pd_en = 0, \ + .mem_dslp = 0, \ + .mem_pd_en = 0, \ + .wifi_pd_en = 0, \ + .cpu_pd_en = 1, \ + .aon_pd_en = 0, \ + .top_pd_en = 0 \ + }, \ + .clk_power = { \ + .i2c_iso_en = 0, \ + .i2c_retention = 0, \ + .xpd_bb_i2c = 1, \ + .xpd_bbpll_i2c = 1, \ + .xpd_bbpll = 1 \ + }, \ + .xtal = { \ + .xpd_xtal = 1 \ + } \ +} + +#define PMU_HP_SLEEP_POWER_CONFIG_DEFAULT() { \ + .dig_power = { \ + .vdd_spi_pd_en = 1, \ + .mem_dslp = 0, \ + .mem_pd_en = 0, \ + .wifi_pd_en = 1, \ + .cpu_pd_en = 0, \ + .aon_pd_en = 0, \ + .top_pd_en = 0 \ + }, \ + .clk_power = { \ + .i2c_iso_en = 1, \ + .i2c_retention = 1, \ + .xpd_bb_i2c = 1, \ + .xpd_bbpll_i2c = 0, \ + .xpd_bbpll = 0, \ + }, \ + .xtal = { \ + .xpd_xtal = 0 \ + } \ +} + +const pmu_hp_system_power_param_t * pmu_hp_system_power_param_default(pmu_hp_mode_t mode) +{ + static const pmu_hp_system_power_param_t hp_power[] = { + PMU_HP_ACTIVE_POWER_CONFIG_DEFAULT(), + PMU_HP_MODEM_POWER_CONFIG_DEFAULT(), + PMU_HP_SLEEP_POWER_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(hp_power)); + return &hp_power[mode]; +} + +#define PMU_HP_ACTIVE_CLOCK_CONFIG_DEFAULT() { \ + .icg_func = 0xffffffff, \ + .icg_apb = 0xffffffff, \ + .icg_modem = { \ + .code = 2 \ + }, \ + .sysclk = { \ + .dig_sysclk_nodiv = 0, \ + .icg_sysclk_en = 1, \ + .sysclk_slp_sel = 0, \ + .icg_slp_sel = 0, \ + .dig_sysclk_sel = PMU_HP_SYSCLK_XTAL \ + } \ +} + +#define PMU_HP_MODEM_CLOCK_CONFIG_DEFAULT() { \ + .icg_func = 0, \ + .icg_apb = 0, \ + .icg_modem = { \ + .code = 1 \ + }, \ + .sysclk = { \ + .dig_sysclk_nodiv = 0, \ + .icg_sysclk_en = 1, \ + .sysclk_slp_sel = 1, \ + .icg_slp_sel = 1, \ + .dig_sysclk_sel = PMU_HP_SYSCLK_PLL \ + } \ +} + +#define PMU_HP_SLEEP_CLOCK_CONFIG_DEFAULT() { \ + .icg_func = 0, \ + .icg_apb = 0, \ + .icg_modem = { \ + .code = 0 \ + }, \ + .sysclk = { \ + .dig_sysclk_nodiv = 0, \ + .icg_sysclk_en = 0, \ + .sysclk_slp_sel = 1, \ + .icg_slp_sel = 1, \ + .dig_sysclk_sel = PMU_HP_SYSCLK_XTAL \ + } \ +} + +const pmu_hp_system_clock_param_t * pmu_hp_system_clock_param_default(pmu_hp_mode_t mode) +{ + static const pmu_hp_system_clock_param_t hp_clock[] = { + PMU_HP_ACTIVE_CLOCK_CONFIG_DEFAULT(), + PMU_HP_MODEM_CLOCK_CONFIG_DEFAULT(), + PMU_HP_SLEEP_CLOCK_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(hp_clock)); + return &hp_clock[mode]; +} + +#define PMU_HP_ACTIVE_DIGITAL_CONFIG_DEFAULT() { \ + .syscntl = { \ + .uart_wakeup_en = 0, \ + .lp_pad_hold_all = 0, \ + .hp_pad_hold_all = 0, \ + .dig_pad_slp_sel = 0, \ + .dig_pause_wdt = 0, \ + .dig_cpu_stall = 0 \ + } \ +} + +#define PMU_HP_MODEM_DIGITAL_CONFIG_DEFAULT() { \ + .syscntl = { \ + .uart_wakeup_en = 1, \ + .lp_pad_hold_all = 0, \ + .hp_pad_hold_all = 0, \ + .dig_pad_slp_sel = 0, \ + .dig_pause_wdt = 1, \ + .dig_cpu_stall = 1 \ + } \ +} + +#define PMU_HP_SLEEP_DIGITAL_CONFIG_DEFAULT() { \ + .syscntl = { \ + .uart_wakeup_en = 1, \ + .lp_pad_hold_all = 0, \ + .hp_pad_hold_all = 0, \ + .dig_pad_slp_sel = 1, \ + .dig_pause_wdt = 1, \ + .dig_cpu_stall = 1 \ + } \ +} + +const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp_mode_t mode) +{ + static const pmu_hp_system_digital_param_t hp_digital[] = { + PMU_HP_ACTIVE_DIGITAL_CONFIG_DEFAULT(), + PMU_HP_MODEM_DIGITAL_CONFIG_DEFAULT(), + PMU_HP_SLEEP_DIGITAL_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(hp_digital)); + return &hp_digital[mode]; +} + +#define PMU_HP_ACTIVE_ANALOG_CONFIG_DEFAULT() { \ + .bias = { \ + .xpd_bias = 1, \ + .dbg_atten = 0x0, \ + .pd_cur = 0, \ + .bias_sleep = 0 \ + }, \ + .regulator0 = { \ + .lp_dbias_vol = 0xd, \ + .hp_dbias_vol = 0x1c,\ + .dbias_sel = 1, \ + .dbias_init = 1, \ + .slp_mem_xpd = 0, \ + .slp_logic_xpd = 0, \ + .xpd = 1, \ + .slp_mem_dbias = 0xc, \ + .slp_logic_dbias = 0xc, \ + .dbias = 0x19 \ + }, \ + .regulator1 = { \ + .drv_b = 0x0 \ + } \ +} + +#define PMU_HP_MODEM_ANALOG_CONFIG_DEFAULT() { \ + .bias = { \ + .xpd_bias = 0, \ + .dbg_atten = 0x0, \ + .pd_cur = 0, \ + .bias_sleep = 0 \ + }, \ + .regulator0 = { \ + .slp_mem_xpd = 0, \ + .slp_logic_xpd = 0, \ + .xpd = 1, \ + .slp_mem_dbias = 0xc, \ + .slp_logic_dbias = 0xc, \ + .dbias = 0x1a \ + }, \ + .regulator1 = { \ + .drv_b = 0x0 \ + } \ +} + +#define PMU_HP_SLEEP_ANALOG_CONFIG_DEFAULT() { \ + .bias = { \ + .xpd_bias = 0, \ + .dbg_atten = 0x0, \ + .pd_cur = 0, \ + .bias_sleep = 0 \ + }, \ + .regulator0 = { \ + .slp_mem_xpd = 1, \ + .slp_logic_xpd = 1, \ + .xpd = 0, \ + .slp_mem_dbias = 0x4, \ + .slp_logic_dbias = 0x4, \ + .dbias = 0x1a \ + }, \ + .regulator1 = { \ + .drv_b = 0x0 \ + } \ +} + +const pmu_hp_system_analog_param_t * pmu_hp_system_analog_param_default(pmu_hp_mode_t mode) +{ + static const pmu_hp_system_analog_param_t hp_analog[] = { + PMU_HP_ACTIVE_ANALOG_CONFIG_DEFAULT(), + PMU_HP_MODEM_ANALOG_CONFIG_DEFAULT(), + PMU_HP_SLEEP_ANALOG_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(hp_analog)); + return &hp_analog[mode]; +} + +#define PMU_HP_RETENTION_REGDMA_CONFIG(dir, entry) ((((dir)<<2) | (entry & 0x3)) & 0x7) + +#define PMU_HP_ACTIVE_RETENTION_CONFIG_DEFAULT() { \ + .retention = { \ + .hp_sleep2active_backup_modem_clk_code = 2, \ + .hp_modem2active_backup_modem_clk_code = 2, \ + .hp_active_retention_mode = 0, \ + .hp_sleep2active_retention_en = 0, \ + .hp_modem2active_retention_en = 0, \ + .hp_sleep2active_backup_clk_sel = 0, \ + .hp_modem2active_backup_clk_sel = 0, \ + .hp_sleep2active_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 0), \ + .hp_modem2active_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 2), \ + .hp_sleep2active_backup_en = 0, \ + .hp_modem2active_backup_en = 0, \ + }, \ + .backup_clk = ( \ + BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ + BIT(PMU_ICG_FUNC_ENA_TG0) | \ + BIT(PMU_ICG_FUNC_ENA_TG1) | \ + BIT(PMU_ICG_FUNC_ENA_HPBUS) | \ + BIT(PMU_ICG_FUNC_ENA_MSPI) | \ + BIT(PMU_ICG_FUNC_ENA_IOMUX) | \ + BIT(PMU_ICG_FUNC_ENA_SPI2) | \ + BIT(PMU_ICG_FUNC_ENA_UART0) | \ + BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ + ) \ +} + +#define PMU_HP_MODEM_RETENTION_CONFIG_DEFAULT() { \ + .retention = { \ + .hp_sleep2modem_backup_modem_clk_code = 1, \ + .hp_modem_retention_mode = 0, \ + .hp_sleep2modem_retention_en = 0, \ + .hp_sleep2modem_backup_clk_sel = 0, \ + .hp_sleep2modem_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(0, 1), \ + .hp_sleep2modem_backup_en = 0, \ + }, \ + .backup_clk = ( \ + BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ + BIT(PMU_ICG_FUNC_ENA_TG0) | \ + BIT(PMU_ICG_FUNC_ENA_TG1) | \ + BIT(PMU_ICG_FUNC_ENA_HPBUS) | \ + BIT(PMU_ICG_FUNC_ENA_MSPI) | \ + BIT(PMU_ICG_FUNC_ENA_IOMUX) | \ + BIT(PMU_ICG_FUNC_ENA_SPI2) | \ + BIT(PMU_ICG_FUNC_ENA_UART0) | \ + BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ + ) \ +} + +#define PMU_HP_SLEEP_RETENTION_CONFIG_DEFAULT() { \ + .retention = { \ + .hp_modem2sleep_backup_modem_clk_code = 0, \ + .hp_active2sleep_backup_modem_clk_code = 2, \ + .hp_sleep_retention_mode = 0, \ + .hp_modem2sleep_retention_en = 0, \ + .hp_active2sleep_retention_en = 0, \ + .hp_modem2sleep_backup_clk_sel = 0, \ + .hp_active2sleep_backup_clk_sel = 0, \ + .hp_modem2sleep_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(1, 1), \ + .hp_active2sleep_backup_mode = PMU_HP_RETENTION_REGDMA_CONFIG(1, 0), \ + .hp_modem2sleep_backup_en = 0, \ + .hp_active2sleep_backup_en = 0, \ + }, \ + .backup_clk = ( \ + BIT(PMU_ICG_FUNC_ENA_REGDMA) | \ + BIT(PMU_ICG_FUNC_ENA_TG0) | \ + BIT(PMU_ICG_FUNC_ENA_TG1) | \ + BIT(PMU_ICG_FUNC_ENA_HPBUS) | \ + BIT(PMU_ICG_FUNC_ENA_MSPI) | \ + BIT(PMU_ICG_FUNC_ENA_IOMUX) | \ + BIT(PMU_ICG_FUNC_ENA_SPI2) | \ + BIT(PMU_ICG_FUNC_ENA_UART0) | \ + BIT(PMU_ICG_FUNC_ENA_SYSTIMER) \ + ) \ +} + +const pmu_hp_system_retention_param_t * pmu_hp_system_retention_param_default(pmu_hp_mode_t mode) +{ + static const pmu_hp_system_retention_param_t hp_retention[] = { + PMU_HP_ACTIVE_RETENTION_CONFIG_DEFAULT(), + PMU_HP_MODEM_RETENTION_CONFIG_DEFAULT(), + PMU_HP_SLEEP_RETENTION_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(hp_retention)); + return &hp_retention[mode]; +} + + +/** LP system default parameter */ + +#define PMU_LP_ACTIVE_POWER_CONFIG_DEFAULT() { \ + .dig_power = { \ + .mem_dslp = 0, \ + .peri_pd_en = 0, \ + }, \ + .clk_power = { \ + .xpd_xtal32k = 1, \ + .xpd_rc32k = 1, \ + .xpd_fosc = 1, \ + .pd_osc = 0 \ + } \ +} + +#define PMU_LP_SLEEP_POWER_CONFIG_DEFAULT() { \ + .dig_power = { \ + .mem_dslp = 1, \ + .peri_pd_en = 0, \ + }, \ + .clk_power = { \ + .xpd_xtal32k = 0, \ + .xpd_rc32k = 0, \ + .xpd_fosc = 0, \ + .pd_osc = 0 \ + }, \ + .xtal = { \ + .xpd_xtal = 0 \ + } \ +} + +const pmu_lp_system_power_param_t * pmu_lp_system_power_param_default(pmu_lp_mode_t mode) +{ + static const pmu_lp_system_power_param_t lp_power[] = { + PMU_LP_ACTIVE_POWER_CONFIG_DEFAULT(), + PMU_LP_SLEEP_POWER_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(lp_power)); + return &lp_power[mode]; +} + +#define PMU_LP_ACTIVE_ANALOG_CONFIG_DEFAULT() { \ + .regulator0 = { \ + .slp_xpd = 0, \ + .xpd = 1, \ + .slp_dbias = 0x0, \ + .dbias = 0x1a \ + }, \ + .regulator1 = { \ + .drv_b = 0x0 \ + } \ +} + +#define PMU_LP_SLEEP_ANALOG_CONFIG_DEFAULT() { \ + .bias = { \ + .xpd_bias = 0, \ + .dbg_atten = 0x0, \ + .pd_cur = 1, \ + .bias_sleep = 1, \ + }, \ + .regulator0 = { \ + .slp_xpd = 1, \ + .xpd = 0, \ + .slp_dbias = 0x0, \ + .dbias = 0x12 \ + }, \ + .regulator1 = { \ + .drv_b = 0x0 \ + } \ +} + +const pmu_lp_system_analog_param_t * pmu_lp_system_analog_param_default(pmu_lp_mode_t mode) +{ + static const pmu_lp_system_analog_param_t lp_analog[] = { + PMU_LP_ACTIVE_ANALOG_CONFIG_DEFAULT(), + PMU_LP_SLEEP_ANALOG_CONFIG_DEFAULT() + }; + assert(mode < ARRAY_SIZE(lp_analog)); + return &lp_analog[mode]; +} diff --git a/components/esp_hw_support/port/esp32c6/pmu_sleep.c b/components/esp_hw_support/port/esp32c6/pmu_sleep.c new file mode 100644 index 0000000000..4e320b7aef --- /dev/null +++ b/components/esp_hw_support/port/esp32c6/pmu_sleep.c @@ -0,0 +1,256 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "sdkconfig.h" +#include "esp_err.h" +#include "esp_attr.h" +#include "soc/soc.h" +#include "soc/rtc.h" +#include "soc/pmu_struct.h" +#include "esp_private/esp_pmu.h" + +#define HP(state) (PMU_MODE_HP_ ## state) +#define LP(state) (PMU_MODE_LP_ ## state) + +void pmu_sleep_enable_regdma_backup(void) +{ + assert(PMU_instance()->hal); + /* entry 0, 1, 2 is used by pmu HP_SLEEP and HP_ACTIVE, HP_SLEEP + * and HP_MODEM or HP_MODEM and HP_ACTIVE states switching, + * respectively. entry 3 is reserved, not used yet! */ + pmu_hal_hp_set_sleep_active_backup_enable(PMU_instance()->hal); + pmu_hal_hp_set_sleep_modem_backup_enable(PMU_instance()->hal); + pmu_hal_hp_set_modem_active_backup_enable(PMU_instance()->hal); +} + +void pmu_sleep_disable_regdma_backup(void) +{ + assert(PMU_instance()->hal); + pmu_hal_hp_set_sleep_active_backup_disable(PMU_instance()->hal); + pmu_hal_hp_set_sleep_modem_backup_disable(PMU_instance()->hal); + pmu_hal_hp_set_modem_active_backup_disable(PMU_instance()->hal); +} + +uint32_t pmu_sleep_calculate_hw_wait_time(uint32_t pd_flags, uint32_t slowclk_period, uint32_t fastclk_period) +{ + const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc; + + /* LP core hardware wait time, microsecond */ + const int lp_wakeup_wait_time = rtc_time_slowclk_to_us(mc->lp.wakeup_wait_cycle, slowclk_period); + const int lp_clk_switch_time = rtc_time_slowclk_to_us(mc->lp.clk_switch_cycle, slowclk_period); + const int lp_clk_power_on_wait_time = (pd_flags & PMU_SLEEP_PD_XTAL) ? mc->lp.xtal_wait_stable_time_ms \ + : rtc_time_slowclk_to_us(mc->lp.clk_power_on_wait_cycle, slowclk_period); + + const int lp_hw_wait_time = mc->lp.min_slp_time_ms + mc->lp.analog_wait_time_ms + lp_clk_power_on_wait_time \ + + lp_wakeup_wait_time + lp_clk_switch_time + mc->lp.power_supply_wait_time_ms \ + + mc->lp.power_up_wait_time_ms; + + /* HP core hardware wait time, microsecond */ + const int hp_digital_power_up_wait_time_ms = mc->hp.power_supply_wait_time_ms + mc->hp.power_up_wait_time_ms; + const int hp_regdma_wait_time = MAX(mc->hp.regdma_s2m_work_time_ms + mc->hp.regdma_m2a_work_time_ms, mc->hp.regdma_s2a_work_time_ms); + const int hp_clock_wait_time = mc->hp.xtal_wait_stable_time_ms + mc->hp.pll_wait_stable_time_ms; + + const int hp_hw_wait_time = mc->hp.analog_wait_time_ms + MAX(hp_digital_power_up_wait_time_ms + hp_regdma_wait_time, hp_clock_wait_time); + + /* When the SOC wakeup (lp timer or GPIO wakeup) and Modem wakeup (Beacon wakeup) complete, the soc + * wakeup will be delayed until the RF is turned on in Modem state. + * + * modem wakeup TBTT, RF on by HW + * | | + * \|/ \|/ + * PMU_HP_ACTIVE /------ + * PMU_HP_MODEM /------------////////////////// + * PMU_HP_SLEEP ----------------------////////////////// + * /|\ /|\ /|\ /|\ /|\ /|\ + * |<- some hw wait ->| | | |<- M2A switch ->| + * | slow cycles & | soc wakeup | | + * | FOSC cycles |<- S2M switch ->| | + * | | + * |<-- PMU guard time, also the maximum time for the SOC -->| + * | wake-up delay | + */ +#if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_AUTO_BEACON_ENABLE + const int rf_on_protect_time = mc->hp.regdma_rf_on_work_time_ms; + const int total_hw_wait_time = lp_hw_wait_time + hp_hw_wait_time + mc->hp.clock_domain_sync_time_ms; +#else + const int rf_on_protect_time = 0; + const int total_hw_wait_time = lp_hw_wait_time + hp_hw_wait_time; +#endif + return total_hw_wait_time + rf_on_protect_time; +} + +#define rtc_time_us_to_fastclk(time_us, period) rtc_time_us_to_slowclk((time_us), (period)) + +static inline pmu_sleep_param_config_t * pmu_sleep_param_config_default( + pmu_sleep_param_config_t *param, + pmu_sleep_power_config_t *power, /* We'll use the runtime power parameter to determine some hardware parameters */ + const uint32_t pd_flags, + const uint32_t adjustment, + const uint32_t slowclk_period, + const uint32_t fastclk_period + ) +{ + const pmu_sleep_machine_constant_t *mc = (pmu_sleep_machine_constant_t *)PMU_instance()->mc; + + param->hp_sys.min_slp_slow_clk_cycle = rtc_time_us_to_slowclk(mc->hp.min_slp_time_ms, slowclk_period); + param->hp_sys.analog_wait_target_cycle = rtc_time_us_to_fastclk(mc->hp.analog_wait_time_ms, fastclk_period); + param->hp_sys.digital_power_supply_wait_cycle = rtc_time_us_to_fastclk(mc->hp.power_supply_wait_time_ms, fastclk_period); + param->hp_sys.digital_power_up_wait_cycle = rtc_time_us_to_fastclk(mc->hp.power_up_wait_time_ms, fastclk_period); + param->hp_sys.pll_stable_wait_cycle = rtc_time_us_to_fastclk(mc->hp.pll_wait_stable_time_ms, fastclk_period); + + const int hw_wait_time = pmu_sleep_calculate_hw_wait_time(pd_flags, slowclk_period, fastclk_period); + const int modem_state_skip_time = mc->hp.regdma_m2a_work_time_ms + mc->hp.system_dfs_up_work_time_ms + mc->lp.min_slp_time_ms; + const int modem_wakeup_wait_time = adjustment - hw_wait_time + modem_state_skip_time + mc->hp.regdma_rf_on_work_time_ms; + param->hp_sys.modem_wakeup_wait_cycle = rtc_time_us_to_fastclk(modem_wakeup_wait_time, fastclk_period); + + param->lp_sys.min_slp_slow_clk_cycle = rtc_time_us_to_slowclk(mc->lp.min_slp_time_ms, slowclk_period); + param->lp_sys.analog_wait_target_cycle = rtc_time_us_to_slowclk(mc->lp.analog_wait_time_ms, slowclk_period); + param->lp_sys.digital_power_supply_wait_cycle = rtc_time_us_to_fastclk(mc->lp.power_supply_wait_time_ms, fastclk_period); + param->lp_sys.digital_power_up_wait_cycle = rtc_time_us_to_fastclk(mc->lp.power_up_wait_time_ms, fastclk_period); + + if (power->hp_sys.xtal.xpd_xtal) { + param->hp_lp.xtal_stable_wait_cycle = rtc_time_us_to_fastclk(mc->hp.xtal_wait_stable_time_ms, fastclk_period); + } else { + param->hp_lp.xtal_stable_wait_slow_clk_cycle = rtc_time_us_to_slowclk(mc->lp.xtal_wait_stable_time_ms, slowclk_period); + } + return param; +} + +const pmu_sleep_config_t* pmu_sleep_config_default( + pmu_sleep_config_t *config, + uint32_t pd_flags, + uint32_t adjustment, + uint32_t slowclk_period, + uint32_t fastclk_period, + bool dslp + ) +{ + pmu_sleep_power_config_t power_default = PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags); + + uint32_t iram_pd_flags = 0; + iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G0) ? BIT(0) : 0; + iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G1) ? BIT(1) : 0; + iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G2) ? BIT(2) : 0; + iram_pd_flags |= (pd_flags & PMU_SLEEP_PD_MEM_G3) ? BIT(3) : 0; + config->power = power_default; + + pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags); + config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, pd_flags, adjustment, slowclk_period, fastclk_period); + + if (dslp) { + pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags); + config->analog = analog_default; + } else { + pmu_sleep_analog_config_t analog_default = PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags); + if (!(pd_flags & PMU_SLEEP_PD_MODEM)){ + analog_default.hp_sys.analog.slp_logic_dbias += 2; + } + if (!(pd_flags & PMU_SLEEP_PD_TOP)){ + analog_default.hp_sys.analog.slp_logic_dbias += 2; + } + config->analog = analog_default; + } + return config; +} + +static void pmu_sleep_power_init(pmu_context_t *ctx, const pmu_sleep_power_config_t *power, bool dslp) +{ + pmu_ll_hp_set_dig_power(ctx->hal->dev, HP(SLEEP), power->hp_sys.dig_power.val); + pmu_ll_hp_set_clk_power(ctx->hal->dev, HP(SLEEP), power->hp_sys.clk_power.val); + pmu_ll_hp_set_xtal_xpd (ctx->hal->dev, HP(SLEEP), power->hp_sys.xtal.xpd_xtal); + + pmu_ll_lp_set_dig_power(ctx->hal->dev, LP(ACTIVE), power->lp_sys[LP(ACTIVE)].dig_power.val); + pmu_ll_lp_set_clk_power(ctx->hal->dev, LP(ACTIVE), power->lp_sys[LP(ACTIVE)].clk_power.val); + + pmu_ll_lp_set_dig_power(ctx->hal->dev, LP(SLEEP), power->lp_sys[LP(SLEEP)].dig_power.val); + pmu_ll_lp_set_clk_power(ctx->hal->dev, LP(SLEEP), power->lp_sys[LP(SLEEP)].clk_power.val); + pmu_ll_lp_set_xtal_xpd (ctx->hal->dev, LP(SLEEP), power->lp_sys[LP(SLEEP)].xtal.xpd_xtal); + + if (dslp) { + // TODO: IDF-5349 + } else { + } +} + +static void pmu_sleep_analog_init(pmu_context_t *ctx, const pmu_sleep_analog_config_t *analog, bool dslp) +{ + assert(ctx->hal); + pmu_ll_hp_set_current_power_off (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.pd_cur); + pmu_ll_hp_set_bias_sleep_enable (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.bias_sleep); + pmu_ll_hp_set_regulator_sleep_memory_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_xpd); + pmu_ll_hp_set_regulator_sleep_logic_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_xpd); + pmu_ll_hp_set_regulator_xpd (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.xpd); + pmu_ll_hp_set_regulator_sleep_memory_dbias(ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_mem_dbias); + pmu_ll_hp_set_regulator_sleep_logic_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.slp_logic_dbias); + pmu_ll_hp_set_regulator_dbias (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.dbias); + pmu_ll_hp_set_regulator_driver_bar (ctx->hal->dev, HP(SLEEP), analog->hp_sys.analog.drv_b); + + pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.slp_dbias); + pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.dbias); + pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, LP(ACTIVE), analog->lp_sys[LP(ACTIVE)].analog.drv_b); + + pmu_ll_lp_set_current_power_off (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.pd_cur); + pmu_ll_lp_set_bias_sleep_enable (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.bias_sleep); + pmu_ll_lp_set_regulator_xpd (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.xpd); + pmu_ll_lp_set_regulator_sleep_dbias(ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.slp_dbias); + pmu_ll_lp_set_regulator_dbias (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.dbias); + pmu_ll_lp_set_regulator_driver_bar (ctx->hal->dev, LP(SLEEP), analog->lp_sys[LP(SLEEP)].analog.drv_b); + + if (dslp) { + // TODO: IDF-5349 + } else { + } +} + +static void pmu_sleep_param_init(pmu_context_t *ctx, const pmu_sleep_param_config_t *param, bool dslp) +{ + assert(ctx->hal); + pmu_ll_hp_set_min_sleep_cycle(ctx->hal->dev, param->hp_sys.min_slp_slow_clk_cycle); + pmu_ll_lp_set_min_sleep_cycle(ctx->hal->dev, param->lp_sys.min_slp_slow_clk_cycle); + + pmu_ll_hp_set_analog_wait_target_cycle(ctx->hal->dev, param->hp_sys.analog_wait_target_cycle); + pmu_ll_lp_set_analog_wait_target_cycle(ctx->hal->dev, param->lp_sys.analog_wait_target_cycle); + + pmu_hal_hp_set_digital_power_up_wait_cycle(ctx->hal, param->hp_sys.digital_power_supply_wait_cycle, param->hp_sys.digital_power_up_wait_cycle); + pmu_hal_lp_set_digital_power_up_wait_cycle(ctx->hal, param->lp_sys.digital_power_supply_wait_cycle, param->lp_sys.digital_power_up_wait_cycle); + + pmu_ll_set_modem_wait_target_cycle(ctx->hal->dev, param->hp_sys.modem_wakeup_wait_cycle); + pmu_ll_set_xtal_stable_wait_cycle(ctx->hal->dev, param->hp_lp.xtal_stable_wait_slow_clk_cycle); + pmu_ll_set_pll_stable_wait_cycle(ctx->hal->dev, param->hp_sys.pll_stable_wait_cycle); +} + +void pmu_sleep_init(const pmu_sleep_config_t *config, bool dslp) +{ + assert(PMU_instance()); + pmu_sleep_power_init(PMU_instance(), &config->power, dslp); + pmu_sleep_analog_init(PMU_instance(), &config->analog, dslp); + pmu_sleep_param_init(PMU_instance(), &config->param, dslp); +} + +uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp) +{ + assert(PMU_instance()->hal); + pmu_ll_hp_set_wakeup_enable(PMU_instance()->hal->dev, wakeup_opt); + pmu_ll_hp_set_reject_enable(PMU_instance()->hal->dev, reject_opt); + + pmu_ll_hp_clear_wakeup_intr_status(PMU_instance()->hal->dev); + pmu_ll_hp_clear_reject_intr_status(PMU_instance()->hal->dev); + pmu_ll_hp_clear_reject_cause(PMU_instance()->hal->dev); + + /* Start entry into sleep mode */ + pmu_ll_hp_set_sleep_enable(PMU_instance()->hal->dev); + + while (!pmu_ll_hp_is_sleep_wakeup(PMU_instance()->hal->dev) && + !pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev)) { + ; + } + + return ESP_OK; +} diff --git a/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h b/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h new file mode 100644 index 0000000000..31f49a0a87 --- /dev/null +++ b/components/esp_hw_support/port/esp32c6/private_include/pmu_param.h @@ -0,0 +1,336 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include "soc/pmu_struct.h" +#include "hal/pmu_hal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + pmu_hp_dig_power_reg_t dig_power; + pmu_hp_clk_power_reg_t clk_power; + pmu_hp_xtal_reg_t xtal; +} pmu_hp_system_power_param_t; + +const pmu_hp_system_power_param_t* pmu_hp_system_power_param_default(pmu_hp_mode_t mode); + +typedef struct { + uint32_t icg_func; + uint32_t icg_apb; + pmu_hp_icg_modem_reg_t icg_modem; + pmu_hp_sysclk_reg_t sysclk; +} pmu_hp_system_clock_param_t; + +const pmu_hp_system_clock_param_t* pmu_hp_system_clock_param_default(pmu_hp_mode_t mode); + +typedef struct { + pmu_hp_sys_cntl_reg_t syscntl; +} pmu_hp_system_digital_param_t; + +const pmu_hp_system_digital_param_t* pmu_hp_system_digital_param_default(pmu_hp_mode_t mode); + +typedef struct { + pmu_hp_bias_reg_t bias; + pmu_hp_regulator0_reg_t regulator0; + pmu_hp_regulator1_reg_t regulator1; +} pmu_hp_system_analog_param_t; + +const pmu_hp_system_analog_param_t* pmu_hp_system_analog_param_default(pmu_hp_mode_t mode); + +typedef struct { + pmu_hp_backup_reg_t retention; + uint32_t backup_clk; +} pmu_hp_system_retention_param_t; + +const pmu_hp_system_retention_param_t* pmu_hp_system_retention_param_default(pmu_hp_mode_t mode); + +typedef struct { + pmu_lp_dig_power_reg_t dig_power; + pmu_lp_clk_power_reg_t clk_power; + pmu_lp_xtal_reg_t xtal; +} pmu_lp_system_power_param_t; + +const pmu_lp_system_power_param_t* pmu_lp_system_power_param_default(pmu_lp_mode_t mode); + +typedef struct { + pmu_lp_bias_reg_t bias; + pmu_lp_regulator0_reg_t regulator0; + pmu_lp_regulator1_reg_t regulator1; +} pmu_lp_system_analog_param_t; + +const pmu_lp_system_analog_param_t* pmu_lp_system_analog_param_default(pmu_lp_mode_t mode); + +#define PMU_HP_SLEEP_MIN_SLOW_CLK_CYCLES (10) +#define PMU_LP_SLEEP_MIN_SLOW_CLK_CYCLES (10) + +#define PMU_HP_WAKEUP_DELAY_CYCLES (0) +#define PMU_HP_XTAL_STABLE_WAIT_CYCLES (3155) /* Not used, Fast OSC as PMU work clock source is about 201 us, corresponding to PMU_LP_XTAL_STABLE_WAIT_SLOW_CLK_CYCLES */ +#define PMU_HP_PLL_STABLE_WAIT_CYCLES (2) +#define PMU_HP_ANALOG_WAIT_TARGET_CYCLES (2419) /* Fast OSC as PMU work clock source is about 154 us */ +#define PMU_HP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES (32) +#define PMU_HP_DIGITAL_POWER_UP_WAIT_CYCLES (32) +#define PMU_HP_MODEM_WAKEUP_WAIT_CYCLES (20700) /* Fast OSC as PMU work clock source is about 1318.6 us */ + +#define PMU_LP_WAKEUP_DELAY_CYCLES (0) +#define PMU_LP_XTAL_STABLE_WAIT_SLOW_CLK_CYCLES (30) /* Slow OSC as PMU slow clock source is about 201 us */ +#define PMU_LP_ANALOG_WAIT_TARGET_CYCLES (23) /* Slow OSC as PMU slow clock source is about 154 us */ +#define PMU_LP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES (32) /* Fast OSC as PMU work clock source is about 2 us */ +#define PMU_LP_DIGITAL_POWER_UP_WAIT_CYCLES (32) /* Fast OSC as PMU work clock source is about 2 us */ + + +typedef struct { + struct { + pmu_hp_power_t dig_power; + pmu_hp_power_t clk_power; + pmu_hp_power_t xtal; + } hp_sys; + struct { + pmu_lp_power_t dig_power; + pmu_lp_power_t clk_power; + pmu_lp_power_t xtal; + } lp_sys[PMU_MODE_LP_MAX]; +} pmu_sleep_power_config_t; + +#define PMU_SLEEP_POWER_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .dig_power = { \ + .vdd_spi_pd_en = ((pd_flags) & PMU_SLEEP_PD_VDDSDIO) ? 1 : 0, \ + .wifi_pd_en = ((pd_flags) & PMU_SLEEP_PD_MODEM) ? 1 : 0, \ + .cpu_pd_en = ((pd_flags) & PMU_SLEEP_PD_CPU) ? 1 : 0, \ + .aon_pd_en = ((pd_flags) & PMU_SLEEP_PD_AON) ? 1 : 0, \ + .top_pd_en = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 1 : 0, \ + .mem_pd_en = 0, \ + .mem_dslp = 0 \ + }, \ + .clk_power = { \ + .i2c_iso_en = 1, \ + .i2c_retention = 1, \ + .xpd_bb_i2c = 0, \ + .xpd_bbpll_i2c = 0, \ + .xpd_bbpll = 0 \ + }, \ + .xtal = { \ + .xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_ACTIVE] = { \ + .dig_power = { \ + .peri_pd_en = 0, \ + .mem_dslp = 0 \ + }, \ + .clk_power = { \ + .xpd_xtal32k = 1, \ + .xpd_rc32k = 1, \ + .xpd_fosc = 1 \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_SLEEP] = { \ + .dig_power = { \ + .peri_pd_en = ((pd_flags) & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \ + .mem_dslp = 1 \ + }, \ + .clk_power = { \ + .xpd_xtal32k = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \ + .xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 1, \ + .xpd_fosc = ((pd_flags) & PMU_SLEEP_PD_RC_FAST) ? 0 : 1 \ + }, \ + .xtal = { \ + .xpd_xtal = ((pd_flags) & PMU_SLEEP_PD_XTAL) ? 0 : 1, \ + } \ + } \ +} + +typedef struct { + struct { + pmu_hp_analog_t analog; + } hp_sys; + struct { + pmu_lp_analog_t analog; + } lp_sys[PMU_MODE_LP_MAX]; +} pmu_sleep_analog_config_t; + +#define PMU_SLEEP_ANALOG_LSLP_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .analog = { \ + .xpd_bias = 0x0, \ + .dbg_atten = 0x0, \ + .pd_cur = 1, \ + .bias_sleep = 1, \ + .slp_mem_xpd = 1, \ + .slp_logic_xpd = 1, \ + .slp_mem_dbias = 0x4, \ + .slp_logic_dbias = 0x4, \ + .xpd = 0, \ + .dbias = 0, \ + .drv_b = 0 \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_ACTIVE] = { \ + .analog = { \ + .slp_xpd = 0, \ + .slp_dbias = 0xc, \ + .xpd = 1, \ + .dbias = 0x1a, \ + .drv_b = 0x0 \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_SLEEP] = { \ + .analog = { \ + .xpd_bias = 0, \ + .dbg_atten = 0x0, \ + .pd_cur = 1, \ + .bias_sleep = 1, \ + .xpd = 0, \ + .dbias = 0x1c, \ + .slp_xpd = 1, \ + .slp_dbias = 0x3, \ + .drv_b = 0x0 \ + } \ + } \ +} + +#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .analog = { \ + .xpd_bias = 0, \ + .dbg_atten = 0x3, \ + .pd_cur = 1, \ + .bias_sleep = 1, \ + .xpd = 0, \ + .dbias = 0x15, \ + .slp_mem_xpd = 1, \ + .slp_mem_dbias = 0xc, \ + .slp_logic_xpd = 1, \ + .slp_logic_dbias = 0x5, \ + .drv_b = 0x18c \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_ACTIVE] = { \ + .analog = { \ + .xpd = 1, \ + .dbias = 0x1a, \ + .slp_xpd = 0, \ + .slp_dbias = 0, \ + .drv_b = 0x7 \ + } \ + }, \ + .lp_sys[PMU_MODE_LP_SLEEP] = { \ + .analog = { \ + .xpd_bias = 0, \ + .dbg_atten = 0xe, \ + .pd_cur = 1, \ + .bias_sleep = 1, \ + .xpd = 0, \ + .dbias = 0, \ + .slp_xpd = 1, \ + .slp_dbias = 0xe, \ + .drv_b = 0 \ + } \ + } \ +} + +typedef struct { + pmu_hp_param_t hp_sys; + pmu_lp_param_t lp_sys; + pmu_hp_lp_param_t hp_lp; +} pmu_sleep_param_config_t; + +#define PMU_SLEEP_PARAM_CONFIG_DEFAULT(pd_flags) { \ + .hp_sys = { \ + .min_slp_slow_clk_cycle = PMU_HP_SLEEP_MIN_SLOW_CLK_CYCLES, \ + .analog_wait_target_cycle = PMU_HP_ANALOG_WAIT_TARGET_CYCLES, \ + .digital_power_supply_wait_cycle = PMU_HP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES, \ + .digital_power_up_wait_cycle = PMU_HP_DIGITAL_POWER_UP_WAIT_CYCLES, \ + .modem_wakeup_wait_cycle = PMU_HP_MODEM_WAKEUP_WAIT_CYCLES, \ + .pll_stable_wait_cycle = PMU_HP_PLL_STABLE_WAIT_CYCLES \ + }, \ + .lp_sys = { \ + .min_slp_slow_clk_cycle = PMU_LP_SLEEP_MIN_SLOW_CLK_CYCLES, \ + .analog_wait_target_cycle = PMU_LP_ANALOG_WAIT_TARGET_CYCLES, \ + .digital_power_supply_wait_cycle = PMU_LP_DIGITAL_POWER_SUPPLY_WAIT_CYCLES, \ + .digital_power_up_wait_cycle = PMU_LP_DIGITAL_POWER_UP_WAIT_CYCLES \ + }, \ + .hp_lp = { \ + .xtal_stable_wait_slow_clk_cycle = PMU_LP_XTAL_STABLE_WAIT_SLOW_CLK_CYCLES \ + } \ +} + +typedef struct { + pmu_sleep_power_config_t power; + pmu_sleep_analog_config_t analog; + pmu_sleep_param_config_t param; +} pmu_sleep_config_t; + +typedef struct pmu_sleep_machine_constant { + struct { + uint16_t min_slp_time_ms; /* Mininum sleep protection time (unit: microsecond) */ + uint8_t wakeup_wait_cycle; /* Modem wakeup signal (WiFi MAC and BEACON wakeup) waits for the slow & fast clock domain synchronization and the wakeup signal triggers the PMU FSM switching wait cycle (unit: slow clock cycle) */ + uint8_t reserved0; + uint16_t reserved1; + uint16_t analog_wait_time_ms; /* LP LDO power up wait time (unit: microsecond) */ + uint16_t xtal_wait_stable_time_ms; /* Main XTAL stabilization wait time (unit: microsecond) */ + uint8_t clk_switch_cycle; /* Clock switch to FOSC (unit: slow clock cycle) */ + uint8_t clk_power_on_wait_cycle; /* Clock power on wait cycle (unit: slow clock cycle) */ + uint16_t power_supply_wait_time_ms; /* (unit: microsecond) */ + uint16_t power_up_wait_time_ms; /* (unit: microsecond) */ + } lp; + struct { + uint16_t min_slp_time_ms; /* Mininum sleep protection time (unit: microsecond) */ + uint16_t clock_domain_sync_time_ms; /* The Slow OSC clock domain synchronizes time with the Fast OSC domain, at least 4 slow clock cycles (unit: microsecond) */ + uint16_t system_dfs_up_work_time_ms; /* System DFS up scaling work time (unit: microsecond) */ + uint16_t analog_wait_time_ms; /* HP LDO power up wait time (unit: microsecond) */ + uint16_t power_supply_wait_time_ms; /* (unit: microsecond) */ + uint16_t power_up_wait_time_ms; /* (unit: microsecond) */ + uint16_t regdma_s2m_work_time_ms; /* Modem Subsystem (S2M switch) REGDMA restore time (unit: microsecond) */ + uint16_t regdma_s2a_work_time_ms; /* SOC System (Digital Peripheral + Modem Subsystem) REGDMA (S2A switch) restore time (unit: microsecond) */ + uint16_t regdma_m2a_work_time_ms; /* Digital Peripheral (M2A switch) REGDMA restore time (unit: microsecond) */ + uint16_t regdma_a2s_work_time_ms; /* SOC System (Digital Peripheral + Modem Subsystem) REGDMA (A2S switch) backup time (unit: microsecond) */ + uint16_t regdma_rf_on_work_time_ms; /* The REGDMA work time of RF enable (unit: microsecond) */ + uint16_t regdma_rf_off_work_time_ms; /* The REGDMA work time of RF disable (unit: microsecond) */ + uint16_t xtal_wait_stable_time_ms; /* Main XTAL stabilization wait time (unit: microsecond) */ + uint16_t pll_wait_stable_time_ms; /* PLL stabilization wait time (unit: microsecond) */ + } hp; +} pmu_sleep_machine_constant_t; + +#define PMU_SLEEP_MC_DEFAULT() { \ + .lp = { \ + .min_slp_time_ms = 450, \ + .wakeup_wait_cycle = 4, \ + .analog_wait_time_ms = 154, \ + .xtal_wait_stable_time_ms = 250, \ + .clk_switch_cycle = 1, \ + .clk_power_on_wait_cycle = 1, \ + .power_supply_wait_time_ms = 2, \ + .power_up_wait_time_ms = 2 \ + }, \ + .hp = { \ + .min_slp_time_ms = 450, \ + .clock_domain_sync_time_ms = 150, \ + .system_dfs_up_work_time_ms = 124, \ + .analog_wait_time_ms = 154, \ + .power_supply_wait_time_ms = 2, \ + .power_up_wait_time_ms = 2, \ + .regdma_s2m_work_time_ms = 172, \ + .regdma_s2a_work_time_ms = 430, \ + .regdma_m2a_work_time_ms = 265, \ + .regdma_a2s_work_time_ms = 338, \ + .regdma_rf_on_work_time_ms = 70, \ + .regdma_rf_off_work_time_ms = 23, \ + .xtal_wait_stable_time_ms = 250, \ + .pll_wait_stable_time_ms = 1 \ + } \ +} + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/port/esp32c6/rtc_init.c b/components/esp_hw_support/port/esp32c6/rtc_init.c deleted file mode 100644 index 0d418b5a6a..0000000000 --- a/components/esp_hw_support/port/esp32c6/rtc_init.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "soc/rtc.h" -#include "soc/pmu_reg.h" -#include "soc/regi2c_dig_reg.h" -#include "regi2c_ctrl.h" - -// TODO: IDF-5781 - -void rtc_init(rtc_config_t cfg) -{ - /* Peripheral reg i2c power up */ - SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB); - SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C); - - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); - REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, 25); - REG_SET_FIELD(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, 26); -} diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 22646afa9f..df56be72bb 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -24,7 +24,11 @@ #include "soc/soc_caps.h" #include "driver/rtc_io.h" #include "hal/rtc_io_hal.h" + +#if !SOC_PMU_SUPPORTED #include "hal/rtc_cntl_ll.h" +#include "hal/rtc_hal.h" +#endif #include "driver/uart.h" @@ -33,7 +37,6 @@ #include "regi2c_ctrl.h" //For `REGI2C_ANA_CALI_PD_WORKAROUND`, temp #include "hal/wdt_hal.h" -#include "hal/rtc_hal.h" #include "hal/uart_hal.h" #if SOC_TOUCH_SENSOR_SUPPORTED #include "hal/touch_sensor_hal.h" @@ -87,6 +90,7 @@ // Cycles for RTC Timer clock source (internal oscillator) calibrate #define RTC_CLK_SRC_CAL_CYCLES (10) +#define FAST_CLK_SRC_CAL_CYCLES (2000) /* ~ 127.4 us */ #ifdef CONFIG_IDF_TARGET_ESP32 #define DEFAULT_SLEEP_OUT_OVERHEAD_US (212) @@ -107,8 +111,8 @@ #define DEFAULT_SLEEP_OUT_OVERHEAD_US (118) #define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9) #elif CONFIG_IDF_TARGET_ESP32C6 -#define DEFAULT_SLEEP_OUT_OVERHEAD_US (118)// TODO: IDF-5348 -#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9) +#define DEFAULT_SLEEP_OUT_OVERHEAD_US (318) +#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (56) #elif CONFIG_IDF_TARGET_ESP32H2 #define DEFAULT_SLEEP_OUT_OVERHEAD_US (118)// TODO: IDF-6267 #define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9) @@ -154,6 +158,7 @@ typedef struct { uint32_t ccount_ticks_record; uint32_t sleep_time_overhead_out; uint32_t rtc_clk_cal_period; + uint32_t fast_clk_cal_period; uint64_t rtc_ticks_at_sleep_start; } sleep_config_t; @@ -161,7 +166,7 @@ typedef struct { _Static_assert(22 >= SOC_RTCIO_PIN_COUNT, "Chip has more RTCIOs than 22, should increase ext1_rtc_gpio_mask field size"); static sleep_config_t s_config = { - .pd_options = {[0 ... ESP_PD_DOMAIN_MAX - 1] = ESP_PD_OPTION_AUTO,}, + .pd_options = { [0 ... ESP_PD_DOMAIN_MAX - 1] = ESP_PD_OPTION_AUTO }, .ccount_ticks_record = 0, .sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US, .wakeup_triggers = 0 @@ -492,6 +497,12 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) } // Enter sleep +#if CONFIG_IDF_TARGET_ESP32C6 + pmu_sleep_config_t config; + pmu_sleep_init(pmu_sleep_config_default(&config, pd_flags, s_config.sleep_time_adjustment, + s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period, + deep_sleep), deep_sleep); +#else rtc_sleep_config_t config; rtc_sleep_get_default_config(sleep_flags, &config); rtc_sleep_init(config); @@ -500,6 +511,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) if (!deep_sleep) { rtc_sleep_low_init(s_config.rtc_clk_cal_period); } +#endif // Configure timer wakeup if (s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) { @@ -665,11 +677,11 @@ static esp_err_t esp_light_sleep_inner(uint32_t pd_flags, * x | 1 | pd flash with relaxed conditions(force_pd) * 1 | 0 | pd flash with strict conditions(safe_pd) */ -static inline bool can_power_down_vddsdio(const uint32_t vddsdio_pd_sleep_duration) +static inline bool can_power_down_vddsdio(uint32_t pd_flags, const uint32_t vddsdio_pd_sleep_duration) { bool force_pd = !(s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) || (s_config.sleep_duration > vddsdio_pd_sleep_duration); bool safe_pd = (s_config.wakeup_triggers == RTC_TIMER_TRIG_EN) && (s_config.sleep_duration > vddsdio_pd_sleep_duration); - return (s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] == ESP_PD_OPTION_OFF) ? force_pd : safe_pd; + return (pd_flags & RTC_SLEEP_PD_VDDSDIO) ? force_pd : safe_pd; } esp_err_t esp_light_sleep_start(void) @@ -743,6 +755,10 @@ esp_err_t esp_light_sleep_start(void) esp_clk_slowclk_cal_set(s_config.rtc_clk_cal_period); #endif +#if CONFIG_IDF_TARGET_ESP32C6 + s_config.fast_clk_cal_period = rtc_clk_cal(RTC_CAL_RC_FAST, FAST_CLK_SRC_CAL_CYCLES); +#endif + /* * Adjustment time consists of parts below: * 1. Hardware time waiting for internal 8M oscilate clock and XTAL; @@ -751,9 +767,15 @@ esp_err_t esp_light_sleep_start(void) * 4. Code execution time which can be measured; */ +#if CONFIG_IDF_TARGET_ESP32C6 + int sleep_time_sw_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US + sleep_time_overhead_in + s_config.sleep_time_overhead_out; + int sleep_time_hw_adjustment = pmu_sleep_calculate_hw_wait_time(pd_flags, s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period); + s_config.sleep_time_adjustment = sleep_time_sw_adjustment + sleep_time_hw_adjustment; +#else uint32_t rtc_cntl_xtl_buf_wait_slp_cycles = rtc_time_us_to_slowclk(RTC_CNTL_XTL_BUF_WAIT_SLP_US, s_config.rtc_clk_cal_period); s_config.sleep_time_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US + sleep_time_overhead_in + s_config.sleep_time_overhead_out + rtc_time_slowclk_to_us(rtc_cntl_xtl_buf_wait_slp_cycles + RTC_CNTL_CK8M_WAIT_SLP_CYCLES + RTC_CNTL_WAKEUP_DELAY_CYCLES, s_config.rtc_clk_cal_period); +#endif // Decide if VDD_SDIO needs to be powered down; // If it needs to be powered down, adjust sleep time. @@ -781,7 +803,7 @@ esp_err_t esp_light_sleep_start(void) flash_enable_time_us + LIGHT_SLEEP_MIN_TIME_US + s_config.sleep_time_adjustment + rtc_time_slowclk_to_us(RTC_MODULE_SLEEP_PREPARE_CYCLES, s_config.rtc_clk_cal_period)); - if (can_power_down_vddsdio(vddsdio_pd_sleep_duration)) { + if (can_power_down_vddsdio(pd_flags, vddsdio_pd_sleep_duration)) { if (s_config.sleep_time_overhead_out < flash_enable_time_us) { s_config.sleep_time_adjustment += flash_enable_time_us; } @@ -1384,9 +1406,27 @@ static uint32_t get_power_down_flags(void) s_config.pd_options[ESP_PD_DOMAIN_CPU] = ESP_PD_OPTION_ON; } #endif + /** + * VDD_SDIO power domain shall be kept on during the light sleep + * when CONFIG_ESP_SLEEP_POWER_DOWN_FLASH is not set and off when it is set. + * The application can still force the power domain to remain on by calling + * `esp_sleep_pd_config` before getting into light sleep mode. + * + * In deep sleep mode, the power domain will be turned off, regardless the + * value of this field. + */ +#if SOC_PM_SUPPORT_VDDSDIO_PD + if (s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] == ESP_PD_OPTION_AUTO) { +#ifndef CONFIG_ESP_SLEEP_POWER_DOWN_FLASH + s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] = ESP_PD_OPTION_ON; +#endif + } +#endif +#if SOC_PM_SUPPORT_XTAL_PD #ifdef CONFIG_IDF_TARGET_ESP32 s_config.pd_options[ESP_PD_DOMAIN_XTAL] = ESP_PD_OPTION_OFF; +#endif #endif const __attribute__((unused)) char *option_str[] = {"OFF", "ON", "AUTO(OFF)" /* Auto works as OFF */}; @@ -1424,31 +1464,39 @@ static uint32_t get_power_down_flags(void) pd_flags |= RTC_SLEEP_PD_CPU; } #endif - if (s_config.pd_options[ESP_PD_DOMAIN_RC_FAST] != ESP_PD_OPTION_ON) { - pd_flags |= RTC_SLEEP_PD_INT_8M; +#if SOC_PM_SUPPORT_XTAL32K_PD + if (s_config.pd_options[ESP_PD_DOMAIN_XTAL32K] != ESP_PD_OPTION_ON) { + pd_flags |= PMU_SLEEP_PD_XTAL32K; } +#endif +#if SOC_PM_SUPPORT_RC32K_PD + if (s_config.pd_options[ESP_PD_DOMAIN_RC32K] != ESP_PD_OPTION_ON) { + pd_flags |= PMU_SLEEP_PD_RC32K; + } +#endif +#if SOC_PM_SUPPORT_RC_FAST_PD + if (s_config.pd_options[ESP_PD_DOMAIN_RC_FAST] != ESP_PD_OPTION_ON) { +#if CONFIG_IDF_TARGET_ESP32C6 + pd_flags |= PMU_SLEEP_PD_FOSC; +#else + pd_flags |= RTC_SLEEP_PD_INT_8M; +#endif + } +#endif +#if SOC_PM_SUPPORT_XTAL_PD if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] != ESP_PD_OPTION_ON) { pd_flags |= RTC_SLEEP_PD_XTAL; } - - /** - * VDD_SDIO power domain shall be kept on during the light sleep - * when CONFIG_ESP_SLEEP_POWER_DOWN_FLASH is not set and off when it is set. - * The application can still force the power domain to remain on by calling - * `esp_sleep_pd_config` before getting into light sleep mode. - * - * In deep sleep mode, the power domain will be turned off, regardless the - * value of this field. - */ - if (s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] == ESP_PD_OPTION_AUTO) { -#ifndef CONFIG_ESP_SLEEP_POWER_DOWN_FLASH - s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] = ESP_PD_OPTION_ON; +#endif +#if SOC_PM_SUPPORT_VDDSDIO_PD + if (s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] != ESP_PD_OPTION_ON) { +#if CONFIG_IDF_TARGET_ESP32C6 + pd_flags |= PMU_SLEEP_PD_VDDSDIO; +#else + pd_flags |= RTC_SLEEP_PD_VDDSDIO; #endif } - - if (s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] != ESP_PD_OPTION_ON) { - pd_flags |= RTC_SLEEP_PD_VDDSDIO; - } +#endif #if ((defined CONFIG_RTC_CLK_SRC_EXT_CRYS) && (defined CONFIG_RTC_EXT_CRYST_ADDIT_CURRENT) && (SOC_PM_SUPPORT_RTC_PERIPH_PD)) if ((s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) == 0) { diff --git a/components/esp_system/fpga_overrides.c b/components/esp_system/fpga_overrides.c index 3e60824033..7439c7cfa3 100644 --- a/components/esp_system/fpga_overrides.c +++ b/components/esp_system/fpga_overrides.c @@ -23,6 +23,7 @@ #include "esp32c2/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32C6 #include "esp32c6/rom/rtc.h" +#include "esp_private/esp_pmu.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/rtc.h" #endif @@ -72,6 +73,9 @@ void IRAM_ATTR bootloader_fill_random(void *buffer, size_t length) void esp_clk_init(void) { s_warn(); +#if SOC_PMU_SUPPORTED + pmu_init(); +#endif } void esp_perip_clk_init(void) diff --git a/components/esp_system/port/soc/esp32c6/clk.c b/components/esp_system/port/soc/esp32c6/clk.c index a6f725fa83..6243a88141 100644 --- a/components/esp_system/port/soc/esp32c6/clk.c +++ b/components/esp_system/port/soc/esp32c6/clk.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,6 +23,7 @@ #include "esp_private/esp_modem_clock.h" #include "esp_private/periph_ctrl.h" #include "esp_private/esp_clk.h" +#include "esp_private/esp_pmu.h" #include "esp_rom_uart.h" #include "esp_rom_sys.h" @@ -42,13 +43,7 @@ static const char *TAG = "clk"; __attribute__((weak)) void esp_clk_init(void) { #if !CONFIG_IDF_ENV_FPGA - rtc_config_t cfg = RTC_CONFIG_DEFAULT(); - soc_reset_reason_t rst_reas; - rst_reas = esp_rom_get_reset_reason(0); - if (rst_reas == RESET_REASON_CHIP_POWER_ON) { - cfg.cali_ocode = 1; - } - rtc_init(cfg); + pmu_init(); assert(rtc_clk_xtal_freq_get() == RTC_XTAL_FREQ_40M); diff --git a/components/hal/esp32c6/rtc_cntl_hal.c b/components/hal/esp32c6/rtc_cntl_hal.c deleted file mode 100644 index ebcfb668f6..0000000000 --- a/components/hal/esp32c6/rtc_cntl_hal.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -// The HAL layer for RTC CNTL (common part) - -#include "soc/soc_caps.h" -#include "soc/lldesc.h" -#include "hal/dma_types.h" -#include "hal/rtc_hal.h" -#include "hal/assert.h" -#include "esp_attr.h" - -#define RTC_CNTL_HAL_LINK_BUF_SIZE_MIN (SOC_RTC_CNTL_CPU_PD_DMA_BLOCK_SIZE) /* The minimum size of dma link buffer */ - -typedef struct rtc_cntl_link_buf_conf { - uint32_t cfg[4]; /* 4 word for dma link buffer configuration */ -} rtc_cntl_link_buf_conf_t; - -void * rtc_cntl_hal_dma_link_init(void *elem, void *buff, int size, void *next) -{ - HAL_ASSERT(elem != NULL); - HAL_ASSERT(buff != NULL); - HAL_ASSERT(size >= RTC_CNTL_HAL_LINK_BUF_SIZE_MIN); - - lldesc_t *plink = (lldesc_t *)elem; - - plink->eof = next ? 0 : 1; - plink->owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA; - plink->size = size >> 4; /* in unit of 16 bytes */ - plink->length = size >> 4; - plink->buf = buff; - plink->offset = 0; - plink->sosf = 0; - STAILQ_NEXT(plink, qe) = next; - return (void *)plink; -} - -#if SOC_PM_SUPPORT_CPU_PD - -void rtc_cntl_hal_enable_cpu_retention(void *addr) -{ - // TODO: IDF-5718 has removed the retention feature -} - -void IRAM_ATTR rtc_cntl_hal_disable_cpu_retention(void *addr) -{ - // TODO: IDF-5718 has removed the retention feature -} - -#endif // SOC_PM_SUPPORT_CPU_PD diff --git a/components/soc/esp32c6/include/soc/rtc.h b/components/soc/esp32c6/include/soc/rtc.h index ed53ef2e02..a2bd881c3b 100644 --- a/components/soc/esp32c6/include/soc/rtc.h +++ b/components/soc/esp32c6/include/soc/rtc.h @@ -578,23 +578,6 @@ typedef struct { uint32_t light_slp_reject : 1; //!< enable light sleep reject } rtc_sleep_config_t; -#define RTC_SLEEP_PD_DIG BIT(0) //!< Deep sleep (power down digital domain) -#define RTC_SLEEP_PD_RTC_PERIPH BIT(1) //!< Power down RTC peripherals -#define RTC_SLEEP_PD_RTC_SLOW_MEM BIT(2) //!< Power down RTC SLOW memory -#define RTC_SLEEP_PD_RTC_FAST_MEM BIT(3) //!< Power down RTC FAST memory -#define RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU BIT(4) //!< RTC FAST and SLOW memories are automatically powered up and down along with the CPU -#define RTC_SLEEP_PD_VDDSDIO BIT(5) //!< Power down VDDSDIO regulator -#define RTC_SLEEP_PD_WIFI BIT(6) //!< Power down WIFI -#define RTC_SLEEP_PD_BT BIT(7) //!< Power down BT -#define RTC_SLEEP_PD_CPU BIT(8) //!< Power down CPU when in lightsleep, but not restart -#define RTC_SLEEP_PD_DIG_PERIPH BIT(9) //!< Power down DIG peripherals -#define RTC_SLEEP_PD_INT_8M BIT(10) //!< Power down Internal 8M oscillator -#define RTC_SLEEP_PD_XTAL BIT(11) //!< Power down main XTAL - -//These flags are not power domains, but will affect some sleep parameters -#define RTC_SLEEP_DIG_USE_8M BIT(16) -#define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17) -#define RTC_SLEEP_NO_ULTRA_LOW BIT(18) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature /** * Default initializer for rtc_sleep_config_t @@ -640,29 +623,6 @@ void rtc_sleep_low_init(uint32_t slowclk_period); */ void rtc_sleep_set_wakeup_time(uint64_t t); -#define RTC_GPIO_TRIG_EN BIT(2) //!< GPIO wakeup -#define RTC_TIMER_TRIG_EN BIT(3) //!< Timer wakeup -#define RTC_WIFI_TRIG_EN BIT(5) //!< WIFI wakeup (light sleep only) -#define RTC_UART0_TRIG_EN BIT(6) //!< UART0 wakeup (light sleep only) -#define RTC_UART1_TRIG_EN BIT(7) //!< UART1 wakeup (light sleep only) -#define RTC_BT_TRIG_EN BIT(10) //!< BT wakeup (light sleep only) -#define RTC_XTAL32K_DEAD_TRIG_EN BIT(12) -#define RTC_USB_TRIG_EN BIT(14) -#define RTC_BROWNOUT_DET_TRIG_EN BIT(16) - -/** - * RTC_SLEEP_REJECT_MASK records sleep reject sources supported by chip - */ -#define RTC_SLEEP_REJECT_MASK (RTC_GPIO_TRIG_EN | \ - RTC_TIMER_TRIG_EN | \ - RTC_WIFI_TRIG_EN | \ - RTC_UART0_TRIG_EN | \ - RTC_UART1_TRIG_EN | \ - RTC_BT_TRIG_EN | \ - RTC_XTAL32K_DEAD_TRIG_EN | \ - RTC_USB_TRIG_EN | \ - RTC_BROWNOUT_DET_TRIG_EN) - /** * @brief Enter deep or light sleep mode * From 1eb08db0df23ad0db2d408cdd111ec0a4b993c59 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Thu, 23 Dec 2021 17:20:52 +0800 Subject: [PATCH 05/16] lp_timer: lp_timer register address mapping structure redefinition --- .../soc/esp32c6/include/soc/lp_timer_struct.h | 387 ++++-------------- 1 file changed, 70 insertions(+), 317 deletions(-) diff --git a/components/soc/esp32c6/include/soc/lp_timer_struct.h b/components/soc/esp32c6/include/soc/lp_timer_struct.h index a45c0b407e..98961dc895 100644 --- a/components/soc/esp32c6/include/soc/lp_timer_struct.h +++ b/components/soc/esp32c6/include/soc/lp_timer_struct.h @@ -1,5 +1,5 @@ /** - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,346 +10,99 @@ extern "C" { #endif -/** Group: configure_register */ -/** Type of tar0_low register - * need_des - */ -typedef union { - struct { - /** main_timer_tar_low0 : R/W; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t main_timer_tar_low0:32; - }; - uint32_t val; -} lp_timer_tar0_low_reg_t; +typedef struct { + union { + struct { + uint32_t target_lo: 32; + }; + uint32_t val; + } lo; + union { + struct { + uint32_t target_hi: 16; + uint32_t reserved0: 15; + uint32_t enable : 1; + }; + uint32_t val; + } hi; +} lp_timer_target_reg_t; -/** Type of tar0_high register - * need_des - */ typedef union { struct { - /** main_timer_tar_high0 : R/W; bitpos: [15:0]; default: 0; - * need_des - */ - uint32_t main_timer_tar_high0:16; - uint32_t reserved_16:15; - /** main_timer_tar_en0 : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t main_timer_tar_en0:1; - }; - uint32_t val; -} lp_timer_tar0_high_reg_t; - -/** Type of tar1_low register - * need_des - */ -typedef union { - struct { - /** main_timer_tar_low1 : R/W; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t main_timer_tar_low1:32; - }; - uint32_t val; -} lp_timer_tar1_low_reg_t; - -/** Type of tar1_high register - * need_des - */ -typedef union { - struct { - /** main_timer_tar_high1 : R/W; bitpos: [15:0]; default: 0; - * need_des - */ - uint32_t main_timer_tar_high1:16; - uint32_t reserved_16:15; - /** main_timer_tar_en1 : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t main_timer_tar_en1:1; - }; - uint32_t val; -} lp_timer_tar1_high_reg_t; - -/** Type of update register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:28; - /** main_timer_update : WT; bitpos: [28]; default: 0; - * need_des - */ - uint32_t main_timer_update:1; - /** main_timer_xtal_off : R/W; bitpos: [29]; default: 0; - * need_des - */ - uint32_t main_timer_xtal_off:1; - /** main_timer_sys_stall : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t main_timer_sys_stall:1; - /** main_timer_sys_rst : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t main_timer_sys_rst:1; + uint32_t reserved0: 28; + uint32_t update : 1; + uint32_t xtal_off : 1; + uint32_t sys_stall: 1; + uint32_t sys_rst : 1; }; uint32_t val; } lp_timer_update_reg_t; -/** Type of main_buf0_low register - * need_des - */ +typedef struct { + union { + struct { + uint32_t counter_lo: 32; + }; + uint32_t val; + } lo; + union { + struct { + uint32_t counter_hi: 16; + uint32_t reserved0 : 16; + }; + uint32_t val; + } hi; +} lp_timer_counter_reg_t; + typedef union { struct { - /** main_timer_buf0_low : RO; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t main_timer_buf0_low:32; + uint32_t reserved0: 31; + uint32_t trigger : 1; }; uint32_t val; -} lp_timer_main_buf0_low_reg_t; +} lp_timer_overflow_reg_t; -/** Type of main_buf0_high register - * need_des - */ typedef union { struct { - /** main_timer_buf0_high : RO; bitpos: [15:0]; default: 0; - * need_des - */ - uint32_t main_timer_buf0_high:16; - uint32_t reserved_16:16; + uint32_t reserved0: 30; + uint32_t overflow : 1; + uint32_t alarm : 1; }; uint32_t val; -} lp_timer_main_buf0_high_reg_t; +} lp_timer_intr_reg_t; -/** Type of main_buf1_low register - * need_des - */ typedef union { struct { - /** main_timer_buf1_low : RO; bitpos: [31:0]; default: 0; - * need_des - */ - uint32_t main_timer_buf1_low:32; + uint32_t reserved0: 30; + uint32_t overflow : 1; + uint32_t alarm : 1; }; uint32_t val; -} lp_timer_main_buf1_low_reg_t; +} lp_timer_lp_intr_reg_t; -/** Type of main_buf1_high register - * need_des - */ -typedef union { - struct { - /** main_timer_buf1_high : RO; bitpos: [15:0]; default: 0; - * need_des - */ - uint32_t main_timer_buf1_high:16; - uint32_t reserved_16:16; - }; - uint32_t val; -} lp_timer_main_buf1_high_reg_t; +typedef volatile struct lp_timer_dev_t{ + lp_timer_target_reg_t target[2]; + lp_timer_update_reg_t update; + lp_timer_counter_reg_t counter[2]; + lp_timer_overflow_reg_t overflow; + lp_timer_intr_reg_t int_raw; + lp_timer_intr_reg_t int_st; + lp_timer_intr_reg_t int_en; + lp_timer_intr_reg_t int_clr; + lp_timer_lp_intr_reg_t lp_int_raw; + lp_timer_lp_intr_reg_t lp_int_st; + lp_timer_lp_intr_reg_t lp_int_en; + lp_timer_lp_intr_reg_t lp_int_clr; -/** Type of main_overflow register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:31; - /** main_timer_alarm_load : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t main_timer_alarm_load:1; - }; - uint32_t val; -} lp_timer_main_overflow_reg_t; + uint32_t reserved[237]; -/** Type of int_raw register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** overflow_raw : R/WTC/SS; bitpos: [30]; default: 0; - * need_des - */ - uint32_t overflow_raw:1; - /** soc_wakeup_int_raw : R/WTC/SS; bitpos: [31]; default: 0; - * need_des - */ - uint32_t soc_wakeup_int_raw:1; - }; - uint32_t val; -} lp_timer_int_raw_reg_t; - -/** Type of int_st register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** overflow_st : RO; bitpos: [30]; default: 0; - * need_des - */ - uint32_t overflow_st:1; - /** soc_wakeup_int_st : RO; bitpos: [31]; default: 0; - * need_des - */ - uint32_t soc_wakeup_int_st:1; - }; - uint32_t val; -} lp_timer_int_st_reg_t; - -/** Type of int_ena register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** overflow_ena : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t overflow_ena:1; - /** soc_wakeup_int_ena : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t soc_wakeup_int_ena:1; - }; - uint32_t val; -} lp_timer_int_ena_reg_t; - -/** Type of int_clr register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** overflow_clr : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t overflow_clr:1; - /** soc_wakeup_int_clr : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t soc_wakeup_int_clr:1; - }; - uint32_t val; -} lp_timer_int_clr_reg_t; - -/** Type of lp_int_raw register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** main_timer_overflow_lp_int_raw : R/WTC/SS; bitpos: [30]; default: 0; - * need_des - */ - uint32_t main_timer_overflow_lp_int_raw:1; - /** main_timer_lp_int_raw : R/WTC/SS; bitpos: [31]; default: 0; - * need_des - */ - uint32_t main_timer_lp_int_raw:1; - }; - uint32_t val; -} lp_timer_lp_int_raw_reg_t; - -/** Type of lp_int_st register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** main_timer_overflow_lp_int_st : RO; bitpos: [30]; default: 0; - * need_des - */ - uint32_t main_timer_overflow_lp_int_st:1; - /** main_timer_lp_int_st : RO; bitpos: [31]; default: 0; - * need_des - */ - uint32_t main_timer_lp_int_st:1; - }; - uint32_t val; -} lp_timer_lp_int_st_reg_t; - -/** Type of lp_int_ena register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** main_timer_overflow_lp_int_ena : R/W; bitpos: [30]; default: 0; - * need_des - */ - uint32_t main_timer_overflow_lp_int_ena:1; - /** main_timer_lp_int_ena : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t main_timer_lp_int_ena:1; - }; - uint32_t val; -} lp_timer_lp_int_ena_reg_t; - -/** Type of lp_int_clr register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:30; - /** main_timer_overflow_lp_int_clr : WT; bitpos: [30]; default: 0; - * need_des - */ - uint32_t main_timer_overflow_lp_int_clr:1; - /** main_timer_lp_int_clr : WT; bitpos: [31]; default: 0; - * need_des - */ - uint32_t main_timer_lp_int_clr:1; - }; - uint32_t val; -} lp_timer_lp_int_clr_reg_t; - -/** Type of date register - * need_des - */ -typedef union { - struct { - /** date : R/W; bitpos: [30:0]; default: 34672976; - * need_des - */ - uint32_t date:31; - /** clk_en : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t clk_en:1; - }; - uint32_t val; -} lp_timer_date_reg_t; - - -typedef struct lp_timer_dev_t { - volatile lp_timer_tar0_low_reg_t tar0_low; - volatile lp_timer_tar0_high_reg_t tar0_high; - volatile lp_timer_tar1_low_reg_t tar1_low; - volatile lp_timer_tar1_high_reg_t tar1_high; - volatile lp_timer_update_reg_t update; - volatile lp_timer_main_buf0_low_reg_t main_buf0_low; - volatile lp_timer_main_buf0_high_reg_t main_buf0_high; - volatile lp_timer_main_buf1_low_reg_t main_buf1_low; - volatile lp_timer_main_buf1_high_reg_t main_buf1_high; - volatile lp_timer_main_overflow_reg_t main_overflow; - volatile lp_timer_int_raw_reg_t int_raw; - volatile lp_timer_int_st_reg_t int_st; - volatile lp_timer_int_ena_reg_t int_ena; - volatile lp_timer_int_clr_reg_t int_clr; - volatile lp_timer_lp_int_raw_reg_t lp_int_raw; - volatile lp_timer_lp_int_st_reg_t lp_int_st; - volatile lp_timer_lp_int_ena_reg_t lp_int_ena; - volatile lp_timer_lp_int_clr_reg_t lp_int_clr; - uint32_t reserved_048[237]; - volatile lp_timer_date_reg_t date; + union { + struct { + uint32_t date : 31; + uint32_t clk_en: 1; + }; + uint32_t val; + } date; } lp_timer_dev_t; extern lp_timer_dev_t LP_TIMER; From c0ddaa592060da690985e4f96fa93ad5b6a32efc Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Thu, 12 Jan 2023 18:04:51 +0800 Subject: [PATCH 06/16] lp_timer: add hal-layer codes for esp32c6 --- .../port/esp32c6/CMakeLists.txt | 3 +- .../esp_hw_support/port/esp32c6/rtc_time.c | 4 +- components/esp_hw_support/sleep_wake_stub.c | 14 +++- components/hal/CMakeLists.txt | 4 ++ .../hal/esp32c6/include/hal/lp_timer_hal.h | 47 +++++++++++++ .../hal/esp32c6/include/hal/lp_timer_ll.h | 66 +++++++++++++++++++ components/hal/esp32c6/lp_timer_hal.c | 46 +++++++++++++ components/hal/include/hal/lp_timer_types.h | 32 +++++++++ .../esp32c6/include/soc/Kconfig.soc_caps.in | 8 +++ components/soc/esp32c6/include/soc/soc_caps.h | 4 ++ 10 files changed, 224 insertions(+), 4 deletions(-) create mode 100644 components/hal/esp32c6/include/hal/lp_timer_hal.h create mode 100644 components/hal/esp32c6/include/hal/lp_timer_ll.h create mode 100644 components/hal/esp32c6/lp_timer_hal.c create mode 100644 components/hal/include/hal/lp_timer_types.h diff --git a/components/esp_hw_support/port/esp32c6/CMakeLists.txt b/components/esp_hw_support/port/esp32c6/CMakeLists.txt index 33047b7052..92e9f981b4 100644 --- a/components/esp_hw_support/port/esp32c6/CMakeLists.txt +++ b/components/esp_hw_support/port/esp32c6/CMakeLists.txt @@ -4,7 +4,8 @@ set(srcs "rtc_clk_init.c" "pmu_init.c" "pmu_sleep.c" "rtc_time.c" - "chip_info.c") + "chip_info.c" + ) if(NOT BOOTLOADER_BUILD) list(APPEND srcs "sar_periph_ctrl.c" diff --git a/components/esp_hw_support/port/esp32c6/rtc_time.c b/components/esp_hw_support/port/esp32c6/rtc_time.c index 98bf1e6f82..483b9fc0bc 100644 --- a/components/esp_hw_support/port/esp32c6/rtc_time.c +++ b/components/esp_hw_support/port/esp32c6/rtc_time.c @@ -8,8 +8,8 @@ #include "esp32c6/rom/ets_sys.h" #include "soc/rtc.h" #include "soc/lp_timer_reg.h" +#include "hal/lp_timer_hal.h" #include "hal/clk_tree_ll.h" -#include "hal/rtc_cntl_ll.h" #include "soc/timer_group_reg.h" #include "esp_rom_sys.h" #include "assert.h" @@ -207,7 +207,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period) uint64_t rtc_time_get(void) { - return rtc_cntl_ll_get_rtc_time(); + return lp_timer_hal_get_cycle_count(0); } uint64_t rtc_light_slp_time_get(void) diff --git a/components/esp_hw_support/sleep_wake_stub.c b/components/esp_hw_support/sleep_wake_stub.c index bb6257a7b9..ba0c411de8 100644 --- a/components/esp_hw_support/sleep_wake_stub.c +++ b/components/esp_hw_support/sleep_wake_stub.c @@ -15,9 +15,14 @@ #include "soc/soc.h" #include "soc/rtc.h" #include "soc/soc_caps.h" -#include "hal/rtc_cntl_ll.h" #include "hal/uart_ll.h" +#if SOC_LP_TIMER_SUPPORTED +#include "hal/lp_timer_ll.h" +#include "hal/lp_timer_hal.h" +#else +#include "hal/rtc_cntl_ll.h" +#endif #include "sdkconfig.h" #include "esp_rom_uart.h" #include "esp_rom_sys.h" @@ -70,9 +75,16 @@ void RTC_IRAM_ATTR esp_wake_stub_uart_tx_wait_idle(uint8_t uart_no) void RTC_IRAM_ATTR esp_wake_stub_set_wakeup_time(uint64_t time_in_us) { +#if SOC_LP_TIMER_SUPPORTED + uint64_t rtc_count_delta = lp_timer_ll_time_to_count(time_in_us); + uint64_t rtc_curr_count = lp_timer_hal_get_cycle_count(0); + lp_timer_hal_set_alarm_target(0, rtc_curr_count + rtc_count_delta); +#else uint64_t rtc_count_delta = rtc_cntl_ll_time_to_count(time_in_us); uint64_t rtc_curr_count = rtc_cntl_ll_get_rtc_time(); rtc_cntl_ll_set_wakeup_timer(rtc_curr_count + rtc_count_delta); +#endif + } uint32_t RTC_IRAM_ATTR esp_wake_stub_get_wakeup_cause(void) diff --git a/components/hal/CMakeLists.txt b/components/hal/CMakeLists.txt index 4ed06a0139..da8ae89434 100644 --- a/components/hal/CMakeLists.txt +++ b/components/hal/CMakeLists.txt @@ -118,6 +118,10 @@ if(NOT BOOTLOADER_BUILD) list(APPEND srcs "${target}/modem_clock_hal.c") endif() + if(CONFIG_SOC_LP_TIMER_SUPPORTED) + list(APPEND srcs "${target}/lp_timer_hal.c") + endif() + if(CONFIG_SOC_BOD_SUPPORTED) list(APPEND srcs "brownout_hal.c") endif() diff --git a/components/hal/esp32c6/include/hal/lp_timer_hal.h b/components/hal/esp32c6/include/hal/lp_timer_hal.h new file mode 100644 index 0000000000..813b865fef --- /dev/null +++ b/components/hal/esp32c6/include/hal/lp_timer_hal.h @@ -0,0 +1,47 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include "soc/soc.h" +#include "hal/lp_timer_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * @brief set alarm target value + * + * @param timer_id timer num of lp_timer, 0 or 1 for esp32c6 + * + * @param value when counter reaches alarm value, alarm event will be triggered + */ +void lp_timer_hal_set_alarm_target(uint8_t timer_id, uint64_t value); + +/** + * @brief get current counter value + * + * @param timer_id timer num of lp_timer, 0 or 1 for esp32c6 + */ +uint64_t lp_timer_hal_get_cycle_count(uint8_t timer_id); + +/** + * @brief clear alarm interrupt status + */ +void lp_timer_hal_clear_alarm_intr_status(void); + +/** + * @brief clear overflow interrupt status + */ +void lp_timer_hal_clear_overflow_intr_status(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c6/include/hal/lp_timer_ll.h b/components/hal/esp32c6/include/hal/lp_timer_ll.h new file mode 100644 index 0000000000..7f2aa34460 --- /dev/null +++ b/components/hal/esp32c6/include/hal/lp_timer_ll.h @@ -0,0 +1,66 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for ESP32-C6 LP_Timer register operations + +#pragma once + +#include +#include "soc/soc.h" +#include "soc/rtc.h" +#include "soc/lp_timer_struct.h" +#include "soc/lp_aon_reg.h" +#include "hal/lp_timer_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +FORCE_INLINE_ATTR void lp_timer_ll_set_alarm_target(lp_timer_dev_t *dev, uint8_t timer_id, uint64_t value) +{ + dev->target[timer_id].hi.target_hi = (value >> 32) & 0xFFFF; + dev->target[timer_id].lo.target_lo = value & 0xFFFFFFFF; +} + +FORCE_INLINE_ATTR void lp_timer_ll_set_target_enable(lp_timer_dev_t *dev, uint8_t timer_id, bool en) +{ + dev->target[timer_id].hi.enable = en; +} + +FORCE_INLINE_ATTR uint32_t lp_timer_ll_get_counter_value_low(lp_timer_dev_t *dev, uint8_t timer_id) +{ + return dev->counter[timer_id].lo.counter_lo; +} + +FORCE_INLINE_ATTR uint32_t lp_timer_ll_get_counter_value_high(lp_timer_dev_t *dev, uint8_t timer_id) +{ + return dev->counter[timer_id].hi.counter_hi; +} + +FORCE_INLINE_ATTR void lp_timer_ll_counter_snapshot(lp_timer_dev_t *dev) +{ + dev->update.update = 1; +} + +FORCE_INLINE_ATTR void lp_timer_ll_clear_alarm_intr_status(lp_timer_dev_t *dev) +{ + dev->int_clr.alarm = 1; +} + +FORCE_INLINE_ATTR void lp_timer_ll_clear_overflow_intr_status(lp_timer_dev_t *dev) +{ + dev->int_clr.overflow = 1; +} + +FORCE_INLINE_ATTR uint64_t lp_timer_ll_time_to_count(uint64_t time_in_us) +{ + uint32_t slow_clk_value = REG_READ(LP_AON_STORE1_REG); + return ((time_in_us * (1 << RTC_CLK_CAL_FRACT)) / slow_clk_value); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/hal/esp32c6/lp_timer_hal.c b/components/hal/esp32c6/lp_timer_hal.c new file mode 100644 index 0000000000..caba3725f8 --- /dev/null +++ b/components/hal/esp32c6/lp_timer_hal.c @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "sdkconfig.h" +#include "esp_attr.h" +#include "soc/soc.h" +#include "hal/lp_timer_ll.h" + +static DRAM_ATTR struct { + lp_timer_dev_t *dev; +} lp_timer_context = { .dev = &LP_TIMER }; + +void IRAM_ATTR lp_timer_hal_set_alarm_target(uint8_t timer_id, uint64_t value) +{ + lp_timer_ll_clear_alarm_intr_status(lp_timer_context.dev); + lp_timer_ll_set_alarm_target(lp_timer_context.dev, timer_id, value); + lp_timer_ll_set_target_enable(lp_timer_context.dev, timer_id, true); +} + +uint64_t IRAM_ATTR lp_timer_hal_get_cycle_count(uint8_t timer_id) +{ + lp_timer_ll_counter_snapshot(lp_timer_context.dev); + uint32_t lo = lp_timer_ll_get_counter_value_low(lp_timer_context.dev, timer_id); + uint32_t hi = lp_timer_ll_get_counter_value_high(lp_timer_context.dev, timer_id); + lp_timer_counter_value_t result = { + .lo = lo, + .hi = hi + }; + return result.val; +} + +void IRAM_ATTR lp_timer_hal_clear_alarm_intr_status(void) +{ + lp_timer_ll_clear_alarm_intr_status(lp_timer_context.dev); +} + +void IRAM_ATTR lp_timer_hal_clear_overflow_intr_status(void) +{ + lp_timer_ll_clear_overflow_intr_status(lp_timer_context.dev); +} diff --git a/components/hal/include/hal/lp_timer_types.h b/components/hal/include/hal/lp_timer_types.h new file mode 100644 index 0000000000..ebb808ca50 --- /dev/null +++ b/components/hal/include/hal/lp_timer_types.h @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "soc/soc_caps.h" + +/** + * @brief The structure of the counter value in lower power timer + */ +typedef struct { + union { + struct { + uint32_t lo: SOC_LP_TIMER_BIT_WIDTH_LO; /*!< Low part of counter value */ + uint32_t hi: SOC_LP_TIMER_BIT_WIDTH_HI; /*!< High part of counter value */ + uint32_t reserved: 16; + }; + uint64_t val; /*!< counter value */ + }; +} lp_timer_counter_value_t; + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index f7ffb86ce6..c7781b8e8d 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -839,6 +839,14 @@ config SOC_SYSTIMER_SUPPORT_ETM bool default y +config SOC_LP_TIMER_BIT_WIDTH_LO + int + default 32 + +config SOC_LP_TIMER_BIT_WIDTH_HI + int + default 16 + config SOC_TIMER_GROUPS int default 2 diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 66d625c26a..d1dd2a4cd9 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -361,6 +361,10 @@ #define SOC_SYSTIMER_ALARM_MISS_COMPENSATE 1 // Systimer peripheral can generate interrupt immediately if t(target) > t(current) #define SOC_SYSTIMER_SUPPORT_ETM 1 // Systimer comparator can generate ETM event +/*-------------------------- LP_TIMER CAPS ----------------------------------*/ +#define SOC_LP_TIMER_BIT_WIDTH_LO 32 // Bit width of lp_timer low part +#define SOC_LP_TIMER_BIT_WIDTH_HI 16 // Bit width of lp_timer high part + /*--------------------------- TIMER GROUP CAPS ---------------------------------------*/ #define SOC_TIMER_GROUPS (2) #define SOC_TIMER_GROUP_TIMERS_PER_GROUP (1U) From 0fb408cc6876577f692ec164bade3c07c1c02a0e Mon Sep 17 00:00:00 2001 From: cje Date: Wed, 11 Jan 2023 13:40:06 +0800 Subject: [PATCH 07/16] pmu active state ICG map initialize and modify i2c master force enable to enable --- .../subproject/main/ld/esp32c6/bootloader.ld | 2 +- .../src/esp32c6/bootloader_esp32c6.c | 6 ++-- .../port/esp32c6/rtc_clk_init.c | 35 ++++++++++++++++++- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/components/bootloader/subproject/main/ld/esp32c6/bootloader.ld b/components/bootloader/subproject/main/ld/esp32c6/bootloader.ld index 5702fd715c..ba4a1b2af9 100644 --- a/components/bootloader/subproject/main/ld/esp32c6/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32c6/bootloader.ld @@ -27,7 +27,7 @@ bootloader_usable_dram_end = 0x4087c610; bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */ bootloader_dram_seg_len = 0x5000; bootloader_iram_loader_seg_len = 0x7000; -bootloader_iram_seg_len = 0x2000; +bootloader_iram_seg_len = 0x2100; /* Start of the lower region is determined by region size and the end of the higher region */ bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead; diff --git a/components/bootloader_support/src/esp32c6/bootloader_esp32c6.c b/components/bootloader_support/src/esp32c6/bootloader_esp32c6.c index eee533e640..105438bae6 100644 --- a/components/bootloader_support/src/esp32c6/bootloader_esp32c6.c +++ b/components/bootloader_support/src/esp32c6/bootloader_esp32c6.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -237,8 +237,8 @@ static inline void bootloader_hardware_init(void) esp_rom_spiflash_fix_dummylen(1, 1); #endif - // TODO: IDF-5990 need update, enable i2c mst clk by force on temporarily - SET_PERI_REG_MASK(MODEM_LPCON_CLK_CONF_FORCE_ON_REG, MODEM_LPCON_CLK_I2C_MST_FO); + /* Enable analog i2c master clock */ + SET_PERI_REG_MASK(MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN); SET_PERI_REG_MASK(MODEM_LPCON_I2C_MST_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_SEL_160M); } diff --git a/components/esp_hw_support/port/esp32c6/rtc_clk_init.c b/components/esp_hw_support/port/esp32c6/rtc_clk_init.c index 78bb356bcb..a605456a6a 100644 --- a/components/esp_hw_support/port/esp32c6/rtc_clk_init.c +++ b/components/esp_hw_support/port/esp32c6/rtc_clk_init.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,14 +19,47 @@ #include "esp_hw_log.h" #include "sdkconfig.h" #include "esp_rom_uart.h" +#include "esp_private/esp_pmu.h" #include "hal/clk_tree_ll.h" +#include "hal/pmu_ll.h" +#include "hal/modem_syscon_ll.h" +#include "hal/modem_lpcon_ll.h" static const char *TAG = "rtc_clk_init"; +/** + * Initialize the ICG map of some modem clock domains in the PMU_ACTIVE state + * + * A pre-initialization interface is used to initialize the ICG map of the + * MODEM_APB, I2C_MST and LP_APB clock domains in the PMU_ACTIVE state, and + * disable the clock gating of these clock domains in the PMU_ACTIVE state, + * because the system clock source (PLL) in the system boot up process needs + * to use the i2c master peripheral. + * + * ICG map of all modem clock domains under different power states (PMU_ACTIVE, + * PMU_MODEM and PMU_SLEEP) will be initialized in esp_perip_clk_init(). + */ +static void rtc_clk_modem_clock_domain_active_state_icg_map_preinit(void) +{ + /* Configure modem ICG code in PMU_ACTIVE state */ + pmu_ll_hp_set_icg_modem(&PMU, PMU_MODE_HP_ACTIVE, PMU_HP_ICG_MODEM_CODE_ACTIVE); + + /* Disable clock gating for MODEM_APB, I2C_MST and LP_APB clock domains in PMU_ACTIVE state */ + modem_syscon_ll_set_modem_apb_icg_bitmap(&MODEM_SYSCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE)); + modem_lpcon_ll_set_i2c_master_icg_bitmap(&MODEM_LPCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE)); + modem_lpcon_ll_set_lp_apb_icg_bitmap(&MODEM_LPCON, BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE)); + + /* Software trigger force update modem ICG code and ICG switch */ + pmu_ll_imm_update_dig_icg_modem_code(&PMU, true); + pmu_ll_imm_update_dig_icg_switch(&PMU, true); +} + void rtc_clk_init(rtc_clk_config_t cfg) { rtc_cpu_freq_config_t old_config, new_config; + rtc_clk_modem_clock_domain_active_state_icg_map_preinit(); + /* Set tuning parameters for RC_FAST, RC_SLOW, and RC32K clocks. * Note: this doesn't attempt to set the clocks to precise frequencies. * Instead, we calibrate these clocks against XTAL frequency later, when necessary. From 2b5618606be21747016fd70f0cd1bd75d79ca7ab Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Wed, 11 Jan 2023 13:49:47 +0800 Subject: [PATCH 08/16] pmu: clean modem clock pmu related code --- .../include/esp_private/esp_pmu.h | 8 ++++ components/esp_hw_support/modem_clock.c | 44 +++++++------------ .../esp_hw_support/port/esp32c6/pmu_param.c | 6 +-- 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/components/esp_hw_support/include/esp_private/esp_pmu.h b/components/esp_hw_support/include/esp_private/esp_pmu.h index ce04a4bb32..7179e9cc33 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -116,6 +116,14 @@ typedef enum pmu_sleep_regdma_entry { PMU_SLEEP_REGDMA_ENTRY_MAX } pmu_sleep_regdma_entry_t; +/** + * @brief PMU ICG modem code of HP system + */ +typedef enum { + PMU_HP_ICG_MODEM_CODE_SLEEP = 0, + PMU_HP_ICG_MODEM_CODE_MODEM = 1, + PMU_HP_ICG_MODEM_CODE_ACTIVE = 2, +} pmu_hp_icg_modem_mode_t; /** diff --git a/components/esp_hw_support/modem_clock.c b/components/esp_hw_support/modem_clock.c index cd9773ad41..2c66910b9c 100644 --- a/components/esp_hw_support/modem_clock.c +++ b/components/esp_hw_support/modem_clock.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,7 @@ #include "freertos/FreeRTOS.h" #include "hal/clk_gate_ll.h" #include "esp_private/esp_modem_clock.h" +#include "esp_private/esp_pmu.h" #include "esp_sleep.h" // Please define the frequently called modules in the low bit, @@ -136,30 +137,25 @@ modem_clock_context_t * __attribute__((weak)) IRAM_ATTR MODEM_CLOCK_instance(voi return &modem_clock_context; } - -// TODO: IDF-5351: move to esp_pmu.h after support pmu driver -#define PMU_SLEEP 0 -#define PMU_MODEM 1 -#define PMU_ACTIVE 2 -#define SLEEP_MODE BIT(PMU_SLEEP) -#define MODEM_MODE BIT(PMU_MODEM) -#define ACTIVE_MODE BIT(PMU_ACTIVE) - static void IRAM_ATTR modem_clock_domain_power_state_icg_map_init(modem_clock_context_t *ctx) { + #define ICG_NOGATING_SLEEP (BIT(PMU_HP_ICG_MODEM_CODE_SLEEP)) + #define ICG_NOGATING_MODEM (BIT(PMU_HP_ICG_MODEM_CODE_MODEM)) + #define ICG_NOGATING_ACTIVE (BIT(PMU_HP_ICG_MODEM_CODE_ACTIVE)) + /* the ICG code's bit 0, 1 and 2 indicates the ICG state * of pmu SLEEP, MODEM and ACTIVE mode respectively */ const uint32_t code[MODEM_CLOCK_DOMAIN_MAX] = { - [MODEM_CLOCK_DOMAIN_MODEM_APB] = MODEM_MODE | ACTIVE_MODE, - [MODEM_CLOCK_DOMAIN_MODEM_PERIPH] = ACTIVE_MODE, - [MODEM_CLOCK_DOMAIN_WIFI] = MODEM_MODE | ACTIVE_MODE, - [MODEM_CLOCK_DOMAIN_BT] = MODEM_MODE | ACTIVE_MODE, - [MODEM_CLOCK_DOMAIN_FE] = MODEM_MODE | ACTIVE_MODE, - [MODEM_CLOCK_DOMAIN_IEEE802154] = MODEM_MODE | ACTIVE_MODE, - [MODEM_CLOCK_DOMAIN_LP_APB] = MODEM_MODE | ACTIVE_MODE, - [MODEM_CLOCK_DOMAIN_I2C_MASTER] = MODEM_MODE | ACTIVE_MODE, - [MODEM_CLOCK_DOMAIN_COEX] = MODEM_MODE | ACTIVE_MODE, - [MODEM_CLOCK_DOMAIN_WIFIPWR] = MODEM_MODE | ACTIVE_MODE, + [MODEM_CLOCK_DOMAIN_MODEM_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_MODEM_PERIPH] = ICG_NOGATING_ACTIVE, + [MODEM_CLOCK_DOMAIN_WIFI] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_BT] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_FE] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_IEEE802154] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_LP_APB] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_I2C_MASTER] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_COEX] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, + [MODEM_CLOCK_DOMAIN_WIFIPWR] = ICG_NOGATING_ACTIVE | ICG_NOGATING_MODEM, }; for (modem_clock_domain_t domain = MODEM_CLOCK_DOMAIN_MODEM_APB; domain < MODEM_CLOCK_DOMAIN_MAX; domain++) { modem_clock_hal_set_clock_domain_icg_bitmap(ctx->hal, domain, code[domain]); @@ -167,16 +163,8 @@ static void IRAM_ATTR modem_clock_domain_power_state_icg_map_init(modem_clock_co } -#include "soc/pmu_reg.h" void modem_clock_domain_pmu_state_icg_map_init(void) { - // Set modem clock ICG code map, should implement with pmu driver // TODO: IDF-5351 - REG_SET_FIELD(PMU_HP_SLEEP_ICG_MODEM_REG, PMU_HP_SLEEP_DIG_ICG_MODEM_CODE, PMU_SLEEP); - REG_SET_FIELD(PMU_HP_MODEM_ICG_MODEM_REG, PMU_HP_MODEM_DIG_ICG_MODEM_CODE, PMU_MODEM); - REG_SET_FIELD(PMU_HP_ACTIVE_ICG_MODEM_REG, PMU_HP_ACTIVE_DIG_ICG_MODEM_CODE, PMU_ACTIVE); - REG_SET_BIT(PMU_IMM_MODEM_ICG_REG, PMU_UPDATE_DIG_ICG_MODEM_EN); - REG_SET_BIT(PMU_IMM_SLEEP_SYSCLK_REG, PMU_UPDATE_DIG_ICG_SWITCH); - modem_clock_domain_power_state_icg_map_init(MODEM_CLOCK_instance()); } diff --git a/components/esp_hw_support/port/esp32c6/pmu_param.c b/components/esp_hw_support/port/esp32c6/pmu_param.c index 0cd70d4985..1121e91109 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_param.c +++ b/components/esp_hw_support/port/esp32c6/pmu_param.c @@ -98,7 +98,7 @@ const pmu_hp_system_power_param_t * pmu_hp_system_power_param_default(pmu_hp_mod .icg_func = 0xffffffff, \ .icg_apb = 0xffffffff, \ .icg_modem = { \ - .code = 2 \ + .code = PMU_HP_ICG_MODEM_CODE_ACTIVE \ }, \ .sysclk = { \ .dig_sysclk_nodiv = 0, \ @@ -113,7 +113,7 @@ const pmu_hp_system_power_param_t * pmu_hp_system_power_param_default(pmu_hp_mod .icg_func = 0, \ .icg_apb = 0, \ .icg_modem = { \ - .code = 1 \ + .code = PMU_HP_ICG_MODEM_CODE_MODEM \ }, \ .sysclk = { \ .dig_sysclk_nodiv = 0, \ @@ -128,7 +128,7 @@ const pmu_hp_system_power_param_t * pmu_hp_system_power_param_default(pmu_hp_mod .icg_func = 0, \ .icg_apb = 0, \ .icg_modem = { \ - .code = 0 \ + .code = PMU_HP_ICG_MODEM_CODE_SLEEP \ }, \ .sysclk = { \ .dig_sysclk_nodiv = 0, \ From 0f6cda1dd30a550c52c656ebb6aaa87d0b22121c Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Mon, 7 Nov 2022 22:10:22 +0800 Subject: [PATCH 09/16] Power Management: support DFS --- components/driver/twai.c | 4 ++-- components/esp_pm/Kconfig | 8 ++++---- components/esp_pm/pm_impl.c | 7 +++++++ components/soc/esp32c6/include/soc/soc.h | 1 + examples/wifi/itwt/main/itwt.c | 8 +++----- examples/wifi/power_save/main/power_save.c | 2 ++ 6 files changed, 19 insertions(+), 11 deletions(-) diff --git a/components/driver/twai.c b/components/driver/twai.c index 418f4b24fe..40092377a1 100644 --- a/components/driver/twai.c +++ b/components/driver/twai.c @@ -470,7 +470,7 @@ esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_ p_twai_obj_dummy->module = twai_controller_periph_signals.controllers[controller_id].module; -#ifdef CONFIG_PM_ENABLE +#if CONFIG_PM_ENABLE && SOC_TWAI_CLK_SUPPORT_APB if (clk_src == TWAI_CLK_SRC_APB) { // TODO: pm_lock name should also reflect the controller ID ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "twai", &(p_twai_obj_dummy->pm_lock)); @@ -478,7 +478,7 @@ esp_err_t twai_driver_install(const twai_general_config_t *g_config, const twai_ goto err; } } -#endif //CONFIG_PM_ENABLE +#endif //CONFIG_PM_ENABLE && SOC_TWAI_CLK_SUPPORT_APB //Initialize TWAI peripheral registers, and allocate interrupt TWAI_ENTER_CRITICAL(); diff --git a/components/esp_pm/Kconfig b/components/esp_pm/Kconfig index a92fa47ad0..2e073b0b3a 100644 --- a/components/esp_pm/Kconfig +++ b/components/esp_pm/Kconfig @@ -2,10 +2,10 @@ menu "Power Management" config PM_ENABLE bool "Support for power management" # SMP FreeRTOS currently does not support power management IDF-4997 - # ESP32C6 currently does not support power management IDF-5347 IDF-6270 - # Note. Disabling this option for C6 will also cause all sdkconfig.release test cases run without pm enabled - # ORed with __DOXYGEN__ to pass C6 docs build, need to remove when pm is supported on C6 - depends on (!FREERTOS_SMP && !IDF_TARGET_ESP32C6 && !IDF_TARGET_ESP32H2) || __DOXYGEN__ + # ESP32H2 currently does not support power management IDF-6270 + # Note. Disabling this option for H2 will also cause all sdkconfig.release test cases run without pm enabled + # ORed with __DOXYGEN__ to pass H2 docs build, need to remove when pm is supported on H2 + depends on (!FREERTOS_SMP && !IDF_TARGET_ESP32H2) || __DOXYGEN__ default n help If enabled, application is compiled with support for power management. diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 4384fa1eb1..3d5b435597 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -288,6 +288,13 @@ esp_err_t esp_pm_configure(const void* vconfig) */ apb_max_freq = 80; } +#elif CONFIG_IDF_TARGET_ESP32C6 + /* Maximum SOC APB clock frequency is 40 MHz, maximum Modem (WiFi, + * Bluetooth, etc..) APB clock frequency is 80 MHz */ + const int soc_apb_clk_freq = esp_clk_apb_freq() / MHZ; + const int modem_apb_clk_freq = MODEM_APB_CLK_FREQ / MHZ; + const int apb_clk_freq = MAX(soc_apb_clk_freq, modem_apb_clk_freq); + int apb_max_freq = MIN(max_freq_mhz, apb_clk_freq); /* CPU frequency in APB_MAX mode */ #else int apb_max_freq = MIN(max_freq_mhz, 80); /* CPU frequency in APB_MAX mode */ #endif diff --git a/components/soc/esp32c6/include/soc/soc.h b/components/soc/esp32c6/include/soc/soc.h index e782be8996..8adccb044b 100644 --- a/components/soc/esp32c6/include/soc/soc.h +++ b/components/soc/esp32c6/include/soc/soc.h @@ -141,6 +141,7 @@ #define EFUSE_CLK_FREQ_ROM ( 20*1000000) #define CPU_CLK_FREQ APB_CLK_FREQ #define APB_CLK_FREQ ( 40*1000000 ) +#define MODEM_APB_CLK_FREQ ( 80*1000000 ) #define REF_CLK_FREQ ( 1000000 ) #define RTC_CLK_FREQ (20*1000000) #define XTAL_CLK_FREQ (40*1000000) diff --git a/examples/wifi/itwt/main/itwt.c b/examples/wifi/itwt/main/itwt.c index ab6ee1d8e7..8ce6db7e26 100644 --- a/examples/wifi/itwt/main/itwt.c +++ b/examples/wifi/itwt/main/itwt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -27,6 +27,7 @@ #include "cmd_system.h" #include "wifi_cmd.h" #include "esp_wifi_he.h" +#include "esp_pm.h" /******************************************************* * Constants @@ -244,10 +245,7 @@ void app_main(void) } // TODO: WIFI-5150 -#if CONFIG_PM_ENABLE - io_toggle_pmu_internal_signal_map_to_io_init(); - io_toggle_gpio_init(); - +#if CONFIG_PM_ENABLE && 0 sleep_clock_system_retention_init(); sleep_clock_modem_retention_init(); sleep_peripheral_retention_init(); diff --git a/examples/wifi/power_save/main/power_save.c b/examples/wifi/power_save/main/power_save.c index 653e67607c..bd39b47d76 100644 --- a/examples/wifi/power_save/main/power_save.c +++ b/examples/wifi/power_save/main/power_save.c @@ -105,6 +105,8 @@ void app_main(void) esp_pm_config_esp32s3_t pm_config = { #elif CONFIG_IDF_TARGET_ESP32C2 esp_pm_config_esp32c2_t pm_config = { +#elif CONFIG_IDF_TARGET_ESP32C6 + esp_pm_config_esp32c6_t pm_config = { #endif .max_freq_mhz = CONFIG_EXAMPLE_MAX_CPU_FREQ_MHZ, .min_freq_mhz = CONFIG_EXAMPLE_MIN_CPU_FREQ_MHZ, From 02f5df3b3ed31f397f09909fc524bf5d356a4d02 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Fri, 16 Dec 2022 11:25:55 +0800 Subject: [PATCH 10/16] Power Management: added protection to the configuration of each power domain --- components/esp_hw_support/sleep_modes.c | 90 ++++++++++++++----------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index df56be72bb..f61b7bac96 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -145,7 +145,12 @@ extern void periph_inform_out_light_sleep_overhead(uint32_t out_light_sleep_time * Internal structure which holds all requested deep sleep parameters */ typedef struct { - esp_sleep_pd_option_t pd_options[ESP_PD_DOMAIN_MAX]; + struct { + esp_sleep_pd_option_t pd_option; + int16_t refs; + uint16_t reserved; /* reserved for 4 bytes aligned */ + } domain[ESP_PD_DOMAIN_MAX]; + portMUX_TYPE lock; uint64_t sleep_duration; uint32_t wakeup_triggers : 15; uint32_t ext1_trigger_mode : 1; @@ -166,7 +171,13 @@ typedef struct { _Static_assert(22 >= SOC_RTCIO_PIN_COUNT, "Chip has more RTCIOs than 22, should increase ext1_rtc_gpio_mask field size"); static sleep_config_t s_config = { - .pd_options = { [0 ... ESP_PD_DOMAIN_MAX - 1] = ESP_PD_OPTION_AUTO }, + .domain = { + [0 ... ESP_PD_DOMAIN_MAX - 1] = { + .pd_option = ESP_PD_OPTION_AUTO, + .refs = 0 + } + }, + .lock = portMUX_INITIALIZER_UNLOCKED, .ccount_ticks_record = 0, .sleep_time_overhead_out = DEFAULT_SLEEP_OUT_OVERHEAD_US, .wakeup_triggers = 0 @@ -686,9 +697,7 @@ static inline bool can_power_down_vddsdio(uint32_t pd_flags, const uint32_t vdds esp_err_t esp_light_sleep_start(void) { -#if CONFIG_IDF_TARGET_ESP32C6 - return ESP_ERR_NOT_SUPPORTED; // TODO: WIFI-5150 -#else + s_config.ccount_ticks_record = esp_cpu_get_cycle_count(); #if CONFIG_ESP_TASK_WDT_USE_ESP_TIMER esp_err_t timerret = ESP_OK; @@ -696,9 +705,7 @@ esp_err_t esp_light_sleep_start(void) timerret = esp_task_wdt_stop(); #endif // CONFIG_ESP_TASK_WDT_USE_ESP_TIMER - s_config.ccount_ticks_record = esp_cpu_get_cycle_count(); - static portMUX_TYPE light_sleep_lock = portMUX_INITIALIZER_UNLOCKED; - portENTER_CRITICAL(&light_sleep_lock); + portENTER_CRITICAL(&s_config.lock); /* Note: We are about to stall the other CPU via the esp_ipc_isr_stall_other_cpu(). However, there is a chance of deadlock if after stalling the other CPU, we attempt to take spinlocks already held by the other CPU that is. @@ -878,8 +885,7 @@ esp_err_t esp_light_sleep_start(void) wdt_hal_disable(&rtc_wdt_ctx); wdt_hal_write_protect_enable(&rtc_wdt_ctx); } - portEXIT_CRITICAL(&light_sleep_lock); - s_config.sleep_time_overhead_out = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL); + portEXIT_CRITICAL(&s_config.lock); #if CONFIG_ESP_TASK_WDT_USE_ESP_TIMER /* Restart the Task Watchdog timer as it was stopped before sleeping. */ @@ -888,6 +894,7 @@ esp_err_t esp_light_sleep_start(void) } #endif // CONFIG_ESP_TASK_WDT_USE_ESP_TIMER + s_config.sleep_time_overhead_out = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL); return err; #endif } @@ -1114,7 +1121,7 @@ static void ext1_wakeup_prepare(void) #if SOC_PM_SUPPORT_RTC_PERIPH_PD // Pad configuration depends on RTC_PERIPH state in sleep mode - if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] != ESP_PD_OPTION_ON) { + if (s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option != ESP_PD_OPTION_ON) { #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED // RTC_PERIPH will be powered down, so RTC_IO_ registers will // loose their state. Lock pad configuration. @@ -1336,13 +1343,20 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void) #endif } -esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain, - esp_sleep_pd_option_t option) +esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain, esp_sleep_pd_option_t option) { if (domain >= ESP_PD_DOMAIN_MAX || option > ESP_PD_OPTION_AUTO) { return ESP_ERR_INVALID_ARG; } - s_config.pd_options[domain] = option; + portENTER_CRITICAL_SAFE(&s_config.lock); + int refs = (option == ESP_PD_OPTION_ON) ? s_config.domain[domain].refs++ \ + : (option == ESP_PD_OPTION_OFF) ? --s_config.domain[domain].refs \ + : s_config.domain[domain].refs; + if (refs == 0) { + s_config.domain[domain].pd_option = option; + } + portEXIT_CRITICAL_SAFE(&s_config.lock); + assert(refs >= 0); return ESP_OK; } @@ -1364,9 +1378,9 @@ static uint32_t get_power_down_flags(void) */ volatile size_t rtc_slow_mem_used = (size_t)&_rtc_slow_length; - if ((s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] == ESP_PD_OPTION_AUTO) && + if ((s_config.domain[ESP_PD_DOMAIN_RTC_SLOW_MEM].pd_option == ESP_PD_OPTION_AUTO) && (rtc_slow_mem_used > 0 || (s_config.wakeup_triggers & RTC_ULP_TRIG_EN))) { - s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] = ESP_PD_OPTION_ON; + s_config.domain[ESP_PD_DOMAIN_RTC_SLOW_MEM].pd_option = ESP_PD_OPTION_ON; } #endif @@ -1375,27 +1389,27 @@ static uint32_t get_power_down_flags(void) /* RTC_FAST_MEM is needed for deep sleep stub. If RTC_FAST_MEM is Auto, keep it powered on, so that deep sleep stub can run. In the new chip revision, deep sleep stub will be optional, and this can be changed. */ - if (s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] == ESP_PD_OPTION_AUTO) { - s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] = ESP_PD_OPTION_ON; + if (s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option == ESP_PD_OPTION_AUTO) { + s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option = ESP_PD_OPTION_ON; } #else /* If RTC_FAST_MEM is used for heap, force RTC_FAST_MEM to be powered on. */ - s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] = ESP_PD_OPTION_ON; + s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option = ESP_PD_OPTION_ON; #endif #endif #if SOC_PM_SUPPORT_RTC_PERIPH_PD // RTC_PERIPH is needed for EXT0 wakeup and GPIO wakeup. // If RTC_PERIPH is left auto (EXT0/GPIO aren't enabled), RTC_PERIPH will be powered off by default. - if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] == ESP_PD_OPTION_AUTO) { + if (s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option == ESP_PD_OPTION_AUTO) { if (s_config.wakeup_triggers & (RTC_EXT0_TRIG_EN | RTC_GPIO_TRIG_EN)) { - s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_ON; + s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option = ESP_PD_OPTION_ON; } #if CONFIG_IDF_TARGET_ESP32 else if (s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) { // On ESP32, forcing power up of RTC_PERIPH // prevents ULP timer and touch FSMs from working correctly. - s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_OFF; + s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option = ESP_PD_OPTION_OFF; } #endif //CONFIG_IDF_TARGET_ESP32 } @@ -1403,7 +1417,7 @@ static uint32_t get_power_down_flags(void) #if SOC_PM_SUPPORT_CPU_PD if (!cpu_domain_pd_allowed()) { - s_config.pd_options[ESP_PD_DOMAIN_CPU] = ESP_PD_OPTION_ON; + s_config.domain[ESP_PD_DOMAIN_CPU].pd_option = ESP_PD_OPTION_ON; } #endif /** @@ -1416,66 +1430,66 @@ static uint32_t get_power_down_flags(void) * value of this field. */ #if SOC_PM_SUPPORT_VDDSDIO_PD - if (s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] == ESP_PD_OPTION_AUTO) { + if (s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option == ESP_PD_OPTION_AUTO) { #ifndef CONFIG_ESP_SLEEP_POWER_DOWN_FLASH - s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] = ESP_PD_OPTION_ON; + s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option = ESP_PD_OPTION_ON; #endif } #endif #if SOC_PM_SUPPORT_XTAL_PD #ifdef CONFIG_IDF_TARGET_ESP32 - s_config.pd_options[ESP_PD_DOMAIN_XTAL] = ESP_PD_OPTION_OFF; + s_config.domain[ESP_PD_DOMAIN_XTAL].pd_option = ESP_PD_OPTION_OFF; #endif #endif const __attribute__((unused)) char *option_str[] = {"OFF", "ON", "AUTO(OFF)" /* Auto works as OFF */}; /* This function is called from a critical section, log with ESP_EARLY_LOGD. */ #if SOC_PM_SUPPORT_RTC_PERIPH_PD - ESP_EARLY_LOGD(TAG, "RTC_PERIPH: %s", option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH]]); + ESP_EARLY_LOGD(TAG, "RTC_PERIPH: %s", option_str[s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option]); #endif #if SOC_PM_SUPPORT_RTC_SLOW_MEM_PD - ESP_EARLY_LOGD(TAG, "RTC_SLOW_MEM: %s", option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM]]); + ESP_EARLY_LOGD(TAG, "RTC_SLOW_MEM: %s", option_str[s_config.domain[ESP_PD_DOMAIN_RTC_SLOW_MEM].pd_option]); #endif #if SOC_PM_SUPPORT_RTC_FAST_MEM_PD - ESP_EARLY_LOGD(TAG, "RTC_FAST_MEM: %s", option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM]]); + ESP_EARLY_LOGD(TAG, "RTC_FAST_MEM: %s", option_str[s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option]); #endif // Prepare flags based on the selected options uint32_t pd_flags = 0; #if SOC_PM_SUPPORT_RTC_FAST_MEM_PD - if (s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] != ESP_PD_OPTION_ON) { + if (s_config.domain[ESP_PD_DOMAIN_RTC_FAST_MEM].pd_option != ESP_PD_OPTION_ON) { pd_flags |= RTC_SLEEP_PD_RTC_FAST_MEM; } #endif #if SOC_PM_SUPPORT_RTC_SLOW_MEM_PD - if (s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] != ESP_PD_OPTION_ON) { + if (s_config.domain[ESP_PD_DOMAIN_RTC_SLOW_MEM].pd_option != ESP_PD_OPTION_ON) { pd_flags |= RTC_SLEEP_PD_RTC_SLOW_MEM; } #endif #if SOC_PM_SUPPORT_RTC_PERIPH_PD - if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] != ESP_PD_OPTION_ON) { + if (s_config.domain[ESP_PD_DOMAIN_RTC_PERIPH].pd_option != ESP_PD_OPTION_ON) { pd_flags |= RTC_SLEEP_PD_RTC_PERIPH; } #endif #if SOC_PM_SUPPORT_CPU_PD - if (s_config.pd_options[ESP_PD_DOMAIN_CPU] != ESP_PD_OPTION_ON) { + if (s_config.domain[ESP_PD_DOMAIN_CPU].pd_option != ESP_PD_OPTION_ON) { pd_flags |= RTC_SLEEP_PD_CPU; } #endif #if SOC_PM_SUPPORT_XTAL32K_PD - if (s_config.pd_options[ESP_PD_DOMAIN_XTAL32K] != ESP_PD_OPTION_ON) { + if (s_config.domain[ESP_PD_DOMAIN_XTAL32K].pd_option != ESP_PD_OPTION_ON) { pd_flags |= PMU_SLEEP_PD_XTAL32K; } #endif #if SOC_PM_SUPPORT_RC32K_PD - if (s_config.pd_options[ESP_PD_DOMAIN_RC32K] != ESP_PD_OPTION_ON) { + if (s_config.domain[ESP_PD_DOMAIN_RC32K].pd_option != ESP_PD_OPTION_ON) { pd_flags |= PMU_SLEEP_PD_RC32K; } #endif #if SOC_PM_SUPPORT_RC_FAST_PD - if (s_config.pd_options[ESP_PD_DOMAIN_RC_FAST] != ESP_PD_OPTION_ON) { + if (s_config.domain[ESP_PD_DOMAIN_RC_FAST].pd_option != ESP_PD_OPTION_ON) { #if CONFIG_IDF_TARGET_ESP32C6 pd_flags |= PMU_SLEEP_PD_FOSC; #else @@ -1484,12 +1498,12 @@ static uint32_t get_power_down_flags(void) } #endif #if SOC_PM_SUPPORT_XTAL_PD - if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] != ESP_PD_OPTION_ON) { + if (s_config.domain[ESP_PD_DOMAIN_XTAL].pd_option != ESP_PD_OPTION_ON) { pd_flags |= RTC_SLEEP_PD_XTAL; } #endif #if SOC_PM_SUPPORT_VDDSDIO_PD - if (s_config.pd_options[ESP_PD_DOMAIN_VDDSDIO] != ESP_PD_OPTION_ON) { + if (s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option != ESP_PD_OPTION_ON) { #if CONFIG_IDF_TARGET_ESP32C6 pd_flags |= PMU_SLEEP_PD_VDDSDIO; #else From 1c39d64f95efc4b063934b995c2c5729993a432e Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Thu, 12 Jan 2023 18:08:14 +0800 Subject: [PATCH 11/16] cpu retention: refactor cpu retention and add cpu retention versions option in soc caps --- components/esp_hw_support/CMakeLists.txt | 4 +- .../{sleep_retention.h => sleep_cpu.h} | 22 +- components/esp_hw_support/include/esp_sleep.h | 37 ++- components/esp_hw_support/sleep_cpu.c | 257 ++++++++++++++++++ components/esp_hw_support/sleep_modes.c | 10 +- components/esp_hw_support/sleep_retention.c | 219 --------------- components/esp_pm/linker.lf | 15 +- components/esp_pm/pm_impl.c | 9 +- components/esp_wifi/esp32c6/esp_adapter.c | 3 +- 9 files changed, 323 insertions(+), 253 deletions(-) rename components/esp_hw_support/include/esp_private/{sleep_retention.h => sleep_cpu.h} (59%) create mode 100644 components/esp_hw_support/sleep_cpu.c delete mode 100644 components/esp_hw_support/sleep_retention.c diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 315cd7732d..81a9e4d36f 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -30,8 +30,8 @@ if(NOT BOOTLOADER_BUILD) "port/${target}/clk_tree.c" "port/clk_tree_common.c") - if(NOT CONFIG_IDF_TARGET_ESP32 AND NOT CONFIG_IDF_TARGET_ESP32S2) - list(APPEND srcs "sleep_retention.c") + if(CONFIG_SOC_PM_SUPPORT_CPU_PD) + list(APPEND srcs "sleep_cpu.c") endif() # [refactor-todo]: requires "driver" for GPIO and RTC (by sleep_gpio and sleep_modes) diff --git a/components/esp_hw_support/include/esp_private/sleep_retention.h b/components/esp_hw_support/include/esp_private/sleep_cpu.h similarity index 59% rename from components/esp_hw_support/include/esp_private/sleep_retention.h rename to components/esp_hw_support/include/esp_private/sleep_cpu.h index 001e559c0c..1e58100e30 100644 --- a/components/esp_hw_support/include/esp_private/sleep_retention.h +++ b/components/esp_hw_support/include/esp_private/sleep_cpu.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,9 +13,9 @@ extern "C" { #endif /** - * @file sleep_retention.h + * @file sleep_cpu.h * - * This file contains declarations of memory retention related functions in light sleeo mode. + * This file contains declarations of cpu retention related functions in light sleep mode. */ #if SOC_PM_SUPPORT_CPU_PD @@ -30,25 +30,25 @@ bool cpu_domain_pd_allowed(void); #endif -#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD +#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL /** - * @brief Enable memory retention of some modules. + * @brief Enable cpu retention of some modules. * - * In light sleep mode, before the system goes to sleep, enable the memory + * In light sleep mode, before the system goes to sleep, enable the cpu * retention of modules such as CPU and I/D-cache tag memory. */ -void sleep_enable_memory_retention(void); +void sleep_enable_cpu_retention(void); /** - * @brief Disable memory retention of some modules. + * @brief Disable cpu retention of some modules. * - * In light sleep mode, after the system exits sleep, disable the memory + * In light sleep mode, after the system exits sleep, disable the cpu * retention of moudles such as CPU and I/D-cache tag memory. */ -void sleep_disable_memory_retention(void); +void sleep_disable_cpu_retention(void); -#endif // SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD +#endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL #ifdef __cplusplus } diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index 25d24aaeab..508e50a435 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -486,15 +486,44 @@ void esp_default_wake_deep_sleep(void); void esp_deep_sleep_disable_rom_logging(void); #ifdef SOC_PM_SUPPORT_CPU_PD + +#if SOC_PM_CPU_RETENTION_BY_RTCCNTL /** - * @brief CPU Power down low-level initialize - * - * @param enable enable or disable CPU power down during light sleep + * @brief CPU Power down low-level initialize, enable CPU power down during light sleep * @return * - ESP_OK on success * - ESP_ERR_NO_MEM not enough retention memory */ -esp_err_t esp_sleep_cpu_pd_low_init(bool enable); +esp_err_t esp_sleep_cpu_pd_low_init(void); + +/** + * @brief CPU Power down low-level deinitialize, disable CPU power down during light sleep + * @return + * - ESP_OK on success + * - ESP_ERR_NO_MEM not enough retention memory + */ +esp_err_t esp_sleep_cpu_pd_low_deinit(void); + +#endif + +/** + * @brief CPU Power down initialize + * + * @return + * - ESP_OK on success + * - ESP_ERR_NO_MEM not enough retention memory + */ +esp_err_t esp_sleep_cpu_retention_init(void); + +/** + * @brief CPU Power down de-initialize + * + * @return + * - ESP_OK on success + * + * Release system retention memory. + */ +esp_err_t esp_sleep_cpu_retention_deinit(void); #endif #if SOC_GPIO_SUPPORT_SLP_SWITCH diff --git a/components/esp_hw_support/sleep_cpu.c b/components/esp_hw_support/sleep_cpu.c new file mode 100644 index 0000000000..472601babc --- /dev/null +++ b/components/esp_hw_support/sleep_cpu.c @@ -0,0 +1,257 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "esp_attr.h" +#include "esp_sleep.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_heap_caps.h" +#include "soc/soc_caps.h" +#include "hal/rtc_hal.h" +#include "esp_private/sleep_cpu.h" +#include "sdkconfig.h" + +#ifdef CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/rom/cache.h" +#endif + +static __attribute__((unused)) const char *TAG = "sleep"; + +/** + * Internal structure which holds all requested light sleep cpu retention parameters + */ +typedef struct { +#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL + rtc_cntl_sleep_retent_t retent; +#endif +} sleep_cpu_retention_t; + +static DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention; + +#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL + +#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP +static int cache_tagmem_retention_setup(uint32_t code_seg_vaddr, uint32_t code_seg_size, uint32_t data_seg_vaddr, uint32_t data_seg_size) +{ + int sets; /* i/d-cache total set counts */ + int index; /* virtual address mapping i/d-cache row offset */ + int waysgrp; + int icache_tagmem_blk_gs, dcache_tagmem_blk_gs; + struct cache_mode imode = { .icache = 1 }; + struct cache_mode dmode = { .icache = 0 }; + + /* calculate/prepare i-cache tag memory retention parameters */ + Cache_Get_Mode(&imode); + sets = imode.cache_size / imode.cache_ways / imode.cache_line_size; + index = (code_seg_vaddr / imode.cache_line_size) % sets; + waysgrp = imode.cache_ways >> 2; + + code_seg_size = ALIGNUP(imode.cache_line_size, code_seg_size); + + s_cpu_retention.retent.tagmem.icache.start_point = index; + s_cpu_retention.retent.tagmem.icache.size = (sets * waysgrp) & 0xff; + s_cpu_retention.retent.tagmem.icache.vld_size = s_cpu_retention.retent.tagmem.icache.size; + if (code_seg_size < imode.cache_size / imode.cache_ways) { + s_cpu_retention.retent.tagmem.icache.vld_size = (code_seg_size / imode.cache_line_size) * waysgrp; + } + s_cpu_retention.retent.tagmem.icache.enable = (code_seg_size != 0) ? 1 : 0; + icache_tagmem_blk_gs = s_cpu_retention.retent.tagmem.icache.vld_size ? s_cpu_retention.retent.tagmem.icache.vld_size : sets * waysgrp; + icache_tagmem_blk_gs = ALIGNUP(4, icache_tagmem_blk_gs); + ESP_LOGD(TAG, "I-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (imode.cache_size>>10), + imode.cache_line_size, imode.cache_ways, sets, index, icache_tagmem_blk_gs); + + /* calculate/prepare d-cache tag memory retention parameters */ + Cache_Get_Mode(&dmode); + sets = dmode.cache_size / dmode.cache_ways / dmode.cache_line_size; + index = (data_seg_vaddr / dmode.cache_line_size) % sets; + waysgrp = dmode.cache_ways >> 2; + + data_seg_size = ALIGNUP(dmode.cache_line_size, data_seg_size); + + s_cpu_retention.retent.tagmem.dcache.start_point = index; + s_cpu_retention.retent.tagmem.dcache.size = (sets * waysgrp) & 0x1ff; + s_cpu_retention.retent.tagmem.dcache.vld_size = s_cpu_retention.retent.tagmem.dcache.size; +#ifndef CONFIG_ESP32S3_DATA_CACHE_16KB + if (data_seg_size < dmode.cache_size / dmode.cache_ways) { + s_cpu_retention.retent.tagmem.dcache.vld_size = (data_seg_size / dmode.cache_line_size) * waysgrp; + } + s_cpu_retention.retent.tagmem.dcache.enable = (data_seg_size != 0) ? 1 : 0; +#else + s_cpu_retention.retent.tagmem.dcache.enable = 1; +#endif + dcache_tagmem_blk_gs = s_cpu_retention.retent.tagmem.dcache.vld_size ? s_cpu_retention.retent.tagmem.dcache.vld_size : sets * waysgrp; + dcache_tagmem_blk_gs = ALIGNUP(4, dcache_tagmem_blk_gs); + ESP_LOGD(TAG, "D-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (dmode.cache_size>>10), + dmode.cache_line_size, dmode.cache_ways, sets, index, dcache_tagmem_blk_gs); + + /* For I or D cache tagmem retention, backup and restore are performed through + * RTC DMA (its bus width is 128 bits), For I/D Cache tagmem blocks (i-cache + * tagmem blocks = 92 bits, d-cache tagmem blocks = 88 bits), RTC DMA automatically + * aligns its bit width to 96 bits, therefore, 3 times RTC DMA can transfer 4 + * i/d-cache tagmem blocks (128 bits * 3 = 96 bits * 4) */ + return (((icache_tagmem_blk_gs + dcache_tagmem_blk_gs) << 2) * 3); +} +#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + +static esp_err_t esp_sleep_tagmem_pd_low_init(void) +{ +#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + if (s_cpu_retention.retent.tagmem.link_addr == NULL) { + extern char _stext[], _etext[]; + uint32_t code_start = (uint32_t)_stext; + uint32_t code_size = (uint32_t)(_etext - _stext); +#if !(CONFIG_SPIRAM && CONFIG_SOC_PM_SUPPORT_TAGMEM_PD) + extern char _rodata_start[], _rodata_reserved_end[]; + uint32_t data_start = (uint32_t)_rodata_start; + uint32_t data_size = (uint32_t)(_rodata_reserved_end - _rodata_start); +#else + uint32_t data_start = SOC_DROM_LOW; + uint32_t data_size = SOC_EXTRAM_DATA_SIZE; +#endif + ESP_LOGI(TAG, "Code start at %08x, total %.2f KiB, data start at %08x, total %.2f KiB", + code_start, (float)code_size/1024, data_start, (float)data_size/1024); + int tagmem_sz = cache_tagmem_retention_setup(code_start, code_size, data_start, data_size); + void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_TAGMEM_PD_DMA_ADDR_ALIGN, + tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE, + MALLOC_CAP_RETENTION); + if (buf) { + memset(buf, 0, tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE); + s_cpu_retention.retent.tagmem.link_addr = rtc_cntl_hal_dma_link_init(buf, + buf + RTC_HAL_DMA_LINK_NODE_SIZE, tagmem_sz, NULL); + } else { + s_cpu_retention.retent.tagmem.icache.enable = 0; + s_cpu_retention.retent.tagmem.dcache.enable = 0; + s_cpu_retention.retent.tagmem.link_addr = NULL; + return ESP_ERR_NO_MEM; + } + } +#else // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + s_cpu_retention.retent.tagmem.icache.enable = 0; + s_cpu_retention.retent.tagmem.dcache.enable = 0; + s_cpu_retention.retent.tagmem.link_addr = NULL; +#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP + return ESP_OK; +} + +static esp_err_t esp_sleep_tagmem_pd_low_deinit(void) +{ +#if SOC_PM_SUPPORT_TAGMEM_PD + if (s_cpu_retention.retent.tagmem.link_addr) { + heap_caps_free(s_cpu_retention.retent.tagmem.link_addr); + s_cpu_retention.retent.tagmem.icache.enable = 0; + s_cpu_retention.retent.tagmem.dcache.enable = 0; + s_cpu_retention.retent.tagmem.link_addr = NULL; + } +#endif + return ESP_OK; +} +#endif // SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL + +#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL + +esp_err_t esp_sleep_cpu_pd_low_init(void) +{ + if (s_cpu_retention.retent.cpu_pd_mem == NULL) { + void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN, + SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE, + MALLOC_CAP_RETENTION); + if (buf) { + memset(buf, 0, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE); + s_cpu_retention.retent.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf, + buf + RTC_HAL_DMA_LINK_NODE_SIZE, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL); + } else { + return ESP_ERR_NO_MEM; + } + } + +#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL + if (esp_sleep_tagmem_pd_low_init() != ESP_OK) { +#ifdef CONFIG_ESP32S3_DATA_CACHE_16KB + esp_sleep_cpu_pd_low_deinit(); + return ESP_ERR_NO_MEM; +#endif + } +#endif + return ESP_OK; +} + +esp_err_t esp_sleep_cpu_pd_low_deinit(void) +{ + if (s_cpu_retention.retent.cpu_pd_mem) { + heap_caps_free(s_cpu_retention.retent.cpu_pd_mem); + s_cpu_retention.retent.cpu_pd_mem = NULL; + } + +#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL + if (esp_sleep_tagmem_pd_low_deinit() != ESP_OK) { +#ifdef CONFIG_ESP32S3_DATA_CACHE_16KB + esp_sleep_cpu_pd_low_deinit(); + return ESP_ERR_NO_MEM; +#endif + } +#endif + return ESP_OK; +} + +void sleep_enable_cpu_retention(void) +{ +#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_REGDMA + rtc_cntl_hal_enable_cpu_retention(&s_cpu_retention.retent); +#endif +#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_REGDMA + rtc_cntl_hal_enable_tagmem_retention(&s_cpu_retention.retent); +#endif +} + +void IRAM_ATTR sleep_disable_cpu_retention(void) +{ +#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_REGDMA + rtc_cntl_hal_disable_cpu_retention(&s_cpu_retention.retent); +#endif +#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_REGDMA + rtc_cntl_hal_disable_tagmem_retention(&s_cpu_retention.retent); +#endif +} + +#endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_REGDMA + + +#if SOC_PM_SUPPORT_CPU_PD + +esp_err_t esp_sleep_cpu_retention_init(void) +{ + esp_err_t err = ESP_OK; +#if SOC_PM_CPU_RETENTION_BY_RTCCNTL + err = esp_sleep_cpu_pd_low_init(); +#endif + return err; +} + +esp_err_t esp_sleep_cpu_retention_deinit(void) +{ + esp_err_t err = ESP_OK; +#if SOC_PM_CPU_RETENTION_BY_RTCCNTL + err = esp_sleep_cpu_pd_low_deinit(); +#endif + return err; +} + +bool cpu_domain_pd_allowed(void) +{ +#if SOC_PM_CPU_RETENTION_BY_RTCCNTL + return (s_cpu_retention.retent.cpu_pd_mem != NULL); +#else + return false; +#endif +} + +#endif diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index f61b7bac96..51b79a8480 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -49,7 +49,7 @@ #include "esp_rom_uart.h" #include "esp_rom_sys.h" #include "esp_private/brownout.h" -#include "esp_private/sleep_retention.h" +#include "esp_private/sleep_cpu.h" #include "esp_private/esp_clk.h" #include "esp_private/startup_internal.h" #include "esp_private/esp_task_wdt.h" @@ -366,8 +366,8 @@ inline static void IRAM_ATTR misc_modules_sleep_prepare(void) #if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL gpio_sleep_mode_config_apply(); #endif -#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD - sleep_enable_memory_retention(); +#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL + sleep_enable_cpu_retention(); #endif #if REGI2C_ANA_CALI_PD_WORKAROUND regi2c_analog_cali_reg_read(); @@ -379,8 +379,8 @@ inline static void IRAM_ATTR misc_modules_sleep_prepare(void) */ inline static void IRAM_ATTR misc_modules_wake_prepare(void) { -#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD - sleep_disable_memory_retention(); +#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL + sleep_disable_cpu_retention(); #endif #if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL gpio_sleep_mode_config_unapply(); diff --git a/components/esp_hw_support/sleep_retention.c b/components/esp_hw_support/sleep_retention.c deleted file mode 100644 index dd19180abf..0000000000 --- a/components/esp_hw_support/sleep_retention.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include - -#include "esp_attr.h" -#include "esp_sleep.h" -#include "esp_log.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_heap_caps.h" -#include "soc/soc_caps.h" -#include "hal/rtc_hal.h" -#include "esp_private/sleep_retention.h" -#include "sdkconfig.h" - -#ifdef CONFIG_IDF_TARGET_ESP32S3 -#include "esp32s3/rom/cache.h" -#endif - -static __attribute__((unused)) const char *TAG = "sleep"; - -/** - * Internal structure which holds all requested light sleep memory retention parameters - */ -typedef struct { - rtc_cntl_sleep_retent_t retent; -} sleep_retention_t; - -static DRAM_ATTR __attribute__((unused)) sleep_retention_t s_retention; - -#if SOC_PM_SUPPORT_TAGMEM_PD - -#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP -static int cache_tagmem_retention_setup(uint32_t code_seg_vaddr, uint32_t code_seg_size, uint32_t data_seg_vaddr, uint32_t data_seg_size) -{ - int sets; /* i/d-cache total set counts */ - int index; /* virtual address mapping i/d-cache row offset */ - int waysgrp; - int icache_tagmem_blk_gs, dcache_tagmem_blk_gs; - struct cache_mode imode = { .icache = 1 }; - struct cache_mode dmode = { .icache = 0 }; - - /* calculate/prepare i-cache tag memory retention parameters */ - Cache_Get_Mode(&imode); - sets = imode.cache_size / imode.cache_ways / imode.cache_line_size; - index = (code_seg_vaddr / imode.cache_line_size) % sets; - waysgrp = imode.cache_ways >> 2; - - code_seg_size = ALIGNUP(imode.cache_line_size, code_seg_size); - - s_retention.retent.tagmem.icache.start_point = index; - s_retention.retent.tagmem.icache.size = (sets * waysgrp) & 0xff; - s_retention.retent.tagmem.icache.vld_size = s_retention.retent.tagmem.icache.size; - if (code_seg_size < imode.cache_size / imode.cache_ways) { - s_retention.retent.tagmem.icache.vld_size = (code_seg_size / imode.cache_line_size) * waysgrp; - } - s_retention.retent.tagmem.icache.enable = (code_seg_size != 0) ? 1 : 0; - icache_tagmem_blk_gs = s_retention.retent.tagmem.icache.vld_size ? s_retention.retent.tagmem.icache.vld_size : sets * waysgrp; - icache_tagmem_blk_gs = ALIGNUP(4, icache_tagmem_blk_gs); - ESP_LOGD(TAG, "I-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (imode.cache_size>>10), - imode.cache_line_size, imode.cache_ways, sets, index, icache_tagmem_blk_gs); - - /* calculate/prepare d-cache tag memory retention parameters */ - Cache_Get_Mode(&dmode); - sets = dmode.cache_size / dmode.cache_ways / dmode.cache_line_size; - index = (data_seg_vaddr / dmode.cache_line_size) % sets; - waysgrp = dmode.cache_ways >> 2; - - data_seg_size = ALIGNUP(dmode.cache_line_size, data_seg_size); - - s_retention.retent.tagmem.dcache.start_point = index; - s_retention.retent.tagmem.dcache.size = (sets * waysgrp) & 0x1ff; - s_retention.retent.tagmem.dcache.vld_size = s_retention.retent.tagmem.dcache.size; -#ifndef CONFIG_ESP32S3_DATA_CACHE_16KB - if (data_seg_size < dmode.cache_size / dmode.cache_ways) { - s_retention.retent.tagmem.dcache.vld_size = (data_seg_size / dmode.cache_line_size) * waysgrp; - } - s_retention.retent.tagmem.dcache.enable = (data_seg_size != 0) ? 1 : 0; -#else - s_retention.retent.tagmem.dcache.enable = 1; -#endif - dcache_tagmem_blk_gs = s_retention.retent.tagmem.dcache.vld_size ? s_retention.retent.tagmem.dcache.vld_size : sets * waysgrp; - dcache_tagmem_blk_gs = ALIGNUP(4, dcache_tagmem_blk_gs); - ESP_LOGD(TAG, "D-cache size:%d KiB, line size:%d B, ways:%d, sets:%d, index:%d, tag block groups:%d", (dmode.cache_size>>10), - dmode.cache_line_size, dmode.cache_ways, sets, index, dcache_tagmem_blk_gs); - - /* For I or D cache tagmem retention, backup and restore are performed through - * RTC DMA (its bus width is 128 bits), For I/D Cache tagmem blocks (i-cache - * tagmem blocks = 92 bits, d-cache tagmem blocks = 88 bits), RTC DMA automatically - * aligns its bit width to 96 bits, therefore, 3 times RTC DMA can transfer 4 - * i/d-cache tagmem blocks (128 bits * 3 = 96 bits * 4) */ - return (((icache_tagmem_blk_gs + dcache_tagmem_blk_gs) << 2) * 3); -} -#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP - -static esp_err_t esp_sleep_tagmem_pd_low_init(bool enable) -{ - if (enable) { -#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP - if (s_retention.retent.tagmem.link_addr == NULL) { - extern char _stext[], _etext[]; - uint32_t code_start = (uint32_t)_stext; - uint32_t code_size = (uint32_t)(_etext - _stext); -#if !(CONFIG_SPIRAM && CONFIG_IDF_TARGET_ESP32S3) - extern char _rodata_start[], _rodata_reserved_end[]; - uint32_t data_start = (uint32_t)_rodata_start; - uint32_t data_size = (uint32_t)(_rodata_reserved_end - _rodata_start); -#else - uint32_t data_start = SOC_DROM_LOW; - uint32_t data_size = SOC_EXTRAM_DATA_SIZE; -#endif - ESP_LOGI(TAG, "Code start at %08x, total %.2f KiB, data start at %08x, total %.2f KiB", - code_start, (float)code_size/1024, data_start, (float)data_size/1024); - int tagmem_sz = cache_tagmem_retention_setup(code_start, code_size, data_start, data_size); - void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_TAGMEM_PD_DMA_ADDR_ALIGN, - tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE, - MALLOC_CAP_RETENTION); - if (buf) { - memset(buf, 0, tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE); - s_retention.retent.tagmem.link_addr = rtc_cntl_hal_dma_link_init(buf, - buf + RTC_HAL_DMA_LINK_NODE_SIZE, tagmem_sz, NULL); - } else { - s_retention.retent.tagmem.icache.enable = 0; - s_retention.retent.tagmem.dcache.enable = 0; - s_retention.retent.tagmem.link_addr = NULL; - return ESP_ERR_NO_MEM; - } - } -#else // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP - s_retention.retent.tagmem.icache.enable = 0; - s_retention.retent.tagmem.dcache.enable = 0; - s_retention.retent.tagmem.link_addr = NULL; -#endif // CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP - } else { -#if SOC_PM_SUPPORT_TAGMEM_PD - if (s_retention.retent.tagmem.link_addr) { - heap_caps_free(s_retention.retent.tagmem.link_addr); - s_retention.retent.tagmem.icache.enable = 0; - s_retention.retent.tagmem.dcache.enable = 0; - s_retention.retent.tagmem.link_addr = NULL; - } -#endif - } - return ESP_OK; -} - -#endif // SOC_PM_SUPPORT_TAGMEM_PD - -#if SOC_PM_SUPPORT_CPU_PD - -esp_err_t esp_sleep_cpu_pd_low_init(bool enable) -{ - if (enable) { - if (s_retention.retent.cpu_pd_mem == NULL) { - void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN, - SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE, - MALLOC_CAP_RETENTION); - if (buf) { - memset(buf, 0, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE); - s_retention.retent.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf, - buf + RTC_HAL_DMA_LINK_NODE_SIZE, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL); - } else { - return ESP_ERR_NO_MEM; - } - } - } else { - if (s_retention.retent.cpu_pd_mem) { - heap_caps_free(s_retention.retent.cpu_pd_mem); - s_retention.retent.cpu_pd_mem = NULL; - } - } -#if SOC_PM_SUPPORT_TAGMEM_PD - if (esp_sleep_tagmem_pd_low_init(enable) != ESP_OK) { -#ifdef CONFIG_ESP32S3_DATA_CACHE_16KB - esp_sleep_cpu_pd_low_init(false); - return ESP_ERR_NO_MEM; -#endif - } -#endif - return ESP_OK; -} - -bool cpu_domain_pd_allowed(void) -{ - return (s_retention.retent.cpu_pd_mem != NULL); -} - -#endif // SOC_PM_SUPPORT_CPU_PD - -#if SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD - -void sleep_enable_memory_retention(void) -{ -#if SOC_PM_SUPPORT_CPU_PD - rtc_cntl_hal_enable_cpu_retention(&s_retention.retent); -#endif -#if SOC_PM_SUPPORT_TAGMEM_PD - rtc_cntl_hal_enable_tagmem_retention(&s_retention.retent); -#endif -} - -void IRAM_ATTR sleep_disable_memory_retention(void) -{ -#if SOC_PM_SUPPORT_CPU_PD - rtc_cntl_hal_disable_cpu_retention(&s_retention.retent); -#endif -#if SOC_PM_SUPPORT_TAGMEM_PD - rtc_cntl_hal_disable_tagmem_retention(&s_retention.retent); -#endif -} - -#endif // SOC_PM_SUPPORT_CPU_PD || SOC_PM_SUPPORT_TAGMEM_PD diff --git a/components/esp_pm/linker.lf b/components/esp_pm/linker.lf index 6ef1e90e06..eacfc0cc2b 100644 --- a/components/esp_pm/linker.lf +++ b/components/esp_pm/linker.lf @@ -21,10 +21,10 @@ entries: esp_clk:esp_rtc_get_time_us (noflash) if GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL = y: sleep_gpio:gpio_sleep_mode_config_apply (noflash) - if SOC_PM_SUPPORT_CPU_PD = y || SOC_PM_SUPPORT_TAGMEM_PD = y: - sleep_retention:sleep_enable_memory_retention (noflash) + if SOC_PM_CPU_RETENTION_BY_RTCCNTL = y && (SOC_PM_SUPPORT_CPU_PD = y || SOC_PM_SUPPORT_TAGMEM_PD = y): + sleep_cpu:sleep_enable_cpu_retention (noflash) if SOC_PM_SUPPORT_CPU_PD = y: - sleep_retention:cpu_domain_pd_allowed (noflash) + sleep_cpu:cpu_domain_pd_allowed (noflash) [mapping:esp_system_pm] archive: libesp_system.a @@ -86,7 +86,8 @@ entries: gpio_hal_workaround:gpio_hal_sleep_pupd_config_unapply (noflash) gpio_hal_workaround:gpio_hal_sleep_mode_setup_wrapper (noflash) gpio_hal_workaround:gpio_hal_fun_pupd_restore (noflash) - if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y: - rtc_cntl_hal:rtc_cntl_hal_enable_cpu_retention (noflash) - if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP = y: - rtc_cntl_hal:rtc_cntl_hal_enable_tagmem_retention (noflash) + if SOC_PM_CPU_RETENTION_BY_RTCCNTL = y: + if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP = y: + rtc_cntl_hal:rtc_cntl_hal_enable_cpu_retention (noflash) + if PM_SLP_IRAM_OPT = y && PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP = y: + rtc_cntl_hal:rtc_cntl_hal_enable_tagmem_retention (noflash) diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 3d5b435597..20b0113c67 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -327,9 +327,12 @@ esp_err_t esp_pm_configure(const void* vconfig) #endif #if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_SUPPORT_CPU_PD - esp_err_t ret = esp_sleep_cpu_pd_low_init(config->light_sleep_enable); - if (config->light_sleep_enable && ret != ESP_OK) { - ESP_LOGW(TAG, "Failed to enable CPU power down during light sleep."); + if (config->light_sleep_enable) { + if (esp_sleep_cpu_retention_init() != ESP_OK) { + ESP_LOGW(TAG, "Failed to enable CPU power down during light sleep."); + } + } else { + esp_sleep_cpu_retention_deinit(); } #endif diff --git a/components/esp_wifi/esp32c6/esp_adapter.c b/components/esp_wifi/esp32c6/esp_adapter.c index ea4a676797..76eb31bd0b 100644 --- a/components/esp_wifi/esp32c6/esp_adapter.c +++ b/components/esp_wifi/esp32c6/esp_adapter.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -33,7 +33,6 @@ #include "esp_phy_init.h" #include "soc/rtc_cntl_periph.h" #include "soc/rtc.h" -#include "esp_private/sleep_retention.h" #include "phy_init_data.h" #include "esp_private/periph_ctrl.h" #include "esp_private/esp_clk.h" From 9b99fc90339e0d06e2f20c76bb7432ffc15100b6 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Wed, 11 Jan 2023 14:12:40 +0800 Subject: [PATCH 12/16] cpu retention: software cpu retention support for esp32c6 cpu retention: add riscv core sleep critical and non-critical register layout structure definition cpu retention: add assembly subroutine for cpu critical register backup and restore cpu retention: add cpu core critical register context backup and restore support cpu retention: add cpu core non-critical register context backup and restore support cpu retention: add interrupt priority register context backup and restore support cpu retention: add cache config register context backup and restore support cpu retention: add plic interrupt register context backup and restore support cpu retention: add clint interrupt register context backup and restore support cpu retention: wait icache state idle before pmu enter sleep --- components/esp_hw_support/CMakeLists.txt | 8 + .../include/esp_private/sleep_cpu.h | 8 + components/esp_hw_support/sleep_cpu.c | 429 +++++++++++++++++- components/esp_hw_support/sleep_cpu_asm.S | 239 ++++++++++ components/esp_rom/include/esp32c6/rom/rtc.h | 40 +- .../riscv/include/riscv/rvsleep-frames.h | 153 +++++++ tools/ci/check_public_headers_exceptions.txt | 1 + 7 files changed, 840 insertions(+), 38 deletions(-) create mode 100644 components/esp_hw_support/sleep_cpu_asm.S create mode 100644 components/riscv/include/riscv/rvsleep-frames.h diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index 81a9e4d36f..fb5e8056fc 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -73,6 +73,14 @@ if(NOT BOOTLOADER_BUILD) list(APPEND srcs "esp_ds.c") endif() + if(CONFIG_SOC_PM_CPU_RETENTION_BY_SW) + list(APPEND srcs "sleep_cpu_asm.S") + set_property(TARGET ${COMPONENT_LIB} + APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u rv_core_critical_regs_save") + set_property(TARGET ${COMPONENT_LIB} + APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u rv_core_critical_regs_restore") + endif() + if(CONFIG_SOC_MODEM_CLOCK_IS_INDEPENDENT) list(APPEND srcs "modem_clock.c") endif() diff --git a/components/esp_hw_support/include/esp_private/sleep_cpu.h b/components/esp_hw_support/include/esp_private/sleep_cpu.h index 1e58100e30..0e05797443 100644 --- a/components/esp_hw_support/include/esp_private/sleep_cpu.h +++ b/components/esp_hw_support/include/esp_private/sleep_cpu.h @@ -50,6 +50,14 @@ void sleep_disable_cpu_retention(void); #endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL + +#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW + +esp_err_t esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool), + uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp); + +#endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/sleep_cpu.c b/components/esp_hw_support/sleep_cpu.c index 472601babc..2f01bdc779 100644 --- a/components/esp_hw_support/sleep_cpu.c +++ b/components/esp_hw_support/sleep_cpu.c @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -16,22 +17,55 @@ #include "freertos/task.h" #include "esp_heap_caps.h" #include "soc/soc_caps.h" -#include "hal/rtc_hal.h" #include "esp_private/sleep_cpu.h" #include "sdkconfig.h" +#if !SOC_PMU_SUPPORTED +#include "hal/rtc_hal.h" +#endif + +#include "soc/rtc_periph.h" + #ifdef CONFIG_IDF_TARGET_ESP32S3 #include "esp32s3/rom/cache.h" +#elif CONFIG_IDF_TARGET_ESP32C6 +#include "esp32c6/rom/rtc.h" +#include "riscv/rvsleep-frames.h" +#include "soc/intpri_reg.h" +#include "soc/extmem_reg.h" +#include "soc/plic_reg.h" +#include "soc/clint_reg.h" +#include "esp32c6/rom/cache.h" #endif static __attribute__((unused)) const char *TAG = "sleep"; +typedef struct { + uint32_t start; + uint32_t end; +} cpu_domain_dev_regs_region_t; + +typedef struct { + cpu_domain_dev_regs_region_t *region; + int region_num; + uint32_t *regs_frame; +} cpu_domain_dev_sleep_frame_t; + /** * Internal structure which holds all requested light sleep cpu retention parameters */ typedef struct { #if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL rtc_cntl_sleep_retent_t retent; +#elif SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW + struct { + RvCoreCriticalSleepFrame *critical_frame; + RvCoreNonCriticalSleepFrame *non_critical_frame; + cpu_domain_dev_sleep_frame_t *intpri_frame; + cpu_domain_dev_sleep_frame_t *cache_config_frame; + cpu_domain_dev_sleep_frame_t *plic_frame; + cpu_domain_dev_sleep_frame_t *clint_frame; + } retent; #endif } sleep_cpu_retention_t; @@ -40,12 +74,12 @@ static DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention; #if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL #if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP -static int cache_tagmem_retention_setup(uint32_t code_seg_vaddr, uint32_t code_seg_size, uint32_t data_seg_vaddr, uint32_t data_seg_size) +static uint32_t cache_tagmem_retention_setup(uint32_t code_seg_vaddr, uint32_t code_seg_size, uint32_t data_seg_vaddr, uint32_t data_seg_size) { - int sets; /* i/d-cache total set counts */ - int index; /* virtual address mapping i/d-cache row offset */ - int waysgrp; - int icache_tagmem_blk_gs, dcache_tagmem_blk_gs; + uint32_t sets; /* i/d-cache total set counts */ + uint32_t index; /* virtual address mapping i/d-cache row offset */ + uint32_t waysgrp; + uint32_t icache_tagmem_blk_gs, dcache_tagmem_blk_gs; struct cache_mode imode = { .icache = 1 }; struct cache_mode dmode = { .icache = 0 }; @@ -117,14 +151,13 @@ static esp_err_t esp_sleep_tagmem_pd_low_init(void) uint32_t data_start = SOC_DROM_LOW; uint32_t data_size = SOC_EXTRAM_DATA_SIZE; #endif - ESP_LOGI(TAG, "Code start at %08x, total %.2f KiB, data start at %08x, total %.2f KiB", - code_start, (float)code_size/1024, data_start, (float)data_size/1024); - int tagmem_sz = cache_tagmem_retention_setup(code_start, code_size, data_start, data_size); - void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_TAGMEM_PD_DMA_ADDR_ALIGN, + ESP_LOGI(TAG, "Code start at 0x%08"PRIx32", total %"PRIu32", data start at 0x%08"PRIx32", total %"PRIu32" Bytes", + code_start, code_size, data_start, data_size); + uint32_t tagmem_sz = cache_tagmem_retention_setup(code_start, code_size, data_start, data_size); + void *buf = heap_caps_aligned_calloc(SOC_RTC_CNTL_TAGMEM_PD_DMA_ADDR_ALIGN, 1, tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE, MALLOC_CAP_RETENTION); if (buf) { - memset(buf, 0, tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE); s_cpu_retention.retent.tagmem.link_addr = rtc_cntl_hal_dma_link_init(buf, buf + RTC_HAL_DMA_LINK_NODE_SIZE, tagmem_sz, NULL); } else { @@ -161,11 +194,10 @@ static esp_err_t esp_sleep_tagmem_pd_low_deinit(void) esp_err_t esp_sleep_cpu_pd_low_init(void) { if (s_cpu_retention.retent.cpu_pd_mem == NULL) { - void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN, + void *buf = heap_caps_aligned_calloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN, 1, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE, MALLOC_CAP_RETENTION); if (buf) { - memset(buf, 0, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE); s_cpu_retention.retent.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf, buf + RTC_HAL_DMA_LINK_NODE_SIZE, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL); } else { @@ -204,25 +236,371 @@ esp_err_t esp_sleep_cpu_pd_low_deinit(void) void sleep_enable_cpu_retention(void) { -#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_REGDMA rtc_cntl_hal_enable_cpu_retention(&s_cpu_retention.retent); -#endif -#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_REGDMA + +#if SOC_PM_SUPPORT_TAGMEM_PD rtc_cntl_hal_enable_tagmem_retention(&s_cpu_retention.retent); #endif } void IRAM_ATTR sleep_disable_cpu_retention(void) { -#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_REGDMA rtc_cntl_hal_disable_cpu_retention(&s_cpu_retention.retent); -#endif -#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_REGDMA + +#if SOC_PM_SUPPORT_TAGMEM_PD rtc_cntl_hal_disable_tagmem_retention(&s_cpu_retention.retent); #endif } -#endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_REGDMA +#endif + + +#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW + +#define CUSTOM_CSR_PCER_MACHINE 0x7e0 +#define CUSTOM_CSR_PCMR_MACHINE 0x7e1 +#define CUSTOM_CSR_PCCR_MACHINE 0x7e2 +#define CUSTOM_CSR_CPU_TESTBUS_CTRL 0x7e3 +#define CUSTOM_CSR_PCER_USER 0x800 +#define CUSTOM_CSR_PCMR_USER 0x801 +#define CUSTOM_CSR_PCCR_USER 0x802 +#define CUSTOM_CSR_GPIO_OEN_USER 0x803 +#define CUSTOM_CSR_GPIO_IN_USER 0x804 +#define CUSTOM_CSR_GPIO_OUT_USER 0x805 +#define CUSTOM_CSR_CO_EXCEPTION_CAUSE 0x7f0 +#define CUSTOM_CSR_CO_HWLP 0x7f1 +#define CUSTOM_CSR_CO_AIA 0x7f2 + +extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame; + +static void * cpu_domain_dev_sleep_frame_alloc_and_init(const cpu_domain_dev_regs_region_t *regions, const int region_num) +{ + const int region_sz = sizeof(cpu_domain_dev_regs_region_t) * region_num; + int regs_frame_sz = 0; + for (int num = 0; num < region_num; num++) { + regs_frame_sz += regions[num].end - regions[num].start; + } + void *frame = heap_caps_malloc(sizeof(cpu_domain_dev_sleep_frame_t) + region_sz + regs_frame_sz, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL); + if (frame) { + cpu_domain_dev_regs_region_t *region = (cpu_domain_dev_regs_region_t *)(frame + sizeof(cpu_domain_dev_sleep_frame_t)); + memcpy(region, regions, region_num * sizeof(cpu_domain_dev_regs_region_t)); + void *regs_frame = frame + sizeof(cpu_domain_dev_sleep_frame_t) + region_sz; + memset(regs_frame, 0, regs_frame_sz); + *(cpu_domain_dev_sleep_frame_t *)frame = (cpu_domain_dev_sleep_frame_t) { + .region = region, + .region_num = region_num, + .regs_frame = (uint32_t *)regs_frame + }; + } + return frame; +} + +static inline void * cpu_domain_intpri_sleep_frame_alloc_and_init(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = INTPRI_CORE0_CPU_INT_ENABLE_REG, .end = INTPRI_RND_ECO_LOW_REG + 4 }, + { .start = INTPRI_RND_ECO_HIGH_REG, .end = INTPRI_RND_ECO_HIGH_REG + 4 } + }; + return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); +} + +static inline void * cpu_domain_cache_config_sleep_frame_alloc_and_init(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = EXTMEM_DCACHE_CTRL_REG, .end = EXTMEM_DCACHE_CTRL_REG + 4 }, + { .start = EXTMEM_CACHE_WRAP_AROUND_CTRL_REG, .end = EXTMEM_CACHE_WRAP_AROUND_CTRL_REG + 4 } + }; + return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); +} + +static inline void * cpu_domain_plic_sleep_frame_alloc_and_init(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = PLIC_MXINT_ENABLE_REG, .end = PLIC_MXINT_CLAIM_REG + 4 }, + { .start = PLIC_MXINT_CONF_REG, .end = PLIC_MXINT_CONF_REG + 4 }, + { .start = PLIC_UXINT_ENABLE_REG, .end = PLIC_UXINT_CLAIM_REG + 4 }, + { .start = PLIC_UXINT_CONF_REG, .end = PLIC_UXINT_CONF_REG + 4 } + }; + return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); +} + +static inline void * cpu_domain_clint_sleep_frame_alloc_and_init(void) +{ + const static cpu_domain_dev_regs_region_t regions[] = { + { .start = CLINT_MINT_SIP_REG, .end = CLINT_MINT_MTIMECMP_H_REG + 4 }, + { .start = CLINT_UINT_SIP_REG, .end = CLINT_UINT_UTIMECMP_H_REG + 4 } + }; + return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0])); +} + +static esp_err_t esp_sleep_cpu_retention_init_impl(void) +{ + if (s_cpu_retention.retent.critical_frame == NULL) { + void *frame = heap_caps_calloc(1, RV_SLEEP_CTX_FRMSZ, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL); + if (frame == NULL) { + goto err; + } + s_cpu_retention.retent.critical_frame = (RvCoreCriticalSleepFrame *)frame; + rv_core_critical_regs_frame = (RvCoreCriticalSleepFrame *)frame; + } + if (s_cpu_retention.retent.non_critical_frame == NULL) { + void *frame = heap_caps_calloc(1, sizeof(RvCoreNonCriticalSleepFrame), MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL); + if (frame == NULL) { + goto err; + } + s_cpu_retention.retent.non_critical_frame = (RvCoreNonCriticalSleepFrame *)frame; + } + if (s_cpu_retention.retent.intpri_frame == NULL) { + void *frame = cpu_domain_intpri_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + s_cpu_retention.retent.intpri_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (s_cpu_retention.retent.cache_config_frame == NULL) { + void *frame = cpu_domain_cache_config_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + s_cpu_retention.retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (s_cpu_retention.retent.plic_frame == NULL) { + void *frame = cpu_domain_plic_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + s_cpu_retention.retent.plic_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + if (s_cpu_retention.retent.clint_frame == NULL) { + void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(); + if (frame == NULL) { + goto err; + } + s_cpu_retention.retent.clint_frame = (cpu_domain_dev_sleep_frame_t *)frame; + } + return ESP_OK; +err: + esp_sleep_cpu_retention_deinit(); + return ESP_ERR_NO_MEM; +} + +static esp_err_t esp_sleep_cpu_retention_deinit_impl(void) +{ + if (s_cpu_retention.retent.critical_frame) { + heap_caps_free((void *)s_cpu_retention.retent.critical_frame); + s_cpu_retention.retent.critical_frame = NULL; + rv_core_critical_regs_frame = NULL; + } + if (s_cpu_retention.retent.non_critical_frame) { + heap_caps_free((void *)s_cpu_retention.retent.non_critical_frame); + s_cpu_retention.retent.non_critical_frame = NULL; + } + if (s_cpu_retention.retent.intpri_frame) { + heap_caps_free((void *)s_cpu_retention.retent.intpri_frame); + s_cpu_retention.retent.intpri_frame = NULL; + } + if (s_cpu_retention.retent.cache_config_frame) { + heap_caps_free((void *)s_cpu_retention.retent.cache_config_frame); + s_cpu_retention.retent.cache_config_frame = NULL; + } + if (s_cpu_retention.retent.plic_frame) { + heap_caps_free((void *)s_cpu_retention.retent.plic_frame); + s_cpu_retention.retent.plic_frame = NULL; + } + if (s_cpu_retention.retent.clint_frame) { + heap_caps_free((void *)s_cpu_retention.retent.clint_frame); + s_cpu_retention.retent.clint_frame = NULL; + } + return ESP_OK; +} + +static inline IRAM_ATTR uint32_t save_mstatus_and_disable_global_int(void) +{ + uint32_t mstatus; + __asm__ __volatile__ ( + "csrr %0, mstatus\n" + "csrci mstatus, 0x8\n" + : "=r"(mstatus) + ); + return mstatus; +} + +static inline IRAM_ATTR void restore_mstatus(uint32_t mstatus) +{ + __asm__ __volatile__ ("csrw mstatus, %0\n" :: "r"(mstatus)); +} + +static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(void) +{ + assert(s_cpu_retention.retent.non_critical_frame); + RvCoreNonCriticalSleepFrame *frame = s_cpu_retention.retent.non_critical_frame; + frame->mscratch = RV_READ_CSR(mscratch); + frame->mideleg = RV_READ_CSR(mideleg); + frame->misa = RV_READ_CSR(misa); + frame->tselect = RV_READ_CSR(tselect); + frame->tdata1 = RV_READ_CSR(tdata1); + frame->tdata2 = RV_READ_CSR(tdata2); + frame->tcontrol = RV_READ_CSR(tcontrol); + frame->pmpcfg0 = RV_READ_CSR(pmpcfg0); + frame->pmpcfg1 = RV_READ_CSR(pmpcfg1); + frame->pmpcfg2 = RV_READ_CSR(pmpcfg2); + frame->pmpcfg3 = RV_READ_CSR(pmpcfg3); + frame->pmpaddr0 = RV_READ_CSR(pmpaddr0); + frame->pmpaddr1 = RV_READ_CSR(pmpaddr1); + frame->pmpaddr2 = RV_READ_CSR(pmpaddr2); + frame->pmpaddr3 = RV_READ_CSR(pmpaddr3); + frame->pmpaddr4 = RV_READ_CSR(pmpaddr4); + frame->pmpaddr5 = RV_READ_CSR(pmpaddr5); + frame->pmpaddr6 = RV_READ_CSR(pmpaddr6); + frame->pmpaddr7 = RV_READ_CSR(pmpaddr7); + frame->pmpaddr8 = RV_READ_CSR(pmpaddr8); + frame->pmpaddr9 = RV_READ_CSR(pmpaddr9); + frame->pmpaddr10 = RV_READ_CSR(pmpaddr10); + frame->pmpaddr11 = RV_READ_CSR(pmpaddr11); + frame->pmpaddr12 = RV_READ_CSR(pmpaddr12); + frame->pmpaddr13 = RV_READ_CSR(pmpaddr13); + frame->pmpaddr14 = RV_READ_CSR(pmpaddr14); + frame->pmpaddr15 = RV_READ_CSR(pmpaddr15); + + frame->utvec = RV_READ_CSR(utvec); + frame->ustatus = RV_READ_CSR(ustatus); + frame->uepc = RV_READ_CSR(uepc); + frame->ucause = RV_READ_CSR(ucause); + + frame->mpcer = RV_READ_CSR(CUSTOM_CSR_PCER_MACHINE); + frame->mpcmr = RV_READ_CSR(CUSTOM_CSR_PCMR_MACHINE); + frame->mpccr = RV_READ_CSR(CUSTOM_CSR_PCCR_MACHINE); + frame->cpu_testbus_ctrl = RV_READ_CSR(CUSTOM_CSR_CPU_TESTBUS_CTRL); + frame->upcer = RV_READ_CSR(CUSTOM_CSR_PCER_USER); + frame->upcmr = RV_READ_CSR(CUSTOM_CSR_PCMR_USER); + frame->upccr = RV_READ_CSR(CUSTOM_CSR_PCCR_USER); + frame->ugpio_oen = RV_READ_CSR(CUSTOM_CSR_GPIO_OEN_USER); + frame->ugpio_in = RV_READ_CSR(CUSTOM_CSR_GPIO_IN_USER); + frame->ugpio_out = RV_READ_CSR(CUSTOM_CSR_GPIO_OUT_USER); + return frame; +} + +static IRAM_ATTR void rv_core_noncritical_regs_restore(RvCoreNonCriticalSleepFrame *frame) +{ + assert(frame); + RV_WRITE_CSR(mscratch, frame->mscratch); + RV_WRITE_CSR(mideleg, frame->mideleg); + RV_WRITE_CSR(misa, frame->misa); + RV_WRITE_CSR(tselect, frame->tselect); + RV_WRITE_CSR(tdata1, frame->tdata1); + RV_WRITE_CSR(tdata2, frame->tdata2); + RV_WRITE_CSR(tcontrol, frame->tcontrol); + RV_WRITE_CSR(pmpcfg0, frame->pmpcfg0); + RV_WRITE_CSR(pmpcfg1, frame->pmpcfg1); + RV_WRITE_CSR(pmpcfg2, frame->pmpcfg2); + RV_WRITE_CSR(pmpcfg3, frame->pmpcfg3); + RV_WRITE_CSR(pmpaddr0, frame->pmpaddr0); + RV_WRITE_CSR(pmpaddr1, frame->pmpaddr1); + RV_WRITE_CSR(pmpaddr2, frame->pmpaddr2); + RV_WRITE_CSR(pmpaddr3, frame->pmpaddr3); + RV_WRITE_CSR(pmpaddr4, frame->pmpaddr4); + RV_WRITE_CSR(pmpaddr5, frame->pmpaddr5); + RV_WRITE_CSR(pmpaddr6, frame->pmpaddr6); + RV_WRITE_CSR(pmpaddr7, frame->pmpaddr7); + RV_WRITE_CSR(pmpaddr8, frame->pmpaddr8); + RV_WRITE_CSR(pmpaddr9, frame->pmpaddr9); + RV_WRITE_CSR(pmpaddr10,frame->pmpaddr10); + RV_WRITE_CSR(pmpaddr11,frame->pmpaddr11); + RV_WRITE_CSR(pmpaddr12,frame->pmpaddr12); + RV_WRITE_CSR(pmpaddr13,frame->pmpaddr13); + RV_WRITE_CSR(pmpaddr14,frame->pmpaddr14); + RV_WRITE_CSR(pmpaddr15,frame->pmpaddr15); + + RV_WRITE_CSR(utvec, frame->utvec); + RV_WRITE_CSR(ustatus, frame->ustatus); + RV_WRITE_CSR(uepc, frame->uepc); + RV_WRITE_CSR(ucause, frame->ucause); + + RV_WRITE_CSR(CUSTOM_CSR_PCER_MACHINE, frame->mpcer); + RV_WRITE_CSR(CUSTOM_CSR_PCMR_MACHINE, frame->mpcmr); + RV_WRITE_CSR(CUSTOM_CSR_PCCR_MACHINE, frame->mpccr); + RV_WRITE_CSR(CUSTOM_CSR_CPU_TESTBUS_CTRL, frame->cpu_testbus_ctrl); + RV_WRITE_CSR(CUSTOM_CSR_PCER_USER, frame->upcer); + RV_WRITE_CSR(CUSTOM_CSR_PCMR_USER, frame->upcmr); + RV_WRITE_CSR(CUSTOM_CSR_PCCR_USER, frame->upccr); + RV_WRITE_CSR(CUSTOM_CSR_GPIO_OEN_USER,frame->ugpio_oen); + RV_WRITE_CSR(CUSTOM_CSR_GPIO_IN_USER, frame->ugpio_in); + RV_WRITE_CSR(CUSTOM_CSR_GPIO_OUT_USER,frame->ugpio_out); +} + +static IRAM_ATTR void cpu_domain_dev_regs_save(cpu_domain_dev_sleep_frame_t *frame) +{ + assert(frame); + cpu_domain_dev_regs_region_t *region = frame->region; + uint32_t *regs_frame = frame->regs_frame; + + int offset = 0; + for (int i = 0; i < frame->region_num; i++) { + for (uint32_t addr = region[i].start; addr < region[i].end; addr+=4) { + regs_frame[offset++] = *(uint32_t *)addr; + } + } +} + +static IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t *frame) +{ + assert(frame); + cpu_domain_dev_regs_region_t *region = frame->region; + uint32_t *regs_frame = frame->regs_frame; + + int offset = 0; + for (int i = 0; i < frame->region_num; i++) { + for (uint32_t addr = region[i].start; addr < region[i].end; addr+=4) { + *(uint32_t *)addr = regs_frame[offset++]; + } + } +} + +extern RvCoreCriticalSleepFrame * rv_core_critical_regs_save(void); +extern RvCoreCriticalSleepFrame * rv_core_critical_regs_restore(void); +typedef uint32_t (* sleep_cpu_entry_cb_t)(uint32_t, uint32_t, uint32_t, bool); + +static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep, + uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp) +{ + RvCoreCriticalSleepFrame * frame = rv_core_critical_regs_save(); + if ((frame->pmufunc & 0x3) == 0x1) { + REG_CLR_BIT(SLEEP_MODE_REG, BIT(0)); /* Tell rom to run light sleep wake stub */ + REG_WRITE(LIGHT_SLEEP_WAKE_STUB_ADDR_REG, (uint32_t)rv_core_critical_regs_restore); + return (*goto_sleep)(wakeup_opt, reject_opt, lslp_mem_inf_fpu, dslp); + } + + return ESP_OK; +} + +esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool), + uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp) +{ + uint32_t mstatus = save_mstatus_and_disable_global_int(); + + /* wait cache idle */ + Cache_Freeze_ICache_Enable(CACHE_FREEZE_ACK_BUSY); + Cache_Freeze_ICache_Disable(); + + cpu_domain_dev_regs_save(s_cpu_retention.retent.plic_frame); + cpu_domain_dev_regs_save(s_cpu_retention.retent.clint_frame); + cpu_domain_dev_regs_save(s_cpu_retention.retent.intpri_frame); + cpu_domain_dev_regs_save(s_cpu_retention.retent.cache_config_frame); + RvCoreNonCriticalSleepFrame *frame = rv_core_noncritical_regs_save(); + + esp_err_t err = do_cpu_retention(goto_sleep, wakeup_opt, reject_opt, lslp_mem_inf_fpu, dslp); + + rv_core_noncritical_regs_restore(frame); + cpu_domain_dev_regs_restore(s_cpu_retention.retent.cache_config_frame); + cpu_domain_dev_regs_restore(s_cpu_retention.retent.intpri_frame); + cpu_domain_dev_regs_restore(s_cpu_retention.retent.clint_frame); + cpu_domain_dev_regs_restore(s_cpu_retention.retent.plic_frame); + + restore_mstatus(mstatus); + return err; +} + +#endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW #if SOC_PM_SUPPORT_CPU_PD @@ -232,6 +610,8 @@ esp_err_t esp_sleep_cpu_retention_init(void) esp_err_t err = ESP_OK; #if SOC_PM_CPU_RETENTION_BY_RTCCNTL err = esp_sleep_cpu_pd_low_init(); +#elif SOC_PM_CPU_RETENTION_BY_SW + err = esp_sleep_cpu_retention_init_impl(); #endif return err; } @@ -241,6 +621,8 @@ esp_err_t esp_sleep_cpu_retention_deinit(void) esp_err_t err = ESP_OK; #if SOC_PM_CPU_RETENTION_BY_RTCCNTL err = esp_sleep_cpu_pd_low_deinit(); +#elif SOC_PM_CPU_RETENTION_BY_SW + err = esp_sleep_cpu_retention_deinit_impl(); #endif return err; } @@ -249,6 +631,13 @@ bool cpu_domain_pd_allowed(void) { #if SOC_PM_CPU_RETENTION_BY_RTCCNTL return (s_cpu_retention.retent.cpu_pd_mem != NULL); +#elif SOC_PM_CPU_RETENTION_BY_SW + return (s_cpu_retention.retent.critical_frame != NULL) && \ + (s_cpu_retention.retent.non_critical_frame != NULL) && \ + (s_cpu_retention.retent.intpri_frame != NULL) && \ + (s_cpu_retention.retent.cache_config_frame != NULL) && \ + (s_cpu_retention.retent.plic_frame != NULL) && \ + (s_cpu_retention.retent.clint_frame != NULL); #else return false; #endif diff --git a/components/esp_hw_support/sleep_cpu_asm.S b/components/esp_hw_support/sleep_cpu_asm.S new file mode 100644 index 0000000000..c62756d889 --- /dev/null +++ b/components/esp_hw_support/sleep_cpu_asm.S @@ -0,0 +1,239 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/soc.h" +#include "riscv/rvsleep-frames.h" +#include "soc/soc_caps.h" +#include "sdkconfig.h" + +#if !CONFIG_IDF_TARGET_ESP32C6 +#include "soc/lp_aon_reg.h" +#include "soc/extmem_reg.h" +#endif + + .section .data1,"aw" + .global rv_core_critical_regs_frame + .type rv_core_critical_regs_frame,@object + .align 4 +rv_core_critical_regs_frame: + .word 0 + +/* +-------------------------------------------------------------------------------- + This assembly subroutine is used to save the critical registers of the CPU + core to the internal RAM before sleep, and modify the PMU control flag to + indicate that the system needs to sleep. When the subroutine returns, it + will return the memory pointer that saves the context information of the CPU + critical registers. +-------------------------------------------------------------------------------- +*/ + + .section .iram1,"ax" + .global rv_core_critical_regs_save + .type rv_core_critical_regs_save,@function + .align 4 + +rv_core_critical_regs_save: + + /* arrived here in critical section. we need: + save riscv core critical registers to RvCoreCriticalSleepFrame + */ + csrw mscratch, t0 /* use mscratch as temp storage */ + la t0, rv_core_critical_regs_frame + lw t0, 0(t0) /* t0 pointer to RvCoreCriticalSleepFrame object */ + + sw ra, RV_SLP_CTX_RA(t0) + sw sp, RV_SLP_CTX_SP(t0) + sw gp, RV_SLP_CTX_GP(t0) + sw tp, RV_SLP_CTX_TP(t0) + sw t1, RV_SLP_CTX_T1(t0) + sw t2, RV_SLP_CTX_T2(t0) + sw s0, RV_SLP_CTX_S0(t0) + sw s1, RV_SLP_CTX_S1(t0) + sw a0, RV_SLP_CTX_A0(t0) + + /* !! WARNING, do not use the a0 register below, a0 carries important sleep + * information and will be returned as the return value !! */ + mv a0, t0 + + sw a1, RV_SLP_CTX_A1(t0) + sw a2, RV_SLP_CTX_A2(t0) + sw a3, RV_SLP_CTX_A3(t0) + sw a4, RV_SLP_CTX_A4(t0) + sw a5, RV_SLP_CTX_A5(t0) + sw a6, RV_SLP_CTX_A6(t0) + sw a7, RV_SLP_CTX_A7(t0) + sw s2, RV_SLP_CTX_S2(t0) + sw s3, RV_SLP_CTX_S3(t0) + sw s4, RV_SLP_CTX_S4(t0) + sw s5, RV_SLP_CTX_S5(t0) + sw s6, RV_SLP_CTX_S6(t0) + sw s7, RV_SLP_CTX_S7(t0) + sw s8, RV_SLP_CTX_S8(t0) + sw s9, RV_SLP_CTX_S9(t0) + sw s10, RV_SLP_CTX_S10(t0) + sw s11, RV_SLP_CTX_S11(t0) + sw t3, RV_SLP_CTX_T3(t0) + sw t4, RV_SLP_CTX_T4(t0) + sw t5, RV_SLP_CTX_T5(t0) + sw t6, RV_SLP_CTX_T6(t0) + + csrr t1, mstatus + sw t1, RV_SLP_CTX_MSTATUS(t0) + csrr t2, mtvec + sw t2, RV_SLP_CTX_MTVEC(t0) + csrr t3, mcause + sw t3, RV_SLP_CTX_MCAUSE(t0) + + csrr t1, mtval + sw t1, RV_SLP_CTX_MTVAL(t0) + csrr t2, mie + sw t2, RV_SLP_CTX_MIE(t0) + csrr t3, mip + sw t3, RV_SLP_CTX_MIP(t0) + csrr t1, mepc + sw t1, RV_SLP_CTX_MEPC(t0) + + /* + !!! Let idf knows it's going to sleep !!! + + RV_SLP_STK_PMUFUNC field is used to identify whether it is going to sleep or + has just been awakened. We use the lowest 2 bits as indication information, + 3 means being awakened, 1 means going to sleep. + */ + li t1, ~0x3 + lw t2, RV_SLP_CTX_PMUFUNC(t0) + and t2, t1, t2 + ori t2, t2, 0x1 + sw t2, RV_SLP_CTX_PMUFUNC(t0) + + mv t3, t0 + csrr t0, mscratch + sw t0, RV_SLP_CTX_T0(t3) + +#if !CONFIG_IDF_TARGET_ESP32C6 + /* writeback dcache is required here!!! */ + la t0, EXTMEM_CACHE_SYNC_MAP_REG + li t1, 0x10 + sw t1, 0x0(t0) /* set EXTMEM_CACHE_SYNC_MAP_REG bit 4 */ + la t2, EXTMEM_CACHE_SYNC_ADDR_REG + sw zero, 0x0(t2) /* clear EXTMEM_CACHE_SYNC_ADDR_REG */ + la t0, EXTMEM_CACHE_SYNC_SIZE_REG + sw zero, 0x0(t0) /* clear EXTMEM_CACHE_SYNC_SIZE_REG */ + + la t1, EXTMEM_CACHE_SYNC_CTRL_REG + lw t2, 0x0(t1) + ori t2, t2, 0x4 + sw t2, 0x0(t1) + + li t0, 0x10 /* SYNC_DONE bit */ +wait_sync_done: + lw t2, 0x0(t1) + and t2, t0, t2 + beqz t2, wait_sync_done +#endif + + lw t0, RV_SLP_CTX_T0(t3) + lw t1, RV_SLP_CTX_T1(t3) + lw t2, RV_SLP_CTX_T2(t3) + lw t3, RV_SLP_CTX_T3(t3) + + ret + + .size rv_core_critical_regs_save, . - rv_core_critical_regs_save + + +#define CSR_PCER_U 0x800 +#define CSR_PCMR_U 0x801 +#define PCER_CYCLES (1<<0) /* count clock cycles */ +#define PCMR_GLOBAL_EN (1<<0) /* enable count */ +#define pcer CSR_PCER_U +#define pcmr CSR_PCMR_U + +/* +-------------------------------------------------------------------------------- + This assembly subroutine is used to restore the CPU core critical register + context before sleep after system wakes up, modify the PMU control + information, and return the critical register context memory object pointer. + After the subroutine returns, continue to restore other modules of the + system. +-------------------------------------------------------------------------------- +*/ + + .section .iram1,"ax" + .global rv_core_critical_regs_restore + .type rv_core_critical_regs_restore,@function + .align 4 + +rv_core_critical_regs_restore: + + la t0, rv_core_critical_regs_frame + lw t0, 0(t0) /* t0 pointer to RvCoreCriticalSleepFrame object */ + beqz t0, .skip_restore /* make sure we do not jump to zero address */ + + /* + !!! Let idf knows it's sleep awake. !!! + + RV_SLP_STK_PMUFUNC field is used to identify whether it is going to sleep or + has just been awakened. We use the lowest 2 bits as indication information, + 3 means being awakened, 1 means going to sleep. + */ + lw t1, RV_SLP_CTX_PMUFUNC(t0) + ori t1, t1, 0x3 + sw t1, RV_SLP_CTX_PMUFUNC(t0) + + lw t2, RV_SLP_CTX_MEPC(t0) + csrw mepc, t2 + lw t3, RV_SLP_CTX_MIP(t0) + csrw mip, t3 + lw t1, RV_SLP_CTX_MIE(t0) + csrw mie, t1 + lw t2, RV_SLP_CTX_MSTATUS(t0) + csrw mstatus, t2 + + lw t3, RV_SLP_CTX_MTVEC(t0) + csrw mtvec, t3 + lw t1, RV_SLP_CTX_MCAUSE(t0) + csrw mcause, t1 + lw t2, RV_SLP_CTX_MTVAL(t0) + csrw mtval, t2 + + lw t6, RV_SLP_CTX_T6(t0) + lw t5, RV_SLP_CTX_T5(t0) + lw t4, RV_SLP_CTX_T4(t0) + lw t3, RV_SLP_CTX_T3(t0) + lw s11, RV_SLP_CTX_S11(t0) + lw s10, RV_SLP_CTX_S10(t0) + lw s9, RV_SLP_CTX_S9(t0) + lw s8, RV_SLP_CTX_S8(t0) + lw s7, RV_SLP_CTX_S7(t0) + lw s6, RV_SLP_CTX_S6(t0) + lw s5, RV_SLP_CTX_S5(t0) + lw s4, RV_SLP_CTX_S4(t0) + lw s3, RV_SLP_CTX_S3(t0) + lw s2, RV_SLP_CTX_S2(t0) + lw a7, RV_SLP_CTX_A7(t0) + lw a6, RV_SLP_CTX_A6(t0) + lw a5, RV_SLP_CTX_A5(t0) + lw a4, RV_SLP_CTX_A4(t0) + lw a3, RV_SLP_CTX_A3(t0) + lw a2, RV_SLP_CTX_A2(t0) + lw a1, RV_SLP_CTX_A1(t0) + lw a0, RV_SLP_CTX_A0(t0) + lw s1, RV_SLP_CTX_S1(t0) + lw s0, RV_SLP_CTX_S0(t0) + lw t2, RV_SLP_CTX_T2(t0) + lw t1, RV_SLP_CTX_T1(t0) + lw tp, RV_SLP_CTX_TP(t0) + lw gp, RV_SLP_CTX_GP(t0) + lw sp, RV_SLP_CTX_SP(t0) + lw ra, RV_SLP_CTX_RA(t0) + lw t0, RV_SLP_CTX_T0(t0) + +.skip_restore: + ret + + .size rv_core_critical_regs_restore, . - rv_core_critical_regs_restore diff --git a/components/esp_rom/include/esp32c6/rom/rtc.h b/components/esp_rom/include/esp32c6/rom/rtc.h index 844f010147..3fba551945 100644 --- a/components/esp_rom/include/esp32c6/rom/rtc.h +++ b/components/esp_rom/include/esp32c6/rom/rtc.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -32,7 +32,7 @@ extern "C" { * Please do not use reserved or used rtc memory or registers. * * * ************************************************************************************* - * RTC Memory & Store Register usage + * LP Memory & Store Register usage ************************************************************************************* * rtc memory addr type size usage * 0x3f421000(0x50000000) Slow SIZE_CP Co-Processor code/Reset Entry @@ -42,25 +42,29 @@ extern "C" { * ************************************************************************************* * RTC store registers usage - * RTC_CNTL_STORE0_REG Reserved - * RTC_CNTL_STORE1_REG RTC_SLOW_CLK calibration value - * RTC_CNTL_STORE2_REG Boot time, low word - * RTC_CNTL_STORE3_REG Boot time, high word - * RTC_CNTL_STORE4_REG External XTAL frequency - * RTC_CNTL_STORE5_REG APB bus frequency - * RTC_CNTL_STORE6_REG FAST_RTC_MEMORY_ENTRY - * RTC_CNTL_STORE7_REG FAST_RTC_MEMORY_CRC + * LP_AON_STORE0_REG Reserved + * LP_AON_STORE1_REG RTC_SLOW_CLK calibration value + * LP_AON_STORE2_REG Boot time, low word + * LP_AON_STORE3_REG Boot time, high word + * LP_AON_STORE4_REG External XTAL frequency + * LP_AON_STORE5_REG FAST_RTC_MEMORY_LENGTH + * LP_AON_STORE6_REG FAST_RTC_MEMORY_ENTRY + * LP_AON_STORE7_REG FAST_RTC_MEMORY_CRC + * LP_AON_STORE8_REG Store light sleep wake stub addr + * LP_AON_STORE9_REG Store the sleep mode at bit[0] (0:light sleep 1:deep sleep) ************************************************************************************* */ -#define RTC_SLOW_CLK_CAL_REG LP_AON_STORE1_REG -#define RTC_BOOT_TIME_LOW_REG LP_AON_STORE2_REG -#define RTC_BOOT_TIME_HIGH_REG LP_AON_STORE3_REG -#define RTC_XTAL_FREQ_REG LP_AON_STORE4_REG -#define RTC_APB_FREQ_REG LP_AON_STORE5_REG -#define RTC_ENTRY_ADDR_REG LP_AON_STORE6_REG -#define RTC_RESET_CAUSE_REG LP_AON_STORE6_REG -#define RTC_MEMORY_CRC_REG LP_AON_STORE7_REG +#define RTC_SLOW_CLK_CAL_REG LP_AON_STORE1_REG +#define RTC_BOOT_TIME_LOW_REG LP_AON_STORE2_REG +#define RTC_BOOT_TIME_HIGH_REG LP_AON_STORE3_REG +#define RTC_XTAL_FREQ_REG LP_AON_STORE4_REG +#define RTC_ENTRY_LENGTH_REG LP_AON_STORE5_REG +#define RTC_ENTRY_ADDR_REG LP_AON_STORE6_REG +#define RTC_RESET_CAUSE_REG LP_AON_STORE6_REG +#define RTC_MEMORY_CRC_REG LP_AON_STORE7_REG +#define LIGHT_SLEEP_WAKE_STUB_ADDR_REG LP_AON_STORE8_REG +#define SLEEP_MODE_REG LP_AON_STORE9_REG #define RTC_DISABLE_ROM_LOG ((1 << 0) | (1 << 16)) //!< Disable logging from the ROM code. diff --git a/components/riscv/include/riscv/rvsleep-frames.h b/components/riscv/include/riscv/rvsleep-frames.h new file mode 100644 index 0000000000..06b2b75d8c --- /dev/null +++ b/components/riscv/include/riscv/rvsleep-frames.h @@ -0,0 +1,153 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __RVSLEEP_FRAMES_H__ +#define __RVSLEEP_FRAMES_H__ + +/* Align a value up to nearest n-byte boundary, where n is a power of 2. */ +#define ALIGNUP(n, val) (((val) + (n) - 1) & -(n)) + +#ifdef STRUCT_BEGIN +#undef STRUCT_BEGIN +#undef STRUCT_FIELD +#undef STRUCT_AFIELD +#undef STRUCT_END +#endif + +#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) +#ifdef __clang__ +#define STRUCT_BEGIN .set RV_STRUCT_OFFSET, 0 +#define STRUCT_FIELD(ctype,size,asname,name) .set asname, RV_STRUCT_OFFSET; .set RV_STRUCT_OFFSET, asname + size +#define STRUCT_AFIELD(ctype,size,asname,name,n) .set asname, RV_STRUCT_OFFSET;\ + .set RV_STRUCT_OFFSET, asname + (size)*(n); +#define STRUCT_END(sname) .set sname##Size, RV_STRUCT_OFFSET; +#else // __clang__ +#define STRUCT_BEGIN .pushsection .text; .struct 0 +#define STRUCT_FIELD(ctype,size,asname,name) asname: .space size +#define STRUCT_AFIELD(ctype,size,asname,name,n) asname: .space (size)*(n) +#define STRUCT_END(sname) sname##Size:; .popsection +#endif // __clang__ +#else +#define STRUCT_BEGIN typedef struct { +#define STRUCT_FIELD(ctype,size,asname,name) ctype name; +#define STRUCT_AFIELD(ctype,size,asname,name,n) ctype name[n]; +#define STRUCT_END(sname) } sname; +#endif + +/* + * ------------------------------------------------------------------------------- + * RISC-V CORE CRITICAL REGISTER CONTEXT LAYOUT FOR SLEEP + * ------------------------------------------------------------------------------- + */ +STRUCT_BEGIN + STRUCT_FIELD (long, 4, RV_SLP_CTX_MEPC, mepc) /* Machine Exception Program Counter */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_RA, ra) /* Return address */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_SP, sp) /* Stack pointer */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_GP, gp) /* Global pointer */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_TP, tp) /* Thread pointer */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_T0, t0) /* Temporary/alternate link register */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_T1, t1) /* t1-2: Temporaries */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_T2, t2) + STRUCT_FIELD (long, 4, RV_SLP_CTX_S0, s0) /* Saved register/frame pointer */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_S1, s1) /* Saved register */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_A0, a0) /* a0-1: Function arguments/return address */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_A1, a1) + STRUCT_FIELD (long, 4, RV_SLP_CTX_A2, a2) /* a2-7: Function arguments */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_A3, a3) + STRUCT_FIELD (long, 4, RV_SLP_CTX_A4, a4) + STRUCT_FIELD (long, 4, RV_SLP_CTX_A5, a5) + STRUCT_FIELD (long, 4, RV_SLP_CTX_A6, a6) + STRUCT_FIELD (long, 4, RV_SLP_CTX_A7, a7) + STRUCT_FIELD (long, 4, RV_SLP_CTX_S2, s2) /* s2-11: Saved registers */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_S3, s3) + STRUCT_FIELD (long, 4, RV_SLP_CTX_S4, s4) + STRUCT_FIELD (long, 4, RV_SLP_CTX_S5, s5) + STRUCT_FIELD (long, 4, RV_SLP_CTX_S6, s6) + STRUCT_FIELD (long, 4, RV_SLP_CTX_S7, s7) + STRUCT_FIELD (long, 4, RV_SLP_CTX_S8, s8) + STRUCT_FIELD (long, 4, RV_SLP_CTX_S9, s9) + STRUCT_FIELD (long, 4, RV_SLP_CTX_S10, s10) + STRUCT_FIELD (long, 4, RV_SLP_CTX_S11, s11) + STRUCT_FIELD (long, 4, RV_SLP_CTX_T3, t3) /* t3-6: Temporaries */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_T4, t4) + STRUCT_FIELD (long, 4, RV_SLP_CTX_T5, t5) + STRUCT_FIELD (long, 4, RV_SLP_CTX_T6, t6) + STRUCT_FIELD (long, 4, RV_SLP_CTX_MSTATUS, mstatus) /* Machine Status */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_MTVEC, mtvec) /* Machine Trap-Vector Base Address */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_MCAUSE, mcause) /* Machine Trap Cause */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_MTVAL, mtval) /* Machine Trap Value */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_MIE, mie) /* Machine intr enable */ + STRUCT_FIELD (long, 4, RV_SLP_CTX_MIP, mip) /* Machine intr pending */ + + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMUFUNC, pmufunc) /* A field is used to identify whether it is going + * to sleep or has just been awakened. We use the + * lowest 2 bits as indication infomation, 3 means + * being awakened, 1 means going to sleep */ +STRUCT_END(RvCoreCriticalSleepFrame) + +#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) +#define RV_SLEEP_CTX_SZ1 RvCoreCriticalSleepFrameSize +#else +#define RV_SLEEP_CTX_SZ1 sizeof(RvCoreCriticalSleepFrame) +#endif + +/* + * Sleep stack frame size, after align up to 16 bytes boundary + */ +#define RV_SLEEP_CTX_FRMSZ (ALIGNUP(0x10, RV_SLEEP_CTX_SZ1)) + +/* + * ------------------------------------------------------------------------------- + * RISC-V CORE NON-CRITICAL REGISTER CONTEXT LAYOUT FOR SLEEP + * ------------------------------------------------------------------------------- + */ +STRUCT_BEGIN + STRUCT_FIELD (long, 4, RV_SLP_CTX_MSCRATCH, mscratch) + STRUCT_FIELD (long, 4, RV_SLP_CTX_MIDELEG, mideleg) + STRUCT_FIELD (long, 4, RV_SLP_CTX_MISA, misa) + STRUCT_FIELD (long, 4, RV_SLP_CTX_TSELECT, tselect) + STRUCT_FIELD (long, 4, RV_SLP_CTX_TDATA1, tdata1) + STRUCT_FIELD (long, 4, RV_SLP_CTX_TDATA2, tdata2) + STRUCT_FIELD (long, 4, RV_SLP_CTX_TCONTROL, tcontrol) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG0, pmpcfg0) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG1, pmpcfg1) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG2, pmpcfg2) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG3, pmpcfg3) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR0, pmpaddr0) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR1, pmpaddr1) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR2, pmpaddr2) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR3, pmpaddr3) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR4, pmpaddr4) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR5, pmpaddr5) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR6, pmpaddr6) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR7, pmpaddr7) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR8, pmpaddr8) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR9, pmpaddr9) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR10, pmpaddr10) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR11, pmpaddr11) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR12, pmpaddr12) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR13, pmpaddr13) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR14, pmpaddr14) + STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR15, pmpaddr15) + + STRUCT_FIELD (long, 4, RV_SLP_CTX_UTVEC, utvec) + STRUCT_FIELD (long, 4, RV_SLP_CTX_USTATUS, ustatus) + STRUCT_FIELD (long, 4, RV_SLP_CTX_UEPC, uepc) + STRUCT_FIELD (long, 4, RV_SLP_CTX_UCAUSE, ucause) + + STRUCT_FIELD (long, 4, RV_SLP_CTX_MPCER, mpcer) + STRUCT_FIELD (long, 4, RV_SLP_CTX_MPCMR, mpcmr) + STRUCT_FIELD (long, 4, RV_SLP_CTX_MPCCR, mpccr) + STRUCT_FIELD (long, 4, RV_SLP_CTX_CPU_TESTBUS_CTRL, cpu_testbus_ctrl) + STRUCT_FIELD (long, 4, RV_SLP_CTX_UPCER, upcer) + STRUCT_FIELD (long, 4, RV_SLP_CTX_UPCMR, upcmr) + STRUCT_FIELD (long, 4, RV_SLP_CTX_UPCCR, upccr) + STRUCT_FIELD (long, 4, RV_SLP_CTX_UGPIO_OEN, ugpio_oen) + STRUCT_FIELD (long, 4, RV_SLP_CTX_UGPIO_IN, ugpio_in) + STRUCT_FIELD (long, 4, RV_SLP_CTX_UGPIO_OUT, ugpio_out) +STRUCT_END(RvCoreNonCriticalSleepFrame) + +#endif /* #ifndef __RVSLEEP_FRAMES_H__ */ diff --git a/tools/ci/check_public_headers_exceptions.txt b/tools/ci/check_public_headers_exceptions.txt index acbbb06184..024e6b9eb6 100644 --- a/tools/ci/check_public_headers_exceptions.txt +++ b/tools/ci/check_public_headers_exceptions.txt @@ -156,3 +156,4 @@ components/espcoredump/include/port/xtensa/esp_core_dump_summary_port.h components/riscv/include/esp_private/panic_reason.h components/riscv/include/riscv/interrupt.h components/riscv/include/riscv/rvruntime-frames.h +components/riscv/include/riscv/rvsleep-frames.h From a5467f42a0cc1be8fcae893739227d692ad35d86 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Tue, 17 Jan 2023 19:22:41 +0800 Subject: [PATCH 13/16] codeclean: only S series chip VDDSDIO is configurable --- components/bootloader/Kconfig.projbuild | 1 + components/esp_hw_support/linker.lf | 3 +- .../esp_hw_support/port/esp32c2/rtc_init.c | 10 ----- .../esp_hw_support/port/esp32c3/rtc_init.c | 37 ------------------- .../esp_hw_support/port/esp32h4/rtc_init.c | 37 ------------------- components/esp_hw_support/sleep_modes.c | 13 +++---- components/esp_pm/linker.lf | 3 +- .../soc/esp32/include/soc/Kconfig.soc_caps.in | 4 ++ components/soc/esp32/include/soc/soc_caps.h | 2 + components/soc/esp32c2/include/soc/rtc.h | 31 ---------------- components/soc/esp32c3/include/soc/rtc.h | 31 ---------------- components/soc/esp32c6/include/soc/rtc.h | 31 ---------------- components/soc/esp32h2/include/soc/rtc.h | 31 ---------------- components/soc/esp32h4/include/soc/rtc.h | 30 --------------- .../esp32s2/include/soc/Kconfig.soc_caps.in | 4 ++ components/soc/esp32s2/include/soc/soc_caps.h | 2 + .../esp32s3/include/soc/Kconfig.soc_caps.in | 4 ++ components/soc/esp32s3/include/soc/soc_caps.h | 1 + 18 files changed, 28 insertions(+), 247 deletions(-) diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index 38f5aa2ec9..761f187033 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -94,6 +94,7 @@ menu "Bootloader config" choice BOOTLOADER_VDDSDIO_BOOST bool "VDDSDIO LDO voltage" default BOOTLOADER_VDDSDIO_BOOST_1_9V + depends on SOC_CONFIGURABLE_VDDSDIO_SUPPORTED help If this option is enabled, and VDDSDIO LDO is set to 1.8V (using eFuse or MTDI bootstrapping pin), bootloader will change LDO settings to diff --git a/components/esp_hw_support/linker.lf b/components/esp_hw_support/linker.lf index 7f093b2e06..dde67db6a4 100644 --- a/components/esp_hw_support/linker.lf +++ b/components/esp_hw_support/linker.lf @@ -13,8 +13,9 @@ entries: cpu: esp_cpu_compare_and_set (noflash) esp_memory_utils (noflash) rtc_clk (noflash) - if IDF_TARGET_ESP32C6 = n && IDF_TARGET_ESP32H2 = n: # TODO: IDF-5645 + if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED: rtc_init:rtc_vddsdio_set_config (noflash) + if IDF_TARGET_ESP32C6 = n && IDF_TARGET_ESP32H2 = n: # TODO: IDF-5645 rtc_pm (noflash_text) rtc_sleep (noflash_text) rtc_time (noflash_text) diff --git a/components/esp_hw_support/port/esp32c2/rtc_init.c b/components/esp_hw_support/port/esp32c2/rtc_init.c index 277b2a0acd..abb5370c67 100644 --- a/components/esp_hw_support/port/esp32c2/rtc_init.c +++ b/components/esp_hw_support/port/esp32c2/rtc_init.c @@ -129,16 +129,6 @@ void rtc_init(rtc_config_t cfg) #endif } -rtc_vddsdio_config_t rtc_vddsdio_get_config(void) -{ - rtc_vddsdio_config_t result = {0}; - return result; -} - -void rtc_vddsdio_set_config(rtc_vddsdio_config_t config) -{ -} - static void set_ocode_by_efuse(int ocode_scheme_ver) { assert(ocode_scheme_ver == 1); diff --git a/components/esp_hw_support/port/esp32c3/rtc_init.c b/components/esp_hw_support/port/esp32c3/rtc_init.c index 4692562138..e3f75bb0ff 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_init.c +++ b/components/esp_hw_support/port/esp32c3/rtc_init.c @@ -159,43 +159,6 @@ void rtc_init(rtc_config_t cfg) #endif } -rtc_vddsdio_config_t rtc_vddsdio_get_config(void) -{ - rtc_vddsdio_config_t result; - uint32_t sdio_conf_reg = REG_READ(RTC_CNTL_SDIO_CONF_REG); - result.drefh = (sdio_conf_reg & RTC_CNTL_DREFH_SDIO_M) >> RTC_CNTL_DREFH_SDIO_S; - result.drefm = (sdio_conf_reg & RTC_CNTL_DREFM_SDIO_M) >> RTC_CNTL_DREFM_SDIO_S; - result.drefl = (sdio_conf_reg & RTC_CNTL_DREFL_SDIO_M) >> RTC_CNTL_DREFL_SDIO_S; - if (sdio_conf_reg & RTC_CNTL_SDIO_FORCE) { - // Get configuration from RTC - result.force = 1; - result.enable = (sdio_conf_reg & RTC_CNTL_XPD_SDIO_REG_M) >> RTC_CNTL_XPD_SDIO_REG_S; - result.tieh = (sdio_conf_reg & RTC_CNTL_SDIO_TIEH_M) >> RTC_CNTL_SDIO_TIEH_S; - return result; - } else { - result.force = 0; - } - - // Otherwise, VDD_SDIO is controlled by bootstrapping pin - uint32_t strap_reg = REG_READ(GPIO_STRAP_REG); - result.force = 0; - result.tieh = (strap_reg & BIT(5)) ? RTC_VDDSDIO_TIEH_1_8V : RTC_VDDSDIO_TIEH_3_3V; - result.enable = 1; - return result; -} - -void rtc_vddsdio_set_config(rtc_vddsdio_config_t config) -{ - uint32_t val = 0; - val |= (config.force << RTC_CNTL_SDIO_FORCE_S); - val |= (config.enable << RTC_CNTL_XPD_SDIO_REG_S); - val |= (config.drefh << RTC_CNTL_DREFH_SDIO_S); - val |= (config.drefm << RTC_CNTL_DREFM_SDIO_S); - val |= (config.drefl << RTC_CNTL_DREFL_SDIO_S); - val |= (config.tieh << RTC_CNTL_SDIO_TIEH_S); - val |= RTC_CNTL_SDIO_PD_EN; - REG_WRITE(RTC_CNTL_SDIO_CONF_REG, val); -} static void set_ocode_by_efuse(int calib_version) { diff --git a/components/esp_hw_support/port/esp32h4/rtc_init.c b/components/esp_hw_support/port/esp32h4/rtc_init.c index 04867ab772..40174e3682 100644 --- a/components/esp_hw_support/port/esp32h4/rtc_init.c +++ b/components/esp_hw_support/port/esp32h4/rtc_init.c @@ -174,40 +174,3 @@ void dslp_osc_pd(void){ REG_SET_FIELD(RTC_CNTL_RC32K_CTRL_REG,RTC_CNTL_RC32K_XPD, 0); REG_SET_FIELD(RTC_CNTL_PLL8M_REG, RTC_CNTL_XPD_PLL8M, 0); } -rtc_vddsdio_config_t rtc_vddsdio_get_config(void) -{ - rtc_vddsdio_config_t result; - uint32_t sdio_conf_reg = REG_READ(RTC_CNTL_SDIO_CONF_REG); - result.drefh = (sdio_conf_reg & RTC_CNTL_DREFH_SDIO_M) >> RTC_CNTL_DREFH_SDIO_S; - result.drefm = (sdio_conf_reg & RTC_CNTL_DREFM_SDIO_M) >> RTC_CNTL_DREFM_SDIO_S; - result.drefl = (sdio_conf_reg & RTC_CNTL_DREFL_SDIO_M) >> RTC_CNTL_DREFL_SDIO_S; - if (sdio_conf_reg & RTC_CNTL_SDIO_FORCE) { - // Get configuration from RTC - result.force = 1; - result.enable = (sdio_conf_reg & RTC_CNTL_XPD_SDIO_REG_M) >> RTC_CNTL_XPD_SDIO_REG_S; - result.tieh = (sdio_conf_reg & RTC_CNTL_SDIO_TIEH_M) >> RTC_CNTL_SDIO_TIEH_S; - return result; - } else { - result.force = 0; - } - - // Otherwise, VDD_SDIO is controlled by bootstrapping pin - uint32_t strap_reg = REG_READ(GPIO_STRAP_REG); - result.force = 0; - result.tieh = (strap_reg & BIT(5)) ? RTC_VDDSDIO_TIEH_1_8V : RTC_VDDSDIO_TIEH_3_3V; - result.enable = 1; - return result; -} - -void rtc_vddsdio_set_config(rtc_vddsdio_config_t config) -{ - uint32_t val = 0; - val |= (config.force << RTC_CNTL_SDIO_FORCE_S); - val |= (config.enable << RTC_CNTL_XPD_SDIO_REG_S); - val |= (config.drefh << RTC_CNTL_DREFH_SDIO_S); - val |= (config.drefm << RTC_CNTL_DREFM_SDIO_S); - val |= (config.drefl << RTC_CNTL_DREFL_SDIO_S); - val |= (config.tieh << RTC_CNTL_SDIO_TIEH_S); - val |= RTC_CNTL_SDIO_PD_EN; - REG_WRITE(RTC_CNTL_SDIO_CONF_REG, val); -} diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 51b79a8480..b0deb421d2 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -649,12 +649,10 @@ void IRAM_ATTR esp_deep_sleep_start(void) */ #if !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150 static esp_err_t esp_light_sleep_inner(uint32_t pd_flags, - uint32_t flash_enable_time_us, - rtc_vddsdio_config_t vddsdio_config) IRAM_ATTR __attribute__((noinline)); + uint32_t flash_enable_time_us) IRAM_ATTR __attribute__((noinline)); static esp_err_t esp_light_sleep_inner(uint32_t pd_flags, - uint32_t flash_enable_time_us, - rtc_vddsdio_config_t vddsdio_config) + uint32_t flash_enable_time_us) { #if CONFIG_IDF_TARGET_ESP32C6 return ESP_ERR_NOT_SUPPORTED; // TODO: WIFI-5150 @@ -662,11 +660,14 @@ static esp_err_t esp_light_sleep_inner(uint32_t pd_flags, // Enter sleep uint32_t reject = esp_sleep_start(pd_flags); +#if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED + rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config(); // If VDDSDIO regulator was controlled by RTC registers before sleep, // restore the configuration. if (vddsdio_config.force) { rtc_vddsdio_set_config(vddsdio_config); } +#endif // If SPI flash was powered down, wait for it to become ready if (pd_flags & RTC_SLEEP_PD_VDDSDIO) { @@ -828,8 +829,6 @@ esp_err_t esp_light_sleep_start(void) periph_inform_out_light_sleep_overhead(s_config.sleep_time_adjustment - sleep_time_overhead_in); - rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config(); - // Safety net: enable WDT in case exit from light sleep fails #if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 // TODO: IDF-5653 wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &LP_WDT}; @@ -858,7 +857,7 @@ esp_err_t esp_light_sleep_start(void) err = ESP_ERR_SLEEP_TOO_SHORT_SLEEP_DURATION; } else { // Enter sleep, then wait for flash to be ready on wakeup - err = esp_light_sleep_inner(pd_flags, flash_enable_time_us, vddsdio_config); + err = esp_light_sleep_inner(pd_flags, flash_enable_time_us); } // light sleep wakeup flag only makes sense after a successful light sleep diff --git a/components/esp_pm/linker.lf b/components/esp_pm/linker.lf index eacfc0cc2b..cad3fb2397 100644 --- a/components/esp_pm/linker.lf +++ b/components/esp_pm/linker.lf @@ -15,7 +15,8 @@ entries: sleep_modes:esp_sleep_enable_timer_wakeup (noflash) sleep_modes:timer_wakeup_prepare (noflash) sleep_modes:get_power_down_flags (noflash) - rtc_init:rtc_vddsdio_get_config (noflash) + if SOC_CONFIGURABLE_VDDSDIO_SUPPORTED: + rtc_init:rtc_vddsdio_get_config (noflash) esp_clk:esp_clk_slowclk_cal_set (noflash) esp_clk:esp_clk_slowclk_cal_get (noflash) esp_clk:esp_rtc_get_time_us (noflash) diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index 2f0f687b25..7d015b5064 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -747,6 +747,10 @@ config SOC_PM_SUPPORT_VDDSDIO_PD bool default y +config SOC_CONFIGURABLE_VDDSDIO_SUPPORTED + bool + default y + config SOC_CLK_APLL_SUPPORTED bool default y diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index cded5d102d..ccabb3b234 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -375,6 +375,8 @@ #define SOC_PM_SUPPORT_RC_FAST_PD (1) #define SOC_PM_SUPPORT_VDDSDIO_PD (1) +#define SOC_CONFIGURABLE_VDDSDIO_SUPPORTED (1) + /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ #define SOC_CLK_APLL_SUPPORTED (1) // apll_multiplier_out = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) diff --git a/components/soc/esp32c2/include/soc/rtc.h b/components/soc/esp32c2/include/soc/rtc.h index 2331a29758..b922a3b2eb 100644 --- a/components/soc/esp32c2/include/soc/rtc.h +++ b/components/soc/esp32c2/include/soc/rtc.h @@ -722,37 +722,6 @@ typedef struct { */ void rtc_init(rtc_config_t cfg); -/** - * Structure describing vddsdio configuration - */ -typedef struct { - uint32_t force : 1; //!< If 1, use configuration from RTC registers; if 0, use EFUSE/bootstrapping pins. - uint32_t enable : 1; //!< Enable VDDSDIO regulator - uint32_t tieh : 1; //!< Select VDDSDIO voltage. One of RTC_VDDSDIO_TIEH_1_8V, RTC_VDDSDIO_TIEH_3_3V - uint32_t drefh : 2; //!< Tuning parameter for VDDSDIO regulator - uint32_t drefm : 2; //!< Tuning parameter for VDDSDIO regulator - uint32_t drefl : 2; //!< Tuning parameter for VDDSDIO regulator -} rtc_vddsdio_config_t; - -/** - * Get current VDDSDIO configuration - * If VDDSDIO configuration is overridden by RTC, get values from RTC - * Otherwise, if VDDSDIO is configured by EFUSE, get values from EFUSE - * Otherwise, use default values and the level of MTDI bootstrapping pin. - * @return currently used VDDSDIO configuration - */ -rtc_vddsdio_config_t rtc_vddsdio_get_config(void); - -/** - * Set new VDDSDIO configuration using RTC registers. - * If config.force == 1, this overrides configuration done using bootstrapping - * pins and EFUSE. - * - * @param config new VDDSDIO configuration - */ -void rtc_vddsdio_set_config(rtc_vddsdio_config_t config); - - // -------------------------- CLOCK TREE DEFS ALIAS ---------------------------- // **WARNING**: The following are only for backwards compatibility. // Please use the declarations in soc/clk_tree_defs.h instead. diff --git a/components/soc/esp32c3/include/soc/rtc.h b/components/soc/esp32c3/include/soc/rtc.h index 0e10a3181e..8b56920082 100644 --- a/components/soc/esp32c3/include/soc/rtc.h +++ b/components/soc/esp32c3/include/soc/rtc.h @@ -764,37 +764,6 @@ typedef struct { */ void rtc_init(rtc_config_t cfg); -/** - * Structure describing vddsdio configuration - */ -typedef struct { - uint32_t force : 1; //!< If 1, use configuration from RTC registers; if 0, use EFUSE/bootstrapping pins. - uint32_t enable : 1; //!< Enable VDDSDIO regulator - uint32_t tieh : 1; //!< Select VDDSDIO voltage. One of RTC_VDDSDIO_TIEH_1_8V, RTC_VDDSDIO_TIEH_3_3V - uint32_t drefh : 2; //!< Tuning parameter for VDDSDIO regulator - uint32_t drefm : 2; //!< Tuning parameter for VDDSDIO regulator - uint32_t drefl : 2; //!< Tuning parameter for VDDSDIO regulator -} rtc_vddsdio_config_t; - -/** - * Get current VDDSDIO configuration - * If VDDSDIO configuration is overridden by RTC, get values from RTC - * Otherwise, if VDDSDIO is configured by EFUSE, get values from EFUSE - * Otherwise, use default values and the level of MTDI bootstrapping pin. - * @return currently used VDDSDIO configuration - */ -rtc_vddsdio_config_t rtc_vddsdio_get_config(void); - -/** - * Set new VDDSDIO configuration using RTC registers. - * If config.force == 1, this overrides configuration done using bootstrapping - * pins and EFUSE. - * - * @param config new VDDSDIO configuration - */ -void rtc_vddsdio_set_config(rtc_vddsdio_config_t config); - - // -------------------------- CLOCK TREE DEFS ALIAS ---------------------------- // **WARNING**: The following are only for backwards compatibility. // Please use the declarations in soc/clk_tree_defs.h instead. diff --git a/components/soc/esp32c6/include/soc/rtc.h b/components/soc/esp32c6/include/soc/rtc.h index a2bd881c3b..000f15b1e8 100644 --- a/components/soc/esp32c6/include/soc/rtc.h +++ b/components/soc/esp32c6/include/soc/rtc.h @@ -714,37 +714,6 @@ typedef struct { */ void rtc_init(rtc_config_t cfg); -/** - * Structure describing vddsdio configuration - */ -typedef struct { - uint32_t force : 1; //!< If 1, use configuration from RTC registers; if 0, use EFUSE/bootstrapping pins. - uint32_t enable : 1; //!< Enable VDDSDIO regulator - uint32_t tieh : 1; //!< Select VDDSDIO voltage. One of RTC_VDDSDIO_TIEH_1_8V, RTC_VDDSDIO_TIEH_3_3V - uint32_t drefh : 2; //!< Tuning parameter for VDDSDIO regulator - uint32_t drefm : 2; //!< Tuning parameter for VDDSDIO regulator - uint32_t drefl : 2; //!< Tuning parameter for VDDSDIO regulator -} rtc_vddsdio_config_t; - -/** - * Get current VDDSDIO configuration - * If VDDSDIO configuration is overridden by RTC, get values from RTC - * Otherwise, if VDDSDIO is configured by EFUSE, get values from EFUSE - * Otherwise, use default values and the level of MTDI bootstrapping pin. - * @return currently used VDDSDIO configuration - */ -rtc_vddsdio_config_t rtc_vddsdio_get_config(void); - -/** - * Set new VDDSDIO configuration using RTC registers. - * If config.force == 1, this overrides configuration done using bootstrapping - * pins and EFUSE. - * - * @param config new VDDSDIO configuration - */ -void rtc_vddsdio_set_config(rtc_vddsdio_config_t config); - - // -------------------------- CLOCK TREE DEFS ALIAS ---------------------------- // **WARNING**: The following are only for backwards compatibility. // Please use the declarations in soc/clk_tree_defs.h instead. diff --git a/components/soc/esp32h2/include/soc/rtc.h b/components/soc/esp32h2/include/soc/rtc.h index ebccc6c12a..2c15f6fc14 100644 --- a/components/soc/esp32h2/include/soc/rtc.h +++ b/components/soc/esp32h2/include/soc/rtc.h @@ -769,37 +769,6 @@ typedef struct { */ void rtc_init(rtc_config_t cfg); -/** - * Structure describing vddsdio configuration - */ -typedef struct { - uint32_t force : 1; //!< If 1, use configuration from RTC registers; if 0, use EFUSE/bootstrapping pins. - uint32_t enable : 1; //!< Enable VDDSDIO regulator - uint32_t tieh : 1; //!< Select VDDSDIO voltage. One of RTC_VDDSDIO_TIEH_1_8V, RTC_VDDSDIO_TIEH_3_3V - uint32_t drefh : 2; //!< Tuning parameter for VDDSDIO regulator - uint32_t drefm : 2; //!< Tuning parameter for VDDSDIO regulator - uint32_t drefl : 2; //!< Tuning parameter for VDDSDIO regulator -} rtc_vddsdio_config_t; - -/** - * Get current VDDSDIO configuration - * If VDDSDIO configuration is overridden by RTC, get values from RTC - * Otherwise, if VDDSDIO is configured by EFUSE, get values from EFUSE - * Otherwise, use default values and the level of MTDI bootstrapping pin. - * @return currently used VDDSDIO configuration - */ -rtc_vddsdio_config_t rtc_vddsdio_get_config(void); - -/** - * Set new VDDSDIO configuration using RTC registers. - * If config.force == 1, this overrides configuration done using bootstrapping - * pins and EFUSE. - * - * @param config new VDDSDIO configuration - */ -void rtc_vddsdio_set_config(rtc_vddsdio_config_t config); - - // -------------------------- CLOCK TREE DEFS ALIAS ---------------------------- // **WARNING**: The following are only for backwards compatibility. // Please use the declarations in soc/clk_tree_defs.h instead. diff --git a/components/soc/esp32h4/include/soc/rtc.h b/components/soc/esp32h4/include/soc/rtc.h index b21a9931e3..bbdd6397b8 100644 --- a/components/soc/esp32h4/include/soc/rtc.h +++ b/components/soc/esp32h4/include/soc/rtc.h @@ -854,36 +854,6 @@ typedef struct { */ void rtc_init(rtc_config_t cfg); -/** - * Structure describing vddsdio configuration - */ -typedef struct { - uint32_t force : 1; //!< If 1, use configuration from RTC registers; if 0, use EFUSE/bootstrapping pins. - uint32_t enable : 1; //!< Enable VDDSDIO regulator - uint32_t tieh : 1; //!< Select VDDSDIO voltage. One of RTC_VDDSDIO_TIEH_1_8V, RTC_VDDSDIO_TIEH_3_3V - uint32_t drefh : 2; //!< Tuning parameter for VDDSDIO regulator - uint32_t drefm : 2; //!< Tuning parameter for VDDSDIO regulator - uint32_t drefl : 2; //!< Tuning parameter for VDDSDIO regulator -} rtc_vddsdio_config_t; - -/** - * Get current VDDSDIO configuration - * If VDDSDIO configuration is overridden by RTC, get values from RTC - * Otherwise, if VDDSDIO is configured by EFUSE, get values from EFUSE - * Otherwise, use default values and the level of MTDI bootstrapping pin. - * @return currently used VDDSDIO configuration - */ -rtc_vddsdio_config_t rtc_vddsdio_get_config(void); - -/** - * Set new VDDSDIO configuration using RTC registers. - * If config.force == 1, this overrides configuration done using bootstrapping - * pins and EFUSE. - * - * @param config new VDDSDIO configuration - */ -void rtc_vddsdio_set_config(rtc_vddsdio_config_t config); - /** * Regulator config */ diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index 6625c4b502..fc7d0175c0 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -959,6 +959,10 @@ config SOC_PM_SUPPORT_VDDSDIO_PD bool default y +config SOC_CONFIGURABLE_VDDSDIO_SUPPORTED + bool + default y + config SOC_CLK_APLL_SUPPORTED bool default y diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index e3b41a8211..2f89ba8101 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -417,6 +417,8 @@ #define SOC_PM_SUPPORT_RC_FAST_PD (1) #define SOC_PM_SUPPORT_VDDSDIO_PD (1) +#define SOC_CONFIGURABLE_VDDSDIO_SUPPORTED (1) + /*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/ #define SOC_CLK_APLL_SUPPORTED (1) // apll_multiplier_out = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536) diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index f7efbec865..f145a7e9ec 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -1007,6 +1007,10 @@ config SOC_PM_SUPPORT_VDDSDIO_PD bool default y +config SOC_CONFIGURABLE_VDDSDIO_SUPPORTED + bool + default y + config SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY bool default y diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 1bda95f405..a0af8c3e9d 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -413,6 +413,7 @@ #define SOC_PM_SUPPORT_RC_FAST_PD (1) #define SOC_PM_SUPPORT_VDDSDIO_PD (1) +#define SOC_CONFIGURABLE_VDDSDIO_SUPPORTED (1) #define SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY (1) /*! Date: Tue, 31 Jan 2023 20:11:25 +0800 Subject: [PATCH 14/16] sleep: light sleep supported for esp32c6 --- .../driver/test_apps/gpio/main/test_gpio.c | 2 +- components/esp_hw_support/Kconfig | 2 +- components/esp_hw_support/sleep_gpio.c | 17 +++ components/esp_hw_support/sleep_modes.c | 108 +++++++++--------- components/esp_pm/Kconfig | 2 +- components/esp_system/system_init_fn.txt | 2 +- components/esp_system/test/test_sleep.c | 13 ++- 7 files changed, 85 insertions(+), 61 deletions(-) diff --git a/components/driver/test_apps/gpio/main/test_gpio.c b/components/driver/test_apps/gpio/main/test_gpio.c index 48ecd99a78..ede7e2e527 100644 --- a/components/driver/test_apps/gpio/main/test_gpio.c +++ b/components/driver/test_apps/gpio/main/test_gpio.c @@ -844,7 +844,7 @@ TEST_CASE("GPIO_USB_DP_pin_pullup_disable_test", "[gpio]") } #endif //SOC_USB_SERIAL_JTAG_SUPPORTED -#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6, ESP32H2) // TODO: IDF-5348, IDF-6267 Remove when light sleep is supported +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32H2) // TODO: IDF-6267 Remove when light sleep is supported // Ignored in CI because it needs manually connect TEST_GPIO_INPUT_LEVEL_LOW_PIN to 3.3v to wake up from light sleep TEST_CASE("GPIO_light_sleep_wake_up_test", "[gpio][ignore]") { diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index 19bcccb506..93224e6e97 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -67,7 +67,7 @@ menu "Hardware Settings" config ESP_SLEEP_GPIO_RESET_WORKAROUND bool "light sleep GPIO reset workaround" - default y if IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 # TODO: IDF-5641 (esp32c6) + default y if IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6 select PM_SLP_DISABLE_GPIO if FREERTOS_USE_TICKLESS_IDLE help esp32c2, esp32c3 and esp32s3 will reset at wake-up if GPIO is received a small electrostatic diff --git a/components/esp_hw_support/sleep_gpio.c b/components/esp_hw_support/sleep_gpio.c index 87c2903814..df3b8801fd 100644 --- a/components/esp_hw_support/sleep_gpio.c +++ b/components/esp_hw_support/sleep_gpio.c @@ -20,10 +20,15 @@ #include "driver/gpio.h" #include "hal/gpio_hal.h" #include "hal/rtc_io_hal.h" + +#if !SOC_PMU_SUPPORTED #include "hal/rtc_hal.h" +#endif + #include "esp_private/gpio.h" #include "esp_private/sleep_gpio.h" #include "esp_private/spi_flash_os.h" +#include "esp_private/startup_internal.h" #include "bootloader_flash.h" static const char *TAG = "sleep"; @@ -180,3 +185,15 @@ void esp_deep_sleep_wakeup_io_reset(void) } #endif } + +#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND && !CONFIG_PM_SLP_DISABLE_GPIO +ESP_SYSTEM_INIT_FN(esp_sleep_startup_init, BIT(0), 105) +{ + // Configure to isolate (disable the Input/Output/Pullup/Pulldown + // function of the pin) all GPIO pins in sleep state + esp_sleep_config_gpio_isolate(); + // Enable automatic switching of GPIO configuration + esp_sleep_enable_gpio_switch(true); + return ESP_OK; +} +#endif diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index b0deb421d2..7d77e772d9 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -51,7 +51,6 @@ #include "esp_private/brownout.h" #include "esp_private/sleep_cpu.h" #include "esp_private/esp_clk.h" -#include "esp_private/startup_internal.h" #include "esp_private/esp_task_wdt.h" #ifdef CONFIG_IDF_TARGET_ESP32 @@ -75,6 +74,8 @@ #include "esp32c2/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32C6 #include "esp32c6/rom/rtc.h" +#include "hal/lp_timer_hal.h" +#include "esp_private/esp_pmu.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/rtc.h" #include "esp32h2/rom/cache.h" @@ -185,9 +186,7 @@ static sleep_config_t s_config = { /* Internal variable used to track if light sleep wakeup sources are to be expected when determining wakeup cause. */ -#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150 static bool s_light_sleep_wakeup = false; -#endif /* Updating RTC_MEMORY_CRC_REG register via set_rtc_memory_crc() is not thread-safe, so we need to disable interrupts before going to deep sleep. */ @@ -210,13 +209,11 @@ static uint32_t get_power_down_flags(void); static void ext0_wakeup_prepare(void); static void ext1_wakeup_prepare(void); #endif -#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150 static void timer_wakeup_prepare(void); -#endif #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 static void touch_wakeup_prepare(void); #endif -#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP && !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150 +#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP static void gpio_deep_sleep_wakeup_prepare(void); #endif @@ -308,7 +305,6 @@ void esp_deep_sleep(uint64_t time_in_us) } // [refactor-todo] provide target logic for body of uart functions below -#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150 static void IRAM_ATTR flush_uarts(void) { for (int i = 0; i < SOC_UART_NUM; ++i) { @@ -353,7 +349,6 @@ static void IRAM_ATTR resume_uarts(void) uart_ll_force_xon(i); } } -#endif /** * These save-restore workaround should be moved to lower layer @@ -393,7 +388,7 @@ inline static void IRAM_ATTR misc_modules_wake_prepare(void) #endif } -inline static uint32_t call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu); +inline static uint32_t call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu, bool dslp); inline static bool is_light_sleep(uint32_t pd_flags) { @@ -402,9 +397,6 @@ inline static bool is_light_sleep(uint32_t pd_flags) static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) { -#if CONFIG_IDF_TARGET_ESP32C6 - return 0; // TODO: WIFI-5150 -#else // Stop UART output so that output is not lost due to APB frequency change. // For light sleep, suspend UART output — it will resume after wakeup. // For deep sleep, wait for the contents of UART FIFO to be sent. @@ -508,7 +500,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) } // Enter sleep -#if CONFIG_IDF_TARGET_ESP32C6 +#if SOC_PMU_SUPPORTED pmu_sleep_config_t config; pmu_sleep_init(pmu_sleep_config_default(&config, pd_flags, s_config.sleep_time_adjustment, s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period, @@ -536,6 +528,8 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) esp_sleep_isolate_digital_gpio(); #endif +#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5349 + #if SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY extern char _rtc_text_start[]; #if CONFIG_ESP32S3_RTCDATA_IN_FAST_MEM @@ -546,7 +540,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) size_t rtc_fast_length = (size_t)_rtc_force_fast_end - (size_t)_rtc_text_start; #endif esp_rom_set_rtc_wake_addr((esp_rom_wake_func_t)esp_wake_stub_entry, rtc_fast_length); - result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu); + result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, 0); #else #if !CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP /* If not possible stack is in RTC FAST memory, use the ROM function to calculate the CRC and save ~140 bytes IRAM */ @@ -554,14 +548,26 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) // RTC has no rtc memory, IDF-3901 set_rtc_memory_crc(); #endif - result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu); + result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, 0); #else /* Otherwise, need to call the dedicated soc function for this */ result = rtc_deep_sleep_start(s_config.wakeup_triggers, reject_triggers); #endif #endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY + +#else + result = ESP_OK; +#endif } else { - result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu); +#if SOC_PM_CPU_RETENTION_BY_SW + if (pd_flags & PMU_SLEEP_PD_CPU) { + result = esp_sleep_cpu_retention(pmu_sleep_start, s_config.wakeup_triggers, reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep); + } else { + result = call_rtc_sleep_start(reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep); + } +#else + result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu, 0); +#endif } // Restore CPU frequency @@ -576,13 +582,14 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) resume_uarts(); return result; -#endif } -inline static uint32_t IRAM_ATTR call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu) +inline static uint32_t IRAM_ATTR call_rtc_sleep_start(uint32_t reject_triggers, uint32_t lslp_mem_inf_fpu, bool dslp) { #ifdef CONFIG_IDF_TARGET_ESP32 return rtc_sleep_start(s_config.wakeup_triggers, reject_triggers); +#elif SOC_PMU_SUPPORTED + return pmu_sleep_start(s_config.wakeup_triggers, reject_triggers, lslp_mem_inf_fpu, dslp); #else return rtc_sleep_start(s_config.wakeup_triggers, reject_triggers, lslp_mem_inf_fpu); #endif @@ -647,16 +654,12 @@ void IRAM_ATTR esp_deep_sleep_start(void) * Helper function which handles entry to and exit from light sleep * Placed into IRAM as flash may need some time to be powered on. */ -#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150 static esp_err_t esp_light_sleep_inner(uint32_t pd_flags, uint32_t flash_enable_time_us) IRAM_ATTR __attribute__((noinline)); static esp_err_t esp_light_sleep_inner(uint32_t pd_flags, uint32_t flash_enable_time_us) { -#if CONFIG_IDF_TARGET_ESP32C6 - return ESP_ERR_NOT_SUPPORTED; // TODO: WIFI-5150 -#else // Enter sleep uint32_t reject = esp_sleep_start(pd_flags); @@ -676,9 +679,7 @@ static esp_err_t esp_light_sleep_inner(uint32_t pd_flags, } return reject ? ESP_ERR_SLEEP_REJECT : ESP_OK; -#endif } -#endif /** * vddsdio is used for power supply of spi flash @@ -730,7 +731,11 @@ esp_err_t esp_light_sleep_start(void) */ esp_clk_private_lock(); +#if SOC_LP_TIMER_SUPPORTED + s_config.rtc_ticks_at_sleep_start = lp_timer_hal_get_cycle_count(0); +#else s_config.rtc_ticks_at_sleep_start = rtc_time_get(); +#endif uint32_t ccount_at_sleep_start = esp_cpu_get_cycle_count(); uint64_t high_res_time_at_start = esp_timer_get_time(); uint32_t sleep_time_overhead_in = (ccount_at_sleep_start - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL); @@ -763,10 +768,6 @@ esp_err_t esp_light_sleep_start(void) esp_clk_slowclk_cal_set(s_config.rtc_clk_cal_period); #endif -#if CONFIG_IDF_TARGET_ESP32C6 - s_config.fast_clk_cal_period = rtc_clk_cal(RTC_CAL_RC_FAST, FAST_CLK_SRC_CAL_CYCLES); -#endif - /* * Adjustment time consists of parts below: * 1. Hardware time waiting for internal 8M oscilate clock and XTAL; @@ -775,7 +776,8 @@ esp_err_t esp_light_sleep_start(void) * 4. Code execution time which can be measured; */ -#if CONFIG_IDF_TARGET_ESP32C6 +#if SOC_PMU_SUPPORTED + s_config.fast_clk_cal_period = rtc_clk_cal(RTC_CAL_RC_FAST, FAST_CLK_SRC_CAL_CYCLES); int sleep_time_sw_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US + sleep_time_overhead_in + s_config.sleep_time_overhead_out; int sleep_time_hw_adjustment = pmu_sleep_calculate_hw_wait_time(pd_flags, s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period); s_config.sleep_time_adjustment = sleep_time_sw_adjustment + sleep_time_hw_adjustment; @@ -864,7 +866,11 @@ esp_err_t esp_light_sleep_start(void) s_light_sleep_wakeup = (err == ESP_OK); // System timer has been stopped for the duration of the sleep, correct for that. +#if SOC_LP_TIMER_SUPPORTED + uint64_t rtc_ticks_at_end = lp_timer_hal_get_cycle_count(0); +#else uint64_t rtc_ticks_at_end = rtc_time_get(); +#endif uint64_t rtc_time_diff = rtc_time_slowclk_to_us(rtc_ticks_at_end - s_config.rtc_ticks_at_sleep_start, s_config.rtc_clk_cal_period); /** @@ -895,7 +901,6 @@ esp_err_t esp_light_sleep_start(void) s_config.sleep_time_overhead_out = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL); return err; -#endif } esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source) @@ -973,7 +978,6 @@ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us) return ESP_OK; } -#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150 static void timer_wakeup_prepare(void) { int64_t sleep_duration = (int64_t) s_config.sleep_duration - (int64_t) s_config.sleep_time_adjustment; @@ -982,9 +986,13 @@ static void timer_wakeup_prepare(void) } int64_t ticks = rtc_time_us_to_slowclk(sleep_duration, s_config.rtc_clk_cal_period); + +#if SOC_LP_TIMER_SUPPORTED + lp_timer_hal_set_alarm_target(0, s_config.rtc_ticks_at_sleep_start + ticks); +#else rtc_hal_set_wakeup_timer(s_config.rtc_ticks_at_sleep_start + ticks); -} #endif +} #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 /* In deep sleep mode, only the sleep channel is supported, and other touch channels should be turned off. */ @@ -1167,16 +1175,20 @@ uint64_t esp_sleep_get_ext1_wakeup_status(void) #if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP uint64_t esp_sleep_get_gpio_wakeup_status(void) { +#if CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5349 + return 0; +#else if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_GPIO) { return 0; } return rtc_hal_gpio_get_wakeup_status(); +#endif } -#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: WIFI-5150 static void gpio_deep_sleep_wakeup_prepare(void) { +#if !CONFIG_IDF_TARGET_ESP32C6 // TODO: IDF-5349 for (gpio_num_t gpio_idx = GPIO_NUM_0; gpio_idx < GPIO_NUM_MAX; gpio_idx++) { if (((1ULL << gpio_idx) & s_config.gpio_wakeup_mask) == 0) { continue; @@ -1192,8 +1204,8 @@ static void gpio_deep_sleep_wakeup_prepare(void) } // Clear state from previous wakeup rtc_hal_gpio_clear_wakeup_status(); -} #endif +} esp_err_t esp_deep_sleep_enable_gpio_wakeup(uint64_t gpio_pin_mask, esp_deepsleep_gpio_wake_up_mode_t mode) { @@ -1293,14 +1305,20 @@ esp_err_t esp_sleep_disable_bt_wakeup(void) esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void) { -#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 // TODO: IDF-5645 +#if CONFIG_IDF_TARGET_ESP32H2 // TODO: IDF-5645 return ESP_SLEEP_WAKEUP_UNDEFINED; #else if (esp_rom_get_reset_reason(0) != RESET_REASON_CORE_DEEP_SLEEP && !s_light_sleep_wakeup) { return ESP_SLEEP_WAKEUP_UNDEFINED; } +#ifdef CONFIG_IDF_TARGET_ESP32 + uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE); +#elif SOC_PMU_SUPPORTED + uint32_t wakeup_cause = pmu_ll_hp_get_wakeup_cause(&PMU); +#else uint32_t wakeup_cause = rtc_cntl_ll_get_wakeup_cause(); +#endif if (wakeup_cause & RTC_TIMER_TRIG_EN) { return ESP_SLEEP_WAKEUP_TIMER; @@ -1489,11 +1507,7 @@ static uint32_t get_power_down_flags(void) #endif #if SOC_PM_SUPPORT_RC_FAST_PD if (s_config.domain[ESP_PD_DOMAIN_RC_FAST].pd_option != ESP_PD_OPTION_ON) { -#if CONFIG_IDF_TARGET_ESP32C6 - pd_flags |= PMU_SLEEP_PD_FOSC; -#else pd_flags |= RTC_SLEEP_PD_INT_8M; -#endif } #endif #if SOC_PM_SUPPORT_XTAL_PD @@ -1503,11 +1517,7 @@ static uint32_t get_power_down_flags(void) #endif #if SOC_PM_SUPPORT_VDDSDIO_PD if (s_config.domain[ESP_PD_DOMAIN_VDDSDIO].pd_option != ESP_PD_OPTION_ON) { -#if CONFIG_IDF_TARGET_ESP32C6 - pd_flags |= PMU_SLEEP_PD_VDDSDIO; -#else pd_flags |= RTC_SLEEP_PD_VDDSDIO; -#endif } #endif @@ -1535,15 +1545,3 @@ void rtc_sleep_enable_ultra_low(bool enable) { s_ultra_low_enabled = enable; } - -#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND && !CONFIG_PM_SLP_DISABLE_GPIO -ESP_SYSTEM_INIT_FN(esp_sleep_startup_init, BIT(0), 105) -{ - // Configure to isolate (disable the Input/Output/Pullup/Pulldown - // function of the pin) all GPIO pins in sleep state - esp_sleep_config_gpio_isolate(); - // Enable automatic switching of GPIO configuration - esp_sleep_enable_gpio_switch(true); - return ESP_OK; -} -#endif diff --git a/components/esp_pm/Kconfig b/components/esp_pm/Kconfig index 2e073b0b3a..dbb638c717 100644 --- a/components/esp_pm/Kconfig +++ b/components/esp_pm/Kconfig @@ -87,7 +87,7 @@ menu "Power Management" config PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP bool "Power down CPU in light sleep" - depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 + depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6 select PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP if ESP32S3_DATA_CACHE_16KB default y help diff --git a/components/esp_system/system_init_fn.txt b/components/esp_system/system_init_fn.txt index 3fb5a7a216..cd0fa76947 100644 --- a/components/esp_system/system_init_fn.txt +++ b/components/esp_system/system_init_fn.txt @@ -17,7 +17,7 @@ 100: esp_timer_startup_init in components/esp_timer/src/esp_timer.c on BIT(0) # esp_sleep doesn't have init dependencies -105: esp_sleep_startup_init in components/esp_hw_support/sleep_modes.c on BIT(0) +105: esp_sleep_startup_init in components/esp_hw_support/sleep_gpio.c on BIT(0) # app_trace has to be initialized before systemview 115: esp_apptrace_init in components/app_trace/app_trace.c on ESP_SYSTEM_INIT_ALL_CORES diff --git a/components/esp_system/test/test_sleep.c b/components/esp_system/test/test_sleep.c index 664ca3039f..f364462977 100644 --- a/components/esp_system/test/test_sleep.c +++ b/components/esp_system/test/test_sleep.c @@ -19,7 +19,6 @@ #include "soc/rtc.h" // for wakeup trigger defines #include "soc/rtc_periph.h" // for read rtc registers directly (cause) #include "soc/soc.h" // for direct register read macros -#include "hal/rtc_cntl_ll.h" #include "esp_newlib.h" #include "test_utils.h" #include "sdkconfig.h" @@ -29,6 +28,12 @@ #include "esp_private/esp_clk.h" #include "esp_random.h" +#if SOC_PMU_SUPPORTED +#include "esp_private/esp_pmu.h" +#else +#include "hal/rtc_cntl_ll.h" +#endif + #define ESP_EXT0_WAKEUP_LEVEL_LOW 0 #define ESP_EXT0_WAKEUP_LEVEL_HIGH 1 @@ -445,7 +450,11 @@ __attribute__((unused)) static float get_time_ms(void) __attribute__((unused)) static uint32_t get_cause(void) { +#if SOC_PMU_SUPPORTED + uint32_t wakeup_cause = pmu_ll_hp_get_wakeup_cause(&PMU); +#else uint32_t wakeup_cause = rtc_cntl_ll_get_wakeup_cause(); +#endif return wakeup_cause; } @@ -590,4 +599,4 @@ TEST_CASE("wake up using GPIO (2 or 4 low)", "[deepsleep][ignore]") } #endif // SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP #endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C2) -#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6, ESP32H2) TODO: IDF-5348, IDF-5349 +#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6, ESP32H2) TODO: IDF-5349 From cd9d914ba07fd993b6bad690d327ec6d96b83572 Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Sat, 28 Jan 2023 17:36:45 +0800 Subject: [PATCH 15/16] codeclean: clean esp32c6 rtc_sleep related code --- .../src/bootloader_clock_init.c | 10 +- .../esp_hw_support/port/esp32c6/rtc_sleep.c | 7 - components/esp_hw_support/sleep_modes.c | 4 +- components/esp_hw_support/sleep_wake_stub.c | 14 ++ .../hal/esp32c6/include/hal/rtc_cntl_ll.h | 89 ---------- components/soc/esp32c6/include/soc/rtc.h | 158 +----------------- 6 files changed, 21 insertions(+), 261 deletions(-) delete mode 100644 components/esp_hw_support/port/esp32c6/rtc_sleep.c delete mode 100644 components/hal/esp32c6/include/hal/rtc_cntl_ll.h diff --git a/components/bootloader_support/src/bootloader_clock_init.c b/components/bootloader_support/src/bootloader_clock_init.c index c5f276304d..075f2c9f0b 100644 --- a/components/bootloader_support/src/bootloader_clock_init.c +++ b/components/bootloader_support/src/bootloader_clock_init.c @@ -95,8 +95,8 @@ __attribute__((weak)) void bootloader_clock_configure(void) CLEAR_PERI_REG_MASK(LP_TIMER_LP_INT_ENA_REG, LP_TIMER_MAIN_TIMER_LP_INT_ENA); /* MAIN_TIMER */ CLEAR_PERI_REG_MASK(LP_ANALOG_PERI_LP_ANA_LP_INT_ENA_REG, LP_ANALOG_PERI_LP_ANA_BOD_MODE0_LP_INT_ENA); /* BROWN_OUT */ CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_LP_WDT_INT_ENA); /* WDT */ - // CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_WAKEUP_INT_ENA); // TODO: IDF-5348 /* SLP_REJECT */ - // CLEAR_PERI_REG_MASK(PMU_SOC_SLEEP_REJECT_INT_ENA, PMU_SOC_SLEEP_REJECT_INT_ENA); /* SLP_WAKEUP */ + CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_WAKEUP_INT_ENA); /* SLP_REJECT */ + CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_SLEEP_REJECT_INT_ENA); /* SLP_WAKEUP */ // SET CLR SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_SUPER_WDT_INT_CLR); /* SWD */ SET_PERI_REG_MASK(LP_TIMER_LP_INT_CLR_REG, LP_TIMER_MAIN_TIMER_LP_INT_CLR); /* MAIN_TIMER */ @@ -108,13 +108,13 @@ __attribute__((weak)) void bootloader_clock_configure(void) CLEAR_PERI_REG_MASK(LP_ANALOG_PERI_LP_ANA_LP_INT_ENA_REG, LP_ANALOG_PERI_LP_ANA_BOD_MODE0_LP_INT_ENA); /* BROWN_OUT */ CLEAR_PERI_REG_MASK(LP_WDT_INT_ENA_REG, LP_WDT_LP_WDT_INT_ENA); /* WDT */ CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_WAKEUP_INT_ENA); /* SLP_REJECT */ - CLEAR_PERI_REG_MASK(PMU_SOC_SLEEP_REJECT_INT_ENA, PMU_SOC_SLEEP_REJECT_INT_ENA); /* SLP_WAKEUP */ + CLEAR_PERI_REG_MASK(PMU_HP_INT_ENA_REG, PMU_SOC_SLEEP_REJECT_INT_ENA); /* SLP_WAKEUP */ // SET CLR SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_SUPER_WDT_INT_CLR); /* SWD */ SET_PERI_REG_MASK(LP_ANALOG_PERI_LP_ANA_LP_INT_CLR_REG, LP_ANALOG_PERI_LP_ANA_BOD_MODE0_LP_INT_CLR); /* BROWN_OUT */ SET_PERI_REG_MASK(LP_WDT_INT_CLR_REG, LP_WDT_LP_WDT_INT_CLR); /* WDT */ - // SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_WAKEUP_INT_CLR); // TODO: IDF-5348 /* SLP_REJECT */ - // SET_PERI_REG_MASK(PMU_SOC_SLEEP_REJECT_INT_CLR, PMU_SOC_SLEEP_REJECT_INT_CLR); /* SLP_WAKEUP */ + SET_PERI_REG_MASK(PMU_HP_INT_CLR_REG, PMU_SOC_WAKEUP_INT_CLR); /* SLP_REJECT */ + SET_PERI_REG_MASK(PMU_SOC_SLEEP_REJECT_INT_CLR, PMU_SOC_SLEEP_REJECT_INT_CLR); /* SLP_WAKEUP */ #else REG_WRITE(RTC_CNTL_INT_ENA_REG, 0); REG_WRITE(RTC_CNTL_INT_CLR_REG, UINT32_MAX); diff --git a/components/esp_hw_support/port/esp32c6/rtc_sleep.c b/components/esp_hw_support/port/esp32c6/rtc_sleep.c deleted file mode 100644 index 8a5daa4517..0000000000 --- a/components/esp_hw_support/port/esp32c6/rtc_sleep.c +++ /dev/null @@ -1,7 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -// TODO: IDF-5645 diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 7d77e772d9..61e8b6084b 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -1312,9 +1312,7 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void) return ESP_SLEEP_WAKEUP_UNDEFINED; } -#ifdef CONFIG_IDF_TARGET_ESP32 - uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE); -#elif SOC_PMU_SUPPORTED +#if SOC_PMU_SUPPORTED uint32_t wakeup_cause = pmu_ll_hp_get_wakeup_cause(&PMU); #else uint32_t wakeup_cause = rtc_cntl_ll_get_wakeup_cause(); diff --git a/components/esp_hw_support/sleep_wake_stub.c b/components/esp_hw_support/sleep_wake_stub.c index ba0c411de8..023e766c45 100644 --- a/components/esp_hw_support/sleep_wake_stub.c +++ b/components/esp_hw_support/sleep_wake_stub.c @@ -23,6 +23,11 @@ #else #include "hal/rtc_cntl_ll.h" #endif + +#if SOC_PMU_SUPPORTED +#include "hal/pmu_ll.h" +#endif + #include "sdkconfig.h" #include "esp_rom_uart.h" #include "esp_rom_sys.h" @@ -62,7 +67,12 @@ void RTC_IRAM_ATTR esp_wake_stub_sleep(esp_deep_sleep_wake_stub_fn_t new_stub) #endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_MEM // Go to sleep. +#if SOC_PMU_SUPPORTED + pmu_ll_hp_set_sleep_enable(&PMU); +#else rtc_cntl_ll_sleep_enable(); +#endif + // A few CPU cycles may be necessary for the sleep to start... while (true) {}; // never reaches here. @@ -89,5 +99,9 @@ void RTC_IRAM_ATTR esp_wake_stub_set_wakeup_time(uint64_t time_in_us) uint32_t RTC_IRAM_ATTR esp_wake_stub_get_wakeup_cause(void) { +#if SOC_PMU_SUPPORTED + return pmu_ll_hp_get_wakeup_cause(&PMU); +#else return rtc_cntl_ll_get_wakeup_cause(); +#endif } diff --git a/components/hal/esp32c6/include/hal/rtc_cntl_ll.h b/components/hal/esp32c6/include/hal/rtc_cntl_ll.h deleted file mode 100644 index 25a1f55372..0000000000 --- a/components/hal/esp32c6/include/hal/rtc_cntl_ll.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "soc/soc.h" -#include "soc/rtc.h" -#include "soc/lp_aon_reg.h" -#include "esp_attr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -FORCE_INLINE_ATTR void rtc_cntl_ll_set_wakeup_timer(uint64_t t) -{ - // TODO: IDF-5645 -} - -FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_gpio_get_wakeup_status(void) -{ - // TODO: IDF-5645 - return 0; -} - -FORCE_INLINE_ATTR void rtc_cntl_ll_gpio_clear_wakeup_status(void) -{ - // TODO: IDF-5645 -} - -FORCE_INLINE_ATTR void rtc_cntl_ll_set_cpu_retention_link_addr(uint32_t addr) -{ - // TODO: IDF-5718 has removed the retention feature -} - -FORCE_INLINE_ATTR void rtc_cntl_ll_enable_cpu_retention_clock(void) -{ - // TODO: IDF-5718 has removed the retention feature -} - -FORCE_INLINE_ATTR void rtc_cntl_ll_enable_cpu_retention(void) -{ - // TODO: IDF-5718 has removed the retention feature -} - -FORCE_INLINE_ATTR void rtc_cntl_ll_disable_cpu_retention(void) -{ - // TODO: IDF-5718 has removed the retention feature -} - -FORCE_INLINE_ATTR void rtc_cntl_ll_reset_system(void) -{ - REG_SET_BIT(LP_AON_SYS_CFG_REG, LP_AON_HPSYS_SW_RESET); -} - -FORCE_INLINE_ATTR void rtc_cntl_ll_reset_cpu(int cpu_no) -{ - REG_SET_BIT(LP_AON_CPUCORE0_CFG_REG, LP_AON_CPU_CORE0_SW_RESET); -} - -FORCE_INLINE_ATTR void rtc_cntl_ll_sleep_enable(void) -{ - // TODO: IDF-6064 -} - -FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_get_rtc_time(void) -{ - // TODO: IDF-6064 - return 0; -} - -FORCE_INLINE_ATTR uint64_t rtc_cntl_ll_time_to_count(uint64_t time_in_us) -{ - // TODO: IDF-6064 - return 0; -} - -FORCE_INLINE_ATTR uint32_t rtc_cntl_ll_get_wakeup_cause(void) -{ - // TODO: IDF-6064 - return 0; -} - -#ifdef __cplusplus -} -#endif diff --git a/components/soc/esp32c6/include/soc/rtc.h b/components/soc/esp32c6/include/soc/rtc.h index 000f15b1e8..dc4fd5339e 100644 --- a/components/soc/esp32c6/include/soc/rtc.h +++ b/components/soc/esp32c6/include/soc/rtc.h @@ -17,7 +17,7 @@ extern "C" { /** * @file rtc.h - * @brief Low-level RTC power, clock, and sleep functions. + * @brief Low-level RTC power, clock functions. * * Functions in this file facilitate configuration of ESP32's RTC_CNTL peripheral. * RTC_CNTL peripheral handles many functions: @@ -514,164 +514,8 @@ bool rtc_dig_8m_enabled(void); */ uint32_t rtc_clk_freq_cal(uint32_t cal_val); -/** - * @brief Power down flags for rtc_sleep_pd function - */ -typedef struct { - uint32_t dig_fpu : 1; //!< Set to 1 to power UP digital part in sleep - uint32_t rtc_fpu : 1; //!< Set to 1 to power UP RTC memories in sleep - uint32_t cpu_fpu : 1; //!< Set to 1 to power UP digital memories and CPU in sleep - uint32_t i2s_fpu : 1; //!< Set to 1 to power UP I2S in sleep - uint32_t bb_fpu : 1; //!< Set to 1 to power UP WiFi in sleep - uint32_t nrx_fpu : 1; //!< Set to 1 to power UP WiFi in sleep - uint32_t fe_fpu : 1; //!< Set to 1 to power UP WiFi in sleep - uint32_t sram_fpu : 1; //!< Set to 1 to power UP SRAM in sleep - uint32_t rom_ram_fpu : 1; //!< Set to 1 to power UP ROM/IRAM0_DRAM0 in sleep -} rtc_sleep_pu_config_t; - -/** - * Initializer for rtc_sleep_pu_config_t which sets all flags to the same value - */ -#define RTC_SLEEP_PU_CONFIG_ALL(val) {\ - .dig_fpu = (val), \ - .rtc_fpu = (val), \ - .cpu_fpu = (val), \ - .i2s_fpu = (val), \ - .bb_fpu = (val), \ - .nrx_fpu = (val), \ - .fe_fpu = (val), \ - .sram_fpu = (val), \ - .rom_ram_fpu = (val), \ -} - -void rtc_sleep_pu(rtc_sleep_pu_config_t cfg); - -/** - * @brief sleep configuration for rtc_sleep_init function - */ -typedef struct { - uint32_t lslp_mem_inf_fpu : 1; //!< force normal voltage in sleep mode (digital domain memory) - uint32_t rtc_mem_inf_follow_cpu : 1;//!< keep low voltage in sleep mode (even if ULP/touch is used) - uint32_t rtc_fastmem_pd_en : 1; //!< power down RTC fast memory - uint32_t rtc_slowmem_pd_en : 1; //!< power down RTC slow memory - uint32_t rtc_peri_pd_en : 1; //!< power down RTC peripherals - uint32_t wifi_pd_en : 1; //!< power down WiFi - uint32_t bt_pd_en : 1; //!< power down BT - uint32_t cpu_pd_en : 1; //!< power down CPU, but not restart when lightsleep. - uint32_t int_8m_pd_en : 1; //!< Power down Internal 8M oscillator - uint32_t dig_peri_pd_en : 1; //!< power down digital peripherals - uint32_t deep_slp : 1; //!< power down digital domain - uint32_t wdt_flashboot_mod_en : 1; //!< enable WDT flashboot mode - uint32_t dig_dbias_wak : 5; //!< set bias for digital domain, in active mode - uint32_t dig_dbias_slp : 5; //!< set bias for digital domain, in sleep mode - uint32_t rtc_dbias_wak : 5; //!< set bias for RTC domain, in active mode - uint32_t rtc_dbias_slp : 5; //!< set bias for RTC domain, in sleep mode - uint32_t dbg_atten_monitor : 4; //!< voltage parameter, in monitor mode - uint32_t bias_sleep_monitor : 1; //!< circuit control parameter, in monitor mode - uint32_t dbg_atten_slp : 4; //!< voltage parameter, in sleep mode - uint32_t bias_sleep_slp : 1; //!< circuit control parameter, in sleep mode - uint32_t pd_cur_monitor : 1; //!< circuit control parameter, in monitor mode - uint32_t pd_cur_slp : 1; //!< circuit control parameter, in sleep mode - uint32_t vddsdio_pd_en : 1; //!< power down VDDSDIO regulator - uint32_t xtal_fpu : 1; //!< keep main XTAL powered up in sleep - uint32_t deep_slp_reject : 1; //!< enable deep sleep reject - uint32_t light_slp_reject : 1; //!< enable light sleep reject -} rtc_sleep_config_t; -/** - * Default initializer for rtc_sleep_config_t - * - * This initializer sets all fields to "reasonable" values (e.g. suggested for - * production use) based on a combination of RTC_SLEEP_PD_x flags. - * - * @param RTC_SLEEP_PD_x flags combined using bitwise OR - */ -void rtc_sleep_get_default_config(uint32_t sleep_flags, rtc_sleep_config_t *out_config); - -/** - * @brief Prepare the chip to enter sleep mode - * - * This function configures various power control state machines to handle - * entry into light sleep or deep sleep mode, switches APB and CPU clock source - * (usually to XTAL), and sets bias voltages for digital and RTC power domains. - * - * This function does not actually enter sleep mode; this is done using - * rtc_sleep_start function. Software may do some other actions between - * rtc_sleep_init and rtc_sleep_start, such as set wakeup timer and configure - * wakeup sources. - * @param cfg sleep mode configuration - */ -void rtc_sleep_init(rtc_sleep_config_t cfg); - -/** - * @brief Low level initialize for rtc state machine waiting cycles after waking up - * - * This function configures the cycles chip need to wait for internal 8MHz - * oscillator and external 40MHz crystal. As we configure fixed time for waiting - * crystal, we need to pass period to calculate cycles. Now this function only - * used in lightsleep mode. - * - * @param slowclk_period re-calibrated slow clock period - */ -void rtc_sleep_low_init(uint32_t slowclk_period); - -/** - * @brief Set target value of RTC counter for RTC_TIMER_TRIG_EN wakeup source - * @param t value of RTC counter at which wakeup from sleep will happen; - * only the lower 48 bits are used - */ -void rtc_sleep_set_wakeup_time(uint64_t t); - -/** - * @brief Enter deep or light sleep mode - * - * This function enters the sleep mode previously configured using rtc_sleep_init - * function. Before entering sleep, software should configure wake up sources - * appropriately (set up GPIO wakeup registers, timer wakeup registers, - * and so on). - * - * If deep sleep mode was configured using rtc_sleep_init, and sleep is not - * rejected by hardware (based on reject_opt flags), this function never returns. - * When the chip wakes up from deep sleep, CPU is reset and execution starts - * from ROM bootloader. - * - * If light sleep mode was configured using rtc_sleep_init, this function - * returns on wakeup, or if sleep is rejected by hardware. - * - * @param wakeup_opt bit mask wake up reasons to enable (RTC_xxx_TRIG_EN flags - * combined with OR) - * @param reject_opt bit mask of sleep reject reasons: - * - RTC_CNTL_GPIO_REJECT_EN - * - RTC_CNTL_SDIO_REJECT_EN - * These flags are used to prevent entering sleep when e.g. - * an external host is communicating via SDIO slave - * @return non-zero if sleep was rejected by hardware - */ -uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu); - -/** - * @brief Enter deep sleep mode - * - * Similar to rtc_sleep_start(), but additionally uses hardware to calculate the CRC value - * of RTC FAST memory. On wake, this CRC is used to determine if a deep sleep wake - * stub is valid to execute (if a wake address is set). - * - * No RAM is accessed while calculating the CRC and going into deep sleep, which makes - * this function safe to use even if the caller's stack is in RTC FAST memory. - * - * @note If no deep sleep wake stub address is set then calling rtc_sleep_start() will - * have the same effect and takes less time as CRC calculation is skipped. - * - * @note This function should only be called after rtc_sleep_init() has been called to - * configure the system for deep sleep. - * - * @param wakeup_opt - same as for rtc_sleep_start - * @param reject_opt - same as for rtc_sleep_start - * - * @return non-zero if sleep was rejected by hardware - */ -uint32_t rtc_deep_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt); /** * RTC power and clock control initialization settings From 7a4d38eac159da7549658403310646de679f613b Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Tue, 17 Jan 2023 18:50:39 +0800 Subject: [PATCH 16/16] example: bringup light sleep example for esp32c6 --- components/hal/esp32c6/include/hal/uart_ll.h | 4 ++-- examples/system/.build-test-rules.yml | 2 +- examples/system/light_sleep/README.md | 4 ++-- examples/system/light_sleep/main/gpio_wakeup.c | 3 ++- examples/system/light_sleep/pytest_light_sleep.py | 3 ++- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/components/hal/esp32c6/include/hal/uart_ll.h b/components/hal/esp32c6/include/hal/uart_ll.h index 543ebfcbda..20f9729049 100644 --- a/components/hal/esp32c6/include/hal/uart_ll.h +++ b/components/hal/esp32c6/include/hal/uart_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -76,7 +76,7 @@ typedef enum { UART_INTR_RS485_FRM_ERR = (0x1 << 16), UART_INTR_RS485_CLASH = (0x1 << 17), UART_INTR_CMD_CHAR_DET = (0x1 << 18), - // UART_INTR_WAKEUP = (0x1 << 19), // TODO: Test UART wakeup while supporting sleep + UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; /** diff --git a/examples/system/.build-test-rules.yml b/examples/system/.build-test-rules.yml index aa81500849..4abd784874 100644 --- a/examples/system/.build-test-rules.yml +++ b/examples/system/.build-test-rules.yml @@ -106,7 +106,7 @@ examples/system/ipc/ipc_isr: examples/system/light_sleep: disable: - - if: IDF_TARGET in ["esp32c2", "esp32c6", "esp32h2"] + - if: IDF_TARGET in ["esp32c2", "esp32h2"] temporary: true reason: target(s) not supported yet diff --git a/examples/system/light_sleep/README.md b/examples/system/light_sleep/README.md index 70ada8ab88..2a7c44ffb9 100644 --- a/examples/system/light_sleep/README.md +++ b/examples/system/light_sleep/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32 | ESP32-C3 | ESP32-S2 | ESP32-S3 | -| ----------------- | ----- | -------- | -------- | -------- | +| Supported Targets | ESP32 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | # Light Sleep Example diff --git a/examples/system/light_sleep/main/gpio_wakeup.c b/examples/system/light_sleep/main/gpio_wakeup.c index d17d836029..d60ec0e380 100644 --- a/examples/system/light_sleep/main/gpio_wakeup.c +++ b/examples/system/light_sleep/main/gpio_wakeup.c @@ -12,7 +12,8 @@ /* Most development boards have "boot" button attached to GPIO0. * You can also change this to another pin. */ -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32H4 +#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2 || CONFIG_IDF_TARGET_ESP32H4 \ + || CONFIG_IDF_TARGET_ESP32C6 #define BOOT_BUTTON_NUM 9 #else #define BOOT_BUTTON_NUM 0 diff --git a/examples/system/light_sleep/pytest_light_sleep.py b/examples/system/light_sleep/pytest_light_sleep.py index 4b0fc8c9a7..827aab61e4 100644 --- a/examples/system/light_sleep/pytest_light_sleep.py +++ b/examples/system/light_sleep/pytest_light_sleep.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 import logging @@ -13,6 +13,7 @@ from pytest_embedded import Dut @pytest.mark.esp32s2 @pytest.mark.esp32s3 @pytest.mark.esp32c3 +@pytest.mark.esp32c6 @pytest.mark.generic def test_light_sleep(dut: Dut) -> None: