From 9143a9dc90210fa71d8421660ca4b41cb7d73bb4 Mon Sep 17 00:00:00 2001 From: Armando Date: Wed, 6 Dec 2023 20:59:41 +0800 Subject: [PATCH] feature(ldo): ldo driver --- components/esp_hw_support/CMakeLists.txt | 4 + .../include/esp_private/esp_ldo.h | 123 +++++ components/esp_hw_support/ldo/esp_ldo.c | 208 +++++++++ components/esp_hw_support/ldo/linker.lf | 4 + .../main/CMakeLists.txt | 4 + .../main/test_ldo.c | 75 +++ components/hal/esp32p4/include/hal/ldo_ll.h | 142 ++++++ .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 + .../soc/esp32p4/include/soc/pmu_struct.h | 435 ++---------------- components/soc/esp32p4/include/soc/soc_caps.h | 1 + 10 files changed, 601 insertions(+), 399 deletions(-) create mode 100644 components/esp_hw_support/include/esp_private/esp_ldo.h create mode 100644 components/esp_hw_support/ldo/esp_ldo.c create mode 100644 components/esp_hw_support/ldo/linker.lf create mode 100644 components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_ldo.c create mode 100644 components/hal/esp32p4/include/hal/ldo_ll.h diff --git a/components/esp_hw_support/CMakeLists.txt b/components/esp_hw_support/CMakeLists.txt index cf8e590e94..0c460cc461 100644 --- a/components/esp_hw_support/CMakeLists.txt +++ b/components/esp_hw_support/CMakeLists.txt @@ -68,6 +68,10 @@ if(NOT BOOTLOADER_BUILD) list(APPEND srcs "dma/gdma.c") endif() + if(CONFIG_SOC_MULTI_USAGE_LDO_SUPPORTED) + list(APPEND srcs "ldo/esp_ldo.c") + endif() + if(CONFIG_SOC_ASYNC_MEMCPY_SUPPORTED) list(APPEND srcs "dma/esp_async_memcpy.c") if(CONFIG_SOC_GDMA_SUPPORTED) diff --git a/components/esp_hw_support/include/esp_private/esp_ldo.h b/components/esp_hw_support/include/esp_private/esp_ldo.h new file mode 100644 index 0000000000..3736eb0d70 --- /dev/null +++ b/components/esp_hw_support/include/esp_private/esp_ldo.h @@ -0,0 +1,123 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ESP_LDO_ID_1 0 ///< See datasheet `VFB/VO1` +#define ESP_LDO_ID_2 1 ///< See datasheet `VFB/VO2` +#define ESP_LDO_ID_3 2 ///< See datasheet `VFB/VO3` +#define ESP_LDO_ID_4 3 ///< See datasheet `VFB/VO4` + +/** + * @brief Type of LDO unit handle + */ +typedef struct ldo_unit_ctx_t *esp_ldo_unit_handle_t; + +/** + * @brief LDO unit configurations + */ +typedef struct { + int voltage_mv; ///< LDO output voltage in mV +} esp_ldo_unit_cfg_t; + +/** + * @brief LDO driver initial configurations + */ +typedef struct { + int unit_id; ///< LDO unit + esp_ldo_unit_cfg_t cfg; ///< LDO unit configuration + struct { + uint32_t enable_unit: 1; ///< Enable the LDO unit after it's initialised + uint32_t shared_ldo: 1; ///< Mark this LDO unit as shared + } flags; ///< LDO unit flags +} esp_ldo_unit_init_cfg_t; + +/** + * @Brief Init a LDO during early stage + * + * @note This API is only for early stage usage + * + * @param[in] unit_id LDO unit ID + * @param[in] cfg LDO unit configuration + * + * @return LDO unit handle + */ +esp_ldo_unit_handle_t esp_ldo_init_unit_early(const esp_ldo_unit_init_cfg_t *init_config); + +/** + * @Brief Init a LDO + * + * @param[in] init_config LDO initial configurations + * @param[out] ret_unit LDO unit handle + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid arguments + * - ESP_ERR_NOT_FOUND: LDO unit is in use already + */ +esp_err_t esp_ldo_init_unit(const esp_ldo_unit_init_cfg_t *init_config, esp_ldo_unit_handle_t *ret_unit); + +/** + * @Brief Enable a LDO + * + * @param[in] unit LDO unit handle + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid arguments + * - ESP_ERR_INVALID_STATE: LDO is enabled already + */ +esp_err_t esp_ldo_enable_unit(esp_ldo_unit_handle_t unit); + +/** + * @Brief Disable a LDO + * + * @param[in] unit LDO unit handle + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid arguments + * - ESP_ERR_INVALID_STATE: LDO is disabled already + */ +esp_err_t esp_ldo_disable_unit(esp_ldo_unit_handle_t unit); + +/** + * @Brief Deinit a LDO + * + * @param[in] unit LDO unit handle + * + * @return + * - ESP_OK: On success + * - ESP_ERR_INVALID_ARG: Invalid arguments + * - ESP_ERR_INVALID_STATE: LDO is still enabled + */ +esp_err_t esp_ldo_deinit_unit(esp_ldo_unit_handle_t unit); + +/** + * Dump LDO usages + * + * @note This API shall not be called from an ISR. + * @note This API does not guarantee thread safety + * + * @param stream stream to print information to; use stdout or stderr to print + * to the console; use fmemopen/open_memstream to print to a + * string buffer. + * @return + * - ESP_OK + */ +esp_err_t esp_ldo_usage_dump(FILE* stream); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/ldo/esp_ldo.c b/components/esp_hw_support/ldo/esp_ldo.c new file mode 100644 index 0000000000..6003fec4f8 --- /dev/null +++ b/components/esp_hw_support/ldo/esp_ldo.c @@ -0,0 +1,208 @@ +/* + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "sdkconfig.h" +#include "stdatomic.h" +#include "esp_log.h" +#include "esp_check.h" +#include "esp_heap_caps.h" +#include "freertos/FreeRTOS.h" +#include "soc/soc_caps.h" +#include "hal/ldo_ll.h" +#include "esp_private/esp_ldo.h" + +static const DRAM_ATTR char TAG[] = "ldo"; + +typedef struct ldo_unit_ctx_t { + int unit_id; + int voltage_mv; + bool enabled; + int ref_cnt; + portMUX_TYPE spinlock; +} ldo_unit_ctx_t; + +typedef struct ldo_ctx_t { + _lock_t mutex; + ldo_unit_ctx_t units[LDO_LL_UNIT_NUM]; +} ldo_ctx_t; + +static ldo_ctx_t s_ctx; //LDO context +//LDO1 is always reserved for Flash usage +static atomic_bool s_ldo_unit_claimed[LDO_LL_UNIT_NUM] = {ATOMIC_VAR_INIT(true), + ATOMIC_VAR_INIT(false), + ATOMIC_VAR_INIT(false), + ATOMIC_VAR_INIT(false)}; + +static bool s_ldo_unit_claim(uint32_t unit); +static bool s_ldo_unit_free(uint32_t unit); +static bool s_ldo_unit_needs_claim(const esp_ldo_unit_init_cfg_t *init_config); + + +//This API should always success +esp_ldo_unit_handle_t esp_ldo_init_unit_early(const esp_ldo_unit_init_cfg_t *init_config) +{ + assert(init_config); + assert(init_config->unit_id < LDO_LL_UNIT_NUM); + + ldo_unit_ctx_t *unit = &s_ctx.units[init_config->unit_id]; + bool needs_claim = s_ldo_unit_needs_claim(init_config); + bool success_claim = false; + + if (needs_claim) { + success_claim = s_ldo_unit_claim(init_config->unit_id); + assert(success_claim); + unit->unit_id = init_config->unit_id; + unit->voltage_mv = init_config->cfg.voltage_mv; + unit->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; + ldo_ll_set_output_voltage_mv(init_config->unit_id, init_config->cfg.voltage_mv); + + if (init_config->flags.enable_unit) { + ldo_ll_enable(init_config->unit_id, true); + unit->enabled = true; + } + } else { + bool same_voltage = init_config->cfg.voltage_mv == unit->voltage_mv; + assert(same_voltage); + } + + unit->ref_cnt++; + + return unit; +} + +esp_err_t esp_ldo_init_unit(const esp_ldo_unit_init_cfg_t *init_config, esp_ldo_unit_handle_t *ret_unit) +{ + ESP_RETURN_ON_FALSE(init_config && ret_unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(init_config->unit_id < LDO_LL_UNIT_NUM, ESP_ERR_INVALID_ARG, TAG, "invalid unit"); + + ldo_unit_ctx_t *unit = &s_ctx.units[init_config->unit_id]; + bool needs_claim = s_ldo_unit_needs_claim(init_config); + bool success_claim = false; + + if (needs_claim) { + success_claim = s_ldo_unit_claim(init_config->unit_id); + ESP_RETURN_ON_FALSE(success_claim, ESP_ERR_NOT_FOUND, TAG, "ldo%d is already in use", init_config->unit_id + 1); + unit->unit_id = init_config->unit_id; + unit->voltage_mv = init_config->cfg.voltage_mv; + unit->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; + ldo_ll_set_output_voltage_mv(init_config->unit_id, init_config->cfg.voltage_mv); + if (init_config->flags.enable_unit) { + ldo_ll_enable(init_config->unit_id, true); + unit->enabled = true; + } + ESP_LOGD(TAG, "new ldo unit%d is created", unit->unit_id); + } else { + bool same_voltage = init_config->cfg.voltage_mv == unit->voltage_mv; + ESP_RETURN_ON_FALSE(same_voltage, ESP_ERR_INVALID_ARG, TAG, "not same voltage, cannot share ldo%d", init_config->unit_id + 1); + ESP_LOGD(TAG, "new ldo unit%d is shared", unit->unit_id); + } + + portENTER_CRITICAL(&unit->spinlock); + unit->ref_cnt++; + portEXIT_CRITICAL(&unit->spinlock); + + *ret_unit = unit; + return ESP_OK; +} + +esp_err_t esp_ldo_deinit_unit(esp_ldo_unit_handle_t unit) +{ + ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(unit->enabled == false, ESP_ERR_INVALID_STATE, TAG, "invalid state: ldo unit is still enabled"); + + bool needs_free = false; + portENTER_CRITICAL(&unit->spinlock); + unit->ref_cnt -= 1; + if (unit->ref_cnt == 0) { + needs_free = true; + } + portEXIT_CRITICAL(&unit->spinlock); + + if (needs_free) { + bool success_free = false; + success_free = s_ldo_unit_free(unit->unit_id); + ESP_RETURN_ON_FALSE(success_free, ESP_ERR_NOT_FOUND, TAG, "ldo%d isn't in use", unit->unit_id + 1); + ESP_LOGD(TAG, "ldo unit%d is deleted", unit->unit_id + 1); + _lock_acquire(&s_ctx.mutex); + memset(&s_ctx.units[unit->unit_id], 0x0, sizeof(ldo_unit_ctx_t)); + _lock_release(&s_ctx.mutex); + } + + return ESP_OK; +} + +esp_err_t esp_ldo_enable_unit(esp_ldo_unit_handle_t unit) +{ + ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(unit->enabled == false, ESP_ERR_INVALID_STATE, TAG, "invalid state: ldo unit is enabled already"); + + ldo_ll_enable(unit->unit_id, true); + unit->enabled = true; + + return ESP_OK; +} + +esp_err_t esp_ldo_disable_unit(esp_ldo_unit_handle_t unit) +{ + ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer"); + ESP_RETURN_ON_FALSE(unit->enabled == true, ESP_ERR_INVALID_STATE, TAG, "invalid state: ldo unit is disabled already"); + + ldo_ll_enable(unit->unit_id, false); + unit->enabled = false; + + return ESP_OK; +} + +esp_err_t esp_ldo_usage_dump(FILE* stream) +{ + char line[100]; + fprintf(stream, "LDOs Info:\n"); + for (int i = 0; i < LDO_LL_UNIT_NUM; i++) { + fprintf(stream, "%-15s %-14s %-14s\n", "LDO ID", "voltage_mv", "enabled"); + + char *buf = line; + size_t len = sizeof(line); + memset(line, 0x0, len); + snprintf(buf, len, "%-15d 0x%-12d %-11x\n", + s_ctx.units[i].unit_id + 1, + s_ctx.units[i].voltage_mv, + s_ctx.units[i].enabled); + fputs(line, stream); + } + + fprintf(stream, "You can use a disabled LDO unit, or share an enabled LDO unit\n"); + + return ESP_OK; +} + +static bool s_ldo_unit_claim(uint32_t unit) +{ + bool false_var = false; + return atomic_compare_exchange_strong(&s_ldo_unit_claimed[unit], &false_var, true); +} + +static bool s_ldo_unit_free(uint32_t unit) +{ + bool true_var = true; + return atomic_compare_exchange_strong(&s_ldo_unit_claimed[unit], &true_var, false); +} + +static bool s_ldo_unit_needs_claim(const esp_ldo_unit_init_cfg_t *init_config) +{ + bool needs_claim = false; + + if (s_ctx.units[init_config->unit_id].ref_cnt == 0) { + needs_claim = true; + } else { + if (!init_config->flags.shared_ldo) { + needs_claim = true; + } + } + + return needs_claim; +} diff --git a/components/esp_hw_support/ldo/linker.lf b/components/esp_hw_support/ldo/linker.lf new file mode 100644 index 0000000000..2d1732faca --- /dev/null +++ b/components/esp_hw_support/ldo/linker.lf @@ -0,0 +1,4 @@ +[mapping:ldo_driver] +archive: libesp_hw_support.a +entries: + esp_ldo: esp_ldo_init_unit_early (noflash) diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/CMakeLists.txt b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/CMakeLists.txt index 0f499f0d84..dcac67fadb 100644 --- a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/CMakeLists.txt +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/CMakeLists.txt @@ -8,6 +8,10 @@ set(srcs "test_app_main.c" "test_random.c" ) +if(CONFIG_SOC_MULTI_USAGE_LDO_SUPPORTED) + list(APPEND srcs "test_ldo.c") +endif() + if(CONFIG_SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX OR CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX) list(APPEND srcs "test_esp_clock_output.c") endif() diff --git a/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_ldo.c b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_ldo.c new file mode 100644 index 0000000000..47c806bcb3 --- /dev/null +++ b/components/esp_hw_support/test_apps/esp_hw_support_unity_tests/main/test_ldo.c @@ -0,0 +1,75 @@ +/* + * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "sdkconfig.h" +#include "unity.h" +#include "esp_private/esp_ldo.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +TEST_CASE("LDO unit early / normal allocation", "[LDO]") +{ + esp_ldo_unit_init_cfg_t init_early_unit_cfg = { + .unit_id = ESP_LDO_ID_3, + .cfg = { + .voltage_mv = 1800, + }, + .flags.enable_unit = true, + }; + esp_ldo_unit_handle_t early_unit = esp_ldo_init_unit_early(&init_early_unit_cfg); + TEST_ASSERT(esp_ldo_enable_unit(early_unit) == ESP_ERR_INVALID_STATE); + TEST_ESP_OK(esp_ldo_disable_unit(early_unit)); + + esp_ldo_unit_handle_t unit = NULL; + esp_ldo_unit_init_cfg_t init_unit_cfg = { + .unit_id = ESP_LDO_ID_4, + .cfg = { + .voltage_mv = 2500, + }, + }; + TEST_ESP_OK(esp_ldo_init_unit(&init_unit_cfg, &unit)); + TEST_ESP_OK(esp_ldo_enable_unit(unit)); + TEST_ESP_OK(esp_ldo_disable_unit(unit)); + + init_unit_cfg.flags.shared_ldo = true; + esp_ldo_unit_handle_t shared_unit = NULL; + TEST_ESP_OK(esp_ldo_init_unit(&init_unit_cfg, &shared_unit)); + + TEST_ESP_OK(esp_ldo_deinit_unit(early_unit)); + TEST_ESP_OK(esp_ldo_deinit_unit(shared_unit)); + TEST_ESP_OK(esp_ldo_deinit_unit(unit)); +} + +TEST_CASE("LDO unit output", "[LDO][mannual][ignore]") +{ + esp_ldo_unit_init_cfg_t early_unit_cfg = { + .unit_id = ESP_LDO_ID_2, + .cfg = { + .voltage_mv = 2500, + }, + .flags.enable_unit = true, + }; + esp_ldo_unit_handle_t early_unit2 = esp_ldo_init_unit_early(&early_unit_cfg); + assert(early_unit2); + + early_unit_cfg.unit_id = ESP_LDO_ID_3; + early_unit_cfg.cfg.voltage_mv = 3300; + esp_ldo_unit_handle_t early_unit3 = esp_ldo_init_unit_early(&early_unit_cfg); + assert(early_unit3); + + early_unit_cfg.unit_id = ESP_LDO_ID_4; + early_unit_cfg.cfg.voltage_mv = 1100; + esp_ldo_unit_handle_t early_unit4 = esp_ldo_init_unit_early(&early_unit_cfg); + assert(early_unit4); + + esp_ldo_usage_dump(stdout); + + while (1) { + vTaskDelay(1); + } +} diff --git a/components/hal/esp32p4/include/hal/ldo_ll.h b/components/hal/esp32p4/include/hal/ldo_ll.h new file mode 100644 index 0000000000..db525a160c --- /dev/null +++ b/components/hal/esp32p4/include/hal/ldo_ll.h @@ -0,0 +1,142 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/******************************************************************************* + * NOTICE + * The ll is not public api, don't use in application code. + * See readme.md in hal/include/hal/readme.md + ******************************************************************************/ + +#pragma once + +#include +#include +#include "esp_bit_defs.h" +#include "hal/assert.h" +#include "soc/pmu_struct.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * LDO capabilities + */ +#define LDO_LL_UNIT_NUM 4 + +/** + * LDO LL macros, these macros are in the unit of mV + */ +#define LDO_LL_EXT_LDO_DREF_VOL_H_BASE 1000 +#define LDO_LL_EXT_LDO_DREF_VOL_H_STEP 100 +#define LDO_LL_EXT_LDO_DREF_VOL_L_BASE 500 +#define LDO_LL_EXT_LDO_DREF_VOL_L_STEP 50 +#define LDO_LL_EXT_LDO_MUL_VOL_BASE 1000 +#define LDO_LL_EXT_LDO_MUL_VOL_STEP 250 + +/** + * Trick to be adapted to the LDO register structure + * + * In pmu_ext_ldo_info_t ext_ldo[6] registers: + * - ext_ldo[0] is LDO1 + * - ext_ldo[3] is LDO2 + * - ext_ldo[1] is LDO3 + * - ext_ldo[4] is LDO4 + */ +#define LDO_ID2INDEX(id) (uint8_t[]){0,3,1,4}[id] + +/** + * @brief Enable a LDO + * + * @param ldo_id LDO ID + * @param enable True: enable; False: disable + */ +__attribute__((always_inline)) +static inline void ldo_ll_enable(int ldo_id, bool enable) +{ + HAL_ASSERT(ldo_id < LDO_LL_UNIT_NUM); + + PMU.ext_ldo[LDO_ID2INDEX(ldo_id)].pmu_ext_ldo.xpd = enable; +} + +/** + * @brief Enable a LDO + * + * @param ldo_id LDO ID + * @param voltage_mv Voltage in mV + */ +__attribute__((always_inline)) +static inline void ldo_ll_set_output_voltage_mv(int ldo_id, int voltage_mv) +{ + int dref = 0, mul = 0; + + /** + * Vout = dref * mul + * + * mul reg[2:0]: + * mul = 1~2.75, step = 0.25 + + * dref reg[3:0]: + * 0~8 : dref = 0.5V ~ 0.9V, step 50mV + * 9~15 : dref = 1.0V ~ 1.6V, step 100mV + */ + if (voltage_mv <= 500) { + dref = 0; + mul = 0; + } else if (voltage_mv <= 900) { + mul = 0; + dref = (voltage_mv - LDO_LL_EXT_LDO_DREF_VOL_L_BASE) / LDO_LL_EXT_LDO_DREF_VOL_L_STEP; + } else if (voltage_mv <= 1600) { + mul = 1; + dref = 6 + (voltage_mv - LDO_LL_EXT_LDO_DREF_VOL_H_BASE) / LDO_LL_EXT_LDO_DREF_VOL_H_STEP; + } else if (voltage_mv <= 2000) { + mul = 4; + dref = (voltage_mv / 2 - LDO_LL_EXT_LDO_DREF_VOL_L_BASE) / LDO_LL_EXT_LDO_DREF_VOL_L_STEP; + } else if (voltage_mv <= 3200) { + mul = 4; + dref = 9 + (voltage_mv / 2 - LDO_LL_EXT_LDO_DREF_VOL_H_BASE) / LDO_LL_EXT_LDO_DREF_VOL_H_STEP; + } else { + mul = 7; + dref = 15; + } + if (mul > 7) { + mul = 7; + } + if (mul < 0) { + mul = 0; + } + if (dref > 15) { + dref = 15; + } + if (dref < 0) { + dref = 0; + } + /** + * tieh_sel: + * - 0: tieh; + * - 1: sdmmc0_tieh; + * - 2: 3.3V; + * - 3: sdmmc1_tieh; + * + * tieh: + * - 0: dref * mul + * - 1: 3.3V + * + * force_tieh_sel: + * - 0: efuse + * - 1: tieh_sel + */ + PMU.ext_ldo[LDO_ID2INDEX(ldo_id)].pmu_ext_ldo.tieh_sel = 0; + PMU.ext_ldo[LDO_ID2INDEX(ldo_id)].pmu_ext_ldo.tieh = 0; + PMU.ext_ldo[LDO_ID2INDEX(ldo_id)].pmu_ext_ldo.force_tieh_sel = 1; + PMU.ext_ldo[LDO_ID2INDEX(ldo_id)].pmu_ext_ldo_ana.dref = dref; + PMU.ext_ldo[LDO_ID2INDEX(ldo_id)].pmu_ext_ldo_ana.mul = mul; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 8318d17b45..c61327b210 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -175,6 +175,10 @@ config SOC_SPI_FLASH_SUPPORTED bool default y +config SOC_MULTI_USAGE_LDO_SUPPORTED + bool + default y + config SOC_XTAL_SUPPORT_40M bool default y diff --git a/components/soc/esp32p4/include/soc/pmu_struct.h b/components/soc/esp32p4/include/soc/pmu_struct.h index 47b9cdb3cb..24e2b99383 100644 --- a/components/soc/esp32p4/include/soc/pmu_struct.h +++ b/components/soc/esp32p4/include/soc/pmu_struct.h @@ -2921,437 +2921,85 @@ typedef union { uint32_t val; } pmu_pwr_state_reg_t; -/** Type of ext_ldo_p0_pmu_0p1a register +/** Type of pmu_ext_ldo register * need_des */ typedef union { struct { uint32_t reserved_0:7; - /** pmu_0p1a_force_tieh_sel_0 : R/W; bitpos: [7]; default: 0; + /** force_tieh_sel : R/W; bitpos: [7]; default: 0; * need_des */ - uint32_t pmu_0p1a_force_tieh_sel_0:1; - /** pmu_0p1a_xpd_0 : R/W; bitpos: [8]; default: 1; + uint32_t force_tieh_sel:1; + /** xpd : R/W; bitpos: [8]; default: 1; * need_des */ - uint32_t pmu_0p1a_xpd_0:1; - /** pmu_0p1a_tieh_sel_0 : R/W; bitpos: [11:9]; default: 0; + uint32_t xpd:1; + /** tieh_sel : R/W; bitpos: [11:9]; default: 0; * need_des */ - uint32_t pmu_0p1a_tieh_sel_0:3; - /** pmu_0p1a_tieh_pos_en_0 : R/W; bitpos: [12]; default: 0; + uint32_t tieh_sel:3; + /** tieh_pos_en : R/W; bitpos: [12]; default: 0; * need_des */ - uint32_t pmu_0p1a_tieh_pos_en_0:1; - /** pmu_0p1a_tieh_neg_en_0 : R/W; bitpos: [13]; default: 0; + uint32_t tieh_pos_en:1; + /** tieh_neg_en : R/W; bitpos: [13]; default: 0; * need_des */ - uint32_t pmu_0p1a_tieh_neg_en_0:1; - /** pmu_0p1a_tieh_0 : R/W; bitpos: [14]; default: 0; + uint32_t tieh_neg_en:1; + /** tieh : R/W; bitpos: [14]; default: 0; * need_des */ - uint32_t pmu_0p1a_tieh_0:1; - /** pmu_0p1a_target1_0 : R/W; bitpos: [22:15]; default: 64; + uint32_t tieh:1; + /** target1 : R/W; bitpos: [22:15]; default: 64; * need_des */ - uint32_t pmu_0p1a_target1_0:8; - /** pmu_0p1a_target0_0 : R/W; bitpos: [30:23]; default: 128; + uint32_t target1:8; + /** target0 : R/W; bitpos: [30:23]; default: 128; * need_des */ - uint32_t pmu_0p1a_target0_0:8; - /** pmu_0p1a_ldo_cnt_prescaler_sel_0 : R/W; bitpos: [31]; default: 0; + uint32_t target0:8; + /** ldo_cnt_prescaler_sel : R/W; bitpos: [31]; default: 0; * need_des */ - uint32_t pmu_0p1a_ldo_cnt_prescaler_sel_0:1; + uint32_t ldo_cnt_prescaler_sel:1; }; uint32_t val; -} pmu_ext_ldo_p0_pmu_0p1a_reg_t; +} pmu_ext_ldo_reg_t; -/** Type of ext_ldo_p0_pmu_0p1a_ana register +/** Type of pmu_ext_ldo_ana register * need_des */ typedef union { struct { uint32_t reserved_0:23; - /** ana_pmu_0p1a_mul_0 : R/W; bitpos: [25:23]; default: 2; + /** mul : R/W; bitpos: [25:23]; default: 2; * need_des */ - uint32_t ana_pmu_0p1a_mul_0:3; - /** ana_pmu_0p1a_en_vdet_0 : R/W; bitpos: [26]; default: 0; + uint32_t mul:3; + /** en_vdet : R/W; bitpos: [26]; default: 0; * need_des */ - uint32_t ana_pmu_0p1a_en_vdet_0:1; - /** ana_pmu_0p1a_en_cur_lim_0 : R/W; bitpos: [27]; default: 0; + uint32_t en_vdet:1; + /** en_cur_lim : R/W; bitpos: [27]; default: 0; * need_des */ - uint32_t ana_pmu_0p1a_en_cur_lim_0:1; - /** ana_pmu_0p1a_dref_0 : R/W; bitpos: [31:28]; default: 11; + uint32_t en_cur_lim:1; + /** dref : R/W; bitpos: [31:28]; default: 11; * need_des */ - uint32_t ana_pmu_0p1a_dref_0:4; + uint32_t dref:4; }; uint32_t val; -} pmu_ext_ldo_p0_pmu_0p1a_ana_reg_t; +} pmu_ext_ldo_ana_reg_t; -/** Type of ext_ldo_p0_pmu_0p2a register +/** Type of ahb_dma_in_chn_reg_t register * need_des */ -typedef union { - struct { - uint32_t reserved_0:7; - /** pmu_0p2a_force_tieh_sel_0 : R/W; bitpos: [7]; default: 0; - * need_des - */ - uint32_t pmu_0p2a_force_tieh_sel_0:1; - /** pmu_0p2a_xpd_0 : R/W; bitpos: [8]; default: 0; - * need_des - */ - uint32_t pmu_0p2a_xpd_0:1; - /** pmu_0p2a_tieh_sel_0 : R/W; bitpos: [11:9]; default: 0; - * need_des - */ - uint32_t pmu_0p2a_tieh_sel_0:3; - /** pmu_0p2a_tieh_pos_en_0 : R/W; bitpos: [12]; default: 0; - * need_des - */ - uint32_t pmu_0p2a_tieh_pos_en_0:1; - /** pmu_0p2a_tieh_neg_en_0 : R/W; bitpos: [13]; default: 0; - * need_des - */ - uint32_t pmu_0p2a_tieh_neg_en_0:1; - /** pmu_0p2a_tieh_0 : R/W; bitpos: [14]; default: 0; - * need_des - */ - uint32_t pmu_0p2a_tieh_0:1; - /** pmu_0p2a_target1_0 : R/W; bitpos: [22:15]; default: 64; - * need_des - */ - uint32_t pmu_0p2a_target1_0:8; - /** pmu_0p2a_target0_0 : R/W; bitpos: [30:23]; default: 128; - * need_des - */ - uint32_t pmu_0p2a_target0_0:8; - /** pmu_0p2a_ldo_cnt_prescaler_sel_0 : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t pmu_0p2a_ldo_cnt_prescaler_sel_0:1; - }; - uint32_t val; -} pmu_ext_ldo_p0_pmu_0p2a_reg_t; - -/** Type of ext_ldo_p0_pmu_0p2a_ana register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:23; - /** ana_pmu_0p2a_mul_0 : R/W; bitpos: [25:23]; default: 0; - * need_des - */ - uint32_t ana_pmu_0p2a_mul_0:3; - /** ana_pmu_0p2a_en_vdet_0 : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t ana_pmu_0p2a_en_vdet_0:1; - /** ana_pmu_0p2a_en_cur_lim_0 : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t ana_pmu_0p2a_en_cur_lim_0:1; - /** ana_pmu_0p2a_dref_0 : R/W; bitpos: [31:28]; default: 10; - * need_des - */ - uint32_t ana_pmu_0p2a_dref_0:4; - }; - uint32_t val; -} pmu_ext_ldo_p0_pmu_0p2a_ana_reg_t; - -/** Type of ext_ldo_p0_pmu_0p3a register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:7; - /** pmu_0p3a_force_tieh_sel_0 : R/W; bitpos: [7]; default: 0; - * need_des - */ - uint32_t pmu_0p3a_force_tieh_sel_0:1; - /** pmu_0p3a_xpd_0 : R/W; bitpos: [8]; default: 0; - * need_des - */ - uint32_t pmu_0p3a_xpd_0:1; - /** pmu_0p3a_tieh_sel_0 : R/W; bitpos: [11:9]; default: 0; - * need_des - */ - uint32_t pmu_0p3a_tieh_sel_0:3; - /** pmu_0p3a_tieh_pos_en_0 : R/W; bitpos: [12]; default: 0; - * need_des - */ - uint32_t pmu_0p3a_tieh_pos_en_0:1; - /** pmu_0p3a_tieh_neg_en_0 : R/W; bitpos: [13]; default: 0; - * need_des - */ - uint32_t pmu_0p3a_tieh_neg_en_0:1; - /** pmu_0p3a_tieh_0 : R/W; bitpos: [14]; default: 0; - * need_des - */ - uint32_t pmu_0p3a_tieh_0:1; - /** pmu_0p3a_target1_0 : R/W; bitpos: [22:15]; default: 64; - * need_des - */ - uint32_t pmu_0p3a_target1_0:8; - /** pmu_0p3a_target0_0 : R/W; bitpos: [30:23]; default: 128; - * need_des - */ - uint32_t pmu_0p3a_target0_0:8; - /** pmu_0p3a_ldo_cnt_prescaler_sel_0 : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t pmu_0p3a_ldo_cnt_prescaler_sel_0:1; - }; - uint32_t val; -} pmu_ext_ldo_p0_pmu_0p3a_reg_t; - -/** Type of ext_ldo_p0_pmu_0p3a_ana register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:23; - /** ana_pmu_0p3a_mul_0 : R/W; bitpos: [25:23]; default: 0; - * need_des - */ - uint32_t ana_pmu_0p3a_mul_0:3; - /** ana_pmu_0p3a_en_vdet_0 : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t ana_pmu_0p3a_en_vdet_0:1; - /** ana_pmu_0p3a_en_cur_lim_0 : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t ana_pmu_0p3a_en_cur_lim_0:1; - /** ana_pmu_0p3a_dref_0 : R/W; bitpos: [31:28]; default: 10; - * need_des - */ - uint32_t ana_pmu_0p3a_dref_0:4; - }; - uint32_t val; -} pmu_ext_ldo_p0_pmu_0p3a_ana_reg_t; - -/** Type of ext_ldo_p1_pmu_0p1a register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:7; - /** pmu_0p1a_force_tieh_sel_1 : R/W; bitpos: [7]; default: 0; - * need_des - */ - uint32_t pmu_0p1a_force_tieh_sel_1:1; - /** pmu_0p1a_xpd_1 : R/W; bitpos: [8]; default: 0; - * need_des - */ - uint32_t pmu_0p1a_xpd_1:1; - /** pmu_0p1a_tieh_sel_1 : R/W; bitpos: [11:9]; default: 0; - * need_des - */ - uint32_t pmu_0p1a_tieh_sel_1:3; - /** pmu_0p1a_tieh_pos_en_1 : R/W; bitpos: [12]; default: 0; - * need_des - */ - uint32_t pmu_0p1a_tieh_pos_en_1:1; - /** pmu_0p1a_tieh_neg_en_1 : R/W; bitpos: [13]; default: 0; - * need_des - */ - uint32_t pmu_0p1a_tieh_neg_en_1:1; - /** pmu_0p1a_tieh_1 : R/W; bitpos: [14]; default: 0; - * need_des - */ - uint32_t pmu_0p1a_tieh_1:1; - /** pmu_0p1a_target1_1 : R/W; bitpos: [22:15]; default: 64; - * need_des - */ - uint32_t pmu_0p1a_target1_1:8; - /** pmu_0p1a_target0_1 : R/W; bitpos: [30:23]; default: 128; - * need_des - */ - uint32_t pmu_0p1a_target0_1:8; - /** pmu_0p1a_ldo_cnt_prescaler_sel_1 : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t pmu_0p1a_ldo_cnt_prescaler_sel_1:1; - }; - uint32_t val; -} pmu_ext_ldo_p1_pmu_0p1a_reg_t; - -/** Type of ext_ldo_p1_pmu_0p1a_ana register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:23; - /** ana_pmu_0p1a_mul_1 : R/W; bitpos: [25:23]; default: 0; - * need_des - */ - uint32_t ana_pmu_0p1a_mul_1:3; - /** ana_pmu_0p1a_en_vdet_1 : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t ana_pmu_0p1a_en_vdet_1:1; - /** ana_pmu_0p1a_en_cur_lim_1 : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t ana_pmu_0p1a_en_cur_lim_1:1; - /** ana_pmu_0p1a_dref_1 : R/W; bitpos: [31:28]; default: 10; - * need_des - */ - uint32_t ana_pmu_0p1a_dref_1:4; - }; - uint32_t val; -} pmu_ext_ldo_p1_pmu_0p1a_ana_reg_t; - -/** Type of ext_ldo_p1_pmu_0p2a register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:7; - /** pmu_0p2a_force_tieh_sel_1 : R/W; bitpos: [7]; default: 0; - * need_des - */ - uint32_t pmu_0p2a_force_tieh_sel_1:1; - /** pmu_0p2a_xpd_1 : R/W; bitpos: [8]; default: 0; - * need_des - */ - uint32_t pmu_0p2a_xpd_1:1; - /** pmu_0p2a_tieh_sel_1 : R/W; bitpos: [11:9]; default: 0; - * need_des - */ - uint32_t pmu_0p2a_tieh_sel_1:3; - /** pmu_0p2a_tieh_pos_en_1 : R/W; bitpos: [12]; default: 0; - * need_des - */ - uint32_t pmu_0p2a_tieh_pos_en_1:1; - /** pmu_0p2a_tieh_neg_en_1 : R/W; bitpos: [13]; default: 0; - * need_des - */ - uint32_t pmu_0p2a_tieh_neg_en_1:1; - /** pmu_0p2a_tieh_1 : R/W; bitpos: [14]; default: 0; - * need_des - */ - uint32_t pmu_0p2a_tieh_1:1; - /** pmu_0p2a_target1_1 : R/W; bitpos: [22:15]; default: 64; - * need_des - */ - uint32_t pmu_0p2a_target1_1:8; - /** pmu_0p2a_target0_1 : R/W; bitpos: [30:23]; default: 128; - * need_des - */ - uint32_t pmu_0p2a_target0_1:8; - /** pmu_0p2a_ldo_cnt_prescaler_sel_1 : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t pmu_0p2a_ldo_cnt_prescaler_sel_1:1; - }; - uint32_t val; -} pmu_ext_ldo_p1_pmu_0p2a_reg_t; - -/** Type of ext_ldo_p1_pmu_0p2a_ana register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:23; - /** ana_pmu_0p2a_mul_1 : R/W; bitpos: [25:23]; default: 0; - * need_des - */ - uint32_t ana_pmu_0p2a_mul_1:3; - /** ana_pmu_0p2a_en_vdet_1 : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t ana_pmu_0p2a_en_vdet_1:1; - /** ana_pmu_0p2a_en_cur_lim_1 : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t ana_pmu_0p2a_en_cur_lim_1:1; - /** ana_pmu_0p2a_dref_1 : R/W; bitpos: [31:28]; default: 10; - * need_des - */ - uint32_t ana_pmu_0p2a_dref_1:4; - }; - uint32_t val; -} pmu_ext_ldo_p1_pmu_0p2a_ana_reg_t; - -/** Type of ext_ldo_p1_pmu_0p3a register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:7; - /** pmu_0p3a_force_tieh_sel_1 : R/W; bitpos: [7]; default: 0; - * need_des - */ - uint32_t pmu_0p3a_force_tieh_sel_1:1; - /** pmu_0p3a_xpd_1 : R/W; bitpos: [8]; default: 0; - * need_des - */ - uint32_t pmu_0p3a_xpd_1:1; - /** pmu_0p3a_tieh_sel_1 : R/W; bitpos: [11:9]; default: 0; - * need_des - */ - uint32_t pmu_0p3a_tieh_sel_1:3; - /** pmu_0p3a_tieh_pos_en_1 : R/W; bitpos: [12]; default: 0; - * need_des - */ - uint32_t pmu_0p3a_tieh_pos_en_1:1; - /** pmu_0p3a_tieh_neg_en_1 : R/W; bitpos: [13]; default: 0; - * need_des - */ - uint32_t pmu_0p3a_tieh_neg_en_1:1; - /** pmu_0p3a_tieh_1 : R/W; bitpos: [14]; default: 0; - * need_des - */ - uint32_t pmu_0p3a_tieh_1:1; - /** pmu_0p3a_target1_1 : R/W; bitpos: [22:15]; default: 64; - * need_des - */ - uint32_t pmu_0p3a_target1_1:8; - /** pmu_0p3a_target0_1 : R/W; bitpos: [30:23]; default: 128; - * need_des - */ - uint32_t pmu_0p3a_target0_1:8; - /** pmu_0p3a_ldo_cnt_prescaler_sel_1 : R/W; bitpos: [31]; default: 0; - * need_des - */ - uint32_t pmu_0p3a_ldo_cnt_prescaler_sel_1:1; - }; - uint32_t val; -} pmu_ext_ldo_p1_pmu_0p3a_reg_t; - -/** Type of ext_ldo_p1_pmu_0p3a_ana register - * need_des - */ -typedef union { - struct { - uint32_t reserved_0:23; - /** ana_pmu_0p3a_mul_1 : R/W; bitpos: [25:23]; default: 0; - * need_des - */ - uint32_t ana_pmu_0p3a_mul_1:3; - /** ana_pmu_0p3a_en_vdet_1 : R/W; bitpos: [26]; default: 0; - * need_des - */ - uint32_t ana_pmu_0p3a_en_vdet_1:1; - /** ana_pmu_0p3a_en_cur_lim_1 : R/W; bitpos: [27]; default: 0; - * need_des - */ - uint32_t ana_pmu_0p3a_en_cur_lim_1:1; - /** ana_pmu_0p3a_dref_1 : R/W; bitpos: [31:28]; default: 10; - * need_des - */ - uint32_t ana_pmu_0p3a_dref_1:4; - }; - uint32_t val; -} pmu_ext_ldo_p1_pmu_0p3a_ana_reg_t; +typedef volatile struct pmu_ext_ldo_info_s { + volatile pmu_ext_ldo_reg_t pmu_ext_ldo; + volatile pmu_ext_ldo_ana_reg_t pmu_ext_ldo_ana; +} pmu_ext_ldo_info_t; /** Type of ext_wakeup_lv register * need_des @@ -3844,18 +3492,7 @@ typedef struct pmu_dev_t { 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_ext_ldo_p0_pmu_0p1a_reg_t ext_ldo_p0_pmu_0p1a; - volatile pmu_ext_ldo_p0_pmu_0p1a_ana_reg_t ext_ldo_p0_pmu_0p1a_ana; - volatile pmu_ext_ldo_p0_pmu_0p2a_reg_t ext_ldo_p0_pmu_0p2a; - volatile pmu_ext_ldo_p0_pmu_0p2a_ana_reg_t ext_ldo_p0_pmu_0p2a_ana; - volatile pmu_ext_ldo_p0_pmu_0p3a_reg_t ext_ldo_p0_pmu_0p3a; - volatile pmu_ext_ldo_p0_pmu_0p3a_ana_reg_t ext_ldo_p0_pmu_0p3a_ana; - volatile pmu_ext_ldo_p1_pmu_0p1a_reg_t ext_ldo_p1_pmu_0p1a; - volatile pmu_ext_ldo_p1_pmu_0p1a_ana_reg_t ext_ldo_p1_pmu_0p1a_ana; - volatile pmu_ext_ldo_p1_pmu_0p2a_reg_t ext_ldo_p1_pmu_0p2a; - volatile pmu_ext_ldo_p1_pmu_0p2a_ana_reg_t ext_ldo_p1_pmu_0p2a_ana; - volatile pmu_ext_ldo_p1_pmu_0p3a_reg_t ext_ldo_p1_pmu_0p3a; - volatile pmu_ext_ldo_p1_pmu_0p3a_ana_reg_t ext_ldo_p1_pmu_0p3a_ana; + volatile pmu_ext_ldo_info_t ext_ldo[6]; volatile pmu_ext_wakeup_lv_reg_t ext_wakeup_lv; volatile pmu_ext_wakeup_sel_reg_t ext_wakeup_sel; volatile pmu_ext_wakeup_st_reg_t ext_wakeup_st; diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index cd2d070a15..3f11d3def0 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -79,6 +79,7 @@ #define SOC_SPI_FLASH_SUPPORTED 1 // #define SOC_TOUCH_SENSOR_SUPPORTED 1 //TODO: IDF-7477 // #define SOC_RNG_SUPPORTED 1 //TODO: IDF-6522 +#define SOC_MULTI_USAGE_LDO_SUPPORTED 1 /*-------------------------- XTAL CAPS ---------------------------------------*/ #define SOC_XTAL_SUPPORT_40M 1