ITE: drivers/i2c: I2C driver divided into two compatibles
As mentioned in #42882, the I2C of IT8XXX2 is designed for two different IP blocks, so this PR divides this I2C driver into two compatibles. Signed-off-by: Tim Lin <tim2.lin@ite.corp-partner.google.com>
This commit is contained in:
parent
f18decd561
commit
f2c42663b4
15 changed files with 1211 additions and 739 deletions
|
@ -278,6 +278,7 @@
|
||||||
/drivers/hwinfo/ @alexanderwachter
|
/drivers/hwinfo/ @alexanderwachter
|
||||||
/drivers/i2c/i2c_common.c @sjg20
|
/drivers/i2c/i2c_common.c @sjg20
|
||||||
/drivers/i2c/i2c_emul.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_ite_it8xxx2.c @GTLin08
|
||||||
/drivers/i2c/i2c_shell.c @nashif
|
/drivers/i2c/i2c_shell.c @nashif
|
||||||
/drivers/i2c/Kconfig.i2c_emul @sjg20
|
/drivers/i2c/Kconfig.i2c_emul @sjg20
|
||||||
|
|
|
@ -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_ESP32 i2c_esp32.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_I2C_GPIO i2c_gpio.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_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_IMX i2c_imx.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_I2C_LPC11U6X i2c_lpc11u6x.c)
|
zephyr_library_sources_ifdef(CONFIG_I2C_LPC11U6X i2c_lpc11u6x.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_I2C_XEC i2c_mchp_xec.c)
|
zephyr_library_sources_ifdef(CONFIG_I2C_XEC i2c_mchp_xec.c)
|
||||||
|
|
|
@ -1,10 +1,22 @@
|
||||||
# Copyright (c) 2020 ITE Corporation. All Rights Reserved.
|
# Copyright (c) 2020 ITE Corporation. All Rights Reserved.
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# 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
|
config I2C_ITE_IT8XXX2
|
||||||
bool "ITE IT8XXX2 I2C driver"
|
bool "ITE IT8XXX2 I2C driver"
|
||||||
depends on SOC_IT8XXX2
|
depends on SOC_IT8XXX2
|
||||||
|
default $(dt_compat_enabled,$(DT_COMPAT_ITE_IT8XXX2_I2C))
|
||||||
help
|
help
|
||||||
Enable I2C support on it8xxx2_evb.
|
Enable I2C support on it8xxx2_evb.
|
||||||
Supported Speeds: 100kHz, 400kHz and 1MHz.
|
Supported Speeds: 100kHz, 400kHz and 1MHz.
|
||||||
This driver supports repeated start.
|
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.
|
||||||
|
|
755
drivers/i2c/i2c_ite_enhance.c
Normal file
755
drivers/i2c/i2c_ite_enhance.c
Normal file
|
@ -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 <drivers/gpio.h>
|
||||||
|
#include <drivers/i2c.h>
|
||||||
|
#include <drivers/pinmux.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <soc.h>
|
||||||
|
#include <soc_dt.h>
|
||||||
|
#include <sys/util.h>
|
||||||
|
|
||||||
|
#include <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)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
|
@ -10,16 +10,21 @@
|
||||||
#include <drivers/i2c.h>
|
#include <drivers/i2c.h>
|
||||||
#include <drivers/pinmux.h>
|
#include <drivers/pinmux.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <logging/log.h>
|
|
||||||
LOG_MODULE_REGISTER(i2c_ite_it8xxx2);
|
|
||||||
#include "i2c-priv.h"
|
|
||||||
#include <soc.h>
|
#include <soc.h>
|
||||||
#include <soc_dt.h>
|
#include <soc_dt.h>
|
||||||
#include <sys/util.h>
|
#include <sys/util.h>
|
||||||
|
|
||||||
#define I2C_STANDARD_PORT_COUNT 3
|
#include <logging/log.h>
|
||||||
/* Default PLL frequency. */
|
LOG_MODULE_REGISTER(i2c_ite_it8xxx2, CONFIG_I2C_LOG_LEVEL);
|
||||||
#define PLL_CLOCK 48000000
|
|
||||||
|
#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
|
* Structure i2c_alts_cfg is about the alternate function
|
||||||
|
@ -45,6 +50,7 @@ struct i2c_it8xxx2_config {
|
||||||
const struct i2c_alts_cfg *alts_list;
|
const struct i2c_alts_cfg *alts_list;
|
||||||
/* GPIO handle */
|
/* GPIO handle */
|
||||||
const struct device *gpio_dev;
|
const struct device *gpio_dev;
|
||||||
|
uint32_t clock_gate_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum i2c_pin_fun {
|
enum i2c_pin_fun {
|
||||||
|
@ -80,57 +86,30 @@ struct i2c_it8xxx2_data {
|
||||||
uint8_t stop;
|
uint8_t stop;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum enhanced_i2c_transfer_direct {
|
enum i2c_host_status {
|
||||||
TX_DIRECT,
|
/* Host busy */
|
||||||
RX_DIRECT,
|
HOSTA_HOBY = 0x01,
|
||||||
};
|
/* Finish Interrupt */
|
||||||
|
HOSTA_FINTR = 0x02,
|
||||||
enum enhanced_i2c_ctl {
|
/* Device error */
|
||||||
/* Hardware reset */
|
HOSTA_DVER = 0x04,
|
||||||
E_HW_RST = 0x01,
|
/* Bus error */
|
||||||
/* Stop */
|
HOSTA_BSER = 0x08,
|
||||||
E_STOP = 0x02,
|
/* Fail */
|
||||||
/* Start & Repeat start */
|
HOSTA_FAIL = 0x10,
|
||||||
E_START = 0x04,
|
/* Not response ACK */
|
||||||
/* Acknowledge */
|
HOSTA_NACK = 0x20,
|
||||||
E_ACK = 0x08,
|
/* Time-out error */
|
||||||
/* State reset */
|
HOSTA_TMOE = 0x40,
|
||||||
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 */
|
/* Byte done status */
|
||||||
E_HOSTA_BDS = 0x80,
|
HOSTA_BDS = 0x80,
|
||||||
/* time out or lost arbitration */
|
/* Error bit is set */
|
||||||
E_HOSTA_ANY_ERROR = (E_HOSTA_TMOE | E_HOSTA_ARB),
|
HOSTA_ANY_ERROR = (HOSTA_DVER | HOSTA_BSER | HOSTA_FAIL |
|
||||||
/* Byte transfer done and ACK receive */
|
HOSTA_NACK | HOSTA_TMOE),
|
||||||
E_HOSTA_BDS_AND_ACK = (E_HOSTA_BDS | E_HOSTA_ACK),
|
/* 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 {
|
enum i2c_reset_cause {
|
||||||
|
@ -138,37 +117,24 @@ enum i2c_reset_cause {
|
||||||
I2C_RC_TIMEOUT,
|
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)
|
static int i2c_parsing_return_value(const struct device *dev)
|
||||||
{
|
{
|
||||||
struct i2c_it8xxx2_data *data = dev->data;
|
struct i2c_it8xxx2_data *data = dev->data;
|
||||||
const struct i2c_it8xxx2_config *config = dev->config;
|
|
||||||
|
|
||||||
if (!data->err)
|
if (!data->err) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Connection timed out */
|
/* Connection timed out */
|
||||||
if (data->err == ETIMEDOUT)
|
if (data->err == ETIMEDOUT) {
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
if (config->port < I2C_STANDARD_PORT_COUNT) {
|
/* The device does not respond ACK */
|
||||||
/* The device does not respond ACK */
|
if (data->err == HOSTA_NACK) {
|
||||||
if (data->err == HOSTA_NACK)
|
return -ENXIO;
|
||||||
return -ENXIO;
|
|
||||||
else
|
|
||||||
return -EIO;
|
|
||||||
} else {
|
} else {
|
||||||
/* The device does not respond ACK */
|
return -EIO;
|
||||||
if (data->err == E_HOSTA_ACK)
|
|
||||||
return -ENXIO;
|
|
||||||
else
|
|
||||||
return -EIO;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,21 +142,9 @@ static int i2c_get_line_levels(const struct device *dev)
|
||||||
{
|
{
|
||||||
const struct i2c_it8xxx2_config *config = dev->config;
|
const struct i2c_it8xxx2_config *config = dev->config;
|
||||||
uint8_t *base = config->base;
|
uint8_t *base = config->base;
|
||||||
int pin_sts = 0;
|
|
||||||
|
|
||||||
if (config->port < I2C_STANDARD_PORT_COUNT) {
|
return (IT8XXX2_SMB_SMBPCTL(base) &
|
||||||
return IT83XX_SMB_SMBPCTL(base) & 0x03;
|
(IT8XXX2_SMB_SMBDCS | IT8XXX2_SMB_SMBCS));
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int i2c_is_busy(const struct device *dev)
|
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;
|
const struct i2c_it8xxx2_config *config = dev->config;
|
||||||
uint8_t *base = config->base;
|
uint8_t *base = config->base;
|
||||||
|
|
||||||
if (config->port < I2C_STANDARD_PORT_COUNT) {
|
return (IT8XXX2_SMB_HOSTA(base) &
|
||||||
return (IT83XX_SMB_HOSTA(base) &
|
(HOSTA_HOBY | HOSTA_ALL_WC_BIT));
|
||||||
(HOSTA_HOBY | HOSTA_ALL_WC_BIT));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (IT83XX_I2C_STR(base) & E_HOSTA_BB);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int i2c_bus_not_available(const struct device *dev)
|
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;
|
const struct i2c_it8xxx2_config *config = dev->config;
|
||||||
uint8_t *base = config->base;
|
uint8_t *base = config->base;
|
||||||
|
|
||||||
if (config->port < I2C_STANDARD_PORT_COUNT) {
|
/* bit1, kill current transaction. */
|
||||||
/* bit1, kill current transaction. */
|
IT8XXX2_SMB_HOCTL(base) = IT8XXX2_SMB_KILL;
|
||||||
IT83XX_SMB_HOCTL(base) = 0x2;
|
IT8XXX2_SMB_HOCTL(base) = 0;
|
||||||
IT83XX_SMB_HOCTL(base) = 0;
|
/* W/C host status register */
|
||||||
/* W/C host status register */
|
IT8XXX2_SMB_HOSTA(base) = HOSTA_ALL_WC_BIT;
|
||||||
IT83XX_SMB_HOSTA(base) = HOSTA_ALL_WC_BIT;
|
|
||||||
} else {
|
|
||||||
/* State reset and hardware reset */
|
|
||||||
IT83XX_I2C_CTR(base) = E_STS_AND_HW_RST;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -240,20 +185,20 @@ static void i2c_reset(const struct device *dev)
|
||||||
static void i2c_standard_port_timing_regs_400khz(uint8_t port)
|
static void i2c_standard_port_timing_regs_400khz(uint8_t port)
|
||||||
{
|
{
|
||||||
/* Port clock frequency depends on setting of timing registers. */
|
/* 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. */
|
/* Suggested setting of timing registers of 400kHz. */
|
||||||
IT83XX_SMB_4P7USL = 0x6;
|
IT8XXX2_SMB_4P7USL = 0x6;
|
||||||
IT83XX_SMB_4P0USL = 0;
|
IT8XXX2_SMB_4P0USL = 0;
|
||||||
IT83XX_SMB_300NS = 0x1;
|
IT8XXX2_SMB_300NS = 0x1;
|
||||||
IT83XX_SMB_250NS = 0x2;
|
IT8XXX2_SMB_250NS = 0x2;
|
||||||
IT83XX_SMB_45P3USL = 0x6a;
|
IT8XXX2_SMB_45P3USL = 0x6a;
|
||||||
IT83XX_SMB_45P3USH = 0x1;
|
IT8XXX2_SMB_45P3USH = 0x1;
|
||||||
IT83XX_SMB_4P7A4P0H = 0;
|
IT8XXX2_SMB_4P7A4P0H = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set clock frequency for i2c port A, B , or C */
|
/* Set clock frequency for i2c port A, B , or C */
|
||||||
static void i2c_standard_port_set_frequency(const struct device *dev,
|
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;
|
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.
|
* for setting. So we can adjust tlow to meet timing.
|
||||||
* The others use basic 50/100/1000 KHz setting.
|
* 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);
|
i2c_standard_port_timing_regs_400khz(config->port);
|
||||||
} else {
|
} 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. */
|
/* This field defines the SMCLK0/1/2 clock/data low timeout. */
|
||||||
IT83XX_SMB_25MS = I2C_CLK_LOW_TIMEOUT;
|
IT8XXX2_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int i2c_it8xxx2_configure(const struct device *dev,
|
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;
|
const struct i2c_it8xxx2_config *config = dev->config;
|
||||||
struct i2c_it8xxx2_data *const data = dev->data;
|
struct i2c_it8xxx2_data *const data = dev->data;
|
||||||
uint32_t freq, freq_set;
|
uint32_t freq_set;
|
||||||
|
|
||||||
if (!(I2C_MODE_MASTER & dev_config_raw)) {
|
if (!(I2C_MODE_MASTER & dev_config_raw)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -330,26 +236,19 @@ static int i2c_it8xxx2_configure(const struct device *dev,
|
||||||
|
|
||||||
switch (data->bus_freq) {
|
switch (data->bus_freq) {
|
||||||
case I2C_SPEED_STANDARD:
|
case I2C_SPEED_STANDARD:
|
||||||
freq = 100;
|
freq_set = IT8XXX2_SMB_SMCLKS_100K;
|
||||||
freq_set = 2;
|
|
||||||
break;
|
break;
|
||||||
case I2C_SPEED_FAST:
|
case I2C_SPEED_FAST:
|
||||||
freq = 400;
|
freq_set = IT8XXX2_SMB_SMCLKS_400K;
|
||||||
freq_set = 3;
|
|
||||||
break;
|
break;
|
||||||
case I2C_SPEED_FAST_PLUS:
|
case I2C_SPEED_FAST_PLUS:
|
||||||
freq = 1000;
|
freq_set = IT8XXX2_SMB_SMCLKS_1M;
|
||||||
freq_set = 4;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config->port < I2C_STANDARD_PORT_COUNT) {
|
i2c_standard_port_set_frequency(dev, config->bitrate, freq_set);
|
||||||
i2c_standard_port_set_frequency(dev, freq, freq_set);
|
|
||||||
} else {
|
|
||||||
i2c_enhanced_port_set_frequency(dev, freq);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -384,180 +283,6 @@ static int i2c_it8xxx2_get_config(const struct device *dev,
|
||||||
return 0;
|
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)
|
static void i2c_r_last_byte(const struct device *dev)
|
||||||
{
|
{
|
||||||
struct i2c_it8xxx2_data *data = dev->data;
|
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.
|
* when the next byte will be the last byte for i2c read.
|
||||||
*/
|
*/
|
||||||
if ((data->msgs->flags & I2C_MSG_STOP) &&
|
if ((data->msgs->flags & I2C_MSG_STOP) &&
|
||||||
(data->ridx == data->msgs->len - 1)) {
|
(data->ridx == data->msgs->len - 1)) {
|
||||||
IT83XX_SMB_HOCTL(base) |= 0x20;
|
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;
|
uint8_t *base = config->base;
|
||||||
|
|
||||||
/* I2C switch direction */
|
/* I2C switch direction */
|
||||||
if (IT83XX_SMB_HOCTL2(base) & 0x08) {
|
if (IT8XXX2_SMB_HOCTL2(base) & IT8XXX2_SMB_I2C_SW_EN) {
|
||||||
i2c_r_last_byte(dev);
|
i2c_r_last_byte(dev);
|
||||||
IT83XX_SMB_HOSTA(base) = HOSTA_NEXT_BYTE;
|
IT8XXX2_SMB_HOSTA(base) = HOSTA_NEXT_BYTE;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* bit2, I2C switch direction wait.
|
* bit2, I2C switch direction wait.
|
||||||
* bit3, I2C switch direction enable.
|
* bit3, I2C switch direction enable.
|
||||||
*/
|
*/
|
||||||
IT83XX_SMB_HOCTL2(base) |= 0x0C;
|
IT8XXX2_SMB_HOCTL2(base) |= IT8XXX2_SMB_I2C_SW_EN |
|
||||||
IT83XX_SMB_HOSTA(base) = HOSTA_NEXT_BYTE;
|
IT8XXX2_SMB_I2C_SW_WAIT;
|
||||||
|
IT8XXX2_SMB_HOSTA(base) = HOSTA_NEXT_BYTE;
|
||||||
i2c_r_last_byte(dev);
|
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) {
|
if (data->msgs->flags & I2C_MSG_START) {
|
||||||
/* i2c enable */
|
/* 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.
|
* bit0, Direction of the host transfer.
|
||||||
* bit[1:7}, Address of the targeted slave.
|
* 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 */
|
/* clear start flag */
|
||||||
data->msgs->flags &= ~I2C_MSG_START;
|
data->msgs->flags &= ~I2C_MSG_START;
|
||||||
/*
|
/*
|
||||||
|
@ -619,14 +348,19 @@ static int i2c_tran_read(const struct device *dev)
|
||||||
* bit6, start.
|
* bit6, start.
|
||||||
*/
|
*/
|
||||||
if ((data->msgs->len == 1) &&
|
if ((data->msgs->len == 1) &&
|
||||||
(data->msgs->flags & I2C_MSG_STOP)) {
|
(data->msgs->flags & I2C_MSG_STOP)) {
|
||||||
IT83XX_SMB_HOCTL(base) = 0x7D;
|
IT8XXX2_SMB_HOCTL(base) = IT8XXX2_SMB_SRT |
|
||||||
|
IT8XXX2_SMB_LABY |
|
||||||
|
IT8XXX2_SMB_SMCD_EXTND |
|
||||||
|
IT8XXX2_SMB_INTREN;
|
||||||
} else {
|
} else {
|
||||||
IT83XX_SMB_HOCTL(base) = 0x5D;
|
IT8XXX2_SMB_HOCTL(base) = IT8XXX2_SMB_SRT |
|
||||||
|
IT8XXX2_SMB_SMCD_EXTND |
|
||||||
|
IT8XXX2_SMB_INTREN;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((data->i2ccs == I2C_CH_REPEAT_START) ||
|
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) {
|
if (data->i2ccs == I2C_CH_REPEAT_START) {
|
||||||
/* write to read */
|
/* write to read */
|
||||||
i2c_w2r_change_direction(dev);
|
i2c_w2r_change_direction(dev);
|
||||||
|
@ -634,14 +368,14 @@ static int i2c_tran_read(const struct device *dev)
|
||||||
/* For last byte */
|
/* For last byte */
|
||||||
i2c_r_last_byte(dev);
|
i2c_r_last_byte(dev);
|
||||||
/* W/C for next byte */
|
/* W/C for next byte */
|
||||||
IT83XX_SMB_HOSTA(base) = HOSTA_NEXT_BYTE;
|
IT8XXX2_SMB_HOSTA(base) = HOSTA_NEXT_BYTE;
|
||||||
}
|
}
|
||||||
data->i2ccs = I2C_CH_NORMAL;
|
data->i2ccs = I2C_CH_NORMAL;
|
||||||
irq_enable(config->i2c_irq_base);
|
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) {
|
if (data->ridx < data->msgs->len) {
|
||||||
/* To get received data. */
|
/* To get received data. */
|
||||||
*(data->msgs->buf++) = IT83XX_SMB_HOBDB(base);
|
*(data->msgs->buf++) = IT8XXX2_SMB_HOBDB(base);
|
||||||
data->ridx++;
|
data->ridx++;
|
||||||
/* For last byte */
|
/* For last byte */
|
||||||
i2c_r_last_byte(dev);
|
i2c_r_last_byte(dev);
|
||||||
|
@ -650,7 +384,7 @@ static int i2c_tran_read(const struct device *dev)
|
||||||
data->msgs->len = 0;
|
data->msgs->len = 0;
|
||||||
if (data->msgs->flags & I2C_MSG_STOP) {
|
if (data->msgs->flags & I2C_MSG_STOP) {
|
||||||
/* W/C for finish */
|
/* W/C for finish */
|
||||||
IT83XX_SMB_HOSTA(base) =
|
IT8XXX2_SMB_HOSTA(base) =
|
||||||
HOSTA_NEXT_BYTE;
|
HOSTA_NEXT_BYTE;
|
||||||
|
|
||||||
data->stop = 1;
|
data->stop = 1;
|
||||||
|
@ -660,7 +394,7 @@ static int i2c_tran_read(const struct device *dev)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* W/C for next byte */
|
/* W/C for next byte */
|
||||||
IT83XX_SMB_HOSTA(base) =
|
IT8XXX2_SMB_HOSTA(base) =
|
||||||
HOSTA_NEXT_BYTE;
|
HOSTA_NEXT_BYTE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -678,14 +412,16 @@ static int i2c_tran_write(const struct device *dev)
|
||||||
|
|
||||||
if (data->msgs->flags & I2C_MSG_START) {
|
if (data->msgs->flags & I2C_MSG_START) {
|
||||||
/* i2c enable */
|
/* 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.
|
* bit0, Direction of the host transfer.
|
||||||
* bit[1:7}, Address of the targeted slave.
|
* 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 */
|
/* Send first byte */
|
||||||
IT83XX_SMB_HOBDB(base) = *(data->msgs->buf++);
|
IT8XXX2_SMB_HOBDB(base) = *(data->msgs->buf++);
|
||||||
|
|
||||||
data->widx++;
|
data->widx++;
|
||||||
/* clear start flag */
|
/* clear start flag */
|
||||||
|
@ -695,17 +431,19 @@ static int i2c_tran_write(const struct device *dev)
|
||||||
* bit[2:4}, Extend command.
|
* bit[2:4}, Extend command.
|
||||||
* bit6, start.
|
* bit6, start.
|
||||||
*/
|
*/
|
||||||
IT83XX_SMB_HOCTL(base) = 0x5D;
|
IT8XXX2_SMB_HOCTL(base) = IT8XXX2_SMB_SRT |
|
||||||
|
IT8XXX2_SMB_SMCD_EXTND |
|
||||||
|
IT8XXX2_SMB_INTREN;
|
||||||
} else {
|
} else {
|
||||||
/* Host has completed the transmission of a byte */
|
/* 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) {
|
if (data->widx < data->msgs->len) {
|
||||||
/* Send next byte */
|
/* Send next byte */
|
||||||
IT83XX_SMB_HOBDB(base) = *(data->msgs->buf++);
|
IT8XXX2_SMB_HOBDB(base) = *(data->msgs->buf++);
|
||||||
|
|
||||||
data->widx++;
|
data->widx++;
|
||||||
/* W/C byte done for next byte */
|
/* 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) {
|
if (data->i2ccs == I2C_CH_REPEAT_START) {
|
||||||
data->i2ccs = I2C_CH_NORMAL;
|
data->i2ccs = I2C_CH_NORMAL;
|
||||||
|
@ -716,10 +454,10 @@ static int i2c_tran_write(const struct device *dev)
|
||||||
data->msgs->len = 0;
|
data->msgs->len = 0;
|
||||||
if (data->msgs->flags & I2C_MSG_STOP) {
|
if (data->msgs->flags & I2C_MSG_STOP) {
|
||||||
/* set I2C_EN = 0 */
|
/* 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 */
|
/* W/C byte done for finish */
|
||||||
IT83XX_SMB_HOSTA(base) =
|
IT8XXX2_SMB_HOSTA(base) = HOSTA_NEXT_BYTE;
|
||||||
HOSTA_NEXT_BYTE;
|
|
||||||
|
|
||||||
data->stop = 1;
|
data->stop = 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -739,69 +477,39 @@ static int i2c_transaction(const struct device *dev)
|
||||||
const struct i2c_it8xxx2_config *config = dev->config;
|
const struct i2c_it8xxx2_config *config = dev->config;
|
||||||
uint8_t *base = config->base;
|
uint8_t *base = config->base;
|
||||||
|
|
||||||
if (config->port < I2C_STANDARD_PORT_COUNT) {
|
/* any error */
|
||||||
/* any error */
|
if (IT8XXX2_SMB_HOSTA(base) & HOSTA_ANY_ERROR) {
|
||||||
if (IT83XX_SMB_HOSTA(base) & HOSTA_ANY_ERROR) {
|
data->err = (IT8XXX2_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;
|
|
||||||
} else {
|
} else {
|
||||||
|
if (!data->stop) {
|
||||||
/* no error */
|
if (data->msgs->flags & I2C_MSG_READ) {
|
||||||
if (!(enhanced_i2c_error(dev))) {
|
return i2c_tran_read(dev);
|
||||||
if (!data->stop) {
|
} else {
|
||||||
/* i2c read */
|
return i2c_tran_write(dev);
|
||||||
if (data->msgs->flags & I2C_MSG_READ) {
|
|
||||||
return enhanced_i2c_tran_read(dev);
|
|
||||||
/* i2c write */
|
|
||||||
} else {
|
|
||||||
return enhanced_i2c_tran_write(dev);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IT83XX_I2C_CTR(base) = E_STS_AND_HW_RST;
|
/* wait finish */
|
||||||
IT83XX_I2C_CTR1(base) = 0;
|
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;
|
data->stop = 0;
|
||||||
/* done doing work */
|
/* done doing work */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int i2c_it8xxx2_transfer(const struct device *dev, struct i2c_msg *msgs,
|
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;
|
struct i2c_it8xxx2_data *data = dev->data;
|
||||||
const struct i2c_it8xxx2_config *config;
|
const struct i2c_it8xxx2_config *config = dev->config;
|
||||||
int res;
|
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 */
|
/* Lock mutex of i2c controller */
|
||||||
k_mutex_lock(&data->mutex, K_FOREVER);
|
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,
|
* The transaction is dropped on any error(timeout, NACK, fail,
|
||||||
* bus error, device error).
|
* bus error, device error).
|
||||||
*/
|
*/
|
||||||
if (data->err)
|
if (data->err) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
data->err = ETIMEDOUT;
|
data->err = ETIMEDOUT;
|
||||||
/* reset i2c port */
|
/* reset i2c port */
|
||||||
i2c_reset(dev);
|
i2c_reset(dev);
|
||||||
printk("I2C ch%d:0x%X reset cause %d\n",
|
LOG_ERR("I2C ch%d:0x%X reset cause %d",
|
||||||
config->port, data->addr_16bit, I2C_RC_TIMEOUT);
|
config->port, data->addr_16bit, I2C_RC_TIMEOUT);
|
||||||
/* If this message is sent fail, drop the transaction. */
|
/* If this message is sent fail, drop the transaction. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -898,7 +607,7 @@ static int i2c_it8xxx2_init(const struct device *dev)
|
||||||
struct i2c_it8xxx2_data *data = dev->data;
|
struct i2c_it8xxx2_data *data = dev->data;
|
||||||
const struct i2c_it8xxx2_config *config = dev->config;
|
const struct i2c_it8xxx2_config *config = dev->config;
|
||||||
uint8_t *base = config->base;
|
uint8_t *base = config->base;
|
||||||
uint32_t bitrate_cfg, offset = 0;
|
uint32_t bitrate_cfg;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -912,68 +621,34 @@ static int i2c_it8xxx2_init(const struct device *dev)
|
||||||
k_mutex_init(&data->mutex);
|
k_mutex_init(&data->mutex);
|
||||||
k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT);
|
k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT);
|
||||||
|
|
||||||
switch ((uint32_t)base) {
|
/* Enable clock to specified peripheral */
|
||||||
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. */
|
|
||||||
volatile uint8_t *reg = (volatile uint8_t *)
|
volatile uint8_t *reg = (volatile uint8_t *)
|
||||||
(IT83XX_ECPM_BASE + (offset >> 8));
|
(IT8XXX2_ECPM_BASE + (config->clock_gate_offset >> 8));
|
||||||
uint8_t reg_mask = offset & 0xff;
|
uint8_t reg_mask = config->clock_gate_offset & 0xff;
|
||||||
*reg &= ~reg_mask;
|
*reg &= ~reg_mask;
|
||||||
|
|
||||||
if (config->port < I2C_STANDARD_PORT_COUNT) {
|
/* Enable SMBus function */
|
||||||
/*
|
/*
|
||||||
* bit0, The SMBus host interface is enabled.
|
* bit0, The SMBus host interface is enabled.
|
||||||
* bit1, Enable to communicate with I2C device
|
* bit1, Enable to communicate with I2C device
|
||||||
* and support I2C-compatible cycles.
|
* and support I2C-compatible cycles.
|
||||||
* bit4, This bit controls the reset mechanism
|
* bit4, This bit controls the reset mechanism
|
||||||
* of SMBus master to handle the SMDAT
|
* of SMBus master to handle the SMDAT
|
||||||
* line low if 25ms reg timeout.
|
* line low if 25ms reg timeout.
|
||||||
*/
|
*/
|
||||||
IT83XX_SMB_HOCTL2(base) = 0x11;
|
IT8XXX2_SMB_HOCTL2(base) = IT8XXX2_SMB_SMD_TO_EN | IT8XXX2_SMB_SMHEN;
|
||||||
/*
|
/*
|
||||||
* bit1, Kill SMBus host transaction.
|
* bit1, Kill SMBus host transaction.
|
||||||
* bit0, Enable the interrupt for the master interface.
|
* bit0, Enable the interrupt for the master interface.
|
||||||
*/
|
*/
|
||||||
IT83XX_SMB_HOCTL(base) = 0x03;
|
IT8XXX2_SMB_HOCTL(base) = IT8XXX2_SMB_KILL | IT8XXX2_SMB_SMHEN;
|
||||||
IT83XX_SMB_HOCTL(base) = 0x01;
|
IT8XXX2_SMB_HOCTL(base) = IT8XXX2_SMB_SMHEN;
|
||||||
|
|
||||||
/* W/C host status register */
|
/* W/C host status register */
|
||||||
IT83XX_SMB_HOSTA(base) = HOSTA_ALL_WC_BIT;
|
IT8XXX2_SMB_HOSTA(base) = HOSTA_ALL_WC_BIT;
|
||||||
IT83XX_SMB_HOCTL2(base) = 0x00;
|
IT8XXX2_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Set clock frequency for I2C ports */
|
||||||
bitrate_cfg = i2c_map_dt_bitrate(config->bitrate);
|
bitrate_cfg = i2c_map_dt_bitrate(config->bitrate);
|
||||||
error = i2c_it8xxx2_configure(dev, I2C_MODE_MASTER | bitrate_cfg);
|
error = i2c_it8xxx2_configure(dev, I2C_MODE_MASTER | bitrate_cfg);
|
||||||
data->i2ccs = I2C_CH_NORMAL;
|
data->i2ccs = I2C_CH_NORMAL;
|
||||||
|
@ -1009,6 +684,11 @@ static int i2c_it8xxx2_recover_bus(const struct device *dev)
|
||||||
config->alts_list[SDA].pin,
|
config->alts_list[SDA].pin,
|
||||||
PINMUX_OUTPUT_ENABLED);
|
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 */
|
/* 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[SCL].pin, 1);
|
||||||
gpio_pin_set(config->gpio_dev, config->alts_list[SDA].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 */
|
/* reset i2c port */
|
||||||
i2c_reset(dev);
|
i2c_reset(dev);
|
||||||
printk("I2C ch%d reset cause %d\n", config->port,
|
LOG_ERR("I2C ch%d reset cause %d", config->port,
|
||||||
I2C_RC_NO_IDLE_FOR_START);
|
I2C_RC_NO_IDLE_FOR_START);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1065,37 +745,39 @@ static const struct i2c_driver_api i2c_it8xxx2_driver_api = {
|
||||||
.recover_bus = i2c_it8xxx2_recover_bus,
|
.recover_bus = i2c_it8xxx2_recover_bus,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define I2C_ITE_IT8XXX2_INIT(idx) \
|
#define I2C_ITE_IT8XXX2_INIT(inst) \
|
||||||
static void i2c_it8xxx2_config_func_##idx(void); \
|
static void i2c_it8xxx2_config_func_##inst(void); \
|
||||||
static const struct i2c_alts_cfg \
|
static const struct i2c_alts_cfg \
|
||||||
i2c_alts_##idx[DT_INST_NUM_PINCTRLS_BY_IDX(idx, 0)] = \
|
i2c_alts_##inst[DT_INST_NUM_PINCTRLS_BY_IDX(inst, 0)] = \
|
||||||
IT8XXX2_DT_ALT_ITEMS_LIST(idx); \
|
IT8XXX2_DT_ALT_ITEMS_LIST(inst); \
|
||||||
\
|
\
|
||||||
static const struct i2c_it8xxx2_config i2c_it8xxx2_cfg_##idx = { \
|
static const struct i2c_it8xxx2_config i2c_it8xxx2_cfg_##inst = { \
|
||||||
.base = (uint8_t *)(DT_INST_REG_ADDR(idx)), \
|
.base = (uint8_t *)(DT_INST_REG_ADDR(inst)), \
|
||||||
.irq_config_func = i2c_it8xxx2_config_func_##idx, \
|
.irq_config_func = i2c_it8xxx2_config_func_##inst, \
|
||||||
.bitrate = DT_INST_PROP(idx, clock_frequency), \
|
.bitrate = DT_INST_PROP(inst, clock_frequency), \
|
||||||
.i2c_irq_base = DT_INST_IRQN(idx), \
|
.i2c_irq_base = DT_INST_IRQN(inst), \
|
||||||
.port = DT_INST_PROP(idx, port_num), \
|
.port = DT_INST_PROP(inst, port_num), \
|
||||||
.alts_list = i2c_alts_##idx, \
|
.alts_list = i2c_alts_##inst, \
|
||||||
.gpio_dev = DEVICE_DT_GET(DT_INST_PHANDLE(idx, gpio_dev)), \
|
.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_##idx; \
|
\
|
||||||
\
|
static struct i2c_it8xxx2_data i2c_it8xxx2_data_##inst; \
|
||||||
I2C_DEVICE_DT_INST_DEFINE(idx, \
|
\
|
||||||
i2c_it8xxx2_init, NULL, \
|
I2C_DEVICE_DT_INST_DEFINE(inst, i2c_it8xxx2_init, \
|
||||||
&i2c_it8xxx2_data_##idx, \
|
NULL, \
|
||||||
&i2c_it8xxx2_cfg_##idx, POST_KERNEL, \
|
&i2c_it8xxx2_data_##inst, \
|
||||||
CONFIG_I2C_INIT_PRIORITY, \
|
&i2c_it8xxx2_cfg_##inst, \
|
||||||
&i2c_it8xxx2_driver_api); \
|
POST_KERNEL, \
|
||||||
\
|
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
|
||||||
static void i2c_it8xxx2_config_func_##idx(void) \
|
&i2c_it8xxx2_driver_api); \
|
||||||
{ \
|
\
|
||||||
IRQ_CONNECT(DT_INST_IRQN(idx), \
|
static void i2c_it8xxx2_config_func_##inst(void) \
|
||||||
0, \
|
{ \
|
||||||
i2c_it8xxx2_isr, \
|
IRQ_CONNECT(DT_INST_IRQN(inst), \
|
||||||
DEVICE_DT_INST_GET(idx), 0); \
|
0, \
|
||||||
|
i2c_it8xxx2_isr, \
|
||||||
|
DEVICE_DT_INST_GET(inst), 0); \
|
||||||
}
|
}
|
||||||
|
|
||||||
DT_INST_FOREACH_STATUS_OKAY(I2C_ITE_IT8XXX2_INIT)
|
DT_INST_FOREACH_STATUS_OKAY(I2C_ITE_IT8XXX2_INIT)
|
||||||
|
|
38
dts/bindings/i2c/ite,common-i2c.yaml
Normal file
38
dts/bindings/i2c/ite,common-i2c.yaml
Normal file
|
@ -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.
|
20
dts/bindings/i2c/ite,enhance-i2c.yaml
Normal file
20
dts/bindings/i2c/ite,enhance-i2c.yaml
Normal file
|
@ -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
|
|
@ -5,31 +5,4 @@ description: ITE it8xxx2 I2C
|
||||||
|
|
||||||
compatible: "ite,it8xxx2-i2c"
|
compatible: "ite,it8xxx2-i2c"
|
||||||
|
|
||||||
include: i2c-controller.yaml
|
include: ite,common-i2c.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.
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <dt-bindings/dt-util.h>
|
#include <dt-bindings/dt-util.h>
|
||||||
#include <dt-bindings/interrupt-controller/ite-intc.h>
|
#include <dt-bindings/interrupt-controller/ite-intc.h>
|
||||||
#include <dt-bindings/i2c/i2c.h>
|
#include <dt-bindings/i2c/i2c.h>
|
||||||
|
#include <dt-bindings/i2c/it8xxx2-i2c.h>
|
||||||
#include <dt-bindings/pinctrl/it8xxx2-pinctrl.h>
|
#include <dt-bindings/pinctrl/it8xxx2-pinctrl.h>
|
||||||
#include <dt-bindings/pwm/pwm.h>
|
#include <dt-bindings/pwm/pwm.h>
|
||||||
#include <dt-bindings/pwm/it8xxx2_pwm.h>
|
#include <dt-bindings/pwm/it8xxx2_pwm.h>
|
||||||
|
@ -660,87 +661,99 @@
|
||||||
&pinctrl_adc15 /* ADC15*/
|
&pinctrl_adc15 /* ADC15*/
|
||||||
&pinctrl_adc16>;/* ADC16*/
|
&pinctrl_adc16>;/* ADC16*/
|
||||||
};
|
};
|
||||||
|
|
||||||
i2c0: i2c@f01c40 {
|
i2c0: i2c@f01c40 {
|
||||||
compatible = "ite,it8xxx2-i2c";
|
compatible = "ite,it8xxx2-i2c";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
reg = <0x00f01c40 0x0040>;
|
reg = <0x00f01c40 0x0040>;
|
||||||
interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
|
interrupts = <IT8XXX2_IRQ_SMB_A IRQ_TYPE_LEVEL_HIGH>;
|
||||||
interrupt-parent = <&intc>;
|
interrupt-parent = <&intc>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
label = "I2C_0";
|
label = "I2C_0";
|
||||||
port-num = <0>;
|
port-num = <0>;
|
||||||
gpio-dev = <&gpiob>;
|
gpio-dev = <&gpiob>;
|
||||||
|
clock-gate-offset = <CGC_OFFSET_SMBA>;
|
||||||
pinctrl-0 = <&pinctrl_i2c_clk0 /* GPB3 */
|
pinctrl-0 = <&pinctrl_i2c_clk0 /* GPB3 */
|
||||||
&pinctrl_i2c_data0>; /* GPB4 */
|
&pinctrl_i2c_data0>; /* GPB4 */
|
||||||
};
|
};
|
||||||
|
|
||||||
i2c1: i2c@f01c80 {
|
i2c1: i2c@f01c80 {
|
||||||
compatible = "ite,it8xxx2-i2c";
|
compatible = "ite,it8xxx2-i2c";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
reg = <0x00f01c80 0x0040>;
|
reg = <0x00f01c80 0x0040>;
|
||||||
interrupts = <10 IRQ_TYPE_EDGE_FALLING>;
|
interrupts = <IT8XXX2_IRQ_SMB_B IRQ_TYPE_LEVEL_HIGH>;
|
||||||
interrupt-parent = <&intc>;
|
interrupt-parent = <&intc>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
label = "I2C_1";
|
label = "I2C_1";
|
||||||
port-num = <1>;
|
port-num = <1>;
|
||||||
gpio-dev = <&gpioc>;
|
gpio-dev = <&gpioc>;
|
||||||
|
clock-gate-offset = <CGC_OFFSET_SMBB>;
|
||||||
pinctrl-0 = <&pinctrl_i2c_clk1 /* GPC1 */
|
pinctrl-0 = <&pinctrl_i2c_clk1 /* GPC1 */
|
||||||
&pinctrl_i2c_data1>; /* GPC2 */
|
&pinctrl_i2c_data1>; /* GPC2 */
|
||||||
};
|
};
|
||||||
|
|
||||||
i2c2: i2c@f01cc0 {
|
i2c2: i2c@f01cc0 {
|
||||||
compatible = "ite,it8xxx2-i2c";
|
compatible = "ite,it8xxx2-i2c";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
reg = <0x00f01cc0 0x0040>;
|
reg = <0x00f01cc0 0x0040>;
|
||||||
interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
|
interrupts = <IT8XXX2_IRQ_SMB_C IRQ_TYPE_LEVEL_HIGH>;
|
||||||
interrupt-parent = <&intc>;
|
interrupt-parent = <&intc>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
label = "I2C_2";
|
label = "I2C_2";
|
||||||
port-num = <2>;
|
port-num = <2>;
|
||||||
gpio-dev = <&gpiof>;
|
gpio-dev = <&gpiof>;
|
||||||
|
clock-gate-offset = <CGC_OFFSET_SMBC>;
|
||||||
pinctrl-0 = <&pinctrl_i2c_clk2 /* GPF6 */
|
pinctrl-0 = <&pinctrl_i2c_clk2 /* GPF6 */
|
||||||
&pinctrl_i2c_data2>; /* GPF7 */
|
&pinctrl_i2c_data2>; /* GPF7 */
|
||||||
};
|
};
|
||||||
|
|
||||||
i2c3: i2c@f03680 {
|
i2c3: i2c@f03680 {
|
||||||
compatible = "ite,it8xxx2-i2c";
|
compatible = "ite,enhance-i2c";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
reg = <0x00f03680 0x0080>;
|
reg = <0x00f03680 0x0080>;
|
||||||
interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
|
interrupts = <IT8XXX2_IRQ_SMB_D IRQ_TYPE_LEVEL_HIGH>;
|
||||||
interrupt-parent = <&intc>;
|
interrupt-parent = <&intc>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
label = "I2C_3";
|
label = "I2C_3";
|
||||||
port-num = <3>;
|
port-num = <3>;
|
||||||
gpio-dev = <&gpioh>;
|
gpio-dev = <&gpioh>;
|
||||||
|
clock-gate-offset = <CGC_OFFSET_SMBD>;
|
||||||
pinctrl-0 = <&pinctrl_i2c_clk3_gph1 /* GPH1 */
|
pinctrl-0 = <&pinctrl_i2c_clk3_gph1 /* GPH1 */
|
||||||
&pinctrl_i2c_data3_gph2>; /* GPH2 */
|
&pinctrl_i2c_data3_gph2>; /* GPH2 */
|
||||||
};
|
};
|
||||||
|
|
||||||
i2c4: i2c@f03500 {
|
i2c4: i2c@f03500 {
|
||||||
compatible = "ite,it8xxx2-i2c";
|
compatible = "ite,enhance-i2c";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
reg = <0x00f03500 0x0080>;
|
reg = <0x00f03500 0x0080>;
|
||||||
interrupts = <152 IRQ_TYPE_EDGE_FALLING>;
|
interrupts = <IT8XXX2_IRQ_SMB_E IRQ_TYPE_LEVEL_HIGH>;
|
||||||
interrupt-parent = <&intc>;
|
interrupt-parent = <&intc>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
label = "I2C_4";
|
label = "I2C_4";
|
||||||
port-num = <4>;
|
port-num = <4>;
|
||||||
gpio-dev = <&gpioe>;
|
gpio-dev = <&gpioe>;
|
||||||
|
clock-gate-offset = <CGC_OFFSET_SMBE>;
|
||||||
pinctrl-0 = <&pinctrl_i2c_clk4 /* GPE0 */
|
pinctrl-0 = <&pinctrl_i2c_clk4 /* GPE0 */
|
||||||
&pinctrl_i2c_data4>; /* GPE7 */
|
&pinctrl_i2c_data4>; /* GPE7 */
|
||||||
};
|
};
|
||||||
|
|
||||||
i2c5: i2c@f03580 {
|
i2c5: i2c@f03580 {
|
||||||
compatible = "ite,it8xxx2-i2c";
|
compatible = "ite,enhance-i2c";
|
||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <0>;
|
#size-cells = <0>;
|
||||||
reg = <0x00f03580 0x0080>;
|
reg = <0x00f03580 0x0080>;
|
||||||
interrupts = <153 IRQ_TYPE_EDGE_FALLING>;
|
interrupts = <IT8XXX2_IRQ_SMB_F IRQ_TYPE_LEVEL_HIGH>;
|
||||||
interrupt-parent = <&intc>;
|
interrupt-parent = <&intc>;
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
label = "I2C_5";
|
label = "I2C_5";
|
||||||
port-num = <5>;
|
port-num = <5>;
|
||||||
gpio-dev = <&gpioa>;
|
gpio-dev = <&gpioa>;
|
||||||
|
clock-gate-offset = <CGC_OFFSET_SMBF>;
|
||||||
pinctrl-0 = <&pinctrl_i2c_clk5 /* GPA4 */
|
pinctrl-0 = <&pinctrl_i2c_clk5 /* GPA4 */
|
||||||
&pinctrl_i2c_data5>; /* GPA5 */
|
&pinctrl_i2c_data5>; /* GPA5 */
|
||||||
};
|
};
|
||||||
|
|
23
include/dt-bindings/i2c/it8xxx2-i2c.h
Normal file
23
include/dt-bindings/i2c/it8xxx2-i2c.h
Normal file
|
@ -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_ */
|
|
@ -17,12 +17,16 @@
|
||||||
/* Group 0 of INTC */
|
/* Group 0 of INTC */
|
||||||
#define IT8XXX2_IRQ_WU20 1
|
#define IT8XXX2_IRQ_WU20 1
|
||||||
#define IT8XXX2_IRQ_KBC_OBE 2
|
#define IT8XXX2_IRQ_KBC_OBE 2
|
||||||
|
#define IT8XXX2_IRQ_SMB_D 4
|
||||||
#define IT8XXX2_IRQ_WU23 6
|
#define IT8XXX2_IRQ_WU23 6
|
||||||
/* Group 1 */
|
/* Group 1 */
|
||||||
|
#define IT8XXX2_IRQ_SMB_A 9
|
||||||
|
#define IT8XXX2_IRQ_SMB_B 10
|
||||||
#define IT8XXX2_IRQ_WU26 12
|
#define IT8XXX2_IRQ_WU26 12
|
||||||
#define IT8XXX2_IRQ_WKINTC 13
|
#define IT8XXX2_IRQ_WKINTC 13
|
||||||
#define IT8XXX2_IRQ_WU25 14
|
#define IT8XXX2_IRQ_WU25 14
|
||||||
/* Group 2 */
|
/* Group 2 */
|
||||||
|
#define IT8XXX2_IRQ_SMB_C 16
|
||||||
#define IT8XXX2_IRQ_WU24 17
|
#define IT8XXX2_IRQ_WU24 17
|
||||||
#define IT8XXX2_IRQ_WU22 21
|
#define IT8XXX2_IRQ_WU22 21
|
||||||
/* Group 3 */
|
/* Group 3 */
|
||||||
|
@ -134,6 +138,8 @@
|
||||||
#define IT8XXX2_IRQ_WU125 146
|
#define IT8XXX2_IRQ_WU125 146
|
||||||
#define IT8XXX2_IRQ_WU126 147
|
#define IT8XXX2_IRQ_WU126 147
|
||||||
/* Group 19 */
|
/* Group 19 */
|
||||||
|
#define IT8XXX2_IRQ_SMB_E 152
|
||||||
|
#define IT8XXX2_IRQ_SMB_F 153
|
||||||
#define IT8XXX2_IRQ_TIMER3 155
|
#define IT8XXX2_IRQ_TIMER3 155
|
||||||
#define IT8XXX2_IRQ_TIMER4 156
|
#define IT8XXX2_IRQ_TIMER4 156
|
||||||
#define IT8XXX2_IRQ_TIMER5 157
|
#define IT8XXX2_IRQ_TIMER5 157
|
||||||
|
|
|
@ -703,113 +703,6 @@ struct pwm_it8xxx2_regs {
|
||||||
#define IT8XXX2_WUC_WUBEMR1 (IT8XXX2_WUC_BASE + 0x3c)
|
#define IT8XXX2_WUC_WUBEMR1 (IT8XXX2_WUC_BASE + 0x3c)
|
||||||
#define IT8XXX2_WUC_WUBEMR5 (IT8XXX2_WUC_BASE + 0x0f)
|
#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)
|
* (1Dxxh) Keyboard Matrix Scan control (KSCAN)
|
||||||
|
@ -1618,22 +1511,13 @@ struct adc_it8xxx2_regs {
|
||||||
/* Automatic hardware calibration enable */
|
/* Automatic hardware calibration enable */
|
||||||
#define IT8XXX2_ADC_AHCE BIT(7)
|
#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__
|
#ifndef __ASSEMBLER__
|
||||||
enum chip_pll_mode {
|
enum chip_pll_mode {
|
||||||
CHIP_PLL_DOZE = 0,
|
CHIP_PLL_DOZE = 0,
|
||||||
|
@ -1641,15 +1525,16 @@ enum chip_pll_mode {
|
||||||
CHIP_PLL_DEEP_DOZE = 3,
|
CHIP_PLL_DEEP_DOZE = 3,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#define IT8XXX2_ECPM_AUTOCG ECREG(IT83XX_ECPM_BASE + 0x04)
|
#define IT8XXX2_ECPM_PLLCTRL ECREG(IT8XXX2_ECPM_BASE + 0x03)
|
||||||
#define IT8XXX2_ECPM_CGCTRL3R ECREG(IT83XX_ECPM_BASE + 0x05)
|
#define IT8XXX2_ECPM_AUTOCG ECREG(IT8XXX2_ECPM_BASE + 0x04)
|
||||||
#define IT8XXX2_ECPM_PLLFREQR ECREG(IT83XX_ECPM_BASE + 0x06)
|
#define IT8XXX2_ECPM_CGCTRL3R ECREG(IT8XXX2_ECPM_BASE + 0x05)
|
||||||
#define IT8XXX2_ECPM_PLLCSS ECREG(IT83XX_ECPM_BASE + 0x08)
|
#define IT8XXX2_ECPM_PLLFREQR ECREG(IT8XXX2_ECPM_BASE + 0x06)
|
||||||
#define IT8XXX2_ECPM_SCDCR0 ECREG(IT83XX_ECPM_BASE + 0x0c)
|
#define IT8XXX2_ECPM_PLLCSS ECREG(IT8XXX2_ECPM_BASE + 0x08)
|
||||||
#define IT8XXX2_ECPM_SCDCR1 ECREG(IT83XX_ECPM_BASE + 0x0d)
|
#define IT8XXX2_ECPM_SCDCR0 ECREG(IT8XXX2_ECPM_BASE + 0x0c)
|
||||||
#define IT8XXX2_ECPM_SCDCR2 ECREG(IT83XX_ECPM_BASE + 0x0e)
|
#define IT8XXX2_ECPM_SCDCR1 ECREG(IT8XXX2_ECPM_BASE + 0x0d)
|
||||||
#define IT8XXX2_ECPM_SCDCR3 ECREG(IT83XX_ECPM_BASE + 0x0f)
|
#define IT8XXX2_ECPM_SCDCR2 ECREG(IT8XXX2_ECPM_BASE + 0x0e)
|
||||||
#define IT8XXX2_ECPM_SCDCR4 ECREG(IT83XX_ECPM_BASE + 0x10)
|
#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.
|
* 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 */
|
#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)
|
* (1Cxxh) SMBus Interface (SMB) registers
|
||||||
#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 IT8XXX2_SMB_BASE 0x00F01C00
|
||||||
#define IT83XX_SMB_25MS ECREG(IT83XX_SMB_BASE+0x04)
|
#define IT8XXX2_SMB_4P7USL ECREG(IT8XXX2_SMB_BASE + 0x00)
|
||||||
#define IT83XX_SMB_45P3USL ECREG(IT83XX_SMB_BASE+0x05)
|
#define IT8XXX2_SMB_4P0USL ECREG(IT8XXX2_SMB_BASE + 0x01)
|
||||||
#define IT83XX_SMB_45P3USH ECREG(IT83XX_SMB_BASE+0x06)
|
#define IT8XXX2_SMB_300NS ECREG(IT8XXX2_SMB_BASE + 0x02)
|
||||||
#define IT83XX_SMB_4P7A4P0H ECREG(IT83XX_SMB_BASE+0x07)
|
#define IT8XXX2_SMB_250NS ECREG(IT8XXX2_SMB_BASE + 0x03)
|
||||||
#define IT83XX_SMB_SLVISELR ECREG(IT83XX_SMB_BASE+0x08)
|
#define IT8XXX2_SMB_25MS ECREG(IT8XXX2_SMB_BASE + 0x04)
|
||||||
#define IT83XX_SMB_SCLKTS(ch) ECREG(IT83XX_SMB_BASE+0x09+ch)
|
#define IT8XXX2_SMB_45P3USL ECREG(IT8XXX2_SMB_BASE + 0x05)
|
||||||
#define IT83XX_SMB_CHSEF ECREG(IT83XX_SMB_BASE+0x11)
|
#define IT8XXX2_SMB_45P3USH ECREG(IT8XXX2_SMB_BASE + 0x06)
|
||||||
#define IT83XX_SMB_CHSAB ECREG(IT83XX_SMB_BASE+0x20)
|
#define IT8XXX2_SMB_4P7A4P0H ECREG(IT8XXX2_SMB_BASE + 0x07)
|
||||||
#define IT83XX_SMB_CHSCD ECREG(IT83XX_SMB_BASE+0x21)
|
#define IT8XXX2_SMB_SLVISELR ECREG(IT8XXX2_SMB_BASE + 0x08)
|
||||||
#define IT8XXX2_SMB_SFFCTL ECREG(IT83XX_SMB_BASE+0x55)
|
#define IT8XXX2_SMB_SCLKTS(ch) ECREG(IT8XXX2_SMB_BASE + 0x09 + ch)
|
||||||
#define IT83XX_SMB_HOSTA(base) ECREG(base+0x00)
|
#define IT8XXX2_SMB_CHSEF ECREG(IT8XXX2_SMB_BASE + 0x11)
|
||||||
#define IT83XX_SMB_HOCTL(base) ECREG(base+0x01)
|
#define IT8XXX2_SMB_CHSAB ECREG(IT8XXX2_SMB_BASE + 0x20)
|
||||||
#define IT83XX_SMB_HOCMD(base) ECREG(base+0x02)
|
#define IT8XXX2_SMB_CHSCD ECREG(IT8XXX2_SMB_BASE + 0x21)
|
||||||
#define IT83XX_SMB_TRASLA(base) ECREG(base+0x03)
|
#define IT8XXX2_SMB_SFFCTL ECREG(IT8XXX2_SMB_BASE + 0x55)
|
||||||
#define IT83XX_SMB_D0REG(base) ECREG(base+0x04)
|
#define IT8XXX2_SMB_HOSTA(base) ECREG(base + 0x00)
|
||||||
#define IT83XX_SMB_D1REG(base) ECREG(base+0x05)
|
#define IT8XXX2_SMB_HOCTL(base) ECREG(base + 0x01)
|
||||||
#define IT83XX_SMB_HOBDB(base) ECREG(base+0x06)
|
#define IT8XXX2_SMB_HOCMD(base) ECREG(base + 0x02)
|
||||||
#define IT83XX_SMB_PECERC(base) ECREG(base+0x07)
|
#define IT8XXX2_SMB_TRASLA(base) ECREG(base + 0x03)
|
||||||
#define IT83XX_SMB_SMBPCTL(base) ECREG(base+0x0A)
|
#define IT8XXX2_SMB_D0REG(base) ECREG(base + 0x04)
|
||||||
#define IT83XX_SMB_HOCTL2(base) ECREG(base+0x10)
|
#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
|
* Enhanced SMBus/I2C Interface
|
||||||
* Ch_D: 0x00F03680, Ch_E: 0x00F03500, Ch_F: 0x00F03580
|
* Ch_D: 0x00F03680, Ch_E: 0x00F03500, Ch_F: 0x00F03580
|
||||||
* Ch_D: ch = 0x03, Ch_E: ch = 0x00, Ch_F: ch = 0x01
|
* Ch_D: ch = 0x03, Ch_E: ch = 0x00, Ch_F: ch = 0x01
|
||||||
*/
|
*/
|
||||||
#define IT83XX_I2C_DRR(base) ECREG(base+0x00)
|
#define IT8XXX2_I2C_DRR(base) ECREG(base + 0x00)
|
||||||
#define IT83XX_I2C_PSR(base) ECREG(base+0x01)
|
#define IT8XXX2_I2C_PSR(base) ECREG(base + 0x01)
|
||||||
#define IT83XX_I2C_HSPR(base) ECREG(base+0x02)
|
#define IT8XXX2_I2C_HSPR(base) ECREG(base + 0x02)
|
||||||
#define IT83XX_I2C_STR(base) ECREG(base+0x03)
|
#define IT8XXX2_I2C_STR(base) ECREG(base + 0x03)
|
||||||
#define IT83XX_I2C_DHTR(base) ECREG(base+0x04)
|
#define IT8XXX2_I2C_DHTR(base) ECREG(base + 0x04)
|
||||||
#define IT83XX_I2C_TOR(base) ECREG(base+0x05)
|
#define IT8XXX2_I2C_TOR(base) ECREG(base + 0x05)
|
||||||
#define IT83XX_I2C_DTR(base) ECREG(base+0x08)
|
#define IT8XXX2_I2C_DTR(base) ECREG(base + 0x08)
|
||||||
#define IT83XX_I2C_CTR(base) ECREG(base+0x09)
|
#define IT8XXX2_I2C_CTR(base) ECREG(base + 0x09)
|
||||||
#define IT83XX_I2C_CTR1(base) ECREG(base+0x0A)
|
#define IT8XXX2_I2C_CTR1(base) ECREG(base + 0x0A)
|
||||||
#define IT83XX_I2C_BYTE_CNT_L(base) ECREG(base+0x0C)
|
#define IT8XXX2_I2C_BYTE_CNT_L(base) ECREG(base + 0x0C)
|
||||||
#define IT83XX_I2C_IRQ_ST(base) ECREG(base+0x0D)
|
#define IT8XXX2_I2C_IRQ_ST(base) ECREG(base + 0x0D)
|
||||||
#define IT83XX_I2C_IDR(base) ECREG(base+0x06)
|
#define IT8XXX2_I2C_IDR(base) ECREG(base + 0x06)
|
||||||
#define IT83XX_I2C_TOS(base) ECREG(base+0x07)
|
#define IT8XXX2_I2C_TOS(base) ECREG(base + 0x07)
|
||||||
#define IT83XX_I2C_IDR2(base) ECREG(base+0x1F)
|
#define IT8XXX2_I2C_IDR2(base) ECREG(base + 0x1F)
|
||||||
#define IT83XX_I2C_RAMHA(base) ECREG(base+0x23)
|
#define IT8XXX2_I2C_RAMHA(base) ECREG(base + 0x23)
|
||||||
#define IT83XX_I2C_RAMLA(base) ECREG(base+0x24)
|
#define IT8XXX2_I2C_RAMLA(base) ECREG(base + 0x24)
|
||||||
#define IT83XX_I2C_RAMHA2(base) ECREG(base+0x2B)
|
#define IT8XXX2_I2C_RAMHA2(base) ECREG(base + 0x2B)
|
||||||
#define IT83XX_I2C_RAMLA2(base) ECREG(base+0x2C)
|
#define IT8XXX2_I2C_RAMLA2(base) ECREG(base + 0x2C)
|
||||||
#define IT83XX_I2C_CMD_ADDH(base) ECREG(base+0x25)
|
#define IT8XXX2_I2C_CMD_ADDH(base) ECREG(base + 0x25)
|
||||||
#define IT83XX_I2C_CMD_ADDL(base) ECREG(base+0x26)
|
#define IT8XXX2_I2C_CMD_ADDL(base) ECREG(base + 0x26)
|
||||||
#define IT83XX_I2C_RAMH2A(base) ECREG(base+0x50)
|
#define IT8XXX2_I2C_RAMH2A(base) ECREG(base + 0x50)
|
||||||
#define IT83XX_I2C_CMD_ADDH2(base) ECREG(base+0x52)
|
#define IT8XXX2_I2C_CMD_ADDH2(base) ECREG(base + 0x52)
|
||||||
|
|
||||||
/* SMBus/I2C register fields */
|
/* 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 */
|
/* 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 */
|
/* 0x07: Time Out Status */
|
||||||
#define IT8XXX2_I2C_SCL_IN BIT(2)
|
#define IT8XXX2_I2C_SCL_IN BIT(2)
|
||||||
#define IT8XXX2_I2C_SDA_IN BIT(0)
|
#define IT8XXX2_I2C_SDA_IN BIT(0)
|
||||||
|
/* 0x0A: Control 1 */
|
||||||
|
#define IT8XXX2_I2C_MDL_EN BIT(1)
|
||||||
|
|
||||||
/* --- General Control (GCTRL) --- */
|
/* --- General Control (GCTRL) --- */
|
||||||
#define IT83XX_GCTRL_BASE 0x00F02000
|
#define IT83XX_GCTRL_BASE 0x00F02000
|
||||||
|
|
|
@ -52,6 +52,7 @@ void ite_intc_init(void);
|
||||||
void timer_5ms_one_shot(void);
|
void timer_5ms_one_shot(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
uint32_t chip_get_pll_freq(void);
|
||||||
void chip_pll_ctrl(enum chip_pll_mode mode);
|
void chip_pll_ctrl(enum chip_pll_mode mode);
|
||||||
void riscv_idle(enum chip_pll_mode mode, unsigned int key);
|
void riscv_idle(enum chip_pll_mode mode, unsigned int key);
|
||||||
|
|
||||||
|
|
|
@ -56,10 +56,6 @@ config GPIO_ITE_IT8XXX2
|
||||||
default y
|
default y
|
||||||
depends on GPIO
|
depends on GPIO
|
||||||
|
|
||||||
config I2C_ITE_IT8XXX2
|
|
||||||
default y
|
|
||||||
depends on I2C
|
|
||||||
|
|
||||||
config ADC_ITE_IT8XXX2
|
config ADC_ITE_IT8XXX2
|
||||||
default y
|
default y
|
||||||
depends on ADC
|
depends on ADC
|
||||||
|
|
|
@ -51,6 +51,42 @@ static const struct pll_config_t pll_configuration[] = {
|
||||||
.div_usbpd = 5}
|
.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)
|
void __intc_ram_code chip_pll_ctrl(enum chip_pll_mode mode)
|
||||||
{
|
{
|
||||||
volatile uint8_t _pll_ctrl __unused;
|
volatile uint8_t _pll_ctrl __unused;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue