diff --git a/drivers/clock_control/clock_control_esp32.c b/drivers/clock_control/clock_control_esp32.c index c62402ed665..c239ec199a1 100644 --- a/drivers/clock_control/clock_control_esp32.c +++ b/drivers/clock_control/clock_control_esp32.c @@ -53,6 +53,284 @@ #include 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; diff --git a/drivers/spi/spi_esp32_spim.c b/drivers/spi/spi_esp32_spim.c index d209fd85b04..5bcec47577f 100644 --- a/drivers/spi/spi_esp32_spim.c +++ b/drivers/spi/spi_esp32_spim.c @@ -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) {