From dda55419f9a6ea434f4320aa21543095be7d3efd Mon Sep 17 00:00:00 2001 From: Eren Terzioglu Date: Thu, 20 Jun 2024 16:21:06 +0300 Subject: [PATCH] esp32[c3|c6|h2]: Add I2C master support --- .../esp32c3/boards/esp32c3-generic/index.rst | 8 + .../platforms/risc-v/esp32c3/index.rst | 2 +- .../esp32c6/boards/esp32c6-devkitc/index.rst | 8 + .../esp32c6/boards/esp32c6-devkitm/index.rst | 8 + .../platforms/risc-v/esp32c6/index.rst | 2 +- .../esp32h2/boards/esp32h2-devkit/index.rst | 8 + .../platforms/risc-v/esp32h2/index.rst | 2 +- arch/risc-v/src/common/espressif/Kconfig | 61 + arch/risc-v/src/common/espressif/Make.defs | 4 + arch/risc-v/src/common/espressif/esp_i2c.c | 1607 +++++++++++++++++ arch/risc-v/src/common/espressif/esp_i2c.h | 91 + arch/risc-v/src/esp32c3/hal_esp32c3.mk | 2 + arch/risc-v/src/esp32c6/hal_esp32c6.mk | 2 + arch/risc-v/src/esp32h2/hal_esp32h2.mk | 2 + .../esp32c3/common/include/esp_board_i2c.h | 74 + boards/risc-v/esp32c3/common/src/Make.defs | 4 + .../risc-v/esp32c3/common/src/esp_board_i2c.c | 82 + .../esp32c3-generic/configs/i2c/defconfig | 52 + .../esp32c3-generic/src/esp32c3_bringup.c | 12 + .../esp32c6/common/include/esp_board_i2c.h | 74 + boards/risc-v/esp32c6/common/src/Make.defs | 4 + .../risc-v/esp32c6/common/src/esp_board_i2c.c | 82 + .../esp32c6-devkitc/configs/i2c/defconfig | 54 + .../esp32c6-devkitc/src/esp32c6_bringup.c | 12 + .../esp32c6-devkitm/configs/i2c/defconfig | 54 + .../esp32c6-devkitm/src/esp32c6_bringup.c | 12 + .../esp32h2/common/include/esp_board_i2c.h | 74 + boards/risc-v/esp32h2/common/src/Make.defs | 4 + .../risc-v/esp32h2/common/src/esp_board_i2c.c | 90 + .../esp32h2-devkit/configs/i2c/defconfig | 54 + .../esp32h2-devkit/src/esp32h2_bringup.c | 12 + 31 files changed, 2554 insertions(+), 3 deletions(-) create mode 100644 arch/risc-v/src/common/espressif/esp_i2c.c create mode 100644 arch/risc-v/src/common/espressif/esp_i2c.h create mode 100644 boards/risc-v/esp32c3/common/include/esp_board_i2c.h create mode 100644 boards/risc-v/esp32c3/common/src/esp_board_i2c.c create mode 100644 boards/risc-v/esp32c3/esp32c3-generic/configs/i2c/defconfig create mode 100644 boards/risc-v/esp32c6/common/include/esp_board_i2c.h create mode 100644 boards/risc-v/esp32c6/common/src/esp_board_i2c.c create mode 100644 boards/risc-v/esp32c6/esp32c6-devkitc/configs/i2c/defconfig create mode 100644 boards/risc-v/esp32c6/esp32c6-devkitm/configs/i2c/defconfig create mode 100644 boards/risc-v/esp32h2/common/include/esp_board_i2c.h create mode 100644 boards/risc-v/esp32h2/common/src/esp_board_i2c.c create mode 100644 boards/risc-v/esp32h2/esp32h2-devkit/configs/i2c/defconfig diff --git a/Documentation/platforms/risc-v/esp32c3/boards/esp32c3-generic/index.rst b/Documentation/platforms/risc-v/esp32c3/boards/esp32c3-generic/index.rst index dc505e2acb..8c3728b10f 100644 --- a/Documentation/platforms/risc-v/esp32c3/boards/esp32c3-generic/index.rst +++ b/Documentation/platforms/risc-v/esp32c3/boards/esp32c3-generic/index.rst @@ -84,6 +84,14 @@ We can use the interrupt pin to send a signal when the interrupt fires:: The pin is configured as a rising edge interrupt, so after issuing the above command, connect it to 3.3V. +i2c +--- + +This configuration can be used to scan and manipulate I2C devices. +You can scan for all I2C devices using the following command:: + + nsh> i2c dev 0x00 0x7f + nsh --- diff --git a/Documentation/platforms/risc-v/esp32c3/index.rst b/Documentation/platforms/risc-v/esp32c3/index.rst index 642c02dfe6..79020922fe 100644 --- a/Documentation/platforms/risc-v/esp32c3/index.rst +++ b/Documentation/platforms/risc-v/esp32c3/index.rst @@ -165,7 +165,7 @@ CDC Console Yes Rev.3 DMA No eFuse No GPIO Yes -I2C No +I2C Yes LED_PWM Yes RNG No RSA No diff --git a/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitc/index.rst b/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitc/index.rst index ba479f1768..b48028e343 100644 --- a/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitc/index.rst +++ b/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitc/index.rst @@ -119,6 +119,14 @@ We can use the interrupt pin to send a signal when the interrupt fires:: The pin is configured as a rising edge interrupt, so after issuing the above command, connect it to 3.3V. +i2c +--- + +This configuration can be used to scan and manipulate I2C devices. +You can scan for all I2C devices using the following command:: + + nsh> i2c dev 0x00 0x7f + nsh --- diff --git a/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitm/index.rst b/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitm/index.rst index 7cfd47a6b9..cfc632f2a9 100644 --- a/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitm/index.rst +++ b/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitm/index.rst @@ -119,6 +119,14 @@ We can use the interrupt pin to send a signal when the interrupt fires:: The pin is configured as a rising edge interrupt, so after issuing the above command, connect it to 3.3V. +i2c +--- + +This configuration can be used to scan and manipulate I2C devices. +You can scan for all I2C devices using the following command:: + + nsh> i2c dev 0x00 0x7f + nsh --- diff --git a/Documentation/platforms/risc-v/esp32c6/index.rst b/Documentation/platforms/risc-v/esp32c6/index.rst index 636ca5bbfe..1d5377b751 100644 --- a/Documentation/platforms/risc-v/esp32c6/index.rst +++ b/Documentation/platforms/risc-v/esp32c6/index.rst @@ -147,7 +147,7 @@ ECC No eFuse No GPIO Yes HMAC No -I2C No +I2C Yes I2S No Int. Temp. No LED No diff --git a/Documentation/platforms/risc-v/esp32h2/boards/esp32h2-devkit/index.rst b/Documentation/platforms/risc-v/esp32h2/boards/esp32h2-devkit/index.rst index 56f181408c..b03b3702a1 100644 --- a/Documentation/platforms/risc-v/esp32h2/boards/esp32h2-devkit/index.rst +++ b/Documentation/platforms/risc-v/esp32h2/boards/esp32h2-devkit/index.rst @@ -118,6 +118,14 @@ We can use the interrupt pin to send a signal when the interrupt fires:: The pin is configured as a rising edge interrupt, so after issuing the above command, connect it to 3.3V. +i2c +--- + +This configuration can be used to scan and manipulate I2C devices. +You can scan for all I2C devices using the following command:: + + nsh> i2c dev 0x00 0x7f + nsh --- diff --git a/Documentation/platforms/risc-v/esp32h2/index.rst b/Documentation/platforms/risc-v/esp32h2/index.rst index 3f5d8d17b9..0a63e9fea2 100644 --- a/Documentation/platforms/risc-v/esp32h2/index.rst +++ b/Documentation/platforms/risc-v/esp32h2/index.rst @@ -147,7 +147,7 @@ ECC No eFuse No GPIO Yes HMAC No -I2C No +I2C Yes I2S No Int. Temp. No LED No diff --git a/arch/risc-v/src/common/espressif/Kconfig b/arch/risc-v/src/common/espressif/Kconfig index 5e10163143..2b048e2d55 100644 --- a/arch/risc-v/src/common/espressif/Kconfig +++ b/arch/risc-v/src/common/espressif/Kconfig @@ -11,16 +11,19 @@ choice ESPRESSIF_CHIP_SERIES config ESPRESSIF_ESP32C3 bool "ESP32-C3" + select ARCH_HAVE_I2CRESET ---help--- ESP32-C3 chip with a single RISC-V IMC core, no embedded Flash memory config ESPRESSIF_ESP32C6 bool "ESP32-C6" + select ARCH_HAVE_I2CRESET ---help--- Espressif ESP32-C6 (RV32IMAC). config ESPRESSIF_ESP32H2 bool "ESP32-H2" + select ARCH_HAVE_I2CRESET ---help--- Espressif ESP32-H2 (RV32IMC). @@ -314,6 +317,23 @@ config ESPRESSIF_LEDC select PWM select ARCH_HAVE_PWM_MULTICHAN +config ESPRESSIF_I2C + bool + default n + +config ESPRESSIF_I2C0 + bool "I2C 0" + default n + select ESPRESSIF_I2C + select I2C + +config ESPRESSIF_I2C1 + bool "I2C 1" + default n + depends on ARCH_CHIP_ESP32H2 + select ESPRESSIF_I2C + select I2C + config ESPRESSIF_SPI bool default n @@ -1208,6 +1228,47 @@ endif # PWM_MULTICHAN && PWM_NCHANNELS > 1 endmenu # LEDC configuration +menu "I2C Configuration" + depends on ESPRESSIF_I2C + +if ESPRESSIF_I2C0 + +config ESPRESSIF_I2C0_SCLPIN + int "I2C0 SCL Pin" + default 6 + range 0 21 + +config ESPRESSIF_I2C0_SDAPIN + int "I2C0 SDA Pin" + default 5 + range 0 21 + +endif # ESPRESSIF_I2C0 + +if ESPRESSIF_I2C1 + +config ESPRESSIF_I2C1_SCLPIN + int "I2C1 SCL Pin" + default 2 + range 0 21 + +config ESPRESSIF_I2C1_SDAPIN + int "I2C1 SDA Pin" + default 1 + range 0 21 + +endif # ESPRESSIF_I2C1 + +config ESPRESSIF_I2CTIMEOSEC + int "Timeout seconds" + default 0 + +config ESPRESSIF_I2CTIMEOMS + int "Timeout milliseconds" + default 500 + +endmenu # I2C configuration + menu "High Resolution Timer" depends on ESPRESSIF_HR_TIMER diff --git a/arch/risc-v/src/common/espressif/Make.defs b/arch/risc-v/src/common/espressif/Make.defs index 9daf4e270e..d75ab3dac1 100644 --- a/arch/risc-v/src/common/espressif/Make.defs +++ b/arch/risc-v/src/common/espressif/Make.defs @@ -84,6 +84,10 @@ ifeq ($(CONFIG_ESP_RMT),y) endif endif +ifeq ($(CONFIG_ESPRESSIF_I2C),y) + CHIP_CSRCS += esp_i2c.c +endif + ifeq ($(CONFIG_ESPRESSIF_SPI),y) CHIP_CSRCS += esp_spi.c ifeq ($(CONFIG_SPI_SLAVE),y) diff --git a/arch/risc-v/src/common/espressif/esp_i2c.c b/arch/risc-v/src/common/espressif/esp_i2c.c new file mode 100644 index 0000000000..2cf0f64e67 --- /dev/null +++ b/arch/risc-v/src/common/espressif/esp_i2c.c @@ -0,0 +1,1607 @@ +/**************************************************************************** + * arch/risc-v/src/common/espressif/esp_i2c.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_I2C + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "esp_i2c.h" +#include "esp_irq.h" +#include "esp_gpio.h" +#include "riscv_internal.h" + +#include "periph_ctrl.h" +#include "hal/i2c_hal.h" +#include "hal/i2c_types.h" +#include "hal/i2c_ll.h" +#include "soc/system_reg.h" +#include "soc/gpio_sig_map.h" +#include "soc/i2c_periph.h" +#if defined(CONFIG_ESPRESSIF_ESP32H2) || defined(CONFIG_ESPRESSIF_ESP32C6) +# include "soc/pcr_reg.h" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_ESPRESSIF_ESP32H2 +# define SYSTEM_I2C_EXT0_CLK_EN PCR_I2C0_CLK_EN +# define SYSTEM_I2C_EXT0_RST PCR_I2C0_RST_EN +# define SYSTEM_I2C_EXT1_CLK_EN PCR_I2C1_CLK_EN +# define SYSTEM_I2C_EXT1_RST PCR_I2C1_RST_EN +#endif + +#ifdef CONFIG_ESPRESSIF_ESP32C6 +# define SYSTEM_I2C_EXT0_CLK_EN PCR_I2C_CLK_EN +# define SYSTEM_I2C_EXT0_RST PCR_I2C_RST_EN +#endif + +#define GET_STATUS(hw) hw->sr.val + +#define ESPRESSIF_I2CTIMEOTICKS \ + (SEC2TICK(CONFIG_ESPRESSIF_I2CTIMEOSEC) + MSEC2TICK(CONFIG_ESPRESSIF_I2CTIMEOMS)) + +/* I2C hardware FIFO depth */ + +#define I2C_FIFO_SIZE (32) + +/* Number of bus cycles filtered by default */ + +#define I2C_FILTER_CYC_NUM_DEF (7) + +/* Number of bus cycles for the master to generate when the slave is in + * deadlock + */ + +#define I2C_SCL_CYC_NUM_DEF (9) + +/* I2C default clock frequency */ + +#define I2C_CLK_FREQ_DEF (100 * 1000) + +/* Mask for the interrupt errors */ + +#define I2C_INT_ERR_MASK (I2C_NACK_INT_ENA_M | \ + I2C_TIME_OUT_INT_ENA_M | \ + I2C_ARBITRATION_LOST_INT_ENA_M) + +/* I2C event trace logic. + * NOTE: trace uses the internal, non-standard, low-level debug interface + * syslog() but does not require that any other debug is enabled. + */ + +#ifndef CONFIG_I2C_TRACE +# define esp_i2c_tracereset(p) +# define esp_i2c_tracenew(p,s) +# define esp_i2c_traceevent(p,e,a,s) +# define esp_i2c_tracedump(p) +#endif + +#ifndef CONFIG_I2C_NTRACE +# define CONFIG_I2C_NTRACE 32 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* I2C state */ + +enum esp_i2cstate_e +{ + I2CSTATE_IDLE = 0, + I2CSTATE_PROC, + I2CSTATE_STOP, +#ifndef CONFIG_I2C_POLLED + I2CSTATE_FINISH, +#endif + I2CSTATE_ERROR +}; + +/* I2C hardware command */ + +enum esp_i2c_opmode_e +{ + I2C_CMD_RESTART = 6, /* I2C restart command */ + I2C_CMD_WRITE = 1, /* I2C write command */ + I2C_CMD_READ = 3, /* I2C read command */ + I2C_CMD_STOP = 2, /* I2C stop command */ + I2C_CMD_END = 4 /* I2C end command */ +}; + +#ifdef CONFIG_I2C_TRACE + +/* Trace events */ + +enum esp_trace_e +{ + I2CEVENT_NONE = 0, /* No events have occurred with this status */ + I2CEVENT_SENDADDR, /* Start/Master bit set and address sent, param = addr */ + I2CEVENT_SENDBYTE, /* Send byte, param = bytes */ + I2CEVENT_RCVMODEEN, /* Receive mode enabled, param = 0 */ + I2CEVENT_RCVBYTE, /* Read more dta, param = bytes */ + I2CEVENT_STOP, /* Last byte sten, send stop, param = length */ + I2CEVENT_ERROR /* Error occurred, param = 0 */ +}; + +/* Trace data */ + +struct esp_trace_s +{ + uint32_t status; /* I2C 32-bit SR status */ + uint32_t count; /* Interrupt count when status change */ + enum esp_i2cstate_e event; /* Last event that occurred with this status */ + uint32_t parm; /* Parameter associated with the event */ + clock_t time; /* First of event or first status */ +}; + +#endif /* CONFIG_I2C_TRACE */ + +/* I2C Device hardware configuration */ + +struct esp_i2c_config_s +{ + uint32_t clk_freq; /* Clock frequency */ + + uint8_t scl_pin; /* GPIO configuration for SCL as SCL */ + uint8_t sda_pin; /* GPIO configuration for SDA as SDA */ + +#ifndef CONFIG_I2C_POLLED + uint8_t periph; /* Peripheral ID */ + uint8_t irq; /* Interrupt ID */ +#endif + + uint32_t clk_bit; /* Clock enable bit */ + uint32_t rst_bit; /* I2C reset bit */ + + uint32_t scl_insig; /* I2C SCL input signal index */ + uint32_t scl_outsig; /* I2C SCL output signal index */ + + uint32_t sda_insig; /* I2C SDA input signal index */ + uint32_t sda_outsig; /* I2C SDA output signal index */ +}; + +/* I2C Device Private Data */ + +struct esp_i2c_priv_s +{ + const struct i2c_ops_s *ops; /* Standard I2C operations */ + + uint32_t id; /* I2C instance */ + + /* Port configuration */ + + const struct esp_i2c_config_s *config; + int refs; /* Reference count */ + mutex_t lock; /* Mutual exclusion mutex */ + +#ifndef CONFIG_I2C_POLLED + sem_t sem_isr; /* Interrupt wait semaphore */ +#endif + + /* I2C work state (see enum esp_i2cstate_e) */ + + volatile enum esp_i2cstate_e i2cstate; + + struct i2c_msg_s *msgv; /* Message list */ + + uint8_t msgid; /* Current message ID */ + ssize_t bytes; /* Processed data bytes */ + +#ifndef CONFIG_I2C_POLLED + int cpuint; /* CPU interrupt assigned to this I2C */ +#endif + + uint32_t error; /* I2C transform error */ + + bool ready_read; /* If I2C is ready for receiving data */ + + uint32_t clk_freq; /* Current I2C Clock frequency */ + + /* I2C trace support */ + +#ifdef CONFIG_I2C_TRACE + int tndx; /* Trace array index */ + clock_t start_time; /* Time when the trace was started */ + + /* The actual trace data */ + + struct esp_trace_s trace[CONFIG_I2C_NTRACE]; + +#endif + i2c_hal_context_t *ctx; /* Common layer struct */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void esp_i2c_reset_fifo(struct esp_i2c_priv_s *priv); +static void esp_i2c_intr_enable(struct esp_i2c_priv_s *priv); +static void esp_i2c_intr_enable(struct esp_i2c_priv_s *priv); +static void esp_i2c_intr_disable(struct esp_i2c_priv_s *priv); +static void esp_i2c_sendstart(struct esp_i2c_priv_s *priv); +static void esp_i2c_senddata(struct esp_i2c_priv_s *priv); +static void esp_i2c_recvdata(struct esp_i2c_priv_s *priv); +static void esp_i2c_startrecv(struct esp_i2c_priv_s *priv); +static void esp_i2c_sendstop(struct esp_i2c_priv_s *priv); +static void esp_i2c_init_clock(struct esp_i2c_priv_s *priv, + uint32_t bus_freq); +static void esp_i2c_init(struct esp_i2c_priv_s *priv); +static void esp_i2c_deinit(struct esp_i2c_priv_s *priv); +static void esp_i2c_reset_fsmc(struct esp_i2c_priv_s *priv); +static int esp_i2c_sem_waitdone(struct esp_i2c_priv_s *priv); +#ifdef CONFIG_I2C_POLLED +static int esp_i2c_polling_waitdone(struct esp_i2c_priv_s *priv); +#endif /* CONFIG_I2C_POLLED */ +static int esp_i2c_transfer(struct i2c_master_s *dev, + struct i2c_msg_s *msgs, + int count); +#ifdef CONFIG_I2C_RESET +static void esp_i2c_clear_bus(struct esp_i2c_priv_s *priv); +static int esp_i2c_reset(struct i2c_master_s *dev); +#endif /* CONFIG_I2C_RESET */ +#ifdef CONFIG_I2C_TRACE +static void esp_i2c_traceclear(struct esp_i2c_priv_s *priv); +static void esp_i2c_tracereset(struct esp_i2c_priv_s *priv); +static void esp_i2c_tracenew(struct esp_i2c_priv_s *priv, + uint32_t status); +static void esp_i2c_traceevent(struct esp_i2c_priv_s *priv, + enum esp_trace_e event, + uint32_t parm, + uint32_t status); +static void esp_i2c_tracedump(struct esp_i2c_priv_s *priv); +#endif /* CONFIG_I2C_TRACE */ +#ifndef CONFIG_I2C_POLLED +static int esp_i2c_irq(int cpuint, void *context, void *arg); +#endif /* CONFIG_I2C_POLLED */ +static inline void esp_i2c_process(struct esp_i2c_priv_s *priv, + uint32_t status); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* I2C interface */ + +static const struct i2c_ops_s esp_i2c_ops = +{ + .transfer = esp_i2c_transfer +#ifdef CONFIG_I2C_RESET + , .reset = esp_i2c_reset +#endif +}; + +#ifdef CONFIG_ESPRESSIF_I2C0 + +i2c_hal_context_t i2c0_ctx = +{ + 0 +}; + +/* I2C device structure */ + +static const struct esp_i2c_config_s esp_i2c0_config = +{ + .clk_freq = I2C_CLK_FREQ_DEF, + .scl_pin = CONFIG_ESPRESSIF_I2C0_SCLPIN, + .sda_pin = CONFIG_ESPRESSIF_I2C0_SDAPIN, +#ifndef CONFIG_I2C_POLLED + .periph = ETS_I2C_EXT0_INTR_SOURCE, + .irq = ESP_IRQ_I2C_EXT0, +#endif + .clk_bit = SYSTEM_I2C_EXT0_CLK_EN, + .rst_bit = SYSTEM_I2C_EXT0_RST, + .scl_insig = I2CEXT0_SCL_IN_IDX, + .scl_outsig = I2CEXT0_SCL_OUT_IDX, + .sda_insig = I2CEXT0_SDA_IN_IDX, + .sda_outsig = I2CEXT0_SDA_OUT_IDX +}; + +static struct esp_i2c_priv_s esp_i2c0_priv = +{ + .ops = &esp_i2c_ops, + .id = 0, + .config = &esp_i2c0_config, + .refs = 0, + .lock = NXMUTEX_INITIALIZER, +#ifndef CONFIG_I2C_POLLED + .sem_isr = SEM_INITIALIZER(0), +#endif + .i2cstate = I2CSTATE_IDLE, + .msgv = NULL, + .msgid = 0, + .bytes = 0, +#ifndef CONFIG_I2C_POLLED + .cpuint = -ENOMEM, +#endif + .error = 0, + .ready_read = false, + .clk_freq = 0, + .ctx = &i2c0_ctx +}; +#endif + +#ifdef CONFIG_ESPRESSIF_I2C1 + +i2c_hal_context_t i2c1_ctx = +{ + 0 +}; + +/* I2C device structure */ + +static const struct esp_i2c_config_s esp_i2c1_config = +{ + .clk_freq = I2C_CLK_FREQ_DEF, + .scl_pin = CONFIG_ESPRESSIF_I2C1_SCLPIN, + .sda_pin = CONFIG_ESPRESSIF_I2C1_SDAPIN, +#ifndef CONFIG_I2C_POLLED + .periph = ETS_I2C_EXT1_INTR_SOURCE, + .irq = ESP_IRQ_I2C_EXT1, +#endif + .clk_bit = SYSTEM_I2C_EXT1_CLK_EN, + .rst_bit = SYSTEM_I2C_EXT1_RST, + .scl_insig = I2CEXT1_SCL_IN_IDX, + .scl_outsig = I2CEXT1_SCL_OUT_IDX, + .sda_insig = I2CEXT1_SDA_IN_IDX, + .sda_outsig = I2CEXT1_SDA_OUT_IDX +}; + +static struct esp_i2c_priv_s esp_i2c1_priv = +{ + .ops = &esp_i2c_ops, + .id = 1, + .config = &esp_i2c1_config, + .refs = 0, + .lock = NXMUTEX_INITIALIZER, +#ifndef CONFIG_I2C_POLLED + .sem_isr = SEM_INITIALIZER(0), +#endif + .i2cstate = I2CSTATE_IDLE, + .msgv = NULL, + .msgid = 0, + .bytes = 0, +#ifndef CONFIG_I2C_POLLED + .cpuint = -ENOMEM, +#endif + .error = 0, + .ready_read = false, + .clk_freq = 0, + .ctx = &i2c1_ctx +}; +#endif /* CONFIG_ESPRESSIF_I2C1 */ + +/* Trace events strings */ + +#ifdef CONFIG_I2C_TRACE +static const char *g_trace_names[] = +{ + "NONE ", + "SENDADDR ", + "SENDBYTE ", + "RCVMODEEN ", + "RCVBYTE ", + "STOP ", + "ERROR " +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_i2c_reset_fifo + * + * Description: + * Reset I2C RX and TX hardware FIFO. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * + ****************************************************************************/ + +static void esp_i2c_reset_fifo(struct esp_i2c_priv_s *priv) +{ + i2c_ll_txfifo_rst(priv->ctx->dev); + i2c_ll_rxfifo_rst(priv->ctx->dev); +} + +/**************************************************************************** + * Name: esp_i2c_intr_enable + * + * Description: + * Enable I2C interrupts. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * + ****************************************************************************/ + +static void esp_i2c_intr_enable(struct esp_i2c_priv_s *priv) +{ + i2c_ll_clear_intr_mask(priv->ctx->dev, I2C_LL_INTR_MASK); + i2c_ll_enable_intr_mask(priv->ctx->dev, I2C_LL_MASTER_EVENT_INTR); +} + +/**************************************************************************** + * Name: esp_i2c_intr_disable + * + * Description: + * Disable I2C interrupts. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * + ****************************************************************************/ + +static void esp_i2c_intr_disable(struct esp_i2c_priv_s *priv) +{ + i2c_ll_disable_intr_mask(priv->ctx->dev, I2C_LL_INTR_MASK); + i2c_ll_clear_intr_mask(priv->ctx->dev, I2C_LL_INTR_MASK); +} + +/**************************************************************************** + * Name: esp_i2c_sendstart + * + * Description: + * Send I2C start signal. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * + ****************************************************************************/ + +static void esp_i2c_sendstart(struct esp_i2c_priv_s *priv) +{ + struct i2c_msg_s *msg = &priv->msgv[priv->msgid]; + uint32_t fifo_val = 0; + i2c_ll_hw_cmd_t restart_cmd; + i2c_ll_hw_cmd_t write_cmd; + i2c_ll_hw_cmd_t end_cmd; + + /* Write I2C command registers */ + + restart_cmd.op_code = I2C_LL_CMD_RESTART; + + write_cmd.byte_num = 1; + write_cmd.ack_en = 1; + write_cmd.op_code = I2C_LL_CMD_WRITE; + + end_cmd.op_code = I2C_LL_CMD_END; + + i2c_ll_write_cmd_reg(priv->ctx->dev, restart_cmd, 0); + i2c_ll_write_cmd_reg(priv->ctx->dev, write_cmd, 1); + i2c_ll_write_cmd_reg(priv->ctx->dev, end_cmd, 2); + + /* Write data to FIFO register */ + + fifo_val = (msg->addr << 1) | (msg->flags & I2C_M_READ); + i2c_ll_write_txfifo(priv->ctx->dev, (uint8_t *)&fifo_val, 1); + + /* Enable I2C master TX interrupt */ + + esp_i2c_intr_enable(priv); + + /* Update I2C configuration */ + + /* Configure the I2C to trigger a transaction */ + + i2c_hal_master_trans_start(priv->ctx); +} + +/**************************************************************************** + * Name: esp_i2c_senddata + * + * Description: + * Send I2C data. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * + ****************************************************************************/ + +static void esp_i2c_senddata(struct esp_i2c_priv_s *priv) +{ + struct i2c_msg_s *msg = &priv->msgv[priv->msgid]; + int n = msg->length - priv->bytes; + i2c_ll_hw_cmd_t write_cmd = + { + .ack_en = 1, + .op_code = I2C_LL_CMD_WRITE + }; + + i2c_ll_hw_cmd_t end_cmd = + { + .op_code = I2C_LL_CMD_END + }; + + n = n < I2C_FIFO_SIZE ? n : I2C_FIFO_SIZE; + + write_cmd.byte_num = n; + i2c_ll_write_cmd_reg(priv->ctx->dev, write_cmd, 0); + i2c_ll_write_cmd_reg(priv->ctx->dev, end_cmd, 1); + i2c_ll_write_txfifo(priv->ctx->dev, &msg->buffer[priv->bytes], n); + i2c_ll_master_enable_tx_it(priv->ctx->dev); + + priv->bytes += n; + + /* Enable I2C master TX interrupt */ + + esp_i2c_intr_enable(priv); + + /* Update I2C configuration */ + + /* Configure the I2C to trigger a transaction */ + + i2c_hal_master_trans_start(priv->ctx); +} + +/**************************************************************************** + * Name: esp_i2c_recvdata + * + * Description: + * Transfer data from the FIFO to the driver buffer. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * + ****************************************************************************/ + +static void esp_i2c_recvdata(struct esp_i2c_priv_s *priv) +{ + struct i2c_msg_s *msg = &priv->msgv[priv->msgid]; + uint32_t cmd = 0; + uint8_t n = 0; + uint32_t data = 0; + + i2c_ll_get_rxfifo_cnt(priv->ctx->dev, &cmd); + n = cmd & 0xff; + + i2c_ll_read_rxfifo(priv->ctx->dev, &msg->buffer[priv->bytes], n); + i2c_ll_master_enable_rx_it(priv->ctx->dev); + + priv->bytes += n; +} + +/**************************************************************************** + * Name: esp_i2c_startrecv + * + * Description: + * Configure I2C to prepare receiving data and it will create an interrupt + * to receive real data. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * + ****************************************************************************/ + +static void esp_i2c_startrecv(struct esp_i2c_priv_s *priv) +{ + int ack_value = 0; + struct i2c_msg_s *msg = &priv->msgv[priv->msgid]; + int n = msg->length - priv->bytes; + i2c_ll_hw_cmd_t read_cmd; + i2c_ll_hw_cmd_t end_cmd; + + if (n > 1) + { + n -= 1; + n = n < I2C_FIFO_SIZE ? n : I2C_FIFO_SIZE; + ack_value = 0; + } + else + { + ack_value = 1; + } + + read_cmd.byte_num = n; + read_cmd.ack_val = ack_value; + read_cmd.op_code = I2C_LL_CMD_READ; + i2c_ll_write_cmd_reg(priv->ctx->dev, read_cmd, 0); + + end_cmd.op_code = I2C_LL_CMD_END; + i2c_ll_write_cmd_reg(priv->ctx->dev, end_cmd, 1); + + /* Enable I2C master RX interrupt */ + + esp_i2c_intr_enable(priv); + + /* Update I2C configuration */ + + /* Configure the I2C to trigger a transaction */ + + i2c_hal_master_trans_start(priv->ctx); +} + +/**************************************************************************** + * Name: esp_i2c_sendstop + * + * Description: + * Send I2C STOP signal. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * + ****************************************************************************/ + +static void esp_i2c_sendstop(struct esp_i2c_priv_s *priv) +{ + i2c_ll_hw_cmd_t stop_cmd = + { + .op_code = I2C_LL_CMD_STOP + }; + + i2c_ll_write_cmd_reg(priv->ctx->dev, stop_cmd, 0); + + /* Enable I2C master TX interrupt */ + + esp_i2c_intr_enable(priv); + + /* Update I2C configuration */ + + /* Configure the I2C to trigger a transaction */ + + i2c_hal_master_trans_start(priv->ctx); +} + +/**************************************************************************** + * Name: esp_i2c_init_clock + * + * Description: + * Initialize I2C hardware clock. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * bus_freq - Clock frequency of the I2C bus in Hz. + * + ****************************************************************************/ + +static void esp_i2c_init_clock(struct esp_i2c_priv_s *priv, + uint32_t bus_freq) +{ + if (bus_freq == priv->clk_freq) + { + return ; + } + + i2c_clock_source_t src_clk = I2C_CLK_SRC_DEFAULT; + i2c_hal_set_bus_timing(priv->ctx, priv->config->clk_freq, + src_clk, XTAL_CLK_FREQ); + i2c_ll_update(priv->ctx->dev); + priv->clk_freq = bus_freq; +} + +/**************************************************************************** + * Name: esp_i2c_init + * + * Description: + * Initialize I2C hardware. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * + ****************************************************************************/ + +static void esp_i2c_init(struct esp_i2c_priv_s *priv) +{ + const struct esp_i2c_config_s *config = priv->config; + + /* Configure GPIO signals for I2C SCL and SDA pins */ + + esp_gpiowrite(config->scl_pin, 1); + esp_gpiowrite(config->sda_pin, 1); + + esp_configgpio(config->scl_pin, INPUT_PULLUP | OUTPUT_OPEN_DRAIN); + esp_gpio_matrix_out(config->scl_pin, config->scl_outsig, 0, 0); + esp_gpio_matrix_in(config->scl_pin, config->scl_insig, 0); + + esp_configgpio(config->sda_pin, INPUT_PULLUP | OUTPUT_OPEN_DRAIN); + esp_gpio_matrix_out(config->sda_pin, config->sda_outsig, 0, 0); + esp_gpio_matrix_in(config->sda_pin, config->sda_insig, 0); + + /* Enable I2C hardware */ + + periph_module_enable(i2c_periph_signal[priv->id].module); + + i2c_hal_init(priv->ctx, priv->id); + + /* Disable I2C interrupts */ + + esp_i2c_intr_disable(priv); + + /* Initialize I2C Master */ + + i2c_hal_master_init(priv->ctx); + + /* Configure the hardware filter function */ + + i2c_ll_set_filter(priv->ctx->dev, I2C_FILTER_CYC_NUM_DEF); + + /* Initialize I2C bus clock */ + + esp_i2c_init_clock(priv, config->clk_freq); +} + +/**************************************************************************** + * Name: esp_i2c_deinit + * + * Description: + * Disable I2C hardware. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * + ****************************************************************************/ + +static void esp_i2c_deinit(struct esp_i2c_priv_s *priv) +{ + const struct esp_i2c_config_s *config = priv->config; + + priv->clk_freq = 0; + i2c_hal_deinit(priv->ctx); + periph_module_disable(i2c_periph_signal[priv->id].module); +} + +/**************************************************************************** + * Name: esp_i2c_reset_fsmc + * + * Description: + * Reset I2C hardware state machine and registers. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * + ****************************************************************************/ + +static void esp_i2c_reset_fsmc(struct esp_i2c_priv_s *priv) +{ + /* Reset FSM machine */ + + i2c_hal_master_fsm_rst(priv->ctx); +} + +/**************************************************************************** + * Name: esp_i2c_sem_waitdone + * + * Description: + * Wait for a transfer to complete. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ +#ifndef CONFIG_I2C_POLLED +static int esp_i2c_sem_waitdone(struct esp_i2c_priv_s *priv) +{ + return nxsem_tickwait_uninterruptible(&priv->sem_isr, + ESPRESSIF_I2CTIMEOTICKS); +} +#endif + +/**************************************************************************** + * Name: esp_i2c_polling_waitdone + * + * Description: + * Wait for a transfer to complete by polling status interrupt registers, + * which indicates the status of the I2C operations. This function is only + * used in polling driven mode. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * + * Returned Values: + * Zero (OK) is returned on successfull transfer. -ETIMEDOUT is returned + * in case a transfer didn't finish within the timeout interval. And ERROR + * is returned in case of any I2C error during the transfer has happened. + * + ****************************************************************************/ +#ifdef CONFIG_I2C_POLLED +static int esp_i2c_polling_waitdone(struct esp_i2c_priv_s *priv) +{ + int ret; + clock_t current; + clock_t timeout; + uint32_t status = 0; + i2c_intr_event_t event = 0; + + /* Get the current absolute time and add an offset as timeout. + * Preferable to use monotonic, so in case the time changes, + * the time reference is kept, i.e., current time can't jump + * forward and backwards. + */ + + current = clock_systime_ticks(); + timeout = current + SEC2TICK(10); + + /* Loop while a transfer is in progress + * and an error didn't occur within the timeout + */ + + while ((sclock_t)(current - timeout) < 0 && (priv->error == 0)) + { + /* Check if any interrupt triggered, clear them + * process the operation. + */ + + i2c_ll_get_intr_mask(priv->ctx->dev, &status); + if (status != 0) + { + i2c_ll_master_get_event(priv->ctx->dev, &event); + /* Check if the stop operation ended. Don't use + * I2CSTATE_FINISH, because it is set before the stop + * signal really ends. This works for interrupts because + * the i2c_state is checked in the next interrupt when + * stop signal has concluded. This is not the case of + * polling. + */ + + if (event == I2C_INTR_EVENT_TRANS_DONE) + { + i2c_ll_clear_intr_mask(priv->ctx->dev, status); + break; + } + + i2c_ll_clear_intr_mask(priv->ctx->dev, status); + esp_i2c_process(priv, status); + } + + /* Update current time */ + + current = clock_systime_ticks(); + } + + /* Return a negated value in case of timeout, and in the other scenarios + * return a positive value. + * The transfer function will check the status of priv to check the other + * scenarios. + */ + + if (current >= timeout) + { + ret = -ETIMEDOUT; + } + else if (priv->error) + { + ret = ERROR; + } + else + { + ret = OK; + } + + /* Disable all interrupts */ + + esp_i2c_intr_disable(priv); + + return ret; +} +#endif + +/**************************************************************************** + * Device Driver Operations + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_i2c_transfer + * + * Description: + * Generic I2C transfer function. + * + * Parameters: + * dev - Device-specific state data + * msgs - A pointer to a set of message descriptors + * count - The number of transfers to perform + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +static int esp_i2c_transfer(struct i2c_master_s *dev, + struct i2c_msg_s *msgs, + int count) +{ + int ret = OK; + struct esp_i2c_priv_s *priv = (struct esp_i2c_priv_s *)dev; +#ifdef CONFIG_I2C_TRACE + uint32_t status = 0; +#endif + + i2cinfo("Starting transfer request of %d message(s):\n", count); + + DEBUGASSERT(count > 0); + + ret = nxmutex_lock(&priv->lock); + if (ret < 0) + { + return ret; + } + + if (priv->i2cstate != I2CSTATE_IDLE) + { + esp_i2c_reset_fsmc(priv); + priv->i2cstate = I2CSTATE_IDLE; + } + + priv->msgv = msgs; + + for (int i = 0; i < count; i++) + { + esp_i2c_reset_fifo(priv); + + priv->bytes = 0; + priv->msgid = i; + priv->ready_read = false; + priv->error = 0; + priv->i2cstate = I2CSTATE_PROC; + + i2cinfo("Sending message %" PRIu8 "...\n", priv->msgid); + + esp_i2c_init_clock(priv, msgs[i].frequency); +#ifdef CONFIG_I2C_TRACE + status = GET_STATUS(priv->ctx->dev); +#endif +#ifndef CONFIG_I2C_POLLED + if ((msgs[i].flags & I2C_M_NOSTART) != 0) + { + esp_i2c_traceevent(priv, I2CEVENT_SENDBYTE, priv->bytes, status); + esp_i2c_senddata(priv); + + if (priv->bytes == msgs[i].length) + { + priv->i2cstate = I2CSTATE_STOP; + if ((msgs[i].flags & I2C_M_NOSTOP) != 0) + { + priv->i2cstate = I2CSTATE_FINISH; + } + } + } + else +#endif + { + /* Reset I2C trace logic */ + + esp_i2c_tracereset(priv); + + esp_i2c_traceevent(priv, I2CEVENT_SENDADDR, msgs[i].addr, status); + + esp_i2c_sendstart(priv); + } + +#ifndef CONFIG_I2C_POLLED + if (esp_i2c_sem_waitdone(priv) < 0) + { + i2cerr("Message %" PRIu8 " timed out.\n", priv->msgid); + ret = -ETIMEDOUT; + break; + } + else + { + if (priv->error != 0) + { + i2cerr("Transfer error %" PRIu32 "\n", priv->error); + ret = -EIO; + break; + } + else + { + priv->i2cstate = I2CSTATE_IDLE; + ret = OK; + } + } +#else + ret = esp_i2c_polling_waitdone(priv); + if (ret < 0) + { + if (ret == -ETIMEDOUT) + { + break; + } + else + { + ret = -EIO; + break; + } + } + else + { + /* Successful transfer, update the I2C state to idle */ + + priv->i2cstate = I2CSTATE_IDLE; + ret = OK; + } +#endif + + i2cinfo("Message %" PRIu8 " transfer complete.\n", priv->msgid); + } + + /* Dump the trace result */ + + esp_i2c_tracedump(priv); + nxmutex_unlock(&priv->lock); + + return ret; +} + +/**************************************************************************** + * Name: esp_i2c_clear_bus + * + * Description: + * Clear I2C bus, when the slave is stuck in a deadlock and keeps pulling + * the bus low, master can control the SCL bus to generate 9 CLKs. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * + ****************************************************************************/ + +#ifdef CONFIG_I2C_RESET +static void esp_i2c_clear_bus(struct esp_i2c_priv_s *priv) +{ + i2c_ll_master_clr_bus(priv->ctx->dev); +} +#endif + +/**************************************************************************** + * Name: esp_i2c_reset + * + * Description: + * Perform an I2C bus reset in an attempt to break loose stuck I2C devices. + * + * Parameters: + * dev - Device-specific state data + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ + +#ifdef CONFIG_I2C_RESET +static int esp_i2c_reset(struct i2c_master_s *dev) +{ + irqstate_t flags; + struct esp_i2c_priv_s *priv = (struct esp_i2c_priv_s *)dev; + + DEBUGASSERT(dev); + + DEBUGASSERT(priv->refs > 0); + + flags = enter_critical_section(); + + esp_i2c_reset_fsmc(priv); + + /* Clear bus */ + + esp_i2c_clear_bus(priv); + + priv->i2cstate = I2CSTATE_IDLE; + priv->msgid = 0; + priv->bytes = 0; + priv->ready_read = false; + + leave_critical_section(flags); + + return OK; +} +#endif + +/**************************************************************************** + * Name: esp_i2c_traceclear + * + * Description: + * Set I2C trace fields to default value. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * + ****************************************************************************/ + +#ifdef CONFIG_I2C_TRACE +static void esp_i2c_traceclear(struct esp_i2c_priv_s *priv) +{ + struct esp_trace_s *trace = &priv->trace[priv->tndx]; + + trace->status = 0; + trace->count = 0; + trace->event = I2CEVENT_NONE; + trace->parm = 0; + trace->time = 0; +} +#endif /* CONFIG_I2C_TRACE */ + +/**************************************************************************** + * Name: esp_i2c_tracereset + * + * Description: + * Reset the trace info for a new data collection. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * + ****************************************************************************/ + +#ifdef CONFIG_I2C_TRACE +static void esp_i2c_tracereset(struct esp_i2c_priv_s *priv) +{ + priv->tndx = 0; + priv->start_time = clock_systime_ticks(); + esp_i2c_traceclear(priv); +} +#endif /* CONFIG_I2C_TRACE */ + +/**************************************************************************** + * Name: esp_i2c_tracenew + * + * Description: + * Create a new trace entry. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * status - Current value of I2C status register. + * + ****************************************************************************/ + +#ifdef CONFIG_I2C_TRACE +static void esp_i2c_tracenew(struct esp_i2c_priv_s *priv, + uint32_t status) +{ + struct esp_trace_s *trace = &priv->trace[priv->tndx]; + + /* Check if the current entry is already initialized or if its status had + * already changed + */ + + if (trace->count == 0 || status != trace->status) + { + /* Check whether the status changed */ + + if (trace->count != 0) + { + /* Bump up the trace index (unless we are out of trace entries) */ + + if (priv->tndx >= (CONFIG_I2C_NTRACE - 1)) + { + i2cerr("ERROR: Trace table overflow\n"); + return; + } + + priv->tndx++; + trace = &priv->trace[priv->tndx]; + } + + /* Initialize the new trace entry */ + + esp_i2c_traceclear(priv); + trace->status = status; + trace->count = 1; + trace->time = clock_systime_ticks(); + } + else + { + /* Just increment the count of times that we have seen this status */ + + trace->count++; + } +} +#endif /* CONFIG_I2C_TRACE */ + +/**************************************************************************** + * Name: esp_i2c_traceevent + * + * Description: + * Record a new trace event. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * event - Event to be recorded on the trace. + * parm - Parameter associated with the event. + * status - Current value of I2C status register. + * + ****************************************************************************/ + +#ifdef CONFIG_I2C_TRACE +static void esp_i2c_traceevent(struct esp_i2c_priv_s *priv, + enum esp_trace_e event, + uint32_t parm, + uint32_t status) +{ + /* Check for new trace setup */ + + esp_i2c_tracenew(priv, status); + + if (event != I2CEVENT_NONE) + { + struct esp_trace_s *trace = &priv->trace[priv->tndx]; + + /* Initialize the new trace entry */ + + trace->event = event; + trace->parm = parm; + + /* Bump up the trace index (unless we are out of trace entries) */ + + if (priv->tndx >= (CONFIG_I2C_NTRACE - 1)) + { + i2cerr("ERROR: Trace table overflow\n"); + return; + } + + priv->tndx++; + esp_i2c_traceclear(priv); + } +} +#endif /* CONFIG_I2C_TRACE */ + +/**************************************************************************** + * Name: esp_i2c_tracedump + * + * Description: + * Dump the trace results. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * + ****************************************************************************/ + +#ifdef CONFIG_I2C_TRACE +static void esp_i2c_tracedump(struct esp_i2c_priv_s *priv) +{ + struct esp_trace_s *trace; + int i; + + syslog(LOG_DEBUG, "Elapsed time: %" PRIu32 "\n", + (clock_systime_ticks() - priv->start_time)); + + for (i = 0; i < priv->tndx; i++) + { + trace = &priv->trace[i]; + syslog(LOG_DEBUG, + "%2d. STATUS: %08" PRIx32 " COUNT: %3" PRIu32 " EVENT: %s(%2d)" + " PARM: %08" PRIx32 " TIME: %" PRIu32 "\n", + i + 1, trace->status, trace->count, g_trace_names[trace->event], + trace->event, trace->parm, trace->time - priv->start_time); + } +} +#endif /* CONFIG_I2C_TRACE */ + +/**************************************************************************** + * Name: esp_i2c_irq + * + * Description: + * This is the common I2C interrupt handler. It will be invoked when an + * interrupt is received on the device. + * + * Parameters: + * cpuint - CPU interrupt index + * context - Context data from the ISR + * arg - Opaque pointer to the internal driver state structure. + * + * Returned Value: + * Zero (OK) is returned on success. A negated errno value is returned on + * failure. + * + ****************************************************************************/ +#ifndef CONFIG_I2C_POLLED +static int esp_i2c_irq(int cpuint, void *context, void *arg) +{ + struct esp_i2c_priv_s *priv = (struct esp_i2c_priv_s *)arg; + uint32_t irq_status = 0; + + i2c_ll_get_intr_mask(priv->ctx->dev, &irq_status); + i2c_ll_clear_intr_mask(priv->ctx->dev, irq_status); + esp_i2c_process(priv , irq_status); + return OK; +} +#endif + +/**************************************************************************** + * Name: esp_i2c_process + * + * Description: + * This routine manages the transfer. It's called after some specific + * commands from the I2C controller are executed or in case of errors. + * It's responsible for writing/reading operations and transferring data + * from/to FIFO. + * It's called in the interrupt and polled driven mode. + * + * Parameters: + * priv - Pointer to the internal driver state structure. + * status - The current interrupt status register. + * + ****************************************************************************/ + +static inline void esp_i2c_process(struct esp_i2c_priv_s *priv, + uint32_t irq_status) +{ + struct i2c_msg_s *msg = &priv->msgv[priv->msgid]; +#ifdef CONFIG_I2C_TRACE + uint32_t status = 0; + status = GET_STATUS(priv->ctx->dev); +#endif + /* Check for any errors */ + + if (I2C_INT_ERR_MASK & irq_status) + { + priv->error = irq_status & I2C_INT_ERR_MASK; + priv->i2cstate = I2CSTATE_ERROR; + esp_i2c_traceevent(priv, I2CEVENT_ERROR, priv->error, status); + esp_i2c_intr_disable(priv); +#ifndef CONFIG_I2C_POLLED + nxsem_post(&priv->sem_isr); +#endif + } + else + { + if (priv->i2cstate == I2CSTATE_PROC) + { + if (msg->flags & I2C_M_READ) + { + if (priv->ready_read) + { + esp_i2c_traceevent(priv, I2CEVENT_RCVBYTE, priv->bytes, + status); + esp_i2c_recvdata(priv); + + priv->ready_read = false; + } + + if (priv->bytes == msg->length) + { + esp_i2c_traceevent(priv, I2CEVENT_STOP, msg->length, + status); + esp_i2c_sendstop(priv); +#ifndef CONFIG_I2C_POLLED + priv->i2cstate = I2CSTATE_FINISH; +#endif + } + else + { + esp_i2c_traceevent(priv, I2CEVENT_RCVMODEEN, 0, + status); + esp_i2c_startrecv(priv); + + priv->ready_read = true; + } + } + else + { + esp_i2c_traceevent(priv, I2CEVENT_SENDBYTE, priv->bytes, + status); + esp_i2c_senddata(priv); + + if (priv->bytes == msg->length) + { + priv->i2cstate = I2CSTATE_STOP; +#ifndef CONFIG_I2C_POLLED + if ((msg->flags & I2C_M_NOSTOP) != 0) + { + priv->i2cstate = I2CSTATE_FINISH; + } +#endif + } + } + } + else if (priv->i2cstate == I2CSTATE_STOP) + { + esp_i2c_traceevent(priv, I2CEVENT_STOP, msg->length, + status); + esp_i2c_sendstop(priv); + +#ifndef CONFIG_I2C_POLLED + priv->i2cstate = I2CSTATE_FINISH; +#endif + } +#ifndef CONFIG_I2C_POLLED + else if (priv->i2cstate == I2CSTATE_FINISH) + { + esp_i2c_intr_disable(priv); + nxsem_post(&priv->sem_isr); + } +#endif + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_i2cbus_initialize + * + * Description: + * Initialize the selected I2C port. And return a pointer to an unique + * instance of struct i2c_master_s. This function may be called to obtain + * multiple instances of the interface, each of which may be set up with a + * different frequency and slave address. + * + * Parameters: + * port - Port number of the I2C interface to be initialized. + * + * Returned Value: + * Pointer to valid I2C device structure is returned on success. + * A NULL pointer is returned on failure. + * + ****************************************************************************/ + +struct i2c_master_s *esp_i2cbus_initialize(int port) +{ + struct esp_i2c_priv_s *priv; +#ifndef CONFIG_I2C_POLLED + const struct esp_i2c_config_s *config; + int ret; +#endif + + switch (port) + { +#ifdef CONFIG_ESPRESSIF_I2C0 + case ESPRESSIF_I2C0: + priv = &esp_i2c0_priv; + break; +#endif +#ifdef CONFIG_ESPRESSIF_I2C1 + case ESPRESSIF_I2C1: + priv = &esp_i2c1_priv; + break; +#endif + default: + return NULL; + } + + nxmutex_lock(&priv->lock); + + if (priv->refs++ != 0) + { + nxmutex_unlock(&priv->lock); + + i2cinfo("Returning previously initialized I2C bus. " + "Handler: %p\n", priv); + + return (struct i2c_master_s *)priv; + } + +#ifndef CONFIG_I2C_POLLED + config = priv->config; + if (priv->cpuint != -ENOMEM) + { + /* Disable the previous IRQ */ + + up_disable_irq(config->irq); + esp_teardown_irq(config->periph, priv->cpuint); + } + + priv->cpuint = esp_setup_irq(config->periph, + ESP_IRQ_PRIORITY_DEFAULT, + ESP_IRQ_TRIGGER_LEVEL); + if (priv->cpuint < 0) + { + /* Failed to allocate a CPU interrupt of this type. */ + + priv->refs--; + nxmutex_unlock(&priv->lock); + + return NULL; + } + + ret = irq_attach(config->irq, esp_i2c_irq, priv); + if (ret != OK) + { + /* Failed to attach IRQ, free the allocated CPU interrupt */ + + esp_teardown_irq(config->periph, priv->cpuint); + priv->cpuint = -ENOMEM; + priv->refs--; + nxmutex_unlock(&priv->lock); + + return NULL; + } + + /* Enable the CPU interrupt that is linked to the I2C device. */ + + up_enable_irq(config->irq); +#endif + + esp_i2c_init(priv); + nxmutex_unlock(&priv->lock); + + i2cinfo("I2C bus initialized! Handler: %p\n", priv); + + return (struct i2c_master_s *)priv; +} + +/**************************************************************************** + * Name: esp_i2cbus_uninitialize + * + * Description: + * De-initialize the selected I2C port and power down the device. + * + * Parameters: + * dev - Device structure as returned by + * esp_i2cbus_initialize() + * + * Returned Value: + * OK is returned on success. ERROR is returned when internal reference + * count mismatches or dev points to invalid hardware device. + * + ****************************************************************************/ + +int esp_i2cbus_uninitialize(struct i2c_master_s *dev) +{ + struct esp_i2c_priv_s *priv = (struct esp_i2c_priv_s *)dev; + + DEBUGASSERT(dev); + + if (priv->refs == 0) + { + return ERROR; + } + + nxmutex_lock(&priv->lock); + if (--priv->refs) + { + nxmutex_unlock(&priv->lock); + return OK; + } + +#ifndef CONFIG_I2C_POLLED + up_disable_irq(priv->config->irq); + esp_teardown_irq(priv->config->periph, priv->cpuint); + priv->cpuint = -ENOMEM; +#endif + + esp_i2c_deinit(priv); + nxmutex_unlock(&priv->lock); + + return OK; +} + +#endif /* CONFIG_ESPRESSIF_I2C */ diff --git a/arch/risc-v/src/common/espressif/esp_i2c.h b/arch/risc-v/src/common/espressif/esp_i2c.h new file mode 100644 index 0000000000..8a51a2ee85 --- /dev/null +++ b/arch/risc-v/src/common/espressif/esp_i2c.h @@ -0,0 +1,91 @@ +/**************************************************************************** + * arch/risc-v/src/common/espressif/esp_i2c.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_RISCV_SRC_COMMON_ESPRESSIF_ESP_I2C_H +#define __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_I2C_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#ifdef CONFIG_ESPRESSIF_I2C0 +# define ESPRESSIF_I2C0 0 +#endif + +#ifdef CONFIG_ESPRESSIF_I2C1 +# define ESPRESSIF_I2C1 1 +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: esp_i2cbus_initialize + * + * Description: + * Initialize the selected I2C port. And return a unique instance of struct + * struct i2c_master_s. This function may be called to obtain multiple + * instances of the interface, each of which may be set up with a + * different frequency and slave address. + * + * Input Parameters: + * port - Port number (for hardware that has multiple I2C interfaces) + * + * Returned Value: + * Valid I2C device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +struct i2c_master_s *esp_i2cbus_initialize(int port); + +/**************************************************************************** + * Name: esp_i2cbus_uninitialize + * + * Description: + * De-initialize the selected I2C port, and power down the device. + * + * Input Parameters: + * dev - Device structure as returned by the esp_i2cbus_initialize() + * + * Returned Value: + * OK on success, ERROR when internal reference count mismatch or dev + * points to invalid hardware device. + * + ****************************************************************************/ + +int esp_i2cbus_uninitialize(struct i2c_master_s *dev); + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_RISCV_SRC_COMMON_ESPRESSIF_ESP_I2C_H */ diff --git a/arch/risc-v/src/esp32c3/hal_esp32c3.mk b/arch/risc-v/src/esp32c3/hal_esp32c3.mk index e12dc422ac..44c688bcce 100644 --- a/arch/risc-v/src/esp32c3/hal_esp32c3.mk +++ b/arch/risc-v/src/esp32c3/hal_esp32c3.mk @@ -125,6 +125,7 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)mpu_hal.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)mmu_hal.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)rmt_hal.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)i2c_hal.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)spi_hal.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)spi_hal_iram.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)twai_hal.c @@ -144,6 +145,7 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)gpio_periph.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)ledc_periph.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)rmt_periph.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)i2c_periph.c ifeq ($(CONFIG_ESPRESSIF_SIMPLE_BOOT),y) CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)bootloader_banner_wrap.c diff --git a/arch/risc-v/src/esp32c6/hal_esp32c6.mk b/arch/risc-v/src/esp32c6/hal_esp32c6.mk index 0ff90470b3..6c8787704b 100644 --- a/arch/risc-v/src/esp32c6/hal_esp32c6.mk +++ b/arch/risc-v/src/esp32c6/hal_esp32c6.mk @@ -125,6 +125,7 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)ledc_hal_iram.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)lp_timer_hal.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)rmt_hal.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)i2c_hal.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)spi_hal.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)spi_hal_iram.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)timer_hal.c @@ -149,6 +150,7 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)gpio_periph.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)ledc_periph.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)rmt_periph.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)i2c_periph.c ifeq ($(CONFIG_ESPRESSIF_SIMPLE_BOOT),y) CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)bootloader_banner_wrap.c diff --git a/arch/risc-v/src/esp32h2/hal_esp32h2.mk b/arch/risc-v/src/esp32h2/hal_esp32h2.mk index f9fb63a08a..b2ce97af2b 100644 --- a/arch/risc-v/src/esp32h2/hal_esp32h2.mk +++ b/arch/risc-v/src/esp32h2/hal_esp32h2.mk @@ -111,6 +111,7 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)ledc_hal_iram.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)lp_timer_hal.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)rmt_hal.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)i2c_hal.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)spi_hal.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)spi_hal_iram.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)hal$(DELIM)timer_hal.c @@ -132,6 +133,7 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)gpio_periph.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)ledc_periph.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)rmt_periph.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)i2c_periph.c ifeq ($(CONFIG_ESPRESSIF_SIMPLE_BOOT),y) CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)bootloader_banner_wrap.c diff --git a/boards/risc-v/esp32c3/common/include/esp_board_i2c.h b/boards/risc-v/esp32c3/common/include/esp_board_i2c.h new file mode 100644 index 0000000000..0b6b032231 --- /dev/null +++ b/boards/risc-v/esp32c3/common/include/esp_board_i2c.h @@ -0,0 +1,74 @@ +/**************************************************************************** + * boards/risc-v/esp32c3/common/include/esp_board_i2c.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. + * + ****************************************************************************/ + +#ifndef __BOARDS_RISCV_ESP32C3_COMMON_INCLUDE_ESP_BOARD_I2C_H +#define __BOARDS_RISCV_ESP32C3_COMMON_INCLUDE_ESP_BOARD_I2C_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: board_i2c_init + * + * Description: + * Configure the I2C driver. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_I2C_DRIVER +int board_i2c_init(void); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_RISCV_ESP32C3_COMMON_INCLUDE_ESP_BOARD_I2C_H */ diff --git a/boards/risc-v/esp32c3/common/src/Make.defs b/boards/risc-v/esp32c3/common/src/Make.defs index bf7869e3b8..62737b91f6 100644 --- a/boards/risc-v/esp32c3/common/src/Make.defs +++ b/boards/risc-v/esp32c3/common/src/Make.defs @@ -40,6 +40,10 @@ ifeq ($(CONFIG_SPI_SLAVE_DRIVER),y) CSRCS += esp_board_spislavedev.c endif +ifeq ($(CONFIG_I2C_DRIVER),y) + CSRCS += esp_board_i2c.c +endif + ifeq ($(CONFIG_ESPRESSIF_SPIFLASH),y) CSRCS += esp_board_spiflash.c endif diff --git a/boards/risc-v/esp32c3/common/src/esp_board_i2c.c b/boards/risc-v/esp32c3/common/src/esp_board_i2c.c new file mode 100644 index 0000000000..04ade5e6f9 --- /dev/null +++ b/boards/risc-v/esp32c3/common/src/esp_board_i2c.c @@ -0,0 +1,82 @@ +/**************************************************************************** + * boards/risc-v/esp32c3/common/src/esp_board_i2c.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 + +#include +#include +#include + +#include + +#include "espressif/esp_i2c.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +static int i2c_driver_init(int bus) +{ + struct i2c_master_s *i2c; + int ret; + + i2c = esp_i2cbus_initialize(bus); + if (i2c == NULL) + { + i2cerr("Failed to get I2C%d interface\n", bus); + return -ENODEV; + } + + ret = i2c_register(i2c, bus); + if (ret < 0) + { + i2cerr("Failed to register I2C%d driver: %d\n", bus, ret); + esp_i2cbus_uninitialize(i2c); + } + + return ret; +} + +/**************************************************************************** + * Name: board_i2c_init + * + * Description: + * Configure the I2C driver. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int board_i2c_init(void) +{ + int ret = OK; + +#ifdef CONFIG_ESPRESSIF_I2C0 + ret = i2c_driver_init(ESPRESSIF_I2C0); +#endif + + return ret; +} diff --git a/boards/risc-v/esp32c3/esp32c3-generic/configs/i2c/defconfig b/boards/risc-v/esp32c3/esp32c3-generic/configs/i2c/defconfig new file mode 100644 index 0000000000..078b54642e --- /dev/null +++ b/boards/risc-v/esp32c3/esp32c3-generic/configs/i2c/defconfig @@ -0,0 +1,52 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="esp32c3-generic" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32C3_GENERIC=y +CONFIG_ARCH_CHIP="esp32c3" +CONFIG_ARCH_CHIP_ESP32C3_GENERIC=y +CONFIG_ARCH_INTERRUPTSTACK=1536 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=15000 +CONFIG_BUILTIN=y +CONFIG_DEV_ZERO=y +CONFIG_ESPRESSIF_I2C0=y +CONFIG_FS_PROCFS=y +CONFIG_I2CTOOL_DEFFREQ=100000 +CONFIG_I2CTOOL_MAXBUS=1 +CONFIG_I2C_RESET=y +CONFIG_I2C_TRACE=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=0 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=29 +CONFIG_START_MONTH=11 +CONFIG_START_YEAR=2019 +CONFIG_SYSTEM_DUMPSTACK=y +CONFIG_SYSTEM_I2CTOOL=y +CONFIG_SYSTEM_NSH=y +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_UART0_SERIAL_CONSOLE=y diff --git a/boards/risc-v/esp32c3/esp32c3-generic/src/esp32c3_bringup.c b/boards/risc-v/esp32c3/esp32c3-generic/src/esp32c3_bringup.c index 41151e4a01..5e640632b2 100644 --- a/boards/risc-v/esp32c3/esp32c3-generic/src/esp32c3_bringup.c +++ b/boards/risc-v/esp32c3/esp32c3-generic/src/esp32c3_bringup.c @@ -36,6 +36,7 @@ #include "esp_board_ledc.h" #include "esp_board_spiflash.h" +#include "esp_board_i2c.h" #ifdef CONFIG_WATCHDOG # include "espressif/esp_wdt.h" @@ -257,6 +258,17 @@ int esp_bringup(void) } #endif +#if defined(CONFIG_I2C_DRIVER) + /* Configure I2C peripheral interfaces */ + + ret = board_i2c_init(); + + if (ret < 0) + { + syslog(LOG_ERR, "Failed to initialize I2C driver: %d\n", ret); + } +#endif + #ifdef CONFIG_ESPRESSIF_TWAI /* Initialize TWAI and register the TWAI driver. */ diff --git a/boards/risc-v/esp32c6/common/include/esp_board_i2c.h b/boards/risc-v/esp32c6/common/include/esp_board_i2c.h new file mode 100644 index 0000000000..0670875d14 --- /dev/null +++ b/boards/risc-v/esp32c6/common/include/esp_board_i2c.h @@ -0,0 +1,74 @@ +/**************************************************************************** + * boards/risc-v/esp32c6/common/include/esp_board_i2c.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. + * + ****************************************************************************/ + +#ifndef __BOARDS_RISCV_ESP32C6_COMMON_INCLUDE_ESP_BOARD_I2C_H +#define __BOARDS_RISCV_ESP32C3_COMMON_INCLUDE_ESP_BOARD_I2C_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: board_i2c_init + * + * Description: + * Configure the I2C driver. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_I2C_DRIVER +int board_i2c_init(void); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_RISCV_ESP32C6_COMMON_INCLUDE_ESP_BOARD_I2C_H */ diff --git a/boards/risc-v/esp32c6/common/src/Make.defs b/boards/risc-v/esp32c6/common/src/Make.defs index 177181975b..f628334a0c 100644 --- a/boards/risc-v/esp32c6/common/src/Make.defs +++ b/boards/risc-v/esp32c6/common/src/Make.defs @@ -40,6 +40,10 @@ ifeq ($(CONFIG_SPI_SLAVE_DRIVER),y) CSRCS += esp_board_spislavedev.c endif +ifeq ($(CONFIG_I2C_DRIVER),y) + CSRCS += esp_board_i2c.c +endif + ifeq ($(CONFIG_ESPRESSIF_SPIFLASH),y) CSRCS += esp_board_spiflash.c endif diff --git a/boards/risc-v/esp32c6/common/src/esp_board_i2c.c b/boards/risc-v/esp32c6/common/src/esp_board_i2c.c new file mode 100644 index 0000000000..094f742b8e --- /dev/null +++ b/boards/risc-v/esp32c6/common/src/esp_board_i2c.c @@ -0,0 +1,82 @@ +/**************************************************************************** + * boards/risc-v/esp32c6/common/src/esp_board_i2c.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 + +#include +#include +#include + +#include + +#include "espressif/esp_i2c.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +static int i2c_driver_init(int bus) +{ + struct i2c_master_s *i2c; + int ret; + + i2c = esp_i2cbus_initialize(bus); + if (i2c == NULL) + { + i2cerr("Failed to get I2C%d interface\n", bus); + return -ENODEV; + } + + ret = i2c_register(i2c, bus); + if (ret < 0) + { + i2cerr("Failed to register I2C%d driver: %d\n", bus, ret); + esp_i2cbus_uninitialize(i2c); + } + + return ret; +} + +/**************************************************************************** + * Name: board_i2c_init + * + * Description: + * Configure the I2C driver. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int board_i2c_init(void) +{ + int ret = OK; + +#ifdef CONFIG_ESPRESSIF_I2C0 + ret = i2c_driver_init(ESPRESSIF_I2C0); +#endif + + return ret; +} diff --git a/boards/risc-v/esp32c6/esp32c6-devkitc/configs/i2c/defconfig b/boards/risc-v/esp32c6/esp32c6-devkitc/configs/i2c/defconfig new file mode 100644 index 0000000000..d1d258708f --- /dev/null +++ b/boards/risc-v/esp32c6/esp32c6-devkitc/configs/i2c/defconfig @@ -0,0 +1,54 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="esp32c6-devkitc" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32C6_DEVKITC=y +CONFIG_ARCH_CHIP="esp32c6" +CONFIG_ARCH_CHIP_ESP32C6=y +CONFIG_ARCH_CHIP_ESP32C6WROOM1=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=15000 +CONFIG_BUILTIN=y +CONFIG_DEV_ZERO=y +CONFIG_ESPRESSIF_ESP32C6=y +CONFIG_ESPRESSIF_I2C0=y +CONFIG_FS_PROCFS=y +CONFIG_I2CTOOL_DEFFREQ=100000 +CONFIG_I2CTOOL_MAXBUS=1 +CONFIG_I2C_RESET=y +CONFIG_I2C_TRACE=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=0 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=29 +CONFIG_START_MONTH=11 +CONFIG_START_YEAR=2019 +CONFIG_SYSTEM_DUMPSTACK=y +CONFIG_SYSTEM_I2CTOOL=y +CONFIG_SYSTEM_NSH=y +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_UART0_SERIAL_CONSOLE=y diff --git a/boards/risc-v/esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c b/boards/risc-v/esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c index d2af1a6352..a101882620 100644 --- a/boards/risc-v/esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c +++ b/boards/risc-v/esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c @@ -36,6 +36,7 @@ #include "esp_board_ledc.h" #include "esp_board_spiflash.h" +#include "esp_board_i2c.h" #ifdef CONFIG_WATCHDOG # include "espressif/esp_wdt.h" @@ -226,6 +227,17 @@ int esp_bringup(void) } #endif +#if defined(CONFIG_I2C_DRIVER) + /* Configure I2C peripheral interfaces */ + + ret = board_i2c_init(); + + if (ret < 0) + { + syslog(LOG_ERR, "Failed to initialize I2C driver: %d\n", ret); + } +#endif + #ifdef CONFIG_ESPRESSIF_TWAI0 /* Initialize TWAI and register the TWAI driver. */ diff --git a/boards/risc-v/esp32c6/esp32c6-devkitm/configs/i2c/defconfig b/boards/risc-v/esp32c6/esp32c6-devkitm/configs/i2c/defconfig new file mode 100644 index 0000000000..56903a9355 --- /dev/null +++ b/boards/risc-v/esp32c6/esp32c6-devkitm/configs/i2c/defconfig @@ -0,0 +1,54 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="esp32c6-devkitm" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32C6_DEVKITM=y +CONFIG_ARCH_CHIP="esp32c6" +CONFIG_ARCH_CHIP_ESP32C6=y +CONFIG_ARCH_CHIP_ESP32C6MINI1=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=15000 +CONFIG_BUILTIN=y +CONFIG_DEV_ZERO=y +CONFIG_ESPRESSIF_ESP32C6=y +CONFIG_ESPRESSIF_I2C0=y +CONFIG_FS_PROCFS=y +CONFIG_I2CTOOL_DEFFREQ=100000 +CONFIG_I2CTOOL_MAXBUS=1 +CONFIG_I2C_RESET=y +CONFIG_I2C_TRACE=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=0 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=29 +CONFIG_START_MONTH=11 +CONFIG_START_YEAR=2019 +CONFIG_SYSTEM_DUMPSTACK=y +CONFIG_SYSTEM_I2CTOOL=y +CONFIG_SYSTEM_NSH=y +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_UART0_SERIAL_CONSOLE=y diff --git a/boards/risc-v/esp32c6/esp32c6-devkitm/src/esp32c6_bringup.c b/boards/risc-v/esp32c6/esp32c6-devkitm/src/esp32c6_bringup.c index d4cf38dc98..d457895ef1 100644 --- a/boards/risc-v/esp32c6/esp32c6-devkitm/src/esp32c6_bringup.c +++ b/boards/risc-v/esp32c6/esp32c6-devkitm/src/esp32c6_bringup.c @@ -36,6 +36,7 @@ #include "esp_board_ledc.h" #include "esp_board_spiflash.h" +#include "esp_board_i2c.h" #ifdef CONFIG_WATCHDOG # include "espressif/esp_wdt.h" @@ -226,6 +227,17 @@ int esp_bringup(void) } #endif +#if defined(CONFIG_I2C_DRIVER) + /* Configure I2C peripheral interfaces */ + + ret = board_i2c_init(); + + if (ret < 0) + { + syslog(LOG_ERR, "Failed to initialize I2C driver: %d\n", ret); + } +#endif + #ifdef CONFIG_ESPRESSIF_TWAI0 /* Initialize TWAI and register the TWAI driver. */ diff --git a/boards/risc-v/esp32h2/common/include/esp_board_i2c.h b/boards/risc-v/esp32h2/common/include/esp_board_i2c.h new file mode 100644 index 0000000000..d478a4b640 --- /dev/null +++ b/boards/risc-v/esp32h2/common/include/esp_board_i2c.h @@ -0,0 +1,74 @@ +/**************************************************************************** + * boards/risc-v/esp32h2/common/include/esp_board_i2c.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. + * + ****************************************************************************/ + +#ifndef __BOARDS_RISCV_ESP32H2_COMMON_INCLUDE_ESP_BOARD_I2C_H +#define __BOARDS_RISCV_ESP32H2_COMMON_INCLUDE_ESP_BOARD_I2C_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: board_i2c_init + * + * Description: + * Configure the I2C driver. + * + * Input Parameters: + * None. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_I2C_DRIVER +int board_i2c_init(void); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __BOARDS_RISCV_ESP32H2_COMMON_INCLUDE_ESP_BOARD_I2C_H */ diff --git a/boards/risc-v/esp32h2/common/src/Make.defs b/boards/risc-v/esp32h2/common/src/Make.defs index 66daeb3213..74bdae3f2f 100644 --- a/boards/risc-v/esp32h2/common/src/Make.defs +++ b/boards/risc-v/esp32h2/common/src/Make.defs @@ -40,6 +40,10 @@ ifeq ($(CONFIG_SPI_SLAVE_DRIVER),y) CSRCS += esp_board_spislavedev.c endif +ifeq ($(CONFIG_I2C_DRIVER),y) + CSRCS += esp_board_i2c.c +endif + ifeq ($(CONFIG_ESPRESSIF_SPIFLASH),y) CSRCS += esp_board_spiflash.c endif diff --git a/boards/risc-v/esp32h2/common/src/esp_board_i2c.c b/boards/risc-v/esp32h2/common/src/esp_board_i2c.c new file mode 100644 index 0000000000..76eda63a29 --- /dev/null +++ b/boards/risc-v/esp32h2/common/src/esp_board_i2c.c @@ -0,0 +1,90 @@ +/**************************************************************************** + * boards/risc-v/esp32h2/common/src/esp_board_i2c.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 + +#include +#include +#include + +#include + +#include "espressif/esp_i2c.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +static int i2c_driver_init(int bus) +{ + struct i2c_master_s *i2c; + int ret; + + i2c = esp_i2cbus_initialize(bus); + if (i2c == NULL) + { + i2cerr("Failed to get I2C%d interface\n", bus); + return -ENODEV; + } + + ret = i2c_register(i2c, bus); + if (ret < 0) + { + i2cerr("Failed to register I2C%d driver: %d\n", bus, ret); + esp_i2cbus_uninitialize(i2c); + } + + return ret; +} + +/**************************************************************************** + * Name: board_i2c_init + * + * Description: + * Configure the I2C driver. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int board_i2c_init(void) +{ + int ret = OK; + +#ifdef CONFIG_ESPRESSIF_I2C0 + ret = i2c_driver_init(ESPRESSIF_I2C0); + if (ret != OK) + { + return ret; + } +#endif + +#ifdef CONFIG_ESPRESSIF_I2C1 + ret = i2c_driver_init(ESPRESSIF_I2C1); +#endif + + return ret; +} diff --git a/boards/risc-v/esp32h2/esp32h2-devkit/configs/i2c/defconfig b/boards/risc-v/esp32h2/esp32h2-devkit/configs/i2c/defconfig new file mode 100644 index 0000000000..1ea79df2b0 --- /dev/null +++ b/boards/risc-v/esp32h2/esp32h2-devkit/configs/i2c/defconfig @@ -0,0 +1,54 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_NSH_ARGCAT is not set +# CONFIG_NSH_CMDOPT_HEXDUMP is not set +CONFIG_ARCH="risc-v" +CONFIG_ARCH_BOARD="esp32h2-devkit" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_ESP32H2_DEVKIT=y +CONFIG_ARCH_CHIP="esp32h2" +CONFIG_ARCH_CHIP_ESP32H2=y +CONFIG_ARCH_INTERRUPTSTACK=2048 +CONFIG_ARCH_RISCV=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARDCTL_RESET=y +CONFIG_BOARD_LOOPSPERMSEC=15000 +CONFIG_BUILTIN=y +CONFIG_DEV_ZERO=y +CONFIG_ESPRESSIF_ESP32H2=y +CONFIG_ESPRESSIF_I2C0=y +CONFIG_ESPRESSIF_I2C1=y +CONFIG_FS_PROCFS=y +CONFIG_I2CTOOL_DEFFREQ=100000 +CONFIG_I2CTOOL_MAXBUS=1 +CONFIG_I2C_RESET=y +CONFIG_I2C_TRACE=y +CONFIG_IDLETHREAD_STACKSIZE=2048 +CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBC_PERROR_STDOUT=y +CONFIG_LIBC_STRERROR=y +CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6 +CONFIG_NSH_ARCHINIT=y +CONFIG_NSH_BUILTIN_APPS=y +CONFIG_NSH_FILEIOSIZE=512 +CONFIG_NSH_READLINE=y +CONFIG_NSH_STRERROR=y +CONFIG_PREALLOC_TIMERS=0 +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_BACKTRACE=y +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=29 +CONFIG_START_MONTH=11 +CONFIG_START_YEAR=2019 +CONFIG_SYSTEM_DUMPSTACK=y +CONFIG_SYSTEM_I2CTOOL=y +CONFIG_SYSTEM_NSH=y +CONFIG_TESTING_GETPRIME=y +CONFIG_TESTING_OSTEST=y +CONFIG_UART0_SERIAL_CONSOLE=y diff --git a/boards/risc-v/esp32h2/esp32h2-devkit/src/esp32h2_bringup.c b/boards/risc-v/esp32h2/esp32h2-devkit/src/esp32h2_bringup.c index 8af13b13f3..19861b777d 100644 --- a/boards/risc-v/esp32h2/esp32h2-devkit/src/esp32h2_bringup.c +++ b/boards/risc-v/esp32h2/esp32h2-devkit/src/esp32h2_bringup.c @@ -36,6 +36,7 @@ #include "esp_board_ledc.h" #include "esp_board_spiflash.h" +#include "esp_board_i2c.h" #ifdef CONFIG_WATCHDOG # include "espressif/esp_wdt.h" @@ -218,6 +219,17 @@ int esp_bringup(void) } #endif +#if defined(CONFIG_I2C_DRIVER) + /* Configure I2C peripheral interfaces */ + + ret = board_i2c_init(); + + if (ret < 0) + { + syslog(LOG_ERR, "Failed to initialize I2C driver: %d\n", ret); + } +#endif + #ifdef CONFIG_ESPRESSIF_TWAI /* Initialize TWAI and register the TWAI driver. */