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