11bd4fe43Sopenharmony_ci/*
21bd4fe43Sopenharmony_ci * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
31bd4fe43Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
41bd4fe43Sopenharmony_ci * you may not use this file except in compliance with the License.
51bd4fe43Sopenharmony_ci * You may obtain a copy of the License at
61bd4fe43Sopenharmony_ci *
71bd4fe43Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
81bd4fe43Sopenharmony_ci *
91bd4fe43Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
101bd4fe43Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
111bd4fe43Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121bd4fe43Sopenharmony_ci * See the License for the specific language governing permissions and
131bd4fe43Sopenharmony_ci * limitations under the License.
141bd4fe43Sopenharmony_ci */
151bd4fe43Sopenharmony_ci
161bd4fe43Sopenharmony_ci#include "i2c_hi35xx.h"
171bd4fe43Sopenharmony_ci#include "asm/platform.h"
181bd4fe43Sopenharmony_ci#include "los_hwi.h"
191bd4fe43Sopenharmony_ci#include "securec.h"
201bd4fe43Sopenharmony_ci#include "device_resource_if.h"
211bd4fe43Sopenharmony_ci#include "hdf_device_desc.h"
221bd4fe43Sopenharmony_ci#include "hdf_log.h"
231bd4fe43Sopenharmony_ci#include "i2c_core.h"
241bd4fe43Sopenharmony_ci#include "i2c_dev.h"
251bd4fe43Sopenharmony_ci#include "osal_io.h"
261bd4fe43Sopenharmony_ci#include "osal_mem.h"
271bd4fe43Sopenharmony_ci#include "osal_spinlock.h"
281bd4fe43Sopenharmony_ci#include "osal_time.h"
291bd4fe43Sopenharmony_ci#include "platform_dumper.h"
301bd4fe43Sopenharmony_ci
311bd4fe43Sopenharmony_ci#define HDF_LOG_TAG i2c_hi35xx
321bd4fe43Sopenharmony_ci#define USER_VFS_SUPPORT
331bd4fe43Sopenharmony_ci
341bd4fe43Sopenharmony_ci#define HI35XX_I2C_DELAY      50
351bd4fe43Sopenharmony_ci#define I2C_FREQ_NORMAL      100000
361bd4fe43Sopenharmony_ci#define HI35XX_SCL_HIGH_CNT   36
371bd4fe43Sopenharmony_ci#define HI35XX_SCL_LOW_CNT    64
381bd4fe43Sopenharmony_ci#define HI35XX_SCL_FULL_CNT   100
391bd4fe43Sopenharmony_ci#define HI35XX_REG_SIZE       4
401bd4fe43Sopenharmony_ci#define HI35XX_I2C_R_LOOP_ADJ 2
411bd4fe43Sopenharmony_ci#define HI35XX_I2C_RESCUE_TIMES 9
421bd4fe43Sopenharmony_ci#define HI35XX_I2C_RESCUE_DELAY 10
431bd4fe43Sopenharmony_ci
441bd4fe43Sopenharmony_ci#define I2C_DUMPER_NAME_LEN     64
451bd4fe43Sopenharmony_ci#define I2C_DUMPER_NAME_PREFIX  "i2c_dumper_"
461bd4fe43Sopenharmony_ci
471bd4fe43Sopenharmony_cistruct Hi35xxI2cCntlr {
481bd4fe43Sopenharmony_ci    struct I2cCntlr cntlr;
491bd4fe43Sopenharmony_ci    OsalSpinlock spin;
501bd4fe43Sopenharmony_ci    uint32_t irqSave;
511bd4fe43Sopenharmony_ci    volatile unsigned char  *regBase;
521bd4fe43Sopenharmony_ci    uint16_t regSize;
531bd4fe43Sopenharmony_ci    int16_t bus;
541bd4fe43Sopenharmony_ci    uint32_t clk;
551bd4fe43Sopenharmony_ci    uint32_t freq;
561bd4fe43Sopenharmony_ci    uint32_t irq;
571bd4fe43Sopenharmony_ci    uint32_t regBasePhy;
581bd4fe43Sopenharmony_ci    struct PlatformDumper *dumper;
591bd4fe43Sopenharmony_ci    char *dumperName;
601bd4fe43Sopenharmony_ci};
611bd4fe43Sopenharmony_ci
621bd4fe43Sopenharmony_cistruct Hi35xxTransferData {
631bd4fe43Sopenharmony_ci    struct I2cMsg *msgs;
641bd4fe43Sopenharmony_ci    int16_t index;
651bd4fe43Sopenharmony_ci    int16_t count;
661bd4fe43Sopenharmony_ci};
671bd4fe43Sopenharmony_ci
681bd4fe43Sopenharmony_ci#define WRITE_REG_BIT(value, offset, addr) \
691bd4fe43Sopenharmony_ci    do {                                   \
701bd4fe43Sopenharmony_ci        unsigned long t, mask;             \
711bd4fe43Sopenharmony_ci        mask = 1 << (offset);              \
721bd4fe43Sopenharmony_ci        t = OSAL_READL(addr);              \
731bd4fe43Sopenharmony_ci        t &= ~mask;                        \
741bd4fe43Sopenharmony_ci        t |= ((value) << (offset)) & mask; \
751bd4fe43Sopenharmony_ci        OSAL_WRITEL(t, (addr));            \
761bd4fe43Sopenharmony_ci    } while (0)
771bd4fe43Sopenharmony_ci
781bd4fe43Sopenharmony_ci#define REG_CRG_I2C           (CRG_REG_BASE + 0x01b8)
791bd4fe43Sopenharmony_ci#define I2C_CRG_RST_OFFSET    19
801bd4fe43Sopenharmony_ci#define I2C_CRG_CLK_OFFSET    11
811bd4fe43Sopenharmony_ci
821bd4fe43Sopenharmony_cistatic int32_t I2cDumperAddDatas(const struct Hi35xxI2cCntlr *hi35xx)
831bd4fe43Sopenharmony_ci{
841bd4fe43Sopenharmony_ci    struct PlatformDumperData datas[] = {
851bd4fe43Sopenharmony_ci        {"HI35XX_I2Cx_GLB", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_GLB)},
861bd4fe43Sopenharmony_ci        {"HI35XX_I2Cx_SCL_H", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_SCL_H)},
871bd4fe43Sopenharmony_ci        {"HI35XX_I2Cx_SCL_L", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_SCL_L)},
881bd4fe43Sopenharmony_ci        {"HI35XX_I2Cx_DATA1", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_DATA1)},
891bd4fe43Sopenharmony_ci        {"HI35XX_I2C_TXF", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_TXF)},
901bd4fe43Sopenharmony_ci        {"HI35XX_I2C_RXF", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_RXF)},
911bd4fe43Sopenharmony_ci        {"HI35XX_I2C_CTRL2", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_CTRL2)},
921bd4fe43Sopenharmony_ci        {"HI35XX_I2C_STAT", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_STAT)},
931bd4fe43Sopenharmony_ci        {"HI35XX_I2C_INTR_RAW", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_INTR_RAW)},
941bd4fe43Sopenharmony_ci        {"HI35XX_I2C_INTR_EN", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_INTR_EN)},
951bd4fe43Sopenharmony_ci        {"HI35XX_I2C_INTR_STAT", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_INTR_STAT)},
961bd4fe43Sopenharmony_ci    };
971bd4fe43Sopenharmony_ci
981bd4fe43Sopenharmony_ci    if (hi35xx->dumper == NULL) {
991bd4fe43Sopenharmony_ci        HDF_LOGE("%s: dumper is NULL", __func__);
1001bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
1011bd4fe43Sopenharmony_ci    }
1021bd4fe43Sopenharmony_ci    return PlatformDumperAddDatas(hi35xx->dumper, datas, sizeof(datas) / sizeof(struct PlatformDumperData));
1031bd4fe43Sopenharmony_ci}
1041bd4fe43Sopenharmony_ci
1051bd4fe43Sopenharmony_cistatic int32_t I2cDumperCreate(struct Hi35xxI2cCntlr *hi35xx)
1061bd4fe43Sopenharmony_ci{
1071bd4fe43Sopenharmony_ci    struct PlatformDumper *dumper = NULL;
1081bd4fe43Sopenharmony_ci    char *name = NULL;
1091bd4fe43Sopenharmony_ci
1101bd4fe43Sopenharmony_ci    name = (char *)OsalMemCalloc(I2C_DUMPER_NAME_LEN);
1111bd4fe43Sopenharmony_ci    if (name == NULL) {
1121bd4fe43Sopenharmony_ci        HDF_LOGE("%s: alloc name fail", __func__);
1131bd4fe43Sopenharmony_ci        return HDF_ERR_MALLOC_FAIL;
1141bd4fe43Sopenharmony_ci    }
1151bd4fe43Sopenharmony_ci
1161bd4fe43Sopenharmony_ci    if (snprintf_s(name, I2C_DUMPER_NAME_LEN, I2C_DUMPER_NAME_LEN - 1, "%s%hd",
1171bd4fe43Sopenharmony_ci        I2C_DUMPER_NAME_PREFIX, hi35xx->bus) < 0) {
1181bd4fe43Sopenharmony_ci        HDF_LOGE("%s: snprintf_s name fail!", __func__);
1191bd4fe43Sopenharmony_ci        OsalMemFree(name);
1201bd4fe43Sopenharmony_ci        return HDF_ERR_IO;
1211bd4fe43Sopenharmony_ci    }
1221bd4fe43Sopenharmony_ci    dumper = PlatformDumperCreate(name);
1231bd4fe43Sopenharmony_ci    if (dumper == NULL) {
1241bd4fe43Sopenharmony_ci        HDF_LOGE("%s: create dumper for %s fail!", __func__, name);
1251bd4fe43Sopenharmony_ci        OsalMemFree(name);
1261bd4fe43Sopenharmony_ci        return HDF_ERR_IO;
1271bd4fe43Sopenharmony_ci    }
1281bd4fe43Sopenharmony_ci
1291bd4fe43Sopenharmony_ci    hi35xx->dumper = dumper;
1301bd4fe43Sopenharmony_ci    hi35xx->dumperName = name;
1311bd4fe43Sopenharmony_ci
1321bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
1331bd4fe43Sopenharmony_ci}
1341bd4fe43Sopenharmony_ci
1351bd4fe43Sopenharmony_cistatic inline void I2cDumperDestroy(struct Hi35xxI2cCntlr *hi35xx)
1361bd4fe43Sopenharmony_ci{
1371bd4fe43Sopenharmony_ci    PlatformDumperDestroy(hi35xx->dumper);
1381bd4fe43Sopenharmony_ci    OsalMemFree(hi35xx->dumperName);
1391bd4fe43Sopenharmony_ci}
1401bd4fe43Sopenharmony_ci
1411bd4fe43Sopenharmony_cistatic void I2cDumperDump(const struct Hi35xxI2cCntlr *hi35xx, const char *executor, int srcLine)
1421bd4fe43Sopenharmony_ci{
1431bd4fe43Sopenharmony_ci    static int line = 0;
1441bd4fe43Sopenharmony_ci    struct PlatformDumperData header = {executor, PLATFORM_DUMPER_INT32, &line};
1451bd4fe43Sopenharmony_ci    int32_t ret;
1461bd4fe43Sopenharmony_ci
1471bd4fe43Sopenharmony_ci    line = srcLine;
1481bd4fe43Sopenharmony_ci    ret = PlatformDumperAddData(hi35xx->dumper, &header);
1491bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
1501bd4fe43Sopenharmony_ci        HDF_LOGE("%s: add header fail", __func__);
1511bd4fe43Sopenharmony_ci        return;
1521bd4fe43Sopenharmony_ci    }
1531bd4fe43Sopenharmony_ci    ret = I2cDumperAddDatas(hi35xx);
1541bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
1551bd4fe43Sopenharmony_ci        return;
1561bd4fe43Sopenharmony_ci    }
1571bd4fe43Sopenharmony_ci    (void)PlatformDumperDump(hi35xx->dumper);
1581bd4fe43Sopenharmony_ci    (void)PlatformDumperClearDatas(hi35xx->dumper);
1591bd4fe43Sopenharmony_ci}
1601bd4fe43Sopenharmony_ci
1611bd4fe43Sopenharmony_cistatic inline void Hi35xxI2cHwInitCfg(struct Hi35xxI2cCntlr *hi35xx)
1621bd4fe43Sopenharmony_ci{
1631bd4fe43Sopenharmony_ci    unsigned long busId = (unsigned long)hi35xx->bus;
1641bd4fe43Sopenharmony_ci
1651bd4fe43Sopenharmony_ci    WRITE_REG_BIT(1, I2C_CRG_CLK_OFFSET + busId, REG_CRG_I2C);
1661bd4fe43Sopenharmony_ci    WRITE_REG_BIT(0, I2C_CRG_RST_OFFSET + busId, REG_CRG_I2C);
1671bd4fe43Sopenharmony_ci}
1681bd4fe43Sopenharmony_ci
1691bd4fe43Sopenharmony_cistatic inline void Hi35xxI2cEnable(const struct Hi35xxI2cCntlr *hi35xx)
1701bd4fe43Sopenharmony_ci{
1711bd4fe43Sopenharmony_ci    unsigned int val;
1721bd4fe43Sopenharmony_ci
1731bd4fe43Sopenharmony_ci    val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_GLB);
1741bd4fe43Sopenharmony_ci    val |= GLB_EN_MASK;
1751bd4fe43Sopenharmony_ci    OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_GLB);
1761bd4fe43Sopenharmony_ci}
1771bd4fe43Sopenharmony_ci
1781bd4fe43Sopenharmony_cistatic inline void Hi35xxI2cDisable(const struct Hi35xxI2cCntlr *hi35xx)
1791bd4fe43Sopenharmony_ci{
1801bd4fe43Sopenharmony_ci    unsigned int val;
1811bd4fe43Sopenharmony_ci
1821bd4fe43Sopenharmony_ci    val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_GLB);
1831bd4fe43Sopenharmony_ci    val &= ~GLB_EN_MASK;
1841bd4fe43Sopenharmony_ci    OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_GLB);
1851bd4fe43Sopenharmony_ci}
1861bd4fe43Sopenharmony_ci
1871bd4fe43Sopenharmony_cistatic inline void Hi35xxI2cDisableIrq(const struct Hi35xxI2cCntlr *hi35xx, unsigned int flag)
1881bd4fe43Sopenharmony_ci{
1891bd4fe43Sopenharmony_ci    unsigned int val;
1901bd4fe43Sopenharmony_ci
1911bd4fe43Sopenharmony_ci    val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_INTR_EN);
1921bd4fe43Sopenharmony_ci    val &= ~flag;
1931bd4fe43Sopenharmony_ci    OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_INTR_EN);
1941bd4fe43Sopenharmony_ci}
1951bd4fe43Sopenharmony_ci
1961bd4fe43Sopenharmony_cistatic inline void Hi35xxI2cCfgIrq(const struct Hi35xxI2cCntlr *hi35xx, unsigned int flag)
1971bd4fe43Sopenharmony_ci{
1981bd4fe43Sopenharmony_ci    OSAL_WRITEL(flag, hi35xx->regBase + HI35XX_I2C_INTR_EN);
1991bd4fe43Sopenharmony_ci}
2001bd4fe43Sopenharmony_ci
2011bd4fe43Sopenharmony_cistatic inline void Hi35xxI2cClrIrq(const struct Hi35xxI2cCntlr *hi35xx)
2021bd4fe43Sopenharmony_ci{
2031bd4fe43Sopenharmony_ci    (void)OSAL_READL(hi35xx->regBase + HI35XX_I2C_INTR_STAT);
2041bd4fe43Sopenharmony_ci    OSAL_WRITEL(INTR_ALL_MASK, hi35xx->regBase + HI35XX_I2C_INTR_RAW);
2051bd4fe43Sopenharmony_ci}
2061bd4fe43Sopenharmony_ci
2071bd4fe43Sopenharmony_cistatic void Hi35xxI2cSetFreq(struct Hi35xxI2cCntlr *hi35xx)
2081bd4fe43Sopenharmony_ci{
2091bd4fe43Sopenharmony_ci    unsigned int maxFreq;
2101bd4fe43Sopenharmony_ci    unsigned int freq;
2111bd4fe43Sopenharmony_ci    unsigned int clkRate;
2121bd4fe43Sopenharmony_ci    unsigned int val;
2131bd4fe43Sopenharmony_ci
2141bd4fe43Sopenharmony_ci    freq = hi35xx->freq;
2151bd4fe43Sopenharmony_ci    clkRate = hi35xx->clk;
2161bd4fe43Sopenharmony_ci    maxFreq = clkRate >> 1;
2171bd4fe43Sopenharmony_ci
2181bd4fe43Sopenharmony_ci    if (freq > maxFreq) {
2191bd4fe43Sopenharmony_ci        hi35xx->freq = maxFreq;
2201bd4fe43Sopenharmony_ci        freq = hi35xx->freq;
2211bd4fe43Sopenharmony_ci    }
2221bd4fe43Sopenharmony_ci    if (freq <= I2C_FREQ_NORMAL) {
2231bd4fe43Sopenharmony_ci        val = clkRate / (freq << 1);
2241bd4fe43Sopenharmony_ci        OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_SCL_H);
2251bd4fe43Sopenharmony_ci        OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_SCL_L);
2261bd4fe43Sopenharmony_ci    } else {
2271bd4fe43Sopenharmony_ci        val = (clkRate * HI35XX_SCL_HIGH_CNT) / (freq * HI35XX_SCL_FULL_CNT);
2281bd4fe43Sopenharmony_ci        OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_SCL_H);
2291bd4fe43Sopenharmony_ci        val = (clkRate * HI35XX_SCL_LOW_CNT) / (freq * HI35XX_SCL_FULL_CNT);
2301bd4fe43Sopenharmony_ci        OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_SCL_L);
2311bd4fe43Sopenharmony_ci    }
2321bd4fe43Sopenharmony_ci    val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_GLB);
2331bd4fe43Sopenharmony_ci    val &= ~GLB_SDA_HOLD_MASK;
2341bd4fe43Sopenharmony_ci    val |= ((0xa << GLB_SDA_HOLD_SHIFT) & GLB_SDA_HOLD_MASK);
2351bd4fe43Sopenharmony_ci    OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_GLB);
2361bd4fe43Sopenharmony_ci}
2371bd4fe43Sopenharmony_ci
2381bd4fe43Sopenharmony_cistatic inline void Hi35xxI2cSetWater(const struct Hi35xxI2cCntlr *hi35xx)
2391bd4fe43Sopenharmony_ci{
2401bd4fe43Sopenharmony_ci    OSAL_WRITEL(I2C_TXF_WATER, hi35xx->regBase + HI35XX_I2C_TX_WATER);
2411bd4fe43Sopenharmony_ci    OSAL_WRITEL(I2C_RXF_WATER, hi35xx->regBase + HI35XX_I2C_RX_WATER);
2421bd4fe43Sopenharmony_ci}
2431bd4fe43Sopenharmony_ci
2441bd4fe43Sopenharmony_ci/*
2451bd4fe43Sopenharmony_ci * config i2c device addr
2461bd4fe43Sopenharmony_ci */
2471bd4fe43Sopenharmony_cistatic void Hi35xxI2cSetAddr(const struct Hi35xxI2cCntlr *hi35xx, const struct Hi35xxTransferData *td)
2481bd4fe43Sopenharmony_ci{
2491bd4fe43Sopenharmony_ci    struct I2cMsg *msg = &td->msgs[td->index];
2501bd4fe43Sopenharmony_ci    unsigned int addr = msg->addr;
2511bd4fe43Sopenharmony_ci
2521bd4fe43Sopenharmony_ci    if (msg->flags & I2C_FLAG_ADDR_10BIT) {
2531bd4fe43Sopenharmony_ci        /* First byte is 11110XX0 where XX is upper 2 bits */
2541bd4fe43Sopenharmony_ci        addr = ((msg->addr & 0x300) << 1) | 0xf000;
2551bd4fe43Sopenharmony_ci        if (msg->flags & I2C_FLAG_READ) {
2561bd4fe43Sopenharmony_ci            addr |= 0x100;
2571bd4fe43Sopenharmony_ci        }
2581bd4fe43Sopenharmony_ci        /* Second byte is the remaining 8 bits */
2591bd4fe43Sopenharmony_ci        addr |= msg->addr & 0xff;
2601bd4fe43Sopenharmony_ci    } else {
2611bd4fe43Sopenharmony_ci        addr = (msg->addr & 0x7f) << 1;
2621bd4fe43Sopenharmony_ci        if (msg->flags & I2C_FLAG_READ) {
2631bd4fe43Sopenharmony_ci            addr |= 1;
2641bd4fe43Sopenharmony_ci        }
2651bd4fe43Sopenharmony_ci    }
2661bd4fe43Sopenharmony_ci
2671bd4fe43Sopenharmony_ci    OSAL_WRITEL(addr, hi35xx->regBase + HI35XX_I2C_DATA1);
2681bd4fe43Sopenharmony_ci}
2691bd4fe43Sopenharmony_ci
2701bd4fe43Sopenharmony_cistatic inline void Hi35xxI2cCmdregSet(const struct Hi35xxI2cCntlr *hi35xx, unsigned int cmd, unsigned int *offset)
2711bd4fe43Sopenharmony_ci{
2721bd4fe43Sopenharmony_ci    PLAT_LOGV("%s: offset=0x%x, cmd=0x%x...", __func__, *offset * HI35XX_REG_SIZE, cmd);
2731bd4fe43Sopenharmony_ci    OSAL_WRITEL(cmd, hi35xx->regBase + HI35XX_I2C_CMD_BASE + *offset * HI35XX_REG_SIZE);
2741bd4fe43Sopenharmony_ci    (*offset)++;
2751bd4fe43Sopenharmony_ci}
2761bd4fe43Sopenharmony_ci
2771bd4fe43Sopenharmony_cistatic void Hi35xxI2cCfgCmd(const struct Hi35xxI2cCntlr *hi35xx, const struct Hi35xxTransferData *td)
2781bd4fe43Sopenharmony_ci{
2791bd4fe43Sopenharmony_ci    unsigned int offset = 0;
2801bd4fe43Sopenharmony_ci    struct I2cMsg *msg = &td->msgs[td->index];
2811bd4fe43Sopenharmony_ci
2821bd4fe43Sopenharmony_ci    Hi35xxI2cCmdregSet(hi35xx, (td->index == 0) ? CMD_TX_S : CMD_TX_RS, &offset);
2831bd4fe43Sopenharmony_ci
2841bd4fe43Sopenharmony_ci    if (msg->flags & I2C_FLAG_ADDR_10BIT) {
2851bd4fe43Sopenharmony_ci        Hi35xxI2cCmdregSet(hi35xx, CMD_TX_D1_2, &offset);
2861bd4fe43Sopenharmony_ci        if (td->index == 0) {
2871bd4fe43Sopenharmony_ci            Hi35xxI2cCmdregSet(hi35xx, CMD_TX_D1_1, &offset);
2881bd4fe43Sopenharmony_ci        }
2891bd4fe43Sopenharmony_ci    } else {
2901bd4fe43Sopenharmony_ci        Hi35xxI2cCmdregSet(hi35xx, CMD_TX_D1_1, &offset);
2911bd4fe43Sopenharmony_ci    }
2921bd4fe43Sopenharmony_ci
2931bd4fe43Sopenharmony_ci    Hi35xxI2cCmdregSet(hi35xx, (msg->flags & I2C_FLAG_IGNORE_NO_ACK) ? CMD_IGN_ACK : CMD_RX_ACK, &offset);
2941bd4fe43Sopenharmony_ci    if (msg->flags & I2C_FLAG_READ) {
2951bd4fe43Sopenharmony_ci        if (msg->len > 1) {
2961bd4fe43Sopenharmony_ci            OSAL_WRITEL(offset, hi35xx->regBase + HI35XX_I2C_DST1);
2971bd4fe43Sopenharmony_ci            OSAL_WRITEL(msg->len - HI35XX_I2C_R_LOOP_ADJ, hi35xx->regBase + HI35XX_I2C_LOOP1);
2981bd4fe43Sopenharmony_ci            Hi35xxI2cCmdregSet(hi35xx, CMD_RX_FIFO, &offset);
2991bd4fe43Sopenharmony_ci            Hi35xxI2cCmdregSet(hi35xx, CMD_TX_ACK, &offset);
3001bd4fe43Sopenharmony_ci            Hi35xxI2cCmdregSet(hi35xx, CMD_JMP1, &offset);
3011bd4fe43Sopenharmony_ci        }
3021bd4fe43Sopenharmony_ci        Hi35xxI2cCmdregSet(hi35xx, CMD_RX_FIFO, &offset);
3031bd4fe43Sopenharmony_ci        Hi35xxI2cCmdregSet(hi35xx, CMD_TX_NACK, &offset);
3041bd4fe43Sopenharmony_ci    } else {
3051bd4fe43Sopenharmony_ci        OSAL_WRITEL(offset, hi35xx->regBase + HI35XX_I2C_DST1);
3061bd4fe43Sopenharmony_ci        OSAL_WRITEL(msg->len - 1, hi35xx->regBase + HI35XX_I2C_LOOP1);
3071bd4fe43Sopenharmony_ci        Hi35xxI2cCmdregSet(hi35xx, CMD_UP_TXF, &offset);
3081bd4fe43Sopenharmony_ci        Hi35xxI2cCmdregSet(hi35xx, CMD_TX_FIFO, &offset);
3091bd4fe43Sopenharmony_ci
3101bd4fe43Sopenharmony_ci        Hi35xxI2cCmdregSet(hi35xx, (msg->flags & I2C_FLAG_IGNORE_NO_ACK) ? CMD_IGN_ACK : CMD_RX_ACK, &offset);
3111bd4fe43Sopenharmony_ci        Hi35xxI2cCmdregSet(hi35xx, CMD_JMP1, &offset);
3121bd4fe43Sopenharmony_ci    }
3131bd4fe43Sopenharmony_ci
3141bd4fe43Sopenharmony_ci    if ((td->index == (td->count - 1)) || (msg->flags & I2C_FLAG_STOP)) {
3151bd4fe43Sopenharmony_ci        PLAT_LOGV("%s: TX stop, idx:%hd, count:%hd, flags:%u", __func__,
3161bd4fe43Sopenharmony_ci            td->index, td->count, msg->flags);
3171bd4fe43Sopenharmony_ci        Hi35xxI2cCmdregSet(hi35xx, CMD_TX_P, &offset);
3181bd4fe43Sopenharmony_ci    }
3191bd4fe43Sopenharmony_ci
3201bd4fe43Sopenharmony_ci    Hi35xxI2cCmdregSet(hi35xx, CMD_EXIT, &offset);
3211bd4fe43Sopenharmony_ci}
3221bd4fe43Sopenharmony_ci
3231bd4fe43Sopenharmony_ci/*
3241bd4fe43Sopenharmony_ci * Start command sequence
3251bd4fe43Sopenharmony_ci */
3261bd4fe43Sopenharmony_cistatic inline void Hi35xxI2cStartCmd(const struct Hi35xxI2cCntlr *hi35xx)
3271bd4fe43Sopenharmony_ci{
3281bd4fe43Sopenharmony_ci    unsigned int val;
3291bd4fe43Sopenharmony_ci
3301bd4fe43Sopenharmony_ci    val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_CTRL1);
3311bd4fe43Sopenharmony_ci    val |= CTRL1_CMD_START_MASK;
3321bd4fe43Sopenharmony_ci    OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_CTRL1);
3331bd4fe43Sopenharmony_ci}
3341bd4fe43Sopenharmony_ci
3351bd4fe43Sopenharmony_cistatic void Hi35xxI2cRescure(const struct Hi35xxI2cCntlr *hi35xx)
3361bd4fe43Sopenharmony_ci{
3371bd4fe43Sopenharmony_ci    int index;
3381bd4fe43Sopenharmony_ci    unsigned int val;
3391bd4fe43Sopenharmony_ci    unsigned int timeCnt;
3401bd4fe43Sopenharmony_ci
3411bd4fe43Sopenharmony_ci    Hi35xxI2cDisable(hi35xx);
3421bd4fe43Sopenharmony_ci    Hi35xxI2cCfgIrq(hi35xx, 0);
3431bd4fe43Sopenharmony_ci    Hi35xxI2cClrIrq(hi35xx);
3441bd4fe43Sopenharmony_ci
3451bd4fe43Sopenharmony_ci    val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT);
3461bd4fe43Sopenharmony_ci    OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_CTRL2);
3471bd4fe43Sopenharmony_ci
3481bd4fe43Sopenharmony_ci    timeCnt = 0;
3491bd4fe43Sopenharmony_ci    do {
3501bd4fe43Sopenharmony_ci        for (index = 0; index < HI35XX_I2C_RESCUE_TIMES; index++) {
3511bd4fe43Sopenharmony_ci            val = (0x1 << GPIO_MODE_SHIFT) | 0x1;
3521bd4fe43Sopenharmony_ci            OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_CTRL2);
3531bd4fe43Sopenharmony_ci
3541bd4fe43Sopenharmony_ci            OsalUDelay(HI35XX_I2C_RESCUE_DELAY);
3551bd4fe43Sopenharmony_ci
3561bd4fe43Sopenharmony_ci            val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT);
3571bd4fe43Sopenharmony_ci            OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_CTRL2);
3581bd4fe43Sopenharmony_ci
3591bd4fe43Sopenharmony_ci            OsalUDelay(HI35XX_I2C_RESCUE_DELAY);
3601bd4fe43Sopenharmony_ci        }
3611bd4fe43Sopenharmony_ci
3621bd4fe43Sopenharmony_ci        timeCnt++;
3631bd4fe43Sopenharmony_ci        if (timeCnt > I2C_WAIT_TIMEOUT) {
3641bd4fe43Sopenharmony_ci            HDF_LOGE("%s: wait Timeout!", __func__);
3651bd4fe43Sopenharmony_ci            goto __DISABLE_RESCURE;
3661bd4fe43Sopenharmony_ci        }
3671bd4fe43Sopenharmony_ci
3681bd4fe43Sopenharmony_ci        val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_CTRL2);
3691bd4fe43Sopenharmony_ci    } while (!(val & (0x1 << CHECK_SDA_IN_SHIFT)));
3701bd4fe43Sopenharmony_ci
3711bd4fe43Sopenharmony_ci    val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT);
3721bd4fe43Sopenharmony_ci    OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_CTRL2);
3731bd4fe43Sopenharmony_ci
3741bd4fe43Sopenharmony_ci    val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT);
3751bd4fe43Sopenharmony_ci    OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_CTRL2);
3761bd4fe43Sopenharmony_ci
3771bd4fe43Sopenharmony_ci    OsalUDelay(HI35XX_I2C_RESCUE_DELAY);
3781bd4fe43Sopenharmony_ci
3791bd4fe43Sopenharmony_ci    val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT);
3801bd4fe43Sopenharmony_ci    OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_CTRL2);
3811bd4fe43Sopenharmony_ci
3821bd4fe43Sopenharmony_ci__DISABLE_RESCURE:
3831bd4fe43Sopenharmony_ci    val = (0x1 << FORCE_SCL_OEN_SHIFT) | 0x1;
3841bd4fe43Sopenharmony_ci    OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_CTRL2);
3851bd4fe43Sopenharmony_ci    HDF_LOGW("%s: done!", __func__);
3861bd4fe43Sopenharmony_ci}
3871bd4fe43Sopenharmony_ci
3881bd4fe43Sopenharmony_cistatic int Hi35xxI2cWaitRxNoempty(const struct Hi35xxI2cCntlr *hi35xx)
3891bd4fe43Sopenharmony_ci{
3901bd4fe43Sopenharmony_ci    unsigned int timeCnt = 0;
3911bd4fe43Sopenharmony_ci    unsigned int val;
3921bd4fe43Sopenharmony_ci
3931bd4fe43Sopenharmony_ci    do {
3941bd4fe43Sopenharmony_ci        val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_STAT);
3951bd4fe43Sopenharmony_ci        if (val & STAT_RXF_NOE_MASK) {
3961bd4fe43Sopenharmony_ci            return 0;
3971bd4fe43Sopenharmony_ci        }
3981bd4fe43Sopenharmony_ci        OsalUDelay(HI35XX_I2C_DELAY);
3991bd4fe43Sopenharmony_ci    } while (timeCnt++ < I2C_TIMEOUT_COUNT);
4001bd4fe43Sopenharmony_ci
4011bd4fe43Sopenharmony_ci    Hi35xxI2cRescure(hi35xx);
4021bd4fe43Sopenharmony_ci    HDF_LOGE("%s:wait rx no empty timeout, RIS:0x%x, SR: 0x%x",
4031bd4fe43Sopenharmony_ci        __func__, OSAL_READL(hi35xx->regBase + HI35XX_I2C_INTR_RAW), val);
4041bd4fe43Sopenharmony_ci    I2cDumperDump(hi35xx, __func__, __LINE__);
4051bd4fe43Sopenharmony_ci    return HDF_ERR_IO;
4061bd4fe43Sopenharmony_ci}
4071bd4fe43Sopenharmony_ci
4081bd4fe43Sopenharmony_cistatic int Hi35xxI2cWaitTxNofull(const struct Hi35xxI2cCntlr *hi35xx)
4091bd4fe43Sopenharmony_ci{
4101bd4fe43Sopenharmony_ci    unsigned int timeCnt = 0;
4111bd4fe43Sopenharmony_ci    unsigned int val;
4121bd4fe43Sopenharmony_ci
4131bd4fe43Sopenharmony_ci    do {
4141bd4fe43Sopenharmony_ci        val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_STAT);
4151bd4fe43Sopenharmony_ci        if (val & STAT_TXF_NOF_MASK) {
4161bd4fe43Sopenharmony_ci            return 0;
4171bd4fe43Sopenharmony_ci        }
4181bd4fe43Sopenharmony_ci        OsalUDelay(HI35XX_I2C_DELAY);
4191bd4fe43Sopenharmony_ci    } while (timeCnt++ < I2C_TIMEOUT_COUNT);
4201bd4fe43Sopenharmony_ci
4211bd4fe43Sopenharmony_ci    Hi35xxI2cRescure(hi35xx);
4221bd4fe43Sopenharmony_ci    HDF_LOGE("%s: wait rx no empty timeout, RIS: 0x%x, SR: 0x%x",
4231bd4fe43Sopenharmony_ci        __func__, OSAL_READL(hi35xx->regBase + HI35XX_I2C_INTR_RAW), val);
4241bd4fe43Sopenharmony_ci    I2cDumperDump(hi35xx, __func__, __LINE__);
4251bd4fe43Sopenharmony_ci    return HDF_ERR_IO;
4261bd4fe43Sopenharmony_ci}
4271bd4fe43Sopenharmony_ci
4281bd4fe43Sopenharmony_cistatic int32_t Hi35xxI2cWaitIdle(const struct Hi35xxI2cCntlr *hi35xx)
4291bd4fe43Sopenharmony_ci{
4301bd4fe43Sopenharmony_ci    unsigned int timeCnt = 0;
4311bd4fe43Sopenharmony_ci    unsigned int val;
4321bd4fe43Sopenharmony_ci
4331bd4fe43Sopenharmony_ci    do {
4341bd4fe43Sopenharmony_ci        val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_INTR_RAW);
4351bd4fe43Sopenharmony_ci        if (val & (INTR_ABORT_MASK)) {
4361bd4fe43Sopenharmony_ci            HDF_LOGE("%s: wait idle abort!, RIS: 0x%x", __func__, val);
4371bd4fe43Sopenharmony_ci            return HDF_ERR_IO;
4381bd4fe43Sopenharmony_ci        }
4391bd4fe43Sopenharmony_ci        if (val & INTR_CMD_DONE_MASK) {
4401bd4fe43Sopenharmony_ci            return 0;
4411bd4fe43Sopenharmony_ci        }
4421bd4fe43Sopenharmony_ci        OsalUDelay(HI35XX_I2C_DELAY);
4431bd4fe43Sopenharmony_ci    } while (timeCnt++ < I2C_WAIT_TIMEOUT);
4441bd4fe43Sopenharmony_ci
4451bd4fe43Sopenharmony_ci    Hi35xxI2cRescure(hi35xx);
4461bd4fe43Sopenharmony_ci    HDF_LOGE("%s: wait idle timeout, RIS: 0x%x, SR: 0x%x",
4471bd4fe43Sopenharmony_ci        __func__, val, OSAL_READL(hi35xx->regBase + HI35XX_I2C_STAT));
4481bd4fe43Sopenharmony_ci    I2cDumperDump(hi35xx, __func__, __LINE__);
4491bd4fe43Sopenharmony_ci    return HDF_ERR_IO;
4501bd4fe43Sopenharmony_ci}
4511bd4fe43Sopenharmony_ci
4521bd4fe43Sopenharmony_cistatic int HdfCopyFromUser(void *to, const void *from, unsigned long n)
4531bd4fe43Sopenharmony_ci{
4541bd4fe43Sopenharmony_ci    int ret;
4551bd4fe43Sopenharmony_ci    ret = LOS_CopyToKernel(to, n, from, n);
4561bd4fe43Sopenharmony_ci    if (ret != LOS_OK) {
4571bd4fe43Sopenharmony_ci        HDF_LOGE("%s: copy from kernel fail:%d", __func__, ret);
4581bd4fe43Sopenharmony_ci        return HDF_FAILURE;
4591bd4fe43Sopenharmony_ci    }
4601bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
4611bd4fe43Sopenharmony_ci}
4621bd4fe43Sopenharmony_ci
4631bd4fe43Sopenharmony_cistatic int HdfCopyToUser(void *to, const void *from, unsigned long n)
4641bd4fe43Sopenharmony_ci{
4651bd4fe43Sopenharmony_ci    int ret;
4661bd4fe43Sopenharmony_ci    ret = LOS_CopyFromKernel(to, n, from, n);
4671bd4fe43Sopenharmony_ci    if (ret != LOS_OK) {
4681bd4fe43Sopenharmony_ci        HDF_LOGE("%s: copy from kernel fail:%d", __func__, ret);
4691bd4fe43Sopenharmony_ci        return HDF_FAILURE;
4701bd4fe43Sopenharmony_ci    }
4711bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
4721bd4fe43Sopenharmony_ci}
4731bd4fe43Sopenharmony_ci
4741bd4fe43Sopenharmony_cistatic int32_t Hi35xxI2cXferOneMsgPolling(const struct Hi35xxI2cCntlr *hi35xx, const struct Hi35xxTransferData *td)
4751bd4fe43Sopenharmony_ci{
4761bd4fe43Sopenharmony_ci    int32_t status;
4771bd4fe43Sopenharmony_ci    uint16_t bufIdx = 0;
4781bd4fe43Sopenharmony_ci    uint8_t val;
4791bd4fe43Sopenharmony_ci    struct I2cMsg *msg = &td->msgs[td->index];
4801bd4fe43Sopenharmony_ci
4811bd4fe43Sopenharmony_ci    PLAT_LOGV("%s: addr:%x, flags:0x%x, len=%hu", __func__, msg->addr, msg->flags, msg->len);
4821bd4fe43Sopenharmony_ci
4831bd4fe43Sopenharmony_ci    Hi35xxI2cEnable(hi35xx);
4841bd4fe43Sopenharmony_ci    Hi35xxI2cDisableIrq(hi35xx, INTR_ALL_MASK);
4851bd4fe43Sopenharmony_ci    Hi35xxI2cClrIrq(hi35xx);
4861bd4fe43Sopenharmony_ci    Hi35xxI2cSetAddr(hi35xx, td);
4871bd4fe43Sopenharmony_ci    Hi35xxI2cCfgCmd(hi35xx, td);
4881bd4fe43Sopenharmony_ci    Hi35xxI2cStartCmd(hi35xx);
4891bd4fe43Sopenharmony_ci
4901bd4fe43Sopenharmony_ci    if (msg->flags & I2C_FLAG_READ) {
4911bd4fe43Sopenharmony_ci        while (bufIdx < msg->len) {
4921bd4fe43Sopenharmony_ci            status = Hi35xxI2cWaitRxNoempty(hi35xx);
4931bd4fe43Sopenharmony_ci            if (status) {
4941bd4fe43Sopenharmony_ci                goto end;
4951bd4fe43Sopenharmony_ci            }
4961bd4fe43Sopenharmony_ci            val = (uint8_t)OSAL_READL(hi35xx->regBase + HI35XX_I2C_RXF);
4971bd4fe43Sopenharmony_ci            status = HdfCopyToUser((void *)&msg->buf[bufIdx], (void *)(uintptr_t)&val, sizeof(val));
4981bd4fe43Sopenharmony_ci            if (status != HDF_SUCCESS) {
4991bd4fe43Sopenharmony_ci                HDF_LOGE("%s: HdfCopyFromUser fail:%d", __func__, status);
5001bd4fe43Sopenharmony_ci                goto end;
5011bd4fe43Sopenharmony_ci            }
5021bd4fe43Sopenharmony_ci            bufIdx++;
5031bd4fe43Sopenharmony_ci        }
5041bd4fe43Sopenharmony_ci    } else {
5051bd4fe43Sopenharmony_ci        while (bufIdx < msg->len) {
5061bd4fe43Sopenharmony_ci            status = Hi35xxI2cWaitTxNofull(hi35xx);
5071bd4fe43Sopenharmony_ci            if (status) {
5081bd4fe43Sopenharmony_ci                goto end;
5091bd4fe43Sopenharmony_ci            }
5101bd4fe43Sopenharmony_ci            status = HdfCopyFromUser((void *)&val, (void *)(uintptr_t)&msg->buf[bufIdx], sizeof(val));
5111bd4fe43Sopenharmony_ci            if (status != HDF_SUCCESS) {
5121bd4fe43Sopenharmony_ci                HDF_LOGE("%s: copy to kernel fail:%d", __func__, status);
5131bd4fe43Sopenharmony_ci                goto end;
5141bd4fe43Sopenharmony_ci            }
5151bd4fe43Sopenharmony_ci            OSAL_WRITEL((unsigned int)val, hi35xx->regBase + HI35XX_I2C_TXF);
5161bd4fe43Sopenharmony_ci            bufIdx++;
5171bd4fe43Sopenharmony_ci        }
5181bd4fe43Sopenharmony_ci    }
5191bd4fe43Sopenharmony_ci
5201bd4fe43Sopenharmony_ci    status = Hi35xxI2cWaitIdle(hi35xx);
5211bd4fe43Sopenharmony_ciend:
5221bd4fe43Sopenharmony_ci    Hi35xxI2cDisable(hi35xx);
5231bd4fe43Sopenharmony_ci
5241bd4fe43Sopenharmony_ci    return status;
5251bd4fe43Sopenharmony_ci}
5261bd4fe43Sopenharmony_ci
5271bd4fe43Sopenharmony_cistatic void Hi35xxI2cCntlrInit(struct Hi35xxI2cCntlr *hi35xx)
5281bd4fe43Sopenharmony_ci{
5291bd4fe43Sopenharmony_ci    Hi35xxI2cHwInitCfg(hi35xx);
5301bd4fe43Sopenharmony_ci    Hi35xxI2cDisable(hi35xx);
5311bd4fe43Sopenharmony_ci    Hi35xxI2cDisableIrq(hi35xx, INTR_ALL_MASK);
5321bd4fe43Sopenharmony_ci    Hi35xxI2cSetFreq(hi35xx);
5331bd4fe43Sopenharmony_ci    Hi35xxI2cSetWater(hi35xx);
5341bd4fe43Sopenharmony_ci    I2cDumperDump(hi35xx, __func__, __LINE__);
5351bd4fe43Sopenharmony_ci    HDF_LOGI("%s: cntlr:%hd init done!", __func__, hi35xx->bus);
5361bd4fe43Sopenharmony_ci}
5371bd4fe43Sopenharmony_ci
5381bd4fe43Sopenharmony_cistatic int32_t Hi35xxI2cTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count)
5391bd4fe43Sopenharmony_ci{
5401bd4fe43Sopenharmony_ci    int32_t ret = HDF_SUCCESS;
5411bd4fe43Sopenharmony_ci    struct Hi35xxI2cCntlr *hi35xx = NULL;
5421bd4fe43Sopenharmony_ci    struct Hi35xxTransferData td;
5431bd4fe43Sopenharmony_ci
5441bd4fe43Sopenharmony_ci    if (cntlr == NULL || cntlr->priv == NULL) {
5451bd4fe43Sopenharmony_ci        HDF_LOGE("Hi35xxI2cTransfer: cntlr lor hi35xxis null!");
5461bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
5471bd4fe43Sopenharmony_ci    }
5481bd4fe43Sopenharmony_ci    hi35xx = (struct Hi35xxI2cCntlr *)cntlr;
5491bd4fe43Sopenharmony_ci
5501bd4fe43Sopenharmony_ci    if (msgs == NULL || count <= 0) {
5511bd4fe43Sopenharmony_ci        HDF_LOGE("Hi35xxI2cTransfer: err parms! count:%hd", count);
5521bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
5531bd4fe43Sopenharmony_ci    }
5541bd4fe43Sopenharmony_ci    td.msgs = msgs;
5551bd4fe43Sopenharmony_ci    td.count = count;
5561bd4fe43Sopenharmony_ci    td.index = 0;
5571bd4fe43Sopenharmony_ci
5581bd4fe43Sopenharmony_ci    while (td.index < td.count) {
5591bd4fe43Sopenharmony_ci        ret = Hi35xxI2cXferOneMsgPolling(hi35xx, &td);
5601bd4fe43Sopenharmony_ci        if (ret != 0) {
5611bd4fe43Sopenharmony_ci            break;
5621bd4fe43Sopenharmony_ci        }
5631bd4fe43Sopenharmony_ci        td.index++;
5641bd4fe43Sopenharmony_ci    }
5651bd4fe43Sopenharmony_ci    return (td.index > 0) ? td.index : ret;
5661bd4fe43Sopenharmony_ci}
5671bd4fe43Sopenharmony_ci
5681bd4fe43Sopenharmony_cistatic const struct I2cMethod g_method = {
5691bd4fe43Sopenharmony_ci    .transfer = Hi35xxI2cTransfer,
5701bd4fe43Sopenharmony_ci};
5711bd4fe43Sopenharmony_ci
5721bd4fe43Sopenharmony_cistatic int32_t Hi35xxI2cLock(struct I2cCntlr *cntlr)
5731bd4fe43Sopenharmony_ci{
5741bd4fe43Sopenharmony_ci    struct Hi35xxI2cCntlr *hi35xx = (struct Hi35xxI2cCntlr *)cntlr;
5751bd4fe43Sopenharmony_ci    if (hi35xx != NULL) {
5761bd4fe43Sopenharmony_ci        return OsalSpinLockIrqSave(&hi35xx->spin, &hi35xx->irqSave);
5771bd4fe43Sopenharmony_ci    }
5781bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
5791bd4fe43Sopenharmony_ci}
5801bd4fe43Sopenharmony_ci
5811bd4fe43Sopenharmony_cistatic void Hi35xxI2cUnlock(struct I2cCntlr *cntlr)
5821bd4fe43Sopenharmony_ci{
5831bd4fe43Sopenharmony_ci    struct Hi35xxI2cCntlr *hi35xx = (struct Hi35xxI2cCntlr *)cntlr;
5841bd4fe43Sopenharmony_ci    if (hi35xx != NULL) {
5851bd4fe43Sopenharmony_ci        (void)OsalSpinUnlockIrqRestore(&hi35xx->spin, &hi35xx->irqSave);
5861bd4fe43Sopenharmony_ci    }
5871bd4fe43Sopenharmony_ci}
5881bd4fe43Sopenharmony_ci
5891bd4fe43Sopenharmony_cistatic const struct I2cLockMethod g_lockOps = {
5901bd4fe43Sopenharmony_ci    .lock = Hi35xxI2cLock,
5911bd4fe43Sopenharmony_ci    .unlock = Hi35xxI2cUnlock,
5921bd4fe43Sopenharmony_ci};
5931bd4fe43Sopenharmony_ci
5941bd4fe43Sopenharmony_cistatic int32_t Hi35xxI2cReadDrs(struct Hi35xxI2cCntlr *hi35xx, const struct DeviceResourceNode *node)
5951bd4fe43Sopenharmony_ci{
5961bd4fe43Sopenharmony_ci    int32_t ret;
5971bd4fe43Sopenharmony_ci    struct DeviceResourceIface *drsOps = NULL;
5981bd4fe43Sopenharmony_ci
5991bd4fe43Sopenharmony_ci    drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
6001bd4fe43Sopenharmony_ci    if (drsOps == NULL || drsOps->GetUint32 == NULL) {
6011bd4fe43Sopenharmony_ci        HDF_LOGE("%s: invalid drs ops fail!", __func__);
6021bd4fe43Sopenharmony_ci        return HDF_FAILURE;
6031bd4fe43Sopenharmony_ci    }
6041bd4fe43Sopenharmony_ci
6051bd4fe43Sopenharmony_ci    ret = drsOps->GetUint32(node, "reg_pbase", &hi35xx->regBasePhy, 0);
6061bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
6071bd4fe43Sopenharmony_ci        HDF_LOGE("%s: read regBase fail!", __func__);
6081bd4fe43Sopenharmony_ci        return ret;
6091bd4fe43Sopenharmony_ci    }
6101bd4fe43Sopenharmony_ci
6111bd4fe43Sopenharmony_ci    ret = drsOps->GetUint16(node, "reg_size", &hi35xx->regSize, 0);
6121bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
6131bd4fe43Sopenharmony_ci        HDF_LOGE("%s: read regsize fail!", __func__);
6141bd4fe43Sopenharmony_ci        return ret;
6151bd4fe43Sopenharmony_ci    }
6161bd4fe43Sopenharmony_ci
6171bd4fe43Sopenharmony_ci    ret = drsOps->GetUint32(node, "freq", &hi35xx->freq, 0);
6181bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
6191bd4fe43Sopenharmony_ci        HDF_LOGE("%s: read freq fail!", __func__);
6201bd4fe43Sopenharmony_ci        return ret;
6211bd4fe43Sopenharmony_ci    }
6221bd4fe43Sopenharmony_ci
6231bd4fe43Sopenharmony_ci    ret = drsOps->GetUint32(node, "irq", &hi35xx->irq, 0);
6241bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
6251bd4fe43Sopenharmony_ci        HDF_LOGE("%s: read irq fail!", __func__);
6261bd4fe43Sopenharmony_ci        return ret;
6271bd4fe43Sopenharmony_ci    }
6281bd4fe43Sopenharmony_ci
6291bd4fe43Sopenharmony_ci    ret = drsOps->GetUint32(node, "clk", &hi35xx->clk, 0);
6301bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
6311bd4fe43Sopenharmony_ci        HDF_LOGE("%s: read clk fail!", __func__);
6321bd4fe43Sopenharmony_ci        return ret;
6331bd4fe43Sopenharmony_ci    }
6341bd4fe43Sopenharmony_ci
6351bd4fe43Sopenharmony_ci    ret = drsOps->GetUint16(node, "bus", (uint16_t *)&hi35xx->bus, 0);
6361bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
6371bd4fe43Sopenharmony_ci        HDF_LOGE("%s: read bus fail!", __func__);
6381bd4fe43Sopenharmony_ci        return ret;
6391bd4fe43Sopenharmony_ci    }
6401bd4fe43Sopenharmony_ci
6411bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
6421bd4fe43Sopenharmony_ci}
6431bd4fe43Sopenharmony_ci
6441bd4fe43Sopenharmony_cistatic int32_t Hi35xxI2cParseAndInit(const struct DeviceResourceNode *node)
6451bd4fe43Sopenharmony_ci{
6461bd4fe43Sopenharmony_ci    int32_t ret;
6471bd4fe43Sopenharmony_ci    struct Hi35xxI2cCntlr *hi35xx = NULL;
6481bd4fe43Sopenharmony_ci
6491bd4fe43Sopenharmony_ci    hi35xx = (struct Hi35xxI2cCntlr *)OsalMemCalloc(sizeof(*hi35xx));
6501bd4fe43Sopenharmony_ci    if (hi35xx == NULL) {
6511bd4fe43Sopenharmony_ci        HDF_LOGE("%s: malloc hi35xx fail!", __func__);
6521bd4fe43Sopenharmony_ci        return HDF_ERR_MALLOC_FAIL;
6531bd4fe43Sopenharmony_ci    }
6541bd4fe43Sopenharmony_ci
6551bd4fe43Sopenharmony_ci    ret = Hi35xxI2cReadDrs(hi35xx, node);
6561bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
6571bd4fe43Sopenharmony_ci        HDF_LOGE("%s: read drs fail! ret:%d", __func__, ret);
6581bd4fe43Sopenharmony_ci        goto __ERR__;
6591bd4fe43Sopenharmony_ci    }
6601bd4fe43Sopenharmony_ci
6611bd4fe43Sopenharmony_ci    hi35xx->regBase = OsalIoRemap(hi35xx->regBasePhy, hi35xx->regSize);
6621bd4fe43Sopenharmony_ci    if (hi35xx->regBase == NULL) {
6631bd4fe43Sopenharmony_ci        HDF_LOGE("%s: ioremap regBase fail!", __func__);
6641bd4fe43Sopenharmony_ci        ret = HDF_ERR_IO;
6651bd4fe43Sopenharmony_ci        goto __ERR__;
6661bd4fe43Sopenharmony_ci    }
6671bd4fe43Sopenharmony_ci
6681bd4fe43Sopenharmony_ci    ret = I2cDumperCreate(hi35xx);
6691bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
6701bd4fe43Sopenharmony_ci        HDF_LOGE("%s: create dumper failed:%d", __func__, ret);
6711bd4fe43Sopenharmony_ci        goto __ERR__;
6721bd4fe43Sopenharmony_ci    }
6731bd4fe43Sopenharmony_ci
6741bd4fe43Sopenharmony_ci    Hi35xxI2cCntlrInit(hi35xx);
6751bd4fe43Sopenharmony_ci
6761bd4fe43Sopenharmony_ci    hi35xx->cntlr.priv = (void *)node;
6771bd4fe43Sopenharmony_ci    hi35xx->cntlr.busId = hi35xx->bus;
6781bd4fe43Sopenharmony_ci    hi35xx->cntlr.ops = &g_method;
6791bd4fe43Sopenharmony_ci    hi35xx->cntlr.lockOps = &g_lockOps;
6801bd4fe43Sopenharmony_ci    (void)OsalSpinInit(&hi35xx->spin);
6811bd4fe43Sopenharmony_ci    ret = I2cCntlrAdd(&hi35xx->cntlr);
6821bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
6831bd4fe43Sopenharmony_ci        HDF_LOGE("%s: add i2c controller fail:%d!", __func__, ret);
6841bd4fe43Sopenharmony_ci        (void)OsalSpinDestroy(&hi35xx->spin);
6851bd4fe43Sopenharmony_ci        goto __ERR__;
6861bd4fe43Sopenharmony_ci    }
6871bd4fe43Sopenharmony_ci
6881bd4fe43Sopenharmony_ci#ifdef USER_VFS_SUPPORT
6891bd4fe43Sopenharmony_ci    (void)I2cAddVfsById(hi35xx->cntlr.busId);
6901bd4fe43Sopenharmony_ci#endif
6911bd4fe43Sopenharmony_ci    return HDF_SUCCESS;
6921bd4fe43Sopenharmony_ci__ERR__:
6931bd4fe43Sopenharmony_ci    if (hi35xx != NULL) {
6941bd4fe43Sopenharmony_ci        if (hi35xx->regBase != NULL) {
6951bd4fe43Sopenharmony_ci            OsalIoUnmap((void *)hi35xx->regBase);
6961bd4fe43Sopenharmony_ci            hi35xx->regBase = NULL;
6971bd4fe43Sopenharmony_ci        }
6981bd4fe43Sopenharmony_ci        OsalMemFree(hi35xx);
6991bd4fe43Sopenharmony_ci        hi35xx = NULL;
7001bd4fe43Sopenharmony_ci    }
7011bd4fe43Sopenharmony_ci    return ret;
7021bd4fe43Sopenharmony_ci}
7031bd4fe43Sopenharmony_ci
7041bd4fe43Sopenharmony_cistatic int32_t Hi35xxI2cInit(struct HdfDeviceObject *device)
7051bd4fe43Sopenharmony_ci{
7061bd4fe43Sopenharmony_ci    int32_t ret;
7071bd4fe43Sopenharmony_ci    const struct DeviceResourceNode *childNode = NULL;
7081bd4fe43Sopenharmony_ci
7091bd4fe43Sopenharmony_ci    if (device == NULL || device->property == NULL) {
7101bd4fe43Sopenharmony_ci        HDF_LOGE("%s: device or property is NULL", __func__);
7111bd4fe43Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
7121bd4fe43Sopenharmony_ci    }
7131bd4fe43Sopenharmony_ci
7141bd4fe43Sopenharmony_ci    ret = HDF_SUCCESS;
7151bd4fe43Sopenharmony_ci    DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
7161bd4fe43Sopenharmony_ci        ret = Hi35xxI2cParseAndInit(childNode);
7171bd4fe43Sopenharmony_ci        if (ret != HDF_SUCCESS) {
7181bd4fe43Sopenharmony_ci            break;
7191bd4fe43Sopenharmony_ci        }
7201bd4fe43Sopenharmony_ci    }
7211bd4fe43Sopenharmony_ci    HDF_LOGI("%s: I2c init success!", __func__);
7221bd4fe43Sopenharmony_ci    return ret;
7231bd4fe43Sopenharmony_ci}
7241bd4fe43Sopenharmony_ci
7251bd4fe43Sopenharmony_cistatic void Hi35xxI2cRemoveByNode(const struct DeviceResourceNode *node)
7261bd4fe43Sopenharmony_ci{
7271bd4fe43Sopenharmony_ci    int32_t ret;
7281bd4fe43Sopenharmony_ci    int16_t bus;
7291bd4fe43Sopenharmony_ci    struct I2cCntlr *cntlr = NULL;
7301bd4fe43Sopenharmony_ci    struct Hi35xxI2cCntlr *hi35xx = NULL;
7311bd4fe43Sopenharmony_ci    struct DeviceResourceIface *drsOps = NULL;
7321bd4fe43Sopenharmony_ci
7331bd4fe43Sopenharmony_ci    drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
7341bd4fe43Sopenharmony_ci    if (drsOps == NULL || drsOps->GetUint32 == NULL) {
7351bd4fe43Sopenharmony_ci        HDF_LOGE("%s: invalid drs ops fail!", __func__);
7361bd4fe43Sopenharmony_ci        return;
7371bd4fe43Sopenharmony_ci    }
7381bd4fe43Sopenharmony_ci
7391bd4fe43Sopenharmony_ci    ret = drsOps->GetUint16(node, "bus", (uint16_t *)&bus, 0);
7401bd4fe43Sopenharmony_ci    if (ret != HDF_SUCCESS) {
7411bd4fe43Sopenharmony_ci        HDF_LOGE("%s: read bus fail!", __func__);
7421bd4fe43Sopenharmony_ci        return;
7431bd4fe43Sopenharmony_ci    }
7441bd4fe43Sopenharmony_ci
7451bd4fe43Sopenharmony_ci    I2cDumperDestroy(hi35xx);
7461bd4fe43Sopenharmony_ci    cntlr = I2cCntlrGet(bus);
7471bd4fe43Sopenharmony_ci    if (cntlr != NULL && cntlr->priv == node) {
7481bd4fe43Sopenharmony_ci        I2cCntlrPut(cntlr);
7491bd4fe43Sopenharmony_ci        I2cCntlrRemove(cntlr);
7501bd4fe43Sopenharmony_ci        hi35xx = (struct Hi35xxI2cCntlr *)cntlr;
7511bd4fe43Sopenharmony_ci        OsalIoUnmap((void *)hi35xx->regBase);
7521bd4fe43Sopenharmony_ci        (void)OsalSpinDestroy(&hi35xx->spin);
7531bd4fe43Sopenharmony_ci        OsalMemFree(hi35xx);
7541bd4fe43Sopenharmony_ci    }
7551bd4fe43Sopenharmony_ci    return;
7561bd4fe43Sopenharmony_ci}
7571bd4fe43Sopenharmony_ci
7581bd4fe43Sopenharmony_cistatic void Hi35xxI2cRelease(struct HdfDeviceObject *device)
7591bd4fe43Sopenharmony_ci{
7601bd4fe43Sopenharmony_ci    const struct DeviceResourceNode *childNode = NULL;
7611bd4fe43Sopenharmony_ci
7621bd4fe43Sopenharmony_ci    HDF_LOGI("%s: enter", __func__);
7631bd4fe43Sopenharmony_ci
7641bd4fe43Sopenharmony_ci    if (device == NULL || device->property == NULL) {
7651bd4fe43Sopenharmony_ci        HDF_LOGE("%s: device or property is NULL", __func__);
7661bd4fe43Sopenharmony_ci        return;
7671bd4fe43Sopenharmony_ci    }
7681bd4fe43Sopenharmony_ci
7691bd4fe43Sopenharmony_ci    DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
7701bd4fe43Sopenharmony_ci        Hi35xxI2cRemoveByNode(childNode);
7711bd4fe43Sopenharmony_ci    }
7721bd4fe43Sopenharmony_ci}
7731bd4fe43Sopenharmony_ci
7741bd4fe43Sopenharmony_cistruct HdfDriverEntry g_i2cDriverEntry = {
7751bd4fe43Sopenharmony_ci    .moduleVersion = 1,
7761bd4fe43Sopenharmony_ci    .Init = Hi35xxI2cInit,
7771bd4fe43Sopenharmony_ci    .Release = Hi35xxI2cRelease,
7781bd4fe43Sopenharmony_ci    .moduleName = "hi35xx_i2c_driver",
7791bd4fe43Sopenharmony_ci};
7801bd4fe43Sopenharmony_ciHDF_INIT(g_i2cDriverEntry);
781