mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat(esp32c5): add system related supports
This commit is contained in:
parent
81aec7b929
commit
a48f4760d2
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <strings.h>
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_efuse_table.h"
|
||||
#include "esp_log.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
static __attribute__((unused)) const char *TAG = "flash_encrypt";
|
||||
|
||||
esp_err_t esp_flash_encryption_enable_secure_features(void)
|
||||
{
|
||||
#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
|
||||
ESP_LOGI(TAG, "Disable UART bootloader encryption...");
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling UART bootloader encryption");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE
|
||||
ESP_LOGI(TAG, "Disable UART bootloader cache...");
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling UART bootloader cache - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
|
||||
ESP_LOGI(TAG, "Disable JTAG...");
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_PAD_JTAG);
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_USB_JTAG);
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT);
|
||||
|
||||
#if defined(CONFIG_SECURE_BOOT_V2_ENABLED) && !defined(CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS)
|
||||
// This bit is set when enabling Secure Boot V2, but we can't enable it until this later point in the first boot
|
||||
// otherwise the Flash Encryption key cannot be read protected
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_RD_DIS);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_FLASH_SKIP_WRITE_PROTECTION_CACHE
|
||||
// Set write-protection for DIS_ICACHE to prevent bricking chip in case it will be set accidentally.
|
||||
// esp32c5 has DIS_ICACHE. Write-protection bit = 2.
|
||||
// List of eFuses with the same write protection bit:
|
||||
// SWAP_UART_SDIO_EN, DIS_ICACHE, DIS_USB_JTAG, DIS_DOWNLOAD_ICACHE,
|
||||
// DIS_USB_SERIAL_JTAG, DIS_FORCE_DOWNLOAD, DIS_TWAI, JTAG_SEL_ENABLE,
|
||||
// DIS_PAD_JTAG, DIS_DOWNLOAD_MANUAL_ENCRYPT.
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_WR_DIS_DIS_ICACHE);
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
@ -5,6 +5,7 @@ components/bootloader_support/test_apps/rtc_custom_section:
|
||||
- if: SOC_RTC_MEM_SUPPORTED == 1
|
||||
reason: this feature is supported on chips that have RTC memory
|
||||
disable:
|
||||
# TODO: [ESP32C5] IDF-8653
|
||||
- if: IDF_TARGET == "esp32c5"
|
||||
temporary: true
|
||||
reason: not supported yet
|
||||
|
56
components/efuse/esp32c5/esp_efuse_fields.c
Normal file
56
components/efuse/esp32c5/esp_efuse_fields.c
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_efuse_utility.h"
|
||||
#include "esp_efuse_table.h"
|
||||
#include "stdlib.h"
|
||||
#include "esp_types.h"
|
||||
#include "esp32c5/rom/efuse.h"
|
||||
#include "assert.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "sys/param.h"
|
||||
|
||||
static __attribute__((unused)) const char *TAG = "efuse";
|
||||
|
||||
// TODO: [ESP32C5] IDF-8674
|
||||
|
||||
// Contains functions that provide access to efuse fields which are often used in IDF.
|
||||
|
||||
// Returns chip package from efuse
|
||||
uint32_t esp_efuse_get_pkg_ver(void)
|
||||
{
|
||||
uint32_t pkg_ver = 0;
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_PKG_VERSION, &pkg_ver, ESP_EFUSE_PKG_VERSION[0]->bit_count);
|
||||
return pkg_ver;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t esp_efuse_set_rom_log_scheme(esp_efuse_rom_log_scheme_t log_scheme)
|
||||
{
|
||||
int cur_log_scheme = 0;
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_UART_PRINT_CONTROL, &cur_log_scheme, 2);
|
||||
if (!cur_log_scheme) { // not burned yet
|
||||
return esp_efuse_write_field_blob(ESP_EFUSE_UART_PRINT_CONTROL, &log_scheme, 2);
|
||||
} else {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_efuse_disable_rom_download_mode(void)
|
||||
{
|
||||
return esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MODE);
|
||||
}
|
||||
|
||||
esp_err_t esp_efuse_enable_rom_secure_download_mode(void)
|
||||
{
|
||||
if (esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MODE)) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
return esp_efuse_write_field_bit(ESP_EFUSE_ENABLE_SECURITY_DOWNLOAD);
|
||||
}
|
4
components/efuse/esp32c5/sources.cmake
Normal file
4
components/efuse/esp32c5/sources.cmake
Normal file
@ -0,0 +1,4 @@
|
||||
set(EFUSE_SOC_SRCS "esp_efuse_table.c"
|
||||
"esp_efuse_fields.c"
|
||||
"esp_efuse_rtc_calib.c"
|
||||
"esp_efuse_utility.c")
|
@ -153,6 +153,15 @@ if(NOT BOOTLOADER_BUILD)
|
||||
"sleep_gpio.c" # TODO: IDF-7528, IDF-7529
|
||||
)
|
||||
endif()
|
||||
if(CONFIG_IDF_TARGET_ESP32C5)
|
||||
list(REMOVE_ITEM srcs
|
||||
"sleep_cpu.c" # TODO: [ESP32C5] IDF-8638, IDF-8640
|
||||
"sleep_modes.c" # TODO: [ESP32C5] IDF-8638, IDF-8640
|
||||
"sleep_wake_stub.c" # TODO: [ESP32C5] IDF-8638, IDF-8640
|
||||
"sleep_gpio.c" # TODO: [ESP32C5] IDF-8638, IDF-8640
|
||||
"port/esp_clk_tree_common.c" # TODO: [ESP32C5] IDF-8638, IDF-8640
|
||||
)
|
||||
endif()
|
||||
else()
|
||||
# Requires "_esp_error_check_failed()" function
|
||||
list(APPEND priv_requires "esp_system")
|
||||
|
@ -247,7 +247,8 @@ menu "Hardware Settings"
|
||||
menu "Main XTAL Config"
|
||||
choice XTAL_FREQ_SEL
|
||||
prompt "Main XTAL frequency"
|
||||
default XTAL_FREQ_40 if SOC_XTAL_SUPPORT_40M
|
||||
default XTAL_FREQ_48 if SOC_XTAL_SUPPORT_48M
|
||||
default XTAL_FREQ_40 if (SOC_XTAL_SUPPORT_40M && !SOC_XTAL_SUPPORT_48M)
|
||||
help
|
||||
This option selects the operating frequency of the XTAL (crystal) clock used to drive the ESP target.
|
||||
The selected value MUST reflect the frequency of the given hardware.
|
||||
@ -270,6 +271,9 @@ menu "Hardware Settings"
|
||||
config XTAL_FREQ_40
|
||||
depends on SOC_XTAL_SUPPORT_40M
|
||||
bool "40 MHz"
|
||||
config XTAL_FREQ_48
|
||||
depends on SOC_XTAL_SUPPORT_48M
|
||||
bool "48 MHz"
|
||||
config XTAL_FREQ_AUTO
|
||||
depends on SOC_XTAL_SUPPORT_AUTO_DETECT
|
||||
bool "Autodetect"
|
||||
@ -283,6 +287,7 @@ menu "Hardware Settings"
|
||||
default 26 if XTAL_FREQ_26
|
||||
default 32 if XTAL_FREQ_32
|
||||
default 40 if XTAL_FREQ_40
|
||||
default 48 if XTAL_FREQ_48
|
||||
default 0 if XTAL_FREQ_AUTO
|
||||
endmenu
|
||||
|
||||
@ -332,7 +337,10 @@ menu "Hardware Settings"
|
||||
# Invisible bringup bypass options for esp_hw_support component
|
||||
config ESP_BRINGUP_BYPASS_CPU_CLK_SETTING
|
||||
bool
|
||||
default y if !SOC_CLK_TREE_SUPPORTED
|
||||
# TODO: [ESP32C5] IDF-8642 IDF_TARGET_ESP32C5 is added because clock
|
||||
# is required when bringup on C5 beta3, remove it when clock tree is
|
||||
# supported
|
||||
default y if !SOC_CLK_TREE_SUPPORTED && !IDF_TARGET_ESP32C5
|
||||
default n
|
||||
help
|
||||
This option is only used for new chip bringup, when
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
// TODO: IDF-5645
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5
|
||||
#include "soc/lp_aon_reg.h"
|
||||
#include "soc/pcr_reg.h"
|
||||
#define SYSTEM_CPU_PER_CONF_REG PCR_CPU_WAITI_CONF_REG
|
||||
@ -107,7 +107,7 @@ void esp_cpu_reset(int core_id)
|
||||
else
|
||||
REG_SET_BIT(LP_CLKRST_HPCPU_RESET_CTRL0_REG, LP_CLKRST_HPCORE1_SW_RESET);
|
||||
#else
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2// TODO: IDF-5645
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-5645
|
||||
SET_PERI_REG_MASK(LP_AON_CPUCORE0_CFG_REG, LP_AON_CPU_CORE0_SW_RESET);
|
||||
#else
|
||||
assert(core_id >= 0 && core_id < SOC_CPU_CORES_NUM);
|
||||
|
@ -46,6 +46,10 @@
|
||||
#include "esp32c6/rom/digital_signature.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C5
|
||||
#include "esp32c5/rom/digital_signature.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32H2
|
||||
#include "esp32h2/rom/digital_signature.h"
|
||||
#endif
|
||||
|
@ -27,8 +27,8 @@ typedef enum {
|
||||
CHIP_ESP32C2 = 12, //!< ESP32-C2
|
||||
CHIP_ESP32C6 = 13, //!< ESP32-C6
|
||||
CHIP_ESP32H2 = 16, //!< ESP32-H2
|
||||
CHIP_ESP32C5 = 17, //!< ESP32-C5 beta3
|
||||
CHIP_ESP32P4 = 18, //!< ESP32-P4
|
||||
CHIP_ESP32C5 = 19, //!< ESP32-C5
|
||||
CHIP_POSIX_LINUX = 999, //!< The code is running on POSIX/Linux simulator
|
||||
} esp_chip_model_t;
|
||||
|
||||
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Acquire lock for HMAC cryptography peripheral
|
||||
*
|
||||
* Internally also locks the SHA peripheral, as the HMAC depends on the SHA peripheral
|
||||
*/
|
||||
void esp_crypto_hmac_lock_acquire(void);
|
||||
|
||||
/**
|
||||
* @brief Release lock for HMAC cryptography peripheral
|
||||
*
|
||||
* Internally also releases the SHA peripheral, as the HMAC depends on the SHA peripheral
|
||||
*/
|
||||
void esp_crypto_hmac_lock_release(void);
|
||||
|
||||
/**
|
||||
* @brief Acquire lock for DS cryptography peripheral
|
||||
*
|
||||
* Internally also locks the HMAC (which locks SHA), AES and MPI peripheral, as the DS depends on these peripherals
|
||||
*/
|
||||
void esp_crypto_ds_lock_acquire(void);
|
||||
|
||||
/**
|
||||
* @brief Release lock for DS cryptography peripheral
|
||||
*
|
||||
* Internally also releases the HMAC (which locks SHA), AES and MPI peripheral, as the DS depends on these peripherals
|
||||
*/
|
||||
void esp_crypto_ds_lock_release(void);
|
||||
|
||||
/**
|
||||
* @brief Acquire lock for the SHA and AES cryptography peripheral.
|
||||
*
|
||||
*/
|
||||
void esp_crypto_sha_aes_lock_acquire(void);
|
||||
|
||||
/**
|
||||
* @brief Release lock for the SHA and AES cryptography peripheral.
|
||||
*
|
||||
*/
|
||||
void esp_crypto_sha_aes_lock_release(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Acquire lock for the mpi cryptography peripheral.
|
||||
*
|
||||
*/
|
||||
void esp_crypto_mpi_lock_acquire(void);
|
||||
|
||||
/**
|
||||
* @brief Release lock for the mpi/rsa cryptography peripheral.
|
||||
*
|
||||
*/
|
||||
void esp_crypto_mpi_lock_release(void);
|
||||
|
||||
/**
|
||||
* @brief Acquire lock for the ECC cryptography peripheral.
|
||||
*
|
||||
*/
|
||||
void esp_crypto_ecc_lock_acquire(void);
|
||||
|
||||
/**
|
||||
* @brief Release lock for the ECC cryptography peripheral.
|
||||
*
|
||||
*/
|
||||
void esp_crypto_ecc_lock_release(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
32
components/esp_hw_support/include/soc/esp32c5/rtc.h
Normal file
32
components/esp_hw_support/include/soc/esp32c5/rtc.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file esp32c5/rtc.h
|
||||
*
|
||||
* This file contains declarations of rtc related functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get current value of RTC counter in microseconds
|
||||
*
|
||||
* Note: this function may take up to 1 RTC_SLOW_CLK cycle to execute
|
||||
*
|
||||
* @return current value of RTC counter in microseconds
|
||||
*/
|
||||
uint64_t esp_rtc_get_time_us(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -245,8 +245,8 @@ void IRAM_ATTR modem_clock_module_mac_reset(periph_module_t module)
|
||||
case PERIPH_IEEE802154_MODULE:
|
||||
modem_syscon_ll_reset_zbmac(ctx->hal->syscon_dev);
|
||||
break;
|
||||
default:
|
||||
#endif
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
portEXIT_CRITICAL_SAFE(&ctx->lock);
|
||||
|
@ -0,0 +1,17 @@
|
||||
set(srcs "rtc_clk_init.c"
|
||||
"rtc_clk.c"
|
||||
"rtc_time.c"
|
||||
"pmu_init.c"
|
||||
"pmu_param.c"
|
||||
"chip_info.c"
|
||||
)
|
||||
|
||||
if(NOT BOOTLOADER_BUILD)
|
||||
list(APPEND srcs "sar_periph_ctrl.c"
|
||||
"esp_crypto_lock.c")
|
||||
endif()
|
||||
|
||||
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")
|
||||
|
||||
target_sources(${COMPONENT_LIB} PRIVATE "${srcs}")
|
||||
target_include_directories(${COMPONENT_LIB} PUBLIC . private_include)
|
41
components/esp_hw_support/port/esp32c5/Kconfig.hw_support
Normal file
41
components/esp_hw_support/port/esp32c5/Kconfig.hw_support
Normal file
@ -0,0 +1,41 @@
|
||||
choice ESP32C5_REV_MIN
|
||||
prompt "Minimum Supported ESP32-C5 Revision"
|
||||
default ESP32C5_REV_MIN_0
|
||||
help
|
||||
Required minimum chip revision. ESP-IDF will check for it and
|
||||
reject to boot if the chip revision fails the check.
|
||||
This ensures the chip used will have some modifications (features, or bugfixes).
|
||||
|
||||
The complied binary will only support chips above this revision,
|
||||
this will also help to reduce binary size.
|
||||
|
||||
config ESP32C5_REV_MIN_0
|
||||
bool "Rev v0.0"
|
||||
endchoice
|
||||
|
||||
config ESP32C5_REV_MIN_FULL
|
||||
int
|
||||
default 0 if ESP32C5_REV_MIN_0
|
||||
|
||||
config ESP_REV_MIN_FULL
|
||||
int
|
||||
default ESP32C5_REV_MIN_FULL
|
||||
|
||||
#
|
||||
# MAX Revision
|
||||
#
|
||||
|
||||
comment "Maximum Supported ESP32-C5 Revision (Rev v0.99)"
|
||||
# Maximum revision that IDF supports.
|
||||
# It can not be changed by user.
|
||||
# Only Espressif can change it when a new version will be supported in IDF.
|
||||
# Supports all chips starting from ESP32C5_REV_MIN_FULL to ESP32C5_REV_MAX_FULL
|
||||
|
||||
config ESP32C5_REV_MAX_FULL
|
||||
int
|
||||
default 99
|
||||
# keep in sync the "Maximum Supported Revision" description with this value
|
||||
|
||||
config ESP_REV_MAX_FULL
|
||||
int
|
||||
default ESP32C5_REV_MAX_FULL
|
46
components/esp_hw_support/port/esp32c5/Kconfig.mac
Normal file
46
components/esp_hw_support/port/esp32c5/Kconfig.mac
Normal file
@ -0,0 +1,46 @@
|
||||
choice ESP32C5_UNIVERSAL_MAC_ADDRESSES
|
||||
bool "Number of universally administered (by IEEE) MAC address"
|
||||
default ESP32C5_UNIVERSAL_MAC_ADDRESSES_FOUR
|
||||
help
|
||||
Configure the number of universally administered (by IEEE) MAC addresses.
|
||||
|
||||
During initialization, MAC addresses for each network interface are generated or derived from a
|
||||
single base MAC address.
|
||||
|
||||
If the number of universal MAC addresses is four, all four interfaces (WiFi station, WiFi softap,
|
||||
Bluetooth and Ethernet) receive a universally administered MAC address. These are generated
|
||||
sequentially by adding 0, 1, 2 and 3 (respectively) to the final octet of the base MAC address.
|
||||
|
||||
If the number of universal MAC addresses is two, only two interfaces (WiFi station and Bluetooth)
|
||||
receive a universally administered MAC address. These are generated sequentially by adding 0
|
||||
and 1 (respectively) to the base MAC address. The remaining two interfaces (WiFi softap and Ethernet)
|
||||
receive local MAC addresses. These are derived from the universal WiFi station and Bluetooth MAC
|
||||
addresses, respectively.
|
||||
|
||||
When using the default (Espressif-assigned) base MAC address, either setting can be used. When using
|
||||
a custom universal MAC address range, the correct setting will depend on the allocation of MAC
|
||||
addresses in this range (either 2 or 4 per device.)
|
||||
|
||||
Note that ESP32-C5 has no integrated Ethernet MAC. Although it's possible to use the esp_read_mac()
|
||||
API to return a MAC for Ethernet, this can only be used with an external MAC peripheral.
|
||||
|
||||
config ESP32C5_UNIVERSAL_MAC_ADDRESSES_TWO
|
||||
bool "Two"
|
||||
select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_TWO
|
||||
select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
|
||||
select ESP_MAC_ADDR_UNIVERSE_BT
|
||||
|
||||
config ESP32C5_UNIVERSAL_MAC_ADDRESSES_FOUR
|
||||
bool "Four"
|
||||
select ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR
|
||||
select ESP_MAC_ADDR_UNIVERSE_IEEE802154
|
||||
select ESP_MAC_ADDR_UNIVERSE_WIFI_STA
|
||||
select ESP_MAC_ADDR_UNIVERSE_WIFI_AP
|
||||
select ESP_MAC_ADDR_UNIVERSE_BT
|
||||
select ESP_MAC_ADDR_UNIVERSE_ETH
|
||||
endchoice
|
||||
|
||||
config ESP32C5_UNIVERSAL_MAC_ADDRESSES
|
||||
int
|
||||
default 2 if ESP32C5_UNIVERSAL_MAC_ADDRESSES_TWO
|
||||
default 4 if ESP32C5_UNIVERSAL_MAC_ADDRESSES_FOUR
|
37
components/esp_hw_support/port/esp32c5/Kconfig.rtc
Normal file
37
components/esp_hw_support/port/esp32c5/Kconfig.rtc
Normal file
@ -0,0 +1,37 @@
|
||||
choice RTC_CLK_SRC
|
||||
prompt "RTC clock source"
|
||||
default RTC_CLK_SRC_INT_RC32K
|
||||
help
|
||||
Choose which clock is used as RTC clock source.
|
||||
|
||||
config RTC_CLK_SRC_EXT_CRYS
|
||||
bool "External 32kHz crystal"
|
||||
select ESP_SYSTEM_RTC_EXT_XTAL
|
||||
config RTC_CLK_SRC_EXT_OSC
|
||||
bool "External 32kHz oscillator at 32K_XP pin"
|
||||
select ESP_SYSTEM_RTC_EXT_OSC
|
||||
config RTC_CLK_SRC_INT_RC32K
|
||||
bool "Internal 32kHz RC oscillator"
|
||||
endchoice
|
||||
|
||||
config RTC_CLK_CAL_CYCLES
|
||||
int "Number of cycles for RTC_SLOW_CLK calibration"
|
||||
default 3000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_RC32K
|
||||
default 1024 if RTC_CLK_SRC_INT_RC
|
||||
range 0 27000 if RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC || RTC_CLK_SRC_INT_RC32K
|
||||
range 0 32766 if RTC_CLK_SRC_INT_RC
|
||||
help
|
||||
When the startup code initializes RTC_SLOW_CLK, it can perform
|
||||
calibration by comparing the RTC_SLOW_CLK frequency with main XTAL
|
||||
frequency. This option sets the number of RTC_SLOW_CLK cycles measured
|
||||
by the calibration routine. Higher numbers increase calibration
|
||||
precision, which may be important for applications which spend a lot of
|
||||
time in deep sleep. Lower numbers reduce startup time.
|
||||
|
||||
When this option is set to 0, clock calibration will not be performed at
|
||||
startup, and approximate clock frequencies will be assumed:
|
||||
|
||||
- 136000 Hz if internal RC oscillator is used as clock source. For this use value 1024.
|
||||
- 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more.
|
||||
In case more value will help improve the definition of the launch of the crystal.
|
||||
If the crystal could not start, it will be switched to internal RC.
|
18
components/esp_hw_support/port/esp32c5/chip_info.c
Normal file
18
components/esp_hw_support/port/esp32c5/chip_info.c
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_chip_info.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
|
||||
void esp_chip_info(esp_chip_info_t *out_info)
|
||||
{
|
||||
memset(out_info, 0, sizeof(*out_info));
|
||||
out_info->model = CHIP_ESP32C5;
|
||||
out_info->revision = efuse_hal_chip_revision();
|
||||
out_info->cores = 1;
|
||||
out_info->features = CHIP_FEATURE_WIFI_BGN | CHIP_FEATURE_BLE;
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
#include "esp_cpu.h"
|
||||
#include "esp_fault.h"
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
// Without L bit set
|
||||
#define CONDITIONAL_NONE 0x0
|
||||
#define CONDITIONAL_RX PMP_R | PMP_X
|
||||
#define CONDITIONAL_RW PMP_R | PMP_W
|
||||
#define CONDITIONAL_RWX PMP_R | PMP_W | PMP_X
|
||||
#else
|
||||
// With L bit set
|
||||
#define CONDITIONAL_NONE NONE
|
||||
#define CONDITIONAL_RX RX
|
||||
#define CONDITIONAL_RW RW
|
||||
#define CONDITIONAL_RWX RWX
|
||||
#endif
|
||||
|
||||
void esp_cpu_configure_region_protection(void)
|
||||
{
|
||||
// TODO: [ESP32C5] IDF-8833
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_clk_tree.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_check.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "hal/clk_tree_hal.h"
|
||||
#include "hal/clk_tree_ll.h"
|
||||
#include "esp_private/esp_clk_tree_common.h"
|
||||
|
||||
static const char *TAG = "esp_clk_tree";
|
||||
|
||||
esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision,
|
||||
uint32_t *freq_value)
|
||||
{
|
||||
// TODO: [ESP32C5] IDF-8642
|
||||
ESP_LOGW(TAG, "esp_clk_tree_src_get_freq_hz() has not implemented yet");
|
||||
*freq_value = 0;
|
||||
return ESP_OK;
|
||||
}
|
89
components/esp_hw_support/port/esp32c5/esp_crypto_lock.c
Normal file
89
components/esp_hw_support/port/esp32c5/esp_crypto_lock.c
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <sys/lock.h>
|
||||
|
||||
#include "esp_crypto_lock.h"
|
||||
|
||||
/* Lock overview:
|
||||
SHA: peripheral independent, but DMA is shared with AES
|
||||
AES: peripheral independent, but DMA is shared with SHA
|
||||
MPI/RSA: independent
|
||||
ECC: independent
|
||||
HMAC: needs SHA
|
||||
DS: needs HMAC (which needs SHA), AES and MPI
|
||||
*/
|
||||
|
||||
/* Lock for DS peripheral */
|
||||
static _lock_t s_crypto_ds_lock;
|
||||
|
||||
/* Lock for HMAC peripheral */
|
||||
static _lock_t s_crypto_hmac_lock;
|
||||
|
||||
/* Lock for the MPI/RSA peripheral, also used by the DS peripheral */
|
||||
static _lock_t s_crypto_mpi_lock;
|
||||
|
||||
/* Single lock for SHA and AES, sharing a reserved GDMA channel */
|
||||
static _lock_t s_crypto_sha_aes_lock;
|
||||
|
||||
/* Lock for ECC peripheral */
|
||||
static _lock_t s_crypto_ecc_lock;
|
||||
|
||||
void esp_crypto_hmac_lock_acquire(void)
|
||||
{
|
||||
_lock_acquire(&s_crypto_hmac_lock);
|
||||
esp_crypto_sha_aes_lock_acquire();
|
||||
}
|
||||
|
||||
void esp_crypto_hmac_lock_release(void)
|
||||
{
|
||||
esp_crypto_sha_aes_lock_release();
|
||||
_lock_release(&s_crypto_hmac_lock);
|
||||
}
|
||||
|
||||
void esp_crypto_ds_lock_acquire(void)
|
||||
{
|
||||
_lock_acquire(&s_crypto_ds_lock);
|
||||
esp_crypto_hmac_lock_acquire();
|
||||
esp_crypto_mpi_lock_acquire();
|
||||
}
|
||||
|
||||
void esp_crypto_ds_lock_release(void)
|
||||
{
|
||||
esp_crypto_mpi_lock_release();
|
||||
esp_crypto_hmac_lock_release();
|
||||
_lock_release(&s_crypto_ds_lock);
|
||||
}
|
||||
|
||||
void esp_crypto_sha_aes_lock_acquire(void)
|
||||
{
|
||||
_lock_acquire(&s_crypto_sha_aes_lock);
|
||||
}
|
||||
|
||||
void esp_crypto_sha_aes_lock_release(void)
|
||||
{
|
||||
_lock_release(&s_crypto_sha_aes_lock);
|
||||
}
|
||||
|
||||
void esp_crypto_mpi_lock_acquire(void)
|
||||
{
|
||||
_lock_acquire(&s_crypto_mpi_lock);
|
||||
}
|
||||
|
||||
void esp_crypto_mpi_lock_release(void)
|
||||
{
|
||||
_lock_release(&s_crypto_mpi_lock);
|
||||
}
|
||||
|
||||
void esp_crypto_ecc_lock_acquire(void)
|
||||
{
|
||||
_lock_acquire(&s_crypto_ecc_lock);
|
||||
}
|
||||
|
||||
void esp_crypto_ecc_lock_release(void)
|
||||
{
|
||||
_lock_release(&s_crypto_ecc_lock);
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_private/io_mux.h"
|
||||
#include "hal/gpio_ll.h"
|
||||
|
||||
static portMUX_TYPE s_io_mux_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
static soc_module_clk_t s_io_mux_clk_src = 0; // by default, the clock source is not set explicitly by any consumer (e.g. SDM, Filter)
|
||||
|
||||
esp_err_t io_mux_set_clock_source(soc_module_clk_t clk_src)
|
||||
{
|
||||
bool clk_conflict = false;
|
||||
// check is the IO MUX has been set to another clock source
|
||||
portENTER_CRITICAL(&s_io_mux_spinlock);
|
||||
if (s_io_mux_clk_src != 0 && s_io_mux_clk_src != clk_src) {
|
||||
clk_conflict = true;
|
||||
} else {
|
||||
s_io_mux_clk_src = clk_src;
|
||||
}
|
||||
portEXIT_CRITICAL(&s_io_mux_spinlock);
|
||||
|
||||
if (clk_conflict) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
gpio_ll_iomux_set_clk_src(clk_src);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
207
components/esp_hw_support/port/esp32c5/pmu_init.c
Normal file
207
components/esp_hw_support/port/esp32c5/pmu_init.c
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <esp_types.h>
|
||||
#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_HP_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());
|
||||
}
|
447
components/esp_hw_support/port/esp32c5/pmu_param.c
Normal file
447
components/esp_hw_support/port/esp32c5/pmu_param.c
Normal file
@ -0,0 +1,447 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <esp_types.h>
|
||||
#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 = 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 \
|
||||
}, \
|
||||
.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 \
|
||||
}, \
|
||||
.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_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 */
|
||||
|
||||
#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 = 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 = 0, \
|
||||
.dbias = LP_CALI_DBIAS \
|
||||
}, \
|
||||
.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];
|
||||
}
|
@ -0,0 +1,481 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <esp_types.h>
|
||||
#include "soc/soc_caps.h"
|
||||
#if SOC_PMU_SUPPORTED
|
||||
#include "soc/pmu_struct.h"
|
||||
#include "hal/pmu_hal.h"
|
||||
#endif
|
||||
|
||||
// TODO: [ESP32C5] IDF-8643
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define HP_CALI_DBIAS 25
|
||||
#define LP_CALI_DBIAS 26
|
||||
|
||||
#if SOC_PMU_SUPPORTED
|
||||
|
||||
// FOR XTAL FORCE PU IN SLEEP
|
||||
#define PMU_PD_CUR_SLEEP_ON 0
|
||||
#define PMU_BIASSLP_SLEEP_ON 0
|
||||
|
||||
// FOR BOTH LIGHTSLEEP & DEEPSLEEP
|
||||
#define PMU_PD_CUR_SLEEP_DEFAULT 1
|
||||
#define PMU_BIASSLP_SLEEP_DEFAULT 1
|
||||
#define PMU_LP_XPD_SLEEP_DEFAULT 1
|
||||
#define PMU_LP_SLP_XPD_SLEEP_DEFAULT 0
|
||||
#define PMU_LP_SLP_DBIAS_SLEEP_DEFAULT 0
|
||||
|
||||
// FOR LIGHTSLEEP
|
||||
#define PMU_HP_DRVB_LIGHTSLEEP 0
|
||||
#define PMU_LP_DRVB_LIGHTSLEEP 0
|
||||
#define PMU_HP_XPD_LIGHTSLEEP 1
|
||||
|
||||
#define PMU_DBG_ATTEN_LIGHTSLEEP_DEFAULT 0
|
||||
#define PMU_HP_DBIAS_LIGHTSLEEP_0V6 1
|
||||
#define PMU_LP_DBIAS_LIGHTSLEEP_0V7 12
|
||||
|
||||
// FOR DEEPSLEEP
|
||||
#define PMU_DBG_HP_DEEPSLEEP 0
|
||||
#define PMU_HP_XPD_DEEPSLEEP 0
|
||||
#define PMU_LP_DRVB_DEEPSLEEP 0
|
||||
|
||||
#define PMU_DBG_ATTEN_DEEPSLEEP_DEFAULT 12
|
||||
#define PMU_LP_DBIAS_DEEPSLEEP_0V7 23
|
||||
|
||||
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);
|
||||
|
||||
|
||||
|
||||
/* Following software configuration instance type from pmu_struct.h used for the PMU state machine in sleep flow*/
|
||||
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;
|
||||
|
||||
#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 */
|
||||
|
||||
#define PMU_LP_ANALOG_WAIT_TARGET_TIME_DSLP_US (500) /* Slow OSC as PMU slow clock source in deepsleep is about 500 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_HP_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 = ((pd_flags) & PMU_SLEEP_PD_XTAL32K) ? 0 : 1, \
|
||||
.xpd_rc32k = ((pd_flags) & PMU_SLEEP_PD_RC32K) ? 0 : 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 {
|
||||
pmu_hp_sys_cntl_reg_t syscntl;
|
||||
} pmu_sleep_digital_config_t;
|
||||
|
||||
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(pd_flags) { \
|
||||
.syscntl = { \
|
||||
.dig_pad_slp_sel = ((pd_flags) & PMU_SLEEP_PD_TOP) ? 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 = { \
|
||||
.drv_b = PMU_HP_DRVB_LIGHTSLEEP, \
|
||||
.pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \
|
||||
.bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \
|
||||
.xpd = PMU_HP_XPD_LIGHTSLEEP, \
|
||||
.dbg_atten = PMU_DBG_ATTEN_LIGHTSLEEP_DEFAULT, \
|
||||
.dbias = PMU_HP_DBIAS_LIGHTSLEEP_0V6 \
|
||||
} \
|
||||
}, \
|
||||
.lp_sys[PMU_MODE_LP_SLEEP] = { \
|
||||
.analog = { \
|
||||
.drv_b = PMU_LP_DRVB_DEEPSLEEP, \
|
||||
.pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \
|
||||
.bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \
|
||||
.slp_xpd = PMU_LP_SLP_XPD_SLEEP_DEFAULT, \
|
||||
.slp_dbias = PMU_LP_SLP_DBIAS_SLEEP_DEFAULT, \
|
||||
.xpd = PMU_LP_XPD_SLEEP_DEFAULT, \
|
||||
.dbg_atten = PMU_DBG_ATTEN_LIGHTSLEEP_DEFAULT, \
|
||||
.dbias = PMU_LP_DBIAS_LIGHTSLEEP_0V7 \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PMU_SLEEP_ANALOG_DSLP_CONFIG_DEFAULT(pd_flags) { \
|
||||
.hp_sys = { \
|
||||
.analog = { \
|
||||
.pd_cur = PMU_PD_CUR_SLEEP_ON, \
|
||||
.bias_sleep = PMU_BIASSLP_SLEEP_ON, \
|
||||
.xpd = PMU_HP_XPD_DEEPSLEEP, \
|
||||
.dbg_atten = PMU_DBG_HP_DEEPSLEEP \
|
||||
} \
|
||||
}, \
|
||||
.lp_sys[PMU_MODE_LP_SLEEP] = { \
|
||||
.analog = { \
|
||||
.drv_b = PMU_LP_DRVB_DEEPSLEEP, \
|
||||
.pd_cur = PMU_PD_CUR_SLEEP_DEFAULT, \
|
||||
.bias_sleep = PMU_BIASSLP_SLEEP_DEFAULT, \
|
||||
.slp_xpd = PMU_LP_SLP_XPD_SLEEP_DEFAULT, \
|
||||
.slp_dbias = PMU_LP_SLP_DBIAS_SLEEP_DEFAULT, \
|
||||
.xpd = PMU_LP_XPD_SLEEP_DEFAULT, \
|
||||
.dbg_atten = PMU_DBG_ATTEN_DEEPSLEEP_DEFAULT, \
|
||||
.dbias = PMU_LP_DBIAS_DEEPSLEEP_0V7 \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
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_digital_config_t digital;
|
||||
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_us; /* 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_us; /* LP LDO power up wait time (unit: microsecond) */
|
||||
uint16_t xtal_wait_stable_time_us; /* 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_us; /* (unit: microsecond) */
|
||||
uint16_t power_up_wait_time_us; /* (unit: microsecond) */
|
||||
} lp;
|
||||
struct {
|
||||
uint16_t min_slp_time_us; /* Mininum sleep protection time (unit: microsecond) */
|
||||
uint16_t clock_domain_sync_time_us; /* 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_us; /* System DFS up scaling work time (unit: microsecond) */
|
||||
uint16_t analog_wait_time_us; /* HP LDO power up wait time (unit: microsecond) */
|
||||
uint16_t power_supply_wait_time_us; /* (unit: microsecond) */
|
||||
uint16_t power_up_wait_time_us; /* (unit: microsecond) */
|
||||
uint16_t regdma_s2m_work_time_us; /* Modem Subsystem (S2M switch) REGDMA restore time (unit: microsecond) */
|
||||
uint16_t regdma_s2a_work_time_us; /* SOC System (Digital Peripheral + Modem Subsystem) REGDMA (S2A switch) restore time (unit: microsecond) */
|
||||
uint16_t regdma_m2a_work_time_us; /* Digital Peripheral (M2A switch) REGDMA restore time (unit: microsecond) */
|
||||
uint16_t regdma_a2s_work_time_us; /* SOC System (Digital Peripheral + Modem Subsystem) REGDMA (A2S switch) backup time (unit: microsecond) */
|
||||
uint16_t regdma_rf_on_work_time_us; /* The REGDMA work time of RF enable (unit: microsecond) */
|
||||
uint16_t regdma_rf_off_work_time_us; /* The REGDMA work time of RF disable (unit: microsecond) */
|
||||
uint16_t xtal_wait_stable_time_us; /* Main XTAL stabilization wait time (unit: microsecond) */
|
||||
uint16_t pll_wait_stable_time_us; /* PLL stabilization wait time (unit: microsecond) */
|
||||
} hp;
|
||||
} pmu_sleep_machine_constant_t;
|
||||
|
||||
#define PMU_SLEEP_MC_DEFAULT() { \
|
||||
.lp = { \
|
||||
.min_slp_time_us = 450, \
|
||||
.wakeup_wait_cycle = 4, \
|
||||
.analog_wait_time_us = 154, \
|
||||
.xtal_wait_stable_time_us = 250, \
|
||||
.clk_switch_cycle = 1, \
|
||||
.clk_power_on_wait_cycle = 1, \
|
||||
.power_supply_wait_time_us = 2, \
|
||||
.power_up_wait_time_us = 2 \
|
||||
}, \
|
||||
.hp = { \
|
||||
.min_slp_time_us = 450, \
|
||||
.clock_domain_sync_time_us = 150, \
|
||||
.system_dfs_up_work_time_us = 124, \
|
||||
.analog_wait_time_us = 154, \
|
||||
.power_supply_wait_time_us = 2, \
|
||||
.power_up_wait_time_us = 2, \
|
||||
.regdma_s2m_work_time_us = 172, \
|
||||
.regdma_s2a_work_time_us = 480, \
|
||||
.regdma_m2a_work_time_us = 278, \
|
||||
.regdma_a2s_work_time_us = 382, \
|
||||
.regdma_rf_on_work_time_us = 70, \
|
||||
.regdma_rf_off_work_time_us = 23, \
|
||||
.xtal_wait_stable_time_us = 250, \
|
||||
.pll_wait_stable_time_us = 1 \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif // SOC_PMU_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
441
components/esp_hw_support/port/esp32c5/rtc_clk.c
Normal file
441
components/esp_hw_support/port/esp32c5/rtc_clk.c
Normal file
@ -0,0 +1,441 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp32c5/rom/rtc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "esp_private/rtc_clk.h"
|
||||
#include "esp_hw_log.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "hal/clk_tree_ll.h"
|
||||
#include "hal/regi2c_ctrl_ll.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/lp_aon_reg.h"
|
||||
#include "esp_private/sleep_event.h"
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
#include "hal/modem_lpcon_ll.h"
|
||||
#else
|
||||
#include "esp_private/esp_modem_clock.h"
|
||||
#endif
|
||||
|
||||
static const char *TAG = "rtc_clk";
|
||||
|
||||
// Current PLL frequency, in 480MHz. Zero if PLL is not enabled.
|
||||
static int s_cur_pll_freq;
|
||||
|
||||
static uint32_t s_bbpll_digi_consumers_ref_count = 0; // Currently, it only tracks whether the 48MHz PHY clock is in-use by USB Serial/JTAG
|
||||
|
||||
void rtc_clk_bbpll_add_consumer(void)
|
||||
{
|
||||
s_bbpll_digi_consumers_ref_count += 1;
|
||||
}
|
||||
|
||||
void rtc_clk_bbpll_remove_consumer(void)
|
||||
{
|
||||
s_bbpll_digi_consumers_ref_count -= 1;
|
||||
}
|
||||
|
||||
void rtc_clk_32k_enable(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
clk_ll_xtal32k_enable(CLK_LL_XTAL32K_ENABLE_MODE_CRYSTAL);
|
||||
} else {
|
||||
clk_ll_xtal32k_disable();
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_clk_32k_enable_external(void)
|
||||
{
|
||||
// EXT_OSC_SLOW_GPIO_NUM == GPIO_NUM_0
|
||||
PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG);
|
||||
REG_SET_BIT(LP_AON_GPIO_HOLD0_REG, BIT(EXT_OSC_SLOW_GPIO_NUM));
|
||||
clk_ll_xtal32k_enable(CLK_LL_XTAL32K_ENABLE_MODE_EXTERNAL);
|
||||
}
|
||||
|
||||
void rtc_clk_32k_bootstrap(uint32_t cycle)
|
||||
{
|
||||
/* No special bootstrapping needed for ESP32-C5, 'cycle' argument is to keep the signature
|
||||
* same as for the ESP32. Just enable the XTAL here.
|
||||
*/
|
||||
(void)cycle;
|
||||
rtc_clk_32k_enable(true);
|
||||
}
|
||||
|
||||
bool rtc_clk_32k_enabled(void)
|
||||
{
|
||||
return clk_ll_xtal32k_is_enabled();
|
||||
}
|
||||
|
||||
void rtc_clk_rc32k_enable(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
clk_ll_rc32k_enable();
|
||||
esp_rom_delay_us(SOC_DELAY_RC32K_ENABLE);
|
||||
} else {
|
||||
clk_ll_rc32k_disable();
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_clk_8m_enable(bool clk_8m_en)
|
||||
{
|
||||
if (clk_8m_en) {
|
||||
clk_ll_rc_fast_enable();
|
||||
esp_rom_delay_us(SOC_DELAY_RC_FAST_ENABLE);
|
||||
} else {
|
||||
clk_ll_rc_fast_disable();
|
||||
}
|
||||
}
|
||||
|
||||
bool rtc_clk_8m_enabled(void)
|
||||
{
|
||||
return clk_ll_rc_fast_is_enabled();
|
||||
}
|
||||
|
||||
void rtc_clk_slow_src_set(soc_rtc_slow_clk_src_t clk_src)
|
||||
{
|
||||
clk_ll_rtc_slow_set_src(clk_src);
|
||||
esp_rom_delay_us(SOC_DELAY_RTC_SLOW_CLK_SWITCH);
|
||||
}
|
||||
|
||||
soc_rtc_slow_clk_src_t rtc_clk_slow_src_get(void)
|
||||
{
|
||||
return clk_ll_rtc_slow_get_src();
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_slow_freq_get_hz(void)
|
||||
{
|
||||
switch (rtc_clk_slow_src_get()) {
|
||||
// case SOC_RTC_SLOW_CLK_SRC_RC_SLOW: return SOC_CLK_RC_SLOW_FREQ_APPROX;
|
||||
case SOC_RTC_SLOW_CLK_SRC_XTAL32K: return SOC_CLK_XTAL32K_FREQ_APPROX;
|
||||
case SOC_RTC_SLOW_CLK_SRC_RC32K: return SOC_CLK_RC32K_FREQ_APPROX;
|
||||
case SOC_RTC_SLOW_CLK_SRC_OSC_SLOW: return SOC_CLK_OSC_SLOW_FREQ_APPROX;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_clk_fast_src_set(soc_rtc_fast_clk_src_t clk_src)
|
||||
{
|
||||
clk_ll_rtc_fast_set_src(clk_src);
|
||||
esp_rom_delay_us(SOC_DELAY_RTC_FAST_CLK_SWITCH);
|
||||
}
|
||||
|
||||
soc_rtc_fast_clk_src_t rtc_clk_fast_src_get(void)
|
||||
{
|
||||
return clk_ll_rtc_fast_get_src();
|
||||
}
|
||||
|
||||
static void rtc_clk_bbpll_disable(void)
|
||||
{
|
||||
clk_ll_bbpll_disable();
|
||||
s_cur_pll_freq = 0;
|
||||
}
|
||||
|
||||
static void rtc_clk_bbpll_enable(void)
|
||||
{
|
||||
clk_ll_bbpll_enable();
|
||||
}
|
||||
|
||||
static void rtc_clk_enable_i2c_ana_master_clock(bool enable)
|
||||
{
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
modem_lpcon_ll_enable_i2c_master_clock(&MODEM_LPCON, enable);
|
||||
#else
|
||||
if (enable) {
|
||||
modem_clock_module_enable(PERIPH_ANA_I2C_MASTER_MODULE);
|
||||
} else {
|
||||
modem_clock_module_disable(PERIPH_ANA_I2C_MASTER_MODULE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq)
|
||||
{
|
||||
assert((pll_freq == CLK_LL_PLL_160M_FREQ_MHZ) || \
|
||||
(pll_freq == CLK_LL_PLL_240M_FREQ_MHZ));
|
||||
/* Digital part */
|
||||
clk_ll_bbpll_set_freq_mhz(CLK_LL_PLL_480M_FREQ_MHZ);
|
||||
/* Analog part */
|
||||
rtc_clk_enable_i2c_ana_master_clock(true);
|
||||
/* BBPLL CALIBRATION START */
|
||||
regi2c_ctrl_ll_bbpll_calibration_start();
|
||||
clk_ll_bbpll_set_config(CLK_LL_PLL_480M_FREQ_MHZ, xtal_freq);
|
||||
/* WAIT CALIBRATION DONE */
|
||||
while(!regi2c_ctrl_ll_bbpll_calibration_is_done());
|
||||
/* BBPLL CALIBRATION STOP */
|
||||
regi2c_ctrl_ll_bbpll_calibration_stop();
|
||||
rtc_clk_enable_i2c_ana_master_clock(false);
|
||||
s_cur_pll_freq = CLK_LL_PLL_480M_FREQ_MHZ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to use XTAL as the CPU clock source.
|
||||
* Must satisfy: cpu_freq = XTAL_FREQ / div.
|
||||
* Does not disable the PLL.
|
||||
*/
|
||||
static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div)
|
||||
{
|
||||
/* Configure clk mspi fast to XTAL*/
|
||||
clk_ll_mspi_fast_sel_clk(SOC_MOD_CLK_XTAL);
|
||||
clk_ll_mspi_fast_set_divider(1);
|
||||
|
||||
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL);
|
||||
clk_ll_ahb_set_divider(div);
|
||||
clk_ll_cpu_set_divider(div);
|
||||
esp_rom_set_cpu_ticks_per_us(cpu_freq);
|
||||
}
|
||||
|
||||
static void rtc_clk_cpu_freq_to_8m(void)
|
||||
{
|
||||
/* Configure clk mspi fast to XTAL*/
|
||||
clk_ll_mspi_fast_sel_clk(SOC_MOD_CLK_XTAL);
|
||||
clk_ll_mspi_fast_set_divider(1);
|
||||
|
||||
clk_ll_ahb_set_divider(1);
|
||||
clk_ll_cpu_set_divider(1);
|
||||
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST);
|
||||
esp_rom_set_cpu_ticks_per_us(20);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to one of PLL-based frequencies. Current frequency can be XTAL or PLL.
|
||||
* PLL must already be enabled.
|
||||
* @param cpu_freq new CPU frequency
|
||||
*/
|
||||
static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)
|
||||
{
|
||||
rtc_cpu_freq_config_t cfg;
|
||||
rtc_clk_cpu_freq_mhz_to_config(cpu_freq_mhz, &cfg);
|
||||
// Set AHB always be 40MHz
|
||||
clk_ll_ahb_set_divider(cfg.source_freq_mhz / 40);
|
||||
clk_ll_cpu_set_divider(cfg.div);
|
||||
clk_ll_cpu_set_src(cfg.source);
|
||||
esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz);
|
||||
|
||||
/* Configure clk mspi fast to 80m*/
|
||||
clk_ll_mspi_fast_set_divider(6);
|
||||
clk_ll_mspi_fast_sel_clk(MSPI_CLK_SRC_SPLL);
|
||||
}
|
||||
|
||||
bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *out_config)
|
||||
{
|
||||
uint32_t source_freq_mhz;
|
||||
soc_cpu_clk_src_t source;
|
||||
uint32_t divider; // divider = freq of SOC_ROOT_CLK / freq of CPU_CLK
|
||||
uint32_t real_freq_mhz;
|
||||
|
||||
uint32_t xtal_freq = (uint32_t)rtc_clk_xtal_freq_get();
|
||||
if (freq_mhz == 48 || freq_mhz == 24 || freq_mhz == 16 || freq_mhz == 12 || freq_mhz == 8) {
|
||||
divider = xtal_freq / freq_mhz;
|
||||
source_freq_mhz = xtal_freq;
|
||||
source = SOC_CPU_CLK_SRC_XTAL;
|
||||
real_freq_mhz = freq_mhz;
|
||||
} else if (freq_mhz == 240 || freq_mhz == 120) {
|
||||
real_freq_mhz = freq_mhz;
|
||||
source = SOC_CPU_CLK_SRC_PLL_F240;
|
||||
source_freq_mhz = CLK_LL_PLL_240M_FREQ_MHZ;
|
||||
divider = CLK_LL_PLL_240M_FREQ_MHZ / freq_mhz;
|
||||
}else if (freq_mhz == 160 || freq_mhz == 80 || freq_mhz == 40) {
|
||||
real_freq_mhz = freq_mhz;
|
||||
source = SOC_CPU_CLK_SRC_PLL_F160;
|
||||
source_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ;
|
||||
divider = CLK_LL_PLL_160M_FREQ_MHZ / freq_mhz;
|
||||
} else {
|
||||
// unsupported frequency
|
||||
return false;
|
||||
}
|
||||
*out_config = (rtc_cpu_freq_config_t) {
|
||||
.source = source,
|
||||
.div = divider,
|
||||
.source_freq_mhz = source_freq_mhz,
|
||||
.freq_mhz = real_freq_mhz
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void rtc_clk_set_cpu_switch_to_bbpll(int event_id)
|
||||
{
|
||||
}
|
||||
|
||||
void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
|
||||
{
|
||||
soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src();
|
||||
if (config->source == SOC_CPU_CLK_SRC_XTAL) {
|
||||
/* Configure clk mspi fast to 80m*/
|
||||
rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
|
||||
if (((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F160) || (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F240)) && !s_bbpll_digi_consumers_ref_count) {
|
||||
// We don't turn off the bbpll if some consumers depend on bbpll
|
||||
rtc_clk_bbpll_disable();
|
||||
}
|
||||
} else if ((config->source == SOC_CPU_CLK_SRC_PLL_F160) || (config->source == SOC_CPU_CLK_SRC_PLL_F240)) {
|
||||
if ((old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F160) && (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F240)) {
|
||||
rtc_clk_set_cpu_switch_to_bbpll(SLEEP_EVENT_HW_BBPLL_EN_START);
|
||||
rtc_clk_bbpll_enable();
|
||||
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz);
|
||||
}
|
||||
rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
|
||||
rtc_clk_set_cpu_switch_to_bbpll(SLEEP_EVENT_HW_BBPLL_EN_STOP);
|
||||
} else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) {
|
||||
rtc_clk_cpu_freq_to_8m();
|
||||
if (((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F160) || (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F240)) && !s_bbpll_digi_consumers_ref_count) {
|
||||
// We don't turn off the bbpll if some consumers depend on bbpll
|
||||
rtc_clk_bbpll_disable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config)
|
||||
{
|
||||
soc_cpu_clk_src_t source = clk_ll_cpu_get_src();
|
||||
uint32_t source_freq_mhz;
|
||||
uint32_t div; // div = freq of SOC_ROOT_CLK / freq of CPU_CLK
|
||||
uint32_t freq_mhz;
|
||||
switch (source) {
|
||||
case SOC_CPU_CLK_SRC_XTAL: {
|
||||
div = clk_ll_cpu_get_divider();
|
||||
source_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get();
|
||||
freq_mhz = source_freq_mhz / div;
|
||||
break;
|
||||
}
|
||||
case SOC_CPU_CLK_SRC_PLL_F160: {
|
||||
div = clk_ll_cpu_get_divider();
|
||||
source_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ;
|
||||
freq_mhz = source_freq_mhz / div;
|
||||
break;
|
||||
}
|
||||
case SOC_CPU_CLK_SRC_PLL_F240: {
|
||||
div = clk_ll_cpu_get_divider();
|
||||
source_freq_mhz = CLK_LL_PLL_240M_FREQ_MHZ;
|
||||
freq_mhz = source_freq_mhz / div;
|
||||
break;
|
||||
}
|
||||
case SOC_CPU_CLK_SRC_RC_FAST:
|
||||
div = clk_ll_cpu_get_divider();
|
||||
source_freq_mhz = 20;
|
||||
freq_mhz = source_freq_mhz / div;
|
||||
break;
|
||||
default:
|
||||
ESP_HW_LOGE(TAG, "unsupported frequency configuration");
|
||||
abort();
|
||||
}
|
||||
*out_config = (rtc_cpu_freq_config_t) {
|
||||
.source = source,
|
||||
.source_freq_mhz = source_freq_mhz,
|
||||
.div = div,
|
||||
.freq_mhz = freq_mhz
|
||||
};
|
||||
}
|
||||
|
||||
void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config)
|
||||
{
|
||||
if (config->source == SOC_CPU_CLK_SRC_XTAL) {
|
||||
rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
|
||||
} else if (((config->source == SOC_CPU_CLK_SRC_PLL_F160) || (config->source == SOC_CPU_CLK_SRC_PLL_F240)) &&
|
||||
s_cur_pll_freq == config->source_freq_mhz) {
|
||||
rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
|
||||
} else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) {
|
||||
rtc_clk_cpu_freq_to_8m();
|
||||
} else {
|
||||
/* fallback */
|
||||
rtc_clk_cpu_freq_set_config(config);
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_clk_cpu_freq_set_xtal(void)
|
||||
{
|
||||
rtc_clk_cpu_set_to_default_config();
|
||||
// We don't turn off the bbpll if some consumers depend on bbpll
|
||||
if (!s_bbpll_digi_consumers_ref_count) {
|
||||
rtc_clk_bbpll_disable();
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_clk_cpu_set_to_default_config(void)
|
||||
{
|
||||
int freq_mhz = (int)rtc_clk_xtal_freq_get();
|
||||
|
||||
rtc_clk_cpu_freq_to_xtal(freq_mhz, 1);
|
||||
}
|
||||
|
||||
void rtc_clk_cpu_freq_to_pll_and_pll_lock_release(int cpu_freq_mhz)
|
||||
{
|
||||
rtc_clk_cpu_freq_to_pll_mhz(cpu_freq_mhz);
|
||||
clk_ll_cpu_clk_src_lock_release();
|
||||
}
|
||||
|
||||
rtc_xtal_freq_t rtc_clk_xtal_freq_get(void)
|
||||
{
|
||||
return CONFIG_XTAL_FREQ;
|
||||
}
|
||||
|
||||
void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq)
|
||||
{
|
||||
clk_ll_xtal_store_freq_mhz(xtal_freq);
|
||||
}
|
||||
|
||||
static uint32_t rtc_clk_ahb_freq_get(void)
|
||||
{
|
||||
soc_cpu_clk_src_t source = clk_ll_cpu_get_src();
|
||||
uint32_t soc_root_freq_mhz;
|
||||
uint32_t divider;
|
||||
switch (source) {
|
||||
case SOC_CPU_CLK_SRC_XTAL:
|
||||
soc_root_freq_mhz = rtc_clk_xtal_freq_get();
|
||||
divider = clk_ll_ahb_get_divider();
|
||||
break;
|
||||
case SOC_CPU_CLK_SRC_PLL_F160:
|
||||
soc_root_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ;
|
||||
divider = clk_ll_ahb_get_divider();
|
||||
break;
|
||||
case SOC_CPU_CLK_SRC_PLL_F240:
|
||||
soc_root_freq_mhz = CLK_LL_PLL_240M_FREQ_MHZ;
|
||||
divider = clk_ll_ahb_get_divider();
|
||||
break;
|
||||
case SOC_CPU_CLK_SRC_RC_FAST:
|
||||
soc_root_freq_mhz = 20;
|
||||
divider = clk_ll_ahb_get_divider();
|
||||
break;
|
||||
default:
|
||||
// Unknown SOC_ROOT clock source
|
||||
soc_root_freq_mhz = 0;
|
||||
divider = 1;
|
||||
ESP_HW_LOGE(TAG, "Invalid SOC_ROOT_CLK");
|
||||
break;
|
||||
}
|
||||
return soc_root_freq_mhz / divider;
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_apb_freq_get(void)
|
||||
{
|
||||
return rtc_clk_ahb_freq_get() / clk_ll_apb_get_divider() * MHZ;
|
||||
}
|
||||
|
||||
void rtc_dig_clk8m_enable(void)
|
||||
{
|
||||
clk_ll_rc_fast_digi_enable();
|
||||
esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH);
|
||||
}
|
||||
|
||||
void rtc_dig_clk8m_disable(void)
|
||||
{
|
||||
clk_ll_rc_fast_digi_disable();
|
||||
esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH);
|
||||
}
|
||||
|
||||
bool rtc_dig_8m_enabled(void)
|
||||
{
|
||||
return clk_ll_rc_fast_digi_is_enabled();
|
||||
}
|
||||
|
||||
/* Name used in libphy.a:phy_chip_v7.o
|
||||
* TODO: update the library to use rtc_clk_xtal_freq_get
|
||||
*/
|
||||
rtc_xtal_freq_t rtc_get_xtal(void) __attribute__((alias("rtc_clk_xtal_freq_get")));
|
116
components/esp_hw_support/port/esp32c5/rtc_clk_init.c
Normal file
116
components/esp_hw_support/port/esp32c5/rtc_clk_init.c
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include "esp32c5/rom/ets_sys.h"
|
||||
#include "esp32c5/rom/rtc.h"
|
||||
#include "esp32c5/rom/uart.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "esp_cpu.h"
|
||||
#include "regi2c_ctrl.h"
|
||||
#include "soc/lp_clkrst_reg.h"
|
||||
#include "soc/regi2c_dig_reg.h"
|
||||
#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"
|
||||
#include "soc/pmu_reg.h"
|
||||
#include "pmu_param.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.
|
||||
* - SCK_DCAP value controls tuning of RC_SLOW clock.
|
||||
* The higher the value of DCAP is, the lower is the frequency.
|
||||
* - CK8M_DFREQ value controls tuning of RC_FAST clock.
|
||||
* CLK_8M_DFREQ constant gives the best temperature characteristics.
|
||||
* - RC32K_DFREQ value controls tuning of RC32K clock.
|
||||
*/
|
||||
REG_SET_FIELD(LP_CLKRST_FOSC_CNTL_REG, LP_CLKRST_FOSC_DFREQ, cfg.clk_8m_dfreq);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_SCK_DCAP, cfg.slow_clk_dcap);
|
||||
REG_SET_FIELD(LP_CLKRST_RC32K_CNTL_REG, LP_CLKRST_RC32K_DFREQ, cfg.rc32k_dfreq);
|
||||
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);
|
||||
REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, HP_CALI_DBIAS);
|
||||
REG_SET_FIELD(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, LP_CALI_DBIAS);
|
||||
|
||||
clk_ll_rc_fast_tick_conf();
|
||||
|
||||
rtc_xtal_freq_t xtal_freq = cfg.xtal_freq;
|
||||
esp_rom_uart_tx_wait_idle(0);
|
||||
rtc_clk_xtal_freq_update(xtal_freq);
|
||||
|
||||
/* Set CPU frequency */
|
||||
rtc_clk_cpu_freq_get_config(&old_config);
|
||||
uint32_t freq_before = old_config.freq_mhz;
|
||||
bool res = rtc_clk_cpu_freq_mhz_to_config(cfg.cpu_freq_mhz, &new_config);
|
||||
if (!res) {
|
||||
ESP_HW_LOGE(TAG, "invalid CPU frequency value");
|
||||
abort();
|
||||
}
|
||||
rtc_clk_cpu_freq_set_config(&new_config);
|
||||
|
||||
/* Re-calculate the ccount to make time calculation correct. */
|
||||
esp_cpu_set_cycle_count( (uint64_t)esp_cpu_get_cycle_count() * cfg.cpu_freq_mhz / freq_before );
|
||||
|
||||
/* Slow & fast clocks setup */
|
||||
// We will not power off RC_FAST in bootloader stage even if it is not being used as any
|
||||
// cpu / rtc_fast / rtc_slow clock sources, this is because RNG always needs it in the bootloader stage.
|
||||
bool need_rc_fast_en = true;
|
||||
if (cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
rtc_clk_32k_enable(true);
|
||||
} else if (cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
|
||||
rtc_clk_32k_enable_external();
|
||||
} else if (cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) {
|
||||
rtc_clk_rc32k_enable(true);
|
||||
}
|
||||
rtc_clk_8m_enable(need_rc_fast_en);
|
||||
rtc_clk_fast_src_set(cfg.fast_clk_src);
|
||||
rtc_clk_slow_src_set(cfg.slow_clk_src);
|
||||
}
|
284
components/esp_hw_support/port/esp32c5/rtc_time.c
Normal file
284
components/esp_hw_support/port/esp32c5/rtc_time.c
Normal file
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp32c5/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/timer_ll.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "assert.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
#include "soc/chip_revision.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
|
||||
static const char *TAG = "rtc_time";
|
||||
|
||||
// TODO: [ESP32C5] IDF-8667
|
||||
|
||||
/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* RTC_SLOW_CLK cycles.
|
||||
*
|
||||
* Slow clock calibration feature has two modes of operation: one-off and cycling.
|
||||
* In cycling mode (which is enabled by default on SoC reset), counting of XTAL
|
||||
* cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled
|
||||
* using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed
|
||||
* once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is
|
||||
* enabled using TIMG_RTC_CALI_START bit.
|
||||
*/
|
||||
|
||||
/* On ESP32C5, TIMG_RTC_CALI_CLK_SEL can config to 0, 1, 2, 3
|
||||
* 0 or 3: calibrate RC_SLOW clock
|
||||
* 1: calibrate RC_FAST clock
|
||||
* 2: calibrate 32K clock, which 32k depends on reg_32k_sel: 0: Internal 32 kHz RC oscillator, 1: External 32 kHz XTAL, 2: External 32kHz clock input by lp_pad_gpio0
|
||||
*/
|
||||
#define TIMG_RTC_CALI_CLK_SEL_RC_SLOW 0
|
||||
#define TIMG_RTC_CALI_CLK_SEL_RC_FAST 1
|
||||
#define TIMG_RTC_CALI_CLK_SEL_32K 2
|
||||
|
||||
/**
|
||||
* @brief Clock calibration function used by rtc_clk_cal
|
||||
*
|
||||
* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* RTC_SLOW_CLK cycles.
|
||||
*
|
||||
* Slow clock calibration feature has two modes of operation: one-off and cycling.
|
||||
* In cycling mode (which is enabled by default on SoC reset), counting of XTAL
|
||||
* cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled
|
||||
* using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed
|
||||
* once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is
|
||||
* enabled using TIMG_RTC_CALI_START bit.
|
||||
*
|
||||
* @param cal_clk which clock to calibrate
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles < TIMG_RTC_CALI_MAX_V);
|
||||
|
||||
uint32_t cali_clk_sel = 0;
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
soc_rtc_slow_clk_src_t old_32k_cal_clk_sel = clk_ll_32k_calibration_get_target();
|
||||
if (cal_clk == RTC_CAL_RTC_MUX) {
|
||||
cal_clk = (rtc_cal_sel_t)slow_clk_src;
|
||||
}
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_FAST;
|
||||
#if !CONFIG_IDF_TARGET_ESP32C5 // TODO: [ESP32C5] IDF-8642 Seems RC_SLOW can't be calibrated
|
||||
} else if (cal_clk == RTC_CAL_RC_SLOW) {
|
||||
cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_SLOW;
|
||||
#endif // !CONFIG_IDF_TARGET_ESP32C5
|
||||
} else {
|
||||
cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_32K;
|
||||
clk_ll_32k_calibration_set_target((soc_rtc_slow_clk_src_t)cal_clk);
|
||||
}
|
||||
|
||||
|
||||
/* Enable requested clock (150k clock is always on) */
|
||||
// All clocks on/off takes time to be stable, so we shouldn't frequently enable/disable the clock
|
||||
// Only enable if orignally was disabled, and set back to the disable state after calibration is done
|
||||
// If the clock is already on, then do nothing
|
||||
bool dig_32k_xtal_enabled = clk_ll_xtal32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
}
|
||||
|
||||
bool rc_fast_enabled = clk_ll_rc_fast_is_enabled();
|
||||
bool dig_rc_fast_enabled = clk_ll_rc_fast_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (!rc_fast_enabled) {
|
||||
rtc_clk_8m_enable(true);
|
||||
}
|
||||
if (!dig_rc_fast_enabled) {
|
||||
rtc_dig_clk8m_enable();
|
||||
}
|
||||
}
|
||||
|
||||
bool rc32k_enabled = clk_ll_rc32k_is_enabled();
|
||||
bool dig_rc32k_enabled = clk_ll_rc32k_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_RC32K) {
|
||||
if (!rc32k_enabled) {
|
||||
rtc_clk_rc32k_enable(true);
|
||||
}
|
||||
if (!dig_rc32k_enabled) {
|
||||
clk_ll_rc32k_digi_enable();
|
||||
}
|
||||
}
|
||||
|
||||
/* There may be another calibration process already running during we call this function,
|
||||
* so we should wait the last process is done.
|
||||
*/
|
||||
if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING)) {
|
||||
/**
|
||||
* Set a small timeout threshold to accelerate the generation of timeout.
|
||||
* The internal circuit will be reset when the timeout occurs and will not affect the next calibration.
|
||||
*/
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, 1);
|
||||
while (!GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY)
|
||||
&& !GET_PERI_REG_MASK(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT));
|
||||
}
|
||||
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cali_clk_sel);
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
|
||||
/* Figure out how long to wait for calibration to finish */
|
||||
|
||||
/* Set timeout reg and expect time delay*/
|
||||
uint32_t expected_freq;
|
||||
if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_32K) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_32K_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX;
|
||||
} else if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX;
|
||||
} else {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_RC_SLOW_FREQ_APPROX;
|
||||
}
|
||||
uint32_t us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) * MHZ / expected_freq);
|
||||
/* Start calibration */
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
SET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
|
||||
/* Wait for calibration to finish up to another us_time_estimate */
|
||||
esp_rom_delay_us(us_time_estimate);
|
||||
uint32_t cal_val;
|
||||
while (true) {
|
||||
if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY)) {
|
||||
cal_val = REG_GET_FIELD(TIMG_RTCCALICFG1_REG(0), TIMG_RTC_CALI_VALUE);
|
||||
|
||||
/*The Fosc CLK of calibration circuit is divided by 32 for ECO1.
|
||||
So we need to multiply the frequency of the Fosc for ECO1 and above chips by 32 times.
|
||||
And ensure that this modification will not affect ECO0.*/
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
cal_val = cal_val >> 5;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (GET_PERI_REG_MASK(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT)) {
|
||||
cal_val = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
|
||||
|
||||
/* if dig_32k_xtal was originally off and enabled due to calibration, then set back to off state */
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_enabled) {
|
||||
clk_ll_xtal32k_digi_disable();
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (!dig_rc_fast_enabled) {
|
||||
rtc_dig_clk8m_disable();
|
||||
}
|
||||
if (!rc_fast_enabled) {
|
||||
rtc_clk_8m_enable(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_RC32K) {
|
||||
if (!dig_rc32k_enabled) {
|
||||
clk_ll_rc32k_digi_disable();
|
||||
}
|
||||
if (!rc32k_enabled) {
|
||||
rtc_clk_rc32k_enable(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Always set back the calibration 32kHz clock selection
|
||||
if (old_32k_cal_clk_sel != SOC_RTC_SLOW_CLK_SRC_INVALID) {
|
||||
clk_ll_32k_calibration_set_target(old_32k_cal_clk_sel);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
|
||||
static bool rtc_clk_cal_32k_valid(rtc_xtal_freq_t xtal_freq, uint32_t slowclk_cycles, uint64_t actual_xtal_cycles)
|
||||
{
|
||||
uint64_t expected_xtal_cycles = (xtal_freq * 1000000ULL * slowclk_cycles) >> 15; // xtal_freq(hz) * slowclk_cycles / 32768
|
||||
uint64_t delta = expected_xtal_cycles / 2000; // 5/10000 = 0.05% error range
|
||||
return (actual_xtal_cycles >= (expected_xtal_cycles - delta)) && (actual_xtal_cycles <= (expected_xtal_cycles + delta));
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
{
|
||||
rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
|
||||
/*The Fosc CLK of calibration circuit is divided by 32 for ECO1.
|
||||
So we need to divide the calibrate cycles of the FOSC for ECO1 and above chips by 32 to
|
||||
avoid excessive calibration time.*/
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
slowclk_cycles = slowclk_cycles >> 5;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !rtc_clk_cal_32k_valid(xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t divider = ((uint64_t)xtal_freq) * slowclk_cycles;
|
||||
uint64_t period_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT) + divider / 2 - 1) / divider;
|
||||
uint32_t period = (uint32_t)(period_64 & UINT32_MAX);
|
||||
return period;
|
||||
}
|
||||
|
||||
uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period)
|
||||
{
|
||||
/* Overflow will happen in this function if time_in_us >= 2^45, which is about 400 days.
|
||||
* TODO: fix overflow.
|
||||
*/
|
||||
return (time_in_us << RTC_CLK_CAL_FRACT) / period;
|
||||
}
|
||||
|
||||
uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)
|
||||
{
|
||||
return (rtc_cycles * period) >> RTC_CLK_CAL_FRACT;
|
||||
}
|
||||
|
||||
uint64_t rtc_time_get(void)
|
||||
{
|
||||
// return lp_timer_hal_get_cycle_count();
|
||||
ESP_EARLY_LOGW(TAG, "rtc_time_get has not been implemented yet");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rtc_clk_wait_for_slow_cycle(void) //This function may not by useful any more
|
||||
{
|
||||
// TODO: IDF-5781
|
||||
ESP_EARLY_LOGW(TAG, "rtc_clk_wait_for_slow_cycle() has not been implemented yet");
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_freq_cal(uint32_t cal_val)
|
||||
{
|
||||
if (cal_val == 0) {
|
||||
return 0; // cal_val will be denominator, return 0 as the symbol of failure.
|
||||
}
|
||||
return 1000000ULL * (1 << RTC_CLK_CAL_FRACT) / cal_val;
|
||||
}
|
||||
|
||||
/// @brief if the calibration is used, we need to enable the timer group0 first
|
||||
__attribute__((constructor))
|
||||
static void enable_timer_group0_for_calibration(void)
|
||||
{
|
||||
PERIPH_RCC_ACQUIRE_ATOMIC(PERIPH_TIMG0_MODULE, ref_count) {
|
||||
if (ref_count == 0) {
|
||||
timer_ll_enable_bus_clock(0, true);
|
||||
timer_ll_reset_register(0);
|
||||
}
|
||||
}
|
||||
}
|
125
components/esp_hw_support/port/esp32c5/sar_periph_ctrl.c
Normal file
125
components/esp_hw_support/port/esp32c5/sar_periph_ctrl.c
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAR related peripherals are interdependent. This file
|
||||
* provides a united control to these registers, as multiple
|
||||
* components require these controls.
|
||||
*
|
||||
* Related peripherals are:
|
||||
* - ADC
|
||||
* - PWDET
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
// #include "esp_private/sar_periph_ctrl.h"
|
||||
// #include "esp_private/esp_modem_clock.h"
|
||||
// #include "hal/sar_ctrl_ll.h"
|
||||
|
||||
static const char *TAG = "sar_periph_ctrl";
|
||||
extern portMUX_TYPE rtc_spinlock;
|
||||
|
||||
// TODO: [ESP32C5] IDF-8701, IDF-8703, IDF-8727
|
||||
|
||||
void sar_periph_ctrl_init(void)
|
||||
{
|
||||
// sar_ctrl_ll_force_power_ctrl_from_pwdet(true);
|
||||
|
||||
//Add other periph power control initialisation here
|
||||
ESP_EARLY_LOGW(TAG, "sar_periph_ctrl_init has not implemented on C5 yet");
|
||||
}
|
||||
|
||||
void sar_periph_ctrl_power_enable(void)
|
||||
{
|
||||
// portENTER_CRITICAL_SAFE(&rtc_spinlock);
|
||||
// sar_ctrl_ll_force_power_ctrl_from_pwdet(true);
|
||||
// portEXIT_CRITICAL_SAFE(&rtc_spinlock);
|
||||
ESP_EARLY_LOGW(TAG, "sar_periph_ctrl_power_enable has not implemented on C5 yet");
|
||||
}
|
||||
|
||||
void sar_periph_ctrl_power_disable(void)
|
||||
{
|
||||
// portENTER_CRITICAL_SAFE(&rtc_spinlock);
|
||||
// sar_ctrl_ll_force_power_ctrl_from_pwdet(false);
|
||||
// portEXIT_CRITICAL_SAFE(&rtc_spinlock);
|
||||
ESP_EARLY_LOGW(TAG, "sar_periph_ctrl_power_disable has not implemented on C5 yet");
|
||||
}
|
||||
|
||||
/**
|
||||
* This gets incremented when s_sar_power_acquire() is called,
|
||||
* and decremented when s_sar_power_release() is called.
|
||||
* PWDET is powered down when the value reaches zero.
|
||||
* Should be modified within critical section.
|
||||
*/
|
||||
static int s_pwdet_power_on_cnt;
|
||||
|
||||
static void s_sar_power_acquire(void)
|
||||
{
|
||||
// modem_clock_module_enable(PERIPH_MODEM_ADC_COMMON_FE_MODULE);
|
||||
portENTER_CRITICAL_SAFE(&rtc_spinlock);
|
||||
s_pwdet_power_on_cnt++;
|
||||
if (s_pwdet_power_on_cnt == 1) {
|
||||
// sar_ctrl_ll_set_power_mode_from_pwdet(SAR_CTRL_LL_POWER_ON);
|
||||
}
|
||||
portEXIT_CRITICAL_SAFE(&rtc_spinlock);
|
||||
ESP_EARLY_LOGW(TAG, "s_sar_power_acquire has not implemented on C5 yet");
|
||||
}
|
||||
|
||||
static void s_sar_power_release(void)
|
||||
{
|
||||
portENTER_CRITICAL_SAFE(&rtc_spinlock);
|
||||
s_pwdet_power_on_cnt--;
|
||||
if (s_pwdet_power_on_cnt < 0) {
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
ESP_LOGE(TAG, "%s called, but s_pwdet_power_on_cnt == 0", __func__);
|
||||
abort();
|
||||
} else if (s_pwdet_power_on_cnt == 0) {
|
||||
// sar_ctrl_ll_set_power_mode_from_pwdet(SAR_CTRL_LL_POWER_FSM);
|
||||
}
|
||||
portEXIT_CRITICAL_SAFE(&rtc_spinlock);
|
||||
ESP_EARLY_LOGW(TAG, "s_sar_power_release has not implemented on C5 yet");
|
||||
// modem_clock_module_disable(PERIPH_MODEM_ADC_COMMON_FE_MODULE);
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* PWDET Power
|
||||
*----------------------------------------------------------------------------*/
|
||||
void sar_periph_ctrl_pwdet_power_acquire(void)
|
||||
{
|
||||
s_sar_power_acquire();
|
||||
}
|
||||
|
||||
void sar_periph_ctrl_pwdet_power_release(void)
|
||||
{
|
||||
s_sar_power_release();
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* ADC Power
|
||||
*----------------------------------------------------------------------------*/
|
||||
void sar_periph_ctrl_adc_oneshot_power_acquire(void)
|
||||
{
|
||||
s_sar_power_acquire();
|
||||
}
|
||||
|
||||
void sar_periph_ctrl_adc_oneshot_power_release(void)
|
||||
{
|
||||
s_sar_power_release();
|
||||
}
|
||||
|
||||
void sar_periph_ctrl_adc_continuous_power_acquire(void)
|
||||
{
|
||||
s_sar_power_acquire();
|
||||
}
|
||||
|
||||
void sar_periph_ctrl_adc_continuous_power_release(void)
|
||||
{
|
||||
s_sar_power_release();
|
||||
}
|
37
components/esp_hw_support/port/esp32c5/systimer.c
Normal file
37
components/esp_hw_support/port/esp32c5/systimer.c
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_private/systimer.h"
|
||||
|
||||
#if CONFIG_XTAL_FREQ_40
|
||||
/**
|
||||
* @brief systimer's clock source is fixed to XTAL (40MHz), and has a fixed fractional divider (2.5).
|
||||
* So the resolution of the systimer is 40MHz/2.5 = 16MHz.
|
||||
*/
|
||||
|
||||
uint64_t systimer_ticks_to_us(uint64_t ticks)
|
||||
{
|
||||
return ticks / 16;
|
||||
}
|
||||
|
||||
uint64_t systimer_us_to_ticks(uint64_t us)
|
||||
{
|
||||
return us * 16;
|
||||
}
|
||||
#elif CONFIG_XTAL_FREQ_48
|
||||
uint64_t systimer_ticks_to_us(uint64_t ticks)
|
||||
{
|
||||
return ticks * 5 / 96;
|
||||
}
|
||||
|
||||
uint64_t systimer_us_to_ticks(uint64_t us)
|
||||
{
|
||||
return us * 96 / 5;
|
||||
}
|
||||
#else
|
||||
#error "Unsupported XTAL frequency by systimer"
|
||||
#endif // CONFIG_XTAL_FREQ_xx
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2016-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2016-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -26,14 +26,14 @@
|
||||
#endif
|
||||
#include "sys/queue.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4// TODO: IDF-8008
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-8008
|
||||
static const char *TAG = "rtc_module";
|
||||
#endif
|
||||
|
||||
// rtc_spinlock is used by other peripheral drivers
|
||||
portMUX_TYPE rtc_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-8008
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 && !CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-8008
|
||||
|
||||
#define NOT_REGISTERED (-1)
|
||||
|
||||
@ -101,7 +101,7 @@ out:
|
||||
|
||||
esp_err_t rtc_isr_register(intr_handler_t handler, void* handler_arg, uint32_t rtc_intr_mask, uint32_t flags)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-8008
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-8008
|
||||
ESP_EARLY_LOGW(TAG, "rtc_isr_register() has not been implemented yet");
|
||||
return ESP_OK;
|
||||
#else
|
||||
@ -132,7 +132,7 @@ esp_err_t rtc_isr_register(intr_handler_t handler, void* handler_arg, uint32_t r
|
||||
|
||||
esp_err_t rtc_isr_deregister(intr_handler_t handler, void* handler_arg)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-8008
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-8008
|
||||
ESP_EARLY_LOGW(TAG, "rtc_isr_deregister() has not been implemented yet");
|
||||
return ESP_OK;
|
||||
#else
|
||||
@ -161,7 +161,7 @@ esp_err_t rtc_isr_deregister(intr_handler_t handler, void* handler_arg)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-8008
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 && !CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-8008
|
||||
/**
|
||||
* @brief This helper function can be used to avoid the interrupt to be triggered with cache disabled.
|
||||
* There are lots of different signals on RTC module (i.e. sleep_wakeup, wdt, brownout_detect, etc.)
|
||||
@ -184,7 +184,7 @@ static void s_rtc_isr_noniram_hook_relieve(uint32_t rtc_intr_mask)
|
||||
|
||||
IRAM_ATTR void rtc_isr_noniram_disable(uint32_t cpu)
|
||||
{
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-8008
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 && !CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-8008
|
||||
if (rtc_isr_cpu == cpu) {
|
||||
rtc_intr_enabled |= RTCCNTL.int_ena.val;
|
||||
RTCCNTL.int_ena.val &= rtc_intr_cache;
|
||||
@ -194,7 +194,7 @@ IRAM_ATTR void rtc_isr_noniram_disable(uint32_t cpu)
|
||||
|
||||
IRAM_ATTR void rtc_isr_noniram_enable(uint32_t cpu)
|
||||
{
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-8008
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32P4 && !CONFIG_IDF_TARGET_ESP32C5 // TODO: IDF-8008
|
||||
if (rtc_isr_cpu == cpu) {
|
||||
RTCCNTL.int_ena.val = rtc_intr_enabled;
|
||||
rtc_intr_enabled = 0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -33,7 +33,7 @@ esp_err_t sleep_clock_system_retention_init(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32C6
|
||||
#define N_REGS_PCR() (((PCR_SRAM_POWER_CONF_REG - DR_REG_PCR_BASE) / 4) + 1)
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5
|
||||
#define N_REGS_PCR() (((PCR_PWDET_SAR_CLK_CONF_REG - DR_REG_PCR_BASE) / 4) + 1)
|
||||
#endif
|
||||
const static sleep_retention_entries_config_t pcr_regs_retention[] = {
|
||||
@ -53,7 +53,11 @@ void sleep_clock_system_retention_deinit(void)
|
||||
|
||||
esp_err_t sleep_clock_modem_retention_init(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32C5
|
||||
#define N_REGS_SYSCON() (((MODEM_SYSCON_MEM_RF2_CONF_REG - MODEM_SYSCON_TEST_CONF_REG) / 4) + 1)
|
||||
#else
|
||||
#define N_REGS_SYSCON() (((MODEM_SYSCON_MEM_CONF_REG - MODEM_SYSCON_TEST_CONF_REG) / 4) + 1)
|
||||
#endif
|
||||
#if SOC_PM_RETENTION_SW_TRIGGER_REGDMA
|
||||
#define N_REGS_LPCON() (((MODEM_LPCON_MEM_CONF_REG - MODEM_LPCON_TEST_CONF_REG) / 4) + 1)
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -47,6 +47,14 @@
|
||||
#include "soc/plic_reg.h"
|
||||
#include "soc/clint_reg.h"
|
||||
#include "esp32c6/rom/cache.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C5
|
||||
#include "esp32c5/rom/rtc.h"
|
||||
#include "riscv/rvsleep-frames.h"
|
||||
#include "soc/intpri_reg.h"
|
||||
#include "soc/cache_reg.h"
|
||||
#include "soc/clic_reg.h"
|
||||
#include "soc/clint_reg.h"
|
||||
#include "esp32c5/rom/cache.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#include "esp32h2/rom/rtc.h"
|
||||
#include "riscv/rvsleep-frames.h"
|
||||
@ -329,7 +337,7 @@ static inline void * cpu_domain_cache_config_sleep_frame_alloc_and_init(void)
|
||||
#if CONFIG_IDF_TARGET_ESP32C6
|
||||
{ .start = EXTMEM_L1_CACHE_CTRL_REG, .end = EXTMEM_L1_CACHE_CTRL_REG + 4 },
|
||||
{ .start = EXTMEM_L1_CACHE_WRAP_AROUND_CTRL_REG, .end = EXTMEM_L1_CACHE_WRAP_AROUND_CTRL_REG + 4 }
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5
|
||||
{ .start = CACHE_L1_CACHE_CTRL_REG, .end = CACHE_L1_CACHE_CTRL_REG + 4 },
|
||||
{ .start = CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG, .end = CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG + 4 }
|
||||
#endif
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "soc/soc_caps.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32C5
|
||||
#include "soc/lp_aon_reg.h"
|
||||
#include "soc/extmem_reg.h"
|
||||
#endif
|
||||
@ -115,7 +115,7 @@ rv_core_critical_regs_save:
|
||||
csrr t0, mscratch
|
||||
sw t0, RV_SLP_CTX_T0(t3)
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32C5
|
||||
/* writeback dcache is required here!!! */
|
||||
la t0, EXTMEM_CACHE_SYNC_MAP_REG
|
||||
li t1, 0x10
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -81,6 +81,9 @@
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#include "esp32c6/rom/rtc.h"
|
||||
#include "hal/gpio_ll.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C5
|
||||
#include "esp32c5/rom/rtc.h"
|
||||
#include "hal/gpio_ll.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#include "esp32h2/rom/rtc.h"
|
||||
#include "esp32h2/rom/cache.h"
|
||||
@ -131,6 +134,9 @@
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (318)
|
||||
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (56)
|
||||
#elif CONFIG_IDF_TARGET_ESP32C5 // TODO: [ESP32C5] IDF-8638, IDF-8640
|
||||
#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)
|
||||
|
@ -125,7 +125,7 @@ esp_err_t sleep_sys_periph_tg0_retention_init(void)
|
||||
|
||||
esp_err_t sleep_sys_periph_iomux_retention_init(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32C6
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C5 // TODO: [ESP32C5] IDF-8638, IDF-8640
|
||||
#define N_REGS_IOMUX_0() (((PERIPHS_IO_MUX_SPID_U - REG_IO_MUX_BASE) / 4) + 1)
|
||||
#define N_REGS_IOMUX_1() (((GPIO_FUNC34_OUT_SEL_CFG_REG - GPIO_FUNC0_OUT_SEL_CFG_REG) / 4) + 1)
|
||||
#define N_REGS_IOMUX_2() (((GPIO_FUNC124_IN_SEL_CFG_REG - GPIO_STATUS_NEXT_REG) / 4) + 1)
|
||||
|
@ -345,6 +345,7 @@ menu "ESP System Settings"
|
||||
prompt "UART console baud rate" if ESP_CONSOLE_UART_CUSTOM
|
||||
depends on ESP_CONSOLE_UART
|
||||
default 74880 if (IDF_TARGET_ESP32C2 && XTAL_FREQ_26)
|
||||
default 138240 if (IDF_TARGET_ESP32C5_BETA3_VERSION && XTAL_FREQ_48)
|
||||
default 115200
|
||||
range 1200 4000000 if !PM_ENABLE
|
||||
range 1200 1000000 if PM_ENABLE
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
#include "spi_flash_mmap.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
#if CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5
|
||||
#include "soc/cache_reg.h"
|
||||
#else
|
||||
#include "soc/extmem_reg.h"
|
||||
|
@ -73,7 +73,7 @@ void esp_brownout_init(void)
|
||||
|
||||
brownout_hal_config(&cfg);
|
||||
brownout_ll_intr_clear();
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32C5 // TODO: [ESP32C5] IDF-8647
|
||||
// TODO IDF-6606: LP_RTC_TIMER interrupt source is shared by lp_timer and brownout detector, but lp_timer interrupt
|
||||
// is not used now. An interrupt allocator is needed when lp_timer intr gets supported.
|
||||
esp_intr_alloc(ETS_LP_RTC_TIMER_INTR_SOURCE, ESP_INTR_FLAG_IRAM, &rtc_brownout_isr_handler, NULL, NULL);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -52,6 +52,10 @@
|
||||
#include "esp32c6/rtc.h"
|
||||
#include "esp32c6/rom/cache.h"
|
||||
#include "esp_memprot.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C5
|
||||
#include "esp32c5/rtc.h"
|
||||
#include "esp32c5/rom/cache.h"
|
||||
#include "esp_memprot.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#include "esp32h2/rtc.h"
|
||||
#include "esp32h2/rom/cache.h"
|
||||
@ -688,12 +692,12 @@ void IRAM_ATTR call_start_cpu0(void)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32P4 //TODO: IDF-7529
|
||||
#if !CONFIG_IDF_TARGET_ESP32P4 && !CONFIG_IDF_TARGET_ESP32C5 //TODO: IDF-7529, IDF-8638
|
||||
// Need to unhold the IOs that were hold right before entering deep sleep, which are used as wakeup pins
|
||||
if (rst_reas[0] == RESET_REASON_CORE_DEEP_SLEEP) {
|
||||
esp_deep_sleep_wakeup_io_reset();
|
||||
}
|
||||
#endif //#if !CONFIG_IDF_TARGET_ESP32P4
|
||||
#endif //#if !CONFIG_IDF_TARGET_ESP32P4 & !CONFIG_IDF_TARGET_ESP32C5
|
||||
|
||||
#if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
|
||||
esp_cache_err_int_init();
|
||||
|
@ -0,0 +1,8 @@
|
||||
set(srcs "clk.c"
|
||||
"reset_reason.c"
|
||||
"system_internal.c"
|
||||
"cache_err_int.c")
|
||||
|
||||
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})
|
||||
|
||||
target_sources(${COMPONENT_LIB} PRIVATE ${srcs})
|
@ -0,0 +1,28 @@
|
||||
choice ESP_DEFAULT_CPU_FREQ_MHZ
|
||||
prompt "CPU frequency"
|
||||
default ESP_DEFAULT_CPU_FREQ_MHZ_40 if IDF_ENV_FPGA
|
||||
default ESP_DEFAULT_CPU_FREQ_MHZ_240
|
||||
help
|
||||
CPU frequency to be set on application startup.
|
||||
|
||||
config ESP_DEFAULT_CPU_FREQ_MHZ_40
|
||||
bool "40 MHz"
|
||||
depends on IDF_ENV_FPGA
|
||||
config ESP_DEFAULT_CPU_FREQ_MHZ_80
|
||||
bool "80 MHz"
|
||||
config ESP_DEFAULT_CPU_FREQ_MHZ_120
|
||||
bool "120 MHz"
|
||||
config ESP_DEFAULT_CPU_FREQ_MHZ_160
|
||||
bool "160 MHz"
|
||||
config ESP_DEFAULT_CPU_FREQ_MHZ_240
|
||||
bool "240 MHz"
|
||||
endchoice
|
||||
|
||||
config ESP_DEFAULT_CPU_FREQ_MHZ
|
||||
int
|
||||
default 40 if ESP_DEFAULT_CPU_FREQ_MHZ_40
|
||||
default 60 if ESP_DEFAULT_CPU_FREQ_MHZ_60
|
||||
default 80 if ESP_DEFAULT_CPU_FREQ_MHZ_80
|
||||
default 120 if ESP_DEFAULT_CPU_FREQ_MHZ_120
|
||||
default 160 if ESP_DEFAULT_CPU_FREQ_MHZ_160
|
||||
default 240 if ESP_DEFAULT_CPU_FREQ_MHZ_240
|
@ -0,0 +1,46 @@
|
||||
menu "Brownout Detector"
|
||||
config ESP_BROWNOUT_DET
|
||||
bool "Hardware brownout detect & reset"
|
||||
depends on !IDF_ENV_FPGA && SOC_BOD_SUPPORTED
|
||||
default y
|
||||
help
|
||||
The ESP32-C5 has a built-in brownout detector which can detect if the voltage is lower than
|
||||
a specific value. If this happens, it will reset the chip in order to prevent unintended
|
||||
behaviour.
|
||||
|
||||
choice ESP_BROWNOUT_DET_LVL_SEL
|
||||
prompt "Brownout voltage level"
|
||||
depends on ESP_BROWNOUT_DET
|
||||
default ESP_BROWNOUT_DET_LVL_SEL_7
|
||||
help
|
||||
TODO: [ESP32C5] IDF-8647
|
||||
The brownout detector will reset the chip when the supply voltage is approximately
|
||||
below this level. Note that there may be some variation of brownout voltage level
|
||||
between each chip.
|
||||
|
||||
#The voltage levels here are estimates, more work needs to be done to figure out the exact voltages
|
||||
#of the brownout threshold levels.
|
||||
config ESP_BROWNOUT_DET_LVL_SEL_7
|
||||
bool "2.51V"
|
||||
config ESP_BROWNOUT_DET_LVL_SEL_6
|
||||
bool "2.64V"
|
||||
config ESP_BROWNOUT_DET_LVL_SEL_5
|
||||
bool "2.76V"
|
||||
config ESP_BROWNOUT_DET_LVL_SEL_4
|
||||
bool "2.92V"
|
||||
config ESP_BROWNOUT_DET_LVL_SEL_3
|
||||
bool "3.10V"
|
||||
config ESP_BROWNOUT_DET_LVL_SEL_2
|
||||
bool "3.27V"
|
||||
endchoice
|
||||
|
||||
config ESP_BROWNOUT_DET_LVL
|
||||
int
|
||||
default 2 if ESP_BROWNOUT_DET_LVL_SEL_2
|
||||
default 3 if ESP_BROWNOUT_DET_LVL_SEL_3
|
||||
default 4 if ESP_BROWNOUT_DET_LVL_SEL_4
|
||||
default 5 if ESP_BROWNOUT_DET_LVL_SEL_5
|
||||
default 6 if ESP_BROWNOUT_DET_LVL_SEL_6
|
||||
default 7 if ESP_BROWNOUT_DET_LVL_SEL_7
|
||||
|
||||
endmenu
|
76
components/esp_system/port/soc/esp32c5/cache_err_int.c
Normal file
76
components/esp_system/port/soc/esp32c5/cache_err_int.c
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
The cache has an interrupt that can be raised as soon as an access to a cached
|
||||
region (flash) is done without the cache being enabled. We use that here
|
||||
to panic the CPU, which from a debugging perspective is better than grabbing bad
|
||||
data from the bus.
|
||||
*/
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/periph_defs.h"
|
||||
#include "soc/soc.h"
|
||||
#include "riscv/interrupt.h"
|
||||
#include "hal/cache_ll.h"
|
||||
|
||||
static const char *TAG = "CACHE_ERR";
|
||||
|
||||
const char cache_error_msg[] = "Cache access error";
|
||||
|
||||
const char *esp_cache_err_panic_string(void)
|
||||
{
|
||||
const uint32_t access_err_status = cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_ACCESS_EVENT_MASK);
|
||||
|
||||
/* Return the error string if a cache error is active */
|
||||
const char* err_str = access_err_status ? cache_error_msg : NULL;
|
||||
|
||||
return err_str;
|
||||
}
|
||||
|
||||
bool esp_cache_err_has_active_err(void)
|
||||
{
|
||||
return cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_ACCESS_EVENT_MASK);
|
||||
}
|
||||
|
||||
void esp_cache_err_int_init(void)
|
||||
{
|
||||
const uint32_t core_id = 0;
|
||||
|
||||
/* Disable cache interrupts if enabled. */
|
||||
ESP_INTR_DISABLE(ETS_CACHEERR_INUM);
|
||||
|
||||
/**
|
||||
* Bind all cache errors to ETS_CACHEERR_INUM interrupt. we will deal with
|
||||
* them in handler by different types
|
||||
*
|
||||
* On ESP32C5 boards, the cache is a shared one but buses are still
|
||||
* distinct. So, we have an bus0 and a bus1 sharing the same cache.
|
||||
* This error can occur if a bus performs a request but the cache
|
||||
* is disabled.
|
||||
*/
|
||||
esp_rom_route_intr_matrix(core_id, ETS_CACHE_INTR_SOURCE, ETS_CACHEERR_INUM);
|
||||
|
||||
/* Set the type and priority to cache error interrupts. */
|
||||
esprv_intc_int_set_type(ETS_CACHEERR_INUM, INTR_TYPE_LEVEL);
|
||||
esprv_intc_int_set_priority(ETS_CACHEERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
|
||||
|
||||
ESP_DRAM_LOGV(TAG, "access error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ACCESS_EVENT_MASK);
|
||||
/* On the hardware side, start by clearing all the bits reponsible for cache access error */
|
||||
cache_ll_l1_clear_access_error_intr(0, CACHE_LL_L1_ACCESS_EVENT_MASK);
|
||||
/* Then enable cache access error interrupts. */
|
||||
cache_ll_l1_enable_access_error_intr(0, CACHE_LL_L1_ACCESS_EVENT_MASK);
|
||||
|
||||
/* Enable the interrupts for cache error. */
|
||||
ESP_INTR_ENABLE(ETS_CACHEERR_INUM);
|
||||
}
|
||||
|
||||
int esp_cache_err_get_cpuid(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
301
components/esp_system/port/soc/esp32c5/clk.c
Normal file
301
components/esp_system/port/soc/esp32c5/clk.c
Normal file
@ -0,0 +1,301 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/param.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_clk_internal.h"
|
||||
#include "esp32c5/rom/ets_sys.h"
|
||||
#include "esp32c5/rom/uart.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "soc/i2s_reg.h"
|
||||
#include "esp_cpu.h"
|
||||
#include "hal/wdt_hal.h"
|
||||
#include "hal/modem_lpcon_ll.h"
|
||||
#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"
|
||||
|
||||
/* Number of cycles to wait from the 32k XTAL oscillator to consider it running.
|
||||
* Larger values increase startup delay. Smaller values may cause false positive
|
||||
* detection (i.e. oscillator runs for a few cycles and then stops).
|
||||
*/
|
||||
#define SLOW_CLK_CAL_CYCLES CONFIG_RTC_CLK_CAL_CYCLES
|
||||
|
||||
#define MHZ (1000000)
|
||||
|
||||
static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src);
|
||||
|
||||
static const char *TAG = "clk";
|
||||
|
||||
// TODO: [ESP32C5] IDF-8642
|
||||
__attribute__((weak)) void esp_clk_init(void)
|
||||
{
|
||||
#if SOC_PMU_SUPPORTED
|
||||
pmu_init();
|
||||
#endif
|
||||
|
||||
assert((rtc_clk_xtal_freq_get() == RTC_XTAL_FREQ_40M) || (rtc_clk_xtal_freq_get() == RTC_XTAL_FREQ_48M));
|
||||
|
||||
modem_lpcon_ll_set_pwr_tick_target(&MODEM_LPCON, rtc_clk_xtal_freq_get() - 1);
|
||||
|
||||
rtc_clk_8m_enable(true);
|
||||
rtc_clk_fast_src_set(SOC_RTC_FAST_CLK_SRC_RC_FAST);
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||
// WDT uses a SLOW_CLK clock source. After a function select_rtc_slow_clk a frequency of this source can changed.
|
||||
// If the frequency changes from 150kHz to 32kHz, then the timeout set for the WDT will increase 4.6 times.
|
||||
// Therefore, for the time of frequency change, set a new lower timeout value (1.6 sec).
|
||||
// This prevents excessive delay before resetting in case the supply voltage is drawdown.
|
||||
// (If frequency is changed from 150kHz to 32kHz then WDT timeout will increased to 1.6sec * 150/32 = 7.5 sec).
|
||||
wdt_hal_context_t rtc_wdt_ctx = RWDT_HAL_CONTEXT_DEFAULT();
|
||||
uint32_t stage_timeout_ticks = (uint32_t)(1600ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_feed(&rtc_wdt_ctx);
|
||||
//Bootloader has enabled RTC WDT until now. We're only modifying timeout, so keep the stage and timeout action the same
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_RTC_CLK_SRC_EXT_CRYS)
|
||||
select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_XTAL32K);
|
||||
#elif defined(CONFIG_RTC_CLK_SRC_EXT_OSC)
|
||||
select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_OSC_SLOW);
|
||||
#elif defined(CONFIG_RTC_CLK_SRC_INT_RC32K)
|
||||
select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_RC32K);
|
||||
#else
|
||||
abort();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||
// After changing a frequency WDT timeout needs to be set for new frequency.
|
||||
stage_timeout_ticks = (uint32_t)((uint64_t)CONFIG_BOOTLOADER_WDT_TIME_MS * rtc_clk_slow_freq_get_hz() / 1000);
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_feed(&rtc_wdt_ctx);
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
#endif
|
||||
|
||||
rtc_cpu_freq_config_t old_config, new_config;
|
||||
rtc_clk_cpu_freq_get_config(&old_config);
|
||||
const uint32_t old_freq_mhz = old_config.freq_mhz;
|
||||
const uint32_t new_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ;
|
||||
|
||||
bool res = rtc_clk_cpu_freq_mhz_to_config(new_freq_mhz, &new_config);
|
||||
assert(res);
|
||||
|
||||
// Wait for UART TX to finish, otherwise some UART output will be lost
|
||||
// when switching APB frequency
|
||||
esp_rom_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
|
||||
if (res) {
|
||||
rtc_clk_cpu_freq_set_config(&new_config);
|
||||
}
|
||||
|
||||
// Re calculate the ccount to make time calculation correct.
|
||||
esp_cpu_set_cycle_count( (uint64_t)esp_cpu_get_cycle_count() * new_freq_mhz / old_freq_mhz );
|
||||
}
|
||||
|
||||
static void select_rtc_slow_clk(soc_rtc_slow_clk_src_t rtc_slow_clk_src)
|
||||
{
|
||||
uint32_t cal_val = 0;
|
||||
/* number of times to repeat 32k XTAL calibration
|
||||
* before giving up and switching to the internal RC
|
||||
*/
|
||||
int retry_32k_xtal = 3;
|
||||
|
||||
do {
|
||||
if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K || rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
|
||||
/* 32k XTAL oscillator needs to be enabled and running before it can
|
||||
* be used. Hardware doesn't have a direct way of checking if the
|
||||
* oscillator is running. Here we use rtc_clk_cal function to count
|
||||
* the number of main XTAL cycles in the given number of 32k XTAL
|
||||
* oscillator cycles. If the 32k XTAL has not started up, calibration
|
||||
* will time out, returning 0.
|
||||
*/
|
||||
ESP_EARLY_LOGD(TAG, "waiting for 32k oscillator to start up");
|
||||
rtc_cal_sel_t cal_sel = 0;
|
||||
if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
rtc_clk_32k_enable(true);
|
||||
cal_sel = RTC_CAL_32K_XTAL;
|
||||
} else if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
|
||||
rtc_clk_32k_enable_external();
|
||||
cal_sel = RTC_CAL_32K_OSC_SLOW;
|
||||
}
|
||||
// When SLOW_CLK_CAL_CYCLES is set to 0, clock calibration will not be performed at startup.
|
||||
if (SLOW_CLK_CAL_CYCLES > 0) {
|
||||
cal_val = rtc_clk_cal(cal_sel, SLOW_CLK_CAL_CYCLES);
|
||||
if (cal_val == 0) {
|
||||
if (retry_32k_xtal-- > 0) {
|
||||
continue;
|
||||
}
|
||||
#if CONFIG_IDF_TARGET_ESP32C5
|
||||
ESP_EARLY_LOGW(TAG, "32 kHz clock not found, switching to internal 32 kHz oscillator");
|
||||
rtc_slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC32K;
|
||||
#else
|
||||
ESP_EARLY_LOGW(TAG, "32 kHz clock not found, switching to internal 150 kHz oscillator");
|
||||
rtc_slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC_SLOW;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} else if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) {
|
||||
rtc_clk_rc32k_enable(true);
|
||||
}
|
||||
rtc_clk_slow_src_set(rtc_slow_clk_src);
|
||||
|
||||
if (SLOW_CLK_CAL_CYCLES > 0) {
|
||||
/* TODO: 32k XTAL oscillator has some frequency drift at startup.
|
||||
* Improve calibration routine to wait until the frequency is stable.
|
||||
*/
|
||||
cal_val = rtc_clk_cal(RTC_CAL_RTC_MUX, SLOW_CLK_CAL_CYCLES);
|
||||
} else {
|
||||
const uint64_t cal_dividend = (1ULL << RTC_CLK_CAL_FRACT) * 1000000ULL;
|
||||
cal_val = (uint32_t) (cal_dividend / rtc_clk_slow_freq_get_hz());
|
||||
}
|
||||
} while (cal_val == 0);
|
||||
ESP_EARLY_LOGD(TAG, "RTC_SLOW_CLK calibration value: %d", cal_val);
|
||||
esp_clk_slowclk_cal_set(cal_val);
|
||||
}
|
||||
|
||||
void rtc_clk_select_rtc_slow_clk(void)
|
||||
{
|
||||
select_rtc_slow_clk(SOC_RTC_SLOW_CLK_SRC_XTAL32K);
|
||||
}
|
||||
|
||||
/* This function is not exposed as an API at this point.
|
||||
* All peripheral clocks are default enabled after chip is powered on.
|
||||
* This function disables some peripheral clocks when cpu starts.
|
||||
* These peripheral clocks are enabled when the peripherals are initialized
|
||||
* and disabled when they are de-initialized.
|
||||
*/
|
||||
__attribute__((weak)) void esp_perip_clk_init(void)
|
||||
{
|
||||
#if 0 // TODO: [ESP32C5] IDF-8844
|
||||
/* During system initialization, the low-power clock source of the modem
|
||||
* (WiFi, BLE or Coexist) follows the configuration of the slow clock source
|
||||
* of the system. If the WiFi, BLE or Coexist module needs a higher
|
||||
* precision sleep clock (for example, the BLE needs to use the main XTAL
|
||||
* oscillator (40 MHz) to provide the clock during the sleep process in some
|
||||
* scenarios), the module needs to switch to the required clock source by
|
||||
* itself. */ //TODO - WIFI-5233
|
||||
soc_rtc_slow_clk_src_t rtc_slow_clk_src = rtc_clk_slow_src_get();
|
||||
modem_clock_lpclk_src_t modem_lpclk_src = (modem_clock_lpclk_src_t) ( \
|
||||
(rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) ? MODEM_CLOCK_LPCLK_SRC_XTAL32K \
|
||||
: (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) ? MODEM_CLOCK_LPCLK_SRC_RC32K \
|
||||
: (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) ? MODEM_CLOCK_LPCLK_SRC_EXT32K \
|
||||
: MODEM_CLOCK_LPCLK_SRC_RC32K);
|
||||
|
||||
modem_clock_select_lp_clock_source(PERIPH_WIFI_MODULE, modem_lpclk_src, 0);
|
||||
#endif
|
||||
|
||||
ESP_EARLY_LOGW(TAG, "esp_perip_clk_init() has not been implemented yet");
|
||||
#if 0 // TODO: [ESP32C5] IDF-8844
|
||||
uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0;
|
||||
uint32_t common_perip_clk1 = 0;
|
||||
|
||||
soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0);
|
||||
|
||||
/* For reason that only reset CPU, do not disable the clocks
|
||||
* that have been enabled before reset.
|
||||
*/
|
||||
if (rst_reason == RESET_REASON_CPU0_MWDT0 || rst_reason == RESET_REASON_CPU0_SW ||
|
||||
rst_reason == RESET_REASON_CPU0_RTC_WDT || rst_reason == RESET_REASON_CPU0_MWDT1) {
|
||||
common_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN0_REG);
|
||||
hwcrypto_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN1_REG);
|
||||
wifi_bt_sdio_clk = ~READ_PERI_REG(SYSTEM_WIFI_CLK_EN_REG);
|
||||
} else {
|
||||
common_perip_clk = SYSTEM_WDG_CLK_EN |
|
||||
SYSTEM_I2S0_CLK_EN |
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 0
|
||||
SYSTEM_UART_CLK_EN |
|
||||
#endif
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 1
|
||||
SYSTEM_UART1_CLK_EN |
|
||||
#endif
|
||||
SYSTEM_SPI2_CLK_EN |
|
||||
SYSTEM_I2C_EXT0_CLK_EN |
|
||||
SYSTEM_UHCI0_CLK_EN |
|
||||
SYSTEM_RMT_CLK_EN |
|
||||
SYSTEM_LEDC_CLK_EN |
|
||||
SYSTEM_TIMERGROUP1_CLK_EN |
|
||||
SYSTEM_SPI3_CLK_EN |
|
||||
SYSTEM_SPI4_CLK_EN |
|
||||
SYSTEM_TWAI_CLK_EN |
|
||||
SYSTEM_I2S1_CLK_EN |
|
||||
SYSTEM_SPI2_DMA_CLK_EN |
|
||||
SYSTEM_SPI3_DMA_CLK_EN;
|
||||
|
||||
common_perip_clk1 = 0;
|
||||
hwcrypto_perip_clk = SYSTEM_CRYPTO_AES_CLK_EN |
|
||||
SYSTEM_CRYPTO_SHA_CLK_EN |
|
||||
SYSTEM_CRYPTO_RSA_CLK_EN;
|
||||
wifi_bt_sdio_clk = SYSTEM_WIFI_CLK_WIFI_EN |
|
||||
SYSTEM_WIFI_CLK_BT_EN_M |
|
||||
SYSTEM_WIFI_CLK_UNUSED_BIT5 |
|
||||
SYSTEM_WIFI_CLK_UNUSED_BIT12;
|
||||
}
|
||||
|
||||
//Reset the communication peripherals like I2C, SPI, UART, I2S and bring them to known state.
|
||||
common_perip_clk |= SYSTEM_I2S0_CLK_EN |
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 0
|
||||
SYSTEM_UART_CLK_EN |
|
||||
#endif
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 1
|
||||
SYSTEM_UART1_CLK_EN |
|
||||
#endif
|
||||
SYSTEM_SPI2_CLK_EN |
|
||||
SYSTEM_I2C_EXT0_CLK_EN |
|
||||
SYSTEM_UHCI0_CLK_EN |
|
||||
SYSTEM_RMT_CLK_EN |
|
||||
SYSTEM_UHCI1_CLK_EN |
|
||||
SYSTEM_SPI3_CLK_EN |
|
||||
SYSTEM_SPI4_CLK_EN |
|
||||
SYSTEM_I2C_EXT1_CLK_EN |
|
||||
SYSTEM_I2S1_CLK_EN |
|
||||
SYSTEM_SPI2_DMA_CLK_EN |
|
||||
SYSTEM_SPI3_DMA_CLK_EN;
|
||||
common_perip_clk1 = 0;
|
||||
|
||||
/* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock,
|
||||
* the current is not reduced when disable I2S clock.
|
||||
*/
|
||||
// TOCK(check replacement)
|
||||
// REG_SET_FIELD(I2S_CLKM_CONF_REG(0), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL);
|
||||
// REG_SET_FIELD(I2S_CLKM_CONF_REG(1), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL);
|
||||
|
||||
/* Disable some peripheral clocks. */
|
||||
CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, common_perip_clk);
|
||||
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, common_perip_clk);
|
||||
|
||||
CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN1_REG, common_perip_clk1);
|
||||
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, common_perip_clk1);
|
||||
|
||||
/* Disable hardware crypto clocks. */
|
||||
CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN1_REG, hwcrypto_perip_clk);
|
||||
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, hwcrypto_perip_clk);
|
||||
|
||||
/* Disable WiFi/BT/SDIO clocks. */
|
||||
CLEAR_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, wifi_bt_sdio_clk);
|
||||
SET_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_EN);
|
||||
|
||||
/* Set WiFi light sleep clock source to RTC slow clock */
|
||||
REG_SET_FIELD(SYSTEM_BT_LPCK_DIV_INT_REG, SYSTEM_BT_LPCK_DIV_NUM, 0);
|
||||
CLEAR_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_8M);
|
||||
SET_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_RTC_SLOW);
|
||||
|
||||
/* Enable RNG clock. */
|
||||
periph_module_enable(PERIPH_RNG_MODULE);
|
||||
#endif
|
||||
}
|
116
components/esp_system/port/soc/esp32c5/reset_reason.c
Normal file
116
components/esp_system/port/soc/esp32c5/reset_reason.c
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "esp_system.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_private/system_internal.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "esp32c5/rom/rtc.h"
|
||||
|
||||
static void esp_reset_reason_clear_hint(void);
|
||||
|
||||
static esp_reset_reason_t s_reset_reason;
|
||||
|
||||
// TODO: [ESP32C5] IDF-8660
|
||||
|
||||
static esp_reset_reason_t get_reset_reason(soc_reset_reason_t rtc_reset_reason, esp_reset_reason_t reset_reason_hint)
|
||||
{
|
||||
switch (rtc_reset_reason) {
|
||||
case RESET_REASON_CHIP_POWER_ON:
|
||||
return ESP_RST_POWERON;
|
||||
|
||||
case RESET_REASON_CPU0_SW:
|
||||
case RESET_REASON_CORE_SW:
|
||||
if (reset_reason_hint == ESP_RST_PANIC ||
|
||||
reset_reason_hint == ESP_RST_BROWNOUT ||
|
||||
reset_reason_hint == ESP_RST_TASK_WDT ||
|
||||
reset_reason_hint == ESP_RST_INT_WDT) {
|
||||
return reset_reason_hint;
|
||||
}
|
||||
return ESP_RST_SW;
|
||||
|
||||
case RESET_REASON_CORE_DEEP_SLEEP:
|
||||
return ESP_RST_DEEPSLEEP;
|
||||
|
||||
case RESET_REASON_CORE_MWDT0:
|
||||
return ESP_RST_TASK_WDT;
|
||||
|
||||
case RESET_REASON_CORE_MWDT1:
|
||||
return ESP_RST_INT_WDT;
|
||||
|
||||
case RESET_REASON_CORE_RTC_WDT:
|
||||
case RESET_REASON_SYS_RTC_WDT:
|
||||
case RESET_REASON_SYS_SUPER_WDT:
|
||||
case RESET_REASON_CPU0_RTC_WDT:
|
||||
case RESET_REASON_CPU0_MWDT0:
|
||||
case RESET_REASON_CPU0_MWDT1:
|
||||
return ESP_RST_WDT;
|
||||
|
||||
case RESET_REASON_SYS_BROWN_OUT:
|
||||
return ESP_RST_BROWNOUT;
|
||||
|
||||
case RESET_REASON_CORE_USB_UART:
|
||||
case RESET_REASON_CORE_USB_JTAG:
|
||||
return ESP_RST_USB;
|
||||
|
||||
default:
|
||||
return ESP_RST_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static void __attribute__((constructor)) esp_reset_reason_init(void)
|
||||
{
|
||||
esp_reset_reason_t hint = esp_reset_reason_get_hint();
|
||||
s_reset_reason = get_reset_reason(esp_rom_get_reset_reason(PRO_CPU_NUM), hint);
|
||||
if (hint != ESP_RST_UNKNOWN) {
|
||||
esp_reset_reason_clear_hint();
|
||||
}
|
||||
}
|
||||
|
||||
esp_reset_reason_t esp_reset_reason(void)
|
||||
{
|
||||
return s_reset_reason;
|
||||
}
|
||||
|
||||
/* Reset reason hint is stored in RTC_RESET_CAUSE_REG, a.k.a. RTC_CNTL_STORE6_REG,
|
||||
* a.k.a. RTC_ENTRY_ADDR_REG. It is safe to use this register both for the
|
||||
* deep sleep wake stub entry address and for reset reason hint, since wake stub
|
||||
* is only used for deep sleep reset, and in this case the reason provided by
|
||||
* esp_rom_get_reset_reason is unambiguous.
|
||||
*
|
||||
* Same layout is used as for RTC_APB_FREQ_REG (a.k.a. RTC_CNTL_STORE5_REG):
|
||||
* the value is replicated in low and high half-words. In addition to that,
|
||||
* MSB is set to 1, which doesn't happen when RTC_CNTL_STORE6_REG contains
|
||||
* deep sleep wake stub address.
|
||||
*/
|
||||
|
||||
#define RST_REASON_BIT 0x80000000
|
||||
#define RST_REASON_MASK 0x7FFF
|
||||
#define RST_REASON_SHIFT 16
|
||||
|
||||
/* in IRAM, can be called from panic handler */
|
||||
void IRAM_ATTR esp_reset_reason_set_hint(esp_reset_reason_t hint)
|
||||
{
|
||||
assert((hint & (~RST_REASON_MASK)) == 0);
|
||||
uint32_t val = hint | (hint << RST_REASON_SHIFT) | RST_REASON_BIT;
|
||||
REG_WRITE(RTC_RESET_CAUSE_REG, val);
|
||||
}
|
||||
|
||||
/* in IRAM, can be called from panic handler */
|
||||
esp_reset_reason_t esp_reset_reason_get_hint(void)
|
||||
{
|
||||
uint32_t reset_reason_hint = REG_READ(RTC_RESET_CAUSE_REG);
|
||||
uint32_t high = (reset_reason_hint >> RST_REASON_SHIFT) & RST_REASON_MASK;
|
||||
uint32_t low = reset_reason_hint & RST_REASON_MASK;
|
||||
if ((reset_reason_hint & RST_REASON_BIT) == 0 || high != low) {
|
||||
return ESP_RST_UNKNOWN;
|
||||
}
|
||||
return (esp_reset_reason_t) low;
|
||||
}
|
||||
static inline void esp_reset_reason_clear_hint(void)
|
||||
{
|
||||
REG_WRITE(RTC_RESET_CAUSE_REG, 0);
|
||||
}
|
122
components/esp_system/port/soc/esp32c5/system_internal.c
Normal file
122
components/esp_system/port/soc/esp32c5/system_internal.c
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_private/system_internal.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "riscv/rv_utils.h"
|
||||
#include "esp_rom_uart.h"
|
||||
#include "soc/gpio_reg.h"
|
||||
#include "esp_cpu.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "esp_private/rtc_clk.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "soc/uart_reg.h"
|
||||
#include "hal/clk_tree_ll.h"
|
||||
#include "hal/wdt_hal.h"
|
||||
#include "hal/modem_syscon_ll.h"
|
||||
#include "hal/modem_lpcon_ll.h"
|
||||
#include "esp_private/cache_err_int.h"
|
||||
|
||||
#include "esp32c5/rom/cache.h"
|
||||
#include "esp32c5/rom/rtc.h"
|
||||
#include "soc/pcr_reg.h"
|
||||
|
||||
void IRAM_ATTR esp_system_reset_modules_on_exit(void)
|
||||
{
|
||||
// Flush any data left in UART FIFOs before reset the UART peripheral
|
||||
esp_rom_uart_tx_wait_idle(0);
|
||||
esp_rom_uart_tx_wait_idle(1);
|
||||
|
||||
modem_syscon_ll_reset_all(&MODEM_SYSCON);
|
||||
modem_lpcon_ll_reset_all(&MODEM_LPCON);
|
||||
|
||||
// Set SPI Flash Freq to 40M
|
||||
clk_ll_mspi_fast_sel_clk(MSPI_CLK_SRC_XTAL);
|
||||
clk_ll_mspi_fast_set_divider(1);
|
||||
|
||||
// Set Peripheral clk rst
|
||||
SET_PERI_REG_MASK(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN);
|
||||
SET_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN);
|
||||
SET_PERI_REG_MASK(PCR_UART0_CONF_REG, PCR_UART0_RST_EN);
|
||||
SET_PERI_REG_MASK(PCR_UART1_CONF_REG, PCR_UART1_RST_EN);
|
||||
SET_PERI_REG_MASK(PCR_SYSTIMER_CONF_REG, PCR_SYSTIMER_RST_EN);
|
||||
SET_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN);
|
||||
SET_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN);
|
||||
SET_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN);
|
||||
SET_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN);
|
||||
|
||||
// Clear Peripheral clk rst
|
||||
CLEAR_PERI_REG_MASK(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN);
|
||||
CLEAR_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN);
|
||||
CLEAR_PERI_REG_MASK(PCR_UART0_CONF_REG, PCR_UART0_RST_EN);
|
||||
CLEAR_PERI_REG_MASK(PCR_UART1_CONF_REG, PCR_UART1_RST_EN);
|
||||
CLEAR_PERI_REG_MASK(PCR_SYSTIMER_CONF_REG, PCR_SYSTIMER_RST_EN);
|
||||
CLEAR_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN);
|
||||
CLEAR_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN);
|
||||
CLEAR_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN);
|
||||
CLEAR_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN);
|
||||
}
|
||||
|
||||
/* "inner" restart function for after RTOS, interrupts & anything else on this
|
||||
* core are already stopped. Stalls other core, resets hardware,
|
||||
* triggers restart.
|
||||
*/
|
||||
void IRAM_ATTR esp_restart_noos(void)
|
||||
{
|
||||
// Disable interrupts
|
||||
rv_utils_intr_global_disable();
|
||||
// Enable RTC watchdog for 1 second
|
||||
wdt_hal_context_t rtc_wdt_ctx;
|
||||
wdt_hal_init(&rtc_wdt_ctx, WDT_RWDT, 0, false);
|
||||
uint32_t stage_timeout_ticks = (uint32_t)(1000ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_SYSTEM);
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE1, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
|
||||
//Enable flash boot mode so that flash booting after restart is protected by the RTC WDT.
|
||||
wdt_hal_set_flashboot_en(&rtc_wdt_ctx, true);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
|
||||
// C5 is a single core SoC, no need to reset and stall the other CPU
|
||||
|
||||
// Disable TG0/TG1 watchdogs
|
||||
wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
|
||||
wdt_hal_write_protect_disable(&wdt0_context);
|
||||
wdt_hal_disable(&wdt0_context);
|
||||
wdt_hal_write_protect_enable(&wdt0_context);
|
||||
|
||||
wdt_hal_context_t wdt1_context = {.inst = WDT_MWDT1, .mwdt_dev = &TIMERG1};
|
||||
wdt_hal_write_protect_disable(&wdt1_context);
|
||||
wdt_hal_disable(&wdt1_context);
|
||||
wdt_hal_write_protect_enable(&wdt1_context);
|
||||
|
||||
// Disable cache
|
||||
Cache_Disable_ICache();
|
||||
|
||||
// Reset wifi/bluetooth/ethernet/sdio (bb/mac)
|
||||
// Moved to module internal
|
||||
// SET_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG,
|
||||
// SYSTEM_SDIO_RST | // SDIO_HINF_HINF_SDIO_RST?
|
||||
// SYSTEM_EMAC_RST | SYSTEM_MACPWR_RST | // TODO: IDF-5325 (ethernet)
|
||||
// REG_WRITE(SYSTEM_CORE_RST_EN_REG, 0);
|
||||
|
||||
esp_system_reset_modules_on_exit();
|
||||
|
||||
// Set CPU back to XTAL source, same as hard reset, but keep BBPLL on so that USB Serial JTAG can log at 1st stage bootloader.
|
||||
#if !CONFIG_IDF_ENV_FPGA
|
||||
rtc_clk_cpu_set_to_default_config();
|
||||
#endif
|
||||
|
||||
// Reset PRO CPU
|
||||
esp_rom_software_reset_cpu(0);
|
||||
while (true) {
|
||||
;
|
||||
}
|
||||
}
|
@ -29,6 +29,8 @@
|
||||
#include "esp32h2/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32P4
|
||||
#include "esp32p4/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C5
|
||||
#include "esp32c5/rtc.h"
|
||||
#endif
|
||||
|
||||
#include "esp_private/startup_internal.h"
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include "esp32c2/rom/ets_sys.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#include "esp32c6/rom/ets_sys.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C5
|
||||
#include "esp32c5/rom/ets_sys.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#include "esp32h2/rom/ets_sys.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32P4
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "esp32c2/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#include "esp32c6/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C5
|
||||
#include "esp32c5/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#include "esp32h2/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32P4
|
||||
|
Loading…
x
Reference in New Issue
Block a user