1 /*
2 * Copyright (C) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18 #include <linux/module.h>
19 #include <linux/version.h>
20 #include "securec.h"
21 #include "hi_log.h"
22 #include "drv_i2c.h"
23 #include "hi_drv_i2c.h"
24 #include "hi_drv_gpioi2c.h"
25 #include "drv_i2c_ioctl.h"
26 #include "hi_common.h"
27 #include "hi_module.h"
28 #include "hi_osal.h"
29
30 #define i2c_write_reg(Addr, Value) ((*(volatile hi_u32 *)(Addr)) = (Value))
31 #define i2c_read_reg(Addr) (*(volatile hi_u32 *)(Addr))
32
33 static osal_dev g_i2c_register_data;
34 static unsigned int g_i2c_id = 0;
35 static gpio_i2c_ext_func *g_pst_gpio_i2c_ext_funcs = HI_NULL;
36
37 #ifdef HI_GPIOI2C_SUPPORT
38 extern i2c_gpio g_st_i2c_gpio[HI_I2C_MAX_NUM];
39 #endif
40
41 typedef struct {
42 hi_u32 i2c_no;
43 hi_u32 dev_addr;
44 hi_u32 reg_addr;
45 hi_u32 reg_addr_len;
46 hi_u32 data_len;
47 } i2c_msg;
48
49 typedef struct {
50 hi_u8 send_data[32]; // 发送数据缓存长度32
51 hi_u32 len;
52 } send_msg;
53
i2c_drv_proc_help(hi_void)54 static hi_void i2c_drv_proc_help(hi_void)
55 {
56 HI_PRINT("\nUsage:\n");
57 HI_PRINT("Read data: echo read 'bus' 'device address'\
58 'Register address' 'Register address length' > /proc/msp/i2c\n");
59 HI_PRINT("Write one Byte data: echo write 'bus'\
60 'device address' 'Register address' 'Register address length' 'data' > /proc/msp/i2c\n");
61 HI_PRINT("Write more Byte data:echo write 'bus' 'device address' 'Register address' 'Register address length'\
62 'data number n(n<=32)' 'data1' ...'datan' > /proc/msp/i2c\n");
63 HI_PRINT("Set Standard i2c rate: echo setrate 'bus'\
64 'rate' > /proc/msp/i2c .such as:echo setrate 1 100000 > /proc/msp/i2c\n");
65 HI_PRINT("Look over i2c info: cat /proc/msp/i2c\n");
66 }
67
i2c_drv_proc_help_print(unsigned int argc,char (* argv)[PROC_CMD_SINGEL_LENGTH_MAX],hi_void * private)68 static hi_s32 i2c_drv_proc_help_print(unsigned int argc,
69 char (*argv)[PROC_CMD_SINGEL_LENGTH_MAX], hi_void *private)
70 {
71 i2c_drv_proc_help();
72 return HI_SUCCESS;
73 }
74
i2c_proc_read(hi_void * p,hi_void * v)75 hi_s32 i2c_proc_read(hi_void *p, hi_void *v)
76 {
77 hi_u8 ii = 0;
78 hi_s32 i2c_rate = 0;
79 if (p == HI_NULL) {
80 HI_PRINT("p pointer is null\n");
81 return HI_FAILURE;
82 }
83
84 osal_proc_print(p, "---------Hisilicon Standard I2C Info---------\n");
85 osal_proc_print(p, "No. Rate\n");
86
87 for (ii = 0; ii < HI_STD_I2C_NUM; ii++) {
88 i2c_rate = i2c_drv_get_rate(ii);
89 osal_proc_print(p, "%hhu %d\n", ii, i2c_rate);
90 }
91
92 #ifdef HI_GPIOI2C_SUPPORT
93 osal_proc_print(p, "---------Hisilicon GPIO simulate I2C Info---------\n");
94 osal_proc_print(p, "No. SCL_IO SDA_IO\n");
95 for (ii = 0; ii < HI_I2C_MAX_NUM; ii++) {
96 if (g_st_i2c_gpio[ii].b_used) {
97 osal_proc_print(p, "%d %d %d\n", g_st_i2c_gpio[ii].i2c_num,
98 g_st_i2c_gpio[ii].scl_gpio_no, g_st_i2c_gpio[ii].sda_gpio_no);
99 }
100 }
101 #endif
102
103 return HI_SUCCESS;
104 }
105
i2c_proc_wr_set_rate(unsigned int arg_count,char (* argv)[PROC_CMD_SINGEL_LENGTH_MAX],hi_void * private)106 hi_s32 i2c_proc_wr_set_rate(unsigned int arg_count,
107 char (*argv)[PROC_CMD_SINGEL_LENGTH_MAX], hi_void *private)
108 {
109 hi_u32 i2c_no;
110 hi_u32 rate;
111
112 if (arg_count < 3) { // 至少是3个参数 setrate、i2c_no和rate
113 i2c_drv_proc_help();
114 return HI_FAILURE;
115 }
116
117 i2c_no = (hi_u32)osal_strtoul(argv[1], NULL, 10); // 命令的第1个参数 字符串转成10进制整数,获取i2c口编号
118 rate = (hi_u32)osal_strtoul(argv[2], NULL, 10); // 命令的第2个参数 字符串转成10进制整数
119
120 if (i2c_no >= HI_STD_I2C_NUM) {
121 HI_LOG_ERR("I2c NO.%u not support rate setting!\n", i2c_no);
122 return HI_FAILURE;
123 }
124 i2c_drv_set_rate(i2c_no, rate);
125 return HI_SUCCESS;
126 }
127
i2c_proc_wr_read_get_dev_msg(hi_u8 arg_count,char (* argv)[PROC_CMD_SINGEL_LENGTH_MAX],i2c_msg * p_data)128 static hi_s32 i2c_proc_wr_read_get_dev_msg(hi_u8 arg_count,
129 char (*argv)[PROC_CMD_SINGEL_LENGTH_MAX], i2c_msg *p_data)
130 {
131 if ((p_data == HI_NULL) || (argv == HI_NULL)) {
132 HI_PRINT("error param!!!\n");
133 return HI_FAILURE;
134 }
135
136 if (arg_count < 5) { // 至少是5个参数
137 i2c_drv_proc_help();
138 return HI_FAILURE;
139 }
140
141 p_data->i2c_no = (hi_u32)osal_strtoul(argv[1], NULL, 16); // 命令的第1个参数 字符串转成16进制的正整数
142 p_data->dev_addr = (hi_u32)osal_strtoul(argv[2], NULL, 16); // 命令的第2个参数 字符串转成16进制的正整数
143 p_data->reg_addr = (hi_u32)osal_strtoul(argv[3], NULL, 16); // 命令的第3个参数 字符串转成16进制的正整数
144 p_data->reg_addr_len = (hi_u32)osal_strtoul(argv[4], NULL, 16); // 命令的第4个参数 字符串转成16进制的正整数
145 p_data->data_len = (hi_u32)osal_strtoul(argv[5], NULL, 16); // 命令的第5个参数 字符串转成16进制的正整数
146
147 hi_dbg_print_s32(p_data->i2c_no);
148 hi_dbg_print_h32(p_data->dev_addr);
149 hi_dbg_print_h32(p_data->reg_addr);
150 hi_dbg_print_s32(p_data->reg_addr_len);
151 hi_dbg_print_s32(p_data->data_len);
152
153 return HI_SUCCESS;
154 }
155
i2c_proc_wr_read(unsigned int arg_count,char (* argv)[PROC_CMD_SINGEL_LENGTH_MAX],hi_void * private)156 static hi_s32 i2c_proc_wr_read(unsigned int arg_count,
157 char (*argv)[PROC_CMD_SINGEL_LENGTH_MAX], hi_void *private)
158 {
159 i2c_msg i2c_dev_msg = {0};
160 hi_s32 ret;
161 hi_u32 i = 0;
162 hi_u8 p_data[32] = {0}; // 数据发送缓冲区长度32
163 hi_bool b_used = HI_FALSE;
164 hi_bool b_temp = HI_FALSE;
165
166 ret = i2c_proc_wr_read_get_dev_msg(arg_count, argv, &i2c_dev_msg);
167 if (ret != HI_SUCCESS) {
168 HI_PRINT("i2c_proc_wr_read_get_dev_msg is failed!!!\n");
169 return ret;
170 }
171
172 HI_I2C_ERR_PRINT(i2c_dev_msg.data_len >= sizeof(p_data), ret, "data len is too long\n\n");
173
174 if ((i2c_dev_msg.i2c_no) < HI_STD_I2C_NUM) {
175 ret = hi_drv_i2c_read(i2c_dev_msg.i2c_no, (hi_u8)(i2c_dev_msg.dev_addr), \
176 i2c_dev_msg.reg_addr, i2c_dev_msg.reg_addr_len, p_data, i2c_dev_msg.data_len);
177
178 HI_I2C_ERR_PRINT(ret != HI_SUCCESS, ret, "Read failed\n\n");
179
180 HI_PRINT("Read Data: \n");
181
182 for (i = 0; i < i2c_dev_msg.data_len; i++) {
183 HI_PRINT("0x%02x \n", p_data[i]);
184 }
185
186 HI_PRINT("\n");
187 }
188 else {
189 if (g_pst_gpio_i2c_ext_funcs == HI_NULL) {
190 ret = osal_exportfunc_get(HI_ID_GPIO_I2C, (hi_void **)&g_pst_gpio_i2c_ext_funcs);
191 b_temp = (ret != HI_SUCCESS) || (g_pst_gpio_i2c_ext_funcs == HI_NULL);
192
193 HI_I2C_ERR_PRINT(b_temp, ret, "GPIO_I2C Function ERR: ret:0x%08x, func:%p\n",
194 ret, g_pst_gpio_i2c_ext_funcs);
195 }
196
197 b_temp = g_pst_gpio_i2c_ext_funcs && g_pst_gpio_i2c_ext_funcs->pfn_gpio_i2c_is_used;
198 HI_I2C_INFO_PRINT(!b_temp, ret, "Read failed(I2cNum=%d not valid)! \n", i2c_dev_msg.i2c_no);
199
200 ret = g_pst_gpio_i2c_ext_funcs->pfn_gpio_i2c_is_used(i2c_dev_msg.i2c_no, &b_used);
201
202 b_temp = (ret == HI_SUCCESS) && (b_used == HI_TRUE);
203 HI_I2C_INFO_PRINT(!b_temp, ret, "Read failed(I2cNum=%d not valid)! \n", i2c_dev_msg.i2c_no);
204
205 if (g_pst_gpio_i2c_ext_funcs->pfn_gpio_i2c_read_ext) {
206 ret = g_pst_gpio_i2c_ext_funcs->pfn_gpio_i2c_read_ext(i2c_dev_msg.i2c_no, i2c_dev_msg.dev_addr, \
207 i2c_dev_msg.reg_addr, i2c_dev_msg.reg_addr_len, \
208 p_data, i2c_dev_msg.data_len);
209
210 HI_I2C_ERR_PRINT(ret != HI_SUCCESS, ret, "Read failed\n");
211
212 HI_PRINT("Read Data: \n");
213
214 for (i = 0; i < i2c_dev_msg.data_len; i++) {
215 HI_PRINT("0x%02x \n", p_data[i]);
216 }
217
218 HI_PRINT("\n");
219 }
220 }
221 return ret;
222 }
223
i2c_proc_wr_write_get_dev_msg(hi_u8 arg_count,char (* argv)[PROC_CMD_SINGEL_LENGTH_MAX],send_msg * send,i2c_msg * p_data)224 static hi_s32 i2c_proc_wr_write_get_dev_msg(hi_u8 arg_count, char (*argv)[PROC_CMD_SINGEL_LENGTH_MAX],
225 send_msg *send, i2c_msg *p_data)
226 {
227 hi_u32 val;
228 hi_u32 i = 0;
229 hi_bool b_temp = HI_FALSE;
230
231 if ((p_data == HI_NULL) || (argv == HI_NULL)) {
232 HI_PRINT("error param!!!\n");
233 return HI_FAILURE;
234 }
235
236 if (arg_count < 6) { // 至少是6个参数
237 i2c_drv_proc_help();
238 return HI_FAILURE;
239 }
240
241 p_data->i2c_no = (hi_u32)osal_strtoul(argv[1], NULL, 16); // 命令的第1个参数 字符串转成16进制的正整数
242 p_data->dev_addr = (hi_u32)osal_strtoul(argv[2], NULL, 16); // 命令的第2个参数 字符串转成16进制的正整数
243 p_data->reg_addr = (hi_u32)osal_strtoul(argv[3], NULL, 16); // 命令的第3个参数 字符串转成16进制的正整数
244 p_data->reg_addr_len = (hi_u32)osal_strtoul(argv[4], NULL, 16); // 命令的第4个参数 字符串转成16进制的正整数
245 val = (hi_u32)osal_strtoul(argv[5], NULL, 16); // 命令的第5个参数 字符串转成16进制的正整数
246
247 if (arg_count > 6) { // 第6个参数开始是数据
248 b_temp = (val != (arg_count - 6)) || ((arg_count - 6) > sizeof(send->send_data)); // 表示第6个参数开始是数据
249
250 if (b_temp) {
251 i2c_drv_proc_help();
252 return HI_FAILURE;
253 }
254
255 for (i = 0; i < val; i++) {
256 send->send_data[i] =
257 (hi_u8)osal_strtoul(argv[6 + i], NULL, 16); /* 第6个参数开始是数据 字符串转成16进制的正整数 */
258 hi_dbg_print_s32(send->send_data[i]);
259 }
260
261 send->len = val;
262 } else {
263 send->send_data[0] = val;
264 send->len = 1;
265 }
266
267 HI_PRINT("Write: \n");
268 hi_dbg_print_s32(p_data->i2c_no);
269 hi_dbg_print_h32(p_data->dev_addr);
270 hi_dbg_print_h32(p_data->reg_addr);
271 hi_dbg_print_s32(send->len);
272
273 return HI_SUCCESS;
274 }
275
i2c_proc_wr_write(unsigned int arg_count,char (* argv)[PROC_CMD_SINGEL_LENGTH_MAX],hi_void * private)276 hi_s32 i2c_proc_wr_write(unsigned int arg_count,
277 char (*argv)[PROC_CMD_SINGEL_LENGTH_MAX], hi_void *private)
278 {
279 hi_s32 ret;
280 hi_bool b_temp = HI_FALSE;
281 hi_bool b_used = HI_FALSE;
282
283 send_msg send = {0};
284 i2c_msg i2c_dev_msg = {0};
285
286 ret = i2c_proc_wr_write_get_dev_msg(arg_count, argv, &send, &i2c_dev_msg);
287 if (ret != HI_SUCCESS) {
288 HI_PRINT("i2c_proc_wr_write_get_dev_msg is failed!!!\n");
289 return ret;
290 }
291
292 if (i2c_dev_msg.i2c_no < HI_STD_I2C_NUM) {
293 ret = hi_drv_i2c_write(i2c_dev_msg.i2c_no, (hi_u8)(i2c_dev_msg.dev_addr), \
294 i2c_dev_msg.reg_addr, i2c_dev_msg.reg_addr_len, send.send_data, send.len);
295 HI_I2C_ERR_PRINT(ret != HI_SUCCESS, ret, "Write failed\n\n");
296 }
297 else {
298 if (g_pst_gpio_i2c_ext_funcs == HI_NULL) {
299 ret = osal_exportfunc_get(HI_ID_GPIO_I2C, (hi_void **)&g_pst_gpio_i2c_ext_funcs);
300
301 b_temp = (ret != HI_SUCCESS) || (g_pst_gpio_i2c_ext_funcs == HI_NULL);
302
303 HI_I2C_ERR_PRINT(b_temp, ret, "GPIO_I2C Function ERR: ret:0x%08x, func:%p\n",
304 ret, g_pst_gpio_i2c_ext_funcs);
305 }
306
307 b_temp = g_pst_gpio_i2c_ext_funcs && g_pst_gpio_i2c_ext_funcs->pfn_gpio_i2c_is_used;
308 HI_I2C_INFO_PRINT(!b_temp, ret, "Write failed(I2cNum=%d not valid)! \n", i2c_dev_msg.i2c_no);
309
310 ret = g_pst_gpio_i2c_ext_funcs->pfn_gpio_i2c_is_used(i2c_dev_msg.i2c_no, &b_used);
311
312 b_temp = (ret == HI_SUCCESS) && (b_used == HI_TRUE);
313
314 HI_I2C_INFO_PRINT(!b_temp, ret, "Write failed(I2cNum=%d not valid)! \n", i2c_dev_msg.i2c_no);
315
316 if (g_pst_gpio_i2c_ext_funcs->pfn_gpio_i2c_write_ext) {
317 ret = g_pst_gpio_i2c_ext_funcs->pfn_gpio_i2c_write_ext(i2c_dev_msg.i2c_no, i2c_dev_msg.dev_addr, \
318 i2c_dev_msg.reg_addr, i2c_dev_msg.reg_addr_len,
319 send.send_data, send.len);
320
321 HI_I2C_ERR_PRINT(ret != HI_SUCCESS, ret, "Write failed(Ret:0x%x)\n\n", ret);
322 }
323 }
324 return ret;
325 }
326
327 static osal_pmops g_i2c_pmops = {
328 .pm_lowpower_enter = i2c_drv_lowpower_enter,
329 .pm_lowpower_exit = i2c_drv_lowpower_exit,
330 .pm_poweroff = NULL,
331 .pm_suspend = i2c_pm_suspend,
332 .pm_resume = i2c_pm_resume,
333 };
334
335
i2c_open(hi_void * private_data)336 hi_s32 i2c_open(hi_void *private_data)
337 {
338 hi_s32 ret;
339
340 ret = osal_exportfunc_get(HI_ID_GPIO_I2C, (hi_void **)&g_pst_gpio_i2c_ext_funcs);
341 if ((ret != HI_SUCCESS) || (g_pst_gpio_i2c_ext_funcs == HI_NULL)) {
342 HI_LOG_INFO("Get GPIO_I2C Function ERR: ret:0x%08x, func:0x%08x\n", ret, g_pst_gpio_i2c_ext_funcs);
343 }
344 return HI_SUCCESS;
345 }
346
i2c_close(hi_void * private_data)347 hi_s32 i2c_close(hi_void *private_data)
348 {
349 return HI_SUCCESS;
350 }
351
352 static osal_ioctl_cmd g_i2c_ioctl_info[] = {
353 {CMD_I2C_WRITE, hi_drv_i2c_cmd_write},
354 {CMD_I2C_READ, hi_drv_i2c_cmd_read},
355 {CMD_I2C_SET_RATE, hi_drv_i2c_cmd_set_rate},
356 {CMD_I2C_CONFIG, hi_drv_gpioi2c_cmd_config},
357 {CMD_I2C_DESTROY, hi_drv_gpioi2c_cmd_destroy},
358 {CMD_I2C_READ_DIRECT, hi_drv_i2c_cmd_read}
359 };
360
361 static osal_proc_cmd g_i2c_proc_cmd[] = {
362 {"help", i2c_drv_proc_help_print},
363 {"read", i2c_proc_wr_read},
364 {"write", i2c_proc_wr_write},
365 {"setrate", i2c_proc_wr_set_rate},
366 };
367
368
369 static osal_fileops g_i2c_fops = {
370 .open = i2c_open,
371 .release = i2c_close,
372 .cmd_list = g_i2c_ioctl_info,
373 .cmd_cnt = 0,
374 };
375
i2c_drv_proc_add(hi_void)376 hi_s32 i2c_drv_proc_add(hi_void)
377 {
378 osal_proc_entry *i2c_proc_entry;
379
380 g_i2c_id = HI_ID_I2C;
381
382 i2c_proc_entry = osal_proc_add(HI_MOD_I2C, strlen(HI_MOD_I2C));
383 if (i2c_proc_entry == HI_NULL) {
384 HI_LOG_ERR("I2C add proc failed!\n");
385 return HI_FAILURE;
386 }
387
388 i2c_proc_entry->read = i2c_proc_read;
389 i2c_proc_entry->cmd_cnt = sizeof(g_i2c_proc_cmd) / sizeof(osal_proc_cmd);
390 i2c_proc_entry->cmd_list = g_i2c_proc_cmd;
391 i2c_proc_entry->private = &g_i2c_id;
392
393 return HI_SUCCESS;
394 }
395
396
i2c_drv_mod_init(hi_void)397 hi_s32 i2c_drv_mod_init(hi_void)
398 {
399 hi_s32 ret;
400 /*
401 HI_MCE_SUPPORT=yes or HI_MCE_SUPPORT=no, all will call hi_drv_i2c_init,
402 make sure HI_i2c_open call it
403 */
404 if (hi_drv_i2c_init() != HI_SUCCESS) {
405 HI_LOG_FATAL("i2c init failed.\n");
406 return HI_FAILURE;
407 }
408
409 g_i2c_fops.cmd_cnt = sizeof(g_i2c_ioctl_info) / sizeof(osal_ioctl_cmd);
410 HI_LOG_INFO("g_i2c_fops cmd_cnt = %d\n", g_i2c_fops.cmd_cnt);
411
412 /* I2C driver register */
413 ret = snprintf_s(g_i2c_register_data.name, sizeof(g_i2c_register_data.name),
414 sizeof(g_i2c_register_data.name) - 1, UMAP_DEVNAME_I2C);
415 if (ret < 0) {
416 HI_LOG_ERR("secure func call error\n");
417 return HI_FAILURE;
418 }
419 g_i2c_register_data.minor = UMAP_MIN_MINOR_I2C;
420 g_i2c_register_data.fops = &g_i2c_fops;
421 g_i2c_register_data.pmops = &g_i2c_pmops;
422 if (osal_dev_register(&g_i2c_register_data) < 0) {
423 HI_LOG_FATAL("register I2C failed.\n");
424 return HI_FAILURE;
425 }
426
427 /* register i2c PROC function */
428 ret = i2c_drv_proc_add();
429 if (ret != HI_SUCCESS) {
430 HI_LOG_INFO("add I2C proc failed.\n");
431 osal_dev_unregister(&g_i2c_register_data);
432 return HI_FAILURE;
433 }
434
435 #if defined(MODULE) || defined(CFG_HI_USER_DRV)
436 HI_PRINT("Load hi_i2c.ko success. \t(%s)\n", VERSION_STRING);
437 #endif
438 return 0;
439 }
440
i2c_drv_mod_exit(hi_void)441 hi_void i2c_drv_mod_exit(hi_void)
442 {
443 osal_proc_remove(HI_MOD_I2C, strlen(HI_MOD_I2C));
444 osal_dev_unregister(&g_i2c_register_data);
445
446 hi_drv_i2c_de_init();
447
448 return;
449 }
450
451 #if defined(MODULE) || defined(CFG_HI_USER_DRV)
452 module_init(i2c_drv_mod_init);
453 module_exit(i2c_drv_mod_exit);
454 #endif
455
456 MODULE_LICENSE("GPL");
457 MODULE_DESCRIPTION("HISILICON");
458
459