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