arch/xtensa/esp32[-s2|-s3]: Add RTC I2C support for HP Core for esp32[-s2|-s3]

Add RTC I2C support for HP Core for esp32[-s2|-s3]

Signed-off-by: Eren Terzioglu <eren.terzioglu@espressif.com>
This commit is contained in:
Eren Terzioglu
2025-09-16 16:23:04 +02:00
committed by Matteo Golin
parent 39b03d79f3
commit 09c298ed16
4 changed files with 209 additions and 13 deletions
+1 -1
View File
@@ -133,7 +133,7 @@ endif
ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty
ifndef ESP_HAL_3RDPARTY_VERSION
ESP_HAL_3RDPARTY_VERSION = 8e7f6a123659cb96f2240575b950748afc9b3dc0
ESP_HAL_3RDPARTY_VERSION = 6782de1b073f93a54c501edf23d99a42a23d41ac
endif
ifndef ESP_HAL_3RDPARTY_URL
+103 -5
View File
@@ -55,6 +55,7 @@
#include "hardware/esp32s2_i2c.h"
#include "hardware/esp32s2_soc.h"
#include "hardware/esp32s2_system.h"
#include "soc/interrupts.h"
#ifdef CONFIG_ESP32S2_RTC_I2C
# include "ulp_riscv.h"
@@ -265,6 +266,10 @@ static void i2c_init(struct esp32s2_i2c_priv_s *priv);
static void i2c_deinit(struct esp32s2_i2c_priv_s *priv);
static int i2c_transfer(struct i2c_master_s *dev, struct i2c_msg_s *msgs,
int count);
#ifdef CONFIG_ESP32S2_RTC_I2C
static int rtc_i2c_transfer(struct i2c_master_s *dev, struct i2c_msg_s *msgs,
int count);
#endif
static inline void i2c_process(struct esp32s2_i2c_priv_s *priv,
uint32_t status);
#ifndef CONFIG_I2C_POLLED
@@ -306,7 +311,7 @@ static const struct i2c_ops_s g_esp32s2_i2c_ops =
#ifdef CONFIG_ESP32S2_RTC_I2C
static const struct i2c_ops_s g_esp32s2_rtc_i2c_ops =
{
.transfer = NULL,
.transfer = rtc_i2c_transfer,
};
#endif
@@ -319,8 +324,8 @@ static const struct esp32s2_i2c_config_s g_esp32s2_i2c0_config =
.scl_pin = CONFIG_ESP32S2_I2C0_SCLPIN,
.sda_pin = CONFIG_ESP32S2_I2C0_SDAPIN,
#ifndef CONFIG_I2C_POLLED
.periph = ESP32S2_PERIPH_I2C_EXT0,
.irq = ESP32S2_IRQ_I2C_EXT0,
.periph = ETS_I2C_EXT0_INTR_SOURCE,
.irq = ESP32S2_PERIPH2IRQ(ETS_I2C_EXT0_INTR_SOURCE),
#endif
.clk_bit = SYSTEM_I2C_EXT0_CLK_EN,
.rst_bit = SYSTEM_I2C_EXT0_RST,
@@ -355,8 +360,8 @@ static const struct esp32s2_i2c_config_s g_esp32s2_i2c1_config =
.scl_pin = CONFIG_ESP32S2_I2C1_SCLPIN,
.sda_pin = CONFIG_ESP32S2_I2C1_SDAPIN,
#ifndef CONFIG_I2C_POLLED
.periph = ESP32S2_PERIPH_I2C_EXT1,
.irq = ESP32S2_IRQ_I2C_EXT1,
.periph = ETS_I2C_EXT1_INTR_SOURCE,
.irq = ESP32S2_PERIPH2IRQ(ETS_I2C_EXT1_INTR_SOURCE),
#endif
.clk_bit = SYSTEM_I2C_EXT1_CLK_EN,
.rst_bit = SYSTEM_I2C_EXT1_RST,
@@ -975,6 +980,99 @@ static int i2c_polling_waitdone(struct esp32s2_i2c_priv_s *priv)
* Device Driver Operations
****************************************************************************/
#ifdef CONFIG_ESP32S2_RTC_I2C
/****************************************************************************
* Name: rtc_i2c_transfer
*
* Description:
* I2C transfer function for RTC I2C.
*
* 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 rtc_i2c_transfer(struct i2c_master_s *dev, struct i2c_msg_s *msgs,
int count)
{
int ret = OK;
struct esp32s2_i2c_priv_s *priv = (struct esp32s2_i2c_priv_s *)dev;
DEBUGASSERT(count > 0);
ret = nxmutex_lock(&priv->lock);
if (ret < 0)
{
return ret;
}
/* If previous state is different than idle,
* reset the FSMC to the idle state.
*/
if (priv->i2cstate != I2CSTATE_IDLE)
{
i2c_reset_fsmc(priv);
priv->i2cstate = I2CSTATE_IDLE;
}
/* Transfer the messages to the internal struct
* and loop count times to make all transfers.
*/
priv->msgv = msgs;
ulp_riscv_i2c_master_set_slave_addr(msgs[0].addr);
/* This is a limitation for RTC I2C. Each transaction has to include
* a sub address
*/
if (msgs[0].flags & I2C_M_NOSTOP)
{
ulp_riscv_i2c_master_set_slave_reg_addr(msgs[0].buffer[0]);
}
else
{
ulp_riscv_i2c_master_set_slave_reg_addr(0);
}
for (int i = 0; i < count; i++)
{
priv->bytes = 0;
priv->msgid = i;
priv->ready_read = false;
priv->error = 0;
priv->i2cstate = I2CSTATE_PROC;
if ((msgs[i].flags & I2C_M_READ) != 0)
{
ulp_riscv_i2c_master_read_from_device(msgs[i].buffer, 1);
}
else
{
ulp_riscv_i2c_master_write_to_device(msgs[i].buffer,
msgs[i].length);
}
}
priv->i2cstate = I2CSTATE_IDLE;
/* Dump the trace result */
i2c_tracedump(priv);
nxmutex_unlock(&priv->lock);
return ret;
}
#endif
/****************************************************************************
* Name: i2c_transfer
*
+1 -1
View File
@@ -207,7 +207,7 @@ endif
ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty
ifndef ESP_HAL_3RDPARTY_VERSION
ESP_HAL_3RDPARTY_VERSION = 8e7f6a123659cb96f2240575b950748afc9b3dc0
ESP_HAL_3RDPARTY_VERSION = 6782de1b073f93a54c501edf23d99a42a23d41ac
endif
ifndef ESP_HAL_3RDPARTY_URL
+104 -6
View File
@@ -55,6 +55,7 @@
#include "hardware/esp32s3_i2c.h"
#include "hardware/esp32s3_soc.h"
#include "hardware/esp32s3_system.h"
#include "soc/interrupts.h"
#ifdef CONFIG_ESP32S3_RTC_I2C
# include "ulp_riscv.h"
@@ -259,6 +260,10 @@ static void i2c_init(struct esp32s3_i2c_priv_s *priv);
static void i2c_deinit(struct esp32s3_i2c_priv_s *priv);
static int i2c_transfer(struct i2c_master_s *dev, struct i2c_msg_s *msgs,
int count);
#ifdef CONFIG_ESP32S3_RTC_I2C
static int rtc_i2c_transfer(struct i2c_master_s *dev, struct i2c_msg_s *msgs,
int count);
#endif
static inline void i2c_process(struct esp32s3_i2c_priv_s *priv,
uint32_t status);
#ifndef CONFIG_I2C_POLLED
@@ -300,7 +305,7 @@ static const struct i2c_ops_s g_esp32s3_i2c_ops =
#ifdef CONFIG_ESP32S3_RTC_I2C
static const struct i2c_ops_s g_esp32s3_rtc_i2c_ops =
{
.transfer = NULL,
.transfer = rtc_i2c_transfer
};
#endif
@@ -313,8 +318,8 @@ static const struct esp32s3_i2c_config_s g_esp32s3_i2c0_config =
.scl_pin = CONFIG_ESP32S3_I2C0_SCLPIN,
.sda_pin = CONFIG_ESP32S3_I2C0_SDAPIN,
#ifndef CONFIG_I2C_POLLED
.periph = ESP32S3_PERIPH_I2C_EXT0,
.irq = ESP32S3_IRQ_I2C_EXT0,
.periph = ETS_I2C_EXT0_INTR_SOURCE,
.irq = ESP32S3_PERIPH2IRQ(ETS_I2C_EXT0_INTR_SOURCE),
#endif
.clk_bit = SYSTEM_I2C_EXT0_CLK_EN,
.rst_bit = SYSTEM_I2C_EXT0_RST,
@@ -349,8 +354,8 @@ static const struct esp32s3_i2c_config_s g_esp32s3_i2c1_config =
.scl_pin = CONFIG_ESP32S3_I2C1_SCLPIN,
.sda_pin = CONFIG_ESP32S3_I2C1_SDAPIN,
#ifndef CONFIG_I2C_POLLED
.periph = ESP32S3_PERIPH_I2C_EXT1,
.irq = ESP32S3_IRQ_I2C_EXT1,
.periph = ETS_I2C_EXT1_INTR_SOURCE,
.irq = ESP32S3_PERIPH2IRQ(ETS_I2C_EXT1_INTR_SOURCE),
#endif
.clk_bit = SYSTEM_I2C_EXT1_CLK_EN,
.rst_bit = SYSTEM_I2C_EXT1_RST,
@@ -1007,6 +1012,99 @@ static int i2c_polling_waitdone(struct esp32s3_i2c_priv_s *priv)
* Device Driver Operations
****************************************************************************/
#ifdef CONFIG_ESP32S3_RTC_I2C
/****************************************************************************
* Name: rtc_i2c_transfer
*
* Description:
* I2C transfer function for RTC I2C.
*
* 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 rtc_i2c_transfer(struct i2c_master_s *dev, struct i2c_msg_s *msgs,
int count)
{
int ret = OK;
struct esp32s3_i2c_priv_s *priv = (struct esp32s3_i2c_priv_s *)dev;
DEBUGASSERT(count > 0);
ret = nxmutex_lock(&priv->lock);
if (ret < 0)
{
return ret;
}
/* If previous state is different than idle,
* reset the FSMC to the idle state.
*/
if (priv->i2cstate != I2CSTATE_IDLE)
{
i2c_reset_fsmc(priv);
priv->i2cstate = I2CSTATE_IDLE;
}
/* Transfer the messages to the internal struct
* and loop count times to make all transfers.
*/
priv->msgv = msgs;
ulp_riscv_i2c_master_set_slave_addr(msgs[0].addr);
/* This is a limitation for RTC I2C. Each transaction has to include
* a sub address
*/
if (msgs[0].flags & I2C_M_NOSTOP)
{
ulp_riscv_i2c_master_set_slave_reg_addr(msgs[0].buffer[0]);
}
else
{
ulp_riscv_i2c_master_set_slave_reg_addr(0);
}
for (int i = 0; i < count; i++)
{
priv->bytes = 0;
priv->msgid = i;
priv->ready_read = false;
priv->error = 0;
priv->i2cstate = I2CSTATE_PROC;
if ((msgs[i].flags & I2C_M_READ) != 0)
{
ulp_riscv_i2c_master_read_from_device(msgs[i].buffer, 1);
}
else
{
ulp_riscv_i2c_master_write_to_device(msgs[i].buffer,
msgs[i].length);
}
}
priv->i2cstate = I2CSTATE_IDLE;
/* Dump the trace result */
i2c_tracedump(priv);
nxmutex_unlock(&priv->lock);
return ret;
}
#endif
/****************************************************************************
* Name: i2c_transfer
*
@@ -1634,7 +1732,7 @@ struct i2c_master_s *esp32s3_i2cbus_initialize(int port)
priv->cpu = this_cpu();
priv->cpuint = esp32s3_setup_irq(priv->cpu, config->periph,
1, ESP32S3_CPUINT_LEVEL);
1, ESP32S3_CPUINT_LEVEL);
if (priv->cpuint < 0)
{
/* Failed to allocate a CPU interrupt of this type */