diff --git a/CODEOWNERS b/CODEOWNERS index db1ea8653da..090d4da432c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -278,6 +278,7 @@ /drivers/hwinfo/ @alexanderwachter /drivers/i2c/i2c_common.c @sjg20 /drivers/i2c/i2c_emul.c @sjg20 +/drivers/i2c/i2c_ite_enhance.c @GTLin08 /drivers/i2c/i2c_ite_it8xxx2.c @GTLin08 /drivers/i2c/i2c_shell.c @nashif /drivers/i2c/Kconfig.i2c_emul @sjg20 diff --git a/drivers/i2c/CMakeLists.txt b/drivers/i2c/CMakeLists.txt index 0cd5ebd228c..4349e0ef8a9 100644 --- a/drivers/i2c/CMakeLists.txt +++ b/drivers/i2c/CMakeLists.txt @@ -11,6 +11,7 @@ zephyr_library_sources_ifdef(CONFIG_I2C_CC32XX i2c_cc32xx.c) zephyr_library_sources_ifdef(CONFIG_I2C_ESP32 i2c_esp32.c) zephyr_library_sources_ifdef(CONFIG_I2C_GPIO i2c_gpio.c) zephyr_library_sources_ifdef(CONFIG_I2C_ITE_IT8XXX2 i2c_ite_it8xxx2.c) +zephyr_library_sources_ifdef(CONFIG_I2C_ITE_ENHANCE i2c_ite_enhance.c) zephyr_library_sources_ifdef(CONFIG_I2C_IMX i2c_imx.c) zephyr_library_sources_ifdef(CONFIG_I2C_LPC11U6X i2c_lpc11u6x.c) zephyr_library_sources_ifdef(CONFIG_I2C_XEC i2c_mchp_xec.c) diff --git a/drivers/i2c/Kconfig.it8xxx2 b/drivers/i2c/Kconfig.it8xxx2 index 6f868100b99..0b25824557a 100644 --- a/drivers/i2c/Kconfig.it8xxx2 +++ b/drivers/i2c/Kconfig.it8xxx2 @@ -1,10 +1,22 @@ # Copyright (c) 2020 ITE Corporation. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 +DT_COMPAT_ITE_IT8XXX2_I2C := ite,it8xxx2-i2c +DT_COMPAT_ITE_ENHANCE_I2C := ite,enhance-i2c + config I2C_ITE_IT8XXX2 bool "ITE IT8XXX2 I2C driver" depends on SOC_IT8XXX2 + default $(dt_compat_enabled,$(DT_COMPAT_ITE_IT8XXX2_I2C)) help Enable I2C support on it8xxx2_evb. Supported Speeds: 100kHz, 400kHz and 1MHz. This driver supports repeated start. + +config I2C_ITE_ENHANCE + bool "ITE IT8XXX2 I2C enhance driver" + depends on SOC_IT8XXX2 + default $(dt_compat_enabled,$(DT_COMPAT_ITE_ENHANCE_I2C)) + help + This option can enable the enhance I2C + of IT8XXX2 and support three channels. diff --git a/drivers/i2c/i2c_ite_enhance.c b/drivers/i2c/i2c_ite_enhance.c new file mode 100644 index 00000000000..81a1f674895 --- /dev/null +++ b/drivers/i2c/i2c_ite_enhance.c @@ -0,0 +1,755 @@ +/* + * Copyright (c) 2022 ITE Corporation. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ite_enhance_i2c + +#include +#include +#include +#include +#include +#include +#include + +#include +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) + +/* + * Structure i2c_alts_cfg is about the alternate function + * setting of i2c, this config will be used at initial + * time and recover bus. + */ +struct i2c_alts_cfg { + /* Pinmux control group */ + const struct device *pinctrls; + /* GPIO pin */ + uint8_t pin; + /* Alternate function */ + uint8_t alt_fun; +}; + +struct i2c_enhance_config { + void (*irq_config_func)(void); + uint32_t bitrate; + uint8_t *base; + uint8_t i2c_irq_base; + uint8_t port; + /* I2C alternate configuration */ + const struct i2c_alts_cfg *alts_list; + /* GPIO handle */ + const struct device *gpio_dev; + 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; + + if (!(I2C_MODE_MASTER & dev_config_raw)) { + return -EINVAL; + } + + if (I2C_ADDR_10_BITS & dev_config_raw) { + return -EINVAL; + } + + 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_STANDARD: + speed = I2C_SPEED_SET(I2C_SPEED_STANDARD); + break; + case I2C_SPEED_FAST: + speed = I2C_SPEED_SET(I2C_SPEED_FAST); + break; + case I2C_SPEED_FAST_PLUS: + speed = I2C_SPEED_SET(I2C_SPEED_FAST_PLUS); + 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); + } + /* Turn on irq before next direct read */ + irq_enable(config->i2c_irq_base); + } 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; + irq_enable(config->i2c_irq_base); + } + } 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) { + /* i2c read */ + if (data->msgs->flags & I2C_MSG_READ) { + return enhanced_i2c_tran_read(dev); + /* i2c write */ + } 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; + /* enable i2c interrupt */ + irq_enable(config->i2c_irq_base); + } + /* Start transaction */ + i2c_transaction(dev); + /* 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)) { + k_sem_give(&data->device_sync_sem); + irq_disable(config->i2c_irq_base); + } +} + +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; + + /* 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 */ + bitrate_cfg = i2c_map_dt_bitrate(config->bitrate); + error = i2c_enhance_configure(dev, I2C_MODE_MASTER | bitrate_cfg); + data->i2ccs = I2C_CH_NORMAL; + + if (error) { + LOG_ERR("i2c: failure initializing"); + return error; + } + + /* The pin is set to I2C alternate function of SCL */ + pinmux_pin_set(config->alts_list[SCL].pinctrls, + config->alts_list[SCL].pin, + config->alts_list[SCL].alt_fun); + /* The pin is set to I2C alternate function of SDA */ + pinmux_pin_set(config->alts_list[SDA].pinctrls, + config->alts_list[SDA].pin, + config->alts_list[SDA].alt_fun); + + return 0; +} + +static int i2c_enhance_recover_bus(const struct device *dev) +{ + const struct i2c_enhance_config *config = dev->config; + int i; + + /* Set SCL of I2C as GPIO pin */ + pinmux_pin_input_enable(config->alts_list[SCL].pinctrls, + config->alts_list[SCL].pin, + PINMUX_OUTPUT_ENABLED); + /* Set SDA of I2C as GPIO pin */ + pinmux_pin_input_enable(config->alts_list[SDA].pinctrls, + config->alts_list[SDA].pin, + PINMUX_OUTPUT_ENABLED); + + /* + * 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(config->gpio_dev, config->alts_list[SCL].pin, 1); + gpio_pin_set(config->gpio_dev, config->alts_list[SDA].pin, 1); + k_msleep(1); + + /* Start condition */ + gpio_pin_set(config->gpio_dev, config->alts_list[SDA].pin, 0); + k_msleep(1); + gpio_pin_set(config->gpio_dev, config->alts_list[SCL].pin, 0); + k_msleep(1); + + /* 9 cycles of SCL with SDA held high */ + for (i = 0; i < 9; i++) { + /* SDA */ + gpio_pin_set(config->gpio_dev, config->alts_list[SDA].pin, 1); + /* SCL */ + gpio_pin_set(config->gpio_dev, config->alts_list[SCL].pin, 1); + k_msleep(1); + /* SCL */ + gpio_pin_set(config->gpio_dev, config->alts_list[SCL].pin, 0); + k_msleep(1); + } + /* SDA */ + gpio_pin_set(config->gpio_dev, config->alts_list[SDA].pin, 0); + k_msleep(1); + + /* Stop condition */ + gpio_pin_set(config->gpio_dev, config->alts_list[SCL].pin, 1); + k_msleep(1); + gpio_pin_set(config->gpio_dev, config->alts_list[SDA].pin, 1); + k_msleep(1); + + /* Set GPIO back to I2C alternate function of SCL */ + pinmux_pin_set(config->alts_list[SCL].pinctrls, + config->alts_list[SCL].pin, + config->alts_list[SCL].alt_fun); + /* Set GPIO back to I2C alternate function of SDA */ + pinmux_pin_set(config->alts_list[SDA].pinctrls, + config->alts_list[SDA].pin, + config->alts_list[SDA].alt_fun); + + /* 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) \ + static void i2c_enhance_config_func_##inst(void); \ + static const struct i2c_alts_cfg \ + i2c_alts_##inst[DT_INST_NUM_PINCTRLS_BY_IDX(inst, 0)] = \ + IT8XXX2_DT_ALT_ITEMS_LIST(inst); \ + \ + 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), \ + .alts_list = i2c_alts_##inst, \ + .gpio_dev = DEVICE_DT_GET(DT_INST_PHANDLE(inst, gpio_dev)), \ + .prescale_scl_low = DT_INST_PROP_OR(inst, prescale_scl_low, 0), \ + .clock_gate_offset = DT_INST_PROP(inst, clock_gate_offset), \ + }; \ + \ + 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) diff --git a/drivers/i2c/i2c_ite_it8xxx2.c b/drivers/i2c/i2c_ite_it8xxx2.c index 26de042255f..b1e34733310 100644 --- a/drivers/i2c/i2c_ite_it8xxx2.c +++ b/drivers/i2c/i2c_ite_it8xxx2.c @@ -10,16 +10,21 @@ #include #include #include -#include - LOG_MODULE_REGISTER(i2c_ite_it8xxx2); -#include "i2c-priv.h" #include #include #include -#define I2C_STANDARD_PORT_COUNT 3 -/* Default PLL frequency. */ -#define PLL_CLOCK 48000000 +#include +LOG_MODULE_REGISTER(i2c_ite_it8xxx2, 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) /* * Structure i2c_alts_cfg is about the alternate function @@ -45,6 +50,7 @@ struct i2c_it8xxx2_config { const struct i2c_alts_cfg *alts_list; /* GPIO handle */ const struct device *gpio_dev; + uint32_t clock_gate_offset; }; enum i2c_pin_fun { @@ -80,57 +86,30 @@ struct i2c_it8xxx2_data { 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, +enum i2c_host_status { + /* Host busy */ + HOSTA_HOBY = 0x01, + /* Finish Interrupt */ + HOSTA_FINTR = 0x02, + /* Device error */ + HOSTA_DVER = 0x04, + /* Bus error */ + HOSTA_BSER = 0x08, + /* Fail */ + HOSTA_FAIL = 0x10, + /* Not response ACK */ + HOSTA_NACK = 0x20, + /* Time-out error */ + HOSTA_TMOE = 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), + HOSTA_BDS = 0x80, + /* Error bit is set */ + HOSTA_ANY_ERROR = (HOSTA_DVER | HOSTA_BSER | HOSTA_FAIL | + HOSTA_NACK | HOSTA_TMOE), + /* W/C for next byte */ + HOSTA_NEXT_BYTE = HOSTA_BDS, + /* W/C host status register */ + HOSTA_ALL_WC_BIT = (HOSTA_FINTR | HOSTA_ANY_ERROR | HOSTA_BDS), }; enum i2c_reset_cause { @@ -138,37 +117,24 @@ enum i2c_reset_cause { I2C_RC_TIMEOUT, }; -/* 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) - static int i2c_parsing_return_value(const struct device *dev) { struct i2c_it8xxx2_data *data = dev->data; - const struct i2c_it8xxx2_config *config = dev->config; - if (!data->err) + if (!data->err) { return 0; + } /* Connection timed out */ - if (data->err == ETIMEDOUT) + if (data->err == ETIMEDOUT) { return -ETIMEDOUT; + } - if (config->port < I2C_STANDARD_PORT_COUNT) { - /* The device does not respond ACK */ - if (data->err == HOSTA_NACK) - return -ENXIO; - else - return -EIO; + /* The device does not respond ACK */ + if (data->err == HOSTA_NACK) { + return -ENXIO; } else { - /* The device does not respond ACK */ - if (data->err == E_HOSTA_ACK) - return -ENXIO; - else - return -EIO; + return -EIO; } } @@ -176,21 +142,9 @@ static int i2c_get_line_levels(const struct device *dev) { const struct i2c_it8xxx2_config *config = dev->config; uint8_t *base = config->base; - int pin_sts = 0; - if (config->port < I2C_STANDARD_PORT_COUNT) { - return IT83XX_SMB_SMBPCTL(base) & 0x03; - } - - if (IT83XX_I2C_TOS(base) & IT8XXX2_I2C_SCL_IN) { - pin_sts |= I2C_LINE_SCL_HIGH; - } - - if (IT83XX_I2C_TOS(base) & IT8XXX2_I2C_SDA_IN) { - pin_sts |= I2C_LINE_SDA_HIGH; - } - - return pin_sts; + return (IT8XXX2_SMB_SMBPCTL(base) & + (IT8XXX2_SMB_SMBDCS | IT8XXX2_SMB_SMBCS)); } static int i2c_is_busy(const struct device *dev) @@ -198,12 +152,8 @@ static int i2c_is_busy(const struct device *dev) const struct i2c_it8xxx2_config *config = dev->config; uint8_t *base = config->base; - if (config->port < I2C_STANDARD_PORT_COUNT) { - return (IT83XX_SMB_HOSTA(base) & - (HOSTA_HOBY | HOSTA_ALL_WC_BIT)); - } - - return (IT83XX_I2C_STR(base) & E_HOSTA_BB); + return (IT8XXX2_SMB_HOSTA(base) & + (HOSTA_HOBY | HOSTA_ALL_WC_BIT)); } static int i2c_bus_not_available(const struct device *dev) @@ -221,16 +171,11 @@ static void i2c_reset(const struct device *dev) const struct i2c_it8xxx2_config *config = dev->config; uint8_t *base = config->base; - if (config->port < I2C_STANDARD_PORT_COUNT) { - /* bit1, kill current transaction. */ - IT83XX_SMB_HOCTL(base) = 0x2; - IT83XX_SMB_HOCTL(base) = 0; - /* W/C host status register */ - IT83XX_SMB_HOSTA(base) = HOSTA_ALL_WC_BIT; - } else { - /* State reset and hardware reset */ - IT83XX_I2C_CTR(base) = E_STS_AND_HW_RST; - } + /* bit1, kill current transaction. */ + IT8XXX2_SMB_HOCTL(base) = IT8XXX2_SMB_KILL; + IT8XXX2_SMB_HOCTL(base) = 0; + /* W/C host status register */ + IT8XXX2_SMB_HOSTA(base) = HOSTA_ALL_WC_BIT; } /* @@ -240,20 +185,20 @@ static void i2c_reset(const struct device *dev) static void i2c_standard_port_timing_regs_400khz(uint8_t port) { /* Port clock frequency depends on setting of timing registers. */ - IT83XX_SMB_SCLKTS(port) = 0; + IT8XXX2_SMB_SCLKTS(port) = 0; /* Suggested setting of timing registers of 400kHz. */ - IT83XX_SMB_4P7USL = 0x6; - IT83XX_SMB_4P0USL = 0; - IT83XX_SMB_300NS = 0x1; - IT83XX_SMB_250NS = 0x2; - IT83XX_SMB_45P3USL = 0x6a; - IT83XX_SMB_45P3USH = 0x1; - IT83XX_SMB_4P7A4P0H = 0; + IT8XXX2_SMB_4P7USL = 0x6; + IT8XXX2_SMB_4P0USL = 0; + IT8XXX2_SMB_300NS = 0x1; + IT8XXX2_SMB_250NS = 0x2; + IT8XXX2_SMB_45P3USL = 0x6a; + IT8XXX2_SMB_45P3USH = 0x1; + IT8XXX2_SMB_4P7A4P0H = 0; } /* Set clock frequency for i2c port A, B , or C */ static void i2c_standard_port_set_frequency(const struct device *dev, - int freq_khz, int freq_set) + int freq_hz, int freq_set) { const struct i2c_it8xxx2_config *config = dev->config; @@ -262,61 +207,22 @@ static void i2c_standard_port_set_frequency(const struct device *dev, * for setting. So we can adjust tlow to meet timing. * The others use basic 50/100/1000 KHz setting. */ - if (freq_khz == 400) { + if (freq_hz == I2C_BITRATE_FAST) { i2c_standard_port_timing_regs_400khz(config->port); } else { - IT83XX_SMB_SCLKTS(config->port) = freq_set; + IT8XXX2_SMB_SCLKTS(config->port) = freq_set; } /* This field defines the SMCLK0/1/2 clock/data low timeout. */ - IT83XX_SMB_25MS = I2C_CLK_LOW_TIMEOUT; -} - -/* Set clock frequency for i2c port D, E , or F */ -static void i2c_enhanced_port_set_frequency(const struct device *dev, - int freq_khz) -{ - struct i2c_it8xxx2_data *data = dev->data; - const struct i2c_it8xxx2_config *config = dev->config; - uint32_t clk_div, psr; - uint8_t *base = config->base; - - /* - * Let psr(Prescale) = IT83XX_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 / (1000 x freq) - * 1 / (1000 x freq) = - * 2 x (psr + 2) x (1 / (PLL_CLOCK / clk_div)) - * psr = ((PLL_CLOCK / clk_div) x - * (1 / (1000 x freq)) x (1 / 2)) - 2 - */ - if (freq_khz) { - /* Get SMBus clock divide value */ - clk_div = (SCDCR2 & 0x0F) + 1U; - /* Calculate PSR value */ - psr = (PLL_CLOCK / (clk_div * (2U * 1000U * freq_khz))) - 2U; - /* Set psr value under 0xFD */ - if (psr > 0xFD) { - psr = 0xFD; - } - - /* Set I2C Speed */ - IT83XX_I2C_PSR(base) = psr & 0xFF; - IT83XX_I2C_HSPR(base) = psr & 0xFF; - /* Backup */ - data->freq = psr & 0xFF; - } - + IT8XXX2_SMB_25MS = I2C_CLK_LOW_TIMEOUT; } static int i2c_it8xxx2_configure(const struct device *dev, - uint32_t dev_config_raw) + uint32_t dev_config_raw) { const struct i2c_it8xxx2_config *config = dev->config; struct i2c_it8xxx2_data *const data = dev->data; - uint32_t freq, freq_set; + uint32_t freq_set; if (!(I2C_MODE_MASTER & dev_config_raw)) { return -EINVAL; @@ -330,26 +236,19 @@ static int i2c_it8xxx2_configure(const struct device *dev, switch (data->bus_freq) { case I2C_SPEED_STANDARD: - freq = 100; - freq_set = 2; + freq_set = IT8XXX2_SMB_SMCLKS_100K; break; case I2C_SPEED_FAST: - freq = 400; - freq_set = 3; + freq_set = IT8XXX2_SMB_SMCLKS_400K; break; case I2C_SPEED_FAST_PLUS: - freq = 1000; - freq_set = 4; + freq_set = IT8XXX2_SMB_SMCLKS_1M; break; default: return -EINVAL; } - if (config->port < I2C_STANDARD_PORT_COUNT) { - i2c_standard_port_set_frequency(dev, freq, freq_set); - } else { - i2c_enhanced_port_set_frequency(dev, freq); - } + i2c_standard_port_set_frequency(dev, config->bitrate, freq_set); return 0; } @@ -384,180 +283,6 @@ static int i2c_it8xxx2_get_config(const struct device *dev, return 0; } -static int enhanced_i2c_error(const struct device *dev) -{ - struct i2c_it8xxx2_data *data = dev->data; - const struct i2c_it8xxx2_config *config = dev->config; - uint8_t *base = config->base; - uint32_t i2c_str = IT83XX_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 (IT83XX_I2C_CTR(base) & E_ACK) - data->err = E_HOSTA_ACK; - } - - return data->err; -} - -static void enhanced_i2c_start(const struct device *dev) -{ - struct i2c_it8xxx2_data *data = dev->data; - const struct i2c_it8xxx2_config *config = dev->config; - uint8_t *base = config->base; - - /* State reset and hardware reset */ - IT83XX_I2C_CTR(base) = E_STS_AND_HW_RST; - /* Set i2c frequency */ - IT83XX_I2C_PSR(base) = data->freq; - IT83XX_I2C_HSPR(base) = data->freq; - /* - * Set time out register. - * I2C D/E/F clock/data low timeout. - */ - IT83XX_I2C_TOR(base) = I2C_CLK_LOW_TIMEOUT; - /* bit1: Enable enhanced i2c module */ - IT83XX_I2C_CTR1(base) = BIT(1); -} - -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_it8xxx2_data *data = dev->data; - const struct i2c_it8xxx2_config *config = dev->config; - uint8_t *base = config->base; - uint32_t nack = 0; - - if (first_byte) { - /* First byte must be slave address. */ - IT83XX_I2C_DTR(base) = trans_data | - (direct == RX_DIRECT ? BIT(0) : 0); - /* start or repeat start signal. */ - IT83XX_I2C_CTR(base) = E_START_ID; - } else { - if (direct == TX_DIRECT) { - /* Transmit data */ - IT83XX_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 */ - IT83XX_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_it8xxx2_data *data = dev->data; - const struct i2c_it8xxx2_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); - } - /* Turn on irq before next direct read */ - irq_enable(config->i2c_irq_base); - } else { - if (data->ridx < data->msgs->len) { - /* read data */ - *(data->msgs->buf++) = IT83XX_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; - IT83XX_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_it8xxx2_data *data = dev->data; - const struct i2c_it8xxx2_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; - irq_enable(config->i2c_irq_base); - } - } else { - /* done */ - data->msgs->len = 0; - if (data->msgs->flags & I2C_MSG_STOP) { - IT83XX_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 void i2c_r_last_byte(const struct device *dev) { struct i2c_it8xxx2_data *data = dev->data; @@ -569,8 +294,8 @@ static void i2c_r_last_byte(const struct device *dev) * when the next byte will be the last byte for i2c read. */ if ((data->msgs->flags & I2C_MSG_STOP) && - (data->ridx == data->msgs->len - 1)) { - IT83XX_SMB_HOCTL(base) |= 0x20; + (data->ridx == data->msgs->len - 1)) { + IT8XXX2_SMB_HOCTL(base) |= IT8XXX2_SMB_LABY; } } @@ -580,18 +305,19 @@ static void i2c_w2r_change_direction(const struct device *dev) uint8_t *base = config->base; /* I2C switch direction */ - if (IT83XX_SMB_HOCTL2(base) & 0x08) { + if (IT8XXX2_SMB_HOCTL2(base) & IT8XXX2_SMB_I2C_SW_EN) { i2c_r_last_byte(dev); - IT83XX_SMB_HOSTA(base) = HOSTA_NEXT_BYTE; + IT8XXX2_SMB_HOSTA(base) = HOSTA_NEXT_BYTE; } else { /* * bit2, I2C switch direction wait. * bit3, I2C switch direction enable. */ - IT83XX_SMB_HOCTL2(base) |= 0x0C; - IT83XX_SMB_HOSTA(base) = HOSTA_NEXT_BYTE; + IT8XXX2_SMB_HOCTL2(base) |= IT8XXX2_SMB_I2C_SW_EN | + IT8XXX2_SMB_I2C_SW_WAIT; + IT8XXX2_SMB_HOSTA(base) = HOSTA_NEXT_BYTE; i2c_r_last_byte(dev); - IT83XX_SMB_HOCTL2(base) &= ~0x04; + IT8XXX2_SMB_HOCTL2(base) &= ~IT8XXX2_SMB_I2C_SW_WAIT; } } @@ -603,12 +329,15 @@ static int i2c_tran_read(const struct device *dev) if (data->msgs->flags & I2C_MSG_START) { /* i2c enable */ - IT83XX_SMB_HOCTL2(base) = 0x13; + IT8XXX2_SMB_HOCTL2(base) = IT8XXX2_SMB_SMD_TO_EN | + IT8XXX2_SMB_I2C_EN | + IT8XXX2_SMB_SMHEN; /* * bit0, Direction of the host transfer. * bit[1:7}, Address of the targeted slave. */ - IT83XX_SMB_TRASLA(base) = (uint8_t)(data->addr_16bit << 1) | 0x01; + IT8XXX2_SMB_TRASLA(base) = (uint8_t)(data->addr_16bit << 1) | + IT8XXX2_SMB_DIR; /* clear start flag */ data->msgs->flags &= ~I2C_MSG_START; /* @@ -619,14 +348,19 @@ static int i2c_tran_read(const struct device *dev) * bit6, start. */ if ((data->msgs->len == 1) && - (data->msgs->flags & I2C_MSG_STOP)) { - IT83XX_SMB_HOCTL(base) = 0x7D; + (data->msgs->flags & I2C_MSG_STOP)) { + IT8XXX2_SMB_HOCTL(base) = IT8XXX2_SMB_SRT | + IT8XXX2_SMB_LABY | + IT8XXX2_SMB_SMCD_EXTND | + IT8XXX2_SMB_INTREN; } else { - IT83XX_SMB_HOCTL(base) = 0x5D; + IT8XXX2_SMB_HOCTL(base) = IT8XXX2_SMB_SRT | + IT8XXX2_SMB_SMCD_EXTND | + IT8XXX2_SMB_INTREN; } } else { if ((data->i2ccs == I2C_CH_REPEAT_START) || - (data->i2ccs == I2C_CH_WAIT_READ)) { + (data->i2ccs == I2C_CH_WAIT_READ)) { if (data->i2ccs == I2C_CH_REPEAT_START) { /* write to read */ i2c_w2r_change_direction(dev); @@ -634,14 +368,14 @@ static int i2c_tran_read(const struct device *dev) /* For last byte */ i2c_r_last_byte(dev); /* W/C for next byte */ - IT83XX_SMB_HOSTA(base) = HOSTA_NEXT_BYTE; + IT8XXX2_SMB_HOSTA(base) = HOSTA_NEXT_BYTE; } data->i2ccs = I2C_CH_NORMAL; irq_enable(config->i2c_irq_base); - } else if (IT83XX_SMB_HOSTA(base) & HOSTA_BDS) { + } else if (IT8XXX2_SMB_HOSTA(base) & HOSTA_BDS) { if (data->ridx < data->msgs->len) { /* To get received data. */ - *(data->msgs->buf++) = IT83XX_SMB_HOBDB(base); + *(data->msgs->buf++) = IT8XXX2_SMB_HOBDB(base); data->ridx++; /* For last byte */ i2c_r_last_byte(dev); @@ -650,7 +384,7 @@ static int i2c_tran_read(const struct device *dev) data->msgs->len = 0; if (data->msgs->flags & I2C_MSG_STOP) { /* W/C for finish */ - IT83XX_SMB_HOSTA(base) = + IT8XXX2_SMB_HOSTA(base) = HOSTA_NEXT_BYTE; data->stop = 1; @@ -660,7 +394,7 @@ static int i2c_tran_read(const struct device *dev) } } else { /* W/C for next byte */ - IT83XX_SMB_HOSTA(base) = + IT8XXX2_SMB_HOSTA(base) = HOSTA_NEXT_BYTE; } } @@ -678,14 +412,16 @@ static int i2c_tran_write(const struct device *dev) if (data->msgs->flags & I2C_MSG_START) { /* i2c enable */ - IT83XX_SMB_HOCTL2(base) = 0x13; + IT8XXX2_SMB_HOCTL2(base) = IT8XXX2_SMB_SMD_TO_EN | + IT8XXX2_SMB_I2C_EN | + IT8XXX2_SMB_SMHEN; /* * bit0, Direction of the host transfer. * bit[1:7}, Address of the targeted slave. */ - IT83XX_SMB_TRASLA(base) = (uint8_t)data->addr_16bit << 1; + IT8XXX2_SMB_TRASLA(base) = (uint8_t)data->addr_16bit << 1; /* Send first byte */ - IT83XX_SMB_HOBDB(base) = *(data->msgs->buf++); + IT8XXX2_SMB_HOBDB(base) = *(data->msgs->buf++); data->widx++; /* clear start flag */ @@ -695,17 +431,19 @@ static int i2c_tran_write(const struct device *dev) * bit[2:4}, Extend command. * bit6, start. */ - IT83XX_SMB_HOCTL(base) = 0x5D; + IT8XXX2_SMB_HOCTL(base) = IT8XXX2_SMB_SRT | + IT8XXX2_SMB_SMCD_EXTND | + IT8XXX2_SMB_INTREN; } else { /* Host has completed the transmission of a byte */ - if (IT83XX_SMB_HOSTA(base) & HOSTA_BDS) { + if (IT8XXX2_SMB_HOSTA(base) & HOSTA_BDS) { if (data->widx < data->msgs->len) { /* Send next byte */ - IT83XX_SMB_HOBDB(base) = *(data->msgs->buf++); + IT8XXX2_SMB_HOBDB(base) = *(data->msgs->buf++); data->widx++; /* W/C byte done for next byte */ - IT83XX_SMB_HOSTA(base) = HOSTA_NEXT_BYTE; + IT8XXX2_SMB_HOSTA(base) = HOSTA_NEXT_BYTE; if (data->i2ccs == I2C_CH_REPEAT_START) { data->i2ccs = I2C_CH_NORMAL; @@ -716,10 +454,10 @@ static int i2c_tran_write(const struct device *dev) data->msgs->len = 0; if (data->msgs->flags & I2C_MSG_STOP) { /* set I2C_EN = 0 */ - IT83XX_SMB_HOCTL2(base) = 0x11; + IT8XXX2_SMB_HOCTL2(base) = IT8XXX2_SMB_SMD_TO_EN | + IT8XXX2_SMB_SMHEN; /* W/C byte done for finish */ - IT83XX_SMB_HOSTA(base) = - HOSTA_NEXT_BYTE; + IT8XXX2_SMB_HOSTA(base) = HOSTA_NEXT_BYTE; data->stop = 1; } else { @@ -739,69 +477,39 @@ static int i2c_transaction(const struct device *dev) const struct i2c_it8xxx2_config *config = dev->config; uint8_t *base = config->base; - if (config->port < I2C_STANDARD_PORT_COUNT) { - /* any error */ - if (IT83XX_SMB_HOSTA(base) & HOSTA_ANY_ERROR) { - data->err = (IT83XX_SMB_HOSTA(base) & HOSTA_ANY_ERROR); - } else { - if (!data->stop) { - if (data->msgs->flags & I2C_MSG_READ) { - return i2c_tran_read(dev); - } else { - return i2c_tran_write(dev); - } - } - /* wait finish */ - if (!(IT83XX_SMB_HOSTA(base) & HOSTA_FINTR)) { - return 1; - } - } - /* W/C */ - IT83XX_SMB_HOSTA(base) = HOSTA_ALL_WC_BIT; - /* disable the SMBus host interface */ - IT83XX_SMB_HOCTL2(base) = 0x00; + /* any error */ + if (IT8XXX2_SMB_HOSTA(base) & HOSTA_ANY_ERROR) { + data->err = (IT8XXX2_SMB_HOSTA(base) & HOSTA_ANY_ERROR); } else { - - /* no error */ - if (!(enhanced_i2c_error(dev))) { - if (!data->stop) { - /* i2c read */ - if (data->msgs->flags & I2C_MSG_READ) { - return enhanced_i2c_tran_read(dev); - /* i2c write */ - } else { - return enhanced_i2c_tran_write(dev); - } + if (!data->stop) { + if (data->msgs->flags & I2C_MSG_READ) { + return i2c_tran_read(dev); + } else { + return i2c_tran_write(dev); } } - IT83XX_I2C_CTR(base) = E_STS_AND_HW_RST; - IT83XX_I2C_CTR1(base) = 0; + /* wait finish */ + if (!(IT8XXX2_SMB_HOSTA(base) & HOSTA_FINTR)) { + return 1; + } } + /* W/C */ + IT8XXX2_SMB_HOSTA(base) = HOSTA_ALL_WC_BIT; + /* disable the SMBus host interface */ + IT8XXX2_SMB_HOCTL2(base) = 0x00; + data->stop = 0; /* done doing work */ return 0; } static int i2c_it8xxx2_transfer(const struct device *dev, struct i2c_msg *msgs, - uint8_t num_msgs, uint16_t addr) + uint8_t num_msgs, uint16_t addr) { - struct i2c_it8xxx2_data *data; - const struct i2c_it8xxx2_config *config; + struct i2c_it8xxx2_data *data = dev->data; + const struct i2c_it8xxx2_config *config = dev->config; int res; - /* Check for NULL pointers */ - if (dev == NULL) { - LOG_ERR("Device handle is NULL"); - return -EINVAL; - } - if (msgs == NULL) { - LOG_ERR("Device message is NULL"); - return -EINVAL; - } - - data = dev->data; - config = dev->config; - /* Lock mutex of i2c controller */ k_mutex_lock(&data->mutex, K_FOREVER); /* @@ -857,15 +565,16 @@ static int i2c_it8xxx2_transfer(const struct device *dev, struct i2c_msg *msgs, * The transaction is dropped on any error(timeout, NACK, fail, * bus error, device error). */ - if (data->err) + if (data->err) { break; + } if (res != 0) { data->err = ETIMEDOUT; /* reset i2c port */ i2c_reset(dev); - printk("I2C ch%d:0x%X reset cause %d\n", - config->port, data->addr_16bit, I2C_RC_TIMEOUT); + 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; } @@ -898,7 +607,7 @@ static int i2c_it8xxx2_init(const struct device *dev) struct i2c_it8xxx2_data *data = dev->data; const struct i2c_it8xxx2_config *config = dev->config; uint8_t *base = config->base; - uint32_t bitrate_cfg, offset = 0; + uint32_t bitrate_cfg; int error; /* @@ -912,68 +621,34 @@ static int i2c_it8xxx2_init(const struct device *dev) k_mutex_init(&data->mutex); k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT); - switch ((uint32_t)base) { - case DT_REG_ADDR(DT_NODELABEL(i2c0)): - offset = CGC_OFFSET_SMBA; - break; - case DT_REG_ADDR(DT_NODELABEL(i2c1)): - offset = CGC_OFFSET_SMBB; - break; - case DT_REG_ADDR(DT_NODELABEL(i2c2)): - offset = CGC_OFFSET_SMBC; - break; - case DT_REG_ADDR(DT_NODELABEL(i2c3)): - offset = CGC_OFFSET_SMBD; - break; - case DT_REG_ADDR(DT_NODELABEL(i2c4)): - offset = CGC_OFFSET_SMBE; - /* Enable SMBus E channel */ - PMER1 |= 0x01; - break; - case DT_REG_ADDR(DT_NODELABEL(i2c5)): - offset = CGC_OFFSET_SMBF; - /* Enable SMBus F channel */ - PMER1 |= 0x02; - break; - } - - /* Enable I2C function. */ + /* Enable clock to specified peripheral */ volatile uint8_t *reg = (volatile uint8_t *) - (IT83XX_ECPM_BASE + (offset >> 8)); - uint8_t reg_mask = offset & 0xff; + (IT8XXX2_ECPM_BASE + (config->clock_gate_offset >> 8)); + uint8_t reg_mask = config->clock_gate_offset & 0xff; *reg &= ~reg_mask; - if (config->port < I2C_STANDARD_PORT_COUNT) { - /* - * bit0, The SMBus host interface is enabled. - * bit1, Enable to communicate with I2C device - * and support I2C-compatible cycles. - * bit4, This bit controls the reset mechanism - * of SMBus master to handle the SMDAT - * line low if 25ms reg timeout. - */ - IT83XX_SMB_HOCTL2(base) = 0x11; - /* - * bit1, Kill SMBus host transaction. - * bit0, Enable the interrupt for the master interface. - */ - IT83XX_SMB_HOCTL(base) = 0x03; - IT83XX_SMB_HOCTL(base) = 0x01; + /* Enable SMBus function */ + /* + * bit0, The SMBus host interface is enabled. + * bit1, Enable to communicate with I2C device + * and support I2C-compatible cycles. + * bit4, This bit controls the reset mechanism + * of SMBus master to handle the SMDAT + * line low if 25ms reg timeout. + */ + IT8XXX2_SMB_HOCTL2(base) = IT8XXX2_SMB_SMD_TO_EN | IT8XXX2_SMB_SMHEN; + /* + * bit1, Kill SMBus host transaction. + * bit0, Enable the interrupt for the master interface. + */ + IT8XXX2_SMB_HOCTL(base) = IT8XXX2_SMB_KILL | IT8XXX2_SMB_SMHEN; + IT8XXX2_SMB_HOCTL(base) = IT8XXX2_SMB_SMHEN; - /* W/C host status register */ - IT83XX_SMB_HOSTA(base) = HOSTA_ALL_WC_BIT; - IT83XX_SMB_HOCTL2(base) = 0x00; - - } else { - /* Software reset */ - IT83XX_I2C_DHTR(base) |= 0x80; - IT83XX_I2C_DHTR(base) &= 0x7F; - /* State reset and hardware reset */ - IT83XX_I2C_CTR(base) = E_STS_AND_HW_RST; - /* bit1, Module enable */ - IT83XX_I2C_CTR1(base) = 0; - } + /* W/C host status register */ + IT8XXX2_SMB_HOSTA(base) = HOSTA_ALL_WC_BIT; + IT8XXX2_SMB_HOCTL2(base) = 0x00; + /* Set clock frequency for I2C ports */ bitrate_cfg = i2c_map_dt_bitrate(config->bitrate); error = i2c_it8xxx2_configure(dev, I2C_MODE_MASTER | bitrate_cfg); data->i2ccs = I2C_CH_NORMAL; @@ -1009,6 +684,11 @@ static int i2c_it8xxx2_recover_bus(const struct device *dev) config->alts_list[SDA].pin, PINMUX_OUTPUT_ENABLED); + /* + * 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(config->gpio_dev, config->alts_list[SCL].pin, 1); gpio_pin_set(config->gpio_dev, config->alts_list[SDA].pin, 1); @@ -1052,8 +732,8 @@ static int i2c_it8xxx2_recover_bus(const struct device *dev) /* reset i2c port */ i2c_reset(dev); - printk("I2C ch%d reset cause %d\n", config->port, - I2C_RC_NO_IDLE_FOR_START); + LOG_ERR("I2C ch%d reset cause %d", config->port, + I2C_RC_NO_IDLE_FOR_START); return 0; } @@ -1065,37 +745,39 @@ static const struct i2c_driver_api i2c_it8xxx2_driver_api = { .recover_bus = i2c_it8xxx2_recover_bus, }; -#define I2C_ITE_IT8XXX2_INIT(idx) \ - static void i2c_it8xxx2_config_func_##idx(void); \ - static const struct i2c_alts_cfg \ - i2c_alts_##idx[DT_INST_NUM_PINCTRLS_BY_IDX(idx, 0)] = \ - IT8XXX2_DT_ALT_ITEMS_LIST(idx); \ - \ - static const struct i2c_it8xxx2_config i2c_it8xxx2_cfg_##idx = { \ - .base = (uint8_t *)(DT_INST_REG_ADDR(idx)), \ - .irq_config_func = i2c_it8xxx2_config_func_##idx, \ - .bitrate = DT_INST_PROP(idx, clock_frequency), \ - .i2c_irq_base = DT_INST_IRQN(idx), \ - .port = DT_INST_PROP(idx, port_num), \ - .alts_list = i2c_alts_##idx, \ - .gpio_dev = DEVICE_DT_GET(DT_INST_PHANDLE(idx, gpio_dev)), \ - }; \ - \ - static struct i2c_it8xxx2_data i2c_it8xxx2_data_##idx; \ - \ - I2C_DEVICE_DT_INST_DEFINE(idx, \ - i2c_it8xxx2_init, NULL, \ - &i2c_it8xxx2_data_##idx, \ - &i2c_it8xxx2_cfg_##idx, POST_KERNEL, \ - CONFIG_I2C_INIT_PRIORITY, \ - &i2c_it8xxx2_driver_api); \ - \ - static void i2c_it8xxx2_config_func_##idx(void) \ - { \ - IRQ_CONNECT(DT_INST_IRQN(idx), \ - 0, \ - i2c_it8xxx2_isr, \ - DEVICE_DT_INST_GET(idx), 0); \ +#define I2C_ITE_IT8XXX2_INIT(inst) \ + static void i2c_it8xxx2_config_func_##inst(void); \ + static const struct i2c_alts_cfg \ + i2c_alts_##inst[DT_INST_NUM_PINCTRLS_BY_IDX(inst, 0)] = \ + IT8XXX2_DT_ALT_ITEMS_LIST(inst); \ + \ + static const struct i2c_it8xxx2_config i2c_it8xxx2_cfg_##inst = { \ + .base = (uint8_t *)(DT_INST_REG_ADDR(inst)), \ + .irq_config_func = i2c_it8xxx2_config_func_##inst, \ + .bitrate = DT_INST_PROP(inst, clock_frequency), \ + .i2c_irq_base = DT_INST_IRQN(inst), \ + .port = DT_INST_PROP(inst, port_num), \ + .alts_list = i2c_alts_##inst, \ + .gpio_dev = DEVICE_DT_GET(DT_INST_PHANDLE(inst, gpio_dev)), \ + .clock_gate_offset = DT_INST_PROP(inst, clock_gate_offset), \ + }; \ + \ + static struct i2c_it8xxx2_data i2c_it8xxx2_data_##inst; \ + \ + I2C_DEVICE_DT_INST_DEFINE(inst, i2c_it8xxx2_init, \ + NULL, \ + &i2c_it8xxx2_data_##inst, \ + &i2c_it8xxx2_cfg_##inst, \ + POST_KERNEL, \ + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ + &i2c_it8xxx2_driver_api); \ + \ + static void i2c_it8xxx2_config_func_##inst(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(inst), \ + 0, \ + i2c_it8xxx2_isr, \ + DEVICE_DT_INST_GET(inst), 0); \ } DT_INST_FOREACH_STATUS_OKAY(I2C_ITE_IT8XXX2_INIT) diff --git a/dts/bindings/i2c/ite,common-i2c.yaml b/dts/bindings/i2c/ite,common-i2c.yaml new file mode 100644 index 00000000000..a876a7c9a75 --- /dev/null +++ b/dts/bindings/i2c/ite,common-i2c.yaml @@ -0,0 +1,38 @@ +# Copyright (c) 2022 ITE Corporation. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +description: Common fields for ITE it8xxx2 I2C + +include: i2c-controller.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + port-num: + type: int + required: true + description: Ordinal identifying the port + + gpio-dev: + type: phandle + required: true + description: Get the handle of the GPIO device + + pinctrl-0: + type: phandles + required: true + description: | + Configuration of I2C SCL and SDA pinmux controller. + The SCL pin must be specified first and the SDA pin + second in the pinctrl-0 array. + + clock-gate-offset: + type: int + required: true + description: | + The clock gate offsets combine the register offset from + ECPM_BASE and the mask within that register into one value. diff --git a/dts/bindings/i2c/ite,enhance-i2c.yaml b/dts/bindings/i2c/ite,enhance-i2c.yaml new file mode 100644 index 00000000000..b335097fb4d --- /dev/null +++ b/dts/bindings/i2c/ite,enhance-i2c.yaml @@ -0,0 +1,20 @@ +# Copyright (c) 2022 ITE Corporation. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +description: ITE enhance I2C + +compatible: "ite,enhance-i2c" + +include: ite,common-i2c.yaml + +properties: + prescale-scl-low: + type: int + required: false + description: | + This option is used to configure the I2C speed prescaler for + the SCL low period. When set to >= 1, it will increase the + low period of the SCL clock and so reduce the signal frequency. + The resulting SCL cycle time is given by the following formula: + SCL cycle = 2 * (psr + prescale_tweak + 2) * + SMBus clock cycle diff --git a/dts/bindings/i2c/ite,it8xxx2-i2c.yaml b/dts/bindings/i2c/ite,it8xxx2-i2c.yaml index adbd71443c7..abffcf4f5c3 100644 --- a/dts/bindings/i2c/ite,it8xxx2-i2c.yaml +++ b/dts/bindings/i2c/ite,it8xxx2-i2c.yaml @@ -5,31 +5,4 @@ description: ITE it8xxx2 I2C compatible: "ite,it8xxx2-i2c" -include: i2c-controller.yaml - -properties: - reg: - required: true - - label: - required: true - - interrupts: - required: true - - port-num: - type: int - required: true - description: Ordinal identifying the port - - gpio-dev: - type: phandle - required: true - description: Get the handle of the GPIO device - - pinctrl-0: - type: phandles - required: true - description: Configuration of I2C SCL and SDA pinmux controller. - The SCL pin must be specified first and the SDA pin - second in the pinctrl-0 array. +include: ite,common-i2c.yaml diff --git a/dts/riscv/it8xxx2.dtsi b/dts/riscv/it8xxx2.dtsi index cc4e5045d27..cfdf8e4bb3e 100644 --- a/dts/riscv/it8xxx2.dtsi +++ b/dts/riscv/it8xxx2.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -660,87 +661,99 @@ &pinctrl_adc15 /* ADC15*/ &pinctrl_adc16>;/* ADC16*/ }; + i2c0: i2c@f01c40 { compatible = "ite,it8xxx2-i2c"; #address-cells = <1>; #size-cells = <0>; reg = <0x00f01c40 0x0040>; - interrupts = <9 IRQ_TYPE_EDGE_FALLING>; + interrupts = ; interrupt-parent = <&intc>; status = "disabled"; label = "I2C_0"; port-num = <0>; gpio-dev = <&gpiob>; + clock-gate-offset = ; pinctrl-0 = <&pinctrl_i2c_clk0 /* GPB3 */ &pinctrl_i2c_data0>; /* GPB4 */ }; + i2c1: i2c@f01c80 { compatible = "ite,it8xxx2-i2c"; #address-cells = <1>; #size-cells = <0>; reg = <0x00f01c80 0x0040>; - interrupts = <10 IRQ_TYPE_EDGE_FALLING>; + interrupts = ; interrupt-parent = <&intc>; status = "disabled"; label = "I2C_1"; port-num = <1>; gpio-dev = <&gpioc>; + clock-gate-offset = ; pinctrl-0 = <&pinctrl_i2c_clk1 /* GPC1 */ &pinctrl_i2c_data1>; /* GPC2 */ }; + i2c2: i2c@f01cc0 { compatible = "ite,it8xxx2-i2c"; #address-cells = <1>; #size-cells = <0>; reg = <0x00f01cc0 0x0040>; - interrupts = <16 IRQ_TYPE_EDGE_FALLING>; + interrupts = ; interrupt-parent = <&intc>; status = "disabled"; label = "I2C_2"; port-num = <2>; gpio-dev = <&gpiof>; + clock-gate-offset = ; pinctrl-0 = <&pinctrl_i2c_clk2 /* GPF6 */ &pinctrl_i2c_data2>; /* GPF7 */ }; + i2c3: i2c@f03680 { - compatible = "ite,it8xxx2-i2c"; + compatible = "ite,enhance-i2c"; #address-cells = <1>; #size-cells = <0>; reg = <0x00f03680 0x0080>; - interrupts = <4 IRQ_TYPE_EDGE_FALLING>; + interrupts = ; interrupt-parent = <&intc>; status = "disabled"; label = "I2C_3"; port-num = <3>; gpio-dev = <&gpioh>; + clock-gate-offset = ; pinctrl-0 = <&pinctrl_i2c_clk3_gph1 /* GPH1 */ &pinctrl_i2c_data3_gph2>; /* GPH2 */ }; + i2c4: i2c@f03500 { - compatible = "ite,it8xxx2-i2c"; + compatible = "ite,enhance-i2c"; #address-cells = <1>; #size-cells = <0>; reg = <0x00f03500 0x0080>; - interrupts = <152 IRQ_TYPE_EDGE_FALLING>; + interrupts = ; interrupt-parent = <&intc>; status = "disabled"; label = "I2C_4"; port-num = <4>; gpio-dev = <&gpioe>; + clock-gate-offset = ; pinctrl-0 = <&pinctrl_i2c_clk4 /* GPE0 */ &pinctrl_i2c_data4>; /* GPE7 */ }; + i2c5: i2c@f03580 { - compatible = "ite,it8xxx2-i2c"; + compatible = "ite,enhance-i2c"; #address-cells = <1>; #size-cells = <0>; reg = <0x00f03580 0x0080>; - interrupts = <153 IRQ_TYPE_EDGE_FALLING>; + interrupts = ; interrupt-parent = <&intc>; status = "disabled"; label = "I2C_5"; port-num = <5>; gpio-dev = <&gpioa>; + clock-gate-offset = ; pinctrl-0 = <&pinctrl_i2c_clk5 /* GPA4 */ &pinctrl_i2c_data5>; /* GPA5 */ }; diff --git a/include/dt-bindings/i2c/it8xxx2-i2c.h b/include/dt-bindings/i2c/it8xxx2-i2c.h new file mode 100644 index 00000000000..a42879d1331 --- /dev/null +++ b/include/dt-bindings/i2c/it8xxx2-i2c.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 ITE Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_I2C_IT8XXX2_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_I2C_IT8XXX2_H_ + + +#define IT8XXX2_ECPM_CGCTRL4R_OFF 0x09 +/* + * The clock gate offsets combine the register offset from ECPM_BASE and the + * mask within that register into one value. These are used for + * clock_enable_peripheral() and clock_disable_peripheral() + */ +#define CGC_OFFSET_SMBF ((IT8XXX2_ECPM_CGCTRL4R_OFF << 8) | 0x80) +#define CGC_OFFSET_SMBE ((IT8XXX2_ECPM_CGCTRL4R_OFF << 8) | 0x40) +#define CGC_OFFSET_SMBD ((IT8XXX2_ECPM_CGCTRL4R_OFF << 8) | 0x20) +#define CGC_OFFSET_SMBC ((IT8XXX2_ECPM_CGCTRL4R_OFF << 8) | 0x10) +#define CGC_OFFSET_SMBB ((IT8XXX2_ECPM_CGCTRL4R_OFF << 8) | 0x08) +#define CGC_OFFSET_SMBA ((IT8XXX2_ECPM_CGCTRL4R_OFF << 8) | 0x04) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_I2C_IT8XXX2_H_ */ diff --git a/include/dt-bindings/interrupt-controller/ite-intc.h b/include/dt-bindings/interrupt-controller/ite-intc.h index 603f2340c50..09ee2caeb36 100644 --- a/include/dt-bindings/interrupt-controller/ite-intc.h +++ b/include/dt-bindings/interrupt-controller/ite-intc.h @@ -17,12 +17,16 @@ /* Group 0 of INTC */ #define IT8XXX2_IRQ_WU20 1 #define IT8XXX2_IRQ_KBC_OBE 2 +#define IT8XXX2_IRQ_SMB_D 4 #define IT8XXX2_IRQ_WU23 6 /* Group 1 */ +#define IT8XXX2_IRQ_SMB_A 9 +#define IT8XXX2_IRQ_SMB_B 10 #define IT8XXX2_IRQ_WU26 12 #define IT8XXX2_IRQ_WKINTC 13 #define IT8XXX2_IRQ_WU25 14 /* Group 2 */ +#define IT8XXX2_IRQ_SMB_C 16 #define IT8XXX2_IRQ_WU24 17 #define IT8XXX2_IRQ_WU22 21 /* Group 3 */ @@ -134,6 +138,8 @@ #define IT8XXX2_IRQ_WU125 146 #define IT8XXX2_IRQ_WU126 147 /* Group 19 */ +#define IT8XXX2_IRQ_SMB_E 152 +#define IT8XXX2_IRQ_SMB_F 153 #define IT8XXX2_IRQ_TIMER3 155 #define IT8XXX2_IRQ_TIMER4 156 #define IT8XXX2_IRQ_TIMER5 157 diff --git a/soc/riscv/riscv-ite/common/chip_chipregs.h b/soc/riscv/riscv-ite/common/chip_chipregs.h index f4708a696f3..71a24b1f2a5 100644 --- a/soc/riscv/riscv-ite/common/chip_chipregs.h +++ b/soc/riscv/riscv-ite/common/chip_chipregs.h @@ -703,113 +703,6 @@ struct pwm_it8xxx2_regs { #define IT8XXX2_WUC_WUBEMR1 (IT8XXX2_WUC_BASE + 0x3c) #define IT8XXX2_WUC_WUBEMR5 (IT8XXX2_WUC_BASE + 0x0f) -/** - * - * (1Cxxh) SMBus Interface (SMB) - * - */ -#define HOSTA_A ECREG(EC_REG_BASE_ADDR + 0x1C40) -#define HOSTA_B ECREG(EC_REG_BASE_ADDR + 0x1C80) -#define HOSTA_C ECREG(EC_REG_BASE_ADDR + 0x1CC0) -#define HOSTA_BDS BIT(7) -#define HOSTA_TMOE BIT(6) -#define HOSTA_NACK BIT(5) -#define HOSTA_FAIL BIT(4) -#define HOSTA_BSER BIT(3) -#define HOSTA_DVER BIT(2) -#define HOSTA_FINTR BIT(1) -#define HOSTA_HOBY BIT(0) -#define HOSTA_ANY_ERROR (HOSTA_DVER | HOSTA_BSER | \ - HOSTA_FAIL | HOSTA_NACK | HOSTA_TMOE) -#define HOSTA_NEXT_BYTE HOSTA_BDS -#define HOSTA_ALL_WC_BIT (HOSTA_FINTR | \ - HOSTA_ANY_ERROR | HOSTA_BDS) - -#define HOCTL_A ECREG(EC_REG_BASE_ADDR + 0x1C41) -#define HOCTL_B ECREG(EC_REG_BASE_ADDR + 0x1C81) -#define HOCTL_C ECREG(EC_REG_BASE_ADDR + 0x1CC1) -#define HOCTL_PEC_EN BIT(7) -#define HOCTL_SRT BIT(6) -#define HOCTL_LABY BIT(5) -#define HOCTL_SMCD2 BIT(4) -#define HOCTL_SMCD1 BIT(3) -#define HOCTL_SMCD0 BIT(2) -#define HOCTL_KILL BIT(1) -#define HOCTL_INTREN BIT(0) - -#define HOCMD_A ECREG(EC_REG_BASE_ADDR + 0x1C42) -#define HOCMD_B ECREG(EC_REG_BASE_ADDR + 0x1C82) -#define HOCMD_C ECREG(EC_REG_BASE_ADDR + 0x1CC2) -#define TRASLA_A ECREG(EC_REG_BASE_ADDR + 0x1C43) -#define TRASLA_B ECREG(EC_REG_BASE_ADDR + 0x1C83) -#define TRASLA_C ECREG(EC_REG_BASE_ADDR + 0x1CC3) -#define D0REG_A ECREG(EC_REG_BASE_ADDR + 0x1C44) -#define D0REG_B ECREG(EC_REG_BASE_ADDR + 0x1C84) -#define D0REG_C ECREG(EC_REG_BASE_ADDR + 0x1CC4) -#define D1REG_A ECREG(EC_REG_BASE_ADDR + 0x1C45) -#define D1REG_B ECREG(EC_REG_BASE_ADDR + 0x1C85) -#define D1REG_C ECREG(EC_REG_BASE_ADDR + 0x1CC5) -#define HOBDB_A ECREG(EC_REG_BASE_ADDR + 0x1C46) -#define HOBDB_B ECREG(EC_REG_BASE_ADDR + 0x1C86) -#define HOBDB_C ECREG(EC_REG_BASE_ADDR + 0x1CC6) -#define PECERC_A ECREG(EC_REG_BASE_ADDR + 0x1C47) -#define PECERC_B ECREG(EC_REG_BASE_ADDR + 0x1C87) -#define PECERC_C ECREG(EC_REG_BASE_ADDR + 0x1CC7) -#define RESLADR_A ECREG(EC_REG_BASE_ADDR + 0x1C48) -#define RESLADR_B ECREG(EC_REG_BASE_ADDR + 0x1C88) -#define RESLADR_2_A ECREG(EC_REG_BASE_ADDR + 0x1C51) -#define RESLADR_2_B ECREG(EC_REG_BASE_ADDR + 0x1C91) -#define SLDA_A ECREG(EC_REG_BASE_ADDR + 0x1C49) -#define SLDA_B ECREG(EC_REG_BASE_ADDR + 0x1C89) -#define SMBPCTL_A ECREG(EC_REG_BASE_ADDR + 0x1C4A) -#define SMBPCTL_B ECREG(EC_REG_BASE_ADDR + 0x1C8A) -#define SMBPCTL_C ECREG(EC_REG_BASE_ADDR + 0x1CCA) -#define SLSTA_A ECREG(EC_REG_BASE_ADDR + 0x1C4B) -#define SLSTA_B ECREG(EC_REG_BASE_ADDR + 0x1C8B) -#define INT81 BIT(7) -#define BIS BIT(6) -#define SPDS BIT(5) -#define MSLA2 BIT(4) -#define RCS BIT(3) -#define STS BIT(2) -#define SDS BIT(1) -#define HONOST BIT(0) - -#define SICR_A ECREG(EC_REG_BASE_ADDR + 0x1C4C) -#define SICR_B ECREG(EC_REG_BASE_ADDR + 0x1C8C) -#define NDADR_A ECREG(EC_REG_BASE_ADDR + 0x1C4D) -#define NDADR_B ECREG(EC_REG_BASE_ADDR + 0x1C8D) -#define NDLB_A ECREG(EC_REG_BASE_ADDR + 0x1C4E) -#define NDLB_B ECREG(EC_REG_BASE_ADDR + 0x1C8E) -#define NDHB_A ECREG(EC_REG_BASE_ADDR + 0x1C4F) -#define NDHB_B ECREG(EC_REG_BASE_ADDR + 0x1C8F) -#define HOCTL2_A ECREG(EC_REG_BASE_ADDR + 0x1C50) -#define HOCTL2_B ECREG(EC_REG_BASE_ADDR + 0x1C90) -#define HOCTL2_C ECREG(EC_REG_BASE_ADDR + 0x1CD0) -#define SMB4P7USL ECREG(EC_REG_BASE_ADDR + 0x1C00) -#define SMB4P0USH ECREG(EC_REG_BASE_ADDR + 0x1C01) -#define SMB300NS ECREG(EC_REG_BASE_ADDR + 0x1C02) -#define SMB250NS ECREG(EC_REG_BASE_ADDR + 0x1C03) -#define SMB25MS ECREG(EC_REG_BASE_ADDR + 0x1C04) -#define SMB45P3USL ECREG(EC_REG_BASE_ADDR + 0x1C05) -#define SMB45P3USH ECREG(EC_REG_BASE_ADDR + 0x1C06) -#define SMB4P7A4P0H ECREG(EC_REG_BASE_ADDR + 0x1C07) -#define SLVISEL ECREG(EC_REG_BASE_ADDR + 0x1C08) -#define SCLKTS_A ECREG(EC_REG_BASE_ADDR + 0x1C09) -#define SCLKTS_B ECREG(EC_REG_BASE_ADDR + 0x1C0A) -#define SCLKTS_C ECREG(EC_REG_BASE_ADDR + 0x1C0B) -#define SMBFFCTRL1 ECREG(EC_REG_BASE_ADDR + 0x1C0D) -#define SMBFFSTS1 ECREG(EC_REG_BASE_ADDR + 0x1C0E) -#define SMBFFCTRL2 ECREG(EC_REG_BASE_ADDR + 0x1C0F) -#define SMBFFSTS2 ECREG(EC_REG_BASE_ADDR + 0x1C10) -#define CHSEF ECREG(EC_REG_BASE_ADDR + 0x1C11) -#define HOCTL3_A ECREG(EC_REG_BASE_ADDR + 0x1C52) -#define HOCTL3_B ECREG(EC_REG_BASE_ADDR + 0x1C92) -#define HOCTL3_C ECREG(EC_REG_BASE_ADDR + 0x1CD2) -#define MCODE_A ECREG(EC_REG_BASE_ADDR + 0x1C53) -#define MCODE_B ECREG(EC_REG_BASE_ADDR + 0x1C93) -#define MCODE_C ECREG(EC_REG_BASE_ADDR + 0x1CD3) - /** * * (1Dxxh) Keyboard Matrix Scan control (KSCAN) @@ -1618,22 +1511,13 @@ struct adc_it8xxx2_regs { /* Automatic hardware calibration enable */ #define IT8XXX2_ADC_AHCE BIT(7) -/* - * Clock and Power Management (ECPM) +/** + * + * (1Exxh) Clock and Power Management (ECPM) registers + * */ -#define IT83XX_ECPM_BASE 0x00F01E00 +#define IT8XXX2_ECPM_BASE 0x00F01E00 -#define IT83XX_ECPM_CGCTRL4R_OFF 0x09 - -#define CGC_OFFSET_SMBF ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x80) -#define CGC_OFFSET_SMBE ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x40) -#define CGC_OFFSET_SMBD ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x20) -#define CGC_OFFSET_SMBC ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x10) -#define CGC_OFFSET_SMBB ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x08) -#define CGC_OFFSET_SMBA ((IT83XX_ECPM_CGCTRL4R_OFF << 8) | 0x04) - -/* TODO: rename IT83XX_ECPM_BASE to IT8XXX2_ECPM_BASE */ -#define IT8XXX2_ECPM_PLLCTRL ECREG(IT83XX_ECPM_BASE + 0x03) #ifndef __ASSEMBLER__ enum chip_pll_mode { CHIP_PLL_DOZE = 0, @@ -1641,15 +1525,16 @@ enum chip_pll_mode { CHIP_PLL_DEEP_DOZE = 3, }; #endif -#define IT8XXX2_ECPM_AUTOCG ECREG(IT83XX_ECPM_BASE + 0x04) -#define IT8XXX2_ECPM_CGCTRL3R ECREG(IT83XX_ECPM_BASE + 0x05) -#define IT8XXX2_ECPM_PLLFREQR ECREG(IT83XX_ECPM_BASE + 0x06) -#define IT8XXX2_ECPM_PLLCSS ECREG(IT83XX_ECPM_BASE + 0x08) -#define IT8XXX2_ECPM_SCDCR0 ECREG(IT83XX_ECPM_BASE + 0x0c) -#define IT8XXX2_ECPM_SCDCR1 ECREG(IT83XX_ECPM_BASE + 0x0d) -#define IT8XXX2_ECPM_SCDCR2 ECREG(IT83XX_ECPM_BASE + 0x0e) -#define IT8XXX2_ECPM_SCDCR3 ECREG(IT83XX_ECPM_BASE + 0x0f) -#define IT8XXX2_ECPM_SCDCR4 ECREG(IT83XX_ECPM_BASE + 0x10) +#define IT8XXX2_ECPM_PLLCTRL ECREG(IT8XXX2_ECPM_BASE + 0x03) +#define IT8XXX2_ECPM_AUTOCG ECREG(IT8XXX2_ECPM_BASE + 0x04) +#define IT8XXX2_ECPM_CGCTRL3R ECREG(IT8XXX2_ECPM_BASE + 0x05) +#define IT8XXX2_ECPM_PLLFREQR ECREG(IT8XXX2_ECPM_BASE + 0x06) +#define IT8XXX2_ECPM_PLLCSS ECREG(IT8XXX2_ECPM_BASE + 0x08) +#define IT8XXX2_ECPM_SCDCR0 ECREG(IT8XXX2_ECPM_BASE + 0x0c) +#define IT8XXX2_ECPM_SCDCR1 ECREG(IT8XXX2_ECPM_BASE + 0x0d) +#define IT8XXX2_ECPM_SCDCR2 ECREG(IT8XXX2_ECPM_BASE + 0x0e) +#define IT8XXX2_ECPM_SCDCR3 ECREG(IT8XXX2_ECPM_BASE + 0x0f) +#define IT8XXX2_ECPM_SCDCR4 ECREG(IT8XXX2_ECPM_BASE + 0x10) /* * The count number of the counter for 25 ms register. @@ -1658,67 +1543,97 @@ enum chip_pll_mode { #define I2C_CLK_LOW_TIMEOUT 255 /* ~=249 ms */ -/* SMBus/I2C Interface (SMB/I2C) */ -#define IT83XX_SMB_BASE 0x00F01C00 -#define IT83XX_SMB_4P7USL ECREG(IT83XX_SMB_BASE+0x00) -#define IT83XX_SMB_4P0USL ECREG(IT83XX_SMB_BASE+0x01) -#define IT83XX_SMB_300NS ECREG(IT83XX_SMB_BASE+0x02) -#define IT83XX_SMB_250NS ECREG(IT83XX_SMB_BASE+0x03) -#define IT83XX_SMB_25MS ECREG(IT83XX_SMB_BASE+0x04) -#define IT83XX_SMB_45P3USL ECREG(IT83XX_SMB_BASE+0x05) -#define IT83XX_SMB_45P3USH ECREG(IT83XX_SMB_BASE+0x06) -#define IT83XX_SMB_4P7A4P0H ECREG(IT83XX_SMB_BASE+0x07) -#define IT83XX_SMB_SLVISELR ECREG(IT83XX_SMB_BASE+0x08) -#define IT83XX_SMB_SCLKTS(ch) ECREG(IT83XX_SMB_BASE+0x09+ch) -#define IT83XX_SMB_CHSEF ECREG(IT83XX_SMB_BASE+0x11) -#define IT83XX_SMB_CHSAB ECREG(IT83XX_SMB_BASE+0x20) -#define IT83XX_SMB_CHSCD ECREG(IT83XX_SMB_BASE+0x21) -#define IT8XXX2_SMB_SFFCTL ECREG(IT83XX_SMB_BASE+0x55) -#define IT83XX_SMB_HOSTA(base) ECREG(base+0x00) -#define IT83XX_SMB_HOCTL(base) ECREG(base+0x01) -#define IT83XX_SMB_HOCMD(base) ECREG(base+0x02) -#define IT83XX_SMB_TRASLA(base) ECREG(base+0x03) -#define IT83XX_SMB_D0REG(base) ECREG(base+0x04) -#define IT83XX_SMB_D1REG(base) ECREG(base+0x05) -#define IT83XX_SMB_HOBDB(base) ECREG(base+0x06) -#define IT83XX_SMB_PECERC(base) ECREG(base+0x07) -#define IT83XX_SMB_SMBPCTL(base) ECREG(base+0x0A) -#define IT83XX_SMB_HOCTL2(base) ECREG(base+0x10) +/** + * + * (1Cxxh) SMBus Interface (SMB) registers + * + */ +#define IT8XXX2_SMB_BASE 0x00F01C00 +#define IT8XXX2_SMB_4P7USL ECREG(IT8XXX2_SMB_BASE + 0x00) +#define IT8XXX2_SMB_4P0USL ECREG(IT8XXX2_SMB_BASE + 0x01) +#define IT8XXX2_SMB_300NS ECREG(IT8XXX2_SMB_BASE + 0x02) +#define IT8XXX2_SMB_250NS ECREG(IT8XXX2_SMB_BASE + 0x03) +#define IT8XXX2_SMB_25MS ECREG(IT8XXX2_SMB_BASE + 0x04) +#define IT8XXX2_SMB_45P3USL ECREG(IT8XXX2_SMB_BASE + 0x05) +#define IT8XXX2_SMB_45P3USH ECREG(IT8XXX2_SMB_BASE + 0x06) +#define IT8XXX2_SMB_4P7A4P0H ECREG(IT8XXX2_SMB_BASE + 0x07) +#define IT8XXX2_SMB_SLVISELR ECREG(IT8XXX2_SMB_BASE + 0x08) +#define IT8XXX2_SMB_SCLKTS(ch) ECREG(IT8XXX2_SMB_BASE + 0x09 + ch) +#define IT8XXX2_SMB_CHSEF ECREG(IT8XXX2_SMB_BASE + 0x11) +#define IT8XXX2_SMB_CHSAB ECREG(IT8XXX2_SMB_BASE + 0x20) +#define IT8XXX2_SMB_CHSCD ECREG(IT8XXX2_SMB_BASE + 0x21) +#define IT8XXX2_SMB_SFFCTL ECREG(IT8XXX2_SMB_BASE + 0x55) +#define IT8XXX2_SMB_HOSTA(base) ECREG(base + 0x00) +#define IT8XXX2_SMB_HOCTL(base) ECREG(base + 0x01) +#define IT8XXX2_SMB_HOCMD(base) ECREG(base + 0x02) +#define IT8XXX2_SMB_TRASLA(base) ECREG(base + 0x03) +#define IT8XXX2_SMB_D0REG(base) ECREG(base + 0x04) +#define IT8XXX2_SMB_D1REG(base) ECREG(base + 0x05) +#define IT8XXX2_SMB_HOBDB(base) ECREG(base + 0x06) +#define IT8XXX2_SMB_PECERC(base) ECREG(base + 0x07) +#define IT8XXX2_SMB_SMBPCTL(base) ECREG(base + 0x0A) +#define IT8XXX2_SMB_HOCTL2(base) ECREG(base + 0x10) /** * Enhanced SMBus/I2C Interface * Ch_D: 0x00F03680, Ch_E: 0x00F03500, Ch_F: 0x00F03580 * Ch_D: ch = 0x03, Ch_E: ch = 0x00, Ch_F: ch = 0x01 */ -#define IT83XX_I2C_DRR(base) ECREG(base+0x00) -#define IT83XX_I2C_PSR(base) ECREG(base+0x01) -#define IT83XX_I2C_HSPR(base) ECREG(base+0x02) -#define IT83XX_I2C_STR(base) ECREG(base+0x03) -#define IT83XX_I2C_DHTR(base) ECREG(base+0x04) -#define IT83XX_I2C_TOR(base) ECREG(base+0x05) -#define IT83XX_I2C_DTR(base) ECREG(base+0x08) -#define IT83XX_I2C_CTR(base) ECREG(base+0x09) -#define IT83XX_I2C_CTR1(base) ECREG(base+0x0A) -#define IT83XX_I2C_BYTE_CNT_L(base) ECREG(base+0x0C) -#define IT83XX_I2C_IRQ_ST(base) ECREG(base+0x0D) -#define IT83XX_I2C_IDR(base) ECREG(base+0x06) -#define IT83XX_I2C_TOS(base) ECREG(base+0x07) -#define IT83XX_I2C_IDR2(base) ECREG(base+0x1F) -#define IT83XX_I2C_RAMHA(base) ECREG(base+0x23) -#define IT83XX_I2C_RAMLA(base) ECREG(base+0x24) -#define IT83XX_I2C_RAMHA2(base) ECREG(base+0x2B) -#define IT83XX_I2C_RAMLA2(base) ECREG(base+0x2C) -#define IT83XX_I2C_CMD_ADDH(base) ECREG(base+0x25) -#define IT83XX_I2C_CMD_ADDL(base) ECREG(base+0x26) -#define IT83XX_I2C_RAMH2A(base) ECREG(base+0x50) -#define IT83XX_I2C_CMD_ADDH2(base) ECREG(base+0x52) +#define IT8XXX2_I2C_DRR(base) ECREG(base + 0x00) +#define IT8XXX2_I2C_PSR(base) ECREG(base + 0x01) +#define IT8XXX2_I2C_HSPR(base) ECREG(base + 0x02) +#define IT8XXX2_I2C_STR(base) ECREG(base + 0x03) +#define IT8XXX2_I2C_DHTR(base) ECREG(base + 0x04) +#define IT8XXX2_I2C_TOR(base) ECREG(base + 0x05) +#define IT8XXX2_I2C_DTR(base) ECREG(base + 0x08) +#define IT8XXX2_I2C_CTR(base) ECREG(base + 0x09) +#define IT8XXX2_I2C_CTR1(base) ECREG(base + 0x0A) +#define IT8XXX2_I2C_BYTE_CNT_L(base) ECREG(base + 0x0C) +#define IT8XXX2_I2C_IRQ_ST(base) ECREG(base + 0x0D) +#define IT8XXX2_I2C_IDR(base) ECREG(base + 0x06) +#define IT8XXX2_I2C_TOS(base) ECREG(base + 0x07) +#define IT8XXX2_I2C_IDR2(base) ECREG(base + 0x1F) +#define IT8XXX2_I2C_RAMHA(base) ECREG(base + 0x23) +#define IT8XXX2_I2C_RAMLA(base) ECREG(base + 0x24) +#define IT8XXX2_I2C_RAMHA2(base) ECREG(base + 0x2B) +#define IT8XXX2_I2C_RAMLA2(base) ECREG(base + 0x2C) +#define IT8XXX2_I2C_CMD_ADDH(base) ECREG(base + 0x25) +#define IT8XXX2_I2C_CMD_ADDL(base) ECREG(base + 0x26) +#define IT8XXX2_I2C_RAMH2A(base) ECREG(base + 0x50) +#define IT8XXX2_I2C_CMD_ADDH2(base) ECREG(base + 0x52) /* SMBus/I2C register fields */ +/* 0x09-0xB: SMCLK Timing Setting */ +#define IT8XXX2_SMB_SMCLKS_1M 4 +#define IT8XXX2_SMB_SMCLKS_400K 3 +#define IT8XXX2_SMB_SMCLKS_100K 2 +#define IT8XXX2_SMB_SMCLKS_50K 1 +/* 0x41 0x81 0xC1: Host Control */ +#define IT8XXX2_SMB_SRT BIT(6) +#define IT8XXX2_SMB_LABY BIT(5) +#define IT8XXX2_SMB_SMCD_EXTND BIT(4) | BIT(3) | BIT(2) +#define IT8XXX2_SMB_KILL BIT(1) +#define IT8XXX2_SMB_INTREN BIT(0) +/* 0x43 0x83 0xC3: Transmit Slave Address */ +#define IT8XXX2_SMB_DIR BIT(0) +/* 0x4A 0x8A 0xCA: SMBus Pin Control */ +#define IT8XXX2_SMB_SMBDCS BIT(1) +#define IT8XXX2_SMB_SMBCS BIT(0) +/* 0x50 0x90 0xD0: Host Control 2 */ +#define IT8XXX2_SMB_SMD_TO_EN BIT(4) +#define IT8XXX2_SMB_I2C_SW_EN BIT(3) +#define IT8XXX2_SMB_I2C_SW_WAIT BIT(2) +#define IT8XXX2_SMB_I2C_EN BIT(1) +#define IT8XXX2_SMB_SMHEN BIT(0) /* 0x55: Slave A FIFO Control */ -#define IT8XXX2_SMB_HSAPE BIT(1) +#define IT8XXX2_SMB_HSAPE BIT(1) +/* 0x04: Data Hold Time */ +#define IT8XXX2_I2C_SOFT_RST BIT(7) /* 0x07: Time Out Status */ -#define IT8XXX2_I2C_SCL_IN BIT(2) -#define IT8XXX2_I2C_SDA_IN BIT(0) +#define IT8XXX2_I2C_SCL_IN BIT(2) +#define IT8XXX2_I2C_SDA_IN BIT(0) +/* 0x0A: Control 1 */ +#define IT8XXX2_I2C_MDL_EN BIT(1) /* --- General Control (GCTRL) --- */ #define IT83XX_GCTRL_BASE 0x00F02000 diff --git a/soc/riscv/riscv-ite/common/soc_common.h b/soc/riscv/riscv-ite/common/soc_common.h index 6b3b2414b4a..55f10614311 100644 --- a/soc/riscv/riscv-ite/common/soc_common.h +++ b/soc/riscv/riscv-ite/common/soc_common.h @@ -52,6 +52,7 @@ void ite_intc_init(void); void timer_5ms_one_shot(void); #endif +uint32_t chip_get_pll_freq(void); void chip_pll_ctrl(enum chip_pll_mode mode); void riscv_idle(enum chip_pll_mode mode, unsigned int key); diff --git a/soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.series b/soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.series index f7f0c791fd1..2d0aa304b90 100644 --- a/soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.series +++ b/soc/riscv/riscv-ite/it8xxx2/Kconfig.defconfig.series @@ -56,10 +56,6 @@ config GPIO_ITE_IT8XXX2 default y depends on GPIO -config I2C_ITE_IT8XXX2 - default y - depends on I2C - config ADC_ITE_IT8XXX2 default y depends on ADC diff --git a/soc/riscv/riscv-ite/it8xxx2/soc.c b/soc/riscv/riscv-ite/it8xxx2/soc.c index 3f6d0d976d8..d5564da831c 100644 --- a/soc/riscv/riscv-ite/it8xxx2/soc.c +++ b/soc/riscv/riscv-ite/it8xxx2/soc.c @@ -51,6 +51,42 @@ static const struct pll_config_t pll_configuration[] = { .div_usbpd = 5} }; +uint32_t chip_get_pll_freq(void) +{ + uint32_t pllfreq; + + switch (IT8XXX2_ECPM_PLLFREQR & 0x0F) { + case 0: + pllfreq = MHZ(8); + break; + case 1: + pllfreq = MHZ(16); + break; + case 2: + pllfreq = MHZ(24); + break; + case 3: + pllfreq = MHZ(32); + break; + case 4: + pllfreq = MHZ(48); + break; + case 5: + pllfreq = MHZ(64); + break; + case 6: + pllfreq = MHZ(72); + break; + case 7: + pllfreq = MHZ(96); + break; + default: + return -ERANGE; + } + + return pllfreq; +} + void __intc_ram_code chip_pll_ctrl(enum chip_pll_mode mode) { volatile uint8_t _pll_ctrl __unused;