Sfoglia il codice sorgente

Merge branch 'feature/esp32c6_ledc_support' into 'master'

ledc: Add basic support for esp32c6

Closes IDF-5328

See merge request espressif/esp-idf!21387
Song Ruo Jing 3 anni fa
parent
commit
6f4d1ea436
33 ha cambiato i file con 811 aggiunte e 133 eliminazioni
  1. 6 2
      components/driver/ledc.c
  2. 3 3
      components/driver/test/test_ledc.c
  3. 15 9
      components/esp_hw_support/clk_ctrl_os.c
  4. 6 6
      components/esp_hw_support/include/clk_ctrl_os.h
  5. 553 0
      components/hal/esp32c6/include/hal/ledc_ll.h
  6. 25 0
      components/hal/include/hal/ledc_hal.h
  7. 2 2
      components/hal/include/hal/ledc_types.h
  8. 17 13
      components/hal/ledc_hal_iram.c
  9. 9 1
      components/soc/esp32/include/soc/Kconfig.soc_caps.in
  10. 3 1
      components/soc/esp32/include/soc/soc_caps.h
  11. 9 1
      components/soc/esp32c2/include/soc/Kconfig.soc_caps.in
  12. 3 1
      components/soc/esp32c2/include/soc/soc_caps.h
  13. 9 1
      components/soc/esp32c3/include/soc/Kconfig.soc_caps.in
  14. 7 5
      components/soc/esp32c3/include/soc/soc_caps.h
  15. 0 1
      components/soc/esp32c6/CMakeLists.txt
  16. 15 3
      components/soc/esp32c6/include/soc/Kconfig.soc_caps.in
  17. 2 2
      components/soc/esp32c6/include/soc/rtc.h
  18. 10 7
      components/soc/esp32c6/include/soc/soc_caps.h
  19. 7 3
      components/soc/esp32h2/include/soc/Kconfig.soc_caps.in
  20. 6 5
      components/soc/esp32h2/include/soc/soc_caps.h
  21. 5 1
      components/soc/esp32h4/include/soc/Kconfig.soc_caps.in
  22. 6 5
      components/soc/esp32h4/include/soc/soc_caps.h
  23. 9 1
      components/soc/esp32s2/include/soc/Kconfig.soc_caps.in
  24. 3 1
      components/soc/esp32s2/include/soc/soc_caps.h
  25. 28 20
      components/soc/esp32s3/include/soc/Kconfig.soc_caps.in
  26. 0 21
      components/soc/esp32s3/include/soc/ledc_caps.h
  27. 7 1
      components/soc/esp32s3/include/soc/soc_caps.h
  28. 20 1
      docs/en/api-reference/peripherals/ledc.rst
  29. 20 1
      docs/zh_CN/api-reference/peripherals/ledc.rst
  30. 2 10
      examples/peripherals/.build-test-rules.yml
  31. 2 2
      examples/peripherals/ledc/ledc_basic/README.md
  32. 2 2
      examples/peripherals/ledc/ledc_fade/README.md
  33. 0 1
      tools/ci/check_copyright_ignore.txt

+ 6 - 2
components/driver/ledc.c

@@ -101,8 +101,8 @@ static bool ledc_slow_clk_calibrate(void)
 {
     if (periph_rtc_dig_clk8m_enable()) {
         s_ledc_slow_clk_8M = periph_rtc_dig_clk8m_get_freq();
-#if !SOC_CLK_RC_FAST_D256_SUPPORTED
-        /* Workaround: CLK8M calibration cannot be performed if there is no d256 div clk, we can only use its theoretic freq */
+#if !SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
+        /* Workaround: CLK8M calibration cannot be performed, we can only use its theoretic freq */
         ESP_LOGD(LEDC_TAG, "Calibration cannot be performed, approximate CLK8M_CLK : %"PRIu32" Hz", s_ledc_slow_clk_8M);
 #else
         ESP_LOGD(LEDC_TAG, "Calibrate CLK8M_CLK : %"PRIu32" Hz", s_ledc_slow_clk_8M);
@@ -253,6 +253,10 @@ int duty_val, ledc_duty_direction_t duty_direction, uint32_t duty_num, uint32_t
     ledc_hal_set_duty_num(&(p_ledc_obj[speed_mode]->ledc_hal), channel, duty_num);
     ledc_hal_set_duty_cycle(&(p_ledc_obj[speed_mode]->ledc_hal), channel, duty_cycle);
     ledc_hal_set_duty_scale(&(p_ledc_obj[speed_mode]->ledc_hal), channel, duty_scale);
+#if SOC_LEDC_GAMMA_FADE_RANGE_MAX > 1
+    ledc_hal_set_duty_range(&(p_ledc_obj[speed_mode]->ledc_hal), channel, 0);
+    ledc_hal_set_range_number(&(p_ledc_obj[speed_mode]->ledc_hal), channel, 1);
+#endif
     ledc_ls_channel_update(speed_mode, channel);
     return ESP_OK;
 }

+ 3 - 3
components/driver/test/test_ledc.c

@@ -24,7 +24,6 @@
 #include "soc/io_mux_reg.h"
 #include "esp_system.h"
 #include "esp_timer.h"
-#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6)
 #include "driver/ledc.h"
 #include "hal/ledc_ll.h"
 #include "driver/gpio.h"
@@ -473,7 +472,7 @@ static void timer_frequency_test(ledc_channel_t channel, ledc_timer_bit_t timer_
         .duty_resolution = timer_bit,
         .timer_num = timer,
         .freq_hz = 5000,
-        .clk_cfg = LEDC_USE_APB_CLK,
+        .clk_cfg = TEST_DEFAULT_CLK_CFG,
     };
     TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
     TEST_ESP_OK(ledc_timer_config(&ledc_time_config));
@@ -536,8 +535,10 @@ TEST_CASE("LEDC timer select specific clock source", "[ledc]")
     TEST_ESP_OK(ledc_channel_config(&ledc_ch_config));
 
     if (test_speed_mode == LEDC_LOW_SPEED_MODE) {
+#if !CONFIG_IDF_TARGET_ESP32C6 // Temporary. RC_FAST not able to calibrate currently. Can be removed once IDF-5346 done.
         printf("Check LEDC_USE_RTC8M_CLK for a 100Hz signal\n");
         timer_set_clk_src_and_freq_test(test_speed_mode, LEDC_USE_RTC8M_CLK, 10, 100);
+#endif
 #if SOC_LEDC_SUPPORT_XTAL_CLOCK
         printf("Check LEDC_USE_XTAL_CLK for a 400Hz signal\n");
         timer_set_clk_src_and_freq_test(test_speed_mode, LEDC_USE_XTAL_CLK, 13, 400);
@@ -645,4 +646,3 @@ TEST_CASE_MULTIPLE_STAGES("LEDC continue work after software reset", "[ledc]",
                           ledc_cpu_reset_test_second_stage);
 
 #endif // SOC_PCNT_SUPPORTED
-#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32C6)

+ 15 - 9
components/esp_hw_support/clk_ctrl_os.c

@@ -6,13 +6,13 @@
 
 #include <freertos/FreeRTOS.h>
 #include "clk_ctrl_os.h"
+#include "soc/rtc.h"
 #include "esp_check.h"
-#include "sdkconfig.h"
 
 static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED;
 
 static uint8_t s_periph_ref_counts = 0;
-static uint32_t s_rtc_clk_freq = 0; // Frequency of the 8M/256 clock in Hz
+static uint32_t s_rc_fast_freq = 0; // Frequency of the RC_FAST clock in Hz
 #if SOC_CLK_APLL_SUPPORTED
 static const char *TAG = "clk_ctrl_os";
 // Current APLL frequency, in HZ. Zero if APLL is not enabled.
@@ -26,13 +26,19 @@ bool periph_rtc_dig_clk8m_enable(void)
     portENTER_CRITICAL(&periph_spinlock);
     if (s_periph_ref_counts == 0) {
         rtc_dig_clk8m_enable();
+#if SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
 #if SOC_CLK_RC_FAST_D256_SUPPORTED
-        s_rtc_clk_freq = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_8MD256, 100));
-        if (s_rtc_clk_freq == 0) {
+        // If RC_FAST_D256 clock exists, calibration on a slow freq clock is much faster (less slow clock cycles need to wait)
+        s_rc_fast_freq = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_8MD256, 100)) << 8; // f_[rc_fast] = f_[rc_fast_d256] * 256;
+#else
+        // Calibrate directly on the RC_FAST clock requires much more slow clock cycles to get an accurate freq value
+        s_rc_fast_freq = rtc_clk_freq_cal(rtc_clk_cal(RTC_CAL_RC_FAST, 10000));
+#endif
+        if (s_rc_fast_freq == 0) {
             portEXIT_CRITICAL(&periph_spinlock);
             return false;
         }
-#endif
+#endif //SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
     }
     s_periph_ref_counts++;
     portEXIT_CRITICAL(&periph_spinlock);
@@ -41,11 +47,11 @@ bool periph_rtc_dig_clk8m_enable(void)
 
 uint32_t periph_rtc_dig_clk8m_get_freq(void)
 {
-#if !SOC_CLK_RC_FAST_D256_SUPPORTED
-    /* Workaround: CLK8M calibration cannot be performed if there is no d256 div clk, we can only return its theoretic value */
+#if !SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
+    /* Workaround: CLK8M calibration cannot be performed, we can only return its theoretic value */
     return SOC_CLK_RC_FAST_FREQ_APPROX;
 #else
-    return s_rtc_clk_freq * 256;
+    return s_rc_fast_freq;
 #endif
 }
 
@@ -55,7 +61,7 @@ void periph_rtc_dig_clk8m_disable(void)
     assert(s_periph_ref_counts > 0);
     s_periph_ref_counts--;
     if (s_periph_ref_counts == 0) {
-        s_rtc_clk_freq = 0;
+        s_rc_fast_freq = 0;
         rtc_dig_clk8m_disable();
     }
     portEXIT_CRITICAL(&periph_spinlock);

+ 6 - 6
components/esp_hw_support/include/clk_ctrl_os.h

@@ -4,7 +4,7 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-#include "soc/rtc.h"
+#include <stdbool.h>
 #include "soc/soc_caps.h"
 #include "esp_err.h"
 
@@ -13,18 +13,18 @@ extern "C" {
 #endif
 
 /**
- * @brief This function is used to enable the digital 8m rtc clock,
+ * @brief This function is used to enable the digital RC_FAST clock,
  *        to support the peripherals.
  *
  * @note If this function is called a number of times, the `periph_rtc_dig_clk8m_disable`
  *       function needs to be called same times to disable.
  *
- * @return true: success for enable the rtc 8M clock, false: rtc 8M clock enable failed
+ * @return true: success for enable the RC_FAST clock, false: RC_FAST clock enable failed
  */
 bool periph_rtc_dig_clk8m_enable(void);
 
 /**
- * @brief This function is used to disable the rtc digital clock, which should be called
+ * @brief This function is used to disable the digital RC_FAST clock, which should be called
  *        with the `periph_rtc_dig_clk8m_enable` pairedly
  *
  * @note If this function is called a number of times, the `periph_rtc_dig_clk8m_disable`
@@ -33,9 +33,9 @@ bool periph_rtc_dig_clk8m_enable(void);
 void periph_rtc_dig_clk8m_disable(void);
 
 /**
- * @brief This function is used to get the real clock frequency value of the rtc clock
+ * @brief This function is used to get the real clock frequency value of RC_FAST clock
  *
- * @return The real clock value
+ * @return The real clock value, in Hz
  */
 uint32_t periph_rtc_dig_clk8m_get_freq(void);
 

+ 553 - 0
components/hal/esp32c6/include/hal/ledc_ll.h

@@ -0,0 +1,553 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// The LL layer for LEDC register operations.
+// Note that most of the register operations in this layer are non-atomic operations.
+
+#pragma once
+
+#include "hal/ledc_types.h"
+#include "soc/ledc_struct.h"
+#include "soc/ledc_reg.h"
+#include "soc/pcr_struct.h"
+#include "hal/assert.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LEDC_LL_GET_HW()           &LEDC
+
+#define LEDC_LL_DUTY_NUM_MAX       (LEDC_CH0_GAMMA_DUTY_NUM_V)
+#define LEDC_LL_DUTY_CYCLE_MAX     (LEDC_CH0_GAMMA_DUTY_CYCLE_V)
+#define LEDC_LL_DUTY_SCALE_MAX     (LEDC_CH0_GAMMA_SCALE_V)
+#define LEDC_LL_HPOINT_VAL_MAX     (LEDC_HPOINT_CH0_V)
+#define LEDC_LL_FRACTIONAL_BITS    (8)
+#define LEDC_LL_FRACTIONAL_MAX     ((1 << LEDC_LL_FRACTIONAL_BITS) - 1)
+#define LEDC_LL_GLOBAL_CLOCKS { \
+                                LEDC_SLOW_CLK_PLL_DIV, \
+                                LEDC_SLOW_CLK_XTAL, \
+                                LEDC_SLOW_CLK_RTC8M, \
+                              }
+#define LEDC_LL_PLL_DIV_CLK_FREQ   (80 * 1000000) // PLL_80M_CLK: 80MHz
+
+
+/**
+ * @brief Enable LEDC function clock
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param en True to enable, false to disable
+ *
+ * @return None
+ */
+static inline void ledc_ll_enable_clock(ledc_dev_t *hw, bool en)
+{
+    (void)hw;
+    PCR.ledc_sclk_conf.ledc_sclk_en = en;
+}
+
+/**
+ * @brief Set LEDC low speed timer clock
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param slow_clk_sel LEDC low speed timer clock source
+ *
+ * @return None
+ */
+static inline void ledc_ll_set_slow_clk_sel(ledc_dev_t *hw, ledc_slow_clk_sel_t slow_clk_sel)
+{
+    (void)hw;
+    uint32_t clk_sel_val = 0;
+    if (slow_clk_sel == LEDC_SLOW_CLK_PLL_DIV) {
+        clk_sel_val = 1;
+    } else if (slow_clk_sel == LEDC_SLOW_CLK_RTC8M) {
+        clk_sel_val = 2;
+    } else if (slow_clk_sel == LEDC_SLOW_CLK_XTAL) {
+        clk_sel_val = 3;
+    }
+    PCR.ledc_sclk_conf.ledc_sclk_sel = clk_sel_val;
+}
+
+/**
+ * @brief Get LEDC low speed timer clock
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param slow_clk_sel LEDC low speed timer clock source
+ *
+ * @return None
+ */
+static inline void ledc_ll_get_slow_clk_sel(ledc_dev_t *hw, ledc_slow_clk_sel_t *slow_clk_sel)
+{
+    (void)hw;
+    uint32_t clk_sel_val = PCR.ledc_sclk_conf.ledc_sclk_sel;
+    if (clk_sel_val == 1) {
+        *slow_clk_sel = LEDC_SLOW_CLK_PLL_DIV;
+    } else if (clk_sel_val == 2) {
+        *slow_clk_sel = LEDC_SLOW_CLK_RTC8M;
+    } else if (clk_sel_val == 3) {
+        *slow_clk_sel = LEDC_SLOW_CLK_XTAL;
+    } else {
+        abort();
+    }
+}
+
+/**
+ * @brief Update LEDC low speed timer
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
+ *
+ * @return None
+ */
+static inline void ledc_ll_ls_timer_update(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel)
+{
+    hw->timer_group[speed_mode].timer[timer_sel].conf.para_up = 1;
+    // Here, we don't wait for the bit gets cleared since it can take quite long depends on the pwm frequency
+}
+
+/**
+ * @brief Reset LEDC timer
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
+ *
+ * @return None
+ */
+static inline void ledc_ll_timer_rst(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel)
+{
+    hw->timer_group[speed_mode].timer[timer_sel].conf.rst = 1;
+    hw->timer_group[speed_mode].timer[timer_sel].conf.rst = 0;
+}
+
+/**
+ * @brief Pause LEDC timer
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
+ *
+ * @return None
+ */
+static inline void ledc_ll_timer_pause(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel)
+{
+    hw->timer_group[speed_mode].timer[timer_sel].conf.pause = 1;
+}
+
+/**
+ * @brief Resume LEDC timer
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
+ *
+ * @return None
+ */
+static inline void ledc_ll_timer_resume(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel)
+{
+    hw->timer_group[speed_mode].timer[timer_sel].conf.pause = 0;
+}
+
+/**
+ * @brief Set LEDC timer clock divider
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
+ * @param clock_divider Timer clock divide value, the timer clock is divided from the selected clock source
+ *
+ * @return None
+ */
+static inline void ledc_ll_set_clock_divider(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t clock_divider)
+{
+    hw->timer_group[speed_mode].timer[timer_sel].conf.clk_div = clock_divider;
+}
+
+/**
+ * @brief Get LEDC timer clock divider
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
+ * @param clock_divider Timer clock divide value, the timer clock is divided from the selected clock source
+ *
+ * @return None
+ */
+static inline void ledc_ll_get_clock_divider(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t *clock_divider)
+{
+    *clock_divider = hw->timer_group[speed_mode].timer[timer_sel].conf.clk_div;
+}
+
+/**
+ * @brief Get LEDC timer clock source
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
+ * @param clk_src Pointer to accept the timer clock source
+ *
+ * @return None
+ */
+static inline void ledc_ll_get_clock_source(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, ledc_clk_src_t *clk_src)
+{
+    // The target has no timer-specific clock source option
+    HAL_ASSERT(hw->timer_group[speed_mode].timer[timer_sel].conf.tick_sel == 0);
+    *clk_src = LEDC_SCLK;
+}
+
+/**
+ * @brief Set LEDC duty resolution
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
+ * @param duty_resolution Resolution of duty setting in number of bits. The range of duty values is [0, (2**duty_resolution)]
+ *
+ * @return None
+ */
+static inline void ledc_ll_set_duty_resolution(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t duty_resolution)
+{
+    hw->timer_group[speed_mode].timer[timer_sel].conf.duty_res = duty_resolution;
+}
+
+/**
+ * @brief Get LEDC duty resolution
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
+ * @param duty_resolution Pointer to accept the resolution of duty setting in number of bits.
+ *
+ * @return None
+ */
+static inline void ledc_ll_get_duty_resolution(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t *duty_resolution)
+{
+    *duty_resolution = hw->timer_group[speed_mode].timer[timer_sel].conf.duty_res;
+}
+
+/**
+ * @brief Update channel configure when select low speed mode
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ *
+ * @return None
+ */
+static inline void ledc_ll_ls_channel_update(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num)
+{
+    hw->channel_group[speed_mode].channel[channel_num].conf0.para_up = 1;
+}
+
+/**
+ * @brief Get LEDC max duty
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param max_duty Pointer to accept the max duty
+ *
+ * @return None
+ */
+static inline void ledc_ll_get_max_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t *max_duty)
+{
+    uint32_t timer_sel = hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel;
+    *max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_res));
+}
+
+/**
+ * @brief Set LEDC hpoint value
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param hpoint_val LEDC hpoint value(max: 0xfffff)
+ *
+ * @return None
+ */
+static inline void ledc_ll_set_hpoint(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t hpoint_val)
+{
+    hw->channel_group[speed_mode].channel[channel_num].hpoint.hpoint = hpoint_val;
+}
+
+/**
+ * @brief Get LEDC hpoint value
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param hpoint_val Pointer to accept the LEDC hpoint value(max: 0xfffff)
+ *
+ * @return None
+ */
+static inline void ledc_ll_get_hpoint(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t *hpoint_val)
+{
+    *hpoint_val = hw->channel_group[speed_mode].channel[channel_num].hpoint.hpoint;
+}
+
+/**
+ * @brief Set LEDC the integer part of duty value
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param duty_val LEDC duty value, the range of duty setting is [0, (2**duty_resolution)]
+ *
+ * @return None
+ */
+static inline void ledc_ll_set_duty_int_part(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t duty_val)
+{
+    hw->channel_group[speed_mode].channel[channel_num].duty.duty = duty_val << 4;
+}
+
+/**
+ * @brief Get LEDC duty value
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param duty_val Pointer to accept the LEDC duty value
+ *
+ * @return None
+ */
+static inline void ledc_ll_get_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t *duty_val)
+{
+    *duty_val = (hw->channel_group[speed_mode].channel[channel_num].duty_rd.duty_r >> 4);
+}
+
+/**
+ * @brief Set LEDC duty change direction
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param duty_direction LEDC duty change direction, increase or decrease
+ *
+ * @return None
+ */
+static inline void ledc_ll_set_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, ledc_duty_direction_t duty_direction)
+{
+    hw->channel_gamma_group[speed_mode].channel[channel_num].wr.gamma_duty_inc = duty_direction;
+}
+
+/**
+ * @brief Get LEDC duty change direction
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param duty_direction Pointer to accept the LEDC duty change direction, increase or decrease
+ *
+ * @return None
+ */
+static inline void ledc_ll_get_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, ledc_duty_direction_t *duty_direction)
+{
+    *duty_direction = (ledc_duty_direction_t)(hw->channel_gamma_group[speed_mode].channel[channel_num].wr.gamma_duty_inc);
+}
+
+/**
+ * @brief Set the number of increased or decreased times
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param duty_num The number of increased or decreased times
+ *
+ * @return None
+ */
+static inline void ledc_ll_set_duty_num(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t duty_num)
+{
+    hw->channel_gamma_group[speed_mode].channel[channel_num].wr.gamma_duty_num = duty_num;
+}
+
+/**
+ * @brief Set the duty cycles of increase or decrease
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param duty_cycle The duty cycles
+ *
+ * @return None
+ */
+static inline void ledc_ll_set_duty_cycle(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t duty_cycle)
+{
+    hw->channel_gamma_group[speed_mode].channel[channel_num].wr.gamma_duty_cycle = duty_cycle;
+}
+
+/**
+ * @brief Set the step scale of increase or decrease
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param duty_scale The step scale
+ *
+ * @return None
+ */
+static inline void ledc_ll_set_duty_scale(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t duty_scale)
+{
+    hw->channel_gamma_group[speed_mode].channel[channel_num].wr.gamma_scale = duty_scale;
+}
+
+/**
+ * @brief Set the range number of the specified duty configurations written to gamma_wr register
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param duty_range Range index (0 - (SOC_LEDC_GAMMA_FADE_RANGE_MAX-1)), it specifies to which range the configurations in gamma_wr register apply
+ *
+ * @return None
+ */
+static inline void ledc_ll_set_duty_range(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t duty_range)
+{
+    hw->channel_gamma_group[speed_mode].channel[channel_num].wr_addr.gamma_wr_addr = duty_range;
+}
+
+/**
+ * @brief Set the total number of ranges in one fading
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param range_num Total number of ranges (1 - SOC_LEDC_GAMMA_FADE_RANGE_MAX) of the fading configured
+ *
+ * @return None
+ */
+static inline void ledc_ll_set_range_number(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t range_num)
+{
+    hw->channel_gamma_conf_group[speed_mode].gamma_conf[channel_num].gamma_entry_num = range_num;
+}
+
+/**
+ * @brief Set the output enable
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param sig_out_en The output enable status
+ *
+ * @return None
+ */
+static inline void ledc_ll_set_sig_out_en(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, bool sig_out_en)
+{
+    hw->channel_group[speed_mode].channel[channel_num].conf0.sig_out_en = sig_out_en;
+}
+
+/**
+ * @brief Set the duty start
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param duty_start The duty start
+ *
+ * @return None
+ */
+static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, bool duty_start)
+{
+    hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = duty_start;
+}
+
+/**
+ * @brief Set output idle level
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param idle_level The output idle level
+ *
+ * @return None
+ */
+static inline void ledc_ll_set_idle_level(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t idle_level)
+{
+    hw->channel_group[speed_mode].channel[channel_num].conf0.idle_lv = idle_level & 0x1;
+}
+
+/**
+ * @brief Set fade end interrupt enable
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param fade_end_intr_en The fade end interrupt enable status
+ *
+ * @return None
+ */
+static inline void ledc_ll_set_fade_end_intr(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, bool fade_end_intr_en)
+{
+    uint32_t value = hw->int_ena.val;
+    uint32_t int_en_base = LEDC_DUTY_CHNG_END_CH0_INT_ENA_S;
+    hw->int_ena.val = fade_end_intr_en ? (value | BIT(int_en_base + channel_num)) : (value & (~(BIT(int_en_base + channel_num))));
+}
+
+/**
+ * @brief Get fade end interrupt status
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param intr_status The fade end interrupt status
+ *
+ * @return None
+ */
+static inline void ledc_ll_get_fade_end_intr_status(ledc_dev_t *hw, ledc_mode_t speed_mode, uint32_t *intr_status)
+{
+    uint32_t value = hw->int_st.val;
+    uint32_t int_en_base = LEDC_DUTY_CHNG_END_CH0_INT_ENA_S;
+    *intr_status = (value >> int_en_base) & 0xff;
+}
+
+/**
+ * @brief Clear fade end interrupt status
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ *
+ * @return None
+ */
+static inline void ledc_ll_clear_fade_end_intr_status(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num)
+{
+    uint32_t int_en_base = LEDC_DUTY_CHNG_END_CH0_INT_ENA_S;
+    hw->int_clr.val = BIT(int_en_base + channel_num);
+}
+
+/**
+ * @brief Set timer index of the specified channel
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
+ *
+ * @return None
+ */
+static inline void ledc_ll_bind_channel_timer(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, ledc_timer_t timer_sel)
+{
+    hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel = timer_sel;
+}
+
+/**
+ * @brief Get timer index of the specified channel
+ *
+ * @param hw Beginning address of the peripheral registers
+ * @param speed_mode LEDC speed_mode, low-speed mode only
+ * @param channel_num LEDC channel index (0-5), select from ledc_channel_t
+ * @param timer_sel Pointer to accept the LEDC timer index
+ *
+ * @return None
+ */
+static inline void ledc_ll_get_channel_timer(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, ledc_timer_t *timer_sel)
+{
+    *timer_sel = (ledc_timer_t)(hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel);
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 25 - 0
components/hal/include/hal/ledc_hal.h

@@ -17,6 +17,7 @@
 
 #include "hal/ledc_ll.h"
 #include "hal/ledc_types.h"
+#include "soc/soc_caps.h"
 
 /**
  * Context that should be maintained by both the driver and the HAL
@@ -337,6 +338,30 @@ void ledc_hal_set_duty_cycle(ledc_hal_context_t *hal, ledc_channel_t channel_num
  */
 void ledc_hal_set_duty_scale(ledc_hal_context_t *hal, ledc_channel_t channel_num, uint32_t duty_scale);
 
+#if SOC_LEDC_GAMMA_FADE_RANGE_MAX > 1
+/**
+ * @brief Set the range number of the specified duty configurations written to gamma_wr register
+ *
+ * @param hal Context of the HAL layer
+ * @param channel_num LEDC channel index, select from ledc_channel_t
+ * @param duty_range Range index (0-15), it specifies to which range the configurations in gamma_wr register apply
+ *
+ * @return None
+ */
+void ledc_hal_set_duty_range(ledc_hal_context_t *hal, ledc_channel_t channel_num, uint32_t duty_range);
+
+/**
+ * @brief Set the total number of ranges in one fading
+ *
+ * @param hal Context of the HAL layer
+ * @param channel_num LEDC channel index, select from ledc_channel_t
+ * @param range_num Total number of ranges (1-16) of the fading configured
+ *
+ * @return None
+ */
+void ledc_hal_set_range_number(ledc_hal_context_t *hal, ledc_channel_t channel_num, uint32_t range_num);
+#endif //SOC_LEDC_GAMMA_FADE_RANGE_MAX > 1
+
 /**
  * @brief Get interrupt status of the specified channel
  *

+ 2 - 2
components/hal/include/hal/ledc_types.h

@@ -61,7 +61,7 @@ typedef enum {
 #if SOC_LEDC_SUPPORT_PLL_DIV_CLOCK
     LEDC_USE_PLL_DIV_CLK, /*!< LEDC timer select the PLL_DIV clock available to LEDC peripheral as source clock*/
 #endif
-    LEDC_USE_RTC8M_CLK,   /*!< LEDC timer select RTC8M_CLK as source clock. Only for low speed channels and this parameter must be the same for all low speed channels*/
+    LEDC_USE_RTC8M_CLK,   /*!< LEDC timer select RTC8M_CLK (i.e. RC_FAST) as source clock. Only for low speed channels and this parameter must be the same for all low speed channels*/
 #if SOC_LEDC_SUPPORT_REF_TICK
     LEDC_USE_REF_TICK,    /*!< LEDC timer select REF_TICK clock as source clock*/
 #endif
@@ -122,7 +122,7 @@ typedef enum {
     LEDC_TIMER_12_BIT,      /*!< LEDC PWM duty resolution of 12 bits */
     LEDC_TIMER_13_BIT,      /*!< LEDC PWM duty resolution of 13 bits */
     LEDC_TIMER_14_BIT,      /*!< LEDC PWM duty resolution of 14 bits */
-#if SOC_LEDC_TIMER_BIT_WIDE_NUM > 14
+#if SOC_LEDC_TIMER_BIT_WIDTH > 14
     LEDC_TIMER_15_BIT,      /*!< LEDC PWM duty resolution of 15 bits */
     LEDC_TIMER_16_BIT,      /*!< LEDC PWM duty resolution of 16 bits */
     LEDC_TIMER_17_BIT,      /*!< LEDC PWM duty resolution of 17 bits */

+ 17 - 13
components/hal/ledc_hal_iram.c

@@ -1,16 +1,8 @@
-// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-
-//     http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
+/*
+ * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 
 // The HAL layer for LEDC (common part, in iram)
 // make these functions in a seperate file to make sure all LL functions are in the IRAM.
@@ -53,6 +45,18 @@ void ledc_hal_set_duty_scale(ledc_hal_context_t *hal, ledc_channel_t channel_num
     ledc_ll_set_duty_scale(hal->dev, hal->speed_mode, channel_num, duty_scale);
 }
 
+#if SOC_LEDC_GAMMA_FADE_RANGE_MAX > 1
+void ledc_hal_set_duty_range(ledc_hal_context_t *hal, ledc_channel_t channel_num, uint32_t duty_range)
+{
+    ledc_ll_set_duty_range(hal->dev, hal->speed_mode, channel_num, duty_range);
+}
+
+void ledc_hal_set_range_number(ledc_hal_context_t *hal, ledc_channel_t channel_num, uint32_t range_num)
+{
+    ledc_ll_set_range_number(hal->dev, hal->speed_mode, channel_num, range_num);
+}
+#endif //SOC_LEDC_GAMMA_FADE_RANGE_MAX > 1
+
 void ledc_hal_get_fade_end_intr_status(ledc_hal_context_t *hal, uint32_t *intr_status)
 {
     ledc_ll_get_fade_end_intr_status(hal->dev, hal->speed_mode, intr_status);

+ 9 - 1
components/soc/esp32/include/soc/Kconfig.soc_caps.in

@@ -375,10 +375,14 @@ config SOC_LEDC_CHANNEL_NUM
     int
     default 8
 
-config SOC_LEDC_TIMER_BIT_WIDE_NUM
+config SOC_LEDC_TIMER_BIT_WIDTH
     int
     default 20
 
+config SOC_LEDC_GAMMA_FADE_RANGE_MAX
+    int
+    default 1
+
 config SOC_MCPWM_GROUPS
     int
     default 2
@@ -739,6 +743,10 @@ config SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256
     bool
     default y
 
+config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
+    bool
+    default y
+
 config SOC_SDMMC_USE_IOMUX
     bool
     default y

+ 3 - 1
components/soc/esp32/include/soc/soc_caps.h

@@ -210,7 +210,8 @@
 #define SOC_LEDC_SUPPORT_REF_TICK        (1)
 #define SOC_LEDC_SUPPORT_HS_MODE         (1)
 #define SOC_LEDC_CHANNEL_NUM             (8)
-#define SOC_LEDC_TIMER_BIT_WIDE_NUM      (20)
+#define SOC_LEDC_TIMER_BIT_WIDTH         (20)
+#define SOC_LEDC_GAMMA_FADE_RANGE_MAX    (1U) // The target does not support gamma curve fading
 
 /*-------------------------- MCPWM CAPS --------------------------------------*/
 #define SOC_MCPWM_GROUPS                     (2)    ///< 2 MCPWM groups on the chip (i.e., the number of independent MCPWM peripherals)
@@ -374,6 +375,7 @@
 
 #define SOC_CLK_RC_FAST_D256_SUPPORTED            (1)
 #define SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256     (1)
+#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION       (1)
 
 /*-------------------------- SDMMC CAPS -----------------------------------------*/
 

+ 9 - 1
components/soc/esp32c2/include/soc/Kconfig.soc_caps.in

@@ -275,7 +275,7 @@ config SOC_LEDC_CHANNEL_NUM
     int
     default 6
 
-config SOC_LEDC_TIMER_BIT_WIDE_NUM
+config SOC_LEDC_TIMER_BIT_WIDTH
     int
     default 14
 
@@ -283,6 +283,10 @@ config SOC_LEDC_SUPPORT_FADE_STOP
     bool
     default y
 
+config SOC_LEDC_GAMMA_FADE_RANGE_MAX
+    int
+    default 1
+
 config SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED
     bool
     default n
@@ -579,6 +583,10 @@ config SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256
     bool
     default y
 
+config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
+    bool
+    default y
+
 config SOC_WIFI_HW_TSF
     bool
     default y

+ 3 - 1
components/soc/esp32c2/include/soc/soc_caps.h

@@ -144,8 +144,9 @@
 #define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK  (1)
 #define SOC_LEDC_SUPPORT_XTAL_CLOCK     (1)
 #define SOC_LEDC_CHANNEL_NUM            (6)
-#define SOC_LEDC_TIMER_BIT_WIDE_NUM     (14)
+#define SOC_LEDC_TIMER_BIT_WIDTH        (14)
 #define SOC_LEDC_SUPPORT_FADE_STOP      (1)
+#define SOC_LEDC_GAMMA_FADE_RANGE_MAX   (1U) // The target does not support gamma curve fading
 
 /*-------------------------- MPU CAPS ----------------------------------------*/
 #define SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED    0
@@ -281,6 +282,7 @@
 /*--------------------------- CLOCK SUBSYSTEM CAPS -------------------------- */
 #define SOC_CLK_RC_FAST_D256_SUPPORTED            (1)
 #define SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256     (1)
+#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION       (1)
 
 /*------------------------------------ WI-FI CAPS ------------------------------------*/
 #define SOC_WIFI_HW_TSF                 (1)    /*!< Support hardware TSF */

+ 9 - 1
components/soc/esp32c3/include/soc/Kconfig.soc_caps.in

@@ -403,7 +403,7 @@ config SOC_LEDC_CHANNEL_NUM
     int
     default 6
 
-config SOC_LEDC_TIMER_BIT_WIDE_NUM
+config SOC_LEDC_TIMER_BIT_WIDTH
     int
     default 14
 
@@ -411,6 +411,10 @@ config SOC_LEDC_SUPPORT_FADE_STOP
     bool
     default y
 
+config SOC_LEDC_GAMMA_FADE_RANGE_MAX
+    int
+    default 1
+
 config SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED
     bool
     default n
@@ -815,6 +819,10 @@ config SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256
     bool
     default y
 
+config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
+    bool
+    default y
+
 config SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC
     bool
     default y

+ 7 - 5
components/soc/esp32c3/include/soc/soc_caps.h

@@ -190,11 +190,12 @@
 #define SOC_I2S_SUPPORTS_TDM        (1)
 
 /*-------------------------- LEDC CAPS ---------------------------------------*/
-#define SOC_LEDC_SUPPORT_APB_CLOCK   (1)
-#define SOC_LEDC_SUPPORT_XTAL_CLOCK  (1)
-#define SOC_LEDC_CHANNEL_NUM         (6)
-#define SOC_LEDC_TIMER_BIT_WIDE_NUM  (14)
-#define SOC_LEDC_SUPPORT_FADE_STOP   (1)
+#define SOC_LEDC_SUPPORT_APB_CLOCK       (1)
+#define SOC_LEDC_SUPPORT_XTAL_CLOCK      (1)
+#define SOC_LEDC_CHANNEL_NUM             (6)
+#define SOC_LEDC_TIMER_BIT_WIDTH         (14)
+#define SOC_LEDC_SUPPORT_FADE_STOP       (1)
+#define SOC_LEDC_GAMMA_FADE_RANGE_MAX    (1U) // The target does not support gamma curve fading
 
 /*-------------------------- MPU CAPS ----------------------------------------*/
 #define SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED    0
@@ -374,6 +375,7 @@
 /*--------------------------- CLOCK SUBSYSTEM CAPS -------------------------- */
 #define SOC_CLK_RC_FAST_D256_SUPPORTED            (1)
 #define SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256     (1)
+#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION       (1)
 
 /*-------------------------- Temperature Sensor CAPS -------------------------------------*/
 #define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC                (1)

+ 0 - 1
components/soc/esp32c6/CMakeLists.txt

@@ -20,7 +20,6 @@ set(srcs
 # ESP32C6-TODO
 list(REMOVE_ITEM srcs
         "adc_periph.c"                  # TODO: IDF-5310
-        "ledc_periph.c"                 # TODO: IDF-5328
         )
 
 add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")

+ 15 - 3
components/soc/esp32c6/include/soc/Kconfig.soc_caps.in

@@ -71,6 +71,10 @@ config SOC_SDM_SUPPORTED
     bool
     default y
 
+config SOC_LEDC_SUPPORTED
+    bool
+    default y
+
 config SOC_I2C_SUPPORTED
     bool
     default y
@@ -375,7 +379,7 @@ config SOC_I2S_SUPPORTS_TDM
     bool
     default y
 
-config SOC_LEDC_SUPPORT_APB_CLOCK
+config SOC_LEDC_SUPPORT_PLL_DIV_CLOCK
     bool
     default y
 
@@ -387,14 +391,18 @@ config SOC_LEDC_CHANNEL_NUM
     int
     default 6
 
-config SOC_LEDC_TIMER_BIT_WIDE_NUM
+config SOC_LEDC_TIMER_BIT_WIDTH
     int
-    default 14
+    default 20
 
 config SOC_LEDC_SUPPORT_FADE_STOP
     bool
     default y
 
+config SOC_LEDC_GAMMA_FADE_RANGE_MAX
+    int
+    default 16
+
 config SOC_MMU_DI_VADDR_SHARED
     bool
     default y
@@ -863,6 +871,10 @@ config SOC_PM_SUPPORT_BT_PD
     bool
     default y
 
+config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
+    bool
+    default y
+
 config SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC
     bool
     default y

+ 2 - 2
components/soc/esp32c6/include/soc/rtc.h

@@ -154,9 +154,9 @@ typedef struct rtc_cpu_freq_config_s {
  */
 typedef enum {
     RTC_CAL_RTC_MUX = 0,       //!< Currently selected RTC SLOW_CLK
-    RTC_CAL_8MD256 = 1,        //!< Internal 8 MHz RC oscillator, divided by 256
     RTC_CAL_32K_XTAL = 2,      //!< External 32 kHz XTAL
-    RTC_CAL_INTERNAL_OSC = 3   //!< Internal 150 kHz oscillator
+    RTC_CAL_INTERNAL_OSC = 3,  //!< Internal 150 kHz oscillator
+    RTC_CAL_RC_FAST,           //!< Internal 20 MHz oscillator
 } rtc_cal_sel_t;
 
 /**

+ 10 - 7
components/soc/esp32c6/include/soc/soc_caps.h

@@ -45,7 +45,7 @@
 #define SOC_I2S_SUPPORTED               1
 #define SOC_RMT_SUPPORTED               1
 #define SOC_SDM_SUPPORTED               1
-// #define SOC_LEDC_SUPPORTED              1 // TODO: IDF-5328
+#define SOC_LEDC_SUPPORTED              1
 #define SOC_I2C_SUPPORTED               1
 #define SOC_SYSTIMER_SUPPORTED          1
 #define SOC_SUPPORT_COEXISTENCE         1
@@ -209,13 +209,13 @@
 #define SOC_I2S_PDM_MAX_TX_LINES    (2)
 #define SOC_I2S_SUPPORTS_TDM        (1)
 
-// TODO: IDF-5328 (Copy from esp32c3, need check)
 /*-------------------------- LEDC CAPS ---------------------------------------*/
-#define SOC_LEDC_SUPPORT_APB_CLOCK   (1)
-#define SOC_LEDC_SUPPORT_XTAL_CLOCK  (1)
-#define SOC_LEDC_CHANNEL_NUM         (6)
-#define SOC_LEDC_TIMER_BIT_WIDE_NUM  (14)
-#define SOC_LEDC_SUPPORT_FADE_STOP   (1)
+#define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK      (1)
+#define SOC_LEDC_SUPPORT_XTAL_CLOCK         (1)
+#define SOC_LEDC_CHANNEL_NUM                (6)
+#define SOC_LEDC_TIMER_BIT_WIDTH            (20)
+#define SOC_LEDC_SUPPORT_FADE_STOP          (1)
+#define SOC_LEDC_GAMMA_FADE_RANGE_MAX       (16)
 
 /*-------------------------- MMU CAPS ----------------------------------------*/
 #define SOC_MMU_DI_VADDR_SHARED               (1) /*!< D/I vaddr are shared */
@@ -427,6 +427,9 @@
 
 #define SOC_PM_SUPPORT_BT_PD            (1)
 
+/*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/
+#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION       (1)
+
 /*-------------------------- Temperature Sensor CAPS -------------------------------------*/
 #define SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC                (1)
 #define SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL                (1)

+ 7 - 3
components/soc/esp32h2/include/soc/Kconfig.soc_caps.in

@@ -271,7 +271,7 @@ config SOC_I2S_SUPPORTS_TDM
     bool
     default y
 
-config SOC_LEDC_SUPPORT_APB_CLOCK
+config SOC_LEDC_SUPPORT_PLL_DIV_CLOCK
     bool
     default y
 
@@ -283,14 +283,18 @@ config SOC_LEDC_CHANNEL_NUM
     int
     default 6
 
-config SOC_LEDC_TIMER_BIT_WIDE_NUM
+config SOC_LEDC_TIMER_BIT_WIDTH
     int
-    default 14
+    default 20
 
 config SOC_LEDC_SUPPORT_FADE_STOP
     bool
     default y
 
+config SOC_LEDC_GAMMA_FADE_RANGE_MAX
+    int
+    default 16
+
 config SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED
     bool
     default n

+ 6 - 5
components/soc/esp32h2/include/soc/soc_caps.h

@@ -198,11 +198,12 @@
 
 // TODO: IDF-6235 (Copy from esp32c6, need check)
 /*-------------------------- LEDC CAPS ---------------------------------------*/
-#define SOC_LEDC_SUPPORT_APB_CLOCK   (1)
-#define SOC_LEDC_SUPPORT_XTAL_CLOCK  (1)
-#define SOC_LEDC_CHANNEL_NUM         (6)
-#define SOC_LEDC_TIMER_BIT_WIDE_NUM  (14)
-#define SOC_LEDC_SUPPORT_FADE_STOP   (1)
+#define SOC_LEDC_SUPPORT_PLL_DIV_CLOCK      (1)
+#define SOC_LEDC_SUPPORT_XTAL_CLOCK         (1)
+#define SOC_LEDC_CHANNEL_NUM                (6)
+#define SOC_LEDC_TIMER_BIT_WIDTH            (20)
+#define SOC_LEDC_SUPPORT_FADE_STOP          (1)
+#define SOC_LEDC_GAMMA_FADE_RANGE_MAX       (16)
 
 // TODO: IDF-6332 (Copy from esp32c6, need check)
 /*-------------------------- MPU CAPS ----------------------------------------*/

+ 5 - 1
components/soc/esp32h4/include/soc/Kconfig.soc_caps.in

@@ -379,7 +379,7 @@ config SOC_LEDC_CHANNEL_NUM
     int
     default 6
 
-config SOC_LEDC_TIMER_BIT_WIDE_NUM
+config SOC_LEDC_TIMER_BIT_WIDTH
     int
     default 14
 
@@ -387,6 +387,10 @@ config SOC_LEDC_SUPPORT_FADE_STOP
     bool
     default y
 
+config SOC_LEDC_GAMMA_FADE_RANGE_MAX
+    int
+    default 1
+
 config SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED
     bool
     default n

+ 6 - 5
components/soc/esp32h4/include/soc/soc_caps.h

@@ -196,11 +196,12 @@
 #define SOC_I2S_SUPPORTS_TDM        (1)
 
 /*-------------------------- LEDC CAPS ---------------------------------------*/
-#define SOC_LEDC_SUPPORT_APB_CLOCK   (1)
-#define SOC_LEDC_SUPPORT_XTAL_CLOCK  (1)
-#define SOC_LEDC_CHANNEL_NUM         (6)
-#define SOC_LEDC_TIMER_BIT_WIDE_NUM  (14)
-#define SOC_LEDC_SUPPORT_FADE_STOP   (1)
+#define SOC_LEDC_SUPPORT_APB_CLOCK       (1)
+#define SOC_LEDC_SUPPORT_XTAL_CLOCK      (1)
+#define SOC_LEDC_CHANNEL_NUM             (6)
+#define SOC_LEDC_TIMER_BIT_WIDTH         (14)
+#define SOC_LEDC_SUPPORT_FADE_STOP       (1)
+#define SOC_LEDC_GAMMA_FADE_RANGE_MAX    (1U) // The target does not support gamma curve fading
 
 /*-------------------------- MPU CAPS ----------------------------------------*/
 #define SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED    0

+ 9 - 1
components/soc/esp32s2/include/soc/Kconfig.soc_caps.in

@@ -415,7 +415,7 @@ config SOC_LEDC_CHANNEL_NUM
     int
     default 8
 
-config SOC_LEDC_TIMER_BIT_WIDE_NUM
+config SOC_LEDC_TIMER_BIT_WIDTH
     int
     default 14
 
@@ -423,6 +423,10 @@ config SOC_LEDC_SUPPORT_FADE_STOP
     bool
     default y
 
+config SOC_LEDC_GAMMA_FADE_RANGE_MAX
+    int
+    default 1
+
 config SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED
     bool
     default n
@@ -923,6 +927,10 @@ config SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256
     bool
     default y
 
+config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
+    bool
+    default y
+
 config SOC_COEX_HW_PTI
     bool
     default y

+ 3 - 1
components/soc/esp32s2/include/soc/soc_caps.h

@@ -199,8 +199,9 @@
 #define SOC_LEDC_SUPPORT_REF_TICK        (1)
 #define SOC_LEDC_SUPPORT_XTAL_CLOCK      (1)
 #define SOC_LEDC_CHANNEL_NUM             (8)
-#define SOC_LEDC_TIMER_BIT_WIDE_NUM      (14)
+#define SOC_LEDC_TIMER_BIT_WIDTH         (14)
 #define SOC_LEDC_SUPPORT_FADE_STOP       (1)
+#define SOC_LEDC_GAMMA_FADE_RANGE_MAX    (1U) // The target does not support gamma curve fading
 
 /*-------------------------- MPU CAPS ----------------------------------------*/
 //TODO: correct the caller and remove unsupported lines
@@ -408,6 +409,7 @@
 
 #define SOC_CLK_RC_FAST_D256_SUPPORTED            (1)
 #define SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256     (1)
+#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION       (1)
 
 /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/
 #define SOC_COEX_HW_PTI                 (1)

+ 28 - 20
components/soc/esp32s3/include/soc/Kconfig.soc_caps.in

@@ -3,26 +3,6 @@
 # using gen_soc_caps_kconfig.py, do not edit manually
 #####################################################
 
-config SOC_LEDC_SUPPORT_APB_CLOCK
-    bool
-    default y
-
-config SOC_LEDC_SUPPORT_XTAL_CLOCK
-    bool
-    default y
-
-config SOC_LEDC_CHANNEL_NUM
-    int
-    default 8
-
-config SOC_LEDC_TIMER_BIT_WIDE_NUM
-    int
-    default 14
-
-config SOC_LEDC_SUPPORT_FADE_STOP
-    bool
-    default y
-
 config SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED
     bool
     default n
@@ -463,6 +443,30 @@ config SOC_I2S_SUPPORTS_TDM
     bool
     default y
 
+config SOC_LEDC_SUPPORT_APB_CLOCK
+    bool
+    default y
+
+config SOC_LEDC_SUPPORT_XTAL_CLOCK
+    bool
+    default y
+
+config SOC_LEDC_CHANNEL_NUM
+    int
+    default 8
+
+config SOC_LEDC_TIMER_BIT_WIDTH
+    int
+    default 14
+
+config SOC_LEDC_SUPPORT_FADE_STOP
+    bool
+    default y
+
+config SOC_LEDC_GAMMA_FADE_RANGE_MAX
+    int
+    default 1
+
 config SOC_MCPWM_GROUPS
     int
     default 2
@@ -971,6 +975,10 @@ config SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256
     bool
     default y
 
+config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
+    bool
+    default y
+
 config SOC_SECURE_BOOT_V2_RSA
     bool
     default y

+ 0 - 21
components/soc/esp32s3/include/soc/ledc_caps.h

@@ -1,21 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
- *
- * SPDX-License-Identifier: Apache-2.0
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define SOC_LEDC_SUPPORT_APB_CLOCK   (1)
-#define SOC_LEDC_SUPPORT_XTAL_CLOCK  (1)
-#define SOC_LEDC_CHANNEL_NUM         (8)
-#define SOC_LEDC_TIMER_BIT_WIDE_NUM  (14)
-#define SOC_LEDC_SUPPORT_FADE_STOP   (1)
-
-#ifdef __cplusplus
-}
-#endif

+ 7 - 1
components/soc/esp32s3/include/soc/soc_caps.h

@@ -193,7 +193,12 @@
 #define SOC_I2S_SUPPORTS_TDM        (1)
 
 /*-------------------------- LEDC CAPS ---------------------------------------*/
-#include "ledc_caps.h"
+#define SOC_LEDC_SUPPORT_APB_CLOCK       (1)
+#define SOC_LEDC_SUPPORT_XTAL_CLOCK      (1)
+#define SOC_LEDC_CHANNEL_NUM             (8)
+#define SOC_LEDC_TIMER_BIT_WIDTH         (14)
+#define SOC_LEDC_SUPPORT_FADE_STOP       (1)
+#define SOC_LEDC_GAMMA_FADE_RANGE_MAX    (1U) // The target does not support gamma curve fading
 
 /*-------------------------- MCPWM CAPS --------------------------------------*/
 #define SOC_MCPWM_GROUPS                     (2)    ///< 2 MCPWM groups on the chip (i.e., the number of independent MCPWM peripherals)
@@ -406,6 +411,7 @@
 /*--------------------------- CLOCK SUBSYSTEM CAPS -------------------------- */
 #define SOC_CLK_RC_FAST_D256_SUPPORTED            (1)
 #define SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256     (1)
+#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION       (1)
 
 /*-------------------------- Secure Boot CAPS----------------------------*/
 #define SOC_SECURE_BOOT_V2_RSA              1

+ 20 - 1
docs/en/api-reference/peripherals/ledc.rst

@@ -1,6 +1,6 @@
 LED Control (LEDC)
 ==================
-{IDF_TARGET_LEDC_CHAN_NUM:default="8", esp32="16", esp32s2="8", esp32c3="6", esp32s3="8", esp32c2="6", esp32h4="6"}
+{IDF_TARGET_LEDC_CHAN_NUM:default="6", esp32="16", esp32s2="8", esp32s3="8"}
 
 :link_to_translation:`zh_CN:[中文]`
 
@@ -146,6 +146,25 @@ The source clock can also limit the PWM frequency. The higher the source clock f
          - 40 MHz
          - Dynamic Frequency Scaling compatible
 
+.. only:: esp32c6
+
+    .. list-table:: Characteristics of {IDF_TARGET_NAME} LEDC source clocks
+       :widths: 15 15 30
+       :header-rows: 1
+
+       * - Clock name
+         - Clock freq
+         - Clock capabilities
+       * - PLL_80M_CLK
+         - 80 MHz
+         - /
+       * - RTC20M_CLK
+         - ~20 MHz
+         - Dynamic Frequency Scaling compatible, Light sleep compatible
+       * - XTAL_CLK
+         - 40 MHz
+         - Dynamic Frequency Scaling compatible
+
 .. only:: esp32h4
 
     .. list-table:: Characteristics of {IDF_TARGET_NAME} LEDC source clocks

+ 20 - 1
docs/zh_CN/api-reference/peripherals/ledc.rst

@@ -1,6 +1,6 @@
 LED PWM 控制器
 ==============
-{IDF_TARGET_LEDC_CHAN_NUM:default="8", esp32="16", esp32s2="8", esp32c3="6", esp32s3="8", esp32c2="6", esp32h4="6"}
+{IDF_TARGET_LEDC_CHAN_NUM:default="6", esp32="16", esp32s2="8", esp32s3="8"}
 
 :link_to_translation:`en:[English]`
 
@@ -146,6 +146,25 @@ LED PWM 控制器可在无需 CPU 干预的情况下自动改变占空比,实
          - 40 MHz
          - 支持动态调频(DFS)功能
 
+.. only:: esp32c6
+
+    .. list-table:: {IDF_TARGET_NAME} LEDC 时钟源特性
+       :widths: 10 10 30
+       :header-rows: 1
+
+       * - 时钟名称
+         - 时钟频率
+         - 时钟功能
+       * - PLL_80M_CLK
+         - 80 MHz
+         - /
+       * - RTC20M_CLK
+         - ~20 MHz
+         - 支持动态调频(DFS)功能,支持Light-sleep模式
+       * - XTAL_CLK
+         - 40 MHz
+         - 支持动态调频(DFS)功能
+
 .. only:: esp32h4
 
     .. list-table:: {IDF_TARGET_NAME} LEDC 时钟源特性

+ 2 - 10
examples/peripherals/.build-test-rules.yml

@@ -80,17 +80,9 @@ examples/peripherals/lcd/rgb_panel:
   disable:
     - if: SOC_LCD_RGB_SUPPORTED != 1
 
-examples/peripherals/ledc/ledc_basic:
+examples/peripherals/ledc:
   disable:
-    - if: IDF_TARGET == "esp32c6"
-      temporary: true
-      reason: target esp32c6 is not supported yet
-
-examples/peripherals/ledc/ledc_fade:
-  disable:
-    - if: IDF_TARGET == "esp32c6"
-      temporary: true
-      reason: target esp32c6 is not supported yet
+    - if: SOC_LEDC_SUPPORTED != 1
 
 examples/peripherals/mcpwm:
   disable:

+ 2 - 2
examples/peripherals/ledc/ledc_basic/README.md

@@ -1,5 +1,5 @@
-| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
-| ----------------- | ----- | -------- | -------- | -------- | -------- |
+| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 |
+| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
 
 # _LEDC Basic Example_
 

+ 2 - 2
examples/peripherals/ledc/ledc_fade/README.md

@@ -1,5 +1,5 @@
-| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
-| ----------------- | ----- | -------- | -------- | -------- | -------- |
+| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 |
+| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |
 
 # _LEDC Fade Example_
 

+ 0 - 1
tools/ci/check_copyright_ignore.txt

@@ -695,7 +695,6 @@ components/hal/include/hal/uhci_types.h
 components/hal/include/hal/usb_hal.h
 components/hal/include/hal/usb_types_private.h
 components/hal/include/hal/wdt_types.h
-components/hal/ledc_hal_iram.c
 components/hal/mpu_hal.c
 components/hal/rtc_io_hal.c
 components/hal/sha_hal.c