drivers: spi: esp32: Fix clock initialization

The clock should be initialised only once at the
drivers init function.

Check wether the subsys needs to be disabled in
peripheral initialization according to reset reason
in clock control.

Signed-off-by: Lucas Tamborrino <lucas.tamborrino@espressif.com>
This commit is contained in:
Lucas Tamborrino 2024-06-03 14:17:50 -03:00 committed by Maureen Helm
parent 54cb89b8d7
commit 604ea9243a
2 changed files with 297 additions and 413 deletions

View File

@ -53,6 +53,284 @@
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(clock_control, CONFIG_CLOCK_CONTROL_LOG_LEVEL);
static bool reset_reason_is_cpu_reset(void)
{
soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0);
if ((rst_reason == RESET_REASON_CPU0_MWDT0 || rst_reason == RESET_REASON_CPU0_SW ||
rst_reason == RESET_REASON_CPU0_RTC_WDT
#if !defined(CONFIG_SOC_SERIES_ESP32)
|| rst_reason == RESET_REASON_CPU0_MWDT1
#endif
)) {
return true;
}
return false;
}
static void esp32_clock_perip_init(void)
{
uint32_t common_perip_clk;
uint32_t hwcrypto_perip_clk;
uint32_t wifi_bt_sdio_clk;
#if !defined(CONFIG_SOC_SERIES_ESP32)
uint32_t common_perip_clk1;
#endif
/* For reason that only reset CPU, do not disable the clocks
* that have been enabled before reset.
*/
if (reset_reason_is_cpu_reset()) {
#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3))
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 /* CONFIG_SOC_SERIES_ESP32 || CONFIG_SOC_SERIES_ESP32S2 */
common_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG);
hwcrypto_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERI_CLK_EN_REG);
wifi_bt_sdio_clk = ~DPORT_READ_PERI_REG(DPORT_WIFI_CLK_EN_REG);
#endif
#if defined(CONFIG_SOC_SERIES_ESP32S2)
hwcrypto_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN1_REG);
#endif
} else {
common_perip_clk =
#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3))
SYSTEM_WDG_CLK_EN |
SYSTEM_I2S0_CLK_EN |
#if ESP_CONSOLE_UART_NUM != 0
SYSTEM_UART_CLK_EN |
#endif
#if ESP_CONSOLE_UART_NUM != 1
SYSTEM_UART1_CLK_EN |
#endif
#if defined(CONFIG_SOC_SERIES_ESP32S3)
#if ESP_CONSOLE_UART_NUM != 2
SYSTEM_UART2_CLK_EN |
#endif
SYSTEM_USB_CLK_EN |
SYSTEM_PCNT_CLK_EN |
SYSTEM_LEDC_CLK_EN |
SYSTEM_PWM0_CLK_EN |
SYSTEM_PWM1_CLK_EN |
SYSTEM_PWM2_CLK_EN |
SYSTEM_PWM3_CLK_EN |
#endif /* CONFIG_SOC_SERIES_ESP32S3 */
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;
#else /* CONFIG_SOC_SERIES_ESP32 || CONFIG_SOC_SERIES_ESP32S2 */
DPORT_WDG_CLK_EN |
DPORT_PCNT_CLK_EN |
DPORT_LEDC_CLK_EN |
DPORT_TIMERGROUP1_CLK_EN |
DPORT_PWM0_CLK_EN |
DPORT_TWAI_CLK_EN |
DPORT_PWM1_CLK_EN |
DPORT_PWM2_CLK_EN |
#if defined(CONFIG_SOC_SERIES_ESP32S2)
DPORT_I2S0_CLK_EN |
DPORT_SPI2_CLK_EN |
DPORT_I2C_EXT0_CLK_EN |
DPORT_UHCI0_CLK_EN |
DPORT_RMT_CLK_EN |
DPORT_SPI3_CLK_EN |
DPORT_I2S1_CLK_EN |
DPORT_SPI2_DMA_CLK_EN |
DPORT_SPI3_DMA_CLK_EN |
#endif /* CONFIG_SOC_SERIES_ESP32S2 */
DPORT_PWM3_CLK_EN;
#endif /* CONFIG_SOC_SERIES_ESP32C3 || CONFIG_SOC_SERIES_ESP32S3 */
#if !defined(CONFIG_SOC_SERIES_ESP32)
common_perip_clk1 = 0;
#endif
hwcrypto_perip_clk =
#if defined(CONFIG_SOC_SERIES_ESP32)
DPORT_PERI_EN_AES |
DPORT_PERI_EN_SHA |
DPORT_PERI_EN_RSA |
DPORT_PERI_EN_SECUREBOOT;
#endif /* CONFIG_SOC_SERIES_ESP32 */
#if defined(CONFIG_SOC_SERIES_ESP32S2)
DPORT_CRYPTO_AES_CLK_EN |
DPORT_CRYPTO_SHA_CLK_EN |
DPORT_CRYPTO_RSA_CLK_EN;
#endif /* CONFIG_SOC_SERIES_ESP32S2 */
#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3))
SYSTEM_CRYPTO_AES_CLK_EN |
SYSTEM_CRYPTO_SHA_CLK_EN |
SYSTEM_CRYPTO_RSA_CLK_EN;
#endif /* CONFIG_SOC_SERIES_ESP32C3 || CONFIG_SOC_SERIES_ESP32S3 */
wifi_bt_sdio_clk =
#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3))
SYSTEM_WIFI_CLK_WIFI_EN |
SYSTEM_WIFI_CLK_BT_EN_M |
SYSTEM_WIFI_CLK_I2C_CLK_EN |
#if defined(CONFIG_SOC_SERIES_ESP32S3)
SYSTEM_WIFI_CLK_SDIO_HOST_EN |
#endif /* CONFIG_SOC_SERIES_ESP32S3 */
SYSTEM_WIFI_CLK_UNUSED_BIT12;
#else /* CONFIG_SOC_SERIES_ESP32 || CONFIG_SOC_SERIES_ESP32S2 */
DPORT_WIFI_CLK_WIFI_EN |
DPORT_WIFI_CLK_BT_EN_M |
DPORT_WIFI_CLK_UNUSED_BIT5 |
DPORT_WIFI_CLK_UNUSED_BIT12 |
DPORT_WIFI_CLK_SDIOSLAVE_EN |
DPORT_WIFI_CLK_SDIO_HOST_EN |
DPORT_WIFI_CLK_EMAC_EN;
#endif /* CONFIG_SOC_SERIES_ESP32C3 */
}
/* Reset peripherals like I2C, SPI, UART, I2S and bring them to known state */
common_perip_clk |=
#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3))
SYSTEM_I2S0_CLK_EN |
#if ESP_CONSOLE_UART_NUM != 0
SYSTEM_UART_CLK_EN |
#endif
#if ESP_CONSOLE_UART_NUM != 1
SYSTEM_UART1_CLK_EN |
#endif
#if defined(CONFIG_SOC_SERIES_ESP32S3)
#if ESP_CONSOLE_UART_NUM != 2
SYSTEM_UART2_CLK_EN |
#endif
SYSTEM_USB_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;
#else
DPORT_I2S0_CLK_EN |
DPORT_SPI2_CLK_EN |
DPORT_I2C_EXT0_CLK_EN |
DPORT_UHCI0_CLK_EN |
DPORT_RMT_CLK_EN |
DPORT_UHCI1_CLK_EN |
DPORT_SPI3_CLK_EN |
DPORT_I2C_EXT1_CLK_EN |
#if ESP_CONSOLE_UART_NUM != 0
DPORT_UART_CLK_EN |
#endif
#if ESP_CONSOLE_UART_NUM != 1
DPORT_UART1_CLK_EN |
#endif
#if defined(CONFIG_SOC_SERIES_ESP32)
DPORT_SPI_DMA_CLK_EN |
#if ESP_CONSOLE_UART_NUM != 2
DPORT_UART2_CLK_EN |
#endif
#endif /* CONFIG_SOC_SERIES_ESP32 */
#if defined(CONFIG_SOC_SERIES_ESP32S2)
DPORT_USB_CLK_EN |
DPORT_SPI2_DMA_CLK_EN |
DPORT_SPI3_DMA_CLK_EN |
#endif /* CONFIG_SOC_SERIES_ESP32S2 */
DPORT_I2S1_CLK_EN;
#endif /* CONFIG_SOC_SERIES_ESP32C3 */
#if !defined(CONFIG_SOC_SERIES_ESP32)
common_perip_clk1 = 0;
#endif
#if defined(CONFIG_SOC_SERIES_ESP32)
common_perip_clk &= ~DPORT_SPI01_CLK_EN;
#if defined(CONFIG_SPIRAM_SPEED_80M)
/*
* 80MHz SPIRAM uses SPI2/SPI3 as well; it's initialized before this is called. Because it
* is used in a weird mode where clock to the peripheral is disabled but reset is also
* disabled, it 'hangs' in a state where it outputs a continuous 80MHz signal. Mask its bit
* here because we should not modify that state, regardless of what we calculated earlier.
*/
common_perip_clk &= ~DPORT_SPI2_CLK_EN;
common_perip_clk &= ~DPORT_SPI3_CLK_EN;
#endif
#endif /* CONFIG_SOC_SERIES_ESP32 */
/* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock,
* the current is not reduced when disable I2S clock.
*/
#if defined(CONFIG_SOC_SERIES_ESP32)
DPORT_SET_PERI_REG_MASK(I2S_CLKM_CONF_REG(0), I2S_CLKA_ENA);
DPORT_SET_PERI_REG_MASK(I2S_CLKM_CONF_REG(1), I2S_CLKA_ENA);
#endif /* CONFIG_SOC_SERIES_ESP32 */
#if defined(CONFIG_SOC_SERIES_ESP32S2)
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);
#endif /* CONFIG_SOC_SERIES_ESP32S2 */
/* Disable some peripheral clocks. */
#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3))
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);
#else /* CONFIG_SOC_SERIES_ESP32 || CONFIG_SOC_SERIES_ESP32S2 */
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, common_perip_clk);
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, common_perip_clk);
#endif /* CONFIG_SOC_SERIES_ESP32C3 || CONFIG_SOC_SERIES_ESP32S3 */
/* Disable hardware crypto clocks. */
#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3))
CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN1_REG, hwcrypto_perip_clk);
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, hwcrypto_perip_clk);
#else /* CONFIG_SOC_SERIES_ESP32 || CONFIG_SOC_SERIES_ESP32S2 */
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERI_CLK_EN_REG, hwcrypto_perip_clk);
DPORT_SET_PERI_REG_MASK(DPORT_PERI_RST_EN_REG, hwcrypto_perip_clk);
#endif /* CONFIG_SOC_SERIES_ESP32C3 || CONFIG_SOC_SERIES_ESP32S3 */
#if defined(CONFIG_SOC_SERIES_ESP32S3)
/* Force clear backup dma reset signal. This is a fix to the backup dma
* implementation in the ROM, the reset signal was not cleared when the
* backup dma was started, which caused the backup dma operation to fail.
*/
CLEAR_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_PERI_BACKUP_RST);
#endif /* CONFIG_SOC_SERIES_ESP32S3 */
/* Disable WiFi/BT/SDIO clocks. */
#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3))
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);
#else /* CONFIG_SOC_SERIES_ESP32 || CONFIG_SOC_SERIES_ESP32S2 */
DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, wifi_bt_sdio_clk);
#endif /* CONFIG_SOC_SERIES_ESP32C3 || CONFIG_SOC_SERIES_ESP32S3 */
#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3))
/* 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);
#endif
/* Enable RNG clock. */
periph_module_enable(PERIPH_RNG_MODULE);
#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3))
periph_module_enable(PERIPH_TIMG0_MODULE);
#endif
}
static enum clock_control_status clock_control_esp32_get_status(const struct device *dev,
clock_control_subsys_t sys)
{
@ -70,7 +348,7 @@ static int clock_control_esp32_on(const struct device *dev, clock_control_subsys
{
enum clock_control_status status = clock_control_esp32_get_status(dev, sys);
if (status == CLOCK_CONTROL_STATUS_ON) {
if (status == CLOCK_CONTROL_STATUS_ON && !reset_reason_is_cpu_reset()) {
return -EALREADY;
}
@ -109,405 +387,6 @@ static int clock_control_esp32_get_rate(const struct device *dev, clock_control_
return 0;
}
#if defined(CONFIG_SOC_SERIES_ESP32)
static void esp32_clock_perip_init(void)
{
uint32_t common_perip_clk;
uint32_t hwcrypto_perip_clk;
uint32_t wifi_bt_sdio_clk;
#if !CONFIG_SMP
soc_reset_reason_t rst_reas[1];
#else
soc_reset_reason_t rst_reas[2];
#endif
rst_reas[0] = esp_rom_get_reset_reason(0);
#if CONFIG_SMP
rst_reas[1] = esp_rom_get_reset_reason(1);
#endif
/* For reason that only reset CPU, do not disable the clocks
* that have been enabled before reset.
*/
if ((rst_reas[0] == RESET_REASON_CPU0_MWDT0 || rst_reas[0] == RESET_REASON_CPU0_SW ||
rst_reas[0] == RESET_REASON_CPU0_RTC_WDT)
#if CONFIG_SMP
|| (rst_reas[1] == RESET_REASON_CPU1_MWDT1 || rst_reas[1] == RESET_REASON_CPU1_SW ||
rst_reas[1] == RESET_REASON_CPU1_RTC_WDT)
#endif
) {
common_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG);
hwcrypto_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERI_CLK_EN_REG);
wifi_bt_sdio_clk = ~DPORT_READ_PERI_REG(DPORT_WIFI_CLK_EN_REG);
} else {
common_perip_clk = DPORT_WDG_CLK_EN |
DPORT_PCNT_CLK_EN |
DPORT_LEDC_CLK_EN |
DPORT_TIMERGROUP1_CLK_EN |
DPORT_PWM0_CLK_EN |
DPORT_TWAI_CLK_EN |
DPORT_PWM1_CLK_EN |
DPORT_PWM2_CLK_EN |
DPORT_PWM3_CLK_EN;
hwcrypto_perip_clk = DPORT_PERI_EN_AES |
DPORT_PERI_EN_SHA |
DPORT_PERI_EN_RSA |
DPORT_PERI_EN_SECUREBOOT;
wifi_bt_sdio_clk = DPORT_WIFI_CLK_WIFI_EN |
DPORT_WIFI_CLK_BT_EN_M |
DPORT_WIFI_CLK_UNUSED_BIT5 |
DPORT_WIFI_CLK_UNUSED_BIT12 |
DPORT_WIFI_CLK_SDIOSLAVE_EN |
DPORT_WIFI_CLK_SDIO_HOST_EN |
DPORT_WIFI_CLK_EMAC_EN;
}
/* Reset peripherals like I2C, SPI, UART, I2S and bring them to known state */
common_perip_clk |= DPORT_I2S0_CLK_EN |
DPORT_UART_CLK_EN |
DPORT_SPI2_CLK_EN |
DPORT_I2C_EXT0_CLK_EN |
DPORT_UHCI0_CLK_EN |
DPORT_RMT_CLK_EN |
DPORT_UHCI1_CLK_EN |
DPORT_SPI3_CLK_EN |
DPORT_I2C_EXT1_CLK_EN |
DPORT_I2S1_CLK_EN |
DPORT_SPI_DMA_CLK_EN;
common_perip_clk &= ~DPORT_SPI01_CLK_EN;
common_perip_clk &= ~DPORT_SPI2_CLK_EN;
common_perip_clk &= ~DPORT_SPI3_CLK_EN;
/* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock,
* the current is not reduced when disable I2S clock.
*/
DPORT_SET_PERI_REG_MASK(I2S_CLKM_CONF_REG(0), I2S_CLKA_ENA);
DPORT_SET_PERI_REG_MASK(I2S_CLKM_CONF_REG(1), I2S_CLKA_ENA);
/* Disable some peripheral clocks. */
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, common_perip_clk);
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, common_perip_clk);
/* Disable hardware crypto clocks. */
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERI_CLK_EN_REG, hwcrypto_perip_clk);
DPORT_SET_PERI_REG_MASK(DPORT_PERI_RST_EN_REG, hwcrypto_perip_clk);
/* Disable WiFi/BT/SDIO clocks. */
DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, wifi_bt_sdio_clk);
/* Enable RNG clock. */
periph_module_enable(PERIPH_RNG_MODULE);
}
#endif /* CONFIG_SOC_SERIES_ESP32 */
#if defined(CONFIG_SOC_SERIES_ESP32S2)
static void esp32_clock_perip_init(void)
{
uint32_t common_perip_clk;
uint32_t hwcrypto_perip_clk;
uint32_t wifi_bt_sdio_clk;
uint32_t common_perip_clk1;
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 = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG);
hwcrypto_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN1_REG);
wifi_bt_sdio_clk = ~DPORT_READ_PERI_REG(DPORT_WIFI_CLK_EN_REG);
} else {
common_perip_clk = DPORT_WDG_CLK_EN |
DPORT_I2S0_CLK_EN |
DPORT_UART1_CLK_EN |
DPORT_SPI2_CLK_EN |
DPORT_I2C_EXT0_CLK_EN |
DPORT_UHCI0_CLK_EN |
DPORT_RMT_CLK_EN |
DPORT_PCNT_CLK_EN |
DPORT_LEDC_CLK_EN |
DPORT_TIMERGROUP1_CLK_EN |
DPORT_SPI3_CLK_EN |
DPORT_PWM0_CLK_EN |
DPORT_TWAI_CLK_EN |
DPORT_PWM1_CLK_EN |
DPORT_I2S1_CLK_EN |
DPORT_SPI2_DMA_CLK_EN |
DPORT_SPI3_DMA_CLK_EN |
DPORT_PWM2_CLK_EN |
DPORT_PWM3_CLK_EN;
common_perip_clk1 = 0;
hwcrypto_perip_clk = DPORT_CRYPTO_AES_CLK_EN |
DPORT_CRYPTO_SHA_CLK_EN |
DPORT_CRYPTO_RSA_CLK_EN;
wifi_bt_sdio_clk = DPORT_WIFI_CLK_WIFI_EN |
DPORT_WIFI_CLK_BT_EN_M |
DPORT_WIFI_CLK_UNUSED_BIT5 |
DPORT_WIFI_CLK_UNUSED_BIT12 |
DPORT_WIFI_CLK_SDIOSLAVE_EN |
DPORT_WIFI_CLK_SDIO_HOST_EN |
DPORT_WIFI_CLK_EMAC_EN;
}
/* Reset peripherals like I2C, SPI, UART, I2S and bring them to known state */
common_perip_clk |= DPORT_I2S0_CLK_EN |
DPORT_UART1_CLK_EN |
DPORT_USB_CLK_EN |
DPORT_SPI2_CLK_EN |
DPORT_I2C_EXT0_CLK_EN |
DPORT_UHCI0_CLK_EN |
DPORT_RMT_CLK_EN |
DPORT_UHCI1_CLK_EN |
DPORT_SPI3_CLK_EN |
DPORT_I2C_EXT1_CLK_EN |
DPORT_I2S1_CLK_EN |
DPORT_SPI2_DMA_CLK_EN |
DPORT_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.
*/
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. */
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, common_perip_clk);
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, common_perip_clk);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN1_REG, common_perip_clk1);
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, common_perip_clk1);
/* Disable hardware crypto clocks. */
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN1_REG, hwcrypto_perip_clk);
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, hwcrypto_perip_clk);
/* Disable WiFi/BT/SDIO clocks. */
DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, wifi_bt_sdio_clk);
/* Enable WiFi MAC and POWER clocks */
DPORT_SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_EN);
/* Set WiFi light sleep clock source to RTC slow clock */
DPORT_REG_SET_FIELD(DPORT_BT_LPCK_DIV_INT_REG, DPORT_BT_LPCK_DIV_NUM, 0);
DPORT_CLEAR_PERI_REG_MASK(DPORT_BT_LPCK_DIV_FRAC_REG, DPORT_LPCLK_SEL_8M);
DPORT_SET_PERI_REG_MASK(DPORT_BT_LPCK_DIV_FRAC_REG, DPORT_LPCLK_SEL_RTC_SLOW);
/* Enable RNG clock. */
periph_module_enable(PERIPH_RNG_MODULE);
}
#endif /* CONFIG_SOC_SERIES_ESP32S2 */
#if defined(CONFIG_SOC_SERIES_ESP32S3)
static void esp32_clock_perip_init(void)
{
#if defined(CONFIG_SOC_ESP32S3_APPCPU)
/* skip APPCPU configuration */
return;
#endif
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 |
SYSTEM_UART1_CLK_EN |
SYSTEM_UART2_CLK_EN |
SYSTEM_USB_CLK_EN |
SYSTEM_SPI2_CLK_EN |
SYSTEM_I2C_EXT0_CLK_EN |
SYSTEM_UHCI0_CLK_EN |
SYSTEM_RMT_CLK_EN |
SYSTEM_PCNT_CLK_EN |
SYSTEM_LEDC_CLK_EN |
SYSTEM_TIMERGROUP1_CLK_EN |
SYSTEM_SPI3_CLK_EN |
SYSTEM_SPI4_CLK_EN |
SYSTEM_PWM0_CLK_EN |
SYSTEM_TWAI_CLK_EN |
SYSTEM_PWM1_CLK_EN |
SYSTEM_I2S1_CLK_EN |
SYSTEM_SPI2_DMA_CLK_EN |
SYSTEM_SPI3_DMA_CLK_EN |
SYSTEM_PWM2_CLK_EN |
SYSTEM_PWM3_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_I2C_CLK_EN |
SYSTEM_WIFI_CLK_UNUSED_BIT12 |
SYSTEM_WIFI_CLK_SDIO_HOST_EN;
}
/* Reset peripherals like I2C, SPI, UART, I2S and bring them to known state */
common_perip_clk |= SYSTEM_I2S0_CLK_EN |
SYSTEM_UART1_CLK_EN |
SYSTEM_UART2_CLK_EN |
SYSTEM_USB_CLK_EN |
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;
/* 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);
/* Enable TimerGroup 0 clock to ensure its reference counter will never
* be decremented to 0 during normal operation and preventing it from
* being disabled.
* If the TimerGroup 0 clock is disabled and then reenabled, the watchdog
* registers (Flashboot protection included) will be reenabled, and some
* seconds later, will trigger an unintended reset.
*/
periph_module_enable(PERIPH_TIMG0_MODULE);
}
#endif /* CONFIG_SOC_SERIES_ESP32S3 */
#if defined(CONFIG_SOC_SERIES_ESP32C3)
static void esp32_clock_perip_init(void)
{
uint32_t common_perip_clk;
uint32_t hwcrypto_perip_clk;
uint32_t wifi_bt_sdio_clk;
uint32_t common_perip_clk1;
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 |
SYSTEM_UART1_CLK_EN |
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_I2C_CLK_EN |
SYSTEM_WIFI_CLK_UNUSED_BIT12;
}
/* Reset peripherals like I2C, SPI, UART, I2S and bring them to known state */
common_perip_clk |= SYSTEM_I2S0_CLK_EN |
SYSTEM_UART1_CLK_EN |
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;
/* 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 /* CONFIG_SOC_SERIES_ESP32C3 */
static int esp32_select_rtc_slow_clk(uint8_t slow_clk)
{
soc_rtc_slow_clk_src_t rtc_slow_clk_src = slow_clk & RTC_CNTL_ANA_CLK_RTC_SEL_V;

View File

@ -216,16 +216,34 @@ static int spi_esp32_init(const struct device *dev)
int err;
const struct spi_esp32_config *cfg = dev->config;
struct spi_esp32_data *data = dev->data;
spi_hal_context_t *hal = &data->hal;
if (!cfg->clock_dev) {
return -EINVAL;
}
if (!device_is_ready(cfg->clock_dev)) {
LOG_ERR("clock control device not ready");
return -ENODEV;
}
/* Enables SPI peripheral */
err = clock_control_on(cfg->clock_dev, cfg->clock_subsys);
if (err < 0) {
LOG_ERR("Error enabling SPI clock");
return err;
}
spi_ll_master_init(hal->hw);
if (cfg->dma_enabled) {
spi_esp32_init_dma(dev);
}
#ifdef CONFIG_SPI_ESP32_INTERRUPT
spi_ll_disable_int(cfg->spi);
spi_ll_clear_int_stat(cfg->spi);
data->irq_line = esp_intr_alloc(cfg->irq_source,
0,
(ISR_HANDLER)spi_esp32_isr,
@ -285,19 +303,6 @@ static int IRAM_ATTR spi_esp32_configure(const struct device *dev,
return 0;
}
if (!device_is_ready(cfg->clock_dev)) {
LOG_ERR("clock control device not ready");
return -ENODEV;
}
/* enables SPI peripheral */
if (clock_control_on(cfg->clock_dev, cfg->clock_subsys)) {
LOG_ERR("Could not enable SPI clock");
return -EIO;
}
spi_ll_master_init(hal->hw);
ctx->config = spi_cfg;
if (spi_cfg->operation & SPI_HALF_DUPLEX) {