drivers: i2c: add Andes atciic100 driver
Add I2C driver for Andes atciic100. Driver supports I2C target mode and tested on adp_xc7k_ae350 in runtime. Signed-off-by: Wei-Tai Lee <wtlee@andestech.com>
This commit is contained in:
parent
adffca1f30
commit
0f8d12d4ed
|
@ -38,6 +38,7 @@ zephyr_library_sources_ifdef(CONFIG_I2C_RCAR i2c_rcar.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_I2C_TCA954X i2c_tca954x.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_I2C_XEC_V2 i2c_mchp_xec_v2.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_I2C_GD32 i2c_gd32.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_I2C_ANDES_ATCIIC100 i2c_andes_atciic100.c)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_I2C_STM32_V1
|
||||
i2c_ll_stm32_v1.c
|
||||
|
|
|
@ -56,6 +56,7 @@ source "drivers/i2c/Kconfig.test"
|
|||
source "drivers/i2c/Kconfig.rcar"
|
||||
source "drivers/i2c/Kconfig.tca954x"
|
||||
source "drivers/i2c/Kconfig.gd32"
|
||||
source "drivers/i2c/Kconfig.andes_atciic100"
|
||||
|
||||
config I2C_INIT_PRIORITY
|
||||
int "Init priority"
|
||||
|
|
13
drivers/i2c/Kconfig.andes_atciic100
Normal file
13
drivers/i2c/Kconfig.andes_atciic100
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Kconfig Andes ATCIIC100 configuration option
|
||||
#
|
||||
# Copyright (c) 2022 Andes Technology Corporation.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
config I2C_ANDES_ATCIIC100
|
||||
bool "Andes ATCIIC100 I2C driver"
|
||||
default y
|
||||
depends on DT_HAS_ANDESTECH_ATCIIC100_ENABLED
|
||||
help
|
||||
Enable driver for the Andes ATCIIC100 I2C controller.
|
788
drivers/i2c/i2c_andes_atciic100.c
Normal file
788
drivers/i2c/i2c_andes_atciic100.c
Normal file
|
@ -0,0 +1,788 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Andes Technology Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file I2C driver for AndesTech atciic100 IP
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#include "i2c_andes_atciic100.h"
|
||||
|
||||
#define DT_DRV_COMPAT andestech_atciic100
|
||||
|
||||
typedef void (*atciic100_dt_init_func_t)(void);
|
||||
|
||||
struct i2c_atciic100_config {
|
||||
uint32_t base;
|
||||
uint32_t irq_num;
|
||||
atciic100_dt_init_func_t dt_init_fn;
|
||||
};
|
||||
|
||||
static int i2c_atciic100_controller_send(const struct device *dev,
|
||||
uint16_t addr, const uint8_t *data, uint32_t num, uint8_t flags);
|
||||
static int i2c_atciic100_controller_receive(const struct device *dev,
|
||||
uint16_t addr, uint8_t *data, uint32_t num, uint8_t flags);
|
||||
static void i2c_controller_fifo_write(const struct device *dev,
|
||||
uint8_t is_init);
|
||||
static void i2c_controller_fifo_read(const struct device *dev);
|
||||
static int i2c_atciic100_init(const struct device *dev);
|
||||
|
||||
#if defined(CONFIG_I2C_TARGET)
|
||||
static void i2c_atciic100_target_send(const struct device *dev,
|
||||
const uint8_t *data);
|
||||
static void i2c_atciic100_target_receive(const struct device *dev,
|
||||
uint8_t *data);
|
||||
#endif
|
||||
|
||||
static void i2c_atciic100_default_control(const struct device *dev)
|
||||
{
|
||||
struct i2c_atciic100_dev_data_t *dev_data = dev->data;
|
||||
uint32_t reg = 0;
|
||||
|
||||
k_sem_init(&dev_data->i2c_busy_sem, 1, 1);
|
||||
|
||||
/* Reset I2C bus */
|
||||
reg = sys_read32(I2C_CMD(dev));
|
||||
reg &= (~CMD_MSK);
|
||||
reg |= (CMD_RESET_I2C);
|
||||
sys_write32(reg, I2C_CMD(dev));
|
||||
|
||||
/* I2C query FIFO depth */
|
||||
reg = sys_read32(I2C_CFG(dev));
|
||||
switch (reg & 0x3) {
|
||||
case 0x0:
|
||||
dev_data->fifo_depth = 2;
|
||||
break;
|
||||
case 0x1:
|
||||
dev_data->fifo_depth = 4;
|
||||
break;
|
||||
case 0x2:
|
||||
dev_data->fifo_depth = 8;
|
||||
break;
|
||||
case 0x3:
|
||||
dev_data->fifo_depth = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* I2C setting: target mode(default), standard speed
|
||||
* 7-bit, CPU mode
|
||||
*/
|
||||
sys_write32(0x0, I2C_SET(dev));
|
||||
reg = sys_read32(I2C_SET(dev));
|
||||
reg |= ((SETUP_T_SUDAT_STD << 24) |
|
||||
(SETUP_T_SP_STD << 21) |
|
||||
(SETUP_T_HDDAT_STD << 16) |
|
||||
(SETUP_T_SCL_RATIO_STD << 13) |
|
||||
(SETUP_T_SCLHI_STD << 4) |
|
||||
SETUP_I2C_EN);
|
||||
|
||||
sys_write32(reg, I2C_SET(dev));
|
||||
|
||||
dev_data->driver_state = I2C_DRV_INIT;
|
||||
dev_data->status.mode = 0;
|
||||
dev_data->status.arbitration_lost = 0;
|
||||
dev_data->status.target_ack = 0;
|
||||
}
|
||||
|
||||
static int i2c_atciic100_configure(const struct device *dev,
|
||||
uint32_t dev_config)
|
||||
{
|
||||
struct i2c_atciic100_dev_data_t *dev_data = dev->data;
|
||||
uint32_t reg = 0;
|
||||
int ret = 0;
|
||||
|
||||
reg = sys_read32(I2C_SET(dev));
|
||||
|
||||
switch (I2C_SPEED_GET(dev_config)) {
|
||||
case I2C_SPEED_STANDARD:
|
||||
reg |= SETUP_SPEED_STD;
|
||||
break;
|
||||
|
||||
case I2C_SPEED_FAST:
|
||||
reg |= SETUP_SPEED_FAST;
|
||||
break;
|
||||
|
||||
case I2C_SPEED_FAST_PLUS:
|
||||
reg |= SETUP_SPEED_FAST_PLUS;
|
||||
|
||||
case I2C_SPEED_HIGH:
|
||||
ret = -EIO;
|
||||
goto unlock;
|
||||
case 0x00:
|
||||
break;
|
||||
default:
|
||||
ret = -EIO;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (dev_config & I2C_MODE_CONTROLLER) {
|
||||
reg |= SETUP_CONTROLLER;
|
||||
dev_data->status.mode = 1;
|
||||
} else {
|
||||
reg &= ~SETUP_CONTROLLER;
|
||||
dev_data->status.mode = 0;
|
||||
}
|
||||
|
||||
if (dev_config & I2C_ADDR_10_BITS) {
|
||||
reg |= SETUP_ADDRESSING;
|
||||
} else {
|
||||
reg &= ~SETUP_ADDRESSING;
|
||||
}
|
||||
|
||||
sys_write32(reg, I2C_SET(dev));
|
||||
|
||||
dev_data->driver_state |= I2C_DRV_CFG_PARAM;
|
||||
|
||||
unlock:
|
||||
k_sem_give(&dev_data->i2c_busy_sem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i2c_atciic100_transfer(const struct device *dev,
|
||||
struct i2c_msg *msgs, uint8_t num_msgs, uint16_t addr)
|
||||
{
|
||||
struct i2c_atciic100_dev_data_t *dev_data = dev->data;
|
||||
int ret = 0;
|
||||
int count = 0;
|
||||
uint8_t burst_write_len = msgs[0].len + msgs[1].len;
|
||||
uint8_t burst_write_buf[I2C_MAX_COUNT + BURST_CMD_COUNT];
|
||||
|
||||
if ((msgs[0].flags == I2C_MSG_WRITE)
|
||||
&& (msgs[1].flags == (I2C_MSG_WRITE | I2C_MSG_STOP))) {
|
||||
|
||||
burst_write_len = msgs[0].len + msgs[1].len;
|
||||
if (burst_write_len > MAX_XFER_SZ) {
|
||||
return -EIO;
|
||||
}
|
||||
for (count = 0; count < burst_write_len; count++) {
|
||||
if (count < msgs[0].len) {
|
||||
burst_write_buf[count] = msgs[0].buf[count];
|
||||
} else {
|
||||
burst_write_buf[count] =
|
||||
msgs[1].buf[count - msgs[0].len];
|
||||
}
|
||||
}
|
||||
ret = i2c_atciic100_controller_send(dev, addr, burst_write_buf,
|
||||
burst_write_len, true);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < num_msgs; i++) {
|
||||
if ((msgs[i].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) {
|
||||
ret = i2c_atciic100_controller_send(dev,
|
||||
addr, msgs[i].buf, msgs[i].len, msgs[i].flags);
|
||||
} else {
|
||||
ret = i2c_atciic100_controller_receive(dev,
|
||||
addr, msgs[i].buf, msgs[i].len, msgs[i].flags);
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
/* Wait for transfer complete */
|
||||
k_sem_take(&dev_data->i2c_busy_sem, K_FOREVER);
|
||||
|
||||
if (dev_data->status.target_ack != 1) {
|
||||
k_sem_give(&dev_data->i2c_busy_sem);
|
||||
return -EIO;
|
||||
}
|
||||
dev_data->status.target_ack = 0;
|
||||
k_sem_give(&dev_data->i2c_busy_sem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int i2c_atciic100_controller_send(const struct device *dev,
|
||||
uint16_t addr, const uint8_t *data, uint32_t num, uint8_t flags)
|
||||
{
|
||||
struct i2c_atciic100_dev_data_t *dev_data = dev->data;
|
||||
uint32_t reg = 0;
|
||||
|
||||
/*
|
||||
* Max to 10-bit address.
|
||||
* Parameters data = null or num = 0 means no payload for
|
||||
* acknowledge polling. If no I2C payload, set Phase_data=0x0.
|
||||
*/
|
||||
if (addr > 0x3FF) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
k_sem_take(&dev_data->i2c_busy_sem, K_FOREVER);
|
||||
|
||||
/* Disable all I2C interrupts */
|
||||
reg = sys_read32(I2C_INTE(dev));
|
||||
reg &= (~IEN_ALL);
|
||||
sys_write32(reg, I2C_INTE(dev));
|
||||
|
||||
dev_data->status.mode = 1;
|
||||
reg = sys_read32(I2C_SET(dev));
|
||||
reg |= SETUP_CONTROLLER;
|
||||
sys_write32(reg, I2C_SET(dev));
|
||||
|
||||
/* Direction => tx:0, rx:1 */
|
||||
dev_data->status.arbitration_lost = 0;
|
||||
dev_data->status.target_ack = 0;
|
||||
dev_data->driver_state = I2C_DRV_CONTROLLER_TX;
|
||||
|
||||
/* Step1, Clear FIFO */
|
||||
reg = sys_read32(I2C_CMD(dev));
|
||||
reg &= (~CMD_MSK);
|
||||
reg |= (CMD_CLEAR_FIFO);
|
||||
sys_write32(reg, I2C_CMD(dev));
|
||||
|
||||
/*
|
||||
* Step2
|
||||
* Enable START, ADDRESS, DATA and STOP phase.
|
||||
* If no payload, clear DATA phase.
|
||||
* STOP condition triggered when transmission finish in controller mode.
|
||||
* The bus is busy until STOP condition triggered.
|
||||
* For 10-bit target address, we must set STOP bit.
|
||||
* I2C direction : controller tx, set xfer DATA count.
|
||||
*/
|
||||
reg = sys_read32(I2C_CTRL(dev));
|
||||
reg &= (~(CTRL_PHASE_START | CTRL_PHASE_ADDR | CTRL_PHASE_STOP |
|
||||
CTRL_DIR | CTRL_DATA_COUNT));
|
||||
|
||||
if (flags & I2C_MSG_STOP) {
|
||||
reg |= CTRL_PHASE_STOP;
|
||||
}
|
||||
if ((flags & I2C_MSG_RESTART) == 0) {
|
||||
reg |= (CTRL_PHASE_START | CTRL_PHASE_ADDR);
|
||||
}
|
||||
if (num) {
|
||||
reg |= (CTRL_PHASE_DATA | (num & CTRL_DATA_COUNT));
|
||||
}
|
||||
|
||||
sys_write32(reg, I2C_CTRL(dev));
|
||||
|
||||
/* Step3 init I2C info */
|
||||
dev_data->target_addr = addr;
|
||||
dev_data->xfered_data_wt_ptr = 0;
|
||||
dev_data->xfer_wt_num = num;
|
||||
dev_data->middleware_tx_buf = (uint8_t *)data;
|
||||
|
||||
/* In I2C target address, general call address = 0x0(7-bit or 10-bit) */
|
||||
reg = sys_read32(I2C_ADDR(dev));
|
||||
reg &= (~TARGET_ADDR_MSK);
|
||||
reg |= (dev_data->target_addr & (TARGET_ADDR_MSK));
|
||||
sys_write32(reg, I2C_ADDR(dev));
|
||||
|
||||
/*
|
||||
* Step4 Enable Interrupts: Complete, Arbitration Lose
|
||||
* Enable/Disable the FIFO Empty Interrupt
|
||||
* Fill the FIFO before enabling FIFO Empty Interrupt
|
||||
*/
|
||||
reg = sys_read32(I2C_INTE(dev));
|
||||
|
||||
i2c_controller_fifo_write(dev, 1);
|
||||
|
||||
reg |= (IEN_CMPL | IEN_ARB_LOSE | IEN_ADDR_HIT);
|
||||
|
||||
if (num > 0) {
|
||||
reg |= IEN_FIFO_EMPTY;
|
||||
} else {
|
||||
reg &= (~IEN_FIFO_EMPTY);
|
||||
}
|
||||
|
||||
sys_write32(reg, I2C_INTE(dev));
|
||||
|
||||
/*
|
||||
* Step5,
|
||||
* I2C Write 0x1 to the Command register to issue the transaction
|
||||
*/
|
||||
reg = sys_read32(I2C_CMD(dev));
|
||||
reg &= (~CMD_MSK);
|
||||
reg |= (CMD_ISSUE_TRANSACTION);
|
||||
sys_write32(reg, I2C_CMD(dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2c_atciic100_controller_receive(const struct device *dev,
|
||||
uint16_t addr, uint8_t *data, uint32_t num, uint8_t flags)
|
||||
{
|
||||
struct i2c_atciic100_dev_data_t *dev_data = dev->data;
|
||||
uint32_t reg = 0;
|
||||
|
||||
/*
|
||||
* Max to 10-bit address.
|
||||
* Parameters data = null or num = 0 means no payload for
|
||||
* acknowledge polling. If no I2C payload, set Phase_data=0x0.
|
||||
*/
|
||||
if (addr > 0x3FF) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
k_sem_take(&dev_data->i2c_busy_sem, K_FOREVER);
|
||||
|
||||
/* Disable all I2C interrupts */
|
||||
reg = sys_read32(I2C_INTE(dev));
|
||||
reg &= (~IEN_ALL);
|
||||
sys_write32(reg, I2C_INTE(dev));
|
||||
|
||||
dev_data->status.mode = 1;
|
||||
reg = sys_read32(I2C_SET(dev));
|
||||
reg |= SETUP_CONTROLLER;
|
||||
sys_write32(reg, I2C_SET(dev));
|
||||
|
||||
/* Direction => tx:0, rx:1 */
|
||||
dev_data->status.arbitration_lost = 0;
|
||||
dev_data->status.target_ack = 0;
|
||||
dev_data->driver_state = I2C_DRV_CONTROLLER_RX;
|
||||
|
||||
/* Step1, Clear FIFO */
|
||||
reg = sys_read32(I2C_CMD(dev));
|
||||
reg &= (~CMD_MSK);
|
||||
reg |= (CMD_CLEAR_FIFO);
|
||||
sys_write32(reg, I2C_CMD(dev));
|
||||
|
||||
/*
|
||||
* Step2
|
||||
* Enable START, ADDRESS, DATA and STOP phase.
|
||||
* If no payload, clear DATA phase.
|
||||
* STOP condition triggered when transmission finish in Controller mode.
|
||||
* The bus is busy until STOP condition triggered.
|
||||
* For 10-bit target address, we must set STOP bit.
|
||||
* I2C direction : controller rx, set xfer data count.
|
||||
*/
|
||||
reg = sys_read32(I2C_CTRL(dev));
|
||||
reg &= (~(CTRL_PHASE_START | CTRL_PHASE_ADDR | CTRL_PHASE_STOP |
|
||||
CTRL_DIR | CTRL_DATA_COUNT));
|
||||
reg |= (CTRL_PHASE_START | CTRL_PHASE_ADDR | CTRL_DIR);
|
||||
|
||||
if (flags & I2C_MSG_STOP) {
|
||||
reg |= CTRL_PHASE_STOP;
|
||||
}
|
||||
if (num) {
|
||||
reg |= (CTRL_PHASE_DATA | (num & CTRL_DATA_COUNT));
|
||||
}
|
||||
|
||||
sys_write32(reg, I2C_CTRL(dev));
|
||||
|
||||
/* Step3 init I2C info */
|
||||
dev_data->target_addr = addr;
|
||||
dev_data->xfered_data_rd_ptr = 0;
|
||||
dev_data->xfer_rd_num = num;
|
||||
dev_data->middleware_rx_buf = (uint8_t *)data;
|
||||
|
||||
/* In I2C target address, general call address = 0x0(7-bit or 10-bit) */
|
||||
reg = sys_read32(I2C_ADDR(dev));
|
||||
reg &= (~TARGET_ADDR_MSK);
|
||||
reg |= (dev_data->target_addr & (TARGET_ADDR_MSK));
|
||||
sys_write32(reg, I2C_ADDR(dev));
|
||||
|
||||
/*
|
||||
* Step4 Enable Interrupts: Complete, Arbitration Lose
|
||||
* Enable/Disable the FIFO Full Interrupt
|
||||
*/
|
||||
reg = sys_read32(I2C_INTE(dev));
|
||||
reg |= (IEN_CMPL | IEN_FIFO_FULL | IEN_ARB_LOSE | IEN_ADDR_HIT);
|
||||
sys_write32(reg, I2C_INTE(dev));
|
||||
|
||||
/*
|
||||
* Step5,
|
||||
* I2C write 0x1 to the Command register to issue the transaction
|
||||
*/
|
||||
reg = sys_read32(I2C_CMD(dev));
|
||||
reg &= (~CMD_MSK);
|
||||
reg |= (CMD_ISSUE_TRANSACTION);
|
||||
sys_write32(reg, I2C_CMD(dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_I2C_TARGET)
|
||||
static void i2c_atciic100_target_send(const struct device *dev,
|
||||
const uint8_t *data)
|
||||
{
|
||||
uint32_t reg = 0;
|
||||
|
||||
/* Clear FIFO */
|
||||
reg = sys_read32(I2C_CMD(dev));
|
||||
reg &= (~CMD_MSK);
|
||||
reg |= (CMD_CLEAR_FIFO);
|
||||
sys_write32(reg, I2C_CMD(dev));
|
||||
|
||||
sys_write32(*data, I2C_DATA(dev));
|
||||
}
|
||||
|
||||
static void i2c_atciic100_target_receive(const struct device *dev,
|
||||
uint8_t *data)
|
||||
{
|
||||
*data = sys_read32(I2C_DATA(dev));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void i2c_controller_fifo_write(const struct device *dev,
|
||||
uint8_t is_init)
|
||||
{
|
||||
struct i2c_atciic100_dev_data_t *dev_data = dev->data;
|
||||
uint32_t i = 0, write_fifo_count = 0, reg = 0;
|
||||
uint8_t write_data;
|
||||
|
||||
write_fifo_count = dev_data->xfer_wt_num - dev_data->xfered_data_wt_ptr;
|
||||
|
||||
if (write_fifo_count >= dev_data->fifo_depth) {
|
||||
write_fifo_count = dev_data->fifo_depth;
|
||||
}
|
||||
|
||||
if (is_init) {
|
||||
write_fifo_count = 2;
|
||||
}
|
||||
|
||||
/* I2C write a patch of data(FIFO_Depth) to FIFO */
|
||||
for (i = 0; i < write_fifo_count; i++) {
|
||||
|
||||
write_data =
|
||||
dev_data->middleware_tx_buf[dev_data->xfered_data_wt_ptr];
|
||||
sys_write32((write_data & DATA_MSK), I2C_DATA(dev));
|
||||
dev_data->xfered_data_wt_ptr++;
|
||||
|
||||
/* Disable the FIFO Empty Interrupt if no more data to send */
|
||||
if (dev_data->xfered_data_wt_ptr == dev_data->xfer_wt_num) {
|
||||
reg = sys_read32(I2C_INTE(dev));
|
||||
reg &= (~IEN_FIFO_EMPTY);
|
||||
sys_write32(reg, I2C_INTE(dev));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Basic fifo read function */
|
||||
static void i2c_controller_fifo_read(const struct device *dev)
|
||||
{
|
||||
struct i2c_atciic100_dev_data_t *dev_data = dev->data;
|
||||
uint32_t i = 0, read_fifo_count = 0, reg = 0;
|
||||
uint8_t read_data;
|
||||
|
||||
read_fifo_count = dev_data->xfer_rd_num - dev_data->xfered_data_rd_ptr;
|
||||
|
||||
if (read_fifo_count >= dev_data->fifo_depth) {
|
||||
read_fifo_count = dev_data->fifo_depth;
|
||||
}
|
||||
|
||||
/* I2C read a patch of data(FIFO_Depth) from FIFO */
|
||||
for (i = 0; i < read_fifo_count; i++) {
|
||||
|
||||
read_data = sys_read32(I2C_DATA(dev)) & DATA_MSK;
|
||||
|
||||
dev_data->middleware_rx_buf[dev_data->xfered_data_rd_ptr] =
|
||||
read_data;
|
||||
dev_data->xfered_data_rd_ptr++;
|
||||
|
||||
/* Disable the FIFO Full Interrupt if no more data to receive */
|
||||
if (dev_data->xfered_data_rd_ptr == dev_data->xfer_rd_num) {
|
||||
reg = sys_read32(I2C_INTE(dev));
|
||||
reg &= (~IEN_FIFO_FULL);
|
||||
sys_write32(reg, I2C_INTE(dev));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void i2c_fifo_empty_handler(const struct device *dev)
|
||||
{
|
||||
struct i2c_atciic100_dev_data_t *dev_data = dev->data;
|
||||
|
||||
if (dev_data->driver_state & I2C_DRV_CONTROLLER_TX) {
|
||||
i2c_controller_fifo_write(dev, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void i2c_fifo_full_handler(const struct device *dev)
|
||||
{
|
||||
struct i2c_atciic100_dev_data_t *dev_data = dev->data;
|
||||
|
||||
if (dev_data->driver_state & I2C_DRV_CONTROLLER_RX) {
|
||||
i2c_controller_fifo_read(dev);
|
||||
}
|
||||
}
|
||||
|
||||
static void i2c_cmpl_handler(const struct device *dev, uint32_t reg_stat)
|
||||
{
|
||||
struct i2c_atciic100_dev_data_t *dev_data = dev->data;
|
||||
uint32_t reg_set = 0, reg_ctrl = 0, reg = 0;
|
||||
|
||||
reg_set = sys_read32(I2C_SET(dev));
|
||||
|
||||
/* Controller mode */
|
||||
if (dev_data->status.mode == 1) {
|
||||
/* Disable all I2C interrupts */
|
||||
reg = sys_read32(I2C_INTE(dev));
|
||||
reg &= (~IEN_ALL);
|
||||
sys_write32(reg, I2C_INTE(dev));
|
||||
}
|
||||
|
||||
if (dev_data->driver_state &
|
||||
(I2C_DRV_CONTROLLER_TX | I2C_DRV_CONTROLLER_RX)) {
|
||||
|
||||
/* Get the remain number of data */
|
||||
reg_ctrl = sys_read32(I2C_CTRL(dev)) & CTRL_DATA_COUNT;
|
||||
|
||||
if (dev_data->driver_state & I2C_DRV_CONTROLLER_TX) {
|
||||
/* Clear & set driver state to controller tx complete */
|
||||
dev_data->driver_state = I2C_DRV_CONTROLLER_TX_CMPL;
|
||||
}
|
||||
|
||||
if (dev_data->driver_state & I2C_DRV_CONTROLLER_RX) {
|
||||
i2c_controller_fifo_read(dev);
|
||||
/* Clear & set driver state to controller rx complete */
|
||||
dev_data->driver_state = I2C_DRV_CONTROLLER_RX_CMPL;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_I2C_TARGET)
|
||||
if (dev_data->driver_state & (I2C_DRV_TARGET_TX | I2C_DRV_TARGET_RX)) {
|
||||
reg_set = sys_read32(I2C_SET(dev));
|
||||
reg_ctrl = sys_read32(I2C_CTRL(dev));
|
||||
|
||||
if (dev_data->driver_state & I2C_DRV_TARGET_TX) {
|
||||
dev_data->driver_state = I2C_DRV_TARGET_TX_CMPL;
|
||||
}
|
||||
|
||||
if (dev_data->driver_state & I2C_DRV_TARGET_RX) {
|
||||
dev_data->driver_state = I2C_DRV_TARGET_RX_CMPL;
|
||||
}
|
||||
|
||||
/* If the Completion Interrupt asserts,
|
||||
* clear the FIFO and go next transaction.
|
||||
*/
|
||||
uint32_t reg_cmd = 0;
|
||||
|
||||
reg_cmd = sys_read32(I2C_CMD(dev));
|
||||
reg_cmd &= (~CMD_MSK);
|
||||
reg_cmd |= (CMD_CLEAR_FIFO);
|
||||
sys_write32(reg_cmd, I2C_CMD(dev));
|
||||
}
|
||||
|
||||
/* Enable Completion & Address Hit Interrupt */
|
||||
/* Enable Byte Receive & Transfer for default target mode */
|
||||
reg = 0x0;
|
||||
reg |= (IEN_CMPL | IEN_ADDR_HIT | STATUS_BYTE_RECV | STATUS_BYTE_TRANS);
|
||||
sys_write32(reg, I2C_INTE(dev));
|
||||
|
||||
reg = sys_read32(I2C_SET(dev));
|
||||
reg &= ~(SETUP_CONTROLLER);
|
||||
sys_write32(reg, I2C_SET(dev));
|
||||
|
||||
reg &= (~TARGET_ADDR_MSK);
|
||||
reg |= (dev_data->target_config->address & (TARGET_ADDR_MSK));
|
||||
sys_write32(reg, I2C_ADDR(dev));
|
||||
|
||||
dev_data->driver_state = I2C_DRV_INIT;
|
||||
dev_data->status.mode = 0;
|
||||
dev_data->status.arbitration_lost = 0;
|
||||
#endif
|
||||
|
||||
k_sem_give(&dev_data->i2c_busy_sem);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_I2C_TARGET)
|
||||
static void andes_i2c_target_event(const struct device *dev,
|
||||
uint32_t reg_stat, uint32_t reg_ctrl)
|
||||
{
|
||||
struct i2c_atciic100_dev_data_t *dev_data = dev->data;
|
||||
uint32_t reg_set = 0;
|
||||
uint8_t val;
|
||||
/*
|
||||
* Here is the entry for target mode driver to detect
|
||||
* target RX/TX action depend on controller TX/RX action.
|
||||
* A new I2C data transaction(START-ADDRESS-DATA-STOP)
|
||||
*/
|
||||
if (reg_stat & STATUS_ADDR_HIT) {
|
||||
if (k_sem_take(&dev_data->i2c_busy_sem, K_NO_WAIT) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (((reg_ctrl & CTRL_DIR) >> 8) == I2C_TARGET_TX) {
|
||||
/* Notify middleware to do target rx action */
|
||||
dev_data->driver_state = I2C_DRV_TARGET_TX;
|
||||
dev_data->target_callbacks->read_requested
|
||||
(dev_data->target_config, &val);
|
||||
i2c_atciic100_target_send(dev, &val);
|
||||
|
||||
} else if (((reg_ctrl & CTRL_DIR) >> 8) == I2C_TARGET_RX) {
|
||||
/* Notify middleware to do target tx action */
|
||||
dev_data->driver_state = I2C_DRV_TARGET_RX;
|
||||
dev_data->target_callbacks->write_requested
|
||||
(dev_data->target_config);
|
||||
}
|
||||
reg_set |= (CMD_ACK);
|
||||
sys_write32(reg_set, I2C_CMD(dev));
|
||||
}
|
||||
|
||||
if (reg_stat & STATUS_BYTE_RECV) {
|
||||
i2c_atciic100_target_receive(dev, &val);
|
||||
dev_data->target_callbacks->write_received
|
||||
(dev_data->target_config, val);
|
||||
|
||||
reg_set = 0;
|
||||
if ((reg_stat & STATUS_CMPL) == 0) {
|
||||
reg_set |= (CMD_ACK);
|
||||
sys_write32(reg_set, I2C_CMD(dev));
|
||||
} else {
|
||||
reg_set |= (CMD_NACK);
|
||||
sys_write32(reg_set, I2C_CMD(dev));
|
||||
}
|
||||
|
||||
} else if (reg_stat & STATUS_BYTE_TRANS) {
|
||||
dev_data->target_callbacks->read_processed
|
||||
(dev_data->target_config, &val);
|
||||
i2c_atciic100_target_send(dev, &val);
|
||||
}
|
||||
|
||||
if (reg_stat & STATUS_CMPL) {
|
||||
i2c_cmpl_handler(dev, reg_stat);
|
||||
}
|
||||
}
|
||||
|
||||
static int i2c_atciic100_target_register(const struct device *dev,
|
||||
struct i2c_target_config *cfg)
|
||||
{
|
||||
struct i2c_atciic100_dev_data_t *dev_data = dev->data;
|
||||
uint16_t reg_addr = 0;
|
||||
uint32_t reg;
|
||||
|
||||
reg_addr &= (~TARGET_ADDR_MSK);
|
||||
reg_addr |= (cfg->address & (TARGET_ADDR_MSK));
|
||||
|
||||
sys_write32(reg_addr, I2C_ADDR(dev));
|
||||
|
||||
dev_data->target_callbacks = cfg->callbacks;
|
||||
dev_data->target_config = cfg;
|
||||
|
||||
/* Enable Completion & Address Hit Interrupt */
|
||||
/* Enable Byte Receive & Transfer for default target mode */
|
||||
reg = 0x0;
|
||||
reg |= (IEN_CMPL | IEN_ADDR_HIT | STATUS_BYTE_RECV | STATUS_BYTE_TRANS);
|
||||
sys_write32(reg, I2C_INTE(dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2c_atciic100_target_unregister(const struct device *dev,
|
||||
struct i2c_target_config *cfg)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
/* Disable all I2C interrupts */
|
||||
reg = sys_read32(I2C_INTE(dev));
|
||||
reg &= (~IEN_ALL);
|
||||
sys_write32(reg, I2C_INTE(dev));
|
||||
|
||||
sys_write32(0x0, I2C_ADDR(dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void i2c_atciic100_irq_handler(void *arg)
|
||||
{
|
||||
const struct device *dev = (struct device *)arg;
|
||||
struct i2c_atciic100_dev_data_t *dev_data = dev->data;
|
||||
|
||||
uint32_t reg_set, reg_stat = 0, reg_ctrl = 0;
|
||||
|
||||
reg_stat = sys_read32(I2C_STAT(dev));
|
||||
reg_set = sys_read32(I2C_SET(dev));
|
||||
reg_ctrl = sys_read32(I2C_CTRL(dev));
|
||||
|
||||
/* Clear interrupts status */
|
||||
sys_write32((reg_stat & STATUS_W1C_ALL), I2C_STAT(dev));
|
||||
|
||||
#if defined(CONFIG_I2C_TARGET)
|
||||
if (dev_data->status.mode == 0) {
|
||||
andes_i2c_target_event(dev, reg_stat, reg_ctrl);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (reg_stat & STATUS_ADDR_HIT) {
|
||||
dev_data->status.target_ack = 1;
|
||||
}
|
||||
|
||||
if (reg_stat & STATUS_FIFO_EMPTY) {
|
||||
i2c_fifo_empty_handler(dev);
|
||||
}
|
||||
|
||||
if (reg_stat & STATUS_FIFO_FULL) {
|
||||
/* Store hw receive data count quickly */
|
||||
i2c_fifo_full_handler(dev);
|
||||
}
|
||||
|
||||
if (reg_stat & STATUS_CMPL) {
|
||||
/* Store hw receive data count quickly */
|
||||
i2c_cmpl_handler(dev, reg_stat);
|
||||
}
|
||||
|
||||
if ((reg_stat & STATUS_ARB_LOSE) && (reg_set & SETUP_CONTROLLER)) {
|
||||
dev_data->status.arbitration_lost = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct i2c_driver_api i2c_atciic100_driver = {
|
||||
.configure = (i2c_api_configure_t)i2c_atciic100_configure,
|
||||
.transfer = (i2c_api_full_io_t)i2c_atciic100_transfer,
|
||||
#if defined(CONFIG_I2C_TARGET)
|
||||
.target_register =
|
||||
(i2c_api_target_register_t)i2c_atciic100_target_register,
|
||||
.target_unregister =
|
||||
(i2c_api_target_unregister_t)i2c_atciic100_target_unregister
|
||||
#endif
|
||||
};
|
||||
|
||||
static int i2c_atciic100_init(const struct device *dev)
|
||||
{
|
||||
const struct i2c_atciic100_config *dev_cfg = dev->config;
|
||||
|
||||
/* Disable all interrupts. */
|
||||
sys_write32(0x00000000, I2C_INTE(dev));
|
||||
/* Clear interrupts status. */
|
||||
sys_write32(0xFFFFFFFF, I2C_STAT(dev));
|
||||
|
||||
dev_cfg->dt_init_fn();
|
||||
|
||||
i2c_atciic100_default_control(dev);
|
||||
|
||||
#if defined(CONFIG_I2C_TARGET)
|
||||
i2c_atciic100_configure(dev, I2C_SPEED_SET(I2C_SPEED_STANDARD));
|
||||
#else
|
||||
i2c_atciic100_configure(dev, I2C_SPEED_SET(I2C_SPEED_STANDARD)
|
||||
| I2C_MODE_CONTROLLER);
|
||||
#endif
|
||||
irq_enable(dev_cfg->irq_num);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define I2C_INIT(n) \
|
||||
static struct i2c_atciic100_dev_data_t \
|
||||
i2c_atciic100_dev_data_##n; \
|
||||
static void i2c_dt_init_##n(void); \
|
||||
static const struct i2c_atciic100_config \
|
||||
i2c_atciic100_config_##n = { \
|
||||
.base = DT_INST_REG_ADDR(n), \
|
||||
.irq_num = DT_INST_IRQN(n), \
|
||||
.dt_init_fn = i2c_dt_init_##n \
|
||||
}; \
|
||||
I2C_DEVICE_DT_INST_DEFINE(n, \
|
||||
i2c_atciic100_init, \
|
||||
NULL, \
|
||||
&i2c_atciic100_dev_data_##n, \
|
||||
&i2c_atciic100_config_##n, \
|
||||
POST_KERNEL, \
|
||||
CONFIG_I2C_INIT_PRIORITY, \
|
||||
&i2c_atciic100_driver); \
|
||||
\
|
||||
static void i2c_dt_init_##n(void) \
|
||||
{ \
|
||||
IRQ_CONNECT(DT_INST_IRQN(n), \
|
||||
DT_INST_IRQ(n, priority), \
|
||||
i2c_atciic100_irq_handler, \
|
||||
DEVICE_DT_INST_GET(n), \
|
||||
0); \
|
||||
}
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(I2C_INIT)
|
239
drivers/i2c/i2c_andes_atciic100.h
Normal file
239
drivers/i2c/i2c_andes_atciic100.h
Normal file
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Andes Technology Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file I2C driver for AndesTech atciic100 IP
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <soc.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/sys/sys_io.h>
|
||||
|
||||
#define I2C_MAX_COUNT 256
|
||||
#define BURST_CMD_COUNT 1
|
||||
|
||||
#define RED_IDR 0x00
|
||||
#define REG_CFG 0x10
|
||||
#define REG_INTE 0x14
|
||||
#define REG_STAT 0x18
|
||||
#define REG_ADDR 0x1C
|
||||
#define REG_DATA 0x20
|
||||
#define REG_CTRL 0x24
|
||||
#define REG_CMD 0x28
|
||||
#define REG_SET 0x2C
|
||||
|
||||
#define I2C_BASE(dev) \
|
||||
((const struct i2c_atciic100_config * const)(dev)->config)->base
|
||||
|
||||
#define I2C_CFG(dev) (I2C_BASE(dev) + REG_CFG)
|
||||
#define I2C_INTE(dev) (I2C_BASE(dev) + REG_INTE)
|
||||
#define I2C_STAT(dev) (I2C_BASE(dev) + REG_STAT)
|
||||
#define I2C_ADDR(dev) (I2C_BASE(dev) + REG_ADDR)
|
||||
#define I2C_CMD(dev) (I2C_BASE(dev) + REG_CMD)
|
||||
#define I2C_SET(dev) (I2C_BASE(dev) + REG_SET)
|
||||
#define I2C_DATA(dev) (I2C_BASE(dev) + REG_DATA)
|
||||
#define I2C_CTRL(dev) (I2C_BASE(dev) + REG_CTRL)
|
||||
|
||||
#define TARGET_ADDR_MSK BIT_MASK(10)
|
||||
#define DATA_MSK BIT_MASK(8)
|
||||
|
||||
/* Interrupt Enable Register(RW) */
|
||||
#define IEN_ALL BIT_MASK(10)
|
||||
#define IEN_CMPL BIT(9)
|
||||
#define IEN_BYTE_RECV BIT(8)
|
||||
#define IEN_BYTE_TRANS BIT(7)
|
||||
#define IEN_START BIT(6)
|
||||
#define IEN_STOP BIT(5)
|
||||
#define IEN_ARB_LOSE BIT(4)
|
||||
#define IEN_ADDR_HIT BIT(3)
|
||||
#define IEN_FIFO_HALF BIT(2)
|
||||
#define IEN_FIFO_FULL BIT(1)
|
||||
#define IEN_FIFO_EMPTY BIT(0)
|
||||
|
||||
/* Status Register(RW) */
|
||||
#define STATUS_W1C_ALL (BIT_MASK(7) << 3)
|
||||
#define STATUS_LINE_SDA BIT(14)
|
||||
#define STATUS_LINE_SCL BIT(13)
|
||||
#define STATUS_GEN_CALL BIT(12)
|
||||
#define STATUS_BUS_BUSY BIT(11)
|
||||
#define STATUS_ACK BIT(10)
|
||||
#define STATUS_CMPL BIT(9)
|
||||
#define STATUS_BYTE_RECV BIT(8)
|
||||
#define STATUS_BYTE_TRANS BIT(7)
|
||||
#define STATUS_START BIT(6)
|
||||
#define STATUS_STOP BIT(5)
|
||||
#define STATUS_ARB_LOSE BIT(4)
|
||||
#define STATUS_ADDR_HIT BIT(3)
|
||||
#define STATUS_FIFO_HALF BIT(2)
|
||||
#define STATUS_FIFO_FULL BIT(1)
|
||||
#define STATUS_FIFO_EMPTY BIT(0)
|
||||
|
||||
/* Control Register(RW) */
|
||||
#define CTRL_PHASE_START BIT(12)
|
||||
#define CTRL_PHASE_ADDR BIT(11)
|
||||
#define CTRL_PHASE_DATA BIT(10)
|
||||
#define CTRL_PHASE_STOP BIT(9)
|
||||
#define CTRL_DIR BIT(8)
|
||||
#define CTRL_DATA_COUNT BIT_MASK(8)
|
||||
|
||||
/* Command Register(RW) */
|
||||
#define CMD_MSK BIT_MASK(3)
|
||||
#define CMD_NO_ACT (0x0)
|
||||
#define CMD_ISSUE_TRANSACTION (0x1)
|
||||
#define CMD_ACK (0x2)
|
||||
#define CMD_NACK (0x3)
|
||||
#define CMD_CLEAR_FIFO (0x4)
|
||||
#define CMD_RESET_I2C (0x5)
|
||||
|
||||
/* Setup Register(RW) */
|
||||
#define SETUP_T_SUDAT (BIT_MASK(5) << 24)
|
||||
#define SETUP_T_SP (BIT_MASK(3) << 21)
|
||||
#define SETUP_T_HDDAT (BIT_MASK(5) << 16)
|
||||
#define SETUP_T_SCL_RATIO BIT(13)
|
||||
#define SETUP_T_SCLHI (BIT_MASK(9) << 4)
|
||||
#define SETUP_DMA_EN BIT(3)
|
||||
#define SETUP_CONTROLLER BIT(2)
|
||||
#define SETUP_ADDRESSING BIT(1)
|
||||
#define SETUP_I2C_EN BIT(0)
|
||||
|
||||
#if CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 30000000
|
||||
|
||||
#define SETUP_T_SUDAT_STD (0x3)
|
||||
#define SETUP_T_SP_STD (0x1)
|
||||
#define SETUP_T_HDDAT_STD (5)
|
||||
#define SETUP_T_SCL_RATIO_STD (0x0)
|
||||
#define SETUP_T_SCLHI_STD (138)
|
||||
|
||||
#define SETUP_T_SUDAT_FAST (0x0)
|
||||
#define SETUP_T_SP_FAST (0x1)
|
||||
#define SETUP_T_HDDAT_FAST (5)
|
||||
#define SETUP_T_SCL_RATIO_FAST (0x1)
|
||||
#define SETUP_T_SCLHI_FAST (18)
|
||||
|
||||
#define SETUP_T_SUDAT_FAST_P (0x0)
|
||||
#define SETUP_T_SP_FAST_P (0x1)
|
||||
#define SETUP_T_HDDAT_FAST_P (0x0)
|
||||
#define SETUP_T_SCL_RATIO_FAST_P (0x1)
|
||||
#define SETUP_T_SCLHI_FAST_P (6)
|
||||
|
||||
#elif CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 40000000
|
||||
|
||||
#define SETUP_T_SUDAT_STD (0x4)
|
||||
#define SETUP_T_SP_STD (0x2)
|
||||
#define SETUP_T_HDDAT_STD (0x6)
|
||||
#define SETUP_T_SCL_RATIO_STD (0x0)
|
||||
#define SETUP_T_SCLHI_STD (182)
|
||||
|
||||
#define SETUP_T_SUDAT_FAST (0x0)
|
||||
#define SETUP_T_SP_FAST (0x2)
|
||||
#define SETUP_T_HDDAT_FAST (0x6)
|
||||
#define SETUP_T_SCL_RATIO_FAST (0x1)
|
||||
#define SETUP_T_SCLHI_FAST (23)
|
||||
|
||||
#define SETUP_T_SUDAT_FAST_P (0x0)
|
||||
#define SETUP_T_SP_FAST_P (0x2)
|
||||
#define SETUP_T_HDDAT_FAST_P (0x0)
|
||||
#define SETUP_T_SCL_RATIO_FAST_P (0x1)
|
||||
#define SETUP_T_SCLHI_FAST_P (7)
|
||||
|
||||
#else
|
||||
|
||||
#define SETUP_T_SUDAT_STD (0x9)
|
||||
#define SETUP_T_SP_STD (0x3)
|
||||
#define SETUP_T_HDDAT_STD (12)
|
||||
#define SETUP_T_SCL_RATIO_STD (0x0)
|
||||
#define SETUP_T_SCLHI_STD (287)
|
||||
|
||||
#define SETUP_T_SUDAT_FAST (0x0)
|
||||
#define SETUP_T_SP_FAST (0x3)
|
||||
#define SETUP_T_HDDAT_FAST (12)
|
||||
#define SETUP_T_SCL_RATIO_FAST (0x1)
|
||||
#define SETUP_T_SCLHI_FAST (38)
|
||||
|
||||
#define SETUP_T_SUDAT_FAST_P (0x0)
|
||||
#define SETUP_T_SP_FAST_P (0x3)
|
||||
#define SETUP_T_HDDAT_FAST_P (0x0)
|
||||
#define SETUP_T_SCL_RATIO_FAST_P (0x1)
|
||||
#define SETUP_T_SCLHI_FAST_P (13)
|
||||
|
||||
#endif
|
||||
|
||||
#define SETUP_SPEED_MSK (SETUP_T_SUDAT | \
|
||||
SETUP_T_SP | \
|
||||
SETUP_T_HDDAT | \
|
||||
SETUP_T_SCL_RATIO | \
|
||||
SETUP_T_SCLHI)
|
||||
|
||||
#define SETUP_SPEED_STD ((SETUP_T_SUDAT_STD << 24) | \
|
||||
(SETUP_T_SP_STD << 21) | \
|
||||
(SETUP_T_HDDAT_STD << 16) | \
|
||||
(SETUP_T_SCL_RATIO_STD << 13) | \
|
||||
(SETUP_T_SCLHI_STD << 4))
|
||||
|
||||
#define SETUP_SPEED_FAST ((SETUP_T_SUDAT_FAST << 24) | \
|
||||
(SETUP_T_SP_FAST << 21) | \
|
||||
(SETUP_T_HDDAT_FAST << 16) | \
|
||||
(SETUP_T_SCL_RATIO_FAST << 13) | \
|
||||
(SETUP_T_SCLHI_FAST << 4))
|
||||
|
||||
#define SETUP_SPEED_FAST_PLUS ((SETUP_T_SUDAT_FAST_P << 24) | \
|
||||
(SETUP_T_SP_FAST_P << 21) | \
|
||||
(SETUP_T_HDDAT_FAST_P << 16) | \
|
||||
(SETUP_T_SCL_RATIO_FAST_P << 13)| \
|
||||
(SETUP_T_SCLHI_FAST_P << 4))
|
||||
|
||||
#define MAX_XFER_SZ (256)
|
||||
|
||||
enum _i2c_ctrl_reg_item_dir {
|
||||
I2C_CONTROLLER_TX = 0x0,
|
||||
I2C_CONTROLLER_RX = 0x1,
|
||||
I2C_TARGET_TX = 0x1,
|
||||
I2C_TARGET_RX = 0x0,
|
||||
};
|
||||
|
||||
/* I2C driver running state */
|
||||
enum _i2c_driver_state {
|
||||
I2C_DRV_NONE = 0x0,
|
||||
I2C_DRV_INIT = BIT(0),
|
||||
I2C_DRV_POWER = BIT(1),
|
||||
I2C_DRV_CFG_PARAM = BIT(2),
|
||||
I2C_DRV_CONTROLLER_TX = BIT(3),
|
||||
I2C_DRV_CONTROLLER_RX = BIT(4),
|
||||
I2C_DRV_TARGET_TX = BIT(5),
|
||||
I2C_DRV_TARGET_RX = BIT(6),
|
||||
I2C_DRV_CONTROLLER_TX_CMPL = BIT(7),
|
||||
I2C_DRV_CONTROLLER_RX_CMPL = BIT(8),
|
||||
I2C_DRV_TARGET_TX_CMPL = BIT(9),
|
||||
I2C_DRV_TARGET_RX_CMPL = BIT(10),
|
||||
};
|
||||
|
||||
/* brief I2C Status */
|
||||
struct _i2c_status {
|
||||
/* /< Mode: 0=Slave, 1=Master */
|
||||
uint32_t mode:1;
|
||||
uint32_t general_call: 1;
|
||||
uint32_t arbitration_lost : 1;
|
||||
uint32_t target_ack : 1;
|
||||
};
|
||||
|
||||
struct i2c_atciic100_dev_data_t {
|
||||
struct k_sem i2c_busy_sem;
|
||||
volatile uint32_t driver_state;
|
||||
uint8_t *middleware_rx_buf;
|
||||
uint8_t *middleware_tx_buf;
|
||||
uint32_t fifo_depth;
|
||||
uint32_t target_addr;
|
||||
uint32_t xfer_wt_num;
|
||||
uint32_t xfer_rd_num;
|
||||
uint32_t xfered_data_wt_ptr; /* write pointer */
|
||||
uint32_t xfered_data_rd_ptr; /* read pointer */
|
||||
volatile struct _i2c_status status;
|
||||
const struct i2c_target_callbacks *target_callbacks;
|
||||
struct i2c_target_config *target_config;
|
||||
};
|
Loading…
Reference in a new issue