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