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