• 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:%d, count:%d, flags:%d", __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 
302     HDF_LOGE("%s: done!", __func__);
303 }
304 
Hi35xxI2cWaitRxNoempty(const struct Hi35xxI2cCntlr * hi35xx)305 static int Hi35xxI2cWaitRxNoempty(const struct Hi35xxI2cCntlr *hi35xx)
306 {
307     unsigned int timeCnt = 0;
308     unsigned int val;
309 
310     do {
311         val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_STAT);
312         if (val & STAT_RXF_NOE_MASK) {
313             return 0;
314         }
315         OsalUDelay(HI35XX_I2C_DELAY);
316     } while (timeCnt++ < I2C_TIMEOUT_COUNT);
317 
318     Hi35xxI2cRescure(hi35xx);
319     HDF_LOGE("%s:wait rx no empty timeout, RIS:0x%x, SR: 0x%x",
320         __func__, OSAL_READL(hi35xx->regBase + HI35XX_I2C_INTR_RAW), val);
321     return HDF_ERR_IO;
322 }
323 
Hi35xxI2cWaitTxNofull(const struct Hi35xxI2cCntlr * hi35xx)324 static int Hi35xxI2cWaitTxNofull(const struct Hi35xxI2cCntlr *hi35xx)
325 {
326     unsigned int timeCnt = 0;
327     unsigned int val;
328 
329     do {
330         val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_STAT);
331         if (val & STAT_TXF_NOF_MASK) {
332             return 0;
333         }
334         OsalUDelay(HI35XX_I2C_DELAY);
335     } while (timeCnt++ < I2C_TIMEOUT_COUNT);
336 
337     Hi35xxI2cRescure(hi35xx);
338     HDF_LOGE("%s: wait rx no empty timeout, RIS: 0x%x, SR: 0x%x",
339         __func__, OSAL_READL(hi35xx->regBase + HI35XX_I2C_INTR_RAW), val);
340     return HDF_ERR_IO;
341 }
342 
Hi35xxI2cWaitIdle(const struct Hi35xxI2cCntlr * hi35xx)343 static int32_t Hi35xxI2cWaitIdle(const struct Hi35xxI2cCntlr *hi35xx)
344 {
345     unsigned int timeCnt = 0;
346     unsigned int val;
347 
348     do {
349         val = OSAL_READL(hi35xx->regBase + HI35XX_I2C_INTR_RAW);
350         if (val & (INTR_ABORT_MASK)) {
351             HDF_LOGE("%s: wait idle abort!, RIS: 0x%x", __func__, val);
352             return HDF_ERR_IO;
353         }
354         if (val & INTR_CMD_DONE_MASK) {
355             return 0;
356         }
357         OsalUDelay(HI35XX_I2C_DELAY);
358     } while (timeCnt++ < I2C_WAIT_TIMEOUT);
359 
360     Hi35xxI2cRescure(hi35xx);
361     HDF_LOGE("%s: wait idle timeout, RIS: 0x%x, SR: 0x%x",
362         __func__, val, OSAL_READL(hi35xx->regBase + HI35XX_I2C_STAT));
363 
364     return HDF_ERR_IO;
365 }
366 
HdfCopyFromUser(void * to,const void * from,unsigned long n)367 static int HdfCopyFromUser(void *to, const void *from, unsigned long n)
368 {
369     int ret;
370     ret = LOS_CopyToKernel(to, n, from, n);
371     if (ret != LOS_OK) {
372         HDF_LOGE("%s: copy from kernel fail:%d", __func__, ret);
373         return HDF_FAILURE;
374     }
375     return HDF_SUCCESS;
376 }
377 
HdfCopyToUser(void * to,const void * from,unsigned long n)378 static int HdfCopyToUser(void *to, const void *from, unsigned long n)
379 {
380     int ret;
381     ret = LOS_CopyFromKernel(to, n, from, n);
382     if (ret != LOS_OK) {
383         HDF_LOGE("%s: copy from kernel fail:%d", __func__, ret);
384         return HDF_FAILURE;
385     }
386     return HDF_SUCCESS;
387 }
388 
Hi35xxI2cXferOneMsgPolling(const struct Hi35xxI2cCntlr * hi35xx,const struct Hi35xxTransferData * td)389 static int32_t Hi35xxI2cXferOneMsgPolling(const struct Hi35xxI2cCntlr *hi35xx, const struct Hi35xxTransferData *td)
390 {
391     int32_t status;
392     uint16_t bufIdx = 0;
393     uint8_t val;
394     struct I2cMsg *msg = &td->msgs[td->index];
395 
396     PLAT_LOGV("%s: msg:%p, addr:%x, flags:0x%x, len=%d", __func__, msg, msg->addr, msg->flags, msg->len);
397 
398     Hi35xxI2cEnable(hi35xx);
399     Hi35xxI2cDisableIrq(hi35xx, INTR_ALL_MASK);
400     Hi35xxI2cClrIrq(hi35xx);
401     Hi35xxI2cSetAddr(hi35xx, td);
402     Hi35xxI2cCfgCmd(hi35xx, td);
403     Hi35xxI2cStartCmd(hi35xx);
404 
405     if (msg->flags & I2C_FLAG_READ) {
406         while (bufIdx < msg->len) {
407             status = Hi35xxI2cWaitRxNoempty(hi35xx);
408             if (status) {
409                 goto end;
410             }
411             val = (uint8_t)OSAL_READL(hi35xx->regBase + HI35XX_I2C_RXF);
412             status = HdfCopyToUser((void *)&msg->buf[bufIdx], (void *)(uintptr_t)&val, sizeof(val));
413             if (status != HDF_SUCCESS) {
414                 HDF_LOGE("%s: HdfCopyFromUser fail:%d", __func__, status);
415                 goto end;
416             }
417             bufIdx++;
418         }
419     } else {
420         while (bufIdx < msg->len) {
421             status = Hi35xxI2cWaitTxNofull(hi35xx);
422             if (status) {
423                 goto end;
424             }
425             status = HdfCopyFromUser((void *)&val, (void *)(uintptr_t)&msg->buf[bufIdx], sizeof(val));
426             if (status != HDF_SUCCESS) {
427                 HDF_LOGE("%s: copy to kernel fail:%d", __func__, status);
428                 goto end;
429             }
430             OSAL_WRITEL((unsigned int)val, hi35xx->regBase + HI35XX_I2C_TXF);
431             bufIdx++;
432         }
433     }
434 
435     status = Hi35xxI2cWaitIdle(hi35xx);
436 end:
437     Hi35xxI2cDisable(hi35xx);
438 
439     return status;
440 }
441 
Hi35xxI2cCntlrInit(struct Hi35xxI2cCntlr * hi35xx)442 static void Hi35xxI2cCntlrInit(struct Hi35xxI2cCntlr *hi35xx)
443 {
444     Hi35xxI2cHwInitCfg(hi35xx);
445     Hi35xxI2cDisable(hi35xx);
446     Hi35xxI2cDisableIrq(hi35xx, INTR_ALL_MASK);
447     Hi35xxI2cSetFreq(hi35xx);
448     Hi35xxI2cSetWater(hi35xx);
449     HDF_LOGI("%s: cntlr:%u init done!", __func__, hi35xx->bus);
450 }
451 
Hi35xxI2cTransfer(struct I2cCntlr * cntlr,struct I2cMsg * msgs,int16_t count)452 static int32_t Hi35xxI2cTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count)
453 {
454     int32_t ret = HDF_SUCCESS;
455     struct Hi35xxI2cCntlr *hi35xx = NULL;
456     struct Hi35xxTransferData td;
457 
458     if (cntlr == NULL || cntlr->priv == NULL) {
459         HDF_LOGE("Hi35xxI2cTransfer: cntlr lor hi35xxis null!");
460         return HDF_ERR_INVALID_OBJECT;
461     }
462     hi35xx = (struct Hi35xxI2cCntlr *)cntlr;
463 
464     if (msgs == NULL || count <= 0) {
465         HDF_LOGE("Hi35xxI2cTransfer: err parms! count:%d", count);
466         return HDF_ERR_INVALID_PARAM;
467     }
468     td.msgs = msgs;
469     td.count = count;
470     td.index = 0;
471 
472     while (td.index < td.count) {
473         ret = Hi35xxI2cXferOneMsgPolling(hi35xx, &td);
474         if (ret != 0) {
475             break;
476         }
477         td.index++;
478     }
479     return (td.index > 0) ? td.index : ret;
480 }
481 
482 static const struct I2cMethod g_method = {
483     .transfer = Hi35xxI2cTransfer,
484 };
485 
Hi35xxI2cLock(struct I2cCntlr * cntlr)486 static int32_t Hi35xxI2cLock(struct I2cCntlr *cntlr)
487 {
488     struct Hi35xxI2cCntlr *hi35xx = (struct Hi35xxI2cCntlr *)cntlr;
489     if (hi35xx != NULL) {
490         return OsalSpinLockIrqSave(&hi35xx->spin, &hi35xx->irqSave);
491     }
492     return HDF_SUCCESS;
493 }
494 
Hi35xxI2cUnlock(struct I2cCntlr * cntlr)495 static void Hi35xxI2cUnlock(struct I2cCntlr *cntlr)
496 {
497     struct Hi35xxI2cCntlr *hi35xx = (struct Hi35xxI2cCntlr *)cntlr;
498     if (hi35xx != NULL) {
499         (void)OsalSpinUnlockIrqRestore(&hi35xx->spin, &hi35xx->irqSave);
500     }
501 }
502 
503 static const struct I2cLockMethod g_lockOps = {
504     .lock = Hi35xxI2cLock,
505     .unlock = Hi35xxI2cUnlock,
506 };
507 
Hi35xxI2cReadDrs(struct Hi35xxI2cCntlr * hi35xx,const struct DeviceResourceNode * node)508 static int32_t Hi35xxI2cReadDrs(struct Hi35xxI2cCntlr *hi35xx, const struct DeviceResourceNode *node)
509 {
510     int32_t ret;
511     struct DeviceResourceIface *drsOps = NULL;
512 
513     drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
514     if (drsOps == NULL || drsOps->GetUint32 == NULL) {
515         HDF_LOGE("%s: invalid drs ops fail!", __func__);
516         return HDF_FAILURE;
517     }
518 
519     ret = drsOps->GetUint32(node, "reg_pbase", &hi35xx->regBasePhy, 0);
520     if (ret != HDF_SUCCESS) {
521         HDF_LOGE("%s: read regBase fail!", __func__);
522         return ret;
523     }
524 
525     ret = drsOps->GetUint16(node, "reg_size", &hi35xx->regSize, 0);
526     if (ret != HDF_SUCCESS) {
527         HDF_LOGE("%s: read regsize fail!", __func__);
528         return ret;
529     }
530 
531     ret = drsOps->GetUint32(node, "freq", &hi35xx->freq, 0);
532     if (ret != HDF_SUCCESS) {
533         HDF_LOGE("%s: read freq fail!", __func__);
534         return ret;
535     }
536 
537     ret = drsOps->GetUint32(node, "irq", &hi35xx->irq, 0);
538     if (ret != HDF_SUCCESS) {
539         HDF_LOGE("%s: read irq fail!", __func__);
540         return ret;
541     }
542 
543     ret = drsOps->GetUint32(node, "clk", &hi35xx->clk, 0);
544     if (ret != HDF_SUCCESS) {
545         HDF_LOGE("%s: read clk fail!", __func__);
546         return ret;
547     }
548 
549     ret = drsOps->GetUint16(node, "bus", (uint16_t *)&hi35xx->bus, 0);
550     if (ret != HDF_SUCCESS) {
551         HDF_LOGE("%s: read bus fail!", __func__);
552         return ret;
553     }
554 
555     return HDF_SUCCESS;
556 }
557 
Hi35xxI2cParseAndInit(struct HdfDeviceObject * device,const struct DeviceResourceNode * node)558 static int32_t Hi35xxI2cParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)
559 {
560     int32_t ret;
561     struct Hi35xxI2cCntlr *hi35xx = NULL;
562     (void)device;
563 
564     hi35xx = (struct Hi35xxI2cCntlr *)OsalMemCalloc(sizeof(*hi35xx));
565     if (hi35xx == NULL) {
566         HDF_LOGE("%s: malloc hi35xx fail!", __func__);
567         return HDF_ERR_MALLOC_FAIL;
568     }
569 
570     ret = Hi35xxI2cReadDrs(hi35xx, node);
571     if (ret != HDF_SUCCESS) {
572         HDF_LOGE("%s: read drs fail! ret:%d", __func__, ret);
573         goto __ERR__;
574     }
575 
576     hi35xx->regBase = OsalIoRemap(hi35xx->regBasePhy, hi35xx->regSize);
577     if (hi35xx->regBase == NULL) {
578         HDF_LOGE("%s: ioremap regBase fail!", __func__);
579         ret = HDF_ERR_IO;
580         goto __ERR__;
581     }
582 
583     Hi35xxI2cCntlrInit(hi35xx);
584 
585     hi35xx->cntlr.priv = (void *)node;
586     hi35xx->cntlr.busId = hi35xx->bus;
587     hi35xx->cntlr.ops = &g_method;
588     hi35xx->cntlr.lockOps = &g_lockOps;
589     (void)OsalSpinInit(&hi35xx->spin);
590     ret = I2cCntlrAdd(&hi35xx->cntlr);
591     if (ret != HDF_SUCCESS) {
592         HDF_LOGE("%s: add i2c controller fail:%d!", __func__, ret);
593         (void)OsalSpinDestroy(&hi35xx->spin);
594         goto __ERR__;
595     }
596 
597 #ifdef USER_VFS_SUPPORT
598     (void)I2cAddVfsById(hi35xx->cntlr.busId);
599 #endif
600     return HDF_SUCCESS;
601 __ERR__:
602     if (hi35xx != NULL) {
603         if (hi35xx->regBase != NULL) {
604             OsalIoUnmap((void *)hi35xx->regBase);
605             hi35xx->regBase = NULL;
606         }
607         OsalMemFree(hi35xx);
608         hi35xx = NULL;
609     }
610     return ret;
611 }
612 
Hi35xxI2cInit(struct HdfDeviceObject * device)613 static int32_t Hi35xxI2cInit(struct HdfDeviceObject *device)
614 {
615     int32_t ret;
616     const struct DeviceResourceNode *childNode = NULL;
617 
618     HDF_LOGE("%s: Enter", __func__);
619     if (device == NULL || device->property == NULL) {
620         HDF_LOGE("%s: device or property is NULL", __func__);
621         return HDF_ERR_INVALID_OBJECT;
622     }
623 
624     ret = HDF_SUCCESS;
625     DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
626         ret = Hi35xxI2cParseAndInit(device, childNode);
627         if (ret != HDF_SUCCESS) {
628             break;
629         }
630     }
631 
632     return ret;
633 }
634 
Hi35xxI2cRemoveByNode(const struct DeviceResourceNode * node)635 static void Hi35xxI2cRemoveByNode(const struct DeviceResourceNode *node)
636 {
637     int32_t ret;
638     int16_t bus;
639     struct I2cCntlr *cntlr = NULL;
640     struct Hi35xxI2cCntlr *hi35xx = NULL;
641     struct DeviceResourceIface *drsOps = NULL;
642 
643     drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
644     if (drsOps == NULL || drsOps->GetUint32 == NULL) {
645         HDF_LOGE("%s: invalid drs ops fail!", __func__);
646         return;
647     }
648 
649     ret = drsOps->GetUint16(node, "bus", (uint16_t *)&bus, 0);
650     if (ret != HDF_SUCCESS) {
651         HDF_LOGE("%s: read bus fail!", __func__);
652         return;
653     }
654 
655     cntlr = I2cCntlrGet(bus);
656     if (cntlr != NULL && cntlr->priv == node) {
657         I2cCntlrPut(cntlr);
658         I2cCntlrRemove(cntlr);
659         hi35xx = (struct Hi35xxI2cCntlr *)cntlr;
660         OsalIoUnmap((void *)hi35xx->regBase);
661         (void)OsalSpinDestroy(&hi35xx->spin);
662         OsalMemFree(hi35xx);
663     }
664     return;
665 }
666 
Hi35xxI2cRelease(struct HdfDeviceObject * device)667 static void Hi35xxI2cRelease(struct HdfDeviceObject *device)
668 {
669     const struct DeviceResourceNode *childNode = NULL;
670 
671     HDF_LOGI("%s: enter", __func__);
672 
673     if (device == NULL || device->property == NULL) {
674         HDF_LOGE("%s: device or property is NULL", __func__);
675         return;
676     }
677 
678     DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
679         Hi35xxI2cRemoveByNode(childNode);
680     }
681 }
682 
683 struct HdfDriverEntry g_i2cDriverEntry = {
684     .moduleVersion = 1,
685     .Init = Hi35xxI2cInit,
686     .Release = Hi35xxI2cRelease,
687     .moduleName = "hi35xx_i2c_driver",
688 };
689 HDF_INIT(g_i2cDriverEntry);
690