esp32: Add support for esp32c6.

This commit adds general support for ESP32-C6 SoCs.

Signed-off-by: Andrew Leech <andrew@alelec.net>
diff --git a/ports/esp32/boards/deploy_c6.md b/ports/esp32/boards/deploy_c6.md
new file mode 100644
index 0000000..941c69c
--- /dev/null
+++ b/ports/esp32/boards/deploy_c6.md
@@ -0,0 +1,14 @@
+Program your board using the esptool.py program, found [here](https://github.com/espressif/esptool).
+
+If you are putting MicroPython on your board for the first time then you should
+first erase the entire flash using:
+
+```bash
+esptool.py --chip esp32c6 --port /dev/ttyUSB0 erase_flash
+```
+
+From then on program the firmware starting at address 0x0:
+
+```bash
+esptool.py --chip esp32c6 --port /dev/ttyUSB0 --baud 460800 write_flash -z 0x0 ESP32_GENERIC_C6-20240602-v1.24.0.bin
+```
diff --git a/ports/esp32/esp32_common.cmake b/ports/esp32/esp32_common.cmake
index e59e2dc..2c81e8c 100644
--- a/ports/esp32/esp32_common.cmake
+++ b/ports/esp32/esp32_common.cmake
@@ -198,7 +198,7 @@
 set(MICROPY_TARGET ${COMPONENT_TARGET})
 
 # Define mpy-cross flags, for use with frozen code.
-if(NOT IDF_TARGET STREQUAL "esp32c3")
+if(CONFIG_IDF_TARGET_ARCH STREQUAL "xtensa")
 set(MICROPY_CROSS_FLAGS -march=xtensawin)
 endif()
 
diff --git a/ports/esp32/gccollect.c b/ports/esp32/gccollect.c
index 4b6dd8a..e6c17fd 100644
--- a/ports/esp32/gccollect.c
+++ b/ports/esp32/gccollect.c
@@ -35,7 +35,7 @@
 #include "py/mpthread.h"
 #include "gccollect.h"
 
-#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
+#if CONFIG_IDF_TARGET_ARCH_XTENSA
 
 #include "xtensa/hal.h"
 
@@ -61,8 +61,7 @@
     gc_collect_end();
 }
 
-#elif CONFIG_IDF_TARGET_ESP32C3
-
+#elif CONFIG_IDF_TARGET_ARCH_RISCV
 #include "shared/runtime/gchelper.h"
 
 void gc_collect(void) {
@@ -74,6 +73,8 @@
     gc_collect_end();
 }
 
+#else
+#error unknown CONFIG_IDF_TARGET_ARCH
 #endif
 
 #if MICROPY_GC_SPLIT_HEAP_AUTO
diff --git a/ports/esp32/machine_adc.c b/ports/esp32/machine_adc.c
index 0ac9f5d..2f27683 100644
--- a/ports/esp32/machine_adc.c
+++ b/ports/esp32/machine_adc.c
@@ -44,7 +44,7 @@
 #define MICROPY_PY_MACHINE_ADC_CLASS_CONSTANTS_WIDTH_9_10_11
 #endif
 
-#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
+#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3
 #define MICROPY_PY_MACHINE_ADC_CLASS_CONSTANTS_WIDTH_12 \
     { MP_ROM_QSTR(MP_QSTR_WIDTH_12BIT), MP_ROM_INT(12) },
 #else
@@ -87,7 +87,7 @@
     {{&machine_adc_type}, ADCBLOCK2, ADC_CHANNEL_7, GPIO_NUM_27},
     {{&machine_adc_type}, ADCBLOCK2, ADC_CHANNEL_8, GPIO_NUM_25},
     {{&machine_adc_type}, ADCBLOCK2, ADC_CHANNEL_9, GPIO_NUM_26},
-    #elif CONFIG_IDF_TARGET_ESP32C3
+    #elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6
     {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_0, GPIO_NUM_0},
     {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_1, GPIO_NUM_1},
     {{&machine_adc_type}, ADCBLOCK1, ADC_CHANNEL_2, GPIO_NUM_2},
diff --git a/ports/esp32/machine_adc_block.c b/ports/esp32/machine_adc_block.c
index c610233..6afdd6f 100644
--- a/ports/esp32/machine_adc_block.c
+++ b/ports/esp32/machine_adc_block.c
@@ -35,7 +35,7 @@
     #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
     {{&machine_adc_block_type}, ADC_UNIT_1, 12, -1, {0}},
     {{&machine_adc_block_type}, ADC_UNIT_2, 12, -1, {0}},
-    #elif CONFIG_IDF_TARGET_ESP32S2
+    #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C6
     {{&machine_adc_block_type}, ADC_UNIT_1, 13, -1, {0}},
     {{&machine_adc_block_type}, ADC_UNIT_2, 13, -1, {0}},
     #endif
diff --git a/ports/esp32/machine_bitstream.c b/ports/esp32/machine_bitstream.c
index ceb1e6a..b4e58c5 100644
--- a/ports/esp32/machine_bitstream.c
+++ b/ports/esp32/machine_bitstream.c
@@ -42,7 +42,7 @@
 // This is a translation of the cycle counter implementation in ports/stm32/machine_bitstream.c.
 static void IRAM_ATTR machine_bitstream_high_low_bitbang(mp_hal_pin_obj_t pin, uint32_t *timing_ns, const uint8_t *buf, size_t len) {
     uint32_t pin_mask, gpio_reg_set, gpio_reg_clear;
-    #if !CONFIG_IDF_TARGET_ESP32C3
+    #if !CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6
     if (pin >= 32) {
         pin_mask = 1 << (pin - 32);
         gpio_reg_set = GPIO_OUT1_W1TS_REG;
diff --git a/ports/esp32/machine_hw_spi.c b/ports/esp32/machine_hw_spi.c
index a0531b9..4b3d392 100644
--- a/ports/esp32/machine_hw_spi.c
+++ b/ports/esp32/machine_hw_spi.c
@@ -38,10 +38,10 @@
 #include "soc/spi_pins.h"
 
 // SPI mappings by device, naming used by IDF old/new
-// upython   | ESP32     | ESP32S2   | ESP32S3 | ESP32C3
-// ----------+-----------+-----------+---------+---------
-// SPI(id=1) | HSPI/SPI2 | FSPI/SPI2 | SPI2    | SPI2
-// SPI(id=2) | VSPI/SPI3 | HSPI/SPI3 | SPI3    | err
+// upython   | ESP32     | ESP32S2   | ESP32S3 | ESP32C3 | ESP32C6
+// ----------+-----------+-----------+---------+---------+---------
+// SPI(id=1) | HSPI/SPI2 | FSPI/SPI2 | SPI2    | SPI2    | SPI2
+// SPI(id=2) | VSPI/SPI3 | HSPI/SPI3 | SPI3    | err     | err
 
 // Number of available hardware SPI peripherals.
 #if SOC_SPI_PERIPH_NUM > 2
@@ -251,14 +251,14 @@
 
     // Select DMA channel based on the hardware SPI host
     int dma_chan = 0;
-    #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3
-    dma_chan = SPI_DMA_CH_AUTO;
-    #else
+    #if CONFIG_IDF_TARGET_ESP32
     if (self->host == SPI2_HOST) {
         dma_chan = 1;
     } else {
         dma_chan = 2;
     }
+    #else
+    dma_chan = SPI_DMA_CH_AUTO;
     #endif
 
     ret = spi_bus_initialize(self->host, &buscfg, dma_chan);
diff --git a/ports/esp32/machine_i2c.c b/ports/esp32/machine_i2c.c
old mode 100755
new mode 100644
index fe42d2e..e1e1850
--- a/ports/esp32/machine_i2c.c
+++ b/ports/esp32/machine_i2c.c
@@ -49,7 +49,7 @@
 #endif
 #endif
 
-#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
+#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32S3
 #define I2C_SCLK_FREQ XTAL_CLK_FREQ
 #elif CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
 #define I2C_SCLK_FREQ APB_CLK_FREQ
diff --git a/ports/esp32/machine_pin.c b/ports/esp32/machine_pin.c
index e48546e..687dfe1 100644
--- a/ports/esp32/machine_pin.c
+++ b/ports/esp32/machine_pin.c
@@ -43,7 +43,7 @@
 #include "modesp32.h"
 #include "genhdr/pins.h"
 
-#if CONFIG_IDF_TARGET_ESP32C3
+#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6
 #include "soc/usb_serial_jtag_reg.h"
 #endif
 
@@ -152,7 +152,7 @@
     // reset the pin to digital if this is a mode-setting init (grab it back from ADC)
     if (args[ARG_mode].u_obj != mp_const_none) {
         if (rtc_gpio_is_valid_gpio(index)) {
-            #if !CONFIG_IDF_TARGET_ESP32C3
+            #if !(CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6)
             rtc_gpio_deinit(index);
             #endif
         }
@@ -163,6 +163,11 @@
         CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_USB_PAD_ENABLE);
     }
     #endif
+    #if CONFIG_IDF_TARGET_ESP32C6 && CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED
+    if (index == 12 || index == 13) {
+        CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_USB_PAD_ENABLE);
+    }
+    #endif
 
     // configure the pin for gpio
     esp_rom_gpio_pad_select_gpio(index);
diff --git a/ports/esp32/machine_pin.h b/ports/esp32/machine_pin.h
index 1d64e7f..3f94508 100644
--- a/ports/esp32/machine_pin.h
+++ b/ports/esp32/machine_pin.h
@@ -94,6 +94,36 @@
 #define MICROPY_HW_ENABLE_GPIO20 (1)
 #define MICROPY_HW_ENABLE_GPIO21 (1)
 
+#elif CONFIG_IDF_TARGET_ESP32C6
+
+#define MICROPY_HW_ENABLE_GPIO0 (1)
+#define MICROPY_HW_ENABLE_GPIO1 (1)
+#define MICROPY_HW_ENABLE_GPIO2 (1)
+#define MICROPY_HW_ENABLE_GPIO3 (1)
+#define MICROPY_HW_ENABLE_GPIO4 (1)
+#define MICROPY_HW_ENABLE_GPIO5 (1)
+#define MICROPY_HW_ENABLE_GPIO6 (1)
+#define MICROPY_HW_ENABLE_GPIO7 (1)
+#define MICROPY_HW_ENABLE_GPIO8 (1)
+#define MICROPY_HW_ENABLE_GPIO9 (1)
+#define MICROPY_HW_ENABLE_GPIO10 (1)
+#define MICROPY_HW_ENABLE_GPIO11 (1)
+#if !CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
+#define MICROPY_HW_ENABLE_GPIO12 (1)
+#define MICROPY_HW_ENABLE_GPIO13 (1)
+#endif
+#define MICROPY_HW_ENABLE_GPIO14 (1)
+#define MICROPY_HW_ENABLE_GPIO15 (1)
+#define MICROPY_HW_ENABLE_GPIO16 (1)
+#define MICROPY_HW_ENABLE_GPIO17 (1)
+#define MICROPY_HW_ENABLE_GPIO18 (1)
+#define MICROPY_HW_ENABLE_GPIO19 (1)
+#define MICROPY_HW_ENABLE_GPIO20 (1)
+#define MICROPY_HW_ENABLE_GPIO21 (1)
+#define MICROPY_HW_ENABLE_GPIO22 (1)
+#define MICROPY_HW_ENABLE_GPIO23 (1)
+// GPIO 24-30 are used for spi/sip flash.
+
 #elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
 
 #define MICROPY_HW_ENABLE_GPIO0 (1)
diff --git a/ports/esp32/machine_pwm.c b/ports/esp32/machine_pwm.c
index e5d8986..71402e1 100644
--- a/ports/esp32/machine_pwm.c
+++ b/ports/esp32/machine_pwm.c
@@ -241,7 +241,11 @@
         // Configure the new resolution and frequency
         timer->duty_resolution = res;
         timer->freq_hz = freq;
+        #if SOC_LEDC_SUPPORT_XTAL_CLOCK
+        timer->clk_cfg = LEDC_USE_XTAL_CLK;
+        #else
         timer->clk_cfg = LEDC_USE_APB_CLK;
+        #endif
         #if SOC_LEDC_SUPPORT_REF_TICK
         if (freq < EMPIRIC_FREQ) {
             timer->clk_cfg = LEDC_USE_REF_TICK;
diff --git a/ports/esp32/main_esp32c3/CMakeLists.txt b/ports/esp32/main_esp32c3/CMakeLists.txt
index c9f1e5b..307c0f3 100644
--- a/ports/esp32/main_esp32c3/CMakeLists.txt
+++ b/ports/esp32/main_esp32c3/CMakeLists.txt
@@ -9,5 +9,6 @@
 endif()
 
 list(APPEND MICROPY_SOURCE_LIB ${MICROPY_DIR}/shared/runtime/gchelper_generic.c)
+list(APPEND IDF_COMPONENTS riscv)
 
 include(${MICROPY_PORT_DIR}/esp32_common.cmake)
diff --git a/ports/esp32/main_esp32c6/CMakeLists.txt b/ports/esp32/main_esp32c6/CMakeLists.txt
new file mode 100644
index 0000000..307c0f3
--- /dev/null
+++ b/ports/esp32/main_esp32c6/CMakeLists.txt
@@ -0,0 +1,14 @@
+# Set location of base MicroPython directory.
+if(NOT MICROPY_DIR)
+    get_filename_component(MICROPY_DIR ${CMAKE_CURRENT_LIST_DIR}/../../.. ABSOLUTE)
+endif()
+
+# Set location of the ESP32 port directory.
+if(NOT MICROPY_PORT_DIR)
+    get_filename_component(MICROPY_PORT_DIR ${MICROPY_DIR}/ports/esp32 ABSOLUTE)
+endif()
+
+list(APPEND MICROPY_SOURCE_LIB ${MICROPY_DIR}/shared/runtime/gchelper_generic.c)
+list(APPEND IDF_COMPONENTS riscv)
+
+include(${MICROPY_PORT_DIR}/esp32_common.cmake)
diff --git a/ports/esp32/main_esp32c6/idf_component.yml b/ports/esp32/main_esp32c6/idf_component.yml
new file mode 100644
index 0000000..5bbab6d
--- /dev/null
+++ b/ports/esp32/main_esp32c6/idf_component.yml
@@ -0,0 +1,5 @@
+## IDF Component Manager Manifest File
+dependencies:
+  espressif/mdns: "~1.1.0"
+  idf:
+    version: ">=5.1.0"
diff --git a/ports/esp32/main_esp32c6/linker.lf b/ports/esp32/main_esp32c6/linker.lf
new file mode 100644
index 0000000..cedabcf
--- /dev/null
+++ b/ports/esp32/main_esp32c6/linker.lf
@@ -0,0 +1 @@
+# Empty linker fragment (no workaround required for C6, see main_esp32/linker.lf).
diff --git a/ports/esp32/modesp32.c b/ports/esp32/modesp32.c
index 1ee9153..e6e6779 100644
--- a/ports/esp32/modesp32.c
+++ b/ports/esp32/modesp32.c
@@ -29,7 +29,6 @@
 
 #include <time.h>
 #include <sys/time.h>
-#include "soc/rtc_cntl_reg.h"
 #include "driver/gpio.h"
 #include "driver/adc.h"
 #include "esp_heap_caps.h"
diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c
index 5e05a26..d77b831 100644
--- a/ports/esp32/modmachine.c
+++ b/ports/esp32/modmachine.c
@@ -90,9 +90,8 @@
 
 static bool is_soft_reset = 0;
 
-#if CONFIG_IDF_TARGET_ESP32C3
-int esp_clk_cpu_freq(void);
-#endif
+// Note: this is from a private IDF header
+extern int esp_clk_cpu_freq(void);
 
 static mp_obj_t mp_machine_get_freq(void) {
     return mp_obj_new_int(esp_rom_get_cpu_ticks_per_us() * 1000000);
@@ -101,11 +100,11 @@
 static void mp_machine_set_freq(size_t n_args, const mp_obj_t *args) {
     mp_int_t freq = mp_obj_get_int(args[0]) / 1000000;
     if (freq != 20 && freq != 40 && freq != 80 && freq != 160
-        #if !CONFIG_IDF_TARGET_ESP32C3
+        #if !(CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6)
         && freq != 240
         #endif
         ) {
-        #if CONFIG_IDF_TARGET_ESP32C3
+        #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6
         mp_raise_ValueError(MP_ERROR_TEXT("frequency must be 20MHz, 40MHz, 80Mhz or 160MHz"));
         #else
         mp_raise_ValueError(MP_ERROR_TEXT("frequency must be 20MHz, 40MHz, 80Mhz, 160MHz or 240MHz"));
@@ -118,6 +117,8 @@
     esp_pm_config_esp32_t pm;
     #elif CONFIG_IDF_TARGET_ESP32C3
     esp_pm_config_esp32c3_t pm;
+    #elif CONFIG_IDF_TARGET_ESP32C6
+    esp_pm_config_esp32c6_t pm;
     #elif CONFIG_IDF_TARGET_ESP32S2
     esp_pm_config_esp32s2_t pm;
     #elif CONFIG_IDF_TARGET_ESP32S3
@@ -146,7 +147,7 @@
         esp_sleep_enable_timer_wakeup(((uint64_t)expiry) * 1000);
     }
 
-    #if !CONFIG_IDF_TARGET_ESP32C3
+    #if !(CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C6)
 
     if (machine_rtc_config.ext0_pin != -1 && (machine_rtc_config.ext0_wake_types & wake_type)) {
         esp_sleep_enable_ext0_wakeup(machine_rtc_config.ext0_pin, machine_rtc_config.ext0_level ? 1 : 0);
diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h
index 4c94fd1..1c5789d 100644
--- a/ports/esp32/mpconfigport.h
+++ b/ports/esp32/mpconfigport.h
@@ -18,7 +18,7 @@
 
 // object representation and NLR handling
 #define MICROPY_OBJ_REPR                    (MICROPY_OBJ_REPR_A)
-#if !CONFIG_IDF_TARGET_ESP32C3
+#if CONFIG_IDF_TARGET_ARCH_XTENSA
 #define MICROPY_NLR_SETJMP                  (1)
 #endif
 
@@ -41,10 +41,10 @@
 
 // emitters
 #define MICROPY_PERSISTENT_CODE_LOAD        (1)
-#if !CONFIG_IDF_TARGET_ESP32C3
-#define MICROPY_EMIT_XTENSAWIN              (1)
-#else
+#if CONFIG_IDF_TARGET_ARCH_RISCV
 #define MICROPY_EMIT_RV32                   (1)
+#else
+#define MICROPY_EMIT_XTENSAWIN              (1)
 #endif
 
 // optimisations
@@ -161,6 +161,8 @@
 #define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32s3"
 #elif CONFIG_IDF_TARGET_ESP32C3
 #define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32c3"
+#elif CONFIG_IDF_TARGET_ESP32C6
+#define MICROPY_PY_NETWORK_HOSTNAME_DEFAULT "mpy-esp32c6"
 #endif
 #endif
 #define MICROPY_PY_NETWORK_INCLUDEFILE      "ports/esp32/modnetwork.h"
@@ -364,11 +366,7 @@
 
 #if MICROPY_PY_NETWORK_LAN && CONFIG_ETH_USE_SPI_ETHERNET
 #ifndef MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ
-#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32C2
-#define MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ       (12)
-#else
-#define MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ       (36)
-#endif
+#define MICROPY_PY_NETWORK_LAN_SPI_CLOCK_SPEED_MZ       (20)
 #endif
 #endif
 
diff --git a/ports/esp32/mphalport.h b/ports/esp32/mphalport.h
index 9a7c394..f95cf21 100644
--- a/ports/esp32/mphalport.h
+++ b/ports/esp32/mphalport.h
@@ -73,7 +73,7 @@
 uint32_t mp_hal_ticks_us(void);
 __attribute__((always_inline)) static inline uint32_t mp_hal_ticks_cpu(void) {
     uint32_t ccount;
-    #if CONFIG_IDF_TARGET_ESP32C3
+    #if CONFIG_IDF_TARGET_ARCH_RISCV
     __asm__ __volatile__ ("csrr %0, 0x7E2" : "=r" (ccount)); // Machine Performance Counter Value
     #else
     __asm__ __volatile__ ("rsr %0,ccount" : "=a" (ccount));