/* * Copyright (c) 2017 Intel Corporation * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. * * SPDX-License-Identifier: Apache-2.0 */ #define DT_DRV_COMPAT espressif_esp32_i2c /* Include esp-idf headers first to avoid redefining BIT() macro */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include LOG_MODULE_REGISTER(i2c_esp32, CONFIG_I2C_LOG_LEVEL); #include "i2c-priv.h" #define I2C_FILTER_CYC_NUM_DEF 7 /* Number of apb cycles filtered by default */ #define I2C_CLR_BUS_SCL_NUM 9 /* Number of SCL clocks to restore SDA signal */ #define I2C_CLR_BUS_HALF_PERIOD_US 5 /* Period of SCL clock to restore SDA signal */ #define I2C_TRANSFER_TIMEOUT_MSEC 500 /* Transfer timeout period */ /* Freq limitation when using different clock sources */ #define I2C_CLK_LIMIT_REF_TICK (1 * 1000 * 1000 / 20) /* REF_TICK, no more than REF_TICK/20*/ #define I2C_CLK_LIMIT_APB (80 * 1000 * 1000 / 20) /* Limited by APB, no more than APB/20 */ #define I2C_CLK_LIMIT_RTC (20 * 1000 * 1000 / 20) /* Limited by RTC, no more than RTC/20 */ #define I2C_CLK_LIMIT_XTAL (40 * 1000 * 1000 / 20) /* Limited by RTC, no more than XTAL/20 */ enum i2c_status_t { I2C_STATUS_READ, /* read status for current master command */ I2C_STATUS_WRITE, /* write status for current master command */ I2C_STATUS_IDLE, /* idle status for current master command */ I2C_STATUS_ACK_ERROR, /* ack error status for current master command */ I2C_STATUS_DONE, /* I2C command done */ I2C_STATUS_TIMEOUT, /* I2C bus status error, and operation timeout */ }; #ifndef SOC_I2C_SUPPORT_HW_CLR_BUS struct i2c_esp32_pin { const char *gpio_name; int sig_out; int sig_in; gpio_pin_t pin; }; #endif struct i2c_esp32_data { i2c_hal_context_t hal; struct k_sem cmd_sem; struct k_sem transfer_sem; volatile enum i2c_status_t status; uint32_t dev_config; int cmd_idx; int irq_line; #ifndef SOC_I2C_SUPPORT_HW_CLR_BUS const struct device *scl_gpio; const struct device *sda_gpio; #endif }; typedef void (*irq_connect_cb)(void); struct i2c_esp32_config { int index; const struct device *clock_dev; #ifndef SOC_I2C_SUPPORT_HW_CLR_BUS const struct i2c_esp32_pin scl; const struct i2c_esp32_pin sda; #endif const struct pinctrl_dev_config *pcfg; const clock_control_subsys_t clock_subsys; const struct { bool tx_lsb_first; bool rx_lsb_first; } mode; int irq_source; const uint32_t default_config; const uint32_t bitrate; }; /* I2C clock characteristic, The order is the same as i2c_sclk_t. */ static uint32_t i2c_clk_alloc[I2C_SCLK_MAX] = { 0, #if SOC_I2C_SUPPORT_APB I2C_CLK_LIMIT_APB, /* I2C APB clock characteristic */ #endif #if SOC_I2C_SUPPORT_XTAL I2C_CLK_LIMIT_XTAL, /* I2C XTAL characteristic */ #endif #if SOC_I2C_SUPPORT_RTC I2C_CLK_LIMIT_RTC, /* I2C 20M RTC characteristic */ #endif #if SOC_I2C_SUPPORT_REF_TICK I2C_CLK_LIMIT_REF_TICK, /* I2C REF_TICK characteristic */ #endif }; static i2c_sclk_t i2c_get_clk_src(uint32_t clk_freq) { for (i2c_sclk_t clk = I2C_SCLK_DEFAULT + 1; clk < I2C_SCLK_MAX; clk++) { if (clk_freq <= i2c_clk_alloc[clk]) { return clk; } } return I2C_SCLK_MAX; /* flag invalid */ } #ifndef SOC_I2C_SUPPORT_HW_CLR_BUS static int i2c_esp32_config_pin(const struct device *dev) { const struct i2c_esp32_config *config = dev->config; struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; int ret = 0; if (config->index >= SOC_I2C_NUM) { LOG_ERR("Invalid I2C peripheral number"); return -EINVAL; } gpio_pin_set(data->sda_gpio, config->sda.pin, 1); ret = gpio_pin_configure(data->sda_gpio, config->sda.pin, GPIO_PULL_UP | GPIO_OPEN_DRAIN | GPIO_OUTPUT | GPIO_INPUT); esp_rom_gpio_matrix_out(config->sda.pin, config->sda.sig_out, 0, 0); esp_rom_gpio_matrix_in(config->sda.pin, config->sda.sig_in, 0); gpio_pin_set(data->scl_gpio, config->scl.pin, 1); ret |= gpio_pin_configure(data->scl_gpio, config->scl.pin, GPIO_PULL_UP | GPIO_OPEN_DRAIN | GPIO_OUTPUT | GPIO_INPUT); esp_rom_gpio_matrix_out(config->scl.pin, config->scl.sig_out, 0, 0); esp_rom_gpio_matrix_in(config->scl.pin, config->scl.sig_in, 0); return ret; } #endif /* Some slave device will die by accident and keep the SDA in low level, * in this case, master should send several clock to make the slave release the bus. * Slave mode of ESP32 might also get in wrong state that held the SDA low, * in this case, master device could send a stop signal to make esp32 slave release the bus. **/ static void IRAM_ATTR i2c_master_clear_bus(const struct device *dev) { struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; #ifndef SOC_I2C_SUPPORT_HW_CLR_BUS const struct i2c_esp32_config *config = dev->config; const int scl_half_period = I2C_CLR_BUS_HALF_PERIOD_US; /* use standard 100kHz data rate */ int i = 0; gpio_pin_t scl_io = config->scl.pin; gpio_pin_t sda_io = config->sda.pin; gpio_pin_configure(data->scl_gpio, scl_io, GPIO_OUTPUT | GPIO_OPEN_DRAIN); gpio_pin_configure(data->sda_gpio, sda_io, GPIO_OUTPUT | GPIO_OPEN_DRAIN | GPIO_INPUT); /* If a SLAVE device was in a read operation when the bus was interrupted, */ /* the SLAVE device is controlling SDA. If the slave is sending a stream of ZERO bytes, */ /* it will only release SDA during the ACK bit period. So, this reset code needs */ /* to synchronize the bit stream with either the ACK bit, or a 1 bit to correctly */ /* generate a STOP condition. */ gpio_pin_set(data->scl_gpio, scl_io, 0); gpio_pin_set(data->sda_gpio, sda_io, 1); esp_rom_delay_us(scl_half_period); while (!gpio_pin_get(data->sda_gpio, sda_io) && (i++ < I2C_CLR_BUS_SCL_NUM)) { gpio_pin_set(data->scl_gpio, scl_io, 1); esp_rom_delay_us(scl_half_period); gpio_pin_set(data->scl_gpio, scl_io, 0); esp_rom_delay_us(scl_half_period); } gpio_pin_set(data->sda_gpio, sda_io, 0); /* setup for STOP */ gpio_pin_set(data->scl_gpio, scl_io, 1); esp_rom_delay_us(scl_half_period); gpio_pin_set(data->sda_gpio, sda_io, 1); /* STOP, SDA low -> high while SCL is HIGH */ i2c_esp32_config_pin(dev); #else i2c_hal_master_clr_bus(&data->hal); #endif i2c_hal_update_config(&data->hal); } static void IRAM_ATTR i2c_hw_fsm_reset(const struct device *dev) { struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; #ifndef SOC_I2C_SUPPORT_HW_FSM_RST const struct i2c_esp32_config *config = dev->config; int scl_low_period, scl_high_period; int scl_start_hold, scl_rstart_setup; int scl_stop_hold, scl_stop_setup; int sda_hold, sda_sample; int timeout; uint8_t filter_cfg; i2c_hal_get_scl_timing(&data->hal, &scl_high_period, &scl_low_period); i2c_hal_get_start_timing(&data->hal, &scl_rstart_setup, &scl_start_hold); i2c_hal_get_stop_timing(&data->hal, &scl_stop_setup, &scl_stop_hold); i2c_hal_get_sda_timing(&data->hal, &sda_sample, &sda_hold); i2c_hal_get_tout(&data->hal, &timeout); i2c_hal_get_filter(&data->hal, &filter_cfg); /* to reset the I2C hw module, we need re-enable the hw */ clock_control_off(config->clock_dev, config->clock_subsys); i2c_master_clear_bus(dev); clock_control_on(config->clock_dev, config->clock_subsys); i2c_hal_master_init(&data->hal, config->index); i2c_hal_disable_intr_mask(&data->hal, I2C_LL_INTR_MASK); i2c_hal_clr_intsts_mask(&data->hal, I2C_LL_INTR_MASK); i2c_hal_set_scl_timing(&data->hal, scl_high_period, scl_low_period); i2c_hal_set_start_timing(&data->hal, scl_rstart_setup, scl_start_hold); i2c_hal_set_stop_timing(&data->hal, scl_stop_setup, scl_stop_hold); i2c_hal_set_sda_timing(&data->hal, sda_sample, sda_hold); i2c_hal_set_tout(&data->hal, timeout); i2c_hal_set_filter(&data->hal, filter_cfg); #else i2c_hal_master_fsm_rst(&data->hal); i2c_master_clear_bus(dev); #endif i2c_hal_update_config(&data->hal); } static int i2c_esp32_recover(const struct device *dev) { struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; k_sem_take(&data->transfer_sem, K_FOREVER); i2c_hw_fsm_reset(dev); k_sem_give(&data->transfer_sem); return 0; } static int i2c_esp32_configure(const struct device *dev, uint32_t dev_config) { const struct i2c_esp32_config *config = dev->config; struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; if (!(dev_config & I2C_MODE_MASTER)) { LOG_ERR("Only I2C Master mode supported."); return -ENOTSUP; } data->dev_config = dev_config; i2c_trans_mode_t tx_mode = I2C_DATA_MODE_MSB_FIRST; i2c_trans_mode_t rx_mode = I2C_DATA_MODE_MSB_FIRST; if (config->mode.tx_lsb_first) { tx_mode = I2C_DATA_MODE_LSB_FIRST; } if (config->mode.rx_lsb_first) { rx_mode = I2C_DATA_MODE_LSB_FIRST; } i2c_hal_master_init(&data->hal, config->index); i2c_hal_set_data_mode(&data->hal, tx_mode, rx_mode); i2c_hal_set_filter(&data->hal, I2C_FILTER_CYC_NUM_DEF); i2c_hal_update_config(&data->hal); if (config->bitrate == 0) { LOG_ERR("Error configuring I2C speed."); return -ENOTSUP; } i2c_hal_set_bus_timing(&data->hal, config->bitrate, i2c_get_clk_src(config->bitrate)); i2c_hal_update_config(&data->hal); return 0; } static void IRAM_ATTR i2c_esp32_reset_fifo(const struct device *dev) { struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; /* reset fifo buffers */ i2c_hal_txfifo_rst(&data->hal); i2c_hal_rxfifo_rst(&data->hal); } static int IRAM_ATTR i2c_esp32_transmit(const struct device *dev) { struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; int ret = 0; /* Start transmission*/ i2c_hal_update_config(&data->hal); i2c_hal_trans_start(&data->hal); data->cmd_idx = 0; ret = k_sem_take(&data->cmd_sem, K_MSEC(I2C_TRANSFER_TIMEOUT_MSEC)); if (ret != 0) { /* If the I2C slave is powered off or the SDA/SCL is */ /* connected to ground, for example, I2C hw FSM would get */ /* stuck in wrong state, we have to reset the I2C module in this case. */ i2c_hw_fsm_reset(dev); return -ETIMEDOUT; } if (data->status == I2C_STATUS_TIMEOUT) { i2c_hw_fsm_reset(dev); ret = -ETIMEDOUT; } else if (data->status == I2C_STATUS_ACK_ERROR) { ret = -EFAULT; } return ret; } static void IRAM_ATTR i2c_esp32_master_start(const struct device *dev) { struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; i2c_hw_cmd_t cmd = { .op_code = I2C_LL_CMD_RESTART }; i2c_hal_write_cmd_reg(&data->hal, cmd, data->cmd_idx++); } static void IRAM_ATTR i2c_esp32_master_stop(const struct device *dev) { struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; i2c_hw_cmd_t cmd = { .op_code = I2C_LL_CMD_STOP }; i2c_hal_write_cmd_reg(&data->hal, cmd, data->cmd_idx++); } static int IRAM_ATTR i2c_esp32_write_addr(const struct device *dev, uint16_t addr) { struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; uint8_t addr_len = 1; uint8_t addr_byte = addr & 0xFF; data->status = I2C_STATUS_WRITE; /* write address value in tx buffer */ i2c_hal_write_txfifo(&data->hal, &addr_byte, 1); if (data->dev_config & I2C_ADDR_10_BITS) { addr_byte = (addr >> 8) & 0xFF; i2c_hal_write_txfifo(&data->hal, &addr_byte, 1); addr_len++; } const i2c_hw_cmd_t cmd_end = { .op_code = I2C_LL_CMD_END, }; i2c_hw_cmd_t cmd = { .op_code = I2C_LL_CMD_WRITE, .ack_en = true, .byte_num = addr_len, }; i2c_hal_write_cmd_reg(&data->hal, cmd, data->cmd_idx++); i2c_hal_write_cmd_reg(&data->hal, cmd_end, data->cmd_idx++); i2c_hal_enable_master_tx_it(&data->hal); return i2c_esp32_transmit(dev); } static int IRAM_ATTR i2c_esp32_master_read(const struct device *dev, struct i2c_msg *msg) { struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; uint8_t rd_filled = 0; uint8_t *read_pr = NULL; int ret = 0; data->status = I2C_STATUS_READ; i2c_hw_cmd_t cmd = { .op_code = I2C_LL_CMD_READ, }; const i2c_hw_cmd_t cmd_end = { .op_code = I2C_LL_CMD_END, }; while (msg->len) { rd_filled = (msg->len > SOC_I2C_FIFO_LEN) ? SOC_I2C_FIFO_LEN : (msg->len - 1); read_pr = msg->buf; msg->buf += rd_filled; msg->len -= rd_filled; if (rd_filled) { cmd.ack_val = 0, cmd.byte_num = rd_filled; i2c_hal_write_cmd_reg(&data->hal, cmd, data->cmd_idx++); i2c_hal_write_cmd_reg(&data->hal, cmd_end, data->cmd_idx++); i2c_hal_enable_master_rx_it(&data->hal); ret = i2c_esp32_transmit(dev); if (ret < 0) { return ret; } i2c_hal_read_rxfifo(&data->hal, read_pr, rd_filled); msg->buf += rd_filled; } /* I2C master won't acknowledge the last byte read from the * slave device. Divide the read command in two segments as * recommended by the ESP32 Technical Reference Manual. */ if (msg->len == 1) { cmd.ack_val = 1, cmd.byte_num = 1, msg->len = 0; rd_filled++; i2c_hal_write_cmd_reg(&data->hal, cmd, data->cmd_idx++); i2c_hal_write_cmd_reg(&data->hal, cmd_end, data->cmd_idx++); i2c_hal_enable_master_rx_it(&data->hal); ret = i2c_esp32_transmit(dev); if (ret < 0) { return ret; } i2c_hal_read_rxfifo(&data->hal, read_pr, rd_filled); msg->buf += rd_filled; } } return 0; } static int IRAM_ATTR i2c_esp32_read_msg(const struct device *dev, struct i2c_msg *msg, uint16_t addr) { int ret = 0; struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; /* Set the R/W bit to R */ addr |= BIT(0); if (msg->flags & I2C_MSG_RESTART) { i2c_esp32_master_start(dev); ret = i2c_esp32_write_addr(dev, addr); if (ret < 0) { LOG_ERR("I2C transfer error: %d", ret); return ret; } } ret = i2c_esp32_master_read(dev, msg); if (ret < 0) { LOG_ERR("I2C transfer error: %d", ret); return ret; } if (msg->flags & I2C_MSG_STOP) { i2c_esp32_master_stop(dev); ret = i2c_esp32_transmit(dev); if (ret < 0) { LOG_ERR("I2C transfer error: %d", ret); return ret; } } return 0; } static int IRAM_ATTR i2c_esp32_master_write(const struct device *dev, struct i2c_msg *msg) { struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; uint8_t wr_filled = 0; uint8_t *write_pr = NULL; int ret = 0; data->status = I2C_STATUS_WRITE; i2c_hw_cmd_t cmd = { .op_code = I2C_LL_CMD_WRITE, .ack_en = true, }; const i2c_hw_cmd_t cmd_end = { .op_code = I2C_LL_CMD_END, }; while (msg->len) { wr_filled = (msg->len > SOC_I2C_FIFO_LEN) ? SOC_I2C_FIFO_LEN : msg->len; write_pr = msg->buf; msg->buf += wr_filled; msg->len -= wr_filled; cmd.byte_num = wr_filled; if (wr_filled > 0) { i2c_hal_write_txfifo(&data->hal, write_pr, wr_filled); i2c_hal_write_cmd_reg(&data->hal, cmd, data->cmd_idx++); i2c_hal_write_cmd_reg(&data->hal, cmd_end, data->cmd_idx++); i2c_hal_enable_master_tx_it(&data->hal); ret = i2c_esp32_transmit(dev); if (ret < 0) { return ret; } } } return 0; } static int IRAM_ATTR i2c_esp32_write_msg(const struct device *dev, struct i2c_msg *msg, uint16_t addr) { struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; int ret = 0; if (msg->flags & I2C_MSG_RESTART) { i2c_esp32_master_start(dev); ret = i2c_esp32_write_addr(dev, addr); if (ret < 0) { LOG_ERR("I2C transfer error: %d", ret); return ret; } } ret = i2c_esp32_master_write(dev, msg); if (ret < 0) { LOG_ERR("I2C transfer error: %d", ret); return ret; } if (msg->flags & I2C_MSG_STOP) { i2c_esp32_master_stop(dev); ret = i2c_esp32_transmit(dev); if (ret < 0) { LOG_ERR("I2C transfer error: %d", ret); return ret; } } return 0; } static int IRAM_ATTR i2c_esp32_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, uint16_t addr) { struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; struct i2c_msg *current, *next; int ret = 0; if (!num_msgs) { return 0; } /* Check for validity of all messages before transfer */ current = msgs; /* Add restart flag on first message to send start event */ current->flags |= I2C_MSG_RESTART; for (int k = 1; k <= num_msgs; k++) { if (k < num_msgs) { next = current + 1; /* messages of different direction require restart event */ if ((current->flags & I2C_MSG_RW_MASK) != (next->flags & I2C_MSG_RW_MASK)) { if (!(next->flags & I2C_MSG_RESTART)) { ret = -EINVAL; break; } } /* check if there is any stop event in the middle of the transaction */ if (current->flags & I2C_MSG_STOP) { ret = -EINVAL; break; } } else { /* make sure the last message contains stop event */ current->flags |= I2C_MSG_STOP; } current++; } if (ret) { return ret; } k_sem_take(&data->transfer_sem, K_FOREVER); /* Mask out unused address bits, and make room for R/W bit */ addr &= BIT_MASK(data->dev_config & I2C_ADDR_10_BITS ? 10 : 7); addr <<= 1; for (; num_msgs > 0; num_msgs--, msgs++) { if (data->status == I2C_STATUS_TIMEOUT || i2c_hal_is_bus_busy(&data->hal)) { i2c_hw_fsm_reset(dev); } /* reset all fifo buffer before start */ i2c_esp32_reset_fifo(dev); /* These two interrupts some times can not be cleared when the FSM gets stuck. */ /* So we disable them when these two interrupt occurs and re-enable them here. */ i2c_hal_disable_intr_mask(&data->hal, I2C_LL_INTR_MASK); i2c_hal_clr_intsts_mask(&data->hal, I2C_LL_INTR_MASK); if ((msgs->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) { ret = i2c_esp32_read_msg(dev, msgs, addr); } else { ret = i2c_esp32_write_msg(dev, msgs, addr); } if (ret < 0) { break; } } k_sem_give(&data->transfer_sem); return ret; } static void IRAM_ATTR i2c_esp32_isr(void *arg) { const struct device *dev = (const struct device *)arg; struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; i2c_intr_event_t evt_type = I2C_INTR_EVENT_ERR; if (data->status == I2C_STATUS_WRITE) { i2c_hal_master_handle_tx_event(&data->hal, &evt_type); } else if (data->status == I2C_STATUS_READ) { i2c_hal_master_handle_rx_event(&data->hal, &evt_type); } if (evt_type == I2C_INTR_EVENT_NACK) { data->status = I2C_STATUS_ACK_ERROR; } else if (evt_type == I2C_INTR_EVENT_TOUT) { data->status = I2C_STATUS_TIMEOUT; } else if (evt_type == I2C_INTR_EVENT_ARBIT_LOST) { data->status = I2C_STATUS_TIMEOUT; } else if (evt_type == I2C_INTR_EVENT_TRANS_DONE) { data->status = I2C_STATUS_DONE; } k_sem_give(&data->cmd_sem); } static const struct i2c_driver_api i2c_esp32_driver_api = { .configure = i2c_esp32_configure, .transfer = i2c_esp32_transfer, .recover_bus = i2c_esp32_recover }; static int IRAM_ATTR i2c_esp32_init(const struct device *dev) { const struct i2c_esp32_config *config = dev->config; #ifndef SOC_I2C_SUPPORT_HW_CLR_BUS struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; if (config->scl.gpio_name == NULL || config->sda.gpio_name == NULL) { LOG_ERR("Failed to get GPIO device"); return -EINVAL; } data->scl_gpio = device_get_binding(config->scl.gpio_name); if (!data->scl_gpio) { LOG_ERR("Failed to get SCL GPIO device"); return -EINVAL; } data->sda_gpio = device_get_binding(config->sda.gpio_name); if (!data->sda_gpio) { LOG_ERR("Failed to get SDA GPIO device"); return -EINVAL; } #endif int ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); if (ret < 0) { LOG_ERR("Failed to configure I2C pins"); return -EINVAL; } clock_control_on(config->clock_dev, config->clock_subsys); esp_intr_alloc(config->irq_source, 0, i2c_esp32_isr, (void *)dev, NULL); return i2c_esp32_configure(dev, config->default_config); } #ifndef SOC_I2C_SUPPORT_HW_CLR_BUS #define GPIO0_NAME COND_CODE_1(DT_NODE_HAS_STATUS(DT_NODELABEL(gpio0), okay), \ (DT_LABEL(DT_INST(0, espressif_esp32_gpio))), (NULL)) #define GPIO1_NAME COND_CODE_1(DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay), \ (DT_LABEL(DT_INST(1, espressif_esp32_gpio))), (NULL)) #define DT_I2C_ESP32_GPIO_NAME(idx, pin) ( \ DT_INST_PROP(idx, pin) < 32 ? GPIO0_NAME : GPIO1_NAME) #define I2C_ESP32_GET_PIN_INFO(idx) \ .scl = { \ .gpio_name = DT_I2C_ESP32_GPIO_NAME(idx, scl_pin), \ .sig_out = I2CEXT##idx##_SCL_OUT_IDX, \ .sig_in = I2CEXT##idx##_SCL_IN_IDX, \ .pin = DT_INST_PROP(idx, scl_pin), \ }, \ .sda = { \ .gpio_name = DT_I2C_ESP32_GPIO_NAME(idx, sda_pin), \ .sig_out = I2CEXT##idx##_SDA_OUT_IDX, \ .sig_in = I2CEXT##idx##_SDA_IN_IDX, \ .pin = DT_INST_PROP(idx, sda_pin), \ }, #else #define I2C_ESP32_GET_PIN_INFO(idx) #endif /* SOC_I2C_SUPPORT_HW_CLR_BUS */ #define I2C_ESP32_FREQUENCY(bitrate) \ (bitrate == I2C_BITRATE_STANDARD ? KHZ(100) \ : bitrate == I2C_BITRATE_FAST ? KHZ(400) \ : bitrate == I2C_BITRATE_FAST_PLUS ? MHZ(1) : 0) #define I2C_FREQUENCY(idx) \ I2C_ESP32_FREQUENCY(DT_INST_PROP(idx, clock_frequency)) #define ESP32_I2C_INIT(idx) \ \ PINCTRL_DT_INST_DEFINE(idx); \ \ static struct i2c_esp32_data i2c_esp32_data_##idx = { \ .hal = { \ .dev = (i2c_dev_t *) DT_REG_ADDR(DT_NODELABEL(i2c##idx)), \ }, \ .cmd_sem = Z_SEM_INITIALIZER( \ i2c_esp32_data_##idx.cmd_sem, 0, 1), \ .transfer_sem = Z_SEM_INITIALIZER( \ i2c_esp32_data_##idx.transfer_sem, 1, 1) \ }; \ \ static const struct i2c_esp32_config i2c_esp32_config_##idx = { \ .index = idx, \ .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(idx)), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \ .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(idx, offset), \ I2C_ESP32_GET_PIN_INFO(idx) \ .mode = { \ .tx_lsb_first = DT_INST_PROP(idx, tx_lsb), \ .rx_lsb_first = DT_INST_PROP(idx, rx_lsb), \ }, \ .irq_source = ETS_I2C_EXT##idx##_INTR_SOURCE, \ .bitrate = I2C_FREQUENCY(idx), \ .default_config = I2C_MODE_MASTER, \ }; \ I2C_DEVICE_DT_DEFINE(DT_NODELABEL(i2c##idx), \ i2c_esp32_init, \ NULL, \ &i2c_esp32_data_##idx, \ &i2c_esp32_config_##idx, \ POST_KERNEL, \ CONFIG_I2C_INIT_PRIORITY, \ &i2c_esp32_driver_api); \ #if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c0), okay) #ifndef SOC_I2C_SUPPORT_HW_CLR_BUS #if !DT_PROP(DT_INST(0, espressif_esp32_i2c), sda_pin) || \ !DT_PROP(DT_INST(0, espressif_esp32_i2c), scl_pin) #error "Missing and properties to build for this target." #endif #else #if DT_PROP(DT_INST(0, espressif_esp32_i2c), sda_pin) || \ DT_PROP(DT_INST(0, espressif_esp32_i2c), scl_pin) #error "Properties and are not required for this target." #endif #endif ESP32_I2C_INIT(0); #endif #if DT_NODE_HAS_STATUS(DT_NODELABEL(i2c1), okay) #ifndef SOC_I2C_SUPPORT_HW_CLR_BUS #if !DT_PROP(DT_INST(1, espressif_esp32_i2c), sda_pin) || \ !DT_PROP(DT_INST(1, espressif_esp32_i2c), scl_pin) #error "Missing and properties to build for this target." #endif #else #if DT_PROP(DT_INST(1, espressif_esp32_i2c), sda_pin) || \ DT_PROP(DT_INST(1, espressif_esp32_i2c), scl_pin) #error "Properties and are not required for this target." #endif #endif ESP32_I2C_INIT(1); #endif