1 /*
2  * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "i2c_hi35xx.h"
17 #include "asm/platform.h"
18 #include "los_hwi.h"
19 #include "securec.h"
20 #include "device_resource_if.h"
21 #include "hdf_device_desc.h"
22 #include "hdf_log.h"
23 #include "i2c_core.h"
24 #include "i2c_dev.h"
25 #include "osal_io.h"
26 #include "osal_mem.h"
27 #include "osal_spinlock.h"
28 #include "osal_time.h"
29 #include "platform_dumper.h"
30 
31 #define HDF_LOG_TAG i2c_hi35xx
32 #define USER_VFS_SUPPORT
33 
34 #define HI35XX_I2C_DELAY      50
35 #define I2C_FREQ_NORMAL      100000
36 #define HI35XX_SCL_HIGH_CNT   36
37 #define HI35XX_SCL_LOW_CNT    64
38 #define HI35XX_SCL_FULL_CNT   100
39 #define HI35XX_REG_SIZE       4
40 #define HI35XX_I2C_R_LOOP_ADJ 2
41 #define HI35XX_I2C_RESCUE_TIMES 9
42 #define HI35XX_I2C_RESCUE_DELAY 10
43 
44 #define I2C_DUMPER_NAME_LEN     64
45 #define I2C_DUMPER_NAME_PREFIX  "i2c_dumper_"
46 
47 struct Hi35xxI2cCntlr {
48     struct I2cCntlr cntlr;
49     OsalSpinlock spin;
50     uint32_t irqSave;
51     volatile unsigned char  *regBase;
52     uint16_t regSize;
53     int16_t bus;
54     uint32_t clk;
55     uint32_t freq;
56     uint32_t irq;
57     uint32_t regBasePhy;
58     struct PlatformDumper *dumper;
59     char *dumperName;
60 };
61 
62 struct Hi35xxTransferData {
63     struct I2cMsg *msgs;
64     int16_t index;
65     int16_t count;
66 };
67 
68 #define WRITE_REG_BIT(value, offset, addr) \
69     do {                                   \
70         unsigned long t, mask;             \
71         mask = 1 << (offset);              \
72         t = OSAL_READL(addr);              \
73         t &= ~mask;                        \
74         t |= ((value) << (offset)) & mask; \
75         OSAL_WRITEL(t, (addr));            \
76     } while (0)
77 
78 #define REG_CRG_I2C           (CRG_REG_BASE + 0x01b8)
79 #define I2C_CRG_RST_OFFSET    19
80 #define I2C_CRG_CLK_OFFSET    11
81 
I2cDumperAddDatas(const struct Hi35xxI2cCntlr *hi35xx)82 static int32_t I2cDumperAddDatas(const struct Hi35xxI2cCntlr *hi35xx)
83 {
84     struct PlatformDumperData datas[] = {
85         {"HI35XX_I2Cx_GLB", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_GLB)},
86         {"HI35XX_I2Cx_SCL_H", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_SCL_H)},
87         {"HI35XX_I2Cx_SCL_L", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_SCL_L)},
88         {"HI35XX_I2Cx_DATA1", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_DATA1)},
89         {"HI35XX_I2C_TXF", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_TXF)},
90         {"HI35XX_I2C_RXF", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_RXF)},
91         {"HI35XX_I2C_CTRL2", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_CTRL2)},
92         {"HI35XX_I2C_STAT", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_STAT)},
93         {"HI35XX_I2C_INTR_RAW", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_INTR_RAW)},
94         {"HI35XX_I2C_INTR_EN", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_INTR_EN)},
95         {"HI35XX_I2C_INTR_STAT", PLATFORM_DUMPER_REGISTERL, (void *)(hi35xx->regBase + HI35XX_I2C_INTR_STAT)},
96     };
97 
98     if (hi35xx->dumper == NULL) {
99         HDF_LOGE("%s: dumper is NULL", __func__);
100         return HDF_ERR_INVALID_OBJECT;
101     }
102     return PlatformDumperAddDatas(hi35xx->dumper, datas, sizeof(datas) / sizeof(struct PlatformDumperData));
103 }
104 
I2cDumperCreate(struct Hi35xxI2cCntlr *hi35xx)105 static int32_t I2cDumperCreate(struct Hi35xxI2cCntlr *hi35xx)
106 {
107     struct PlatformDumper *dumper = NULL;
108     char *name = NULL;
109 
110     name = (char *)OsalMemCalloc(I2C_DUMPER_NAME_LEN);
111     if (name == NULL) {
112         HDF_LOGE("%s: alloc name fail", __func__);
113         return HDF_ERR_MALLOC_FAIL;
114     }
115 
116     if (snprintf_s(name, I2C_DUMPER_NAME_LEN, I2C_DUMPER_NAME_LEN - 1, "%s%hd",
117         I2C_DUMPER_NAME_PREFIX, hi35xx->bus) < 0) {
118         HDF_LOGE("%s: snprintf_s name fail!", __func__);
119         OsalMemFree(name);
120         return HDF_ERR_IO;
121     }
122     dumper = PlatformDumperCreate(name);
123     if (dumper == NULL) {
124         HDF_LOGE("%s: create dumper for %s fail!", __func__, name);
125         OsalMemFree(name);
126         return HDF_ERR_IO;
127     }
128 
129     hi35xx->dumper = dumper;
130     hi35xx->dumperName = name;
131 
132     return HDF_SUCCESS;
133 }
134 
I2cDumperDestroy(struct Hi35xxI2cCntlr *hi35xx)135 static inline void I2cDumperDestroy(struct Hi35xxI2cCntlr *hi35xx)
136 {
137     PlatformDumperDestroy(hi35xx->dumper);
138     OsalMemFree(hi35xx->dumperName);
139 }
140 
I2cDumperDump(const struct Hi35xxI2cCntlr *hi35xx, const char *executor, int srcLine)141 static void I2cDumperDump(const struct Hi35xxI2cCntlr *hi35xx, const char *executor, int srcLine)
142 {
143     static int line = 0;
144     struct PlatformDumperData header = {executor, PLATFORM_DUMPER_INT32, &line};
145     int32_t ret;
146 
147     line = srcLine;
148     ret = PlatformDumperAddData(hi35xx->dumper, &header);
149     if (ret != HDF_SUCCESS) {
150         HDF_LOGE("%s: add header fail", __func__);
151         return;
152     }
153     ret = I2cDumperAddDatas(hi35xx);
154     if (ret != HDF_SUCCESS) {
155         return;
156     }
157     (void)PlatformDumperDump(hi35xx->dumper);
158     (void)PlatformDumperClearDatas(hi35xx->dumper);
159 }
160 
Hi35xxI2cHwInitCfg(struct Hi35xxI2cCntlr *hi35xx)161 static inline void Hi35xxI2cHwInitCfg(struct Hi35xxI2cCntlr *hi35xx)
162 {
163     unsigned long busId = (unsigned long)hi35xx->bus;
164 
165     WRITE_REG_BIT(1, I2C_CRG_CLK_OFFSET + busId, REG_CRG_I2C);
166     WRITE_REG_BIT(0, I2C_CRG_RST_OFFSET + busId, REG_CRG_I2C);
167 }
168 
Hi35xxI2cEnable(const struct Hi35xxI2cCntlr *hi35xx)169 static inline void Hi35xxI2cEnable(const struct Hi35xxI2cCntlr *hi35xx)
170 {
171     unsigned int val;
172 
173     val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_GLB);
174     val |= GLB_EN_MASK;
175     OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_GLB);
176 }
177 
Hi35xxI2cDisable(const struct Hi35xxI2cCntlr *hi35xx)178 static inline void Hi35xxI2cDisable(const struct Hi35xxI2cCntlr *hi35xx)
179 {
180     unsigned int val;
181 
182     val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_GLB);
183     val &= ~GLB_EN_MASK;
184     OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_GLB);
185 }
186 
Hi35xxI2cDisableIrq(const struct Hi35xxI2cCntlr *hi35xx, unsigned int flag)187 static inline void Hi35xxI2cDisableIrq(const struct Hi35xxI2cCntlr *hi35xx, unsigned int flag)
188 {
189     unsigned int val;
190 
191     val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_INTR_EN);
192     val &= ~flag;
193     OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_INTR_EN);
194 }
195 
Hi35xxI2cCfgIrq(const struct Hi35xxI2cCntlr *hi35xx, unsigned int flag)196 static inline void Hi35xxI2cCfgIrq(const struct Hi35xxI2cCntlr *hi35xx, unsigned int flag)
197 {
198     OSAL_WRITEL(flag, hi35xx->regBase + HI35XX_I2C_INTR_EN);
199 }
200 
Hi35xxI2cClrIrq(const struct Hi35xxI2cCntlr *hi35xx)201 static inline void Hi35xxI2cClrIrq(const struct Hi35xxI2cCntlr *hi35xx)
202 {
203     (void)OSAL_READL(hi35xx->regBase + HI35XX_I2C_INTR_STAT);
204     OSAL_WRITEL(INTR_ALL_MASK, hi35xx->regBase + HI35XX_I2C_INTR_RAW);
205 }
206 
Hi35xxI2cSetFreq(struct Hi35xxI2cCntlr *hi35xx)207 static void Hi35xxI2cSetFreq(struct Hi35xxI2cCntlr *hi35xx)
208 {
209     unsigned int maxFreq;
210     unsigned int freq;
211     unsigned int clkRate;
212     unsigned int val;
213 
214     freq = hi35xx->freq;
215     clkRate = hi35xx->clk;
216     maxFreq = clkRate >> 1;
217 
218     if (freq > maxFreq) {
219         hi35xx->freq = maxFreq;
220         freq = hi35xx->freq;
221     }
222     if (freq <= I2C_FREQ_NORMAL) {
223         val = clkRate / (freq << 1);
224         OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_SCL_H);
225         OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_SCL_L);
226     } else {
227         val = (clkRate * HI35XX_SCL_HIGH_CNT) / (freq * HI35XX_SCL_FULL_CNT);
228         OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_SCL_H);
229         val = (clkRate * HI35XX_SCL_LOW_CNT) / (freq * HI35XX_SCL_FULL_CNT);
230         OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_SCL_L);
231     }
232     val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_GLB);
233     val &= ~GLB_SDA_HOLD_MASK;
234     val |= ((0xa << GLB_SDA_HOLD_SHIFT) & GLB_SDA_HOLD_MASK);
235     OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_GLB);
236 }
237 
Hi35xxI2cSetWater(const struct Hi35xxI2cCntlr *hi35xx)238 static inline void Hi35xxI2cSetWater(const struct Hi35xxI2cCntlr *hi35xx)
239 {
240     OSAL_WRITEL(I2C_TXF_WATER, hi35xx->regBase + HI35XX_I2C_TX_WATER);
241     OSAL_WRITEL(I2C_RXF_WATER, hi35xx->regBase + HI35XX_I2C_RX_WATER);
242 }
243 
244 /*
245  * config i2c device addr
246  */
Hi35xxI2cSetAddr(const struct Hi35xxI2cCntlr *hi35xx, const struct Hi35xxTransferData *td)247 static void Hi35xxI2cSetAddr(const struct Hi35xxI2cCntlr *hi35xx, const struct Hi35xxTransferData *td)
248 {
249     struct I2cMsg *msg = &td->msgs[td->index];
250     unsigned int addr = msg->addr;
251 
252     if (msg->flags & I2C_FLAG_ADDR_10BIT) {
253         /* First byte is 11110XX0 where XX is upper 2 bits */
254         addr = ((msg->addr & 0x300) << 1) | 0xf000;
255         if (msg->flags & I2C_FLAG_READ) {
256             addr |= 0x100;
257         }
258         /* Second byte is the remaining 8 bits */
259         addr |= msg->addr & 0xff;
260     } else {
261         addr = (msg->addr & 0x7f) << 1;
262         if (msg->flags & I2C_FLAG_READ) {
263             addr |= 1;
264         }
265     }
266 
267     OSAL_WRITEL(addr, hi35xx->regBase + HI35XX_I2C_DATA1);
268 }
269 
Hi35xxI2cCmdregSet(const struct Hi35xxI2cCntlr *hi35xx, unsigned int cmd, unsigned int *offset)270 static inline void Hi35xxI2cCmdregSet(const struct Hi35xxI2cCntlr *hi35xx, unsigned int cmd, unsigned int *offset)
271 {
272     PLAT_LOGV("%s: offset=0x%x, cmd=0x%x...", __func__, *offset * HI35XX_REG_SIZE, cmd);
273     OSAL_WRITEL(cmd, hi35xx->regBase + HI35XX_I2C_CMD_BASE + *offset * HI35XX_REG_SIZE);
274     (*offset)++;
275 }
276 
Hi35xxI2cCfgCmd(const struct Hi35xxI2cCntlr *hi35xx, const struct Hi35xxTransferData *td)277 static void Hi35xxI2cCfgCmd(const struct Hi35xxI2cCntlr *hi35xx, const struct Hi35xxTransferData *td)
278 {
279     unsigned int offset = 0;
280     struct I2cMsg *msg = &td->msgs[td->index];
281 
282     Hi35xxI2cCmdregSet(hi35xx, (td->index == 0) ? CMD_TX_S : CMD_TX_RS, &offset);
283 
284     if (msg->flags & I2C_FLAG_ADDR_10BIT) {
285         Hi35xxI2cCmdregSet(hi35xx, CMD_TX_D1_2, &offset);
286         if (td->index == 0) {
287             Hi35xxI2cCmdregSet(hi35xx, CMD_TX_D1_1, &offset);
288         }
289     } else {
290         Hi35xxI2cCmdregSet(hi35xx, CMD_TX_D1_1, &offset);
291     }
292 
293     Hi35xxI2cCmdregSet(hi35xx, (msg->flags & I2C_FLAG_IGNORE_NO_ACK) ? CMD_IGN_ACK : CMD_RX_ACK, &offset);
294     if (msg->flags & I2C_FLAG_READ) {
295         if (msg->len > 1) {
296             OSAL_WRITEL(offset, hi35xx->regBase + HI35XX_I2C_DST1);
297             OSAL_WRITEL(msg->len - HI35XX_I2C_R_LOOP_ADJ, hi35xx->regBase + HI35XX_I2C_LOOP1);
298             Hi35xxI2cCmdregSet(hi35xx, CMD_RX_FIFO, &offset);
299             Hi35xxI2cCmdregSet(hi35xx, CMD_TX_ACK, &offset);
300             Hi35xxI2cCmdregSet(hi35xx, CMD_JMP1, &offset);
301         }
302         Hi35xxI2cCmdregSet(hi35xx, CMD_RX_FIFO, &offset);
303         Hi35xxI2cCmdregSet(hi35xx, CMD_TX_NACK, &offset);
304     } else {
305         OSAL_WRITEL(offset, hi35xx->regBase + HI35XX_I2C_DST1);
306         OSAL_WRITEL(msg->len - 1, hi35xx->regBase + HI35XX_I2C_LOOP1);
307         Hi35xxI2cCmdregSet(hi35xx, CMD_UP_TXF, &offset);
308         Hi35xxI2cCmdregSet(hi35xx, CMD_TX_FIFO, &offset);
309 
310         Hi35xxI2cCmdregSet(hi35xx, (msg->flags & I2C_FLAG_IGNORE_NO_ACK) ? CMD_IGN_ACK : CMD_RX_ACK, &offset);
311         Hi35xxI2cCmdregSet(hi35xx, CMD_JMP1, &offset);
312     }
313 
314     if ((td->index == (td->count - 1)) || (msg->flags & I2C_FLAG_STOP)) {
315         PLAT_LOGV("%s: TX stop, idx:%hd, count:%hd, flags:%u", __func__,
316             td->index, td->count, msg->flags);
317         Hi35xxI2cCmdregSet(hi35xx, CMD_TX_P, &offset);
318     }
319 
320     Hi35xxI2cCmdregSet(hi35xx, CMD_EXIT, &offset);
321 }
322 
323 /*
324  * Start command sequence
325  */
Hi35xxI2cStartCmd(const struct Hi35xxI2cCntlr *hi35xx)326 static inline void Hi35xxI2cStartCmd(const struct Hi35xxI2cCntlr *hi35xx)
327 {
328     unsigned int val;
329 
330     val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_CTRL1);
331     val |= CTRL1_CMD_START_MASK;
332     OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_CTRL1);
333 }
334 
Hi35xxI2cRescure(const struct Hi35xxI2cCntlr *hi35xx)335 static void Hi35xxI2cRescure(const struct Hi35xxI2cCntlr *hi35xx)
336 {
337     int index;
338     unsigned int val;
339     unsigned int timeCnt;
340 
341     Hi35xxI2cDisable(hi35xx);
342     Hi35xxI2cCfgIrq(hi35xx, 0);
343     Hi35xxI2cClrIrq(hi35xx);
344 
345     val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT);
346     OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_CTRL2);
347 
348     timeCnt = 0;
349     do {
350         for (index = 0; index < HI35XX_I2C_RESCUE_TIMES; index++) {
351             val = (0x1 << GPIO_MODE_SHIFT) | 0x1;
352             OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_CTRL2);
353 
354             OsalUDelay(HI35XX_I2C_RESCUE_DELAY);
355 
356             val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT);
357             OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_CTRL2);
358 
359             OsalUDelay(HI35XX_I2C_RESCUE_DELAY);
360         }
361 
362         timeCnt++;
363         if (timeCnt > I2C_WAIT_TIMEOUT) {
364             HDF_LOGE("%s: wait Timeout!", __func__);
365             goto __DISABLE_RESCURE;
366         }
367 
368         val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_CTRL2);
369     } while (!(val & (0x1 << CHECK_SDA_IN_SHIFT)));
370 
371     val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT);
372     OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_CTRL2);
373 
374     val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT);
375     OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_CTRL2);
376 
377     OsalUDelay(HI35XX_I2C_RESCUE_DELAY);
378 
379     val = (0x1 << GPIO_MODE_SHIFT) | (0x1 << FORCE_SCL_OEN_SHIFT) | (0x1 << FORCE_SDA_OEN_SHIFT);
380     OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_CTRL2);
381 
382 __DISABLE_RESCURE:
383     val = (0x1 << FORCE_SCL_OEN_SHIFT) | 0x1;
384     OSAL_WRITEL(val, hi35xx->regBase + HI35XX_I2C_CTRL2);
385     HDF_LOGW("%s: done!", __func__);
386 }
387 
Hi35xxI2cWaitRxNoempty(const struct Hi35xxI2cCntlr *hi35xx)388 static int Hi35xxI2cWaitRxNoempty(const struct Hi35xxI2cCntlr *hi35xx)
389 {
390     unsigned int timeCnt = 0;
391     unsigned int val;
392 
393     do {
394         val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_STAT);
395         if (val & STAT_RXF_NOE_MASK) {
396             return 0;
397         }
398         OsalUDelay(HI35XX_I2C_DELAY);
399     } while (timeCnt++ < I2C_TIMEOUT_COUNT);
400 
401     Hi35xxI2cRescure(hi35xx);
402     HDF_LOGE("%s:wait rx no empty timeout, RIS:0x%x, SR: 0x%x",
403         __func__, OSAL_READL(hi35xx->regBase + HI35XX_I2C_INTR_RAW), val);
404     I2cDumperDump(hi35xx, __func__, __LINE__);
405     return HDF_ERR_IO;
406 }
407 
Hi35xxI2cWaitTxNofull(const struct Hi35xxI2cCntlr *hi35xx)408 static int Hi35xxI2cWaitTxNofull(const struct Hi35xxI2cCntlr *hi35xx)
409 {
410     unsigned int timeCnt = 0;
411     unsigned int val;
412 
413     do {
414         val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_STAT);
415         if (val & STAT_TXF_NOF_MASK) {
416             return 0;
417         }
418         OsalUDelay(HI35XX_I2C_DELAY);
419     } while (timeCnt++ < I2C_TIMEOUT_COUNT);
420 
421     Hi35xxI2cRescure(hi35xx);
422     HDF_LOGE("%s: wait rx no empty timeout, RIS: 0x%x, SR: 0x%x",
423         __func__, OSAL_READL(hi35xx->regBase + HI35XX_I2C_INTR_RAW), val);
424     I2cDumperDump(hi35xx, __func__, __LINE__);
425     return HDF_ERR_IO;
426 }
427 
Hi35xxI2cWaitIdle(const struct Hi35xxI2cCntlr *hi35xx)428 static int32_t Hi35xxI2cWaitIdle(const struct Hi35xxI2cCntlr *hi35xx)
429 {
430     unsigned int timeCnt = 0;
431     unsigned int val;
432 
433     do {
434         val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_INTR_RAW);
435         if (val & (INTR_ABORT_MASK)) {
436             HDF_LOGE("%s: wait idle abort!, RIS: 0x%x", __func__, val);
437             return HDF_ERR_IO;
438         }
439         if (val & INTR_CMD_DONE_MASK) {
440             return 0;
441         }
442         OsalUDelay(HI35XX_I2C_DELAY);
443     } while (timeCnt++ < I2C_WAIT_TIMEOUT);
444 
445     Hi35xxI2cRescure(hi35xx);
446     HDF_LOGE("%s: wait idle timeout, RIS: 0x%x, SR: 0x%x",
447         __func__, val, OSAL_READL(hi35xx->regBase + HI35XX_I2C_STAT));
448     I2cDumperDump(hi35xx, __func__, __LINE__);
449     return HDF_ERR_IO;
450 }
451 
HdfCopyFromUser(void *to, const void *from, unsigned long n)452 static int HdfCopyFromUser(void *to, const void *from, unsigned long n)
453 {
454     int ret;
455     ret = LOS_CopyToKernel(to, n, from, n);
456     if (ret != LOS_OK) {
457         HDF_LOGE("%s: copy from kernel fail:%d", __func__, ret);
458         return HDF_FAILURE;
459     }
460     return HDF_SUCCESS;
461 }
462 
HdfCopyToUser(void *to, const void *from, unsigned long n)463 static int HdfCopyToUser(void *to, const void *from, unsigned long n)
464 {
465     int ret;
466     ret = LOS_CopyFromKernel(to, n, from, n);
467     if (ret != LOS_OK) {
468         HDF_LOGE("%s: copy from kernel fail:%d", __func__, ret);
469         return HDF_FAILURE;
470     }
471     return HDF_SUCCESS;
472 }
473 
Hi35xxI2cXferOneMsgPolling(const struct Hi35xxI2cCntlr *hi35xx, const struct Hi35xxTransferData *td)474 static int32_t Hi35xxI2cXferOneMsgPolling(const struct Hi35xxI2cCntlr *hi35xx, const struct Hi35xxTransferData *td)
475 {
476     int32_t status;
477     uint16_t bufIdx = 0;
478     uint8_t val;
479     struct I2cMsg *msg = &td->msgs[td->index];
480 
481     PLAT_LOGV("%s: addr:%x, flags:0x%x, len=%hu", __func__, msg->addr, msg->flags, msg->len);
482 
483     Hi35xxI2cEnable(hi35xx);
484     Hi35xxI2cDisableIrq(hi35xx, INTR_ALL_MASK);
485     Hi35xxI2cClrIrq(hi35xx);
486     Hi35xxI2cSetAddr(hi35xx, td);
487     Hi35xxI2cCfgCmd(hi35xx, td);
488     Hi35xxI2cStartCmd(hi35xx);
489 
490     if (msg->flags & I2C_FLAG_READ) {
491         while (bufIdx < msg->len) {
492             status = Hi35xxI2cWaitRxNoempty(hi35xx);
493             if (status) {
494                 goto end;
495             }
496             val = (uint8_t)OSAL_READL(hi35xx->regBase + HI35XX_I2C_RXF);
497             status = HdfCopyToUser((void *)&msg->buf[bufIdx], (void *)(uintptr_t)&val, sizeof(val));
498             if (status != HDF_SUCCESS) {
499                 HDF_LOGE("%s: HdfCopyFromUser fail:%d", __func__, status);
500                 goto end;
501             }
502             bufIdx++;
503         }
504     } else {
505         while (bufIdx < msg->len) {
506             status = Hi35xxI2cWaitTxNofull(hi35xx);
507             if (status) {
508                 goto end;
509             }
510             status = HdfCopyFromUser((void *)&val, (void *)(uintptr_t)&msg->buf[bufIdx], sizeof(val));
511             if (status != HDF_SUCCESS) {
512                 HDF_LOGE("%s: copy to kernel fail:%d", __func__, status);
513                 goto end;
514             }
515             OSAL_WRITEL((unsigned int)val, hi35xx->regBase + HI35XX_I2C_TXF);
516             bufIdx++;
517         }
518     }
519 
520     status = Hi35xxI2cWaitIdle(hi35xx);
521 end:
522     Hi35xxI2cDisable(hi35xx);
523 
524     return status;
525 }
526 
Hi35xxI2cCntlrInit(struct Hi35xxI2cCntlr *hi35xx)527 static void Hi35xxI2cCntlrInit(struct Hi35xxI2cCntlr *hi35xx)
528 {
529     Hi35xxI2cHwInitCfg(hi35xx);
530     Hi35xxI2cDisable(hi35xx);
531     Hi35xxI2cDisableIrq(hi35xx, INTR_ALL_MASK);
532     Hi35xxI2cSetFreq(hi35xx);
533     Hi35xxI2cSetWater(hi35xx);
534     I2cDumperDump(hi35xx, __func__, __LINE__);
535     HDF_LOGI("%s: cntlr:%hd init done!", __func__, hi35xx->bus);
536 }
537 
Hi35xxI2cTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count)538 static int32_t Hi35xxI2cTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count)
539 {
540     int32_t ret = HDF_SUCCESS;
541     struct Hi35xxI2cCntlr *hi35xx = NULL;
542     struct Hi35xxTransferData td;
543 
544     if (cntlr == NULL || cntlr->priv == NULL) {
545         HDF_LOGE("Hi35xxI2cTransfer: cntlr lor hi35xxis null!");
546         return HDF_ERR_INVALID_OBJECT;
547     }
548     hi35xx = (struct Hi35xxI2cCntlr *)cntlr;
549 
550     if (msgs == NULL || count <= 0) {
551         HDF_LOGE("Hi35xxI2cTransfer: err parms! count:%hd", count);
552         return HDF_ERR_INVALID_PARAM;
553     }
554     td.msgs = msgs;
555     td.count = count;
556     td.index = 0;
557 
558     while (td.index < td.count) {
559         ret = Hi35xxI2cXferOneMsgPolling(hi35xx, &td);
560         if (ret != 0) {
561             break;
562         }
563         td.index++;
564     }
565     return (td.index > 0) ? td.index : ret;
566 }
567 
568 static const struct I2cMethod g_method = {
569     .transfer = Hi35xxI2cTransfer,
570 };
571 
Hi35xxI2cLock(struct I2cCntlr *cntlr)572 static int32_t Hi35xxI2cLock(struct I2cCntlr *cntlr)
573 {
574     struct Hi35xxI2cCntlr *hi35xx = (struct Hi35xxI2cCntlr *)cntlr;
575     if (hi35xx != NULL) {
576         return OsalSpinLockIrqSave(&hi35xx->spin, &hi35xx->irqSave);
577     }
578     return HDF_SUCCESS;
579 }
580 
Hi35xxI2cUnlock(struct I2cCntlr *cntlr)581 static void Hi35xxI2cUnlock(struct I2cCntlr *cntlr)
582 {
583     struct Hi35xxI2cCntlr *hi35xx = (struct Hi35xxI2cCntlr *)cntlr;
584     if (hi35xx != NULL) {
585         (void)OsalSpinUnlockIrqRestore(&hi35xx->spin, &hi35xx->irqSave);
586     }
587 }
588 
589 static const struct I2cLockMethod g_lockOps = {
590     .lock = Hi35xxI2cLock,
591     .unlock = Hi35xxI2cUnlock,
592 };
593 
Hi35xxI2cReadDrs(struct Hi35xxI2cCntlr *hi35xx, const struct DeviceResourceNode *node)594 static int32_t Hi35xxI2cReadDrs(struct Hi35xxI2cCntlr *hi35xx, const struct DeviceResourceNode *node)
595 {
596     int32_t ret;
597     struct DeviceResourceIface *drsOps = NULL;
598 
599     drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
600     if (drsOps == NULL || drsOps->GetUint32 == NULL) {
601         HDF_LOGE("%s: invalid drs ops fail!", __func__);
602         return HDF_FAILURE;
603     }
604 
605     ret = drsOps->GetUint32(node, "reg_pbase", &hi35xx->regBasePhy, 0);
606     if (ret != HDF_SUCCESS) {
607         HDF_LOGE("%s: read regBase fail!", __func__);
608         return ret;
609     }
610 
611     ret = drsOps->GetUint16(node, "reg_size", &hi35xx->regSize, 0);
612     if (ret != HDF_SUCCESS) {
613         HDF_LOGE("%s: read regsize fail!", __func__);
614         return ret;
615     }
616 
617     ret = drsOps->GetUint32(node, "freq", &hi35xx->freq, 0);
618     if (ret != HDF_SUCCESS) {
619         HDF_LOGE("%s: read freq fail!", __func__);
620         return ret;
621     }
622 
623     ret = drsOps->GetUint32(node, "irq", &hi35xx->irq, 0);
624     if (ret != HDF_SUCCESS) {
625         HDF_LOGE("%s: read irq fail!", __func__);
626         return ret;
627     }
628 
629     ret = drsOps->GetUint32(node, "clk", &hi35xx->clk, 0);
630     if (ret != HDF_SUCCESS) {
631         HDF_LOGE("%s: read clk fail!", __func__);
632         return ret;
633     }
634 
635     ret = drsOps->GetUint16(node, "bus", (uint16_t *)&hi35xx->bus, 0);
636     if (ret != HDF_SUCCESS) {
637         HDF_LOGE("%s: read bus fail!", __func__);
638         return ret;
639     }
640 
641     return HDF_SUCCESS;
642 }
643 
Hi35xxI2cParseAndInit(const struct DeviceResourceNode *node)644 static int32_t Hi35xxI2cParseAndInit(const struct DeviceResourceNode *node)
645 {
646     int32_t ret;
647     struct Hi35xxI2cCntlr *hi35xx = NULL;
648 
649     hi35xx = (struct Hi35xxI2cCntlr *)OsalMemCalloc(sizeof(*hi35xx));
650     if (hi35xx == NULL) {
651         HDF_LOGE("%s: malloc hi35xx fail!", __func__);
652         return HDF_ERR_MALLOC_FAIL;
653     }
654 
655     ret = Hi35xxI2cReadDrs(hi35xx, node);
656     if (ret != HDF_SUCCESS) {
657         HDF_LOGE("%s: read drs fail! ret:%d", __func__, ret);
658         goto __ERR__;
659     }
660 
661     hi35xx->regBase = OsalIoRemap(hi35xx->regBasePhy, hi35xx->regSize);
662     if (hi35xx->regBase == NULL) {
663         HDF_LOGE("%s: ioremap regBase fail!", __func__);
664         ret = HDF_ERR_IO;
665         goto __ERR__;
666     }
667 
668     ret = I2cDumperCreate(hi35xx);
669     if (ret != HDF_SUCCESS) {
670         HDF_LOGE("%s: create dumper failed:%d", __func__, ret);
671         goto __ERR__;
672     }
673 
674     Hi35xxI2cCntlrInit(hi35xx);
675 
676     hi35xx->cntlr.priv = (void *)node;
677     hi35xx->cntlr.busId = hi35xx->bus;
678     hi35xx->cntlr.ops = &g_method;
679     hi35xx->cntlr.lockOps = &g_lockOps;
680     (void)OsalSpinInit(&hi35xx->spin);
681     ret = I2cCntlrAdd(&hi35xx->cntlr);
682     if (ret != HDF_SUCCESS) {
683         HDF_LOGE("%s: add i2c controller fail:%d!", __func__, ret);
684         (void)OsalSpinDestroy(&hi35xx->spin);
685         goto __ERR__;
686     }
687 
688 #ifdef USER_VFS_SUPPORT
689     (void)I2cAddVfsById(hi35xx->cntlr.busId);
690 #endif
691     return HDF_SUCCESS;
692 __ERR__:
693     if (hi35xx != NULL) {
694         if (hi35xx->regBase != NULL) {
695             OsalIoUnmap((void *)hi35xx->regBase);
696             hi35xx->regBase = NULL;
697         }
698         OsalMemFree(hi35xx);
699         hi35xx = NULL;
700     }
701     return ret;
702 }
703 
Hi35xxI2cInit(struct HdfDeviceObject *device)704 static int32_t Hi35xxI2cInit(struct HdfDeviceObject *device)
705 {
706     int32_t ret;
707     const struct DeviceResourceNode *childNode = NULL;
708 
709     if (device == NULL || device->property == NULL) {
710         HDF_LOGE("%s: device or property is NULL", __func__);
711         return HDF_ERR_INVALID_OBJECT;
712     }
713 
714     ret = HDF_SUCCESS;
715     DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
716         ret = Hi35xxI2cParseAndInit(childNode);
717         if (ret != HDF_SUCCESS) {
718             break;
719         }
720     }
721     HDF_LOGI("%s: I2c init success!", __func__);
722     return ret;
723 }
724 
Hi35xxI2cRemoveByNode(const struct DeviceResourceNode *node)725 static void Hi35xxI2cRemoveByNode(const struct DeviceResourceNode *node)
726 {
727     int32_t ret;
728     int16_t bus;
729     struct I2cCntlr *cntlr = NULL;
730     struct Hi35xxI2cCntlr *hi35xx = NULL;
731     struct DeviceResourceIface *drsOps = NULL;
732 
733     drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
734     if (drsOps == NULL || drsOps->GetUint32 == NULL) {
735         HDF_LOGE("%s: invalid drs ops fail!", __func__);
736         return;
737     }
738 
739     ret = drsOps->GetUint16(node, "bus", (uint16_t *)&bus, 0);
740     if (ret != HDF_SUCCESS) {
741         HDF_LOGE("%s: read bus fail!", __func__);
742         return;
743     }
744 
745     I2cDumperDestroy(hi35xx);
746     cntlr = I2cCntlrGet(bus);
747     if (cntlr != NULL && cntlr->priv == node) {
748         I2cCntlrPut(cntlr);
749         I2cCntlrRemove(cntlr);
750         hi35xx = (struct Hi35xxI2cCntlr *)cntlr;
751         OsalIoUnmap((void *)hi35xx->regBase);
752         (void)OsalSpinDestroy(&hi35xx->spin);
753         OsalMemFree(hi35xx);
754     }
755     return;
756 }
757 
Hi35xxI2cRelease(struct HdfDeviceObject *device)758 static void Hi35xxI2cRelease(struct HdfDeviceObject *device)
759 {
760     const struct DeviceResourceNode *childNode = NULL;
761 
762     HDF_LOGI("%s: enter", __func__);
763 
764     if (device == NULL || device->property == NULL) {
765         HDF_LOGE("%s: device or property is NULL", __func__);
766         return;
767     }
768 
769     DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
770         Hi35xxI2cRemoveByNode(childNode);
771     }
772 }
773 
774 struct HdfDriverEntry g_i2cDriverEntry = {
775     .moduleVersion = 1,
776     .Init = Hi35xxI2cInit,
777     .Release = Hi35xxI2cRelease,
778     .moduleName = "hi35xx_i2c_driver",
779 };
780 HDF_INIT(g_i2cDriverEntry);
781