esp32: Add SDCard support for S3, and a GENERIC_S3_SPIRAM board.

Also add support for GPIO 47 and 48 on S3 boards.
diff --git a/ports/esp32/boards/GENERIC_S3/mpconfigboard.h b/ports/esp32/boards/GENERIC_S3/mpconfigboard.h
index 562521c..53caa7f 100644
--- a/ports/esp32/boards/GENERIC_S3/mpconfigboard.h
+++ b/ports/esp32/boards/GENERIC_S3/mpconfigboard.h
@@ -2,12 +2,11 @@
 #define MICROPY_HW_MCU_NAME                 "ESP32S3"
 
 #define MICROPY_PY_BLUETOOTH                (0)
-#define MICROPY_HW_ENABLE_SDCARD            (0)
 #define MICROPY_PY_MACHINE_DAC              (0)
 
 #define MICROPY_HW_I2C0_SCL                 (9)
 #define MICROPY_HW_I2C0_SDA                 (8)
 
-#define MICROPY_HW_SPI1_MOSI                (35)  // SDO
-#define MICROPY_HW_SPI1_MISO                (37)  // SDI
-#define MICROPY_HW_SPI1_SCK                 (36)
+#define MICROPY_HW_SPI1_MOSI                (35)
+#define MICROPY_HW_SPI1_MISO                (36)
+#define MICROPY_HW_SPI1_SCK                 (37)
diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM/board.json b/ports/esp32/boards/GENERIC_S3_SPIRAM/board.json
new file mode 100644
index 0000000..47bc34e
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_S3_SPIRAM/board.json
@@ -0,0 +1,16 @@
+{
+    "deploy": [
+        "../deploy.md"
+    ],
+    "docs": "",
+    "features": [
+        "BLE",
+        "WiFi"
+    ],
+    "images": [],
+    "mcu": "esp32s3",
+    "product": "Generic ESP32-S3 (SPIRAM)",
+    "thumbnail": "",
+    "url": "https://www.espressif.com/en/products/modules",
+    "vendor": "Espressif"
+}
diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.cmake b/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.cmake
new file mode 100644
index 0000000..682c314
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.cmake
@@ -0,0 +1,12 @@
+set(IDF_TARGET esp32s3)
+
+set(SDKCONFIG_DEFAULTS
+    boards/sdkconfig.base
+    boards/sdkconfig.usb
+    boards/sdkconfig.spiram_sx
+    boards/GENERIC_S3_SPIRAM/sdkconfig.board
+)
+
+if(NOT MICROPY_FROZEN_MANIFEST)
+    set(MICROPY_FROZEN_MANIFEST ${MICROPY_PORT_DIR}/boards/manifest.py)
+endif()
diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h b/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h
new file mode 100644
index 0000000..10085ae
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_S3_SPIRAM/mpconfigboard.h
@@ -0,0 +1,12 @@
+#define MICROPY_HW_BOARD_NAME               "ESP32S3 module (spiram)"
+#define MICROPY_HW_MCU_NAME                 "ESP32S3"
+
+#define MICROPY_PY_BLUETOOTH                (0)
+#define MICROPY_PY_MACHINE_DAC              (0)
+
+#define MICROPY_HW_I2C0_SCL                 (9)
+#define MICROPY_HW_I2C0_SDA                 (8)
+
+#define MICROPY_HW_SPI1_MOSI                (35)
+#define MICROPY_HW_SPI1_MISO                (36)
+#define MICROPY_HW_SPI1_SCK                 (37)
diff --git a/ports/esp32/boards/GENERIC_S3_SPIRAM/sdkconfig.board b/ports/esp32/boards/GENERIC_S3_SPIRAM/sdkconfig.board
new file mode 100644
index 0000000..c9726d4
--- /dev/null
+++ b/ports/esp32/boards/GENERIC_S3_SPIRAM/sdkconfig.board
@@ -0,0 +1,12 @@
+CONFIG_FLASHMODE_QIO=y
+CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
+CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
+CONFIG_ESPTOOLPY_AFTER_NORESET=y
+
+CONFIG_SPIRAM_MEMTEST=
+
+CONFIG_ESPTOOLPY_FLASHSIZE_4MB=
+CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
+CONFIG_ESPTOOLPY_FLASHSIZE_16MB=
+CONFIG_PARTITION_TABLE_CUSTOM=y
+CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-8MiB.csv"
diff --git a/ports/esp32/boards/sdkconfig.spiram_sx b/ports/esp32/boards/sdkconfig.spiram_sx
index 18a0712..ef24e90 100644
--- a/ports/esp32/boards/sdkconfig.spiram_sx
+++ b/ports/esp32/boards/sdkconfig.spiram_sx
@@ -1,5 +1,7 @@
 # MicroPython on ESP32-S2 and ESP32-PAD1_subscript_3, ESP IDF configuration with SPIRAM support
 CONFIG_ESP32S2_SPIRAM_SUPPORT=y
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_MODE_QUAD=y
 CONFIG_SPIRAM_TYPE_AUTO=y
 CONFIG_DEFAULT_PSRAM_CLK_IO=30
 CONFIG_DEFAULT_PSRAM_CS_IO=26
@@ -9,3 +11,5 @@
 CONFIG_SPIRAM_IGNORE_NOTFOUND=y
 CONFIG_SPIRAM_USE_MEMMAP=y
 CONFIG_SPIRAM_MEMTEST=y
+CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
+CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768
diff --git a/ports/esp32/machine_pin.c b/ports/esp32/machine_pin.c
index bf61122..42c4194 100644
--- a/ports/esp32/machine_pin.c
+++ b/ports/esp32/machine_pin.c
@@ -200,6 +200,13 @@
     {{&machine_pin_type}, GPIO_NUM_46},
 
     #endif
+
+    #if CONFIG_IDF_TARGET_ESP32S3 && MICROPY_HW_ESP32S3_EXTENDED_IO
+
+    {{&machine_pin_type}, GPIO_NUM_47},
+    {{&machine_pin_type}, GPIO_NUM_48},
+
+    #endif
 };
 
 // forward declaration
@@ -631,6 +638,14 @@
     {{&machine_pin_irq_type}, GPIO_NUM_43},
     {{&machine_pin_irq_type}, GPIO_NUM_44},
     {{&machine_pin_irq_type}, GPIO_NUM_45},
+    {{&machine_pin_irq_type}, GPIO_NUM_46},
+
+    #endif
+
+    #if CONFIG_IDF_TARGET_ESP32S3 && MICROPY_HW_ESP32S3_EXTENDED_IO
+
+    {{&machine_pin_irq_type}, GPIO_NUM_47},
+    {{&machine_pin_irq_type}, GPIO_NUM_48},
 
     #endif
 };
diff --git a/ports/esp32/machine_sdcard.c b/ports/esp32/machine_sdcard.c
index 3f70311..82c2e6c 100644
--- a/ports/esp32/machine_sdcard.c
+++ b/ports/esp32/machine_sdcard.c
@@ -188,7 +188,11 @@
     }
 
     if (is_spi) {
+        #if CONFIG_IDF_TARGET_ESP32S3
+        self->host.slot = slot_num ? SPI3_HOST : SPI2_HOST;
+        #else
         self->host.slot = slot_num ? HSPI_HOST : VSPI_HOST;
+        #endif
     }
 
     DEBUG_printf("  Calling host.init()");
@@ -198,6 +202,20 @@
 
     if (is_spi) {
         // SPI interface
+        #if CONFIG_IDF_TARGET_ESP32S3
+        STATIC const sdspi_slot_config_t slot_defaults[2] = {
+            {
+                .gpio_miso = GPIO_NUM_36,
+                .gpio_mosi = GPIO_NUM_35,
+                .gpio_sck = GPIO_NUM_37,
+                .gpio_cs = GPIO_NUM_34,
+                .gpio_cd = SDSPI_SLOT_NO_CD,
+                .gpio_wp = SDSPI_SLOT_NO_WP,
+                .dma_channel = 2
+            },
+            SDSPI_SLOT_CONFIG_DEFAULT()
+        };
+        #else
         STATIC const sdspi_slot_config_t slot_defaults[2] = {
             {
                 .gpio_miso = GPIO_NUM_19,
@@ -210,6 +228,7 @@
             },
             SDSPI_SLOT_CONFIG_DEFAULT()
         };
+        #endif
 
         DEBUG_printf("  Setting up SPI slot configuration");
         sdspi_slot_config_t slot_config = slot_defaults[slot_num];
diff --git a/ports/esp32/main.c b/ports/esp32/main.c
index ca0ab14..c1728e3 100644
--- a/ports/esp32/main.c
+++ b/ports/esp32/main.c
@@ -101,7 +101,7 @@
     #if CONFIG_ESP32_SPIRAM_SUPPORT || CONFIG_SPIRAM_SUPPORT
     // Try to use the entire external SPIRAM directly for the heap
     size_t mp_task_heap_size;
-    void *mp_task_heap = (void *)0x3f800000;
+    void *mp_task_heap = (void *)SOC_EXTRAM_DATA_LOW;
     switch (esp_spiram_get_chip_size()) {
         case ESP_SPIRAM_SIZE_16MBITS:
             mp_task_heap_size = 2 * 1024 * 1024;
@@ -120,7 +120,7 @@
     // Try to use the entire external SPIRAM directly for the heap
     size_t mp_task_heap_size;
     size_t esp_spiram_size = esp_spiram_get_size();
-    void *mp_task_heap = (void *)0x3ff80000 - esp_spiram_size;
+    void *mp_task_heap = (void *)SOC_EXTRAM_DATA_HIGH - esp_spiram_size;
     if (esp_spiram_size > 0) {
         mp_task_heap_size = esp_spiram_size;
     } else {
diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h
index 82bef87..52949c5 100644
--- a/ports/esp32/mpconfigport.h
+++ b/ports/esp32/mpconfigport.h
@@ -315,6 +315,11 @@
 // board specifics
 #define MICROPY_PY_SYS_PLATFORM "esp32"
 
+// ESP32-S3 extended IO for 47 & 48
+#ifndef MICROPY_HW_ESP32S3_EXTENDED_IO
+#define MICROPY_HW_ESP32S3_EXTENDED_IO      (1)
+#endif
+
 #ifndef MICROPY_HW_ENABLE_MDNS_QUERIES
 #define MICROPY_HW_ENABLE_MDNS_QUERIES      (1)
 #endif