zephyr/drivers/i2c/i2c_ite_enhance.c
Tim Lin 19724ba002 ITE: drivers/i2c: Enable I2C interrupt after completing configuration
Fix the flow of I2C enable interrupt. We should enable the interrupt
after I2C configuration is completed to avoid pending interrupts and
cause errors irq.

Test port:
i2c_ite_it8xxx2: i2c0
i2c_ite_enhance: i2c4
Test:
tests\drivers\i2c\i2c_api --> pass

Signed-off-by: Tim Lin <tim2.lin@ite.corp-partner.google.com>
2022-06-20 10:24:27 +02:00

759 lines
20 KiB
C

/*
* Copyright (c) 2022 ITE Corporation. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT ite_enhance_i2c
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/drivers/pinctrl.h>
#include <errno.h>
#include <soc.h>
#include <soc_dt.h>
#include <zephyr/sys/util.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(i2c_ite_enhance, CONFIG_I2C_LOG_LEVEL);
#include "i2c-priv.h"
/* Start smbus session from idle state */
#define I2C_MSG_START BIT(5)
#define I2C_LINE_SCL_HIGH BIT(0)
#define I2C_LINE_SDA_HIGH BIT(1)
#define I2C_LINE_IDLE (I2C_LINE_SCL_HIGH | I2C_LINE_SDA_HIGH)
struct i2c_enhance_config {
void (*irq_config_func)(void);
uint32_t bitrate;
uint8_t *base;
uint8_t i2c_irq_base;
uint8_t port;
/* SCL GPIO cells */
struct gpio_dt_spec scl_gpios;
/* SDA GPIO cells */
struct gpio_dt_spec sda_gpios;
/* I2C alternate configuration */
const struct pinctrl_dev_config *pcfg;
uint8_t prescale_scl_low;
uint32_t clock_gate_offset;
};
enum i2c_pin_fun {
SCL = 0,
SDA,
};
enum i2c_ch_status {
I2C_CH_NORMAL = 0,
I2C_CH_REPEAT_START,
I2C_CH_WAIT_READ,
I2C_CH_WAIT_NEXT_XFER,
};
struct i2c_enhance_data {
enum i2c_ch_status i2ccs;
struct i2c_msg *msgs;
struct k_mutex mutex;
struct k_sem device_sync_sem;
/* Index into output data */
size_t widx;
/* Index into input data */
size_t ridx;
/* operation freq of i2c */
uint32_t bus_freq;
/* Error code, if any */
uint32_t err;
/* address of device */
uint16_t addr_16bit;
/* wait for stop bit interrupt */
uint8_t stop;
};
enum enhanced_i2c_transfer_direct {
TX_DIRECT,
RX_DIRECT,
};
enum enhanced_i2c_ctl {
/* Hardware reset */
E_HW_RST = 0x01,
/* Stop */
E_STOP = 0x02,
/* Start & Repeat start */
E_START = 0x04,
/* Acknowledge */
E_ACK = 0x08,
/* State reset */
E_STS_RST = 0x10,
/* Mode select */
E_MODE_SEL = 0x20,
/* I2C interrupt enable */
E_INT_EN = 0x40,
/* 0 : Standard mode , 1 : Receive mode */
E_RX_MODE = 0x80,
/* State reset and hardware reset */
E_STS_AND_HW_RST = (E_STS_RST | E_HW_RST),
/* Generate start condition and transmit slave address */
E_START_ID = (E_INT_EN | E_MODE_SEL | E_ACK | E_START | E_HW_RST),
/* Generate stop condition */
E_FINISH = (E_INT_EN | E_MODE_SEL | E_ACK | E_STOP | E_HW_RST),
};
enum enhanced_i2c_host_status {
/* ACK receive */
E_HOSTA_ACK = 0x01,
/* Interrupt pending */
E_HOSTA_INTP = 0x02,
/* Read/Write */
E_HOSTA_RW = 0x04,
/* Time out error */
E_HOSTA_TMOE = 0x08,
/* Arbitration lost */
E_HOSTA_ARB = 0x10,
/* Bus busy */
E_HOSTA_BB = 0x20,
/* Address match */
E_HOSTA_AM = 0x40,
/* Byte done status */
E_HOSTA_BDS = 0x80,
/* time out or lost arbitration */
E_HOSTA_ANY_ERROR = (E_HOSTA_TMOE | E_HOSTA_ARB),
/* Byte transfer done and ACK receive */
E_HOSTA_BDS_AND_ACK = (E_HOSTA_BDS | E_HOSTA_ACK),
};
enum i2c_reset_cause {
I2C_RC_NO_IDLE_FOR_START = 1,
I2C_RC_TIMEOUT,
};
static int i2c_parsing_return_value(const struct device *dev)
{
struct i2c_enhance_data *data = dev->data;
if (!data->err) {
return 0;
}
/* Connection timed out */
if (data->err == ETIMEDOUT) {
return -ETIMEDOUT;
}
/* The device does not respond ACK */
if (data->err == E_HOSTA_ACK) {
return -ENXIO;
} else {
return -EIO;
}
}
static int i2c_get_line_levels(const struct device *dev)
{
const struct i2c_enhance_config *config = dev->config;
uint8_t *base = config->base;
int pin_sts = 0;
if (IT8XXX2_I2C_TOS(base) & IT8XXX2_I2C_SCL_IN) {
pin_sts |= I2C_LINE_SCL_HIGH;
}
if (IT8XXX2_I2C_TOS(base) & IT8XXX2_I2C_SDA_IN) {
pin_sts |= I2C_LINE_SDA_HIGH;
}
return pin_sts;
}
static int i2c_is_busy(const struct device *dev)
{
const struct i2c_enhance_config *config = dev->config;
uint8_t *base = config->base;
return (IT8XXX2_I2C_STR(base) & E_HOSTA_BB);
}
static int i2c_bus_not_available(const struct device *dev)
{
if (i2c_is_busy(dev) ||
(i2c_get_line_levels(dev) != I2C_LINE_IDLE)) {
return -EIO;
}
return 0;
}
static void i2c_reset(const struct device *dev)
{
const struct i2c_enhance_config *config = dev->config;
uint8_t *base = config->base;
/* State reset and hardware reset */
IT8XXX2_I2C_CTR(base) = E_STS_AND_HW_RST;
}
/* Set clock frequency for i2c port D, E , or F */
static void i2c_enhanced_port_set_frequency(const struct device *dev,
int freq_hz)
{
const struct i2c_enhance_config *config = dev->config;
uint32_t clk_div, psr, pll_clock;
uint8_t *base = config->base;
pll_clock = chip_get_pll_freq();
/*
* Let psr(Prescale) = IT8XXX2_I2C_PSR(p_ch)
* Then, 1 SCL cycle = 2 x (psr + 2) x SMBus clock cycle
* SMBus clock = pll_clock / clk_div
* SMBus clock cycle = 1 / SMBus clock
* 1 SCL cycle = 1 / freq
* 1 / freq = 2 x (psr + 2) x (1 / (pll_clock / clk_div))
* psr = ((pll_clock / clk_div) x (1 / freq) x (1 / 2)) - 2
*/
if (freq_hz) {
/* Get SMBus clock divide value */
clk_div = (IT8XXX2_ECPM_SCDCR2 & 0x0F) + 1U;
/* Calculate PSR value */
psr = (pll_clock / (clk_div * (2U * freq_hz))) - 2U;
/* Set psr value under 0xFD */
if (psr > 0xFD) {
psr = 0xFD;
}
/* Adjust SCL low period prescale */
psr += config->prescale_scl_low;
/* Set I2C Speed */
IT8XXX2_I2C_PSR(base) = psr & 0xFF;
IT8XXX2_I2C_HSPR(base) = psr & 0xFF;
}
}
static int i2c_enhance_configure(const struct device *dev,
uint32_t dev_config_raw)
{
const struct i2c_enhance_config *config = dev->config;
struct i2c_enhance_data *const data = dev->data;
if (!(I2C_MODE_MASTER & dev_config_raw)) {
return -EINVAL;
}
if (I2C_ADDR_10_BITS & dev_config_raw) {
return -EINVAL;
}
data->bus_freq = I2C_SPEED_GET(dev_config_raw);
i2c_enhanced_port_set_frequency(dev, config->bitrate);
return 0;
}
static int i2c_enhance_get_config(const struct device *dev, uint32_t *dev_config)
{
struct i2c_enhance_data *const data = dev->data;
uint32_t speed;
if (!data->bus_freq) {
LOG_ERR("The bus frequency is not initially configured.");
return -EIO;
}
switch (data->bus_freq) {
case I2C_SPEED_DT:
case I2C_SPEED_STANDARD:
case I2C_SPEED_FAST:
case I2C_SPEED_FAST_PLUS:
speed = I2C_SPEED_SET(data->bus_freq);
break;
default:
return -ERANGE;
}
*dev_config = (I2C_MODE_MASTER | speed);
return 0;
}
static int enhanced_i2c_error(const struct device *dev)
{
struct i2c_enhance_data *data = dev->data;
const struct i2c_enhance_config *config = dev->config;
uint8_t *base = config->base;
uint32_t i2c_str = IT8XXX2_I2C_STR(base);
if (i2c_str & E_HOSTA_ANY_ERROR) {
data->err = i2c_str & E_HOSTA_ANY_ERROR;
/* device does not respond ACK */
} else if ((i2c_str & E_HOSTA_BDS_AND_ACK) == E_HOSTA_BDS) {
if (IT8XXX2_I2C_CTR(base) & E_ACK)
data->err = E_HOSTA_ACK;
}
return data->err;
}
static void enhanced_i2c_start(const struct device *dev)
{
const struct i2c_enhance_config *config = dev->config;
uint8_t *base = config->base;
/* reset i2c port */
i2c_reset(dev);
/* Set i2c frequency */
i2c_enhanced_port_set_frequency(dev, config->bitrate);
/*
* Set time out register.
* I2C D/E/F clock/data low timeout.
*/
IT8XXX2_I2C_TOR(base) = I2C_CLK_LOW_TIMEOUT;
/* bit1: Enable enhanced i2c module */
IT8XXX2_I2C_CTR1(base) = IT8XXX2_I2C_MDL_EN;
}
static void i2c_pio_trans_data(const struct device *dev,
enum enhanced_i2c_transfer_direct direct,
uint16_t trans_data, int first_byte)
{
struct i2c_enhance_data *data = dev->data;
const struct i2c_enhance_config *config = dev->config;
uint8_t *base = config->base;
uint32_t nack = 0;
if (first_byte) {
/* First byte must be slave address. */
IT8XXX2_I2C_DTR(base) = trans_data |
(direct == RX_DIRECT ? BIT(0) : 0);
/* start or repeat start signal. */
IT8XXX2_I2C_CTR(base) = E_START_ID;
} else {
if (direct == TX_DIRECT) {
/* Transmit data */
IT8XXX2_I2C_DTR(base) = (uint8_t)trans_data;
} else {
/*
* Receive data.
* Last byte should be NACK in the end of read cycle
*/
if (((data->ridx + 1) == data->msgs->len) &&
(data->msgs->flags & I2C_MSG_STOP)) {
nack = 1;
}
}
/* Set hardware reset to start next transmission */
IT8XXX2_I2C_CTR(base) = E_INT_EN | E_MODE_SEL |
E_HW_RST | (nack ? 0 : E_ACK);
}
}
static int enhanced_i2c_tran_read(const struct device *dev)
{
struct i2c_enhance_data *data = dev->data;
const struct i2c_enhance_config *config = dev->config;
uint8_t *base = config->base;
uint8_t in_data = 0;
if (data->msgs->flags & I2C_MSG_START) {
/* clear start flag */
data->msgs->flags &= ~I2C_MSG_START;
enhanced_i2c_start(dev);
/* Direct read */
data->i2ccs = I2C_CH_WAIT_READ;
/* Send ID */
i2c_pio_trans_data(dev, RX_DIRECT, data->addr_16bit << 1, 1);
} else {
if (data->i2ccs) {
if (data->i2ccs == I2C_CH_WAIT_READ) {
data->i2ccs = I2C_CH_NORMAL;
/* Receive data */
i2c_pio_trans_data(dev, RX_DIRECT, in_data, 0);
/* data->msgs->flags == I2C_MSG_RESTART */
} else {
/* Write to read */
data->i2ccs = I2C_CH_WAIT_READ;
/* Send ID */
i2c_pio_trans_data(dev, RX_DIRECT,
data->addr_16bit << 1, 1);
}
} else {
if (data->ridx < data->msgs->len) {
/* read data */
*(data->msgs->buf++) = IT8XXX2_I2C_DRR(base);
data->ridx++;
/* done */
if (data->ridx == data->msgs->len) {
data->msgs->len = 0;
if (data->msgs->flags & I2C_MSG_STOP) {
data->i2ccs = I2C_CH_NORMAL;
IT8XXX2_I2C_CTR(base) = E_FINISH;
/* wait for stop bit interrupt */
data->stop = 1;
return 1;
}
/* End the transaction */
data->i2ccs = I2C_CH_WAIT_READ;
return 0;
}
/* read next byte */
i2c_pio_trans_data(dev, RX_DIRECT, in_data, 0);
}
}
}
return 1;
}
static int enhanced_i2c_tran_write(const struct device *dev)
{
struct i2c_enhance_data *data = dev->data;
const struct i2c_enhance_config *config = dev->config;
uint8_t *base = config->base;
uint8_t out_data;
if (data->msgs->flags & I2C_MSG_START) {
/* Clear start bit */
data->msgs->flags &= ~I2C_MSG_START;
enhanced_i2c_start(dev);
/* Send ID */
i2c_pio_trans_data(dev, TX_DIRECT, data->addr_16bit << 1, 1);
} else {
/* Host has completed the transmission of a byte */
if (data->widx < data->msgs->len) {
out_data = *(data->msgs->buf++);
data->widx++;
/* Send Byte */
i2c_pio_trans_data(dev, TX_DIRECT, out_data, 0);
if (data->i2ccs == I2C_CH_WAIT_NEXT_XFER) {
data->i2ccs = I2C_CH_NORMAL;
}
} else {
/* done */
data->msgs->len = 0;
if (data->msgs->flags & I2C_MSG_STOP) {
IT8XXX2_I2C_CTR(base) = E_FINISH;
/* wait for stop bit interrupt */
data->stop = 1;
} else {
/* Direct write with direct read */
data->i2ccs = I2C_CH_WAIT_NEXT_XFER;
return 0;
}
}
}
return 1;
}
static int i2c_transaction(const struct device *dev)
{
struct i2c_enhance_data *data = dev->data;
const struct i2c_enhance_config *config = dev->config;
uint8_t *base = config->base;
/* no error */
if (!(enhanced_i2c_error(dev))) {
if (!data->stop) {
/*
* The return value indicates if there is more data
* to be read or written. If the return value = 1,
* it means that the interrupt cannot be disable and
* continue to transmit data.
*/
if (data->msgs->flags & I2C_MSG_READ) {
return enhanced_i2c_tran_read(dev);
} else {
return enhanced_i2c_tran_write(dev);
}
}
}
/* reset i2c port */
i2c_reset(dev);
IT8XXX2_I2C_CTR1(base) = 0;
data->stop = 0;
/* done doing work */
return 0;
}
static int i2c_enhance_transfer(const struct device *dev, struct i2c_msg *msgs,
uint8_t num_msgs, uint16_t addr)
{
struct i2c_enhance_data *data = dev->data;
const struct i2c_enhance_config *config = dev->config;
int res;
/* Lock mutex of i2c controller */
k_mutex_lock(&data->mutex, K_FOREVER);
/*
* If the transaction of write to read is divided into two
* transfers, the repeat start transfer uses this flag to
* exclude checking bus busy.
*/
if (data->i2ccs == I2C_CH_NORMAL) {
/* Make sure we're in a good state to start */
if (i2c_bus_not_available(dev)) {
/* Recovery I2C bus */
i2c_recover_bus(dev);
/*
* After resetting I2C bus, if I2C bus is not available
* (No external pull-up), drop the transaction.
*/
if (i2c_bus_not_available(dev)) {
/* Unlock mutex of i2c controller */
k_mutex_unlock(&data->mutex);
return -EIO;
}
}
msgs->flags |= I2C_MSG_START;
}
for (int i = 0; i < num_msgs; i++) {
data->widx = 0;
data->ridx = 0;
data->err = 0;
data->msgs = &(msgs[i]);
data->addr_16bit = addr;
if (msgs->flags & I2C_MSG_START) {
data->i2ccs = I2C_CH_NORMAL;
}
/*
* Start transaction.
* The return value indicates if the initial configuration
* of I2C transaction for read or write has been completed.
*/
if (i2c_transaction(dev)) {
/* Enable I2C interrupt. */
irq_enable(config->i2c_irq_base);
}
/* Wait for the transfer to complete */
/* TODO: the timeout should be adjustable */
res = k_sem_take(&data->device_sync_sem, K_MSEC(100));
/*
* The irq will be enabled at the condition of start or
* repeat start of I2C. If timeout occurs without being
* wake up during suspend(ex: interrupt is not fired),
* the irq should be disabled immediately.
*/
irq_disable(config->i2c_irq_base);
/*
* The transaction is dropped on any error(timeout, NACK, fail,
* bus error, device error).
*/
if (data->err) {
break;
}
if (res != 0) {
data->err = ETIMEDOUT;
/* reset i2c port */
i2c_reset(dev);
LOG_ERR("I2C ch%d:0x%X reset cause %d",
config->port, data->addr_16bit, I2C_RC_TIMEOUT);
/* If this message is sent fail, drop the transaction. */
break;
}
}
/* reset i2c channel status */
if (data->err || (msgs->flags & I2C_MSG_STOP)) {
data->i2ccs = I2C_CH_NORMAL;
}
/* Unlock mutex of i2c controller */
k_mutex_unlock(&data->mutex);
return i2c_parsing_return_value(dev);
}
static void i2c_enhance_isr(void *arg)
{
struct device *dev = (struct device *)arg;
struct i2c_enhance_data *data = dev->data;
const struct i2c_enhance_config *config = dev->config;
/* If done doing work, wake up the task waiting for the transfer */
if (!i2c_transaction(dev)) {
irq_disable(config->i2c_irq_base);
k_sem_give(&data->device_sync_sem);
}
}
static int i2c_enhance_init(const struct device *dev)
{
struct i2c_enhance_data *data = dev->data;
const struct i2c_enhance_config *config = dev->config;
uint8_t *base = config->base;
uint32_t bitrate_cfg;
int error, status;
/* Initialize mutex and semaphore */
k_mutex_init(&data->mutex);
k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT);
/* Enable clock to specified peripheral */
volatile uint8_t *reg = (volatile uint8_t *)
(IT8XXX2_ECPM_BASE + (config->clock_gate_offset >> 8));
uint8_t reg_mask = config->clock_gate_offset & 0xff;
*reg &= ~reg_mask;
/* Enable I2C function */
/* Software reset */
IT8XXX2_I2C_DHTR(base) |= IT8XXX2_I2C_SOFT_RST;
IT8XXX2_I2C_DHTR(base) &= ~IT8XXX2_I2C_SOFT_RST;
/* reset i2c port */
i2c_reset(dev);
/* bit1, Module enable */
IT8XXX2_I2C_CTR1(base) = 0;
/* Set clock frequency for I2C ports */
if (config->bitrate == I2C_BITRATE_STANDARD ||
config->bitrate == I2C_BITRATE_FAST ||
config->bitrate == I2C_BITRATE_FAST_PLUS) {
bitrate_cfg = i2c_map_dt_bitrate(config->bitrate);
} else {
/* Device tree specified speed */
bitrate_cfg = I2C_SPEED_DT << I2C_SPEED_SHIFT;
}
error = i2c_enhance_configure(dev, I2C_MODE_MASTER | bitrate_cfg);
data->i2ccs = I2C_CH_NORMAL;
if (error) {
LOG_ERR("i2c: failure initializing");
return error;
}
/* Set the pin to I2C alternate function. */
status = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
if (status < 0) {
LOG_ERR("Failed to configure I2C pins");
return status;
}
return 0;
}
static int i2c_enhance_recover_bus(const struct device *dev)
{
const struct i2c_enhance_config *config = dev->config;
int i, status;
/* Set SCL of I2C as GPIO pin */
gpio_pin_configure_dt(&config->scl_gpios, GPIO_OUTPUT);
/* Set SDA of I2C as GPIO pin */
gpio_pin_configure_dt(&config->sda_gpios, GPIO_OUTPUT);
/*
* In I2C recovery bus, 1ms sleep interval for bitbanging i2c
* is mainly to ensure that gpio has enough time to go from
* low to high or high to low.
*/
/* Pull SCL and SDA pin to high */
gpio_pin_set_dt(&config->scl_gpios, 1);
gpio_pin_set_dt(&config->sda_gpios, 1);
k_msleep(1);
/* Start condition */
gpio_pin_set_dt(&config->sda_gpios, 0);
k_msleep(1);
gpio_pin_set_dt(&config->scl_gpios, 0);
k_msleep(1);
/* 9 cycles of SCL with SDA held high */
for (i = 0; i < 9; i++) {
/* SDA */
gpio_pin_set_dt(&config->sda_gpios, 1);
/* SCL */
gpio_pin_set_dt(&config->scl_gpios, 1);
k_msleep(1);
/* SCL */
gpio_pin_set_dt(&config->scl_gpios, 0);
k_msleep(1);
}
/* SDA */
gpio_pin_set_dt(&config->sda_gpios, 0);
k_msleep(1);
/* Stop condition */
gpio_pin_set_dt(&config->scl_gpios, 1);
k_msleep(1);
gpio_pin_set_dt(&config->sda_gpios, 1);
k_msleep(1);
/* Set GPIO back to I2C alternate function */
status = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
if (status < 0) {
LOG_ERR("Failed to configure I2C pins");
return status;
}
/* reset i2c port */
i2c_reset(dev);
LOG_ERR("I2C ch%d reset cause %d", config->port,
I2C_RC_NO_IDLE_FOR_START);
return 0;
}
static const struct i2c_driver_api i2c_enhance_driver_api = {
.configure = i2c_enhance_configure,
.get_config = i2c_enhance_get_config,
.transfer = i2c_enhance_transfer,
.recover_bus = i2c_enhance_recover_bus,
};
#define I2C_ITE_ENHANCE_INIT(inst) \
PINCTRL_DT_INST_DEFINE(inst); \
BUILD_ASSERT((DT_INST_PROP(inst, clock_frequency) == \
50000) || \
(DT_INST_PROP(inst, clock_frequency) == \
I2C_BITRATE_STANDARD) || \
(DT_INST_PROP(inst, clock_frequency) == \
I2C_BITRATE_FAST) || \
(DT_INST_PROP(inst, clock_frequency) == \
I2C_BITRATE_FAST_PLUS), "Not support I2C bit rate value"); \
static void i2c_enhance_config_func_##inst(void); \
\
static const struct i2c_enhance_config i2c_enhance_cfg_##inst = { \
.base = (uint8_t *)(DT_INST_REG_ADDR(inst)), \
.irq_config_func = i2c_enhance_config_func_##inst, \
.bitrate = DT_INST_PROP(inst, clock_frequency), \
.i2c_irq_base = DT_INST_IRQN(inst), \
.port = DT_INST_PROP(inst, port_num), \
.scl_gpios = GPIO_DT_SPEC_INST_GET(inst, scl_gpios), \
.sda_gpios = GPIO_DT_SPEC_INST_GET(inst, sda_gpios), \
.prescale_scl_low = DT_INST_PROP_OR(inst, prescale_scl_low, 0), \
.clock_gate_offset = DT_INST_PROP(inst, clock_gate_offset), \
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \
}; \
\
static struct i2c_enhance_data i2c_enhance_data_##inst; \
\
I2C_DEVICE_DT_INST_DEFINE(inst, i2c_enhance_init, \
NULL, \
&i2c_enhance_data_##inst, \
&i2c_enhance_cfg_##inst, \
POST_KERNEL, \
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
&i2c_enhance_driver_api); \
\
static void i2c_enhance_config_func_##inst(void) \
{ \
IRQ_CONNECT(DT_INST_IRQN(inst), \
0, \
i2c_enhance_isr, \
DEVICE_DT_INST_GET(inst), 0); \
}
DT_INST_FOREACH_STATUS_OKAY(I2C_ITE_ENHANCE_INIT)