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