diff --git a/arch/risc-v/src/common/espressif/Kconfig b/arch/risc-v/src/common/espressif/Kconfig index 9fbed736002..2c5316f975c 100644 --- a/arch/risc-v/src/common/espressif/Kconfig +++ b/arch/risc-v/src/common/espressif/Kconfig @@ -384,6 +384,10 @@ config ESPRESSIF_I2C bool default n +config ESPRESSIF_LPI2C + bool + default n + config ESPRESSIF_I2C_PERIPH_MASTER_MODE bool depends on (ESPRESSIF_I2C0_MASTER_MODE || ESPRESSIF_I2C1_MASTER_MODE) @@ -407,6 +411,14 @@ config ESPRESSIF_I2C1 select ESPRESSIF_I2C select I2C +config ESPRESSIF_LP_I2C0 + bool "LP I2C 0" + default n + depends on ARCH_CHIP_ESP32C6 + select ESPRESSIF_I2C + select ESPRESSIF_LPI2C + select I2C + choice ESPRESSIF_I2C0_MODE prompt "I2C0 Mode" depends on ESPRESSIF_I2C0 @@ -2041,7 +2053,8 @@ if ESPRESSIF_I2C0 config ESPRESSIF_I2C0_SCLPIN int "I2C0 SCL Pin" - default 6 + default 6 if !ESPRESSIF_LPI2C + default 23 if ESPRESSIF_LPI2C range 0 21 config ESPRESSIF_I2C0_SDAPIN diff --git a/arch/risc-v/src/common/espressif/esp_i2c.c b/arch/risc-v/src/common/espressif/esp_i2c.c index 77975e60209..07cccc1cb44 100644 --- a/arch/risc-v/src/common/espressif/esp_i2c.c +++ b/arch/risc-v/src/common/espressif/esp_i2c.c @@ -64,11 +64,24 @@ #if defined(CONFIG_ESPRESSIF_ESP32H2) || defined(CONFIG_ESPRESSIF_ESP32C6) # include "soc/pcr_reg.h" #endif +#if defined(CONFIG_ESPRESSIF_LP_I2C0) +# include "driver/rtc_io.h" +# include "hal/rtc_io_hal.h" +# include "io_mux.h" +# include "lp_core_i2c.h" +# include "soc/i2c_struct.h" +#endif /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +#if defined(CONFIG_ESPRESSIF_LP_I2C0) +# define ESP_LP_I2C0_ID LP_I2C_NUM_0 +#else +# define ESP_LP_I2C0_ID I2C_NUM_MAX +#endif + #ifdef CONFIG_ESPRESSIF_ESP32H2 # define SYSTEM_I2C_EXT0_CLK_EN PCR_I2C0_CLK_EN # define SYSTEM_I2C_EXT0_RST PCR_I2C0_RST_EN @@ -251,6 +264,8 @@ struct esp_i2c_priv_s bool ready_read; /* If I2C is ready for receiving data */ + soc_module_clk_t clk_src; /* Clock source */ + uint32_t clk_freq; /* Current I2C Clock frequency */ /* I2C trace support */ @@ -373,6 +388,7 @@ static struct esp_i2c_priv_s esp_i2c0_priv = #endif .error = 0, .ready_read = false, + .clk_src = I2C_CLK_SRC_DEFAULT, .clk_freq = 0, .ctx = &i2c0_ctx }; @@ -424,11 +440,63 @@ static struct esp_i2c_priv_s esp_i2c1_priv = #endif .error = 0, .ready_read = false, + .clk_src = I2C_CLK_SRC_DEFAULT, .clk_freq = 0, .ctx = &i2c1_ctx }; #endif /* CONFIG_ESPRESSIF_I2C1 */ +#ifdef CONFIG_ESPRESSIF_LP_I2C0 +i2c_hal_context_t lp_i2c0_ctx = +{ + 0 +}; + +/* I2C device structure */ + +static const struct esp_i2c_config_s esp_lp_i2c0_config = +{ + .clk_freq = I2C_CLK_FREQ_DEF, + .scl_pin = 7, + .sda_pin = 6, +#ifndef CONFIG_I2C_POLLED + .periph = ETS_LP_I2C_INTR_SOURCE, + .irq = ESP_IRQ_LP_I2C, +#endif + .clk_bit = SYSTEM_I2C_EXT0_CLK_EN, + .rst_bit = SYSTEM_I2C_EXT0_RST, + .scl_insig = 0, + .scl_outsig = 0, + .sda_insig = 0, + .sda_outsig = 0 +}; + +static struct esp_i2c_priv_s esp_lp_i2c0_priv = +{ + .ops = &esp_i2c_ops, + .id = LP_I2C_NUM_0, + .module = PERIPH_LP_I2C0_MODULE, + .config = &esp_lp_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_src = LP_I2C_SCLK_DEFAULT, + .clk_freq = 0, + .ctx = &lp_i2c0_ctx +}; +#endif /* CONFIG_ESPRESSIF_LP_I2C0 */ + /* Trace events strings */ #ifdef CONFIG_I2C_TRACE @@ -718,25 +786,64 @@ 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) { - uint32_t src_clk_frequency; + uint32_t src_clk_frequency = 0; if (bus_freq == priv->clk_freq) { return ; } - i2c_clock_source_t src_clk = I2C_CLK_SRC_DEFAULT; - esp_clk_tree_src_get_freq_hz((soc_module_clk_t)src_clk, - ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, + esp_clk_tree_src_get_freq_hz(priv->clk_src, + ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX, &src_clk_frequency); i2c_hal_set_bus_timing(priv->ctx, priv->config->clk_freq, - src_clk, src_clk_frequency); + priv->clk_src, src_clk_frequency); i2c_hal_master_set_scl_timeout_val(priv->ctx, SCL_TIMEOUT_VAL_US, src_clk_frequency); + +#ifdef CONFIG_ESPRESSIF_LPI2C + PERIPH_RCC_ATOMIC() + { + lp_i2c_ll_set_source_clk(priv->ctx->dev, priv->clk_src); + } +#endif + i2c_ll_update(priv->ctx->dev); priv->clk_freq = bus_freq; } +#ifdef CONFIG_ESPRESSIF_LPI2C +/**************************************************************************** + * Name: esp_lp_i2c_config_io + * + * Description: + * Configures LP I2C pin. + * + * Parameters: + * priv - Pointer to the private driver struct. + * pin - Pin number to configure. + * + * Return Value: + * None. + * + ****************************************************************************/ + +static void esp_lp_i2c_config_io(const struct esp_i2c_priv_s *priv, + int8_t pin) +{ + int lp_pin = rtc_io_num_map[pin]; + + DEBUGASSERT(lp_pin != -1); + + rtc_gpio_set_level(pin, 1); + rtc_gpio_init(pin); + + rtc_gpio_set_direction(pin, RTC_GPIO_MODE_INPUT_OUTPUT_OD); + rtc_gpio_pulldown_dis(pin); + rtc_gpio_pullup_en(pin); +} +#endif /* CONFIG_ESPRESSIF_LPI2C */ + /**************************************************************************** * Name: esp_i2c_init * @@ -752,22 +859,53 @@ 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 */ + if (priv->id < ESP_LP_I2C0_ID) + { + /* Configure GPIO signals for I2C SCL and SDA pins */ - esp_gpiowrite(config->scl_pin, 1); - esp_gpiowrite(config->sda_pin, 1); + 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->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); + 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 */ + /* Enable I2C hardware */ - periph_module_enable(priv->module); + periph_module_enable(priv->module); + } +#ifdef CONFIG_ESPRESSIF_LPI2C + else + { + PERIPH_RCC_ATOMIC() + { + /* Enable LP I2C bus clock */ + + lp_i2c_ll_enable_bus_clock(priv->id - LP_I2C_NUM_0, true); + + /* Reset LP I2C register */ + + lp_i2c_ll_reset_register(priv->id - LP_I2C_NUM_0); + } + + esp_lp_i2c_config_io(priv, config->scl_pin); + esp_lp_i2c_config_io(priv, config->sda_pin); + const i2c_signal_conn_t *p_i2c_pin = &i2c_periph_signal[priv->id]; +#if !SOC_LP_GPIO_MATRIX_SUPPORTED + rtc_gpio_iomux_func_sel(config->sda_pin, p_i2c_pin->iomux_func); + rtc_gpio_iomux_func_sel(config->scl_pin, p_i2c_pin->iomux_func); +#else + /* ToDo: Add LP I2C for LP GPIO Matrix + * supported devices (e.g ESP32-P4) + */ + +#endif /* SOC_LP_GPIO_MATRIX_SUPPORTED */ + } +#endif i2c_hal_init(priv->ctx, priv->id); @@ -783,6 +921,17 @@ static void esp_i2c_init(struct esp_i2c_priv_s *priv) i2c_ll_master_set_filter(priv->ctx->dev, I2C_FILTER_CYC_NUM_DEF); +#ifdef CONFIG_ESPRESSIF_LPI2C + /* Enable internal open-drain mode for I2C IO lines */ + + priv->ctx->dev->ctr.sda_force_out = 0; + priv->ctx->dev->ctr.scl_force_out = 0; + + /* Configure the I2C master to send a NACK when the Rx FIFO count is full */ + + i2c_ll_master_rx_full_ack_level(priv->ctx->dev, 1); +#endif + /* Initialize I2C bus clock */ esp_i2c_init_clock(priv, config->clk_freq); @@ -1531,6 +1680,11 @@ struct i2c_master_s *esp_i2cbus_initialize(int port) case ESPRESSIF_I2C1: priv = &esp_i2c1_priv; break; +#endif +#ifdef CONFIG_ESPRESSIF_LP_I2C0 + case ESPRESSIF_LP_I2C0: + priv = &esp_lp_i2c0_priv; + break; #endif default: return NULL; diff --git a/arch/risc-v/src/common/espressif/esp_i2c.h b/arch/risc-v/src/common/espressif/esp_i2c.h index 7b8def9f1c2..60087867a84 100644 --- a/arch/risc-v/src/common/espressif/esp_i2c.h +++ b/arch/risc-v/src/common/espressif/esp_i2c.h @@ -49,6 +49,10 @@ # define ESPRESSIF_I2C1 1 #endif +#ifdef CONFIG_ESPRESSIF_LP_I2C0 +# define ESPRESSIF_LP_I2C0 2 +#endif + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ diff --git a/arch/risc-v/src/common/espressif/esp_i2c_slave.c b/arch/risc-v/src/common/espressif/esp_i2c_slave.c index 97f33d5cb74..ef7e738c39e 100644 --- a/arch/risc-v/src/common/espressif/esp_i2c_slave.c +++ b/arch/risc-v/src/common/espressif/esp_i2c_slave.c @@ -540,7 +540,7 @@ static void esp_i2c_slave_init(struct esp_i2c_priv_s *priv) /* Enable I2C hardware */ - periph_module_enable(i2c_periph_signal[priv->id].module); + periph_module_enable(PERIPH_I2C0_MODULE); i2c_hal_init(priv->ctx, priv->id); @@ -551,7 +551,7 @@ static void esp_i2c_slave_init(struct esp_i2c_priv_s *priv) /* Initialize I2C Slave */ i2c_hal_slave_init(priv->ctx); - i2c_ll_slave_tx_auto_start_en(priv->ctx->dev, true); + i2c_ll_slave_enable_auto_start(priv->ctx->dev, true); i2c_ll_set_source_clk(priv->ctx->dev, I2C_CLK_SRC_DEFAULT); i2c_ll_set_slave_addr(priv->ctx->dev, priv->addr, false); i2c_ll_set_rxfifo_full_thr(priv->ctx->dev, I2C_FIFO_FULL_THRESH_VAL); @@ -583,7 +583,7 @@ static void esp_i2c_slave_deinit(struct esp_i2c_priv_s *priv) const struct esp_i2c_config_s *config = priv->config; i2c_hal_deinit(priv->ctx); - periph_module_disable(i2c_periph_signal[priv->id].module); + periph_module_disable(PERIPH_I2C0_MODULE); } /**************************************************************************** diff --git a/arch/risc-v/src/esp32c6/hal_esp32c6.mk b/arch/risc-v/src/esp32c6/hal_esp32c6.mk index 9deb2e01023..dd7f8a2a39b 100644 --- a/arch/risc-v/src/esp32c6/hal_esp32c6.mk +++ b/arch/risc-v/src/esp32c6/hal_esp32c6.mk @@ -212,6 +212,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)rtc_io_periph.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)$(CHIP_SERIES)$(DELIM)temperature_sensor_periph.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)soc$(DELIM)${CHIP_SERIES}$(DELIM)uart_periph.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)ulp$(DELIM)lp_core$(DELIM)lp_core_i2c.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)components$(DELIM)esp_driver_gpio$(DELIM)src$(DELIM)gpio.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)nuttx$(DELIM)src$(DELIM)components$(DELIM)esp_driver_gpio$(DELIM)src$(DELIM)rtc_io.c diff --git a/boards/risc-v/esp32c6/common/src/esp_board_i2c.c b/boards/risc-v/esp32c6/common/src/esp_board_i2c.c index a79e97518ed..bf400503e81 100644 --- a/boards/risc-v/esp32c6/common/src/esp_board_i2c.c +++ b/boards/risc-v/esp32c6/common/src/esp_board_i2c.c @@ -160,5 +160,9 @@ int board_i2c_init(void) ret = i2c_slave_driver_init(ESPRESSIF_I2C0_SLAVE, I2C0_SLAVE_ADDR); #endif +#ifdef CONFIG_ESPRESSIF_LP_I2C0 + ret = i2c_driver_init(ESPRESSIF_LP_I2C0); +#endif + return ret; }