You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by pk...@apache.org on 2022/08/11 12:50:00 UTC
[incubator-nuttx] branch master updated: xtensa/esp32s2: Add basic support to SPI
This is an automated email from the ASF dual-hosted git repository.
pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 0b4ef1406d xtensa/esp32s2: Add basic support to SPI
0b4ef1406d is described below
commit 0b4ef1406d6182e9acaade94862e1f01a5ed955f
Author: Alan Carvalho de Assis <ac...@gmail.com>
AuthorDate: Thu Aug 4 15:16:13 2022 -0300
xtensa/esp32s2: Add basic support to SPI
---
arch/xtensa/src/esp32s2/Kconfig | 79 ++
arch/xtensa/src/esp32s2/Make.defs | 4 +
arch/xtensa/src/esp32s2/esp32s2_spi.c | 1215 +++++++++++++++++++++
arch/xtensa/src/esp32s2/esp32s2_spi.h | 150 +++
arch/xtensa/src/esp32s2/hardware/esp32s2_pinmap.h | 54 +
arch/xtensa/src/esp32s2/hardware/esp32s2_soc.h | 2 +
arch/xtensa/src/esp32s2/hardware/esp32s2_spi.h | 136 +--
7 files changed, 1572 insertions(+), 68 deletions(-)
diff --git a/arch/xtensa/src/esp32s2/Kconfig b/arch/xtensa/src/esp32s2/Kconfig
index 01c68a72b4..ff5a671adf 100644
--- a/arch/xtensa/src/esp32s2/Kconfig
+++ b/arch/xtensa/src/esp32s2/Kconfig
@@ -237,6 +237,10 @@ config ESP32S2_I2C
bool
default n
+config ESP32S2_SPI
+ bool
+ default n
+
config ESP32S2_TIMER
bool
default n
@@ -252,6 +256,18 @@ config ESP32S2_RNG
---help---
ESP32-S2 supports a RNG that passed on Dieharder test suite.
+config ESP32S2_SPI2
+ bool "SPI 2"
+ default n
+ select ESP32S2_SPI
+ select SPI
+
+config ESP32S2_SPI3
+ bool "SPI 3"
+ default n
+ select ESP32S2_SPI
+ select SPI
+
config ESP32S2_SPIFLASH
bool "SPI Flash"
default n
@@ -361,6 +377,69 @@ config ESP32S2_GPIO_IRQ
---help---
Enable support for interrupting GPIO pins.
+menu "SPI configuration"
+ depends on ESP32S2_SPI
+
+config ESP32S2_SPI_SWCS
+ bool "SPI software CS"
+ default n
+ ---help---
+ Use SPI software CS.
+
+config ESP32S2_SPI_UDCS
+ bool "User defined CS"
+ default n
+ depends on ESP32S2_SPI_SWCS
+ ---help---
+ Use user-defined CS.
+
+if ESP32S2_SPI2
+config ESP32S2_SPI2_CSPIN
+ int "SPI2 CS Pin"
+ default 10
+ range 0 48
+
+config ESP32S2_SPI2_CLKPIN
+ int "SPI2 CLK Pin"
+ default 12
+ range 0 48
+
+config ESP32S2_SPI2_MOSIPIN
+ int "SPI2 MOSI Pin"
+ default 11
+ range 0 48
+
+config ESP32S2_SPI2_MISOPIN
+ int "SPI2 MISO Pin"
+ default 13
+ range 0 48
+
+endif # ESP32S2_SPI2
+
+if ESP32S2_SPI3
+config ESP32S2_SPI3_CSPIN
+ int "SPI3 CS Pin"
+ default 10
+ range 0 48
+
+config ESP32S2_SPI3_CLKPIN
+ int "SPI3 CLK Pin"
+ default 12
+ range 0 48
+
+config ESP32S2_SPI3_MOSIPIN
+ int "SPI3 MOSI Pin"
+ default 11
+ range 0 48
+
+config ESP32S2_SPI3_MISOPIN
+ int "SPI3 MISO Pin"
+ default 13
+ range 0 48
+
+endif # ESP32S2_SPI3
+endmenu
+
menu "UART Configuration"
depends on ESP32S2_UART
diff --git a/arch/xtensa/src/esp32s2/Make.defs b/arch/xtensa/src/esp32s2/Make.defs
index db87863817..6d79385633 100644
--- a/arch/xtensa/src/esp32s2/Make.defs
+++ b/arch/xtensa/src/esp32s2/Make.defs
@@ -49,6 +49,10 @@ ifeq ($(CONFIG_ESP32S2_I2C),y)
CHIP_CSRCS += esp32s2_i2c.c
endif
+ifeq ($(CONFIG_ESP32S2_SPI),y)
+CHIP_CSRCS += esp32s2_spi.c
+endif
+
ifeq ($(CONFIG_ESP32S2_TIMER),y)
CHIP_CSRCS += esp32s2_tim.c
ifeq ($(CONFIG_TIMER),y)
diff --git a/arch/xtensa/src/esp32s2/esp32s2_spi.c b/arch/xtensa/src/esp32s2/esp32s2_spi.c
new file mode 100644
index 0000000000..d86f418846
--- /dev/null
+++ b/arch/xtensa/src/esp32s2/esp32s2_spi.c
@@ -0,0 +1,1215 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32s2/esp32s2_spi.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_ESP32S2_SPI
+
+#include <assert.h>
+#include <debug.h>
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <nuttx/clock.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/spinlock.h>
+#include <nuttx/spi/spi.h>
+
+#include <arch/board/board.h>
+
+#include "esp32s2_spi.h"
+#include "esp32s2_irq.h"
+#include "esp32s2_gpio.h"
+
+#include "xtensa.h"
+#include "hardware/esp32s2_gpio_sigmap.h"
+#include "hardware/esp32s2_pinmap.h"
+#include "hardware/esp32s2_spi.h"
+#include "hardware/esp32s2_soc.h"
+#include "hardware/esp32s2_system.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Check if Chip-Select pin will be controlled via software */
+
+#ifdef CONFIG_ESP32S2_SPI_SWCS
+# define SPI_HAVE_SWCS 1
+#else
+# define SPI_HAVE_SWCS 0
+#endif
+
+/* SPI default frequency (limited by clock divider) */
+
+#define SPI_DEFAULT_FREQ (400000)
+
+/* SPI default width */
+
+#define SPI_DEFAULT_WIDTH (8)
+
+/* SPI default mode */
+
+#define SPI_DEFAULT_MODE (SPIDEV_MODE0)
+
+/* SPI Maximum buffer size in bytes */
+
+#define SPI_MAX_BUF_SIZE (64)
+
+#ifndef MIN
+# define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* SPI Device hardware configuration */
+
+struct esp32s2_spi_config_s
+{
+ uint32_t clk_freq; /* SPI default clock frequency */
+ uint32_t width; /* SPI default width */
+ enum spi_mode_e mode; /* SPI default mode */
+
+ uint8_t id; /* ESP32-S2 SPI device ID: SPIx {2,3} */
+ uint8_t cs_pin; /* GPIO configuration for CS */
+ uint8_t mosi_pin; /* GPIO configuration for MOSI */
+ uint8_t miso_pin; /* GPIO configuration for MISO */
+ uint8_t clk_pin; /* GPIO configuration for CLK */
+ uint32_t clk_bit; /* Clock enable bit */
+ uint32_t rst_bit; /* SPI reset bit */
+ uint32_t cs_insig; /* SPI CS input signal index */
+ uint32_t cs_outsig; /* SPI CS output signal index */
+ uint32_t mosi_insig; /* SPI MOSI input signal index */
+ uint32_t mosi_outsig; /* SPI MOSI output signal index */
+ uint32_t miso_insig; /* SPI MISO input signal index */
+ uint32_t miso_outsig; /* SPI MISO output signal index */
+ uint32_t clk_insig; /* SPI CLK input signal index */
+ uint32_t clk_outsig; /* SPI CLK output signal index */
+};
+
+struct esp32s2_spi_priv_s
+{
+ /* Externally visible part of the SPI interface */
+
+ struct spi_dev_s spi_dev;
+
+ /* Port configuration */
+
+ const struct esp32s2_spi_config_s *config;
+ int refs; /* Reference count */
+ sem_t exclsem; /* Held while chip is selected for mutual exclusion */
+ uint32_t frequency; /* Requested clock frequency */
+ uint32_t actual; /* Actual clock frequency */
+ enum spi_mode_e mode; /* Actual SPI hardware mode */
+ uint8_t nbits; /* Actual SPI send/receive bits once transmission */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int esp32s2_spi_lock(struct spi_dev_s *dev, bool lock);
+#ifndef CONFIG_ESP32S2_SPI_UDCS
+static void esp32s2_spi_select(struct spi_dev_s *dev,
+ uint32_t devid, bool selected);
+#endif
+static uint32_t esp32s2_spi_setfrequency(struct spi_dev_s *dev,
+ uint32_t frequency);
+static void esp32s2_spi_setmode(struct spi_dev_s *dev,
+ enum spi_mode_e mode);
+static void esp32s2_spi_setbits(struct spi_dev_s *dev, int nbits);
+#ifdef CONFIG_SPI_HWFEATURES
+static int esp32s2_spi_hwfeatures(struct spi_dev_s *dev,
+ spi_hwfeatures_t features);
+#endif
+static uint32_t esp32s2_spi_send(struct spi_dev_s *dev, uint32_t wd);
+static void esp32s2_spi_exchange(struct spi_dev_s *dev,
+ const void *txbuffer,
+ void *rxbuffer, size_t nwords);
+static void esp32s2_spi_poll_exchange(struct esp32s2_spi_priv_s *priv,
+ const void *txbuffer,
+ void *rxbuffer,
+ size_t nwords);
+#ifndef CONFIG_SPI_EXCHANGE
+static void esp32s2_spi_sndblock(struct spi_dev_s *dev,
+ const void *txbuffer,
+ size_t nwords);
+static void esp32s2_spi_recvblock(struct spi_dev_s *dev,
+ void *rxbuffer,
+ size_t nwords);
+#endif
+#ifdef CONFIG_SPI_TRIGGER
+static int esp32s2_spi_trigger(struct spi_dev_s *dev);
+#endif
+static void esp32s2_spi_init(struct spi_dev_s *dev);
+static void esp32s2_spi_deinit(struct spi_dev_s *dev);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32S2_SPI2
+static const struct esp32s2_spi_config_s esp32s2_spi2_config =
+{
+ .clk_freq = SPI_DEFAULT_FREQ,
+ .width = SPI_DEFAULT_WIDTH,
+ .id = 2,
+ .mode = SPI_DEFAULT_MODE,
+ .cs_pin = CONFIG_ESP32S2_SPI2_CSPIN,
+ .mosi_pin = CONFIG_ESP32S2_SPI2_MOSIPIN,
+ .miso_pin = CONFIG_ESP32S2_SPI2_MISOPIN,
+ .clk_pin = CONFIG_ESP32S2_SPI2_CLKPIN,
+ .clk_bit = SYSTEM_SPI2_CLK_EN,
+ .rst_bit = SYSTEM_SPI2_RST,
+ .cs_insig = FSPICS0_IN_IDX,
+ .cs_outsig = FSPICS0_OUT_IDX,
+ .mosi_insig = FSPID_IN_IDX,
+ .mosi_outsig = FSPID_OUT_IDX,
+ .miso_insig = FSPIQ_IN_IDX,
+ .miso_outsig = FSPIQ_OUT_IDX,
+ .clk_insig = FSPICLK_IN_IDX,
+ .clk_outsig = FSPICLK_OUT_IDX
+};
+
+static const struct spi_ops_s esp32s2_spi2_ops =
+{
+#ifdef CONFIG_ESP32S2_SPI_UDCS
+ .select = esp32s2_spi2_select,
+#else
+ .select = esp32s2_spi_select,
+#endif
+ .setfrequency = esp32s2_spi_setfrequency,
+ .setmode = esp32s2_spi_setmode,
+ .setbits = esp32s2_spi_setbits,
+#ifdef CONFIG_SPI_HWFEATURES
+ .hwfeatures = esp32s2_spi_hwfeatures,
+#endif
+ .status = esp32s2_spi2_status,
+#ifdef CONFIG_SPI_CMDDATA
+ .cmddata = esp32s2_spi2_cmddata,
+#endif
+ .send = esp32s2_spi_send,
+#ifdef CONFIG_SPI_EXCHANGE
+ .exchange = esp32s2_spi_exchange,
+#else
+ .sndblock = esp32s2_spi_sndblock,
+ .recvblock = esp32s2_spi_recvblock,
+#endif
+#ifdef CONFIG_SPI_TRIGGER
+ .trigger = esp32s2_spi_trigger,
+#endif
+ .registercallback = NULL,
+};
+
+static struct esp32s2_spi_priv_s esp32s2_spi2_priv =
+{
+ .spi_dev =
+ {
+ .ops = &esp32s2_spi2_ops
+ },
+ .config = &esp32s2_spi2_config,
+ .refs = 0,
+ .exclsem = SEM_INITIALIZER(0),
+ .frequency = 0,
+ .actual = 0,
+ .mode = 0,
+ .nbits = 0
+};
+#endif /* CONFIG_ESP32S2_SPI2 */
+
+#ifdef CONFIG_ESP32S2_SPI3
+static const struct esp32s2_spi_config_s esp32s2_spi3_config =
+{
+ .clk_freq = SPI_DEFAULT_FREQ,
+ .width = SPI_DEFAULT_WIDTH,
+ .id = 3,
+ .mode = SPI_DEFAULT_MODE,
+ .cs_pin = CONFIG_ESP32S2_SPI3_CSPIN,
+ .mosi_pin = CONFIG_ESP32S2_SPI3_MOSIPIN,
+ .miso_pin = CONFIG_ESP32S2_SPI3_MISOPIN,
+ .clk_pin = CONFIG_ESP32S2_SPI3_CLKPIN,
+ .clk_bit = SYSTEM_SPI3_CLK_EN,
+ .rst_bit = SYSTEM_SPI3_RST,
+ .cs_insig = FSPICS0_IN_IDX,
+ .cs_outsig = FSPICS0_OUT_IDX,
+ .mosi_insig = FSPID_IN_IDX,
+ .mosi_outsig = FSPID_OUT_IDX,
+ .miso_insig = FSPIQ_IN_IDX,
+ .miso_outsig = FSPIQ_OUT_IDX,
+ .clk_insig = FSPICLK_IN_IDX,
+ .clk_outsig = FSPICLK_OUT_IDX
+};
+
+static const struct spi_ops_s esp32s2_spi3_ops =
+{
+#ifdef CONFIG_ESP32S2_SPI_UDCS
+ .select = esp32s2_spi3_select,
+#else
+ .select = esp32s2_spi_select,
+#endif
+ .setfrequency = esp32s2_spi_setfrequency,
+ .setmode = esp32s2_spi_setmode,
+ .setbits = esp32s2_spi_setbits,
+#ifdef CONFIG_SPI_HWFEATURES
+ .hwfeatures = esp32s2_spi_hwfeatures,
+#endif
+ .status = esp32s2_spi3_status,
+#ifdef CONFIG_SPI_CMDDATA
+ .cmddata = esp32s2_spi3_cmddata,
+#endif
+ .send = esp32s2_spi_send,
+#ifdef CONFIG_SPI_EXCHANGE
+ .exchange = esp32s2_spi_exchange,
+#else
+ .sndblock = esp32s2_spi_sndblock,
+ .recvblock = esp32s2_spi_recvblock,
+#endif
+#ifdef CONFIG_SPI_TRIGGER
+ .trigger = esp32s2_spi_trigger,
+#endif
+ .registercallback = NULL,
+};
+
+static struct esp32s2_spi_priv_s esp32s2_spi3_priv =
+{
+ .spi_dev =
+ {
+ .ops = &esp32s2_spi3_ops
+ },
+ .config = &esp32s2_spi3_config,
+ .refs = 0,
+ .exclsem = SEM_INITIALIZER(0),
+ .frequency = 0,
+ .actual = 0,
+ .mode = 0,
+ .nbits = 0
+};
+#endif /* CONFIG_ESP32S2_SPI3 */
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32s2_spi_set_regbits
+ *
+ * Description:
+ * Set the bits of the SPI register.
+ *
+ * Input Parameters:
+ * addr - Address of the register of interest
+ * bits - Bits to be set
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+static inline void esp32s2_spi_set_regbits(uint32_t addr, uint32_t bits)
+{
+ uint32_t tmp = getreg32(addr);
+
+ putreg32(tmp | bits, addr);
+}
+
+/****************************************************************************
+ * Name: esp32s2_spi_clr_regbits
+ *
+ * Description:
+ * Clear the bits of the SPI register.
+ *
+ * Input Parameters:
+ * addr - Address of the register of interest
+ * bits - Bits to be cleared
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+static inline void esp32s2_spi_clr_regbits(uint32_t addr, uint32_t bits)
+{
+ uint32_t tmp = getreg32(addr);
+
+ putreg32(tmp & ~bits, addr);
+}
+
+/****************************************************************************
+ * Name: esp32s2_spi_iomux
+ *
+ * Description:
+ * Check if the option SPI GPIO pins can use IOMUX directly
+ *
+ * Input Parameters:
+ * priv - Private SPI device structure
+ *
+ * Returned Value:
+ * True if can use IOMUX or false if can't.
+ *
+ ****************************************************************************/
+
+static inline bool esp32s2_spi_iomux(struct esp32s2_spi_priv_s *priv)
+{
+ bool mapped = false;
+ const struct esp32s2_spi_config_s *cfg = priv->config;
+
+ /* We only need to check SPI2, SPI3 doesn't support IOMUX */
+
+ if (cfg->id == 2)
+ {
+ if (cfg->mosi_pin == SPI2_IOMUX_MOSIPIN &&
+#ifndef CONFIG_ESP32S2_SPI_SWCS
+ cfg->cs_pin == SPI2_IOMUX_CSPIN &&
+#endif
+ cfg->miso_pin == SPI2_IOMUX_MISOPIN &&
+ cfg->clk_pin == SPI2_IOMUX_CLKPIN)
+ {
+ mapped = true;
+ }
+ }
+
+ return mapped;
+}
+
+/****************************************************************************
+ * Name: esp32s2_spi_lock
+ *
+ * Description:
+ * Lock or unlock the SPI device.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * lock - true: Lock SPI bus, false: unlock SPI bus
+ *
+ * Returned Value:
+ * The result of lock or unlock the SPI device.
+ *
+ ****************************************************************************/
+
+static int esp32s2_spi_lock(struct spi_dev_s *dev, bool lock)
+{
+ int ret;
+ struct esp32s2_spi_priv_s *priv = (struct esp32s2_spi_priv_s *)dev;
+
+ if (lock)
+ {
+ ret = nxsem_wait_uninterruptible(&priv->exclsem);
+ }
+ else
+ {
+ ret = nxsem_post(&priv->exclsem);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: esp32s2_spi_select
+ *
+ * Description:
+ * Enable/disable the SPI chip select. The implementation of this method
+ * must include handshaking: If a device is selected, it must hold off
+ * all other attempts to select the device until the device is deselected.
+ *
+ * If ESP32S2_SPI_SWCS is disabled, the driver will use hardware CS so that
+ * once transmission is started the hardware selects the device and when
+ * this transmission is done hardware deselects the device automatically.
+ * So, this function will do nothing.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * devid - Identifies the device to select
+ * selected - true: slave selected, false: slave de-selected
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_ESP32S2_SPI_UDCS
+static void esp32s2_spi_select(struct spi_dev_s *dev,
+ uint32_t devid, bool selected)
+{
+#if SPI_HAVE_SWCS
+ struct esp32s2_spi_priv_s *priv = (struct esp32s2_spi_priv_s *)dev;
+
+ esp32s2_gpiowrite(priv->config->cs_pin, !selected);
+#endif
+
+ spiinfo("devid: %08" PRIx32 " CS: %s\n",
+ devid, selected ? "select" : "free");
+}
+#endif
+
+/****************************************************************************
+ * Name: esp32s2_spi_setfrequency
+ *
+ * Description:
+ * Set the SPI frequency.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * frequency - The requested SPI frequency
+ *
+ * Returned Value:
+ * Returns the current selected frequency.
+ *
+ ****************************************************************************/
+
+static uint32_t esp32s2_spi_setfrequency(struct spi_dev_s *dev,
+ uint32_t frequency)
+{
+ uint32_t reg_val;
+ struct esp32s2_spi_priv_s *priv = (struct esp32s2_spi_priv_s *)dev;
+ const uint32_t duty_cycle = 128;
+
+ if (priv->frequency == frequency)
+ {
+ /* Requested frequency is the same as the current frequency. */
+
+ return priv->actual;
+ }
+
+ /* In HW, n, h and l fields range from 1 to 64, pre ranges from 1 to 8K.
+ * The value written to register is one lower than the used value.
+ */
+
+ if (frequency > ((APB_CLK_FREQ / 4) * 3))
+ {
+ /* Using APB frequency directly will give us the best result here. */
+
+ reg_val = SPI_CLK_EQU_SYSCLK_M;
+ priv->actual = APB_CLK_FREQ;
+ }
+ else
+ {
+ /* For best duty cycle resolution, we want n to be as close to 32 as
+ * possible, but we also need a pre/n combo that gets us as close as
+ * possible to the intended frequency. To do this, we bruteforce n and
+ * calculate the best pre to go along with that. If there's a choice
+ * between pre/n combos that give the same result, use the one with the
+ * higher n.
+ */
+
+ int32_t pre;
+ int32_t n;
+ int32_t h;
+ int32_t l;
+ int32_t bestn = -1;
+ int32_t bestpre = -1;
+ int32_t besterr = 0;
+ int32_t errval;
+
+ /* Start at n = 2. We need to be able to set h/l so we have at least
+ * one high and one low pulse.
+ */
+
+ for (n = 2; n <= 64; n++)
+ {
+ /* Effectively, this does:
+ * pre = round((APB_CLK_FREQ / n) / frequency)
+ */
+
+ pre = ((APB_CLK_FREQ / n) + (frequency / 2)) / frequency;
+
+ if (pre <= 0)
+ {
+ pre = 1;
+ }
+
+ if (pre > 16)
+ {
+ pre = 16;
+ }
+
+ errval = abs(APB_CLK_FREQ / (pre * n) - frequency);
+ if (bestn == -1 || errval <= besterr)
+ {
+ besterr = errval;
+ bestn = n;
+ bestpre = pre;
+ }
+ }
+
+ n = bestn;
+ pre = bestpre;
+ l = n;
+
+ /* Effectively, this does:
+ * h = round((duty_cycle * n) / 256)
+ */
+
+ h = (duty_cycle * n + 127) / 256;
+ if (h <= 0)
+ {
+ h = 1;
+ }
+
+ reg_val = ((l - 1) << SPI_CLKCNT_L_S) |
+ ((h - 1) << SPI_CLKCNT_H_S) |
+ ((n - 1) << SPI_CLKCNT_N_S) |
+ ((pre - 1) << SPI_CLKDIV_PRE_S);
+
+ priv->actual = APB_CLK_FREQ / (n * pre);
+ }
+
+ priv->frequency = frequency;
+
+ putreg32(reg_val, SPI_CLOCK_REG(priv->config->id));
+
+ spiinfo("frequency=%" PRIu32 ", actual=%" PRIu32 "\n",
+ priv->frequency, priv->actual);
+
+ return priv->actual;
+}
+
+/****************************************************************************
+ * Name: esp32s2_spi_setmode
+ *
+ * Description:
+ * Set the SPI mode.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * mode - The requested SPI mode
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+static void esp32s2_spi_setmode(struct spi_dev_s *dev,
+ enum spi_mode_e mode)
+{
+ struct esp32s2_spi_priv_s *priv = (struct esp32s2_spi_priv_s *)dev;
+
+ spiinfo("mode=%d\n", mode);
+
+ /* Has the mode changed? */
+
+ if (mode != priv->mode)
+ {
+ uint32_t ck_idle_edge;
+ uint32_t ck_out_edge;
+
+ switch (mode)
+ {
+ case SPIDEV_MODE0: /* CPOL=0; CPHA=0 */
+ ck_idle_edge = 0;
+ ck_out_edge = 0;
+ break;
+
+ case SPIDEV_MODE1: /* CPOL=0; CPHA=1 */
+ ck_idle_edge = 0;
+ ck_out_edge = 1;
+ break;
+
+ case SPIDEV_MODE2: /* CPOL=1; CPHA=0 */
+ ck_idle_edge = 1;
+ ck_out_edge = 1;
+ break;
+
+ case SPIDEV_MODE3: /* CPOL=1; CPHA=1 */
+ ck_idle_edge = 1;
+ ck_out_edge = 0;
+ break;
+
+ default:
+ spierr("Invalid mode: %d\n", mode);
+ DEBUGPANIC();
+ return;
+ }
+
+ esp32s2_spi_clr_regbits(SPI_MISC_REG(priv->config->id),
+ SPI_CK_IDLE_EDGE_M);
+ esp32s2_spi_set_regbits(SPI_MISC_REG(priv->config->id),
+ VALUE_TO_FIELD(ck_idle_edge,
+ SPI_CK_IDLE_EDGE));
+
+ esp32s2_spi_clr_regbits(SPI_USER_REG(priv->config->id),
+ SPI_CK_OUT_EDGE_M);
+ esp32s2_spi_set_regbits(SPI_USER_REG(priv->config->id),
+ VALUE_TO_FIELD(ck_out_edge, SPI_CK_OUT_EDGE));
+
+ priv->mode = mode;
+ }
+}
+
+/****************************************************************************
+ * Name: esp32s2_spi_setbits
+ *
+ * Description:
+ * Set the number of bits per word.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * nbits - The number of bits in an SPI word.
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+static void esp32s2_spi_setbits(struct spi_dev_s *dev, int nbits)
+{
+ struct esp32s2_spi_priv_s *priv = (struct esp32s2_spi_priv_s *)dev;
+
+ spiinfo("nbits=%d\n", nbits);
+
+ priv->nbits = nbits;
+}
+
+/****************************************************************************
+ * Name: esp32s2_spi_hwfeatures
+ *
+ * Description:
+ * Set hardware-specific feature flags.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * features - H/W feature flags
+ *
+ * Returned Value:
+ * Zero (OK) if the selected H/W features are enabled; A negated errno
+ * value if any H/W feature is not supportable.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SPI_HWFEATURES
+static int esp32s2_spi_hwfeatures(struct spi_dev_s *dev,
+ spi_hwfeatures_t features)
+{
+ /* Other H/W features are not supported */
+
+ return (features == 0) ? OK : -ENOSYS;
+}
+#endif
+
+/****************************************************************************
+ * Name: esp32s2_spi_poll_send
+ *
+ * Description:
+ * Send one word on SPI by polling mode.
+ *
+ * Input Parameters:
+ * priv - SPI private state data
+ * wd - The word to send. The size of the data is determined by the
+ * number of bits selected for the SPI interface.
+ *
+ * Returned Value:
+ * Received value.
+ *
+ ****************************************************************************/
+
+static uint32_t esp32s2_spi_poll_send(struct esp32s2_spi_priv_s *priv,
+ uint32_t wd)
+{
+ uint32_t val;
+
+ const uintptr_t spi_miso_dlen_reg = SPI_MISO_DLEN_REG(priv->config->id);
+ const uintptr_t spi_mosi_dlen_reg = SPI_MOSI_DLEN_REG(priv->config->id);
+ const uintptr_t spi_w0_reg = SPI_W0_REG(priv->config->id);
+ const uintptr_t spi_cmd_reg = SPI_CMD_REG(priv->config->id);
+
+ putreg32((priv->nbits - 1), spi_miso_dlen_reg);
+ putreg32((priv->nbits - 1), spi_mosi_dlen_reg);
+
+ putreg32(wd, spi_w0_reg);
+
+ esp32s2_spi_set_regbits(spi_cmd_reg, SPI_USR_M);
+
+ while ((getreg32(spi_cmd_reg) & SPI_USR_M) != 0)
+ {
+ ;
+ }
+
+ val = getreg32(spi_w0_reg);
+
+ spiinfo("send=0x%" PRIx32 " and recv=0x%" PRIx32 "\n", wd, val);
+
+ return val;
+}
+
+/****************************************************************************
+ * Name: esp32s2_spi_send
+ *
+ * Description:
+ * Send one word on SPI.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * wd - The word to send. The size of the data is determined by the
+ * number of bits selected for the SPI interface.
+ *
+ * Returned Value:
+ * Received value.
+ *
+ ****************************************************************************/
+
+static uint32_t esp32s2_spi_send(struct spi_dev_s *dev, uint32_t wd)
+{
+ struct esp32s2_spi_priv_s *priv = (struct esp32s2_spi_priv_s *)dev;
+
+ return esp32s2_spi_poll_send(priv, wd);
+}
+
+/****************************************************************************
+ * Name: esp32s2_spi_poll_exchange
+ *
+ * Description:
+ * Exchange a block of data from SPI.
+ *
+ * Input Parameters:
+ * priv - SPI private state data
+ * txbuffer - A pointer to the buffer of data to be sent
+ * rxbuffer - A pointer to the buffer in which to receive data
+ * nwords - The length of data that to be exchanged in units of words.
+ * The wordsize is determined by the number of bits-per-word
+ * selected for the SPI interface. If nbits <= 8, the data is
+ * packed into uint8_t's; if nbits >8, the data is packed into
+ * uint16_t's
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+static void esp32s2_spi_poll_exchange(struct esp32s2_spi_priv_s *priv,
+ const void *txbuffer,
+ void *rxbuffer,
+ size_t nwords)
+{
+ const uint32_t total_bytes = nwords * (priv->nbits / 8);
+ uintptr_t bytes_remaining = total_bytes;
+ const uint8_t *tp = (const uint8_t *)txbuffer;
+ uint8_t *rp = (uint8_t *)rxbuffer;
+
+ while (bytes_remaining != 0)
+ {
+ /* Initialize data_buf_reg with the address of the first data buffer
+ * register (W0).
+ */
+
+ uintptr_t data_buf_reg = SPI_W0_REG(priv->config->id);
+ uint32_t transfer_size = MIN(SPI_MAX_BUF_SIZE, bytes_remaining);
+
+ /* Write data words to data buffer registers.
+ * SPI peripheral contains 16 registers (W0 - W15).
+ */
+
+ for (int i = 0 ; i < transfer_size; i += sizeof(uintptr_t))
+ {
+ uintptr_t w_wd = UINT32_MAX;
+
+ if (tp != NULL)
+ {
+ memcpy(&w_wd, tp, sizeof(uintptr_t));
+
+ tp += sizeof(uintptr_t);
+ }
+
+ putreg32(w_wd, data_buf_reg);
+
+ spiinfo("send=0x%" PRIx32 " data_reg=0x%" PRIxPTR "\n",
+ w_wd, data_buf_reg);
+
+ /* Update data_buf_reg to point to the next data buffer register. */
+
+ data_buf_reg += sizeof(uintptr_t);
+ }
+
+ esp32s2_spi_set_regbits(SPI_USER_REG(priv->config->id),
+ SPI_USR_MOSI_M);
+
+ if (rp == NULL)
+ {
+ esp32s2_spi_clr_regbits(SPI_USER_REG(priv->config->id),
+ SPI_USR_MISO_M);
+ }
+ else
+ {
+ esp32s2_spi_set_regbits(SPI_USER_REG(priv->config->id),
+ SPI_USR_MISO_M);
+ }
+
+ putreg32((transfer_size * 8) - 1,
+ SPI_MOSI_DLEN_REG(priv->config->id));
+
+ putreg32((transfer_size * 8) - 1,
+ SPI_MISO_DLEN_REG(priv->config->id));
+
+ /* Trigger start of user-defined transaction for master. */
+
+ esp32s2_spi_set_regbits(SPI_CMD_REG(priv->config->id), SPI_USR_M);
+
+ /* Wait for the user-defined transaction to finish. */
+
+ while ((getreg32(SPI_CMD_REG(priv->config->id)) & SPI_USR_M) != 0)
+ {
+ ;
+ }
+
+ if (rp != NULL)
+ {
+ /* Set data_buf_reg with the address of the first data buffer
+ * register (W0).
+ */
+
+ data_buf_reg = SPI_W0_REG(priv->config->id);
+
+ /* Read received data words from SPI data buffer registers. */
+
+ for (int i = 0 ; i < transfer_size; i += sizeof(uintptr_t))
+ {
+ uintptr_t r_wd = getreg32(data_buf_reg);
+
+ spiinfo("recv=0x%" PRIx32 " data_reg=0x%" PRIxPTR "\n",
+ r_wd, data_buf_reg);
+
+ memcpy(rp, &r_wd, sizeof(uintptr_t));
+
+ rp += sizeof(uintptr_t);
+
+ /* Update data_buf_reg to point to the next data buffer
+ * register.
+ */
+
+ data_buf_reg += sizeof(uintptr_t);
+ }
+ }
+
+ bytes_remaining -= transfer_size;
+ }
+}
+
+/****************************************************************************
+ * Name: esp32s2_spi_exchange
+ *
+ * Description:
+ * Exchange a block of data from SPI.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * txbuffer - A pointer to the buffer of data to be sent
+ * rxbuffer - A pointer to the buffer in which to receive data
+ * nwords - The length of data that to be exchanged in units of words.
+ * The wordsize is determined by the number of bits-per-word
+ * selected for the SPI interface. If nbits <= 8, the data is
+ * packed into uint8_t's; if nbits >8, the data is packed into
+ * uint16_t's
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+static void esp32s2_spi_exchange(struct spi_dev_s *dev,
+ const void *txbuffer,
+ void *rxbuffer,
+ size_t nwords)
+{
+ struct esp32s2_spi_priv_s *priv = (struct esp32s2_spi_priv_s *)dev;
+
+ esp32s2_spi_poll_exchange(priv, txbuffer, rxbuffer, nwords);
+}
+
+#ifndef CONFIG_SPI_EXCHANGE
+
+/****************************************************************************
+ * Name: esp32s2_spi_sndblock
+ *
+ * Description:
+ * Send a block of data on SPI.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * txbuffer - A pointer to the buffer of data to be sent
+ * nwords - The length of data to send from the buffer in number of
+ * words. The wordsize is determined by the number of
+ * bits-per-word selected for the SPI interface. If nbits <= 8,
+ * the data is packed into uint8_t's; if nbits >8, the data is
+ * packed into uint16_t's
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+static void esp32s2_spi_sndblock(struct spi_dev_s *dev,
+ const void *txbuffer,
+ size_t nwords)
+{
+ spiinfo("txbuffer=%p nwords=%d\n", txbuffer, nwords);
+
+ esp32s2_spi_exchange(dev, txbuffer, NULL, nwords);
+}
+
+/****************************************************************************
+ * Name: esp32s2_spi_recvblock
+ *
+ * Description:
+ * Receive a block of data from SPI.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * rxbuffer - A pointer to the buffer in which to receive data
+ * nwords - The length of data that can be received in the buffer in
+ * number of words. The wordsize is determined by the number of
+ * bits-per-word selected for the SPI interface. If nbits <= 8,
+ * the data is packed into uint8_t's; if nbits >8, the data is
+ * packed into uint16_t's
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+static void esp32s2_spi_recvblock(struct spi_dev_s *dev,
+ void *rxbuffer,
+ size_t nwords)
+{
+ spiinfo("rxbuffer=%p nwords=%d\n", rxbuffer, nwords);
+
+ esp32s2_spi_exchange(dev, NULL, rxbuffer, nwords);
+}
+#endif
+
+/****************************************************************************
+ * Name: esp32s2_spi_init
+ *
+ * Description:
+ * Initialize ESP32-S2 SPI hardware interface.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+static void esp32s2_spi_init(struct spi_dev_s *dev)
+{
+ struct esp32s2_spi_priv_s *priv = (struct esp32s2_spi_priv_s *)dev;
+ const struct esp32s2_spi_config_s *config = priv->config;
+ uint32_t regval;
+
+ /* Initialize the SPI semaphore that enforces mutually exclusive access */
+
+ nxsem_init(&priv->exclsem, 0, 1);
+
+ esp32s2_gpiowrite(config->cs_pin, true);
+ esp32s2_gpiowrite(config->mosi_pin, true);
+ esp32s2_gpiowrite(config->miso_pin, true);
+ esp32s2_gpiowrite(config->clk_pin, true);
+
+#if SPI_HAVE_SWCS
+ esp32s2_configgpio(config->cs_pin, OUTPUT_FUNCTION_1);
+ esp32s2_gpio_matrix_out(config->cs_pin, SIG_GPIO_OUT_IDX, 0, 0);
+#endif
+
+ /* SPI3 doesn't have IOMUX, if SPI3 is enabled use GPIO Matrix for both */
+
+ if (esp32s2_spi_iomux(priv))
+ {
+#if !SPI_HAVE_SWCS
+ esp32s2_configgpio(config->cs_pin, OUTPUT_FUNCTION_5);
+ esp32s2_gpio_matrix_out(config->cs_pin, SIG_GPIO_OUT_IDX, 0, 0);
+#endif
+ esp32s2_configgpio(config->mosi_pin, OUTPUT_FUNCTION_5);
+ esp32s2_gpio_matrix_out(config->mosi_pin, SIG_GPIO_OUT_IDX, 0, 0);
+
+ esp32s2_configgpio(config->miso_pin, INPUT_FUNCTION_5 | PULLUP);
+ esp32s2_gpio_matrix_out(config->miso_pin, SIG_GPIO_OUT_IDX, 0, 0);
+
+ esp32s2_configgpio(config->clk_pin, OUTPUT_FUNCTION_5);
+ esp32s2_gpio_matrix_out(config->clk_pin, SIG_GPIO_OUT_IDX, 0, 0);
+ }
+ else
+ {
+#if !SPI_HAVE_SWCS
+ esp32s2_configgpio(config->cs_pin, OUTPUT);
+ esp32s2_gpio_matrix_out(config->cs_pin, config->cs_outsig, 0, 0);
+#endif
+ esp32s2_configgpio(config->mosi_pin, OUTPUT);
+ esp32s2_gpio_matrix_out(config->mosi_pin, config->mosi_outsig, 0, 0);
+
+ esp32s2_configgpio(config->miso_pin, INPUT | PULLUP);
+ esp32s2_gpio_matrix_in(config->miso_pin, config->miso_insig, 0);
+
+ esp32s2_configgpio(config->clk_pin, OUTPUT);
+ esp32s2_gpio_matrix_out(config->clk_pin, config->clk_outsig, 0, 0);
+ }
+
+ modifyreg32(SYSTEM_PERIP_CLK_EN0_REG, 0, config->clk_bit);
+ modifyreg32(SYSTEM_PERIP_RST_EN0_REG, config->rst_bit, 0);
+
+ regval = SPI_DOUTDIN_M | SPI_USR_MISO_M | SPI_USR_MOSI_M | SPI_CS_HOLD_M;
+ putreg32(regval, SPI_USER_REG(priv->config->id));
+ putreg32(0, SPI_USER1_REG(priv->config->id));
+ putreg32(0, SPI_SLAVE_REG(priv->config->id));
+ putreg32(SPI_CS1_DIS_M | SPI_CS2_DIS_M,
+ SPI_MISC_REG(priv->config->id));
+
+#if SPI_HAVE_SWCS
+ esp32s2_spi_set_regbits(SPI_MISC_REG(priv->config->id), SPI_CS0_DIS_M);
+#endif
+
+ putreg32(0, SPI_CTRL_REG(priv->config->id));
+ putreg32(VALUE_TO_FIELD(0, SPI_CS_HOLD_TIME),
+ SPI_USER1_REG(priv->config->id));
+
+ esp32s2_spi_setfrequency(dev, config->clk_freq);
+ esp32s2_spi_setbits(dev, config->width);
+ esp32s2_spi_setmode(dev, config->mode);
+}
+
+/****************************************************************************
+ * Name: esp32s2_spi_deinit
+ *
+ * Description:
+ * Deinitialize ESP32-S2 SPI hardware interface.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ *
+ * Returned Value:
+ * None.
+ *
+ ****************************************************************************/
+
+static void esp32s2_spi_deinit(struct spi_dev_s *dev)
+{
+ struct esp32s2_spi_priv_s *priv = (struct esp32s2_spi_priv_s *)dev;
+
+ modifyreg32(SYSTEM_PERIP_RST_EN0_REG, 0, priv->config->rst_bit);
+ modifyreg32(SYSTEM_PERIP_CLK_EN0_REG, priv->config->clk_bit, 0);
+
+ priv->frequency = 0;
+ priv->actual = 0;
+ priv->mode = SPIDEV_MODE0;
+ priv->nbits = 0;
+}
+
+/****************************************************************************
+ * Name: esp32s2_spibus_initialize
+ *
+ * Description:
+ * Initialize the selected SPI bus.
+ *
+ * Input Parameters:
+ * port - Port number (for hardware that has multiple SPI interfaces)
+ *
+ * Returned Value:
+ * Valid SPI device structure reference on success; NULL on failure.
+ *
+ ****************************************************************************/
+
+struct spi_dev_s *esp32s2_spibus_initialize(int port)
+{
+ struct spi_dev_s *spi_dev;
+ struct esp32s2_spi_priv_s *priv;
+ irqstate_t flags;
+
+ switch (port)
+ {
+#ifdef CONFIG_ESP32S2_SPI2
+ case ESP32S2_SPI2:
+ priv = &esp32s2_spi2_priv;
+ break;
+#endif
+#ifdef CONFIG_ESP32S2_SPI3
+ case ESP32S2_SPI3:
+ priv = &esp32s2_spi3_priv;
+ break;
+#endif
+ default:
+ return NULL;
+ }
+
+ spi_dev = (struct spi_dev_s *)priv;
+
+ flags = enter_critical_section();
+
+ esp32s2_spi_init(spi_dev);
+
+ priv->refs++;
+
+ leave_critical_section(flags);
+
+ return spi_dev;
+}
+
+/****************************************************************************
+ * Name: esp32s2_spibus_uninitialize
+ *
+ * Description:
+ * Uninitialize an SPI bus.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success. Otherwise -1 (ERROR).
+ *
+ ****************************************************************************/
+
+int esp32s2_spibus_uninitialize(struct spi_dev_s *dev)
+{
+ irqstate_t flags;
+ struct esp32s2_spi_priv_s *priv = (struct esp32s2_spi_priv_s *)dev;
+
+ DEBUGASSERT(dev);
+
+ if (priv->refs == 0)
+ {
+ return ERROR;
+ }
+
+ flags = enter_critical_section();
+
+ if (--priv->refs != 0)
+ {
+ leave_critical_section(flags);
+ return OK;
+ }
+
+ leave_critical_section(flags);
+
+ esp32s2_spi_deinit(dev);
+
+ nxsem_destroy(&priv->exclsem);
+
+ return OK;
+}
+
+#endif /* CONFIG_ESP32S2_SPI */
diff --git a/arch/xtensa/src/esp32s2/esp32s2_spi.h b/arch/xtensa/src/esp32s2/esp32s2_spi.h
new file mode 100644
index 0000000000..3f569b73c8
--- /dev/null
+++ b/arch/xtensa/src/esp32s2/esp32s2_spi.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32s2/esp32s2_spi.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#ifndef __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_SPI_H
+#define __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_SPI_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifndef __ASSEMBLY__
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+#ifdef CONFIG_ESP32S2_SPI
+
+#include <nuttx/spi/spi.h>
+
+#ifdef CONFIG_ESP32S2_SPI2
+# define ESP32S2_SPI2 2
+#endif
+
+#ifdef CONFIG_ESP32S2_SPI3
+# define ESP32S2_SPI3 3
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: esp32s2_spibus_initialize
+ *
+ * Description:
+ * Initialize the selected SPI bus.
+ *
+ * Input Parameters:
+ * port - Port number (for hardware that has multiple SPI interfaces)
+ *
+ * Returned Value:
+ * Valid SPI device structure reference on success; NULL on failure
+ *
+ ****************************************************************************/
+
+struct spi_dev_s *esp32s2_spibus_initialize(int port);
+
+/****************************************************************************
+ * Name: esp32s2_spi[2|3]_select and esp32s2_spi[2|3]_status
+ *
+ * Description:
+ * The external functions, esp32s2_spi[2|3]_select,
+ * esp32s2_spi[2|3]_status, and esp32s2_spi[2|3]_cmddata must be provided
+ * by board-specific logic.
+ * These are implementations of the select, status, and cmddata methods of
+ * the SPI interface defined by struct spi_ops_s (include/nuttx/spi/spi.h).
+ * All other methods (including esp32s2_spibus_initialize()) are provided
+ * by common ESP32-S2 logic. To use this common SPI logic on your board:
+ *
+ * 1. Provide logic in esp32s2_board_initialize() to configure SPI chip
+ * select pins.
+ * 2. Provide esp32s2_spi[2|3]_select() and esp32s2_spi[2|3]_status()
+ * functions in your board-specific logic. These functions will perform
+ * chip selection and status operations using GPIOs in the way your
+ * board is configured.
+ * 3. If CONFIG_SPI_CMDDATA is defined in your NuttX configuration file,
+ * then provide esp32s2_spi[2|3]_cmddata() functions in your
+ * board-specific logic. These functions will perform cmd/data selection
+ * operations using GPIOs in the way your board is configured.
+ * 4. Add a call to esp32s2_spibus_initialize() in your low level
+ * application initialization logic.
+ * 5. The handle returned by esp32s2_spibus_initialize() may then be used
+ * to bind the SPI driver to higher level logic (e.g., calling
+ * mmcsd_spislotinitialize(), for example, will bind the SPI driver to
+ * the SPI MMC/SD driver).
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ESP32S2_SPI2
+void esp32s2_spi2_select(struct spi_dev_s *dev, uint32_t devid,
+ bool selected);
+uint8_t esp32s2_spi2_status(struct spi_dev_s *dev, uint32_t devid);
+int esp32s2_spi2_cmddata(struct spi_dev_s *dev,
+ uint32_t devid,
+ bool cmd);
+#endif
+
+#ifdef CONFIG_ESP32S2_SPI3
+void esp32s2_spi3_select(struct spi_dev_s *dev, uint32_t devid,
+ bool selected);
+uint8_t esp32s2_spi3_status(struct spi_dev_s *dev, uint32_t devid);
+int esp32s2_spi3_cmddata(struct spi_dev_s *dev,
+ uint32_t devid,
+ bool cmd);
+#endif
+
+/****************************************************************************
+ * Name: esp32s2_spibus_uninitialize
+ *
+ * Description:
+ * Uninitialize an SPI bus.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ *
+ * Returned Value:
+ * Zero (OK) is returned on success. Otherwise -1 (ERROR).
+ *
+ ****************************************************************************/
+
+int esp32s2_spibus_uninitialize(struct spi_dev_s *dev);
+
+#endif /* CONFIG_ESP32S2_SPI */
+
+#ifdef __cplusplus
+}
+#endif
+#undef EXTERN
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ARCH_XTENSA_SRC_ESP32S2_ESP32S2_SPI_H */
diff --git a/arch/xtensa/src/esp32s2/hardware/esp32s2_pinmap.h b/arch/xtensa/src/esp32s2/hardware/esp32s2_pinmap.h
new file mode 100644
index 0000000000..4b7ecf609b
--- /dev/null
+++ b/arch/xtensa/src/esp32s2/hardware/esp32s2_pinmap.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+ * arch/xtensa/src/esp32s2/hardware/esp32s2_pinmap.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#ifndef __ARCH_XTENSA_SRC_ESP32S2_HARDWARE_ESP32S2_PINMAP_H
+#define __ARCH_XTENSA_SRC_ESP32S2_HARDWARE_ESP32S2_PINMAP_H
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/**
+ * Peripheral' fixed mapped pins by IOMUX, these GPIO pins can have better
+ * speed performance.
+ */
+
+/* UART0 */
+
+/* UART1 */
+
+/* SPI2 */
+
+#define SPI2_IOMUX_MISOPIN (13)
+#define SPI2_IOMUX_MOSIPIN (11)
+#define SPI2_IOMUX_CLKPIN (12)
+#define SPI2_IOMUX_CSPIN (10)
+#define SPI2_IOMUX_WPPIN (14)
+#define SPI2_IOMUX_HDPIN (9)
+
+/* SPI3 */
+
+/* SPI3 have no iomux pins */
+
+#endif /* __ARCH_XTENSA_SRC_ESP32S2_HARDWARE_ESP32S2_PINMAP_H */
diff --git a/arch/xtensa/src/esp32s2/hardware/esp32s2_soc.h b/arch/xtensa/src/esp32s2/hardware/esp32s2_soc.h
index 9276d98d7a..8d7b945421 100644
--- a/arch/xtensa/src/esp32s2/hardware/esp32s2_soc.h
+++ b/arch/xtensa/src/esp32s2/hardware/esp32s2_soc.h
@@ -274,6 +274,8 @@
#define REG_SPI_MEM_BASE(i) (DR_REG_SPI0_BASE - (i) * 0x1000)
#define REG_I2C_BASE(i) (DR_REG_I2C_EXT_BASE + (i) * 0x14000 )
+#define REG_SPI_BASE(i) (DR_REG_SPI2_BASE + (((i) > 3) ? ((((i) - 2) * 0x1000) + 0x10000) : (((i) - 2) * 0x1000)))
+
/* Registers Operation */
#define REG_UART_BASE( i ) (DR_REG_UART_BASE + (i) * 0x10000 )
diff --git a/arch/xtensa/src/esp32s2/hardware/esp32s2_spi.h b/arch/xtensa/src/esp32s2/hardware/esp32s2_spi.h
index 1fa5538c47..5abb83e03b 100644
--- a/arch/xtensa/src/esp32s2/hardware/esp32s2_spi.h
+++ b/arch/xtensa/src/esp32s2/hardware/esp32s2_spi.h
@@ -33,7 +33,7 @@
/* SPI_CMD_REG register */
-#define SPI_CMD_REG (DR_REG_SPI_BASE + 0x0)
+#define SPI_CMD_REG(i) (REG_SPI_BASE(i) + 0x0)
/* SPI_USR : R/W; bitpos: [24]; default: 0;
* User define command enable. An operation will be triggered when the bit
@@ -57,7 +57,7 @@
/* SPI_ADDR_REG register */
-#define SPI_ADDR_REG (DR_REG_SPI_BASE + 0x4)
+#define SPI_ADDR_REG(i) (REG_SPI_BASE(i) + 0x4)
/* SPI_USR_ADDR_VALUE : R/W; bitpos: [31:0]; default: 0;
* [31:8]:address to slave, [7:0]:Reserved.
@@ -70,7 +70,7 @@
/* SPI_CTRL_REG register */
-#define SPI_CTRL_REG (DR_REG_SPI_BASE + 0x8)
+#define SPI_CTRL_REG(i) (REG_SPI_BASE(i) + 0x8)
/* SPI_WR_BIT_ORDER : R/W; bitpos: [26]; default: 0;
* In command address write-data (MOSI) phases 1: LSB firs 0: MSB first
@@ -225,7 +225,7 @@
/* SPI_CTRL1_REG register */
-#define SPI_CTRL1_REG (DR_REG_SPI_BASE + 0xc)
+#define SPI_CTRL1_REG(i) (REG_SPI_BASE(i) + 0xc)
/* SPI_CS_HOLD_DELAY : R/W; bitpos: [19:14]; default: 1;
* SPI cs signal is delayed by spi clock cycles.
@@ -280,7 +280,7 @@
/* SPI_CTRL2_REG register */
-#define SPI_CTRL2_REG (DR_REG_SPI_BASE + 0x10)
+#define SPI_CTRL2_REG(i) (REG_SPI_BASE(i) + 0x10)
/* SPI_CS_DELAY_NUM : R/W; bitpos: [30:29]; default: 0;
* spi_cs signal is delayed by system clock cycles
@@ -325,7 +325,7 @@
/* SPI_CLOCK_REG register */
-#define SPI_CLOCK_REG (DR_REG_SPI_BASE + 0x14)
+#define SPI_CLOCK_REG(i) (REG_SPI_BASE(i) + 0x14)
/* SPI_CLK_EQU_SYSCLK : R/W; bitpos: [31]; default: 1;
* In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided
@@ -378,7 +378,7 @@
/* SPI_USER_REG register */
-#define SPI_USER_REG (DR_REG_SPI_BASE + 0x18)
+#define SPI_USER_REG(i) (REG_SPI_BASE(i) + 0x18)
/* SPI_USR_COMMAND : R/W; bitpos: [31]; default: 1;
* This bit enable the command phase of an operation.
@@ -649,7 +649,7 @@
/* SPI_USER1_REG register */
-#define SPI_USER1_REG (DR_REG_SPI_BASE + 0x1c)
+#define SPI_USER1_REG(i) (REG_SPI_BASE(i) + 0x1c)
/* SPI_USR_ADDR_BITLEN : R/W; bitpos: [31:27]; default: 23;
* The length in bits of address phase. The register value shall be
@@ -673,7 +673,7 @@
/* SPI_USER2_REG register */
-#define SPI_USER2_REG (DR_REG_SPI_BASE + 0x20)
+#define SPI_USER2_REG(i) (REG_SPI_BASE(i) + 0x20)
/* SPI_USR_COMMAND_BITLEN : R/W; bitpos: [31:28]; default: 7;
* The length in bits of command phase. The register value shall be
@@ -696,7 +696,7 @@
/* SPI_MOSI_DLEN_REG register */
-#define SPI_MOSI_DLEN_REG (DR_REG_SPI_BASE + 0x24)
+#define SPI_MOSI_DLEN_REG(i) (REG_SPI_BASE(i) + 0x24)
/* SPI_USR_MOSI_DBITLEN : R/W; bitpos: [22:0]; default: 0;
* The length in bits of write-data. The register value shall be (bit_num-1).
@@ -709,7 +709,7 @@
/* SPI_MISO_DLEN_REG register */
-#define SPI_MISO_DLEN_REG (DR_REG_SPI_BASE + 0x28)
+#define SPI_MISO_DLEN_REG(i) (REG_SPI_BASE(i) + 0x28)
/* SPI_USR_MISO_DBITLEN : R/W; bitpos: [22:0]; default: 0;
* The length in bits of read-data. The register value shall be (bit_num-1).
@@ -722,7 +722,7 @@
/* SPI_SLV_WR_STATUS_REG register */
-#define SPI_SLV_WR_STATUS_REG (DR_REG_SPI_BASE + 0x2c)
+#define SPI_SLV_WR_STATUS_REG(i) (REG_SPI_BASE(i) + 0x2c)
/* SPI_OPI_MODE : R/W; bitpos: [1]; default: 0;
* Just for master mode. 1: spi controller is in OPI mode (all in 8-b-m). 0:
@@ -746,7 +746,7 @@
/* SPI_MISC_REG register */
-#define SPI_MISC_REG (DR_REG_SPI_BASE + 0x30)
+#define SPI_MISC_REG(i) (REG_SPI_BASE(i) + 0x30)
/* SPI_QUAD_DIN_PIN_SWAP : R/W; bitpos: [31]; default: 0;
* 1: spi quad input swap enable 0: spi quad input swap disable
@@ -917,7 +917,7 @@
/* SPI_SLAVE_REG register */
-#define SPI_SLAVE_REG (DR_REG_SPI_BASE + 0x34)
+#define SPI_SLAVE_REG(i) (REG_SPI_BASE(i) + 0x34)
/* SPI_SOFT_RESET : R/W; bitpos: [31]; default: 0;
* Software reset enable, reset the spi clock line cs line and data lines.
@@ -1031,7 +1031,7 @@
/* SPI_SLAVE1_REG register */
-#define SPI_SLAVE1_REG (DR_REG_SPI_BASE + 0x38)
+#define SPI_SLAVE1_REG(i) (REG_SPI_BASE(i) + 0x38)
/* SPI_SLV_LAST_ADDR : R/W; bitpos: [31:24]; default: 0;
* In the slave mode it is the value of address.
@@ -1083,7 +1083,7 @@
/* SPI_SLAVE2_REG register */
-#define SPI_SLAVE2_REG (DR_REG_SPI_BASE + 0x3c)
+#define SPI_SLAVE2_REG(i) (REG_SPI_BASE(i) + 0x3c)
/* SPI_SLV_RD_DMA_DONE : R/W; bitpos: [8]; default: 0;
* The interrupt raw bit for the completion of Rd-DMA operation in the slave
@@ -1097,7 +1097,7 @@
/* SPI_SLV_WRBUF_DLEN_REG register */
-#define SPI_SLV_WRBUF_DLEN_REG (DR_REG_SPI_BASE + 0x40)
+#define SPI_SLV_WRBUF_DLEN_REG(i) (REG_SPI_BASE(i) + 0x40)
/* SPI_CONF_BASE_BITLEN : R/W; bitpos: [31:25]; default: 108;
* The basic spi_clk cycles of CONF state. The real cycle length of CONF
@@ -1122,7 +1122,7 @@
/* SPI_SLV_RDBUF_DLEN_REG register */
-#define SPI_SLV_RDBUF_DLEN_REG (DR_REG_SPI_BASE + 0x44)
+#define SPI_SLV_RDBUF_DLEN_REG(i) (REG_SPI_BASE(i) + 0x44)
/* SPI_SEG_MAGIC_ERR : R/W; bitpos: [25]; default: 0;
* 1: The recent magic value in CONF buffer is not right in master DMA
@@ -1156,7 +1156,7 @@
/* SPI_SLV_RD_BYTE_REG register */
-#define SPI_SLV_RD_BYTE_REG (DR_REG_SPI_BASE + 0x48)
+#define SPI_SLV_RD_BYTE_REG(i) (REG_SPI_BASE(i) + 0x48)
/* SPI_USR_CONF : R/W; bitpos: [31]; default: 0;
* 1: Enable the DMA CONF phase of current seg-trans operation, which means
@@ -1230,7 +1230,7 @@
/* SPI_FSM_REG register */
-#define SPI_FSM_REG (DR_REG_SPI_BASE + 0x50)
+#define SPI_FSM_REG(i) (REG_SPI_BASE(i) + 0x50)
/* SPI_MST_DMA_RD_BYTELEN : R/W; bitpos: [31:12]; default: 0;
* Define the master DMA read byte length in non seg-trans or seg-trans
@@ -1255,7 +1255,7 @@
/* SPI_HOLD_REG register */
-#define SPI_HOLD_REG (DR_REG_SPI_BASE + 0x54)
+#define SPI_HOLD_REG(i) (REG_SPI_BASE(i) + 0x54)
/* SPI_DMA_SEG_TRANS_DONE : R/W; bitpos: [7]; default: 0;
* 1: spi master DMA full-duplex/half-duplex seg-trans ends or slave
@@ -1311,7 +1311,7 @@
/* SPI_DMA_CONF_REG register */
-#define SPI_DMA_CONF_REG (DR_REG_SPI_BASE + 0x58)
+#define SPI_DMA_CONF_REG(i) (REG_SPI_BASE(i) + 0x58)
/* SPI_EXT_MEM_BK_SIZE : R/W; bitpos: [27:26]; default: 0;
* Select the external memory block size.
@@ -1552,7 +1552,7 @@
/* SPI_DMA_OUT_LINK_REG register */
-#define SPI_DMA_OUT_LINK_REG (DR_REG_SPI_BASE + 0x5c)
+#define SPI_DMA_OUT_LINK_REG(i) (REG_SPI_BASE(i) + 0x5c)
/* SPI_DMA_TX_ENA : R/W; bitpos: [31]; default: 0;
* spi dma write data status bit.
@@ -1601,7 +1601,7 @@
/* SPI_DMA_IN_LINK_REG register */
-#define SPI_DMA_IN_LINK_REG (DR_REG_SPI_BASE + 0x60)
+#define SPI_DMA_IN_LINK_REG(i) (REG_SPI_BASE(i) + 0x60)
/* SPI_DMA_RX_ENA : R/W; bitpos: [31]; default: 0;
* spi dma read data status bit.
@@ -1660,7 +1660,7 @@
/* SPI_DMA_INT_ENA_REG register */
-#define SPI_DMA_INT_ENA_REG (DR_REG_SPI_BASE + 0x64)
+#define SPI_DMA_INT_ENA_REG(i) (REG_SPI_BASE(i) + 0x64)
/* SPI_OUT_TOTAL_EOF_INT_ENA : R/W; bitpos: [8]; default: 0;
* The enable bit for sending all the packets to host done.
@@ -1745,7 +1745,7 @@
/* SPI_DMA_INT_RAW_REG register */
-#define SPI_DMA_INT_RAW_REG (DR_REG_SPI_BASE + 0x68)
+#define SPI_DMA_INT_RAW_REG(i) (REG_SPI_BASE(i) + 0x68)
/* SPI_OUT_TOTAL_EOF_INT_RAW : RO; bitpos: [8]; default: 0;
* The raw bit for sending all the packets to host done.
@@ -1830,7 +1830,7 @@
/* SPI_DMA_INT_ST_REG register */
-#define SPI_DMA_INT_ST_REG (DR_REG_SPI_BASE + 0x6c)
+#define SPI_DMA_INT_ST_REG(i) (REG_SPI_BASE(i) + 0x6c)
/* SPI_OUT_TOTAL_EOF_INT_ST : RO; bitpos: [8]; default: 0;
* The status bit for sending all the packets to host done.
@@ -1915,7 +1915,7 @@
/* SPI_DMA_INT_CLR_REG register */
-#define SPI_DMA_INT_CLR_REG (DR_REG_SPI_BASE + 0x70)
+#define SPI_DMA_INT_CLR_REG(i) (REG_SPI_BASE(i) + 0x70)
/* SPI_OUT_TOTAL_EOF_INT_CLR : R/W; bitpos: [8]; default: 0;
* The clear bit for sending all the packets to host done.
@@ -2000,7 +2000,7 @@
/* SPI_IN_ERR_EOF_DES_ADDR_REG register */
-#define SPI_IN_ERR_EOF_DES_ADDR_REG (DR_REG_SPI_BASE + 0x74)
+#define SPI_IN_ERR_EOF_DES_ADDR_REG(i) (REG_SPI_BASE(i) + 0x74)
/* SPI_DMA_IN_ERR_EOF_DES_ADDR : RO; bitpos: [31:0]; default: 0;
* The inlink descriptor address when spi dma produce receiving error.
@@ -2013,7 +2013,7 @@
/* SPI_IN_SUC_EOF_DES_ADDR_REG register */
-#define SPI_IN_SUC_EOF_DES_ADDR_REG (DR_REG_SPI_BASE + 0x78)
+#define SPI_IN_SUC_EOF_DES_ADDR_REG(i) (REG_SPI_BASE(i) + 0x78)
/* SPI_DMA_IN_SUC_EOF_DES_ADDR : RO; bitpos: [31:0]; default: 0;
* The last inlink descriptor address when spi dma produce from_suc_eof.
@@ -2026,7 +2026,7 @@
/* SPI_INLINK_DSCR_REG register */
-#define SPI_INLINK_DSCR_REG (DR_REG_SPI_BASE + 0x7c)
+#define SPI_INLINK_DSCR_REG(i) (REG_SPI_BASE(i) + 0x7c)
/* SPI_DMA_INLINK_DSCR : RO; bitpos: [31:0]; default: 0;
* The content of current in descriptor pointer.
@@ -2039,7 +2039,7 @@
/* SPI_INLINK_DSCR_BF0_REG register */
-#define SPI_INLINK_DSCR_BF0_REG (DR_REG_SPI_BASE + 0x80)
+#define SPI_INLINK_DSCR_BF0_REG(i) (REG_SPI_BASE(i) + 0x80)
/* SPI_DMA_INLINK_DSCR_BF0 : RO; bitpos: [31:0]; default: 0;
* The content of next in descriptor pointer.
@@ -2052,7 +2052,7 @@
/* SPI_INLINK_DSCR_BF1_REG register */
-#define SPI_INLINK_DSCR_BF1_REG (DR_REG_SPI_BASE + 0x84)
+#define SPI_INLINK_DSCR_BF1_REG(i) (REG_SPI_BASE(i) + 0x84)
/* SPI_DMA_INLINK_DSCR_BF1 : RO; bitpos: [31:0]; default: 0;
* The content of current in descriptor data buffer pointer.
@@ -2065,7 +2065,7 @@
/* SPI_OUT_EOF_BFR_DES_ADDR_REG register */
-#define SPI_OUT_EOF_BFR_DES_ADDR_REG (DR_REG_SPI_BASE + 0x88)
+#define SPI_OUT_EOF_BFR_DES_ADDR_REG(i) (REG_SPI_BASE(i) + 0x88)
/* SPI_DMA_OUT_EOF_BFR_DES_ADDR : RO; bitpos: [31:0]; default: 0;
* The address of buffer relative to the outlink descriptor that produce eof.
@@ -2078,7 +2078,7 @@
/* SPI_OUT_EOF_DES_ADDR_REG register */
-#define SPI_OUT_EOF_DES_ADDR_REG (DR_REG_SPI_BASE + 0x8c)
+#define SPI_OUT_EOF_DES_ADDR_REG(i) (REG_SPI_BASE(i) + 0x8c)
/* SPI_DMA_OUT_EOF_DES_ADDR : RO; bitpos: [31:0]; default: 0;
* The last outlink descriptor address when spi dma produce to_eof.
@@ -2091,7 +2091,7 @@
/* SPI_OUTLINK_DSCR_REG register */
-#define SPI_OUTLINK_DSCR_REG (DR_REG_SPI_BASE + 0x90)
+#define SPI_OUTLINK_DSCR_REG(i) (REG_SPI_BASE(i) + 0x90)
/* SPI_DMA_OUTLINK_DSCR : RO; bitpos: [31:0]; default: 0;
* The content of current out descriptor pointer.
@@ -2104,7 +2104,7 @@
/* SPI_OUTLINK_DSCR_BF0_REG register */
-#define SPI_OUTLINK_DSCR_BF0_REG (DR_REG_SPI_BASE + 0x94)
+#define SPI_OUTLINK_DSCR_BF0_REG(i) (REG_SPI_BASE(i) + 0x94)
/* SPI_DMA_OUTLINK_DSCR_BF0 : RO; bitpos: [31:0]; default: 0;
* The content of next out descriptor pointer.
@@ -2117,7 +2117,7 @@
/* SPI_OUTLINK_DSCR_BF1_REG register */
-#define SPI_OUTLINK_DSCR_BF1_REG (DR_REG_SPI_BASE + 0x98)
+#define SPI_OUTLINK_DSCR_BF1_REG(i) (REG_SPI_BASE(i) + 0x98)
/* SPI_DMA_OUTLINK_DSCR_BF1 : RO; bitpos: [31:0]; default: 0;
* The content of current out descriptor data buffer pointer.
@@ -2130,7 +2130,7 @@
/* SPI_DMA_OUTSTATUS_REG register */
-#define SPI_DMA_OUTSTATUS_REG (DR_REG_SPI_BASE + 0x9c)
+#define SPI_DMA_OUTSTATUS_REG(i) (REG_SPI_BASE(i) + 0x9c)
/* SPI_DMA_OUTFIFO_EMPTY : RO; bitpos: [31]; default: 1;
* SPI dma outfifo is empty.
@@ -2188,7 +2188,7 @@
/* SPI_DMA_INSTATUS_REG register */
-#define SPI_DMA_INSTATUS_REG (DR_REG_SPI_BASE + 0xa0)
+#define SPI_DMA_INSTATUS_REG(i) (REG_SPI_BASE(i) + 0xa0)
/* SPI_DMA_INFIFO_EMPTY : RO; bitpos: [31]; default: 1;
* SPI dma infifo is empty.
@@ -2246,7 +2246,7 @@
/* SPI_W0_REG register */
-#define SPI_W0_REG (DR_REG_SPI_BASE + 0xa4)
+#define SPI_W0_REG(i) (REG_SPI_BASE(i) + 0xa4)
/* SPI_BUF0 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2259,7 +2259,7 @@
/* SPI_W1_REG register */
-#define SPI_W1_REG (DR_REG_SPI_BASE + 0xa8)
+#define SPI_W1_REG(i) (REG_SPI_BASE(i) + 0xa8)
/* SPI_BUF1 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2272,7 +2272,7 @@
/* SPI_W2_REG register */
-#define SPI_W2_REG (DR_REG_SPI_BASE + 0xac)
+#define SPI_W2_REG(i) (REG_SPI_BASE(i) + 0xac)
/* SPI_BUF2 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2285,7 +2285,7 @@
/* SPI_W3_REG register */
-#define SPI_W3_REG (DR_REG_SPI_BASE + 0xb0)
+#define SPI_W3_REG(i) (REG_SPI_BASE(i) + 0xb0)
/* SPI_BUF3 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2298,7 +2298,7 @@
/* SPI_W4_REG register */
-#define SPI_W4_REG (DR_REG_SPI_BASE + 0xb4)
+#define SPI_W4_REG(i) (REG_SPI_BASE(i) + 0xb4)
/* SPI_BUF4 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2311,7 +2311,7 @@
/* SPI_W5_REG register */
-#define SPI_W5_REG (DR_REG_SPI_BASE + 0xb8)
+#define SPI_W5_REG(i) (REG_SPI_BASE(i) + 0xb8)
/* SPI_BUF5 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2324,7 +2324,7 @@
/* SPI_W6_REG register */
-#define SPI_W6_REG (DR_REG_SPI_BASE + 0xbc)
+#define SPI_W6_REG(i) (REG_SPI_BASE(i) + 0xbc)
/* SPI_BUF6 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2337,7 +2337,7 @@
/* SPI_W7_REG register */
-#define SPI_W7_REG (DR_REG_SPI_BASE + 0xc0)
+#define SPI_W7_REG(i) (REG_SPI_BASE(i) + 0xc0)
/* SPI_BUF7 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2350,7 +2350,7 @@
/* SPI_W8_REG register */
-#define SPI_W8_REG (DR_REG_SPI_BASE + 0xc4)
+#define SPI_W8_REG(i) (REG_SPI_BASE(i) + 0xc4)
/* SPI_BUF8 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2363,7 +2363,7 @@
/* SPI_W9_REG register */
-#define SPI_W9_REG (DR_REG_SPI_BASE + 0xc8)
+#define SPI_W9_REG(i) (REG_SPI_BASE(i) + 0xc8)
/* SPI_BUF9 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2376,7 +2376,7 @@
/* SPI_W10_REG register */
-#define SPI_W10_REG (DR_REG_SPI_BASE + 0xcc)
+#define SPI_W10_REG(i) (REG_SPI_BASE(i) + 0xcc)
/* SPI_BUF10 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2389,7 +2389,7 @@
/* SPI_W11_REG register */
-#define SPI_W11_REG (DR_REG_SPI_BASE + 0xd0)
+#define SPI_W11_REG(i) (REG_SPI_BASE(i) + 0xd0)
/* SPI_BUF11 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2402,7 +2402,7 @@
/* SPI_W12_REG register */
-#define SPI_W12_REG (DR_REG_SPI_BASE + 0xd4)
+#define SPI_W12_REG(i) (REG_SPI_BASE(i) + 0xd4)
/* SPI_BUF12 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2415,7 +2415,7 @@
/* SPI_W13_REG register */
-#define SPI_W13_REG (DR_REG_SPI_BASE + 0xd8)
+#define SPI_W13_REG(i) (REG_SPI_BASE(i) + 0xd8)
/* SPI_BUF13 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2428,7 +2428,7 @@
/* SPI_W14_REG register */
-#define SPI_W14_REG (DR_REG_SPI_BASE + 0xdc)
+#define SPI_W14_REG(i) (REG_SPI_BASE(i) + 0xdc)
/* SPI_BUF14 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2441,7 +2441,7 @@
/* SPI_W15_REG register */
-#define SPI_W15_REG (DR_REG_SPI_BASE + 0xe0)
+#define SPI_W15_REG(i) (REG_SPI_BASE(i) + 0xe0)
/* SPI_BUF15 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2454,7 +2454,7 @@
/* SPI_W16_REG register */
-#define SPI_W16_REG (DR_REG_SPI_BASE + 0xe4)
+#define SPI_W16_REG(i) (REG_SPI_BASE(i) + 0xe4)
/* SPI_BUF16 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2467,7 +2467,7 @@
/* SPI_W17_REG register */
-#define SPI_W17_REG (DR_REG_SPI_BASE + 0xe8)
+#define SPI_W17_REG(i) (REG_SPI_BASE(i) + 0xe8)
/* SPI_BUF17 : R/W; bitpos: [31:0]; default: 0;
* data buffer
@@ -2480,7 +2480,7 @@
/* SPI_DIN_MODE_REG register */
-#define SPI_DIN_MODE_REG (DR_REG_SPI_BASE + 0xec)
+#define SPI_DIN_MODE_REG(i) (REG_SPI_BASE(i) + 0xec)
/* SPI_TIMING_CLK_ENA : R/W; bitpos: [24]; default: 0;
* 1:enable hclk in spi_timing.v. 0: disable it.
@@ -2597,7 +2597,7 @@
/* SPI_DIN_NUM_REG register */
-#define SPI_DIN_NUM_REG (DR_REG_SPI_BASE + 0xf0)
+#define SPI_DIN_NUM_REG(i) (REG_SPI_BASE(i) + 0xf0)
/* SPI_DIN7_NUM : R/W; bitpos: [15:14]; default: 0;
* the input signals are delayed by system clock cycles, 0: delayed by 1
@@ -2681,7 +2681,7 @@
/* SPI_DOUT_MODE_REG register */
-#define SPI_DOUT_MODE_REG (DR_REG_SPI_BASE + 0xf4)
+#define SPI_DOUT_MODE_REG(i) (REG_SPI_BASE(i) + 0xf4)
/* SPI_DOUT7_MODE : R/W; bitpos: [23:21]; default: 0;
* Configure the output signal delay mode. 0: without delayed, 1: with the
@@ -2789,7 +2789,7 @@
/* SPI_DOUT_NUM_REG register */
-#define SPI_DOUT_NUM_REG (DR_REG_SPI_BASE + 0xf8)
+#define SPI_DOUT_NUM_REG(i) (REG_SPI_BASE(i) + 0xf8)
/* SPI_DOUT7_NUM : R/W; bitpos: [15:14]; default: 0;
* the output signals are delayed by system clock cycles, 0: delayed by 1
@@ -2873,7 +2873,7 @@
/* SPI_LCD_CTRL_REG register */
-#define SPI_LCD_CTRL_REG (DR_REG_SPI_BASE + 0xfc)
+#define SPI_LCD_CTRL_REG(i) (REG_SPI_BASE(i) + 0xfc)
/* SPI_LCD_SRGB_MODE_EN : R/W; bitpos: [31]; default: 0;
* 1: Enable LCD mode output vsync, hsync, de. 0: Disable.
@@ -2913,7 +2913,7 @@
/* SPI_LCD_CTRL1_REG register */
-#define SPI_LCD_CTRL1_REG (DR_REG_SPI_BASE + 0x100)
+#define SPI_LCD_CTRL1_REG(i) (REG_SPI_BASE(i) + 0x100)
/* SPI_LCD_HT_WIDTH : R/W; bitpos: [31:20]; default: 0;
* It is the horizontal total width of a frame.
@@ -2944,7 +2944,7 @@
/* SPI_LCD_CTRL2_REG register */
-#define SPI_LCD_CTRL2_REG (DR_REG_SPI_BASE + 0x104)
+#define SPI_LCD_CTRL2_REG(i) (REG_SPI_BASE(i) + 0x104)
/* SPI_LCD_HSYNC_POSITION : R/W; bitpos: [31:24]; default: 0;
* It is the position of spi_hsync_out active pulse in a line.
@@ -3002,7 +3002,7 @@
/* SPI_LCD_D_MODE_REG register */
-#define SPI_LCD_D_MODE_REG (DR_REG_SPI_BASE + 0x108)
+#define SPI_LCD_D_MODE_REG(i) (REG_SPI_BASE(i) + 0x108)
/* SPI_D_VSYNC_MODE : R/W; bitpos: [14:12]; default: 0;
* Configure the output spi_vsync delay mode. 0: without delayed, 1: with
@@ -3071,7 +3071,7 @@
/* SPI_LCD_D_NUM_REG register */
-#define SPI_LCD_D_NUM_REG (DR_REG_SPI_BASE + 0x10c)
+#define SPI_LCD_D_NUM_REG(i) (REG_SPI_BASE(i) + 0x10c)
/* SPI_D_VSYNC_NUM : R/W; bitpos: [9:8]; default: 0;
* the output spi_vsync is delayed by system clock cycles, 0: delayed by 1
@@ -3125,7 +3125,7 @@
/* SPI_REG_DATE_REG register */
-#define SPI_REG_DATE_REG (DR_REG_SPI_BASE + 0x3fc)
+#define SPI_REG_DATE_REG(i) (REG_SPI_BASE(i) + 0x3fc)
/* SPI_DATE : RW; bitpos: [27:0]; default: 26222993;
* SPI register version.