/* * SPDX-FileCopyrightText: 2023-2024 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" #include "hal/efuse_ll.h" #include "hal/efuse_hal.h" #include "esp_hw_log.h" static __attribute__((unused)) const char *TAG = "pmu_param"; #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 = PMU_HP_ICG_MODEM_CODE_ACTIVE \ }, \ .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 = PMU_HP_ICG_MODEM_CODE_MODEM \ }, \ .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 = PMU_HP_ICG_MODEM_CODE_SLEEP \ }, \ .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 = 0, \ .slp_logic_dbias = 0, \ .dbias = HP_CALI_DBIAS_DEFAULT \ }, \ .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 = 0, \ .slp_logic_dbias = 0, \ .dbias = HP_CALI_DBIAS_DEFAULT \ }, \ .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 = 0, \ .slp_logic_xpd = 0, \ .xpd = 1, \ .slp_mem_dbias = 0, \ .slp_logic_dbias = 0, \ .dbias = 1 \ }, \ .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 = 1, \ .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_GDMA) | \ 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_GDMA) | \ 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 */ #if CONFIG_ESP_SYSTEM_RTC_EXT_XTAL # define PMU_SLOW_CLK_USE_EXT_XTAL (1) #else # define PMU_SLOW_CLK_USE_EXT_XTAL (0) #endif #define PMU_LP_ACTIVE_POWER_CONFIG_DEFAULT() { \ .dig_power = { \ .mem_dslp = 0, \ .peri_pd_en = 0, \ }, \ .clk_power = { \ .xpd_xtal32k = PMU_SLOW_CLK_USE_EXT_XTAL, \ .xpd_rc32k = 0, \ .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 = 0, \ .dbias = LP_CALI_DBIAS_DEFAULT \ }, \ .regulator1 = { \ .drv_b = 0x0 \ } \ } #define PMU_LP_SLEEP_ANALOG_CONFIG_DEFAULT() { \ .bias = { \ .xpd_bias = 0, \ .dbg_atten = 0, \ .pd_cur = 1, \ .bias_sleep = 1, \ }, \ .regulator0 = { \ .slp_xpd = 0, \ .xpd = 1, \ .slp_dbias = 0, \ .dbias = 12 \ }, \ .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]; } uint32_t get_act_hp_dbias(void) { /* hp_cali_dbias is read from efuse to ensure that the hp_active_voltage is close to 1.15V */ uint32_t hp_cali_dbias = HP_CALI_DBIAS_DEFAULT; uint32_t blk_version = efuse_hal_blk_version(); if (blk_version >= 3) { hp_cali_dbias = efuse_ll_get_active_hp_dbias(); if (hp_cali_dbias != 0) { //efuse dbias need to add 2 to meet the CPU frequency switching if (hp_cali_dbias + 2 > 31) { hp_cali_dbias = 31; } else { hp_cali_dbias += 2; } } else { hp_cali_dbias = HP_CALI_DBIAS_DEFAULT; ESP_HW_LOGD(TAG, "hp_cali_dbias not burnt in efuse or wrong value was burnt in blk version: %" PRIu32 "\n", blk_version); } } return hp_cali_dbias; } uint32_t get_act_lp_dbias(void) { /* lp_cali_dbias is read from efuse to ensure that the lp_active_voltage is close to 1.15V */ uint32_t lp_cali_dbias = LP_CALI_DBIAS_DEFAULT; uint32_t blk_version = efuse_hal_blk_version(); if (blk_version >= 3) { lp_cali_dbias = efuse_ll_get_active_lp_dbias(); if (lp_cali_dbias != 0) { //efuse dbias need to add 2 to meet the CPU frequency switching if (lp_cali_dbias + 2 > 31) { lp_cali_dbias = 31; } else { lp_cali_dbias += 2; } } else { lp_cali_dbias = LP_CALI_DBIAS_DEFAULT; ESP_HW_LOGD(TAG, "lp_cali_dbias not burnt in efuse or wrong value was burnt in blk version: %" PRIu32 "\n", blk_version); } } else { ESP_HW_LOGD(TAG, "blk_version is less than 3, act dbias not burnt in efuse\n"); } return lp_cali_dbias; }