Browse Source

Merge pull request #9199 from unicornx/dev-i2c-new

bsp: cvitek: re-wrote i2c driver
Bernard Xiong 1 year ago
parent
commit
4e630fed08
2 changed files with 979 additions and 550 deletions
  1. 310 356
      bsp/cvitek/drivers/drv_hw_i2c.c
  2. 669 194
      bsp/cvitek/drivers/drv_hw_i2c.h

+ 310 - 356
bsp/cvitek/drivers/drv_hw_i2c.c

@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
+ * Copyright (c) 2006-2024, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:
  * Date           Author       Notes
- *2024-02-14      ShichengChu  first version
+ * 2024-02-14     ShichengChu  first version
  */
 #include "drv_hw_i2c.h"
 #include <rtdevice.h>
@@ -16,458 +16,416 @@
 #define DBG_LVL               DBG_INFO
 #include <rtdbg.h>
 
-#define false 0
-#define true  1
-struct _i2c_bus
+struct dw_iic_bus
 {
     struct rt_i2c_bus_device parent;
-    uint8_t i2c_id;
+    dw_iic_regs_t *iic_base;
+    rt_uint32_t irq;
     char *device_name;
 };
 
-static struct _i2c_bus _i2c_obj[] =
+static struct dw_iic_bus _i2c_obj[] =
 {
 #ifdef BSP_USING_I2C0
     {
-        .i2c_id = I2C0,
-        .device_name = "i2c0",
+        .iic_base       = (dw_iic_regs_t *)I2C0_BASE,
+        .device_name    = "i2c0",
+        .irq            = I2C0_IRQ,
     },
 #endif /* BSP_USING_I2C0 */
 #ifdef BSP_USING_I2C1
     {
-        .i2c_id = I2C1,
-        .device_name = "i2c1",
+        .iic_base       = (dw_iic_regs_t *)I2C1_BASE,
+        .device_name    = "i2c1",
+        .irq            = I2C1_IRQ,
     },
 #endif /* BSP_USING_I2C1 */
+#ifdef BSP_USING_I2C2
+    {
+        .iic_base       = (dw_iic_regs_t *)I2C2_BASE,
+        .device_name    = "i2c2",
+        .irq            = I2C2_IRQ,
+    },
+#endif /* BSP_USING_I2C2 */
+#ifdef BSP_USING_I2C3
+    {
+        .iic_base       = (dw_iic_regs_t *)I2C3_BASE,
+        .device_name    = "i2c3",
+        .irq            = I2C3_IRQ,
+    },
+#endif /* BSP_USING_I2C3 */
+#ifdef BSP_USING_I2C4
+    {
+        .iic_base       = (dw_iic_regs_t *)I2C4_BASE,
+        .device_name    = "i2c4",
+        .irq            = I2C4_IRQ,
+    },
+#endif /* BSP_USING_I2C4 */
 };
 
-static struct i2c_regs *get_i2c_base(uint8_t i2c_id)
+static rt_uint32_t dw_iic_wait_for_bb(dw_iic_regs_t *iic_base)
 {
-    struct i2c_regs *i2c_base = NULL;
-
-    switch (i2c_id) {
-    case I2C0:
-        i2c_base = (struct i2c_regs *)I2C0_BASE;
-        break;
-    case I2C1:
-        i2c_base = (struct i2c_regs *)I2C1_BASE;
-        break;
-    case I2C2:
-        i2c_base = (struct i2c_regs *)I2C2_BASE;
-        break;
-    case I2C3:
-        i2c_base = (struct i2c_regs *)I2C3_BASE;
-        break;
-    case I2C4:
-        i2c_base = (struct i2c_regs *)I2C4_BASE;
-        break;
+    uint16_t    timeout = 0;
+    while ((iic_base->IC_STATUS & DW_IIC_MST_ACTIVITY_STATE) || !(iic_base->IC_STATUS & DW_IIC_TXFIFO_EMPTY_STATE))
+    {
+        /* Evaluate timeout */
+        rt_hw_us_delay(5);
+        timeout ++;
+        if (timeout > 200)
+        {
+            /* exceed 1 ms */
+            LOG_E("Timed out waiting for bus busy");
+            return 1;
+        }
     }
 
-    return i2c_base;
+    return 0;
 }
 
-static uint32_t get_i2c_intr(uint8_t i2c_id)
+void dw_iic_set_reg_address(dw_iic_regs_t *iic_base, rt_uint32_t addr, uint8_t addr_len)
 {
-    uint32_t i2c_intr = 0;
-
-    switch (i2c_id) {
-    case I2C0:
-        i2c_intr = I2C0_IRQ;
-        break;
-    case I2C1:
-        i2c_intr = I2C1_IRQ;
-        break;
-    case I2C2:
-        i2c_intr = I2C2_IRQ;
-        break;
-    case I2C3:
-        i2c_intr = I2C3_IRQ;
-        break;
-    case I2C4:
-        i2c_intr = I2C4_IRQ;
-        break;
+    while (addr_len)
+    {
+        addr_len --;
+        /* high byte address going out first */
+        dw_iic_transmit_data(iic_base, (addr >> (addr_len * 8)) & 0xff);
     }
-
-    return i2c_intr;
 }
 
-void i2c_write_cmd_data(struct i2c_regs *i2c, uint16_t value)
+static void dw_iic_set_target_address(dw_iic_regs_t *iic_base, rt_uint32_t address)
 {
-    mmio_write_32((uintptr_t)&i2c->ic_cmd_data, value);
-}
+    rt_uint32_t i2c_status;
+    i2c_status = dw_iic_get_iic_status(iic_base);
+    dw_iic_disable(iic_base);
+    iic_base->IC_TAR = (iic_base->IC_TAR & ~0x3ff) | address; /* this register can be written only when the I2C is disabled*/
 
-static void i2c_enable(struct i2c_regs *i2c, uint8_t enable)
-{
-    uint32_t ena = enable ? IC_ENABLE : 0;
-    int timeout = 100;
-
-    do {
-        mmio_write_32((uintptr_t)&i2c->ic_enable, ena);
-        if ((mmio_read_32((uintptr_t)&i2c->ic_enable_status) & IC_ENABLE) == ena)
-            return;
-
-        /*
-         * Wait 10 times the signaling period of the highest I2C
-         * transfer supported by the driver (for 400KHz this is
-         * 25us) as described in the DesignWare I2C databook.
-         */
-        rt_hw_us_delay(25);
-    } while (timeout--);
-
-    LOG_I("timeout in %sabling I2C adapter\n", enable ? "en" : "dis");
+    if (i2c_status == DW_IIC_EN)
+    {
+        dw_iic_enable(iic_base);
+    }
 }
 
-static void i2c_disable(struct i2c_regs *i2c)
+static int dw_iic_xfer_init(dw_iic_regs_t *iic_base, rt_uint32_t dev_addr)
 {
-    int timeout = 100;
-
-    do {
-        mmio_write_32((uintptr_t)&i2c->ic_enable, 0x0);
-        if ((mmio_read_32((uintptr_t)&i2c->ic_enable_status) & IC_ENABLE) == 0x0)
-            return;
-
-        /*
-         * Wait 10 times the signaling period of the highest I2C
-         * transfer supported by the driver (for 400KHz this is
-         * 25us) as described in the DesignWare I2C databook.
-         */
-        rt_hw_us_delay(25);
-    } while (timeout--);
-
-    LOG_I("timeout in disabling I2C adapter\n");
-}
+    if (dw_iic_wait_for_bb(iic_base))
+        return -RT_ERROR;
 
-/*
- * i2c_flush_rxfifo - Flushes the i2c RX FIFO
- *
- * Flushes the i2c RX FIFO
- */
-static void i2c_flush_rxfifo(struct i2c_regs *i2c)
-{
-    while (mmio_read_32((uintptr_t)&i2c->ic_status) & IC_STATUS_RFNE)
-        mmio_read_32((uintptr_t)&i2c->ic_cmd_data);
+    dw_iic_set_target_address(iic_base, dev_addr);
+    dw_iic_enable(iic_base);
+
+    return RT_EOK;
 }
 
-/*
- * i2c_wait_for_bb - Waits for bus busy
- *
- * Waits for bus busy
- */
-static int i2c_wait_for_bb(struct i2c_regs *i2c)
+static int dw_iic_xfer_finish(dw_iic_regs_t *iic_base)
 {
-    uint16_t    timeout = 0;
+    rt_uint32_t timeout = 0;
 
-    while ((mmio_read_32((uintptr_t)&i2c->ic_status) & IC_STATUS_MA) ||
-           !(mmio_read_32((uintptr_t)&i2c->ic_status) & IC_STATUS_TFE)) {
+    while (1)
+    {
+        if (iic_base->IC_RAW_INTR_STAT & DW_IIC_RAW_STOP_DET)
+        {
+            iic_base->IC_CLR_STOP_DET;
+            break;
+        }
+        else
+        {
+            timeout ++;
+            rt_hw_us_delay(5);
+            if (timeout > 10000)
+            {
+                LOG_E("xfer finish tiemout");
+                break;
+            }
+        }
+    }
 
-        /* Evaluate timeout */
-        rt_hw_us_delay(5);
-        timeout++;
-        if (timeout > 200) /* exceed 1 ms */
-            return 1;
+    if (dw_iic_wait_for_bb(iic_base))
+    {
+        return -RT_ERROR;
     }
 
-    return 0;
+    dw_iic_flush_rxfifo(iic_base);
+
+    return RT_EOK;
 }
 
-/*
- * i2c_setaddress - Sets the target slave address
- * @i2c_addr:    target i2c address
- *
- * Sets the target slave address.
- */
-static void i2c_setaddress(struct i2c_regs *i2c, uint16_t i2c_addr)
+static void dw_iic_set_slave_mode(dw_iic_regs_t *iic_base)
 {
-    /* Disable i2c */
-    i2c_enable(i2c, false);
-    mmio_write_32((uintptr_t)&i2c->ic_tar, i2c_addr);
-    /* Enable i2c */
-    i2c_enable(i2c, true);
-}
+    rt_uint32_t i2c_status;
+    i2c_status = dw_iic_get_iic_status(iic_base);
+    dw_iic_disable(iic_base);
+    rt_uint32_t val = DW_IIC_CON_MASTER_EN | DW_IIC_CON_SLAVE_EN;
+    iic_base->IC_CON &= ~val;  ///< set 0 to disabled master mode; set 0 to enabled slave mode
 
+    if (i2c_status == DW_IIC_EN)
+    {
+        dw_iic_enable(iic_base);
+    }
+}
 
-static int i2c_xfer_init(struct i2c_regs *i2c, uint16_t chip, uint16_t addr, uint16_t alen)
+static void dw_iic_set_master_mode(dw_iic_regs_t *iic_base)
 {
-    if (i2c_wait_for_bb(i2c))
-        return 1;
-
-    i2c_setaddress(i2c, chip);
+    rt_uint32_t i2c_status;
+    i2c_status = dw_iic_get_iic_status(iic_base);
+    dw_iic_disable(iic_base);
+    rt_uint32_t val = DW_IIC_CON_MASTER_EN | DW_IIC_CON_SLAVE_EN; ///< set 1 to enabled master mode; set 1 to disabled slave mode
+    iic_base->IC_CON |= val;
 
-    while (alen) {
-        alen--;
-        /* high byte address going out first */
-        i2c_write_cmd_data(i2c, (addr >> (alen * 8)) & 0xff); // TODO
-        //mmio_write_32((uintptr_t)&i2c_base->ic_cmd_data, (addr >> (alen * 8)) & 0xff);
+    if (i2c_status == DW_IIC_EN)
+    {
+        dw_iic_enable(iic_base);
     }
-    return 0;
 }
 
-static int i2c_xfer_finish(struct i2c_regs *i2c)
+static rt_err_t dw_iic_recv(dw_iic_regs_t *iic_base, rt_uint32_t devaddr, rt_uint8_t *data, rt_uint32_t size, rt_uint32_t timeout)
 {
-    uint16_t timeout = 0;
-    while (1) {
-        if ((mmio_read_32((uintptr_t)&i2c->ic_raw_intr_stat) & IC_STOP_DET)) {
-            mmio_read_32((uintptr_t)&i2c->ic_clr_stop_det);
-            break;
-        } else {
-            timeout++;
-            rt_hw_us_delay(5);
-            if (timeout > I2C_STOPDET_TO * 100) {
-                LOG_I("%s, tiemout\n", __func__);
-                break;
-            }
-        }
-    }
+    rt_err_t ret = RT_EOK;
+    rt_uint32_t timecount = 0;
 
-    if (i2c_wait_for_bb(i2c))
-        return 1;
+    RT_ASSERT(data != RT_NULL);
 
-    i2c_flush_rxfifo(i2c);
+    if (dw_iic_xfer_init(iic_base, devaddr))
+    {
+        ret = -RT_EIO;
+        goto ERR_EXIT;
+    }
 
-    return 0;
-}
+    timecount = timeout + rt_tick_get_millisecond();
 
-/*
- * i2c_read - Read from i2c memory
- * @chip:    target i2c address
- * @addr:    address to read from
- * @alen:
- * @buffer:    buffer for read data
- * @len:    no of bytes to be read
- *
- * Read from i2c memory.
- */
-static int hal_i2c_read(uint8_t i2c_id, uint8_t dev, uint16_t addr, uint16_t alen, uint8_t *buffer, uint16_t len)
-{
-    unsigned int active = 0;
-    unsigned int time_count = 0;
-    struct i2c_regs *i2c;
-    int ret = 0;
-
-    i2c = get_i2c_base(i2c_id);
-
-    i2c_enable(i2c, true);
-
-    if (i2c_xfer_init(i2c, dev, addr, alen))
-        return 1;
-
-    while (len) {
-        if (!active) {
-            /*
-             * Avoid writing to ic_cmd_data multiple times
-             * in case this loop spins too quickly and the
-             * ic_status RFNE bit isn't set after the first
-             * write. Subsequent writes to ic_cmd_data can
-             * trigger spurious i2c transfer.
-             */
-            i2c_write_cmd_data(i2c, (dev <<1) | BIT_I2C_CMD_DATA_READ_BIT | BIT_I2C_CMD_DATA_STOP_BIT);
-            //mmio_write_32((uintptr_t)&i2c_base->ic_cmd_data, (dev <<1) | BIT_I2C_CMD_DATA_READ_BIT | BIT_I2C_CMD_DATA_STOP_BIT);
-            active = 1;
+    for (int i = 0 ; i < size; i ++)
+    {
+        if(i != (size - 1))
+        {
+            dw_iic_transmit_data(iic_base, DW_IIC_DATA_CMD);
+        }
+        else
+        {
+            dw_iic_transmit_data(iic_base, DW_IIC_DATA_CMD | DW_IIC_DATA_STOP);
         }
+    }
 
-        if (mmio_read_32((uintptr_t)&i2c->ic_raw_intr_stat) & BIT_I2C_INT_RX_FULL) {
-            *buffer++ = (uint8_t)mmio_read_32((uintptr_t)&i2c->ic_cmd_data);
-            len--;
-            time_count = 0;
-            active = 0;
+    while (size > 0)
+    {
+        if (iic_base->IC_STATUS & DW_IIC_RXFIFO_NOT_EMPTY_STATE)
+        {
+            *data ++ = dw_iic_receive_data(iic_base);
+            -- size;
         }
-        else {
-            rt_hw_us_delay(5);
-            time_count++;
-            if (time_count  >= I2C_BYTE_TO * 100)
-                return 1;
+        else if (rt_tick_get_millisecond() >= timecount)
+        {
+            LOG_E("Timed out read ic_cmd_data");
+            ret = -RT_ETIMEOUT;
+            goto ERR_EXIT;
         }
     }
 
-    ret = i2c_xfer_finish(i2c);
-    i2c_disable(i2c);
-
-    return ret;
-}
+    if (dw_iic_xfer_finish(iic_base))
+    {
+        ret = -RT_EIO;
+        goto ERR_EXIT;
+    }
 
-/*
- * i2c_write - Write to i2c memory
- * @chip:    target i2c address
- * @addr:    address to read from
- * @alen:
- * @buffer:    buffer for read data
- * @len:    no of bytes to be read
- *
- * Write to i2c memory.
- */
+ERR_EXIT:
+    dw_iic_disable(iic_base);
 
-static int hal_i2c_write(uint8_t i2c_id, uint8_t dev, uint16_t addr, uint16_t alen, uint8_t *buffer, uint16_t len)
-{
-    struct i2c_regs *i2c;
-    int ret = 0;
-    i2c = get_i2c_base(i2c_id);
-
-    i2c_enable(i2c, true);
-
-    if (i2c_xfer_init(i2c, dev, addr, alen))
-        return 1;
-
-    while (len) {
-        if (i2c->ic_status & IC_STATUS_TFNF) {
-            if (--len == 0) {
-                i2c_write_cmd_data(i2c, *buffer | IC_STOP);
-                //mmio_write_32((uintptr_t)&i2c_base->ic_cmd_data, *buffer | IC_STOP);
-            } else {
-                i2c_write_cmd_data(i2c, *buffer);
-                //mmio_write_32((uintptr_t)&i2c_base->ic_cmd_data, *buffer);
-            }
-            buffer++;
-        } else
-            LOG_I("len=%d, ic status is not TFNF\n", len);
-    }
-    ret = i2c_xfer_finish(i2c);
-    i2c_disable(i2c);
     return ret;
 }
 
-/*
- * hal_i2c_set_bus_speed - Set the i2c speed
- * @speed:    required i2c speed
- *
- * Set the i2c speed.
- */
-static void i2c_set_bus_speed(struct i2c_regs *i2c, unsigned int speed)
+static rt_err_t dw_iic_send(dw_iic_regs_t *iic_base, rt_uint32_t devaddr, const uint8_t *data, rt_uint32_t size, rt_uint32_t timeout)
 {
-    unsigned int cntl;
-    unsigned int hcnt, lcnt;
-    int i2c_spd;
-
-    if (speed > I2C_FAST_SPEED)
-        i2c_spd = IC_SPEED_MODE_MAX;
-    else if ((speed <= I2C_FAST_SPEED) && (speed > I2C_STANDARD_SPEED))
-        i2c_spd = IC_SPEED_MODE_FAST;
-    else
-        i2c_spd = IC_SPEED_MODE_STANDARD;
-
-    /* to set speed cltr must be disabled */
-    i2c_enable(i2c, false);
-
-    cntl = (mmio_read_32((uintptr_t)&i2c->ic_con) & (~IC_CON_SPD_MSK));
-
-    switch (i2c_spd) {
-    case IC_SPEED_MODE_MAX:
-        cntl |= IC_CON_SPD_HS;
-            //hcnt = (u16)(((IC_CLK * MIN_HS100pF_SCL_HIGHTIME) / 1000) - 8);
-            /* 7 = 6+1 == MIN LEN +IC_FS_SPKLEN */
-            //lcnt = (u16)(((IC_CLK * MIN_HS100pF_SCL_LOWTIME) / 1000) - 1);
-            hcnt = 6;
-            lcnt = 8;
-
-        mmio_write_32((uintptr_t)&i2c->ic_hs_scl_hcnt, hcnt);
-        mmio_write_32((uintptr_t)&i2c->ic_hs_scl_lcnt, lcnt);
-        break;
+    rt_err_t ret = RT_EOK;
+    rt_uint32_t timecount;
 
-    case IC_SPEED_MODE_STANDARD:
-        cntl |= IC_CON_SPD_SS;
-
-        hcnt = (uint16_t)(((IC_CLK * MIN_SS_SCL_HIGHTIME) / 1000) - 7);
-        lcnt = (uint16_t)(((IC_CLK * MIN_SS_SCL_LOWTIME) / 1000) - 1);
-
-        mmio_write_32((uintptr_t)&i2c->ic_ss_scl_hcnt, hcnt);
-        mmio_write_32((uintptr_t)&i2c->ic_ss_scl_lcnt, lcnt);
-        break;
+    RT_ASSERT(data != RT_NULL);
 
-    case IC_SPEED_MODE_FAST:
-    default:
-        cntl |= IC_CON_SPD_FS;
-        hcnt = (uint16_t)(((IC_CLK * MIN_FS_SCL_HIGHTIME) / 1000) - 7);
-        lcnt = (uint16_t)(((IC_CLK * MIN_FS_SCL_LOWTIME) / 1000) - 1);
-
-        mmio_write_32((uintptr_t)&i2c->ic_fs_scl_hcnt, hcnt);
-        mmio_write_32((uintptr_t)&i2c->ic_fs_scl_lcnt, lcnt);
-        break;
+    if (dw_iic_xfer_init(iic_base, devaddr))
+    {
+        ret = -RT_EIO;
+        goto ERR_EXIT;
     }
 
-    mmio_write_32((uintptr_t)&i2c->ic_con, cntl);
-
-    /* Enable back i2c now speed set */
-    i2c_enable(i2c, true);
-}
-
-/*
- * __hal_i2c_init - Init function
- * @speed:    required i2c speed
- * @slaveaddr:    slave address for the device
- *
- * Initialization function.
- */
-static void hal_i2c_init(uint8_t i2c_id)
-{
-    struct i2c_regs *i2c;
-    uint32_t i2c_intr;
+    timecount = timeout + rt_tick_get_millisecond();
 
-    LOG_I("%s, i2c-%d\n", __func__, i2c_id);
-    /* Disable i2c */
-    //Need to acquire lock here
+    while (size > 0)
+    {
+        if (iic_base->IC_STATUS & DW_IIC_TXFIFO_NOT_FULL_STATE)
+        {
+            if (-- size == 0)
+            {
+                dw_iic_transmit_data(iic_base, *data ++ | DW_IIC_DATA_STOP);
+            }
+            else
+            {
+                dw_iic_transmit_data(iic_base, *data ++);
+            }
+        }
+        else if (rt_tick_get_millisecond() >= timecount)
+        {
+            LOG_D("ic status is not TFNF\n");
+            ret = -RT_ETIMEOUT;
+            goto ERR_EXIT;
+        }
+    }
 
-    i2c = get_i2c_base(i2c_id);
-    i2c_intr = get_i2c_intr(i2c_id);
+    LOG_D("dw_iic_xfer_finish");
 
-    // request_irq(i2c_intr, i2c_dw_isr, 0, "IC2_INTR int", &dw_i2c[i2c_id]);
+    if (dw_iic_xfer_finish(iic_base))
+    {
+        ret = -RT_EIO;
+        goto ERR_EXIT;
+    }
 
-    i2c_enable(i2c, false);
-    mmio_write_32((uintptr_t)&i2c->ic_con, (IC_CON_SD | IC_CON_SPD_FS | IC_CON_MM | IC_CON_RE));
-    mmio_write_32((uintptr_t)&i2c->ic_rx_tl, IC_RX_TL);
-    mmio_write_32((uintptr_t)&i2c->ic_tx_tl, IC_TX_TL);
-    mmio_write_32((uintptr_t)&i2c->ic_intr_mask, 0x0);
-    i2c_set_bus_speed(i2c, I2C_SPEED);
-    //mmio_write_32((uintptr_t)&i2c->ic_sar, slaveaddr);
-    /* Enable i2c */
-    i2c_enable(i2c, false);
+ERR_EXIT:
+    dw_iic_disable(iic_base);
 
-    //Need to release lock here
+    return ret;
 }
 
-static rt_ssize_t _master_xfer(struct rt_i2c_bus_device *bus,
-                             struct rt_i2c_msg msgs[],
-                             rt_uint32_t num)
+static rt_ssize_t dw_iic_master_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num)
 {
     struct rt_i2c_msg *msg;
     rt_uint32_t i;
     rt_ssize_t ret = -RT_ERROR;
+    rt_uint32_t timeout;
 
-    struct _i2c_bus *i2c = (struct _i2c_bus *)bus;
+    struct dw_iic_bus *i2c_bus = (struct dw_iic_bus *)bus;
+    dw_iic_regs_t *iic_base = i2c_bus->iic_base;
 
     for (i = 0; i < num; i++)
     {
         msg = &msgs[i];
 
+        if (msg->flags & RT_I2C_ADDR_10BIT)
+        {
+            dw_iic_set_master_10bit_addr_mode(iic_base);
+            dw_iic_set_slave_10bit_addr_mode(iic_base);
+        }
+        else
+        {
+            dw_iic_set_master_7bit_addr_mode(iic_base);
+            dw_iic_set_slave_7bit_addr_mode(iic_base);
+        }
+
         if (msg->flags & RT_I2C_RD)
         {
-            hal_i2c_read(i2c->i2c_id, msg->addr, RT_NULL, 1, msg->buf, msg->len);
+            timeout = 1000;
+            ret = dw_iic_recv(iic_base, msg->addr, msg->buf, msg->len, timeout);
+            if (ret != RT_EOK)
+                LOG_E("dw_iic_recv error: %d", ret);
         }
         else
         {
-            hal_i2c_write(i2c->i2c_id, msg->addr, RT_NULL, 1, msg->buf, msg->len);
+            timeout = 100;
+            ret = dw_iic_send(iic_base, msg->addr, msg->buf, msg->len, timeout);
+            if (ret != RT_EOK)
+                LOG_E("dw_iic_send error: %d", ret);
         }
     }
 
-    return ret;
+    return ret == RT_EOK ? num : ret;
+}
+
+static void dw_iic_set_transfer_speed_high(dw_iic_regs_t *iic_base)
+{
+    rt_uint32_t speed_config = iic_base->IC_CON;
+    speed_config &= ~(DW_IIC_CON_SPEEDL_EN | DW_IIC_CON_SPEEDH_EN);
+    speed_config |= DW_IIC_CON_SPEEDL_EN | DW_IIC_CON_SPEEDH_EN;
+    iic_base->IC_CON = speed_config;
 }
 
-static void rt_hw_i2c_isr(int irqno, void *param)
+static void dw_iic_set_transfer_speed_fast(dw_iic_regs_t *iic_base)
 {
-    uint32_t stat, enabled;
-    struct i2c_regs *i2c = (struct i2c_regs *)param;
+    rt_uint32_t speed_config = iic_base->IC_CON;
+    speed_config &= ~(DW_IIC_CON_SPEEDL_EN | DW_IIC_CON_SPEEDH_EN);
+    speed_config |= DW_IIC_CON_SPEEDH_EN;
+    iic_base->IC_CON = speed_config;
+}
+
+static void dw_iic_set_transfer_speed_standard(dw_iic_regs_t *iic_base)
+{
+    rt_uint32_t speed_config = iic_base->IC_CON;
+    speed_config &= ~(DW_IIC_CON_SPEEDL_EN | DW_IIC_CON_SPEEDH_EN);
+    speed_config |= DW_IIC_CON_SPEEDL_EN;
+    iic_base->IC_CON = speed_config;
+}
+
+static rt_err_t dw_iic_bus_control(struct rt_i2c_bus_device *bus, int cmd, void *args)
+{
+    struct dw_iic_bus *i2c_bus = (struct dw_iic_bus *)bus;
+
+    RT_ASSERT(bus != RT_NULL);
 
-    enabled = mmio_read_32((uintptr_t)&i2c->ic_enable);
-    stat = mmio_read_32((uintptr_t)&i2c->ic_intr_stat);
+    dw_iic_regs_t *iic_base = i2c_bus->iic_base;
 
-    LOG_I("i2c interrupt stat: 0x%08x", stat);
+    switch (cmd)
+    {
+        case RT_I2C_DEV_CTRL_CLK:
+        {
+            rt_uint32_t speed = *(rt_uint32_t *)args;
+            if (speed == 100 * 1000)
+            {
+                dw_iic_set_transfer_speed_standard(iic_base);
+                dw_iic_set_standard_scl_hcnt(iic_base, (((IC_CLK * 4000U) / 1000U) - 7U));
+                dw_iic_set_standard_scl_lcnt(iic_base, (((IC_CLK * 4700) / 1000U) - 1U));
+            }
+            else if (speed == 400 * 1000)
+            {
+                dw_iic_set_transfer_speed_fast(iic_base);
+                dw_iic_set_fast_scl_hcnt(iic_base, (((IC_CLK * 600U) / 1000U) - 7U));
+                dw_iic_set_fast_scl_lcnt(iic_base, (((IC_CLK * 1300U) / 1000U) - 1U));
+            }
+            else if (speed == 4 * 1000 * 1000)
+            {
+                dw_iic_set_transfer_speed_high(iic_base);
+                dw_iic_set_high_scl_hcnt(iic_base, 6U);
+                dw_iic_set_high_scl_lcnt(iic_base, 8U);
+            }
+            else
+            {
+                return -RT_EIO;
+            }
+        }
+        break;
+
+        case RT_I2C_DEV_CTRL_10BIT:
+            dw_iic_set_master_10bit_addr_mode(iic_base);
+            dw_iic_set_slave_10bit_addr_mode(iic_base);
+        break;
+
+        default:
+            return -RT_EIO;
+        break;
+    }
+
+    return RT_EOK;
 }
 
 static const struct rt_i2c_bus_device_ops i2c_ops =
 {
-    .master_xfer      = _master_xfer,
+    .master_xfer      = dw_iic_master_xfer,
     .slave_xfer       = RT_NULL,
-    .i2c_bus_control  = RT_NULL
+    .i2c_bus_control  = dw_iic_bus_control,
 };
 
+static void dw_iic_init(dw_iic_regs_t *iic_base)
+{
+    dw_iic_disable(iic_base);
+    dw_iic_clear_all_irq(iic_base);
+    dw_iic_disable_all_irq(iic_base);
+
+    iic_base->IC_SAR = 0;
+
+    dw_iic_set_receive_fifo_threshold(iic_base, 0x1);
+    dw_iic_set_transmit_fifo_threshold(iic_base, 0x0);
+    dw_iic_set_sda_hold_time(iic_base, 0x1e);
+
+    dw_iic_set_master_mode(iic_base);
+    dw_iic_enable_restart(iic_base);
+
+    dw_iic_set_transfer_speed_standard(iic_base);
+    dw_iic_set_standard_scl_hcnt(iic_base, (((IC_CLK * 4000U) / 1000U) - 7U));
+    dw_iic_set_standard_scl_lcnt(iic_base, (((IC_CLK * 4700) / 1000U) - 1U));
+}
 
 #if defined(BOARD_TYPE_MILKV_DUO) || defined(BOARD_TYPE_MILKV_DUO_SPINOR)
 
@@ -531,7 +489,7 @@ static const char *pinname_whitelist_i2c4_sda[] = {
 #elif defined(BOARD_TYPE_MILKV_DUO256M) || defined(BOARD_TYPE_MILKV_DUO256M_SPINOR)
 
 #ifdef BSP_USING_I2C0
-// I2C0 is not ALLOWED for Duo
+// I2C0 is not ALLOWED for Duo256
 static const char *pinname_whitelist_i2c0_scl[] = {
     NULL,
 };
@@ -576,7 +534,7 @@ static const char *pinname_whitelist_i2c3_sda[] = {
 #endif
 
 #ifdef BSP_USING_I2C4
-// I2C4 is not ALLOWED for Duo
+// I2C4 is not ALLOWED for Duo256
 static const char *pinname_whitelist_i2c4_scl[] = {
     NULL,
 };
@@ -623,9 +581,9 @@ int rt_hw_i2c_init(void)
 
     rt_hw_i2c_pinmux_config();
 
-    for (rt_size_t i = 0; i < sizeof(_i2c_obj) / sizeof(struct _i2c_bus); i++)
+    for (rt_size_t i = 0; i < sizeof(_i2c_obj) / sizeof(struct dw_iic_bus); i++)
     {
-        hal_i2c_init(_i2c_obj->i2c_id);
+        dw_iic_init(_i2c_obj->iic_base);
 
         _i2c_obj[i].parent.ops = &i2c_ops;
 
@@ -639,10 +597,6 @@ int rt_hw_i2c_init(void)
             LOG_E("%s register failed", _i2c_obj[i].device_name);
             result = -RT_ERROR;
         }
-
-        uint32_t irqno = get_i2c_intr(_i2c_obj[i].i2c_id);
-        struct i2c_regs *_i2c = get_i2c_base(_i2c_obj[i].i2c_id);
-        rt_hw_interrupt_install(irqno, rt_hw_i2c_isr, _i2c, _i2c_obj[i].device_name);
     }
 
     return result;

+ 669 - 194
bsp/cvitek/drivers/drv_hw_i2c.h

@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2006-2023, RT-Thread Development Team
+ * Copyright (c) 2006-2024, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:
  * Date           Author       Notes
- *2024-02-14      ShichengChu  first version
+ * 2024-02-14     ShichengChu  first version
  */
 #ifndef __DRV_HW_I2C_H__
 #define __DRV_HW_I2C_H__
@@ -29,204 +29,679 @@
 #define I2C3_BASE                0x4030000
 #define I2C4_BASE                0x4040000
 
-#define BIT_I2C_CMD_DATA_READ_BIT           (0x01 << 8)
-#define BIT_I2C_CMD_DATA_STOP_BIT           (0x01 << 9)
-
-/* bit definition */
-#define BIT_I2C_CON_MASTER_MODE              (0x01 << 0)
-#define BIT_I2C_CON_STANDARD_SPEED           (0x01 << 1)
-#define BIT_I2C_CON_FULL_SPEED               (0x02 << 1)
-#define BIT_I2C_CON_HIGH_SPEED               (0x03 << 1)
-#define BIT_I2C_CON_10B_ADDR_SLAVE           (0x01 << 3)
-#define BIT_I2C_CON_10B_ADDR_MASTER          (0x01 << 4)
-#define BIT_I2C_CON_RESTART_EN               (0x01 << 5)
-#define BIT_I2C_CON_SLAVE_DIS                (0x01 << 6)
-
-#define BIT_I2C_TAR_10B_ADDR_MASTER     (0x01 << 12)
-
-#define BIT_I2C_INT_RX_UNDER                 (0x01 << 0)
-#define BIT_I2C_INT_RX_OVER                  (0x01 << 1)
-#define BIT_I2C_INT_RX_FULL                  (0x01 << 2)
-#define BIT_I2C_INT_TX_OVER                  (0x01 << 3)
-#define BIT_I2C_INT_TX_EMPTY                 (0x01 << 4)
-#define BIT_I2C_INT_RD_REQ                   (0x01 << 5)
-#define BIT_I2C_INT_TX_ABRT                  (0x01 << 6)
-#define BIT_I2C_INT_RX_DONE                  (0x01 << 7)
-#define BIT_I2C_INT_ACTIVITY                 (0x01 << 8)
-#define BIT_I2C_INT_STOP_DET                 (0x01 << 9)
-#define BIT_I2C_INT_START_DET                (0x01 << 10)
-#define BIT_I2C_INT_GEN_ALL                  (0x01 << 11)
-#define I2C_INTR_MASTER_MASK         (BIT_I2C_INT_TX_ABRT | \
-                    BIT_I2C_INT_STOP_DET | \
-                    BIT_I2C_INT_RX_FULL | \
-                    BIT_I2C_INT_TX_EMPTY)
-
-#define BIT_I2C_INT_RX_UNDER_MASK            (0x01 << 0)
-#define BIT_I2C_INT_RX_OVER_MASK             (0x01 << 1)
-#define BIT_I2C_INT_RX_FULL_MASK             (0x01 << 2)
-#define BIT_I2C_INT_TX_OVER_MASK             (0x01 << 3)
-#define BIT_I2C_INT_TX_EMPTY_MASK            (0x01 << 4)
-#define BIT_I2C_INT_RD_REQ_MASK              (0x01 << 5)
-#define BIT_I2C_INT_TX_ABRT_MASK             (0x01 << 6)
-#define BIT_I2C_INT_RX_DONE_MASK             (0x01 << 7)
-#define BIT_I2C_INT_ACTIVITY_MASK            (0x01 << 8)
-#define BIT_I2C_INT_STOP_DET_MASK            (0x01 << 9)
-#define BIT_I2C_INT_START_DET_MASK           (0x01 << 10)
-#define BIT_I2C_INT_GEN_ALL_MASK             (0x01 << 11)
-
-#define BIT_I2C_INT_RX_UNDER_RAW             (0x01 << 0)
-#define BIT_I2C_INT_RX_OVER_RAW              (0x01 << 1)
-#define BIT_I2C_INT_RX_FULL_RAW              (0x01 << 2)
-#define BIT_I2C_INT_TX_OVER_RAW              (0x01 << 3)
-#define BIT_I2C_INT_TX_EMPTY_RAW             (0x01 << 4)
-#define BIT_I2C_INT_RD_REQ_RAW               (0x01 << 5)
-#define BIT_I2C_INT_TX_ABRT_RAW              (0x01 << 6)
-#define BIT_I2C_INT_RX_DONE_RAW              (0x01 << 7)
-#define BIT_I2C_INT_ACTIVITY_RAW             (0x01 << 8)
-#define BIT_I2C_INT_STOP_DET_RAW             (0x01 << 9)
-#define BIT_I2C_INT_START_DET_RAW            (0x01 << 10)
-#define BIT_I2C_INT_GEN_ALL_RAW              (0x01 << 11)
-
-#define BIT_I2C_DMA_CR_TDMAE                 (0x01 << 1)
-#define BIT_I2C_DMA_CR_RDMAE                 (0x01 << 0)
-
-struct i2c_regs {
-    volatile uint32_t ic_con;        /* 0x00 */
-    volatile uint32_t ic_tar;        /* 0x04 */
-    volatile uint32_t ic_sar;        /* 0x08 */
-    volatile uint32_t ic_hs_maddr;    /* 0x0c */
-    volatile uint32_t ic_cmd_data;    /* 0x10 */
-    volatile uint32_t ic_ss_scl_hcnt;    /* 0x14 */
-    volatile uint32_t ic_ss_scl_lcnt;    /* 0x18 */
-    volatile uint32_t ic_fs_scl_hcnt;    /* 0x1c */
-    volatile uint32_t ic_fs_scl_lcnt;    /* 0x20 */
-    volatile uint32_t ic_hs_scl_hcnt;    /* 0x24 */
-    volatile uint32_t ic_hs_scl_lcnt;    /* 0x28 */
-    volatile uint32_t ic_intr_stat;    /* 0x2c */
-    volatile uint32_t ic_intr_mask;    /* 0x30 */
-    volatile uint32_t ic_raw_intr_stat;    /* 0x34 */
-    volatile uint32_t ic_rx_tl;        /* 0x38 */
-    volatile uint32_t ic_tx_tl;        /* 0x3c */
-    volatile uint32_t ic_clr_intr;     /* 0x40 */
-    volatile uint32_t ic_clr_rx_under;   /* 0x44 */
-    volatile uint32_t ic_clr_rx_over;    /* 0x48 */
-    volatile uint32_t ic_clr_tx_over;    /* 0x4c */
-    volatile uint32_t ic_clr_rd_req;     /* 0x50 */
-    volatile uint32_t ic_clr_tx_abrt;    /* 0x54 */
-    volatile uint32_t ic_clr_rx_done;    /* 0x58 */
-    volatile uint32_t ic_clr_activity;   /* 0x5c */
-    volatile uint32_t ic_clr_stop_det;   /* 0x60 */
-    volatile uint32_t ic_clr_start_det;  /* 0x64 */
-    volatile uint32_t ic_clr_gen_call;   /* 0x68 */
-    volatile uint32_t ic_enable;         /* 0x6c */
-    volatile uint32_t ic_status;         /* 0x70 */
-    volatile uint32_t ic_txflr;          /* 0x74 */
-    volatile uint32_t ic_rxflr;          /* 0x78 */
-    volatile uint32_t ic_sda_hold;       /* 0x7c */
-    volatile uint32_t ic_tx_abrt_source;    /* 0x80 */
-    volatile uint32_t ic_slv_dat_nack_only; /* 0x84 */
-    volatile uint32_t ic_dma_cr;      /* 0x88 */
-    volatile uint32_t ic_dma_tdlr;    /* 0x8c */
-    volatile uint32_t ic_dma_rdlr;    /* 0x90 */
-    volatile uint32_t ic_sda_setup;   /* 0x94 */
-    volatile uint32_t ic_ack_general_call; /* 0x98 */
-    volatile uint32_t ic_enable_status;    /* 0x9c */
-    volatile uint32_t ic_fs_spklen;    /* 0xa0 */
-    volatile uint32_t ic_hs_spklen;    /* 0xa4 */
-};
+#define I2C0_IRQ           (I2C_IRQ_BASE + 0)
+#define I2C1_IRQ           (I2C_IRQ_BASE + 1)
+#define I2C2_IRQ           (I2C_IRQ_BASE + 2)
+#define I2C3_IRQ           (I2C_IRQ_BASE + 3)
+#define I2C4_IRQ           (I2C_IRQ_BASE + 4)
+
 
 #if !defined(IC_CLK)
 #define IC_CLK            100
 #endif
 
-#define NANO_TO_MICRO        1000
-
-/* High and low times in different speed modes (in ns) */
-#define MIN_SS_SCL_HIGHTIME    4000
-#define MIN_SS_SCL_LOWTIME     4700
-#define MIN_FS_SCL_HIGHTIME    600
-#define MIN_FS_SCL_LOWTIME     1300
-#define MIN_HS100pF_SCL_HIGHTIME 60
-#define MIN_HS100pF_SCL_LOWTIME    120
-#define MIN_HS400pF_SCL_HIGHTIME   160
-#define MIN_HS400pF_SCL_LOWTIME    320
-
-#define CONFIG_SYS_HZ        1000    /* decrementer freq: 1ms ticks */
-/* Worst case timeout for 1 byte is kept as 2ms */
-#define I2C_BYTE_TO        (CONFIG_SYS_HZ/500)
-
-#define I2C_STOPDET_TO        (CONFIG_SYS_HZ/500)
-#define I2C_BYTE_TO_BB        (I2C_BYTE_TO * 16)
-
-/* i2c control register definitions */
-#define IC_CON_SD        0x0040
-#define IC_CON_RE        0x0020
-#define IC_CON_10BITADDRMASTER    0x0010
-#define IC_CON_10BITADDR_SLAVE    0x0008
-#define IC_CON_SPD_MSK       0x0006
-#define IC_CON_SPD_SS        0x0002
-#define IC_CON_SPD_FS        0x0004
-#define IC_CON_SPD_HS        0x0006
-#define IC_CON_MM        0x0001
-
-/* i2c data buffer and command register definitions */
-#define IC_CMD            0x0100
-#define IC_STOP           0x0200
-
-/* i2c interrupt status register definitions */
-#define IC_GEN_CALL        0x0800
-#define IC_START_DET       0x0400
-#define IC_STOP_DET        0x0200
-#define IC_ACTIVITY        0x0100
-#define IC_RX_DONE         0x0080
-#define IC_TX_ABRT         0x0040
-#define IC_RD_REQ          0x0020
-#define IC_TX_EMPTY        0x0010
-#define IC_TX_OVER         0x0008
-#define IC_RX_FULL         0x0004
-#define IC_RX_OVER         0x0002
-#define IC_RX_UNDER        0x0001
-
-/* fifo threshold register definitions */
-#define IC_TL0            0x00
-#define IC_TL1            0x01
-#define IC_TL2            0x02
-#define IC_TL3            0x03
-#define IC_TL4            0x04
-#define IC_TL5            0x05
-#define IC_TL6            0x06
-#define IC_TL7            0x07
-#define IC_RX_TL        IC_TL0
-#define IC_TX_TL        IC_TL0
-
-/* i2c enable register definitions */
-#define IC_ENABLE        0x0001
-
-/* i2c status register  definitions */
-#define IC_STATUS_SA        0x0040
-#define IC_STATUS_MA        0x0020
-#define IC_STATUS_RFF       0x0010
-#define IC_STATUS_RFNE      0x0008
-#define IC_STATUS_TFE       0x0004
-#define IC_STATUS_TFNF      0x0002
-#define IC_STATUS_ACT       0x0001
-
-/* Speed Selection */
-#define IC_SPEED_MODE_STANDARD  1
-#define IC_SPEED_MODE_FAST      2
-#define IC_SPEED_MODE_MAX       3
-
-#define I2C_MAX_SPEED         3400000
-#define I2C_FAST_SPEED        400000
-#define I2C_STANDARD_SPEED    100000
-
-#define I2C_SPEED        I2C_FAST_SPEED
+/*
+ * I2C register bit definitions
+ */
 
-#define I2C0_IRQ           (I2C_IRQ_BASE + 0)
-#define I2C1_IRQ           (I2C_IRQ_BASE + 1)
-#define I2C2_IRQ           (I2C_IRQ_BASE + 2)
-#define I2C3_IRQ           (I2C_IRQ_BASE + 3)
-#define I2C4_IRQ           (I2C_IRQ_BASE + 4)
+/* IC_CON, offset: 0x00 */
+#define DW_IIC_CON_DEFAUL                          (0x23U)
+#define DW_IIC_CON_MASTER_Pos                      (0U)
+#define DW_IIC_CON_MASTER_Msk                      (0x1U << DW_IIC_CON_MASTER_Pos)
+#define DW_IIC_CON_MASTER_EN                       DW_IIC_CON_MASTER_Msk
+
+#define DW_IIC_CON_SPEEDL_Pos                      (1U)
+#define DW_IIC_CON_SPEEDL_Msk                      (0x1U << DW_IIC_CON_SPEEDL_Pos)
+#define DW_IIC_CON_SPEEDL_EN                       DW_IIC_CON_SPEEDL_Msk
+
+#define DW_IIC_CON_SPEEDH_Pos                      (2U)
+#define DW_IIC_CON_SPEEDH_Msk                      (0x1U << DW_IIC_CON_SPEEDH_Pos)
+#define DW_IIC_CON_SPEEDH_EN                       DW_IIC_CON_SPEEDH_Msk
+
+#define DW_IIC_CON_SLAVE_ADDR_MODE_Pos             (3U)
+#define DW_IIC_CON_SLAVE_ADDR_MODE_Msk             (0x1U << DW_IIC_CON_SLAVE_ADDR_MODE_Pos)
+#define DW_IIC_CON_SLAVE_ADDR_MODE                 DW_IIC_CON_SLAVE_ADDR_MODE_Msk
+
+#define DW_IIC_CON_MASTER_ADDR_MODE_Pos             (4U)
+#define DW_IIC_CON_MASTER_ADDR_MODE_Msk             (0x1U << DW_IIC_CON_MASTER_ADDR_MODE_Pos)
+#define DW_IIC_CON_MASTER_ADDR_MODE                 DW_IIC_CON_MASTER_ADDR_MODE_Msk
+
+#define DW_IIC_CON_RESTART_Pos                     (5U)
+#define DW_IIC_CON_RESTART_Msk                     (0x1U << DW_IIC_CON_RESTART_Pos)
+#define DW_IIC_CON_RESTART_EN                      DW_IIC_CON_RESTART_Msk
+
+#define DW_IIC_CON_SLAVE_Pos                       (6U)
+#define DW_IIC_CON_SLAVE_Msk                       (0x1U << DW_IIC_CON_SLAVE_Pos)
+#define DW_IIC_CON_SLAVE_EN                        DW_IIC_CON_SLAVE_Msk
+
+/* IC_TAR, offset: 0x04 */
+#define DW_IIC_TAR_GC_OR_START_Pos                 (10U)
+#define DW_IIC_TAR_GC_OR_START_Msk                 (0x1U << DW_IIC_TAR_GC_OR_START_Pos)
+#define DW_IIC_TAR_GC_OR_START                     DW_IIC_TAR_GC_OR_START_Msk
+
+#define DW_IIC_TAR_SPECIAL_Pos                     (11U)
+#define DW_IIC_TAR_SPECIAL_Msk                     (0x1U << DW_IIC_TAR_SPECIAL_Pos)
+#define DW_IIC_TAR_SPECIAL                         DW_IIC_TAR_SPECIAL_Msk
+
+#define DW_IIC_TAR_MASTER_ADDR_MODE_Pos            (12U)
+#define DW_IIC_TAR_MASTER_ADDR_MODE_Msk            (0x1U << DW_IIC_TAR_MASTER_ADDR_MODE_Pos)
+#define DW_IIC_TAR_MASTER_ADDR_MODE                DW_IIC_TAR_MASTER_ADDR_MODE_Msk
+
+/* IC_DATA_CMD, offset: 0x10 */
+#define DW_IIC_DATA_CMD_Pos                        (8U)
+#define DW_IIC_DATA_CMD_Msk                        (0x1U << DW_IIC_DATA_CMD_Pos)
+#define DW_IIC_DATA_CMD                            DW_IIC_DATA_CMD_Msk
+
+#define DW_IIC_DATA_STOP_Pos                       (9U)
+#define DW_IIC_DATA_STOP_Msk                       (0x1U << DW_IIC_DATA_STOP_Pos)
+#define DW_IIC_DATA_STOP                           DW_IIC_DATA_STOP_Msk
+
+/* IC_INTR_STAT, offset: 0x2C */
+#define DW_IIC_INTR_RX_UNDER_Pos                   (0U)
+#define DW_IIC_INTR_RX_UNDER_Msk                   (0x1U << DW_IIC_INTR_RX_UNDER_Pos)
+#define DW_IIC_INTR_RX_UNDER                       DW_IIC_INTR_RX_UNDER_Msk
+
+#define DW_IIC_INTR_RX_OVER_Pos                    (1U)
+#define DW_IIC_INTR_RX_OVER_Msk                    (0x1U << DW_IIC_INTR_RX_OVER_Pos)
+#define DW_IIC_INTR_RX_OVER                        DW_IIC_INTR_RX_OVER_Msk
+
+#define DW_IIC_INTR_RX_FULL_Pos                    (2U)
+#define DW_IIC_INTR_RX_FULL_Msk                    (0x1U << DW_IIC_INTR_RX_FULL_Pos)
+#define DW_IIC_INTR_RX_FULL                        DW_IIC_INTR_RX_FULL_Msk
+
+#define DW_IIC_INTR_TX_OVER_Pos                    (3U)
+#define DW_IIC_INTR_TX_OVER_Msk                    (0x1U << DW_IIC_INTR_TX_OVER_Pos)
+#define DW_IIC_INTR_TX_OVER                        DW_IIC_INTR_TX_OVER_Msk
+
+#define DW_IIC_INTR_TX_EMPTY_Pos                   (4U)
+#define DW_IIC_INTR_TX_EMPTY_Msk                   (0x1U << DW_IIC_INTR_TX_EMPTY_Pos)
+#define DW_IIC_INTR_TX_EMPTY                       DW_IIC_INTR_TX_EMPTY_Msk
+
+#define DW_IIC_INTR_RD_REQ_Pos                     (5U)
+#define DW_IIC_INTR_RD_REQ_Msk                     (0x1U << DW_IIC_INTR_RD_REQ_Pos)
+#define DW_IIC_INTR_RD_REQ                         DW_IIC_INTR_RD_REQ_Msk
+
+#define DW_IIC_INTR_TX_ABRT_Pos                    (6U)
+#define DW_IIC_INTR_TX_ABRT_Msk                    (0x1U << DW_IIC_INTR_TX_ABRT_Pos)
+#define DW_IIC_INTR_TX_ABRT                        DW_IIC_INTR_TX_ABRT_Msk
+
+#define DW_IIC_INTR_RX_DONE_Pos                    (7U)
+#define DW_IIC_INTR_RX_DONE_Msk                    (0x1U << DW_IIC_INTR_RX_DONE_Pos)
+#define DW_IIC_INTR_RX_DONE                        DW_IIC_INTR_RX_DONE_Msk
+
+#define DW_IIC_INTR_ACTIVITY_Pos                   (8U)
+#define DW_IIC_INTR_ACTIVITY_Msk                   (0x1U << DW_IIC_INTR_ACTIVITY_Pos)
+#define DW_IIC_INTR_ACTIVITY                       DW_IIC_INTR_ACTIVITY_Msk
+
+#define DW_IIC_INTR_STOP_DET_Pos                   (9U)
+#define DW_IIC_INTR_STOP_DET_Msk                   (0x1U << DW_IIC_INTR_STOP_DET_Pos)
+#define DW_IIC_INTR_STOP_DET                       DW_IIC_INTR_STOP_DET_Msk
+
+#define DW_IIC_INTR_START_DET_Pos                  (10U)
+#define DW_IIC_INTR_START_DET_Msk                  (0x1U << DW_IIC_INTR_START_DET_Pos)
+#define DW_IIC_INTR_START_DET                      DW_IIC_INTR_START_DET_Msk
+
+#define DW_IIC_INTR_GEN_CALL_Pos                   (11U)
+#define DW_IIC_INTR_GEN_CALL_Msk                   (0x1U << DW_IIC_INTR_GEN_CALL_Pos)
+#define DW_IIC_INTR_GEN_CALL                       DW_IIC_INTR_GEN_CALL_Msk
+
+/* IC_INTR_MASK, offset: 0x30 */
+#define DW_IIC_M_RX_UNDER_Pos                      (0U)
+#define DW_IIC_M_RX_UNDER_Msk                      (0x1U << DW_IIC_INTR_RX_UNDER_Pos)
+#define DW_IIC_M_RX_UNDER                          DW_IIC_INTR_RX_UNDER_Msk
+
+#define DW_IIC_M_RX_OVER_Pos                       (1U)
+#define DW_IIC_M_RX_OVER_Msk                       (0x1U << DW_IIC_INTR_RX_OVER_Pos)
+#define DW_IIC_M_RX_OVER                           DW_IIC_INTR_RX_OVER_Msk
+
+#define DW_IIC_M_RX_FULL_Pos                       (2U)
+#define DW_IIC_M_RX_FULL_Msk                       (0x1U << DW_IIC_INTR_RX_FULL_Pos)
+#define DW_IIC_M_RX_FULL                           DW_IIC_INTR_RX_FULL_Msk
+
+#define DW_IIC_M_TX_OVER_Pos                       (3U)
+#define DW_IIC_M_TX_OVER_Msk                       (0x1U << DW_IIC_INTR_TX_OVER_Pos)
+#define DW_IIC_M_TX_OVER                           DW_IIC_INTR_TX_OVER_Msk
+
+#define DW_IIC_M_TX_EMPTY_Pos                      (4U)
+#define DW_IIC_M_TX_EMPTY_Msk                      (0x1U << DW_IIC_INTR_TX_EMPTY_Pos)
+#define DW_IIC_M_TX_EMPTY                          DW_IIC_INTR_TX_EMPTY_Msk
+
+#define DW_IIC_M_RD_REQ_Pos                        (5U)
+#define DW_IIC_M_RD_REQ_Msk                        (0x1U << DW_IIC_INTR_RD_REQ_Pos)
+#define DW_IIC_M_RD_REQ                            DW_IIC_INTR_RD_REQ_Msk
+
+#define DW_IIC_M_TX_ABRT_Pos                       (6U)
+#define DW_IIC_M_TX_ABRT_Msk                       (0x1U << DW_IIC_INTR_TX_ABRT_Pos)
+#define DW_IIC_M_TX_ABRT                           DW_IIC_INTR_TX_ABRT_Msk
+
+#define DW_IIC_M_RX_DONE_Pos                       (7U)
+#define DW_IIC_M_RX_DONE_Msk                       (0x1U << DW_IIC_INTR_RX_DONE_Pos)
+#define DW_IIC_M_RX_DONE                           DW_IIC_INTR_RX_DONE_Msk
+
+#define DW_IIC_M_ACTIVITY_Pos                      (8U)
+#define DW_IIC_M_ACTIVITY_Msk                      (0x1U << DW_IIC_INTR_ACTIVITY_Pos)
+#define DW_IIC_M_ACTIVITY                          DW_IIC_INTR_ACTIVITY_Msk
+
+#define DW_IIC_M_STOP_DET_Pos                      (9U)
+#define DW_IIC_M_STOP_DET_Msk                      (0x1U << DW_IIC_INTR_STOP_DET_Pos)
+#define DW_IIC_M_STOP_DET                          DW_IIC_INTR_STOP_DET_Msk
+
+#define DW_IIC_M_START_DET_Pos                     (10U)
+#define DW_IIC_M_START_DET_Msk                     (0x1U << DW_IIC_INTR_START_DET_Pos)
+#define DW_IIC_M_START_DET                         DW_IIC_INTR_START_DET_Msk
+
+#define DW_IIC_M_GEN_CALL_Pos                      (11U)
+#define DW_IIC_M_GEN_CALL_Msk                      (0x1U << DW_IIC_INTR_GEN_CALL_Pos)
+#define DW_IIC_M_GEN_CALL                          DW_IIC_INTR_GEN_CALL_Msk
+
+#define DW_IIC_INTR_DEFAULT_MASK                   ( DW_IIC_M_RX_FULL | DW_IIC_M_TX_EMPTY | DW_IIC_M_TX_ABRT | DW_IIC_M_STOP_DET)
+
+/* IC_RAW_INTR_STAT, offset: 0x34 */
+#define DW_IIC_RAW_RX_UNDER_Pos                    (0U)
+#define DW_IIC_RAW_RX_UNDER_Msk                    (0x1U << DW_IIC_INTR_RX_UNDER_Pos)
+#define DW_IIC_RAW_RX_UNDER                        DW_IIC_INTR_RX_UNDER_Msk
+
+#define DW_IIC_RAW_RX_OVER_Pos                     (1U)
+#define DW_IIC_RAW_RX_OVER_Msk                     (0x1U << DW_IIC_INTR_RX_OVER_Pos)
+#define DW_IIC_RAW_RX_OVER                         DW_IIC_INTR_RX_OVER_Msk
+
+#define DW_IIC_RAW_RX_FULL_Pos                     (2U)
+#define DW_IIC_RAW_RX_FULL_Msk                     (0x1U << DW_IIC_INTR_RX_FULL_Pos)
+#define DW_IIC_RAW_RX_FULL                         DW_IIC_INTR_RX_FULL_Msk
+
+#define DW_IIC_RAW_TX_OVER_Pos                     (3U)
+#define DW_IIC_RAW_TX_OVER_Msk                     (0x1U << DW_IIC_INTR_TX_OVER_Pos)
+#define DW_IIC_RAW_TX_OVER                         DW_IIC_INTR_TX_OVER_Msk
+
+#define DW_IIC_RAW_TX_EMPTY_Pos                    (4U)
+#define DW_IIC_RAW_TX_EMPTY_Msk                    (0x1U << DW_IIC_INTR_TX_EMPTY_Pos)
+#define DW_IIC_RAW_TX_EMPTY                        DW_IIC_INTR_TX_EMPTY_Msk
+
+#define DW_IIC_RAW_RD_REQ_Pos                      (5U)
+#define DW_IIC_RAW_RD_REQ_Msk                      (0x1U << DW_IIC_INTR_RD_REQ_Pos)
+#define DW_IIC_RAW_RD_REQ                          DW_IIC_INTR_RD_REQ_Msk
+
+#define DW_IIC_RAW_TX_ABRT_Pos                     (6U)
+#define DW_IIC_RAW_TX_ABRT_Msk                     (0x1U << DW_IIC_INTR_TX_ABRT_Pos)
+#define DW_IIC_RAW_TX_ABRT                         DW_IIC_INTR_TX_ABRT_Msk
+
+#define DW_IIC_RAW_RX_DONE_Pos                     (7U)
+#define DW_IIC_RAW_RX_DONE_Msk                     (0x1U << DW_IIC_INTR_RX_DONE_Pos)
+#define DW_IIC_RAW_RX_DONE                         DW_IIC_INTR_RX_DONE_Msk
+
+#define DW_IIC_RAW_ACTIVITY_Pos                    (8U)
+#define DW_IIC_RAW_ACTIVITY_Msk                    (0x1U << DW_IIC_INTR_ACTIVITY_Pos)
+#define DW_IIC_RAW_ACTIVITY                        DW_IIC_INTR_ACTIVITY_Msk
+
+#define DW_IIC_RAW_STOP_DET_Pos                    (9U)
+#define DW_IIC_RAW_STOP_DET_Msk                    (0x1U << DW_IIC_INTR_STOP_DET_Pos)
+#define DW_IIC_RAW_STOP_DET                        DW_IIC_INTR_STOP_DET_Msk
+
+#define DW_IIC_RAW_START_DET_Pos                   (10U)
+#define DW_IIC_RAW_START_DET_Msk                   (0x1U << DW_IIC_INTR_START_DET_Pos)
+#define DW_IIC_RAW_START_DET                       DW_IIC_INTR_START_DET_Msk
+
+#define DW_IIC_RAW_GEN_CALL_Pos                    (11U)
+#define DW_IIC_RAW_GEN_CALL_Msk                    (0x1U << DW_IIC_INTR_GEN_CALL_Pos)
+#define DW_IIC_RAW_GEN_CALL                        DW_IIC_INTR_GEN_CALL_Msk
+
+
+/* IC_ENABLE, offset: 0x6C */
+#define DW_IIC_ENABLE_Pos                          (0U)
+#define DW_IIC_ENABLE_Msk                          (0x1U << DW_IIC_ENABLE_Pos)
+#define DW_IIC_EN                                  DW_IIC_ENABLE_Msk
+
+/* IC_STATUS, offset: 0x70 */
+#define DW_IIC_STATUS_ACTIVITY_Pos                 (0U)
+#define DW_IIC_STATUS_ACTIVITY_Msk                 (0x1U << DW_IIC_STATUS_ACTIVITY_Pos)
+#define DW_IIC_STATUS_ACTIVITY_STATE               DW_IIC_STATUS_ACTIVITY_Msk
+
+#define DW_IIC_STATUS_TFNE_Pos                     (1U)
+#define DW_IIC_STATUS_TFNE_Msk                     (0x1U << DW_IIC_STATUS_TFNE_Pos)
+#define DW_IIC_TXFIFO_NOT_FULL_STATE               DW_IIC_STATUS_TFNE_Msk
+
+#define DW_IIC_STATUS_TFE_Pos                      (2U)
+#define DW_IIC_STATUS_TFE_Msk                      (0x1U << DW_IIC_STATUS_TFE_Pos)
+#define DW_IIC_TXFIFO_EMPTY_STATE                  DW_IIC_STATUS_TFE_Msk
+
+#define DW_IIC_STATUS_RFNE_Pos                     (3U)
+#define DW_IIC_STATUS_RFNE_Msk                     (0x1U << DW_IIC_STATUS_RFNE_Pos)
+#define DW_IIC_RXFIFO_NOT_EMPTY_STATE              DW_IIC_STATUS_RFNE_Msk
+
+#define DW_IIC_STATUS_REF_Pos                      (4U)
+#define DW_IIC_STATUS_REF_Msk                      (0x1U << DW_IIC_STATUS_REF_Pos)
+#define DW_IIC_RXFIFO_FULL_STATE                   DW_IIC_STATUS_REF_Msk
+
+#define DW_IIC_STATUS_MST_ACTIVITY_Pos             (5U)
+#define DW_IIC_STATUS_MST_ACTIVITY_Msk             (0x1U << DW_IIC_STATUS_MST_ACTIVITY_Pos)
+#define DW_IIC_MST_ACTIVITY_STATE                  DW_IIC_STATUS_MST_ACTIVITY_Msk
+
+#define DW_IIC_STATUS_SLV_ACTIVITY_Pos             (6U)
+#define DW_IIC_STATUS_SLV_ACTIVITY_Msk             (0x1U << DW_IIC_STATUS_SLV_ACTIVITY_Pos)
+#define DW_IIC_SLV_ACTIVITY_STATE                  DW_IIC_STATUS_SLV_ACTIVITY_Msk
+
+/* IC_TX_ABRT_SOURCE, offset: 0x80 */
+#define DW_IIC_TX_ABRT_7B_ADDR_NOACK_Pos           (0U)
+#define DW_IIC_TX_ABRT_7B_ADDR_NOACK_Msk           (0x1U << DW_IIC_TX_ABRT_7B_ADDR_NOACK_Pos)
+#define DW_IIC_TX_ABRT_7B_ADDR_NOACK               DW_IIC_TX_ABRT_7B_ADDR_NOACK_Msk
+
+#define DW_IIC_TX_ABRT_10ADDR1_NOACK_Pos           (1U)
+#define DW_IIC_TX_ABRT_10ADDR1_NOACK_Msk           (0x1U << DW_IIC_TX_ABRT_10ADDR1_NOACK_Pos)
+#define DW_IIC_TX_ABRT_10ADDR1_NOACK               DW_IIC_TX_ABRT_10ADDR1_NOACK_Msk
+
+#define DW_IIC_TX_ABRT_10ADDR2_NOACK_Pos           (2U)
+#define DW_IIC_TX_ABRT_10ADDR2_NOACK_Msk           (0x1U << DW_IIC_TX_ABRT_10ADDR2_NOACK_Pos)
+#define DW_IIC_TX_ABRT_10ADDR2_NOACK               DW_IIC_TX_ABRT_10ADDR2_NOACK_Msk
+
+#define DW_IIC_TX_ABRT_TXDATA_NOACK_Pos            (3U)
+#define DW_IIC_TX_ABRT_TXDATA_NOACK_Msk            (0x1U << DW_IIC_TX_ABRT_TXDATA_NOACK_Pos)
+#define DW_IIC_TX_ABRT_TXDATA_NOACK                DW_IIC_TX_ABRT_TXDATA_NOACK_Msk
+
+#define DW_IIC_TX_ABRT_GCALL_NOACK_Pos             (4U)
+#define DW_IIC_TX_ABRT_GCALL_NOACK_Msk             (0x1U << DW_IIC_TX_ABRT_GCALL_NOACK_Pos)
+#define DW_IIC_TX_ABRT_GCALL_NOACK                 DW_IIC_TX_ABRT_GCALL_NOACK_Msk
+
+#define DW_IIC_TX_ABRT_GCALL_READ_Pos              (5U)
+#define DW_IIC_TX_ABRT_GCALL_READ_Msk              (0x1U << DW_IIC_TX_ABRT_GCALL_READ_Pos)
+#define DW_IIC_TX_ABRT_GCALL_READ                  DW_IIC_TX_ABRT_GCALL_READ_Msk
+
+#define DW_IIC_TX_ABRT_HS_ACKDET_Pos               (6U)
+#define DW_IIC_TX_ABRT_HS_ACKDET_Msk               (0x1U << DW_IIC_TX_ABRT_HS_ACKDET_Pos)
+#define DW_IIC_TX_ABRT_HS_ACKDET                   DW_IIC_TX_ABRT_HS_ACKDET_Msk
+
+#define DW_IIC_TX_ABRT_SBYTE_ACKDET_Pos            (7U)
+#define DW_IIC_TX_ABRT_SBYTE_ACKDET_Msk            (0x1U << DW_IIC_TX_ABRT_SBYTE_ACKDET_Pos)
+#define DW_IIC_TX_ABRT_SBYTE_ACKDET                DW_IIC_TX_ABRT_SBYTE_ACKDET_Msk
+
+#define DW_IIC_TX_ABRT_HS_NORSTRT_Pos              (8U)
+#define DW_IIC_TX_ABRT_HS_NORSTRT_Msk              (0x1U << DW_IIC_TX_ABRT_HS_NORSTRT_Pos)
+#define DW_IIC_TX_ABRT_HS_NORSTRT                  DW_IIC_TX_ABRT_HS_NORSTRT_Msk
+
+#define DW_IIC_TX_ABRT_SBYTE_NORSTRT_Pos           (9U)
+#define DW_IIC_TX_ABRT_SBYTE_NORSTRT_Msk           (0x1U << DW_IIC_TX_ABRT_SBYTE_NORSTRT_Pos)
+#define DW_IIC_TX_ABRT_SBYTE_NORSTRT               DW_IIC_TX_ABRT_SBYTE_NORSTRT_Msk
+
+#define DW_IIC_TX_ABRT_10B_RD_NORSTRT_Pos          (10U)
+#define DW_IIC_TX_ABRT_10B_RD_NORSTRT_Msk          (0x1U << DW_IIC_TX_ABRT_10B_RD_NORSTRT_Pos)
+#define DW_IIC_TX_ABRT_10B_RD_NORSTRT              DW_IIC_TX_ABRT_10B_RD_NORSTRT_Msk
+
+#define DW_IIC_TX_ABRT_ARB_MASTER_DIS_Pos          (11U)
+#define DW_IIC_TX_ABRT_ARB_MASTER_DIS_Msk          (0x1U << DW_IIC_TX_ABRT_ARB_MASTER_DIS_Pos)
+#define DW_IIC_TX_ABRT_ARB_MASTER_DIS              DW_IIC_TX_ABRT_ARB_MASTER_DIS_Msk
+
+#define DW_IIC_TX_ABRT_ARB_LOST_Pos                (12U)
+#define DW_IIC_TX_ABRT_ARB_LOST_Msk                (0x1U << DW_IIC_TX_ABRT_ARB_LOST_Pos)
+#define DW_IIC_TX_ABRT_ARB_LOST                    DW_IIC_TX_ABRT_ARB_LOST_Msk
+
+#define DW_IIC_TX_ABRT_SLVFLUSH_TXFIFO_Pos         (13U)
+#define DW_IIC_TX_ABRT_SLVFLUSH_TXFIFO_Msk         (0x1U << DW_IIC_TX_ABRT_SLVFLUSH_TXFIFO_Pos)
+#define DW_IIC_TX_ABRT_SLVFLUSH_TXFIFO             DW_IIC_TX_ABRT_SLVFLUSH_TXFIFO_Msk
+
+#define DW_IIC_TX_ABRT_SLV_ARBLOST_Pos             (14U)
+#define DW_IIC_TX_ABRT_SLV_ARBLOST_Msk             (0x1U << DW_IIC_TX_ABRT_SLV_ARBLOST_Pos)
+#define DW_IIC_TX_ABRT_SLV_ARBLOST                 DW_IIC_TX_ABRT_SLV_ARBLOST_Msk
+
+#define DW_IIC_TX_ABRT_SLVRD_INTX_Pos              (15U)
+#define DW_IIC_TX_ABRT_SLVRD_INTX_Msk              (0x1U << DW_IIC_TX_ABRT_SLVRD_INTX_Pos)
+#define DW_IIC_TX_ABRT_SLVRD_INTX                  DW_IIC_TX_ABRT_SLVRD_INTX_Msk
+
+/* IC_DMA_CR, offset: 0x88 */
+#define DW_IIC_DMA_CR_RDMAE_Pos                    (0U)
+#define DW_IIC_DMA_CR_RDMAE_Msk                    (0x1U << DW_IIC_DMA_CR_RDMAE_Pos)
+#define DW_IIC_DMA_CR_RDMAE                        DW_IIC_DMA_CR_RDMAE_Msk
+
+#define DW_IIC_DMA_CR_TDMAE_Pos                    (1U)
+#define DW_IIC_DMA_CR_TDMAE_Msk                    (0x1U << DW_IIC_DMA_CR_TDMAE_Pos)
+#define DW_IIC_DMA_CR_TDMAE                        DW_IIC_DMA_CR_TDMAE_Msk
+
+/* IC_DMA_TDLR, offset: 0x8C */
+#define DW_IIC_DMA_TDLR_Msk                        (0x7U)
+/* IC_DMA_RDLR, offset: 0x90 */
+#define DW_IIC_DMA_RDLR_Msk                        (0x7U)
+
+/* IC_GEN_CALL_EN, offset: 0xA0 */
+//no this register
+#define DW_IIC_GEN_CALL_EN_Pos                     (0U)
+#define DW_IIC_GEN_CALL_EN_Msk                     (0x1U << DW_IIC_GEN_CALL_EN_Pos)
+#define DW_IIC_GEN_CALL_EN                         DW_IIC_GEN_CALL_EN_Msk
+
+/* IC_FIFO_RST_EN, offset: 0xA4 */
+//no this register
+#define DW_IIC_FIFO_RST_EN_Pos                     (0U)
+#define DW_IIC_FIFO_RST_EN_Msk                     (0x1U << DW_IIC_FIFO_RST_EN_Pos)
+#define DW_IIC_FIFO_RST_EN                         DW_IIC_FIFO_RST_EN_Msk
+
+#define TXFIFO_IRQ_TH                              (0x4U)
+#define RXFIFO_IRQ_TH                              (0x2U)
+#define IIC_MAX_FIFO                               (0x8U)
+
+/* IIC default value definitions */
+#define DW_IIC_TIMEOUT_DEF_VAL  0x1000U
+
+#define DW_IIC_EEPROM_MAX_WRITE_LEN  0X1U
+
+typedef struct {
+    volatile uint32_t IC_CON;                    /* Offset: 0x000 (R/W)  I2C Control */
+    volatile uint32_t IC_TAR;                    /* Offset: 0x004 (R/W)  I2C target address */
+    volatile uint32_t IC_SAR;                    /* Offset: 0x008 (R/W)  I2C slave address  */
+    volatile uint32_t IC_HS_MADDR;               /* Offset: 0x00C (R/W)  I2C HS Master Mode Code Address */
+    volatile uint32_t IC_DATA_CMD;               /* Offset: 0x010 (R/W)  I2C RX/TX Data Buffer and Command */
+    volatile uint32_t IC_SS_SCL_HCNT;            /* Offset: 0x014 (R/W)  Standard speed I2C Clock SCL High Count */
+    volatile uint32_t IC_SS_SCL_LCNT;            /* Offset: 0x018 (R/W)  Standard speed I2C Clock SCL Low Count */
+    volatile uint32_t IC_FS_SCL_HCNT;            /* Offset: 0x01C (R/W)  Fast speed I2C Clock SCL High Count */
+    volatile uint32_t IC_FS_SCL_LCNT;            /* Offset: 0x020 (R/W)  Fast speed I2C Clock SCL Low Count */
+    volatile uint32_t IC_HS_SCL_HCNT;            /* Offset: 0x024 (R/W)  High speed I2C Clock SCL High Count*/
+    volatile uint32_t IC_HS_SCL_LCNT;            /* Offset: 0x028 (R/W)  High speed I2C Clock SCL Low Count */
+    volatile const  uint32_t IC_INTR_STAT;              /* Offset: 0x02C (R)    I2C Interrupt Status */
+    volatile uint32_t IC_INTR_MASK;              /* Offset: 0x030 (R/W)  I2C Interrupt Mask */
+    volatile const  uint32_t IC_RAW_INTR_STAT;          /* Offset: 0x034 (R)    I2C Raw Interrupt Status */
+    volatile uint32_t IC_RX_TL;                  /* Offset: 0x038 (R/W)  I2C Receive FIFO Threshold */
+    volatile uint32_t IC_TX_TL;                  /* Offset: 0x03C (R/W)  I2C Transmit FIFO Threshold */
+    volatile const  uint32_t IC_CLR_INTR;               /* Offset: 0x040 (R)    Clear combined and individual interrupts*/
+    volatile const  uint32_t IC_CLR_RX_UNDER;           /* Offset: 0x044 (R)    I2C Clear RX_UNDER interrupt  */
+    volatile const  uint32_t IC_CLR_RX_OVER;            /* Offset: 0x048 (R)    I2C Clear RX_OVER interrupt  */
+    volatile const  uint32_t IC_CLR_TX_OVER;            /* Offset: 0x04C (R)    I2C Clear TX_OVER interrupt  */
+    volatile const  uint32_t IC_CLR_RD_REQ;             /* Offset: 0x050 (R)    I2C Clear RD_REQ interrupt  */
+    volatile const  uint32_t IC_CLR_TX_ABRT;            /* Offset: 0x054 (R)    I2C Clear TX_ABRT interrupt  */
+    volatile const  uint32_t IC_CLR_RX_DONE;            /* Offset: 0x058 (R)    I2C Clear RX_DONE interrupt  */
+    volatile const  uint32_t IC_CLR_ACTIVITY;           /* Offset: 0x05C (R)    I2C Clear ACTIVITY interrupt  */
+    volatile const  uint32_t IC_CLR_STOP_DET;           /* Offset: 0x060 (R)    I2C Clear STOP_DET interrupt  */
+    volatile const  uint32_t IC_CLR_START_DET;          /* Offset: 0x064 (R)    I2C Clear START_DET interrupt  */
+    volatile const  uint32_t IC_CLR_GEN_CALL;           /* Offset: 0x068 (R)    I2C Clear GEN_CAL interrupt  */
+    volatile uint32_t IC_ENABLE;                 /* Offset: 0x06C (R/W)  I2C enable */
+    volatile const  uint32_t IC_STATUS;                 /* Offset: 0x070 (R)    I2C status register */
+    volatile const  uint32_t IC_TXFLR;                  /* Offset: 0x074 (R)    Transmit FIFO Level register */
+    volatile const  uint32_t IC_RXFLR;                  /* Offset: 0x078 (R)    Receive FIFO Level Register */
+    volatile uint32_t IC_SDA_HOLD;               /* Offset: 0x07C (R/W)  SDA hold time register */
+    volatile uint32_t IC_TX_ABRT_SOURCE;         /* Offset: 0x080 (R/W)  I2C Transmit Abort Status Register */
+    volatile uint32_t IC_SLV_DAT_NACK_ONLY;      /* Offset: 0x084 (R/W)  I2C Slave Address1 */
+    volatile uint32_t IC_DMA_CR;                 /* Offset: 0x088 (R/W)  DMA Control Register for transmit and receive handshaking interface  */
+    volatile uint32_t IC_DMA_TDLR;               /* Offset: 0x08C (R/W)  DMA Transmit Data Level */
+    volatile uint32_t IC_DMA_RDLR;               /* Offset: 0x090 (R/W)  DMA Receive Data Level */
+    volatile uint32_t IC_SDA_SETUP;              /* Offset: 0x094 (R/W)  I2C Slave Address2 */
+    volatile uint32_t IC_ACK_GENERAL_CALL;       /* Offset: 0x098 (R/W)  I2C Slave Address3 */
+    volatile uint32_t IC_ENABLE_STATUS;          /* Offset: 0x09C (R/W)  I2C address number in slave mode */
+    volatile uint32_t IC_FS_SPKLEN;              /* Offset: 0x0A0 (R/W)  I2C general call mask register when I2C is in the slave mode */
+    volatile uint32_t IC_HS_SPKLEN;              /* Offset: 0x0A4 (R/W)  I2C FIFO flush register when I2C is in the slave transfer mode*/
+} dw_iic_regs_t;
+
+static inline void dw_iic_enable(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_ENABLE = DW_IIC_EN;
+}
+
+static inline void dw_iic_disable(dw_iic_regs_t *iic_base)
+{
+    /* First clear ACTIVITY, then Disable IIC */
+    iic_base->IC_CLR_ACTIVITY;
+    iic_base->IC_ENABLE = ~DW_IIC_EN;
+}
+
+static inline uint32_t dw_iic_get_iic_status(dw_iic_regs_t *iic_base)
+{
+    return iic_base->IC_ENABLE;
+}
+
+static inline void dw_iic_enable_restart(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_CON |= DW_IIC_CON_RESTART_EN;
+}
+
+static inline void dw_iic_master_enable_transmit_irq(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_INTR_MASK =  DW_IIC_INTR_TX_EMPTY | DW_IIC_INTR_TX_OVER | DW_IIC_INTR_STOP_DET;
+    iic_base->IC_CLR_INTR;
+}
+
+static inline void dw_iic_slave_enable_transmit_irq(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_INTR_MASK = DW_IIC_INTR_RD_REQ | DW_IIC_INTR_STOP_DET;
+    iic_base->IC_CLR_INTR;
+}
+
+static inline void dw_iic_master_enable_receive_irq(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_INTR_MASK = DW_IIC_INTR_STOP_DET | DW_IIC_INTR_RX_FULL | DW_IIC_INTR_RX_OVER;
+    iic_base->IC_CLR_INTR;
+}
+
+static inline void dw_iic_slave_enable_receive_irq(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_INTR_MASK = DW_IIC_INTR_STOP_DET | DW_IIC_INTR_RX_FULL;
+    iic_base->IC_CLR_INTR;
+}
+
+static inline void dw_iic_clear_all_irq(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_CLR_INTR;
+    iic_base->IC_CLR_RX_UNDER;
+    iic_base->IC_CLR_RX_OVER;
+    iic_base->IC_CLR_TX_OVER;
+    iic_base->IC_CLR_RD_REQ;
+    iic_base->IC_CLR_TX_ABRT;
+    iic_base->IC_CLR_RX_DONE;
+    iic_base->IC_CLR_ACTIVITY;
+    iic_base->IC_CLR_STOP_DET;
+    iic_base->IC_CLR_START_DET;
+    iic_base->IC_CLR_GEN_CALL;
+}
+
+static inline void dw_iic_set_sda_hold_time(dw_iic_regs_t *iic_base, uint32_t val)
+{
+    iic_base->IC_SDA_HOLD = val;
+}
+
+static inline void dw_iic_flush_rxfifo(dw_iic_regs_t *iic_base)
+{
+    while (iic_base->IC_STATUS & DW_IIC_RXFIFO_NOT_EMPTY_STATE)
+        iic_base->IC_DATA_CMD;
+}
+
+static inline void dw_iic_set_slave_10bit_addr_mode(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_CON |= DW_IIC_CON_SLAVE_ADDR_MODE;
+}
+
+static inline void dw_iic_set_slave_7bit_addr_mode(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_CON &= ~DW_IIC_CON_SLAVE_ADDR_MODE;
+}
+
+static inline void dw_iic_set_master_10bit_addr_mode(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_TAR |= DW_IIC_TAR_MASTER_ADDR_MODE;
+}
+
+static inline void dw_iic_set_master_7bit_addr_mode(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_TAR &= ~DW_IIC_TAR_MASTER_ADDR_MODE;
+    iic_base->IC_CON &= ~DW_IIC_CON_MASTER_ADDR_MODE;
+}
+
+static inline void dw_iic_set_standard_scl_hcnt(dw_iic_regs_t *iic_base, uint32_t cnt)
+{
+    iic_base->IC_SS_SCL_HCNT = cnt;
+}
+
+static inline void dw_iic_set_standard_scl_lcnt(dw_iic_regs_t *iic_base, uint32_t cnt)
+{
+    iic_base->IC_SS_SCL_LCNT = cnt;
+}
+
+static inline void dw_iic_set_fast_scl_hcnt(dw_iic_regs_t *iic_base, uint32_t cnt)
+{
+    iic_base->IC_FS_SCL_HCNT = cnt;
+}
+
+static inline void dw_iic_set_fast_scl_lcnt(dw_iic_regs_t *iic_base, uint32_t cnt)
+{
+    iic_base->IC_FS_SCL_LCNT = cnt;
+}
+
+static inline void dw_iic_set_high_scl_hcnt(dw_iic_regs_t *iic_base, uint32_t cnt)
+{
+    iic_base->IC_HS_SCL_HCNT = cnt;
+}
+
+static inline void dw_iic_set_high_scl_lcnt(dw_iic_regs_t *iic_base, uint32_t cnt)
+{
+    iic_base->IC_HS_SCL_LCNT = cnt;
+}
+
+static inline void dw_iic_set_own_address(dw_iic_regs_t *iic_base, uint32_t address)
+{
+    iic_base->IC_SAR = address;
+}
+
+static inline void dw_iic_set_transmit_fifo_threshold(dw_iic_regs_t *iic_base, uint32_t level)
+{
+    iic_base->IC_TX_TL = level;
+}
+
+static inline void dw_iic_set_receive_fifo_threshold(dw_iic_regs_t *iic_base, uint32_t level)
+{
+    iic_base->IC_RX_TL = level - 1U;
+}
+
+static inline uint32_t dw_iic_get_transmit_fifo_num(dw_iic_regs_t *iic_base)
+{
+    return iic_base->IC_TXFLR;
+}
+
+static inline uint32_t dw_iic_get_receive_fifo_num(dw_iic_regs_t *iic_base)
+{
+    return iic_base->IC_RXFLR;
+}
+
+static inline void dw_iic_transmit_data(dw_iic_regs_t *iic_base, uint16_t data)
+{
+    iic_base->IC_DATA_CMD = data;
+}
+
+static inline uint8_t dw_iic_receive_data(dw_iic_regs_t *iic_base)
+{
+    return (uint8_t)iic_base->IC_DATA_CMD;
+}
+
+static inline void dw_iic_data_cmd(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_DATA_CMD = DW_IIC_DATA_CMD;
+}
+
+static inline void dw_iic_data_cmd_stop(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_DATA_CMD = DW_IIC_DATA_CMD | (1<<9);
+}
+
+static inline void dw_iic_fifo_rst(dw_iic_regs_t *iic_base, uint32_t en)
+{
+    //no this register
+    //iic_base->IC_FIFO_RST_EN = (en & DW_IIC_FIFO_RST_EN_Msk);
+}
+
+static inline void dw_iic_dma_transmit_enable(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_DMA_CR |= DW_IIC_DMA_CR_TDMAE;
+}
+
+static inline void dw_iic_dma_transmit_disable(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_DMA_CR &= ~DW_IIC_DMA_CR_TDMAE;
+}
+
+static inline void dw_iic_dma_receive_enable(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_DMA_CR |= DW_IIC_DMA_CR_RDMAE;
+}
+
+static inline void dw_iic_dma_receive_disable(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_DMA_CR &= ~DW_IIC_DMA_CR_RDMAE;
+}
+
+static inline void dw_iic_dma_transmit_level(dw_iic_regs_t *iic_base, uint8_t level)
+{
+    iic_base->IC_DMA_TDLR = ((uint32_t)level & DW_IIC_DMA_TDLR_Msk);
+}
+
+static inline void dw_iic_dma_receive_level(dw_iic_regs_t *iic_base, uint8_t level)
+{
+    iic_base->IC_DMA_RDLR = ((uint32_t)level & DW_IIC_DMA_RDLR_Msk);
+}
+
+static inline uint32_t dw_iic_get_raw_interrupt_state(dw_iic_regs_t *iic_base)
+{
+    return iic_base->IC_RAW_INTR_STAT;
+}
+
+static inline void dw_iic_disable_all_irq(dw_iic_regs_t *iic_base)
+{
+    iic_base->IC_INTR_MASK = 0U;
+}
+
+static inline uint32_t dw_iic_read_clear_intrbits(dw_iic_regs_t *iic_base)
+{
+    uint32_t  stat = 0U;
+
+    stat = iic_base->IC_INTR_STAT;
+
+    if (stat & DW_IIC_INTR_RX_UNDER)
+    {
+        iic_base->IC_CLR_RX_UNDER;
+    }
+
+    if (stat & DW_IIC_INTR_RX_OVER)
+    {
+        iic_base->IC_CLR_RX_OVER;
+    }
+
+    if (stat & DW_IIC_INTR_TX_OVER)
+    {
+        iic_base->IC_CLR_TX_OVER;
+    }
+
+    if (stat & DW_IIC_INTR_RD_REQ)
+    {
+        iic_base->IC_CLR_RD_REQ;
+    }
+
+    if (stat & DW_IIC_INTR_TX_ABRT)
+    {
+        iic_base->IC_TX_ABRT_SOURCE;
+    }
+
+    if (stat & DW_IIC_INTR_RX_DONE)
+    {
+        iic_base->IC_CLR_RX_DONE;
+    }
+
+    if (stat & DW_IIC_INTR_ACTIVITY)
+    {
+        iic_base->IC_CLR_ACTIVITY;
+    }
+
+    if (stat & DW_IIC_INTR_STOP_DET)
+    {
+        iic_base->IC_CLR_STOP_DET;
+    }
+
+    if (stat & DW_IIC_INTR_START_DET)
+    {
+        iic_base->IC_CLR_START_DET;
+    }
+
+    if (stat & DW_IIC_INTR_GEN_CALL)
+    {
+        iic_base->IC_CLR_GEN_CALL;
+    }
+
+    return stat;
+}
+
+static inline uint32_t dw_iic_get_intrrupt_state(dw_iic_regs_t *iic_base)
+{
+    return iic_base->IC_INTR_STAT;
+}
 
 int rt_hw_i2c_init(void);