240 lines
6.5 KiB
C
240 lines
6.5 KiB
C
/*
|
|
* 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 <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 bus_lock;
|
|
struct k_sem device_sync_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;
|
|
};
|