mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-14 02:18:54 +00:00
660 lines
17 KiB
C
660 lines
17 KiB
C
/*
|
|
* Copyright (c) 2022-2024, ArtInChip Technology Co., Ltd
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Authors: Geo <guojun.dong@artinchip.com>
|
|
*/
|
|
#include <rtthread.h>
|
|
#include <rtdevice.h>
|
|
#include <aic_core.h>
|
|
#include <drivers/i2c.h>
|
|
#include <hal_i2c.h>
|
|
|
|
#ifndef AIC_DEV_I2C0_10BIT
|
|
#define AIC_DEV_I2C0_10BIT 0
|
|
#endif
|
|
#ifndef AIC_DEV_I2C1_10BIT
|
|
#define AIC_DEV_I2C1_10BIT 0
|
|
#endif
|
|
#ifndef AIC_DEV_I2C2_10BIT
|
|
#define AIC_DEV_I2C2_10BIT 0
|
|
#endif
|
|
#ifndef AIC_DEV_I2C3_10BIT
|
|
#define AIC_DEV_I2C3_10BIT 0
|
|
#endif
|
|
#ifndef AIC_DEV_I2C4_10BIT
|
|
#define AIC_DEV_I2C4_10BIT 0
|
|
#endif
|
|
#ifndef AIC_DEV_SP_I2C_10BIT
|
|
#define AIC_DEV_SP_I2C_10BIT 0
|
|
#endif
|
|
#ifndef AIC_DEV_R_I2C0_10BIT
|
|
#define AIC_DEV_R_I2C0_10BIT 0
|
|
#endif
|
|
#ifndef AIC_DEV_R_I2C1_10BIT
|
|
#define AIC_DEV_R_I2C1_10BIT 0
|
|
#endif
|
|
|
|
#ifndef AIC_DEV_I2C0_SPEED
|
|
#define AIC_DEV_I2C0_SPEED 400000
|
|
#endif
|
|
#ifndef AIC_DEV_I2C1_SPEED
|
|
#define AIC_DEV_I2C1_SPEED 400000
|
|
#endif
|
|
#ifndef AIC_DEV_I2C2_SPEED
|
|
#define AIC_DEV_I2C2_SPEED 400000
|
|
#endif
|
|
#ifndef AIC_DEV_I2C3_SPEED
|
|
#define AIC_DEV_I2C3_SPEED 400000
|
|
#endif
|
|
#ifndef AIC_DEV_I2C4_SPEED
|
|
#define AIC_DEV_I2C4_SPEED 400000
|
|
#endif
|
|
#ifndef AIC_DEV_SP_I2C_SPEED
|
|
#define AIC_DEV_SP_I2C_SPEED 400000
|
|
#endif
|
|
#ifndef AIC_DEV_R_I2C0_SPEED
|
|
#define AIC_DEV_R_I2C0_SPEED 400000
|
|
#endif
|
|
#ifndef AIC_DEV_R_I2C1_SPEED
|
|
#define AIC_DEV_R_I2C1_SPEED 400000
|
|
#endif
|
|
|
|
#ifndef AIC_DEV_I2C0_SLAVE_MODE
|
|
#define AIC_DEV_I2C0_SLAVE_MODE 0
|
|
#endif
|
|
#ifndef AIC_DEV_I2C1_SLAVE_MODE
|
|
#define AIC_DEV_I2C1_SLAVE_MODE 0
|
|
#endif
|
|
#ifndef AIC_DEV_I2C2_SLAVE_MODE
|
|
#define AIC_DEV_I2C2_SLAVE_MODE 0
|
|
#endif
|
|
#ifndef AIC_DEV_I2C3_SLAVE_MODE
|
|
#define AIC_DEV_I2C3_SLAVE_MODE 0
|
|
#endif
|
|
#ifndef AIC_DEV_I2C4_SLAVE_MODE
|
|
#define AIC_DEV_I2C4_SLAVE_MODE 0
|
|
#endif
|
|
#ifndef AIC_DEV_SP_I2C_SLAVE_MODE
|
|
#define AIC_DEV_SP_I2C_SLAVE_MODE 0
|
|
#endif
|
|
#ifndef AIC_DEV_R_I2C0_SLAVE_MODE
|
|
#define AIC_DEV_R_I2C0_SLAVE_MODE 0
|
|
#endif
|
|
#ifndef AIC_DEV_R_I2C1_SLAVE_MODE
|
|
#define AIC_DEV_R_I2C1_SLAVE_MODE 0
|
|
#endif
|
|
|
|
#ifndef AIC_DEV_I2C0_SLAVE_ADDR
|
|
#define AIC_DEV_I2C0_SLAVE_ADDR 0
|
|
#endif
|
|
#ifndef AIC_DEV_I2C1_SLAVE_ADDR
|
|
#define AIC_DEV_I2C1_SLAVE_ADDR 0
|
|
#endif
|
|
#ifndef AIC_DEV_I2C2_SLAVE_ADDR
|
|
#define AIC_DEV_I2C2_SLAVE_ADDR 0
|
|
#endif
|
|
#ifndef AIC_DEV_I2C3_SLAVE_ADDR
|
|
#define AIC_DEV_I2C3_SLAVE_ADDR 0
|
|
#endif
|
|
#ifndef AIC_DEV_I2C4_SLAVE_ADDR
|
|
#define AIC_DEV_I2C4_SLAVE_ADDR 0
|
|
#endif
|
|
#ifndef AIC_DEV_SP_I2C_SLAVE_ADDR
|
|
#define AIC_DEV_SP_I2C_SLAVE_ADDR 0
|
|
#endif
|
|
#ifndef AIC_DEV_R_I2C0_SLAVE_ADDR
|
|
#define AIC_DEV_R_I2C0_SLAVE_ADDR 0
|
|
#endif
|
|
#ifndef AIC_DEV_R_I2C1_SLAVE_ADDR
|
|
#define AIC_DEV_R_I2C1_SLAVE_ADDR 0
|
|
#endif
|
|
|
|
struct aic_i2c_bus {
|
|
struct rt_i2c_bus_device bus;
|
|
aic_i2c_ctrl aic_bus;
|
|
struct rt_completion cmd_complete;
|
|
};
|
|
|
|
static struct aic_i2c_bus g_aic_i2c_dev[I2C_MAX_CHAN];
|
|
|
|
irqreturn_t aic_i2c_slave_irqhandler(int irq, void * data)
|
|
{
|
|
int i, index = 0;
|
|
uint32_t intr_stat;
|
|
uint8_t val;
|
|
uint8_t fifo_num;
|
|
struct slave_param parm;
|
|
aic_i2c_ctrl *i2c_dev;
|
|
|
|
for (i = 0; i < I2C_MAX_CHAN; i++) {
|
|
if (irq == g_aic_i2c_dev[i].aic_bus.irq_index) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
i2c_dev = &g_aic_i2c_dev[index].aic_bus;
|
|
intr_stat = hal_i2c_get_raw_interrupt_state(i2c_dev);
|
|
fifo_num = hal_i2c_get_receive_fifo_num(i2c_dev);
|
|
|
|
if (!i2c_dev->slave.slave_cb)
|
|
{
|
|
/*
|
|
* if the slave is not registered, we need to read the fifo empty
|
|
* to avoid interrupts from being triggered continuously
|
|
*/
|
|
for (int i = 0; i < fifo_num; i++)
|
|
hal_i2c_get_receive_data(i2c_dev);
|
|
|
|
hal_i2c_clear_all_irq_flags(i2c_dev);
|
|
pr_debug("slave callback not register!\n");
|
|
return IRQ_NONE;
|
|
}
|
|
|
|
|
|
if (intr_stat & I2C_INTR_START_DET) {
|
|
parm.cmd = I2C_SLAVE_WRITE_REQUESTED;
|
|
parm.arg = &val;
|
|
i2c_dev->slave.slave_cb((void *)&parm);
|
|
hal_i2c_clear_irq_flags(i2c_dev, I2C_INTR_START_DET);
|
|
}
|
|
|
|
if (intr_stat & I2C_INTR_RX_FULL) {
|
|
val = hal_i2c_get_receive_data(i2c_dev);
|
|
parm.cmd = I2C_SLAVE_WRITE_RECEIVED;
|
|
parm.arg = &val;
|
|
if (!i2c_dev->slave.slave_cb((void *)&parm)) {
|
|
pr_debug("Byte 0x%02x acked!\n", val);
|
|
}
|
|
hal_i2c_clear_irq_flags(i2c_dev, I2C_INTR_RX_FULL);
|
|
}
|
|
|
|
if (intr_stat & I2C_INTR_RD_REQ) {
|
|
parm.cmd = I2C_SLAVE_READ_REQUESTED;
|
|
parm.arg = &val;
|
|
i2c_dev->slave.slave_cb((void *)&parm);
|
|
hal_i2c_transmit_data(i2c_dev, *parm.arg);
|
|
|
|
parm.cmd = I2C_SLAVE_READ_PROCESSED;
|
|
parm.arg = &val;
|
|
i2c_dev->slave.slave_cb((void *)&parm);
|
|
hal_i2c_clear_irq_flags(i2c_dev, I2C_INTR_RD_REQ);
|
|
}
|
|
|
|
if (intr_stat & I2C_INTR_RX_DONE) {
|
|
parm.cmd = I2C_SLAVE_STOP;
|
|
parm.arg = &val;
|
|
i2c_dev->slave.slave_cb((void *)&parm);
|
|
hal_i2c_clear_irq_flags(i2c_dev, I2C_INTR_RX_DONE);
|
|
}
|
|
|
|
if (intr_stat & I2C_INTR_RX_UNDER) {
|
|
hal_i2c_clear_irq_flags(i2c_dev, I2C_INTR_RX_UNDER);
|
|
}
|
|
|
|
if (intr_stat & I2C_INTR_TX_ABRT) {
|
|
hal_i2c_clear_irq_flags(i2c_dev, I2C_INTR_TX_ABRT);
|
|
}
|
|
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
#ifdef AIC_I2C_INTERRUPT_MODE
|
|
static void aic_i2c_handle_read(struct aic_i2c_ctrl *i2c_dev)
|
|
{
|
|
struct aic_i2c_msg *msg = i2c_dev->msg;
|
|
int rx_valid;
|
|
uint32_t idx;
|
|
|
|
idx = i2c_dev->index;
|
|
rx_valid = hal_i2c_get_receive_fifo_num(i2c_dev);
|
|
|
|
while (rx_valid--) {
|
|
msg->buf[i2c_dev->buf_read_idx++] = hal_i2c_get_receive_data(i2c_dev);
|
|
}
|
|
|
|
/* message transfer done if it is a read message */
|
|
if (i2c_dev->buf_read_idx == msg->len) {
|
|
hal_i2c_disable_all_irq(i2c_dev);
|
|
rt_completion_done(&g_aic_i2c_dev[idx].cmd_complete);
|
|
}
|
|
}
|
|
|
|
static void aic_i2c_handle_write(struct aic_i2c_ctrl *i2c_dev)
|
|
{
|
|
struct aic_i2c_msg *msg = i2c_dev->msg;
|
|
int rx_valid, tx_valid, buf_len;
|
|
uint32_t intr_mask = I2C_INTR_MASTER_MASK;
|
|
uint32_t idx;
|
|
|
|
idx = i2c_dev->index;
|
|
|
|
if ((i2c_dev->msg_status == MSG_IDLE) && (msg->len == 0)
|
|
&& (i2c_dev->is_first_message) && (i2c_dev->is_last_message)) {
|
|
uint32_t cmd = 0;
|
|
|
|
cmd |= I2C_DATA_CMD_STOP;
|
|
/* Write operation */
|
|
hal_i2c_transmit_data_with_cmd(i2c_dev, cmd);
|
|
hal_i2c_disable_all_irq(i2c_dev);
|
|
rt_completion_done(&g_aic_i2c_dev[idx].cmd_complete);
|
|
}
|
|
|
|
i2c_dev->msg_status = MSG_IN_PROCESS;
|
|
rx_valid = I2C_FIFO_DEPTH - hal_i2c_get_receive_fifo_num(i2c_dev);
|
|
tx_valid = I2C_FIFO_DEPTH - hal_i2c_get_transmit_fifo_num(i2c_dev);
|
|
buf_len = msg->len - i2c_dev->buf_write_idx;
|
|
|
|
while (buf_len > 0 && rx_valid > 0 && tx_valid > 0) {
|
|
uint32_t cmd = 0;
|
|
|
|
if (buf_len == 1 && i2c_dev->is_last_message) {
|
|
cmd |= I2C_DATA_CMD_STOP;
|
|
}
|
|
|
|
if (!i2c_dev->is_first_message && !i2c_dev->buf_write_idx) {
|
|
cmd |= I2C_DATA_CMD_RESTART;
|
|
}
|
|
|
|
if (msg->flags & RT_I2C_RD) {
|
|
cmd |= I2C_DATA_CMD_READ;
|
|
hal_i2c_transmit_data_with_cmd(i2c_dev, cmd);
|
|
rx_valid--;
|
|
} else {
|
|
hal_i2c_transmit_data_with_cmd(i2c_dev, cmd | msg->buf[i2c_dev->buf_write_idx]);
|
|
/* ensure the data is sent out */
|
|
while (hal_i2c_get_transmit_fifo_num(i2c_dev) != 0) {};
|
|
}
|
|
|
|
i2c_dev->buf_write_idx++;
|
|
tx_valid--;
|
|
buf_len--;
|
|
|
|
if (i2c_dev->buf_write_idx == msg->len) {
|
|
intr_mask &= ~I2C_INTR_TX_EMPTY;
|
|
hal_i2c_flags_mask(i2c_dev, intr_mask);
|
|
/* message transfer done if it is a write message */
|
|
if (!(msg->flags & RT_I2C_RD)) {
|
|
hal_i2c_disable_all_irq(i2c_dev);
|
|
rt_completion_done(&g_aic_i2c_dev[idx].cmd_complete);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
irqreturn_t aic_i2c_irqhandler(int irq, void * data)
|
|
{
|
|
int i, index = 0;
|
|
uint32_t status = 0;
|
|
aic_i2c_ctrl *i2c_dev;
|
|
|
|
for (i = 0; i < I2C_MAX_CHAN; i++) {
|
|
if (irq == g_aic_i2c_dev[i].aic_bus.irq_index) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
i2c_dev = &g_aic_i2c_dev[index].aic_bus;
|
|
status = hal_i2c_get_raw_interrupt_state(i2c_dev);
|
|
/* clear all interrupt flags */
|
|
hal_i2c_clear_all_irq_flags(i2c_dev);
|
|
|
|
if (status & I2C_INTR_TX_ABRT) {
|
|
i2c_dev->msg_err = -I2C_INTR_ERROR_ABRT;
|
|
goto i2c_err;
|
|
}
|
|
|
|
if (status & I2C_INTR_RX_UNDER) {
|
|
i2c_dev->msg_err = -I2C_INTR_ERROR_RX;
|
|
goto i2c_err;
|
|
}
|
|
|
|
if (status & I2C_INTR_RX_FULL) {
|
|
aic_i2c_handle_read(i2c_dev);
|
|
}
|
|
|
|
if (status & I2C_INTR_TX_EMPTY) {
|
|
aic_i2c_handle_write(i2c_dev);
|
|
}
|
|
|
|
i2c_err:
|
|
if (status & (I2C_INTR_TX_ABRT | I2C_INTR_RX_UNDER | I2C_INTR_STOP_DET)) {
|
|
hal_i2c_disable_all_irq(i2c_dev);
|
|
rt_completion_done(&g_aic_i2c_dev[index].cmd_complete);
|
|
}
|
|
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
static void aic_i2c_xfer_msg_init(struct aic_i2c_ctrl *i2c_dev)
|
|
{
|
|
i2c_dev->buf_write_idx = 0;
|
|
i2c_dev->buf_read_idx = 0;
|
|
i2c_dev->msg_err = 0;
|
|
i2c_dev->abort_source = 0;
|
|
i2c_dev->msg_status = MSG_IDLE;
|
|
|
|
/* clear and enable interrupts */
|
|
hal_i2c_clear_all_irq_flags(i2c_dev);
|
|
hal_i2c_master_enable_irq(i2c_dev);
|
|
}
|
|
|
|
static int aic_i2c_xfer_msg(struct aic_i2c_ctrl *i2c_dev, struct aic_i2c_msg *msg,
|
|
bool is_first, bool is_last)
|
|
{
|
|
int ret = 0;
|
|
rt_err_t timeout;
|
|
uint32_t idx;
|
|
|
|
i2c_dev->msg = msg;
|
|
i2c_dev->is_first_message = is_first;
|
|
i2c_dev->is_last_message = is_last;
|
|
idx = i2c_dev->index;
|
|
|
|
rt_completion_init(&g_aic_i2c_dev[idx].cmd_complete);
|
|
if (is_first) {
|
|
/* Set the slave address */
|
|
hal_i2c_target_addr(i2c_dev, msg->addr);
|
|
/* Enable i2c dev */
|
|
hal_i2c_module_enable(i2c_dev);
|
|
|
|
ret = hal_i2c_wait_bus_free(i2c_dev, 10);
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
|
|
aic_i2c_xfer_msg_init(i2c_dev);
|
|
|
|
timeout = rt_completion_wait(&g_aic_i2c_dev[idx].cmd_complete, 1000);
|
|
if (timeout) {
|
|
pr_err("message xfer timeout\n");
|
|
ret = I2C_TIMEOUT;
|
|
}
|
|
|
|
if (i2c_dev->msg_err) {
|
|
ret = I2C_ERR;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static rt_size_t aic_i2c_master_xfer(struct rt_i2c_bus_device *bus,
|
|
struct rt_i2c_msg msgs[], rt_uint32_t num)
|
|
{
|
|
CHECK_PARAM(bus, -EINVAL);
|
|
|
|
aic_i2c_ctrl *i2c_dev;
|
|
int ret = 0, index;
|
|
uint8_t idx;
|
|
|
|
idx = bus->parent.device_id;
|
|
i2c_dev = &g_aic_i2c_dev[idx].aic_bus;
|
|
|
|
for (index = 0; index < num; index++) {
|
|
i2c_dev->msg = (struct aic_i2c_msg*)msgs;
|
|
ret = aic_i2c_xfer_msg(i2c_dev, &i2c_dev->msg[index], index == 0, index == (num-1));
|
|
}
|
|
hal_i2c_module_disable(i2c_dev);
|
|
|
|
return (ret < 0) ? 0 : num;
|
|
}
|
|
#else
|
|
static rt_size_t aic_i2c_master_xfer(struct rt_i2c_bus_device *bus,
|
|
struct rt_i2c_msg msgs[], rt_uint32_t num)
|
|
{
|
|
CHECK_PARAM(bus, -EINVAL);
|
|
|
|
struct rt_i2c_msg *msg = NULL;
|
|
aic_i2c_ctrl *i2c_dev;
|
|
int ret_msg_len = 0;
|
|
int32_t bytes_cnt = 0;
|
|
int8_t is_last_message = 0;
|
|
uint8_t index;
|
|
|
|
index = bus->parent.device_id;
|
|
i2c_dev = &g_aic_i2c_dev[index].aic_bus;
|
|
|
|
for (uint32_t i = 0; i < num; i++) {
|
|
msg = &msgs[i];
|
|
if (i == num -1)
|
|
is_last_message = 1;
|
|
else
|
|
is_last_message = 0;
|
|
|
|
if ((msg->flags & RT_I2C_RD)) {
|
|
bytes_cnt = hal_i2c_master_receive_msg(i2c_dev,
|
|
(struct aic_i2c_msg*)msg, is_last_message);
|
|
} else {
|
|
bytes_cnt = hal_i2c_master_send_msg(i2c_dev,
|
|
(struct aic_i2c_msg*)msg, is_last_message);
|
|
}
|
|
|
|
if (bytes_cnt == msg->len) {
|
|
ret_msg_len++;
|
|
}
|
|
}
|
|
|
|
return ret_msg_len;
|
|
}
|
|
#endif
|
|
|
|
static rt_err_t aic_i2c_slave_control(struct rt_i2c_bus_device *bus,
|
|
rt_uint32_t cmd, void *arg)
|
|
{
|
|
RT_ASSERT(bus != RT_NULL);
|
|
|
|
aic_i2c_ctrl *i2c_dev;
|
|
|
|
uint8_t index = bus->parent.device_id;
|
|
i2c_dev = &g_aic_i2c_dev[index].aic_bus;
|
|
|
|
struct aic_i2c_slave_info *slave_info = (struct aic_i2c_slave_info *)arg;
|
|
|
|
i2c_dev->slave.slave_cb = slave_info->slave_cb;
|
|
i2c_dev->slave.callback_param = slave_info->callback_param;
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
static rt_err_t aic_i2c_bus_control(struct rt_i2c_bus_device *bus,
|
|
rt_uint32_t cmd, rt_uint32_t value)
|
|
{
|
|
RT_ASSERT(bus != RT_NULL);
|
|
|
|
aic_i2c_ctrl *i2c_dev;
|
|
|
|
uint8_t index = bus->parent.device_id;
|
|
i2c_dev = &g_aic_i2c_dev[index].aic_bus;
|
|
|
|
switch(cmd)
|
|
{
|
|
case RT_I2C_DEV_CTRL_CLK:
|
|
i2c_dev->target_rate = value;
|
|
hal_i2c_set_speed(i2c_dev);
|
|
break;
|
|
default:
|
|
return -RT_EIO;
|
|
}
|
|
|
|
return RT_EOK;
|
|
}
|
|
|
|
const struct rt_i2c_bus_device_ops i2c_ops = {
|
|
aic_i2c_master_xfer,
|
|
RT_NULL,
|
|
aic_i2c_bus_control,
|
|
aic_i2c_slave_control,
|
|
};
|
|
|
|
static struct aic_i2c_bus aic_i2c_dev[] = {
|
|
#ifdef AIC_USING_I2C0
|
|
{
|
|
.bus.ops = &i2c_ops,
|
|
.aic_bus = {
|
|
.index = 0,
|
|
.reg_base = I2C0_BASE,
|
|
.device_name = "i2c0",
|
|
.addr_bit = AIC_DEV_I2C0_10BIT,
|
|
.target_rate = AIC_DEV_I2C0_SPEED,
|
|
.bus_mode = AIC_DEV_I2C0_SLAVE_MODE,
|
|
.slave_addr = AIC_DEV_I2C0_SLAVE_ADDR,
|
|
.irq_index = I2C0_IRQn,
|
|
.clk_id = CLK_I2C0,
|
|
},
|
|
},
|
|
#endif
|
|
|
|
#ifdef AIC_USING_I2C1
|
|
{
|
|
.bus.ops = &i2c_ops,
|
|
.aic_bus = {
|
|
.index = 1,
|
|
.reg_base = I2C1_BASE,
|
|
.device_name = "i2c1",
|
|
.addr_bit = AIC_DEV_I2C1_10BIT,
|
|
.target_rate = AIC_DEV_I2C1_SPEED,
|
|
.bus_mode = AIC_DEV_I2C1_SLAVE_MODE,
|
|
.slave_addr = AIC_DEV_I2C1_SLAVE_ADDR,
|
|
.irq_index = I2C1_IRQn,
|
|
.clk_id = CLK_I2C1,
|
|
},
|
|
},
|
|
#endif
|
|
|
|
#ifdef AIC_USING_I2C2
|
|
{
|
|
.bus.ops = &i2c_ops,
|
|
.aic_bus = {
|
|
.index = 2,
|
|
.reg_base = I2C2_BASE,
|
|
.device_name = "i2c2",
|
|
.addr_bit = AIC_DEV_I2C2_10BIT,
|
|
.target_rate = AIC_DEV_I2C2_SPEED,
|
|
.bus_mode = AIC_DEV_I2C2_SLAVE_MODE,
|
|
.slave_addr = AIC_DEV_I2C2_SLAVE_ADDR,
|
|
.irq_index = I2C2_IRQn,
|
|
.clk_id = CLK_I2C2,
|
|
},
|
|
},
|
|
#endif
|
|
|
|
#ifdef AIC_USING_I2C3
|
|
{
|
|
.bus.ops = &i2c_ops,
|
|
.aic_bus = {
|
|
.index = 3,
|
|
.reg_base = I2C3_BASE,
|
|
.device_name = "i2c3",
|
|
.addr_bit = AIC_DEV_I2C3_10BIT,
|
|
.target_rate = AIC_DEV_I2C3_SPEED,
|
|
.bus_mode = AIC_DEV_I2C3_SLAVE_MODE,
|
|
.slave_addr = AIC_DEV_I2C3_SLAVE_ADDR,
|
|
.irq_index = I2C3_IRQn,
|
|
.clk_id = CLK_I2C3,
|
|
},
|
|
},
|
|
#endif
|
|
|
|
#ifdef AIC_USING_I2C4
|
|
{
|
|
.bus.ops = &i2c_ops,
|
|
.aic_bus = {
|
|
.index = 4,
|
|
.reg_base = I2C4_BASE,
|
|
.device_name = "i2c4",
|
|
.addr_bit = AIC_DEV_I2C4_10BIT,
|
|
.target_rate = AIC_DEV_I2C4_SPEED,
|
|
.bus_mode = AIC_DEV_I2C4_SLAVE_MODE,
|
|
.slave_addr = AIC_DEV_I2C4_SLAVE_ADDR,
|
|
.irq_index = I2C4_IRQn,
|
|
.clk_id = CLK_I2C4,
|
|
},
|
|
},
|
|
#endif
|
|
|
|
#ifdef AIC_USING_SP_I2C
|
|
{
|
|
.bus.ops = &i2c_ops,
|
|
.aic_bus = {
|
|
.index = 5,
|
|
.reg_base = SP_I2C_BASE,
|
|
.device_name = "sp_i2c",
|
|
.addr_bit = AIC_DEV_SP_I2C_10BIT,
|
|
.target_rate = AIC_DEV_SP_I2C_SPEED,
|
|
.bus_mode = AIC_DEV_SP_I2C_SLAVE_MODE,
|
|
.slave_addr = AIC_DEV_SP_I2C_SLAVE_ADDR,
|
|
.irq_index = SP_I2C_IRQn,
|
|
.clk_id = CLK_SP_I2C,
|
|
},
|
|
},
|
|
#endif
|
|
#ifdef AIC_USING_R_I2C0
|
|
{
|
|
.bus.ops = &i2c_ops,
|
|
.aic_bus = {
|
|
.index = 6,
|
|
.reg_base = R_I2C0_BASE,
|
|
.device_name = "r_i2c0",
|
|
.addr_bit = AIC_DEV_R_I2C0_10BIT,
|
|
.target_rate = AIC_DEV_R_I2C0_SPEED,
|
|
.bus_mode = AIC_DEV_R_I2C0_SLAVE_MODE,
|
|
.slave_addr = AIC_DEV_R_I2C0_SLAVE_ADDR,
|
|
.irq_index = R_I2C0_IRQn,
|
|
.clk_id = CLK_R_I2C0,
|
|
},
|
|
},
|
|
#endif
|
|
#ifdef AIC_USING_R_I2C1
|
|
{
|
|
.bus.ops = &i2c_ops,
|
|
.aic_bus = {
|
|
.index = 7,
|
|
.reg_base = R_I2C1_BASE,
|
|
.device_name = "r_i2c1",
|
|
.addr_bit = AIC_DEV_R_I2C1_10BIT,
|
|
.target_rate = AIC_DEV_R_I2C1_SPEED,
|
|
.bus_mode = AIC_DEV_R_I2C1_SLAVE_MODE,
|
|
.slave_addr = AIC_DEV_R_I2C1_SLAVE_ADDR,
|
|
.irq_index = R_I2C1_IRQn,
|
|
.clk_id = CLK_R_I2C1,
|
|
},
|
|
},
|
|
#endif
|
|
};
|
|
|
|
static int aic_hw_i2c_register()
|
|
{
|
|
int ret = -1;
|
|
uint8_t index;
|
|
|
|
for (uint8_t i = 0; i < ARRAY_SIZE(aic_i2c_dev); i++) {
|
|
index = aic_i2c_dev[i].aic_bus.index;
|
|
aic_i2c_dev[i].bus.parent.device_id = index;
|
|
|
|
ret = hal_i2c_init(&aic_i2c_dev[i].aic_bus);
|
|
if (ret) {
|
|
return ret;
|
|
}
|
|
g_aic_i2c_dev[index] = aic_i2c_dev[i];
|
|
|
|
#ifdef AIC_I2C_INTERRUPT_MODE
|
|
aicos_request_irq(aic_i2c_dev[i].aic_bus.irq_index, aic_i2c_irqhandler, 0, "i2c", NULL);
|
|
#endif
|
|
if (aic_i2c_dev[i].aic_bus.bus_mode) {
|
|
aicos_request_irq(aic_i2c_dev[i].aic_bus.irq_index, aic_i2c_slave_irqhandler, 0, "i2c_slave", NULL);
|
|
}
|
|
|
|
ret = rt_i2c_bus_device_register(&aic_i2c_dev[i].bus,
|
|
aic_i2c_dev[i].aic_bus.device_name);
|
|
if (ret) {
|
|
return ret;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
INIT_BOARD_EXPORT(aic_hw_i2c_register);
|