From 28e5e554d3589985a974f5067e1185fdd369b33f Mon Sep 17 00:00:00 2001 From: Eren Terzioglu Date: Thu, 10 Oct 2024 15:44:35 +0300 Subject: [PATCH] esp32[s2|s3]: Add SPI bitbang support --- arch/xtensa/src/common/espressif/Kconfig | 59 ++++ arch/xtensa/src/common/espressif/Make.defs | 4 + .../src/common/espressif/esp_spi_bitbang.c | 273 ++++++++++++++++++ .../src/common/espressif/esp_spi_bitbang.h | 133 +++++++++ arch/xtensa/src/esp32/Kconfig | 2 + arch/xtensa/src/esp32s2/Kconfig | 2 + arch/xtensa/src/esp32s3/Kconfig | 2 + .../esp32/common/src/esp32_board_spidev.c | 146 +++++++++- .../esp32s2/common/src/esp32s2_board_spidev.c | 133 ++++++++- .../esp32s3/common/src/esp32s3_board_spidev.c | 139 ++++++++- .../esp32s3-devkit/src/esp32s3_bringup.c | 13 +- 11 files changed, 884 insertions(+), 22 deletions(-) create mode 100644 arch/xtensa/src/common/espressif/esp_spi_bitbang.c create mode 100644 arch/xtensa/src/common/espressif/esp_spi_bitbang.h diff --git a/arch/xtensa/src/common/espressif/Kconfig b/arch/xtensa/src/common/espressif/Kconfig index bb670641595db..91b9e0e0b3721 100644 --- a/arch/xtensa/src/common/espressif/Kconfig +++ b/arch/xtensa/src/common/espressif/Kconfig @@ -23,6 +23,22 @@ config ESPRESSIF_TEMP ---help--- A built-in sensor used to measure the chip's internal temperature. +config ESPRESSIF_SPI_PERIPH + bool + depends on (ESP32S3_SPI2 || ESP32S3_SPI3) || (ESP32_SPI2 || ESP32_SPI3) || (ESP32S2_SPI2 || ESP32S2_SPI3) + default n + +config ESPRESSIF_SPI_BITBANG + bool "SPI Bitbang" + default n + select ESP32_SPI if ARCH_CHIP_ESP32 + select ESP32S2_SPI if ARCH_CHIP_ESP32S2 + select ESP32S3_SPI if ARCH_CHIP_ESP32S3 + select SPI + select SPI_BITBANG + ---help--- + Software implemented SPI peripheral with GPIOs. Suggested to use if SPI peripherals are already in use. + config ESPRESSIF_SPIFLASH bool "SPI Flash" depends on ARCH_CHIP_ESP32S2 @@ -72,6 +88,49 @@ config ESPRESSIF_TEMP_THREAD_STACKSIZE endmenu # ESPRESSIF_TEMP +menu "SPI bitbang configuration" + depends on ESPRESSIF_SPI_BITBANG + +config ESPRESSIF_SPI_BITBANG_CSPIN + int "SPI Bitbang CS Pin" + default 0 + range 0 21 + +config ESPRESSIF_SPI_BITBANG_CLKPIN + int "SPI Bitbang CLK Pin" + default 1 + range 0 21 + +config ESPRESSIF_SPI_BITBANG_MOSIPIN + int "SPI Bitbang MOSI Pin" + default 2 + range 0 21 + +config ESPRESSIF_SPI_BITBANG_MISOPIN + int "SPI Bitbang MISO Pin" + default 3 + range 0 21 + +choice ESPRESSIF_SPI_BITBANG_MODE + prompt "SPI Bitbang mode" + default ESPRESSIF_SPI_BITBANG_MODE0 + +config ESPRESSIF_SPI_BITBANG_MODE0 + bool "SPI MODE0" + +config ESPRESSIF_SPI_BITBANG_MODE1 + bool "SPI MODE1" + +config ESPRESSIF_SPI_BITBANG_MODE2 + bool "SPI MODE2" + +config ESPRESSIF_SPI_BITBANG_MODE3 + bool "SPI MODE3" + +endchoice # ESPRESSIF_SPI_BITBANG_MODE + +endmenu # SPI bitbang configuration + config ESPRESSIF_HAVE_OTA_PARTITION bool default n diff --git a/arch/xtensa/src/common/espressif/Make.defs b/arch/xtensa/src/common/espressif/Make.defs index 58b2a6f4b0ceb..38250f6b9423a 100644 --- a/arch/xtensa/src/common/espressif/Make.defs +++ b/arch/xtensa/src/common/espressif/Make.defs @@ -40,6 +40,10 @@ ifeq ($(CONFIG_ESPRESSIF_TEMP),y) CHIP_CSRCS += esp_temperature_sensor.c endif +ifeq ($(CONFIG_ESPRESSIF_SPI_BITBANG),y) +CHIP_CSRCS += esp_spi_bitbang.c +endif + ifeq ($(CONFIG_ESPRESSIF_SPIFLASH),y) CHIP_CSRCS += esp_spiflash.c ifeq ($(CONFIG_ESPRESSIF_MTD),y) diff --git a/arch/xtensa/src/common/espressif/esp_spi_bitbang.c b/arch/xtensa/src/common/espressif/esp_spi_bitbang.c new file mode 100644 index 0000000000000..25133e649ba3f --- /dev/null +++ b/arch/xtensa/src/common/espressif/esp_spi_bitbang.c @@ -0,0 +1,273 @@ +/**************************************************************************** + * arch/xtensa/src/common/espressif/esp_spi_bitbang.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 + +#ifdef CONFIG_ESPRESSIF_SPI_BITBANG +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "esp_spi_bitbang.h" +#include + +#if defined(CONFIG_ARCH_CHIP_ESP32S3) +#include "esp32s3_gpio.h" +#include "hardware/esp32s3_gpio_sigmap.h" +#elif defined(CONFIG_ARCH_CHIP_ESP32S2) +#include "esp32s2_gpio.h" +#include "esp32s2_gpio_sigmap.h" +#else +#include "esp32_gpio.h" +#include "esp32_gpio_sigmap.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if defined(CONFIG_ARCH_CHIP_ESP32S3) +#define CONFIG_GPIO(pin, attr) esp32s3_configgpio(pin, attr) +#define GPIO_MATRIX_OUT(pin, idx, inv, en_inv) esp32s3_gpio_matrix_out(pin, \ + idx, inv, en_inv) +#elif defined(CONFIG_ARCH_CHIP_ESP32S2) +#define CONFIG_GPIO(pin, attr) esp32s2_configgpio(pin, attr) +#define GPIO_MATRIX_OUT(pin, idx, inv, en_inv) esp32s2_gpio_matrix_out(pin, \ + idx, inv, en_inv) +#else +#define CONFIG_GPIO(pin, attr) esp32_configgpio(pin, attr) +#define GPIO_MATRIX_OUT(pin, idx, inv, en_inv) esp32_gpio_matrix_out(pin, \ + idx, inv, en_inv) +#endif + +#if defined(CONFIG_ESPRESSIF_SPI_BITBANG_MODE0) +#undef SPI_BITBANG_DISABLEMODE0 +#define SPI_BITBANG_DISABLEMODE1 1 +#define SPI_BITBANG_DISABLEMODE2 1 +#define SPI_BITBANG_DISABLEMODE3 1 +#elif defined(CONFIG_ESPRESSIF_SPI_BITBANG_MODE1) +#undef SPI_BITBANG_DISABLEMODE1 +#define SPI_BITBANG_DISABLEMODE0 1 +#define SPI_BITBANG_DISABLEMODE2 1 +#define SPI_BITBANG_DISABLEMODE3 1 +#elif defined(CONFIG_ESPRESSIF_SPI_BITBANG_MODE2) +#undef SPI_BITBANG_DISABLEMODE2 +#define SPI_BITBANG_DISABLEMODE0 1 +#define SPI_BITBANG_DISABLEMODE1 1 +#define SPI_BITBANG_DISABLEMODE3 1 +#else +#undef SPI_BITBANG_DISABLEMODE3 +#define SPI_BITBANG_DISABLEMODE0 1 +#define SPI_BITBANG_DISABLEMODE1 1 +#define SPI_BITBANG_DISABLEMODE2 1 +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Lower-half SPI */ + +static void spi_select(struct spi_bitbang_s *priv, uint32_t devid, + bool selected); +static uint8_t spi_status(struct spi_bitbang_s *priv, uint32_t devid); +#ifdef CONFIG_SPI_CMDDATA +static int spi_cmddata(struct spi_bitbang_s *priv, uint32_t devid, + bool cmd); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +struct spi_bitbang_ops_s esp_spi_bitbang_ops = +{ + .select = spi_select, + .status = spi_status, +#ifdef CONFIG_SPI_CMDDATA + .cmddata = spi_cmddata, +#endif + .setfrequency = spi_setfrequency, + .setmode = spi_setmode, + .exchange = spi_exchange, +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: spi_select + * + * Description: + * Select or de-selected the SPI device specified by 'devid' + * + * Input Parameters: + * priv - An instance of the bit-bang driver structure + * devid - The device to select or de-select + * selected - True:select false:de-select + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void spi_select(struct spi_bitbang_s *priv, uint32_t devid, + bool selected) +{ + if (selected) + { + SPI_CLRCS; + } + else + { + SPI_SETCS; + } +} + +/**************************************************************************** + * Name: spi_status + * + * Description: + * Return status of the SPI device specified by 'devid' + * + * Input Parameters: + * priv - An instance of the bit-bang driver structure + * devid - The device to select or de-select + * + * Returned Value: + * An 8-bit, bit-encoded status byte + * + ****************************************************************************/ + +static uint8_t spi_status(struct spi_bitbang_s *priv, uint32_t devid) +{ + if (devid == SPIDEV_MMCSD(0)) + { + return SPI_STATUS_PRESENT; + } + + return 0; +} + +/**************************************************************************** + * Name: spi_cmddata + * + * Description: + * If there were was a CMD/DATA line, this function would manage it + * + * Input Parameters: + * priv - An instance of the bit-bang driver structure + * devid - The device to use + * cmd - True=MCD false=DATA + * + * Returned Value: + * OK + * + ****************************************************************************/ + +#ifdef CONFIG_SPI_CMDDATA +static int spi_cmddata(struct spi_bitbang_s *priv, uint32_t devid, + bool cmd) +{ + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_spi_bitbang_init + * + * Description: + * Initialize the SPI bit-bang driver + * + * Input Parameters: + * None + * + * Returned Value: + * A non-NULL reference to the SPI driver on success + * + ****************************************************************************/ + +struct spi_dev_s *esp_spi_bitbang_init(void) +{ + /* Configure the SPI bit-bang pins */ + + GPIO_WRITE(CONFIG_ESPRESSIF_SPI_BITBANG_CSPIN, true); + GPIO_WRITE(CONFIG_ESPRESSIF_SPI_BITBANG_MOSIPIN, true); + GPIO_WRITE(CONFIG_ESPRESSIF_SPI_BITBANG_CLKPIN, true); + +#if CONFIG_ESPRESSIF_SPI_SWCS + CONFIG_GPIO(CONFIG_ESPRESSIF_SPI_BITBANG_CSPIN, OUTPUT_FUNCTION_1); + GPIO_MATRIX_OUT(CONFIG_ESPRESSIF_SPI_BITBANG_CSPIN, SIG_GPIO_OUT_IDX, + 0, 0); +#endif + CONFIG_GPIO(CONFIG_ESPRESSIF_SPI_BITBANG_MOSIPIN, OUTPUT_FUNCTION_1); + GPIO_MATRIX_OUT(CONFIG_ESPRESSIF_SPI_BITBANG_MOSIPIN, SIG_GPIO_OUT_IDX, + 0, 0); + + CONFIG_GPIO(CONFIG_ESPRESSIF_SPI_BITBANG_MISOPIN, + INPUT_FUNCTION_1 | PULLUP); + GPIO_MATRIX_OUT(CONFIG_ESPRESSIF_SPI_BITBANG_MISOPIN, SIG_GPIO_OUT_IDX, + 0, 0); + + CONFIG_GPIO(CONFIG_ESPRESSIF_SPI_BITBANG_CLKPIN, OUTPUT_FUNCTION_1); + GPIO_MATRIX_OUT(CONFIG_ESPRESSIF_SPI_BITBANG_CLKPIN, SIG_GPIO_OUT_IDX, + 0, 0); + + /* Create the SPI driver instance */ + + return spi_create_bitbang(&esp_spi_bitbang_ops, NULL); +} + +/**************************************************************************** + * Name: esp_spi_bitbang_uninitialize + * + * Description: + * Destroy an instance of the SPI bit-bang driver. + * + * Input Parameters: + * dev - device instance, target driver to destroy. + * + ****************************************************************************/ + +void esp_spi_bitbang_uninitialize(struct spi_dev_s *dev) +{ + spi_destroy_bitbang(dev); +} + +#endif /* CONFIG_ESPRESSIF_SPI_BITBANG */ diff --git a/arch/xtensa/src/common/espressif/esp_spi_bitbang.h b/arch/xtensa/src/common/espressif/esp_spi_bitbang.h new file mode 100644 index 0000000000000..b01a12bc75956 --- /dev/null +++ b/arch/xtensa/src/common/espressif/esp_spi_bitbang.h @@ -0,0 +1,133 @@ +/**************************************************************************** + * arch/xtensa/src/common/espressif/esp_spi_bitbang.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_COMMON_ESPRESSIF_ESP_SPI_BITBANG_H +#define __ARCH_XTENSA_SRC_COMMON_ESPRESSIF_ESP_SPI_BITBANG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#ifdef CONFIG_ESPRESSIF_SPI_BITBANG + +#include +#include +#if defined(CONFIG_ARCH_CHIP_ESP32S3) +#include "esp32s3_gpio.h" +#elif defined(CONFIG_ARCH_CHIP_ESP32S2) +#include "esp32s2_gpio.h" +#else +#include "esp32_gpio.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if defined(CONFIG_ARCH_CHIP_ESP32S3) +#define GPIO_WRITE(pin, value) esp32s3_gpiowrite(pin, value) +#define GPIO_READ(pin) esp32s3_gpioread(pin) +#elif defined(CONFIG_ARCH_CHIP_ESP32S2) +#define GPIO_WRITE(pin, value) esp32s2_gpiowrite(pin, value) +#define GPIO_READ(pin) esp32s2_gpioread(pin) +#else +#define GPIO_WRITE(pin, value) esp32_gpiowrite(pin, value) +#define GPIO_READ(pin) esp3_gpioread(pin) +#endif + +/* Macros needed to include/nuttx/spi/spi_bitbang.c. */ + +#define SPI_SETSCK GPIO_WRITE(CONFIG_ESPRESSIF_SPI_BITBANG_CLKPIN, true) +#define SPI_CLRSCK GPIO_WRITE(CONFIG_ESPRESSIF_SPI_BITBANG_CLKPIN, false) +#define SPI_SETMOSI GPIO_WRITE(CONFIG_ESPRESSIF_SPI_BITBANG_MOSIPIN, true) +#define SPI_CLRMOSI GPIO_WRITE(CONFIG_ESPRESSIF_SPI_BITBANG_MOSIPIN, \ + false) +#define SPI_GETMISO GPIO_READ(CONFIG_ESPRESSIF_SPI_BITBANG_MISOPIN) +#define SPI_SETCS GPIO_WRITE(CONFIG_ESPRESSIF_SPI_BITBANG_CSPIN, true) +#define SPI_CLRCS GPIO_WRITE(CONFIG_ESPRESSIF_SPI_BITBANG_CSPIN, false) + +/* Calibration value for timing loop */ + +#define SPI_BITBANG_LOOPSPERMSEC CONFIG_BOARD_LOOPSPERMSEC + +/* SPI_PERBIT_NSEC is the minimum time to transfer one bit. This determines + * the maximum frequency and is also used to calculate delays to achieve + * other SPI frequencies. + */ + +#define SPI_PERBIT_NSEC 100 + +#define ESPRESSIF_SPI_BITBANG 4 + +/**************************************************************************** + * Name: esp_spi_bitbang_init + * + * Description: + * Initialize the SPI bit-bang driver + * + * Input Parameters: + * None + * + * Returned Value: + * A non-NULL reference to the SPI driver on success + * + ****************************************************************************/ + +struct spi_dev_s *esp_spi_bitbang_init(void); + +/**************************************************************************** + * Name: esp_spi_bitbang_uninitialize + * + * Description: + * Destroy an instance of the SPI bit-bang driver. + * + * Input Parameters: + * dev - device instance, target driver to destroy. + * + ****************************************************************************/ + +void esp_spi_bitbang_uninitialize(struct spi_dev_s *dev); + +#endif /* CONFIG_ESPRESSIF_SPI_BITBANG */ + +#ifdef __cplusplus +} +#endif +#undef EXTERN + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_XTENSA_SRC_COMMON_ESPRESSIF_ESP_SPI_BITBANG_H */ diff --git a/arch/xtensa/src/esp32/Kconfig b/arch/xtensa/src/esp32/Kconfig index 66390e6284392..19327ee59a686 100644 --- a/arch/xtensa/src/esp32/Kconfig +++ b/arch/xtensa/src/esp32/Kconfig @@ -610,6 +610,7 @@ config ESP32_SPI2 select ESP32_SPI select ESP32_GPIO_IRQ select SPI + select ESPRESSIF_SPI_PERIPH config ESP32_SPI3 bool "SPI 3" @@ -617,6 +618,7 @@ config ESP32_SPI3 select ESP32_SPI select ESP32_GPIO_IRQ select SPI + select ESPRESSIF_SPI_PERIPH config ESP32_SPIRAM bool "SPI RAM" diff --git a/arch/xtensa/src/esp32s2/Kconfig b/arch/xtensa/src/esp32s2/Kconfig index 0afe64c8b28f8..5afd13b7c042b 100644 --- a/arch/xtensa/src/esp32s2/Kconfig +++ b/arch/xtensa/src/esp32s2/Kconfig @@ -353,12 +353,14 @@ config ESP32S2_SPI2 default n select ESP32S2_SPI select SPI + select ESPRESSIF_SPI_PERIPH config ESP32S2_SPI3 bool "SPI 3" default n select ESP32S2_SPI select SPI + select ESPRESSIF_SPI_PERIPH config ESP32S2_SPIRAM bool "SPI RAM Support" diff --git a/arch/xtensa/src/esp32s3/Kconfig b/arch/xtensa/src/esp32s3/Kconfig index f76bbdd9f377d..a03c78b0800b1 100644 --- a/arch/xtensa/src/esp32s3/Kconfig +++ b/arch/xtensa/src/esp32s3/Kconfig @@ -615,6 +615,7 @@ config ESP32S3_SPI2 select ESP32S3_SPI select SPI select ESP32S3_GPIO_IRQ if SPI_SLAVE + select ESPRESSIF_SPI_PERIPH config ESP32S3_SPI3 bool "SPI 3" @@ -622,6 +623,7 @@ config ESP32S3_SPI3 select ESP32S3_SPI select SPI select ESP32S3_GPIO_IRQ if SPI_SLAVE + select ESPRESSIF_SPI_PERIPH config ESP32S3_DMA bool "General DMA (GDMA)" diff --git a/boards/xtensa/esp32/common/src/esp32_board_spidev.c b/boards/xtensa/esp32/common/src/esp32_board_spidev.c index 0d7a5c2f94f6a..2eaedad6dc785 100644 --- a/boards/xtensa/esp32/common/src/esp32_board_spidev.c +++ b/boards/xtensa/esp32/common/src/esp32_board_spidev.c @@ -30,43 +30,173 @@ #include +#ifdef CONFIG_ESPRESSIF_SPI_PERIPH #include "esp32_spi.h" +#endif + +#ifdef CONFIG_ESPRESSIF_SPI_BITBANG +#include "espressif/esp_spi_bitbang.h" +#endif /**************************************************************************** - * Public Functions + * Private Functions ****************************************************************************/ /**************************************************************************** - * Name: board_spidev_initialize + * Name: spi_bitbang_driver_init * * Description: - * Initialize and register SPI driver for the specified SPI port. + * Initialize SPI bitbang driver and register the /dev/spi device. + * + * Input Parameters: + * port - The SPI bus number, used to build the device path as /dev/spiN + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. * ****************************************************************************/ -int board_spidev_initialize(int port) +#ifdef CONFIG_ESPRESSIF_SPI_BITBANG +static int spi_bitbang_driver_init(int port) { int ret; struct spi_dev_s *spi; - spiinfo("Initializing /dev/spi%d...\n", port); + syslog(LOG_INFO, "Initializing /dev/spi%d...\n", port); /* Initialize SPI device */ - spi = esp32_spibus_initialize(port); + spi = esp_spi_bitbang_init(); + if (spi == NULL) { - spierr("Failed to initialize SPI%d.\n", port); + syslog(LOG_ERR, "Failed to initialize SPI%d.\n", port); return -ENODEV; } ret = spi_register(spi, port); if (ret < 0) { - spierr("Failed to register /dev/spi%d: %d\n", port, ret); + syslog(LOG_ERR, "Failed to register /dev/spi%d: %d\n", port, ret); + esp_spi_bitbang_uninitialize(spi); + } + + return ret; +} +#endif +/**************************************************************************** + * Name: spi_driver_init + * + * Description: + * Initialize SPI driver and register the /dev/spi device. + * + * Input Parameters: + * port - The SPI bus number, used to build the device path as /dev/spiN + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ESPRESSIF_SPI_PERIPH +static int spi_driver_init(int port) +{ + int ret = OK; + struct spi_dev_s *spi; + + syslog(LOG_INFO, "Initializing /dev/spi%d...\n", port); + + /* Initialize SPI device */ + + spi = esp32_spibus_initialize(port); + + if (spi == NULL) + { + syslog(LOG_ERR, "Failed to initialize SPI%d.\n", port); + return -ENODEV; + } + + ret = spi_register(spi, port); + if (ret < 0) + { + syslog(LOG_ERR, "Failed to register /dev/spi%d: %d\n", port, ret); esp32_spibus_uninitialize(spi); } return ret; } +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_spidev_initialize + * + * Description: + * Initialize SPI driver and register the /dev/spi device. + * + * Input Parameters: + * port - The SPI bus number, used to build the device path as /dev/spiN + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int board_spidev_initialize(int port) +{ + int ret = OK; + + switch (port) + { +#ifdef CONFIG_ESP32_SPI2 + case ESP32_SPI2: + { + ret = spi_driver_init(ESP32_SPI2); + if (ret != OK) + { + return ret; + } + break; + } +#endif + +#ifdef CONFIG_ESP32_SPI3 + case ESP32_SPI3: + { + ret = spi_driver_init(ESP32_SPI3); + if (ret != OK) + { + return ret; + } + break; + } +#endif + +#ifdef CONFIG_ESPRESSIF_SPI_BITBANG + case ESPRESSIF_SPI_BITBANG: + { + ret = spi_bitbang_driver_init(ESPRESSIF_SPI_BITBANG); + if (ret != OK) + { + return ret; + } + break; + } +#endif + + default: + { + wderr("ERROR: unsupported SPI %d\n", port); + return ERROR; + } + } + + return ret; +} diff --git a/boards/xtensa/esp32s2/common/src/esp32s2_board_spidev.c b/boards/xtensa/esp32s2/common/src/esp32s2_board_spidev.c index 5bec3c86b26c2..b1af0e06c98c2 100644 --- a/boards/xtensa/esp32s2/common/src/esp32s2_board_spidev.c +++ b/boards/xtensa/esp32s2/common/src/esp32s2_board_spidev.c @@ -30,19 +30,25 @@ #include +#ifdef CONFIG_ESPRESSIF_SPI_PERIPH #include "esp32s2_spi.h" +#endif + +#ifdef CONFIG_ESPRESSIF_SPI_BITBANG +#include "espressif/esp_spi_bitbang.h" +#endif #include "esp32s2_board_spidev.h" /**************************************************************************** - * Public Functions + * Private Functions ****************************************************************************/ /**************************************************************************** - * Name: board_spidev_initialize + * Name: spi_bitbang_driver_init * * Description: - * Initialize SPI driver and register the /dev/spi device. + * Initialize SPI bitbang driver and register the /dev/spi device. * * Input Parameters: * port - The SPI bus number, used to build the device path as /dev/spiN @@ -53,7 +59,8 @@ * ****************************************************************************/ -int board_spidev_initialize(int port) +#ifdef CONFIG_ESPRESSIF_SPI_BITBANG +static int spi_bitbang_driver_init(int port) { int ret; struct spi_dev_s *spi; @@ -62,7 +69,8 @@ int board_spidev_initialize(int port) /* Initialize SPI device */ - spi = esp32s2_spibus_initialize(port); + spi = esp_spi_bitbang_init(); + if (spi == NULL) { syslog(LOG_ERR, "Failed to initialize SPI%d.\n", port); @@ -73,9 +81,124 @@ int board_spidev_initialize(int port) if (ret < 0) { syslog(LOG_ERR, "Failed to register /dev/spi%d: %d\n", port, ret); + esp_spi_bitbang_uninitialize(spi); + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: spi_driver_init + * + * Description: + * Initialize SPI driver and register the /dev/spi device. + * + * Input Parameters: + * port - The SPI bus number, used to build the device path as /dev/spiN + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ +#ifdef CONFIG_ESPRESSIF_SPI_PERIPH +static int spi_driver_init(int port) +{ + int ret = OK; + struct spi_dev_s *spi; + + syslog(LOG_INFO, "Initializing /dev/spi%d...\n", port); + + /* Initialize SPI device */ + + spi = esp32s2_spibus_initialize(port); + + if (spi == NULL) + { + syslog(LOG_ERR, "Failed to initialize SPI%d.\n", port); + return -ENODEV; + } + + ret = spi_register(spi, port); + if (ret < 0) + { + syslog(LOG_ERR, "Failed to register /dev/spi%d: %d\n", port, ret); esp32s2_spibus_uninitialize(spi); } return ret; } +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_spidev_initialize + * + * Description: + * Initialize SPI driver and register the /dev/spi device. + * + * Input Parameters: + * port - The SPI bus number, used to build the device path as /dev/spiN + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int board_spidev_initialize(int port) +{ + int ret = OK; + + switch (port) + { +#ifdef CONFIG_ESP32S2_SPI2 + case ESP32S2_SPI2: + { + ret = spi_driver_init(ESP32S2_SPI2); + if (ret != OK) + { + return ret; + } + break; + } +#endif + +#ifdef CONFIG_ESP32S2_SPI3 + case ESP32S2_SPI3: + { + ret = spi_driver_init(ESP32S2_SPI3); + if (ret != OK) + { + return ret; + } + break; + } +#endif + +#ifdef CONFIG_ESPRESSIF_SPI_BITBANG + case ESPRESSIF_SPI_BITBANG: + { + ret = spi_bitbang_driver_init(ESPRESSIF_SPI_BITBANG); + if (ret != OK) + { + return ret; + } + break; + } +#endif + + default: + { + wderr("ERROR: unsupported SPI %d\n", port); + return ERROR; + } + } + + return ret; +} diff --git a/boards/xtensa/esp32s3/common/src/esp32s3_board_spidev.c b/boards/xtensa/esp32s3/common/src/esp32s3_board_spidev.c index c5d391e9be4c9..9511492f65e86 100644 --- a/boards/xtensa/esp32s3/common/src/esp32s3_board_spidev.c +++ b/boards/xtensa/esp32s3/common/src/esp32s3_board_spidev.c @@ -30,17 +30,23 @@ #include +#ifdef CONFIG_ESPRESSIF_SPI_PERIPH #include "esp32s3_spi.h" +#endif + +#ifdef CONFIG_ESPRESSIF_SPI_BITBANG +#include "espressif/esp_spi_bitbang.h" +#endif /**************************************************************************** - * Public Functions + * Private Functions ****************************************************************************/ /**************************************************************************** - * Name: board_spidev_initialize + * Name: spi_bitbang_driver_init * * Description: - * Initialize SPI driver and register the /dev/spi device. + * Initialize SPI bitbang driver and register the /dev/spi device. * * Input Parameters: * port - The SPI bus number, used to build the device path as /dev/spiN @@ -51,29 +57,146 @@ * ****************************************************************************/ -int board_spidev_initialize(int port) +#ifdef CONFIG_ESPRESSIF_SPI_BITBANG +static int spi_bitbang_driver_init(int port) { int ret; struct spi_dev_s *spi; - spiinfo("Initializing /dev/spi%d...\n", port); + syslog(LOG_INFO, "Initializing /dev/spi%d...\n", port); /* Initialize SPI device */ - spi = esp32s3_spibus_initialize(port); + spi = esp_spi_bitbang_init(); + if (spi == NULL) { - spierr("Failed to initialize SPI%d.\n", port); + syslog(LOG_ERR, "Failed to initialize SPI%d.\n", port); return -ENODEV; } ret = spi_register(spi, port); if (ret < 0) { - spierr("Failed to register /dev/spi%d: %d\n", port, ret); + syslog(LOG_ERR, "Failed to register /dev/spi%d: %d\n", port, ret); + esp_spi_bitbang_uninitialize(spi); + } + + return ret; +} +#endif + +/**************************************************************************** + * Name: spi_driver_init + * + * Description: + * Initialize SPI driver and register the /dev/spi device. + * + * Input Parameters: + * port - The SPI bus number, used to build the device path as /dev/spiN + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_ESPRESSIF_SPI_PERIPH +static int spi_driver_init(int port) +{ + int ret = OK; + struct spi_dev_s *spi; + + syslog(LOG_INFO, "Initializing /dev/spi%d...\n", port); + + /* Initialize SPI device */ + + spi = esp32s3_spibus_initialize(port); + + if (spi == NULL) + { + syslog(LOG_ERR, "Failed to initialize SPI%d.\n", port); + return -ENODEV; + } + ret = spi_register(spi, port); + if (ret < 0) + { + syslog(LOG_ERR, "Failed to register /dev/spi%d: %d\n", port, ret); esp32s3_spibus_uninitialize(spi); } return ret; } +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_spidev_initialize + * + * Description: + * Initialize SPI driver and register the /dev/spi device. + * + * Input Parameters: + * port - The SPI bus number, used to build the device path as /dev/spiN + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int board_spidev_initialize(int port) +{ + int ret = OK; + + switch (port) + { +#ifdef CONFIG_ESP32S3_SPI2 + case ESP32S3_SPI2: + { + ret = spi_driver_init(ESP32S3_SPI2); + if (ret != OK) + { + return ret; + } + break; + } +#endif + +#ifdef CONFIG_ESP32S3_SPI3 + case ESP32S3_SPI3: + { + ret = spi_driver_init(ESP32S3_SPI3); + if (ret != OK) + { + return ret; + } + break; + } +#endif + +#ifdef CONFIG_ESPRESSIF_SPI_BITBANG + case ESPRESSIF_SPI_BITBANG: + { + ret = spi_bitbang_driver_init(ESPRESSIF_SPI_BITBANG); + if (ret != OK) + { + return ret; + } + break; + } +#endif + + default: + { + wderr("ERROR: unsupported SPI %d\n", port); + return ERROR; + } + } + + return ret; +} diff --git a/boards/xtensa/esp32s3/esp32s3-devkit/src/esp32s3_bringup.c b/boards/xtensa/esp32s3/esp32s3-devkit/src/esp32s3_bringup.c index 8718a875db1b5..e5afb34c696c3 100644 --- a/boards/xtensa/esp32s3/esp32s3-devkit/src/esp32s3_bringup.c +++ b/boards/xtensa/esp32s3/esp32s3-devkit/src/esp32s3_bringup.c @@ -107,6 +107,9 @@ #ifdef CONFIG_ESP32S3_SPI #include "esp32s3_spi.h" #include "esp32s3_board_spidev.h" +# ifdef CONFIG_ESPRESSIF_SPI_BITBANG +# include "espressif/esp_spi_bitbang.h" +# endif #endif #ifdef CONFIG_ESP32S3_SDMMC @@ -179,7 +182,15 @@ int esp32s3_bringup(void) syslog(LOG_ERR, "ERROR: Failed to init spidev 3: %d\n", ret); } #endif -#endif + + #ifdef CONFIG_ESPRESSIF_SPI_BITBANG + ret = board_spidev_initialize(ESPRESSIF_SPI_BITBANG); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: Failed to init spidev 3: %d\n", ret); + } + #endif /* CONFIG_ESPRESSIF_SPI_BITBANG */ +#endif /* CONFIG_ESP32S3_SPI && CONFIG_SPI_DRIVER*/ #if defined(CONFIG_ESP32S3_EFUSE) ret = esp32s3_efuse_initialize("/dev/efuse");