• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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