blob: c761476ff0761ae146a5b1e2a4005cb2af4b26be [file] [log] [blame]
liubin281ac462023-07-19 14:22:54 +08001/**
2 * \file gpio-test.c
3 * \brief A Documented file.
4 *
5 * Detailed description
6 * \Author: Sniper <js.wang@mobiletek.cn>
7 * \Version: 1.0.0
8 * \Date: 2022-04-26
9 */
10
11#include <stdio.h>
12#include <string.h>
13#include <sys/types.h>
14#include <sys/stat.h>
15#include <fcntl.h>
16#include <errno.h>
17#include <limits.h>
18#include <sys/wait.h>
19#include <unistd.h>
20#include <sys/mount.h>
21#include "mbtk_log.h"
22#include <sys/mman.h>
23#include <ctype.h>
24#include <cutils/properties.h>
25#include "gpio-define.h"
26
27#define gpio_log(...) if(gpio_debug)printf(__VA_ARGS__)
28
29static int gpio_debug = 0;
30
31struct gpio_register_function gpio_func_register[128] = {
32 {GPIO_FUNC_GPIO_00, 0},
33 {GPIO_FUNC_GPIO_01, 0},
34 {GPIO_FUNC_GPIO_02, 0},
35 {GPIO_FUNC_GPIO_03, 0},
36 {GPIO_FUNC_GPIO_04, 0},
37 {GPIO_FUNC_GPIO_05, 0},
38 {GPIO_FUNC_GPIO_06, 0},
39 {GPIO_FUNC_GPIO_07, 0},
40 {GPIO_FUNC_GPIO_08, 0},
41 {GPIO_FUNC_GPIO_09, 0},
42 {GPIO_FUNC_GPIO_10, 0},
43 {GPIO_FUNC_GPIO_11, 0},
44 {GPIO_FUNC_GPIO_12, 0},
45 {GPIO_FUNC_GPIO_13, 0},
46 {GPIO_FUNC_GPIO_14, 0},
47 {GPIO_FUNC_GPIO_15, 0},
48 {GPIO_FUNC_GPIO_16, 0},
49 {GPIO_FUNC_GPIO_17, 0},
50 {GPIO_FUNC_GPIO_18, 0},
51 {GPIO_FUNC_GPIO_19, 0},
52 {GPIO_FUNC_GPIO_20, 0},
53 {GPIO_FUNC_GPIO_21, 0},
54 {GPIO_FUNC_GPIO_22, 0},
55 {GPIO_FUNC_GPIO_23, 0},
56 {GPIO_FUNC_GPIO_24, 0},
57 {GPIO_FUNC_GPIO_25, 0},
58 {GPIO_FUNC_GPIO_26, 0},
59 {GPIO_FUNC_GPIO_27, 0},
60 {GPIO_FUNC_GPIO_28, 0},
61 {GPIO_FUNC_GPIO_29, 0},
62 {GPIO_FUNC_GPIO_30, 0},
63 {GPIO_FUNC_GPIO_31, 0},
64 {GPIO_FUNC_GPIO_32, 0},
65 {GPIO_FUNC_GPIO_33, 0},
66 {GPIO_FUNC_GPIO_34, 0},
67 {GPIO_FUNC_GPIO_35, 0},
68 {GPIO_FUNC_GPIO_36, 0},
69 {GPIO_FUNC_MMC1_DAT3, 5}, // GPIO_37
70 {GPIO_FUNC_MMC1_DAT2, 5}, // GPIO_38
71 {GPIO_FUNC_MMC1_DAT1, 5}, // GPIO_39
72 {GPIO_FUNC_MMC1_DAT0, 5}, // GPIO_40
73 {GPIO_FUNC_MMC1_CMD, 5}, //GPIO_41
74 {GPIO_FUNC_MMC1_CLK, 5}, //GPIO_42
75 {GPIO_FUNC_MMC1_CD , 1}, //GPIO_43
76 {0,0},{0,0},{0,0},{0,0},
77 {GPIO_FUNC_SDIO_DAT3, 1}, //GPIO_48
78 {GPIO_FUNC_GPIO_49, 0},
79 {GPIO_FUNC_GPIO_50, 0},
80 {GPIO_FUNC_GPIO_51, 0},
81 {GPIO_FUNC_GPIO_52, 0},
82 {GPIO_FUNC_GPIO_53, 0},
83 {GPIO_FUNC_GPIO_54, 0},
84 {GPIO_FUNC_SDIO_DAT2, 1}, //GPIO_55
85 {GPIO_FUNC_SDIO_DAT1, 1}, //GPIO_56
86 {GPIO_FUNC_SDIO_DAT0, 1}, //GPIO_57
87 {GPIO_FUNC_SDIO_CMD, 1}, //GPIO_58
88 {GPIO_FUNC_SDIO_CLK, 1}, //GPIO_59
89 {GPIO_FUNC_GPIO_60, 0},
90 {0,0},{0,0},{0,0},{0,0},
91 {0,0},{0,0},
92 {GPIO_FUNC_DVL_0, 1},//GPIO_67
93 {GPIO_FUNC_DVL_1, 1},//GPIO_68
94 {GPIO_FUNC_GPIO_69, 0},
95 {GPIO_FUNC_GPIO_70, 0},
96 {GPIO_FUNC_QSPI_DAT3, 1}, //GPIO_71
97 {GPIO_FUNC_QSPI_DAT2, 1}, //GPIO_72
98 {GPIO_FUNC_QSPI_DAT1, 1}, //GPIO_73
99 {GPIO_FUNC_QSPI_DAT0, 1}, //GPIO_74
100 {GPIO_FUNC_QSPI_CLK, 1}, //GPIO_75
101 {GPIO_FUNC_QSPI_CS1, 1}, //GPIO_76
102 {GPIO_FUNC_GPIO_77, 0},
103 {GPIO_FUNC_GPIO_78, 0},
104 {GPIO_FUNC_GPIO_79, 0},
105 {GPIO_FUNC_GPIO_80, 0},
106 {GPIO_FUNC_USIM_UCLK, 1},//GPIO_81
107 {GPIO_FUNC_USIM_UIO, 1},//GPIO_82
108 {GPIO_FUNC_USIM_URSTn, 1},//GPIO_83
109 {0,0},{0,0},{0,0},{0,0},
110 {0,0},{0,0},{0,0},{0,0},
111 {0,0},{0,0},{0,0},{0,0},
112 {0,0},{0,0},{0,0},
113 {GPIO_FUNC_USB_ID, 1},//GPIO_99
114 {0,0},{0,0},{0,0},{0,0},
115 {0,0},{0,0},{0,0},{0,0},
116 {0,0},{0,0},{0,0},{0,0},
117 {0,0},{0,0},{0,0},{0,0},
118 {0,0},
119 {GPIO_FUNC_PRI_TDI, 1}, //GPIO_117
120 {GPIO_FUNC_PRI_TMS, 1}, //GPIO_118
121 {GPIO_FUNC_PRI_TCK, 1}, //GPIO_119
122 {GPIO_FUNC_PRI_TDO, 1}, //GPIO_120
123 {GPIO_FUNC_QSPI_VMODE_GPIO, 1}, //GPIO_121
124 {GPIO_FUNC_VBUS_DRV, 1}, //GPIO_122
125 {GPIO_FUNC_CLK_REQ, 1}, //GPIO_123
126 {0,0},
127 {GPIO_FUNC_VCXO_REQ, 1}, //GPIO_125
128 {GPIO_FUNC_VCXO_OUT, 1}, //GPIO_126
129 {0,0},
130};
131#if 0
132/**
133 * \brief strstr_n
134 *
135 * find string return number
136 *
137 * \param param
138 * \return return type
139 */
140int strstr_n(const char *s1, const char *s2)
141{
142 int n;
143 int strlen = 0;
144
145 if(*s2)
146 {
147 while(*s1)
148 {
149 for(n = 0; *(s1+n) == *(s2 + n); n++)
150 {
151 if(!*(s2 + n + 1))
152 {
153 strlen++;
154 return strlen;
155 }
156 }
157 s1++;
158 strlen++;
159 }
160 return 0;
161 }else
162 return 0;
163}
164static short int from_hex(char a)
165{
166 if (a >= 'A' && a <= 'F')
167 return a - 'A' + 10;
168 else if (a >= 'a' && a <= 'f')
169 return a - 'a' + 10;
170 else
171 return a - '0';
172}
173
174int str_to_hex(char *str)
175{
176 unsigned char str_len = strlen(str);
177 int i;
178 int ret = 0;
179
180 if(str[0] != '0' || (str[1] != 'x' && str[1] != 'X'))
181 {
182 printf("%s error, %s!\n", __FUNCTION__, str);
183 return ret;
184 }
185 for (i = 2; i < str_len; ++i) {
186 ret = ret * 16 + from_hex(str[i]);
187 }
188 return ret;
189}
190#endif
191
192#define HWMAP_DEVICE "/dev/hwmap"
193#define PAGE_OFFS_BITS(pgsz) ((unsigned int)(pgsz)-1)
194#define PAGE_MASK_BITS(pgsz) (~PAGE_OFFS_BITS(pgsz))
195
196static int hwacc_register(int rw, unsigned int addr, unsigned int *data)
197{
198 int fid;
199 unsigned int pagesize, len, len_aligned;
200 unsigned int addr_aligned;
201 volatile unsigned int *pa;
202 void *vpa;
203
204 len = pagesize = sysconf(_SC_PAGESIZE);
205 if((fid = open(HWMAP_DEVICE, O_RDWR)) < 0)
206 {
207 printf("Failed to open %s\n", HWMAP_DEVICE);
208 exit(-1);
209 }
210
211 // Align the length so the mapped area is page-aligned and contains the requested area
212 addr_aligned = addr & PAGE_MASK_BITS(pagesize);
213 len_aligned =((addr + len - addr_aligned) + pagesize - 1) & PAGE_MASK_BITS(pagesize);
214
215 /* Notes on flags: MAP_PRIVATE results in copy on write; MAP_SHARED allows normal write */
216 /* MAP_SHARED required O_RDWR in open above, otherwise mmap fails with errno=EACCES */
217 /* Notes on prot: PROT_WRITE allows read and write; PROT_READ allows read only */
218 /* Notes on off: an unsigned 32-bit value, should be aligned to page size according to mmap manpage */
219 if((vpa = mmap(0, len_aligned, PROT_READ|PROT_WRITE, MAP_SHARED, fid, addr_aligned)) == MAP_FAILED)
220 {
221 printf("mmap failed (%d)\n", errno);
222 }
223 else
224 {
225 pa = (volatile unsigned int *)((unsigned char *)vpa + (addr & PAGE_OFFS_BITS(pagesize)));
226 if(rw == 0)
227 {
228 *data = *pa;
229 gpio_log("Value read from 0x%.8x via MVA=0x%p is 0x%.8x\n", addr, pa, *data);
230 }
231 else if(rw == 1)
232 {
233 *pa = *data;
234 gpio_log("Value %.8x written to 0x%.8x via MVA=0x%p\n", *data, addr, pa);
235#if defined(HWACC_DEBUG)
236 {
237 unsigned int val;
238 val = *pa;
239 printf("Value read from 0x%.8x via MVA=0x%p is 0x%.8x\n", addr, pa, val);
240 }
241#endif
242 }
243 munmap(vpa, len);
244 }
245
246 close(fid);
247 return 0;
248}
249/*
250设置GPIO 模式:第一步读GPIO22默认function
251root@OpenWrt:/# hwacc r 0xd401e134
252Option = r Addr = d401e134
253Value read from 0xd401e134 via MVA=0x0xb6fc3134 is 0x0000d040 //默认GPIO功能
254Bit0~bit2值对应上面表格各function,0代表GPIO功能
255 */
256static int gpio_register_read(int reg)
257{
258 int ret = -1;
259#if 0
260 FILE * fp;
261 // "/bin/hwacc r 0xd401e134";
262 char command[36] = {0};
263 char buffer[1024];
264 int i = 0;
265
266 sprintf(command, "/bin/hwacc r 0x%x", reg);
267 fp = popen(command, "r");
268 while(1)
269 {
270 if( fgets (buffer, sizeof(buffer), fp)!=NULL ) {
271 buffer[strlen(buffer) - 1] = 0;
272 // gpio_log("out [%d]: %s\n", strlen(buffer), buffer);
273 }else{
274 break;
275 }
276 i = strstr_n(buffer, "is");
277 if(i)
278 {
279 ret = str_to_hex(&buffer[i + 2]);
280 gpio_log("read 0x%x value:%s, %x\n", reg, &buffer[i + 2], ret);
281 }
282 }
283 pclose(fp);
284#else
285 hwacc_register(0, reg, &ret);
286#endif
287 return ret;
288}
289/*
290设置输入输出状态,设置PDR寄存器GPIO22为output
291root@OpenWrt:/# hwacc w 0xD401900c 0x00c03800
292Option = w Addr = d401900c Data=00c03800
293Value 00c03800 written to 0xd401900c via MVA=0x0xb6f9f00c
294 */
295static void gpio_register_write(int reg, int value)
296{
297#if 0
298 FILE * fp;
299 // "/bin/hwacc w 0xD401900c 0x00c03800"
300 char command[36] = {0};
301 char buffer[1024];
302
303 sprintf(command, "/bin/hwacc w 0x%x 0x%x", reg, value);
304 gpio_log("command: %s\n", command);
305 fp = popen(command, "r");
306 while(1)
307 {
308 if( fgets (buffer, sizeof(buffer), fp)!=NULL ) {
309 gpio_log("%s\n", buffer);
310 }else{
311 break;
312 }
313 }
314 pclose(fp);
315
316#else
317 hwacc_register(1, reg, &value);
318#endif
319}
320/*
321AF SEL<p>This field is used for alternate function selection for a pin.
322It selects between the eight possible alternate functions for the pin.
323Alternate function 0 is always the reset case.
324
325<p>0x0 = Alternate function 0 (primary function at reset)
326<p>0x1 = Alternate function 1
327<p>0x2 = Alternate function 2
328<p>0x3 = Alternate function 3
329<p>0x4 = Alternate function 4
330<p>0x5 = Alternate function 5
331<p>0x6 = Alternate function 6
332<p>0x7 = Alternate function 7
333 */
334static int gpio_register_set_func_0(int port)
335{
336 int ret;
337 struct gpio_register_function *reg = NULL;
338 if(port > 128)
339 return -1;
340 reg = &gpio_func_register[port];
341 if(0 == reg->reg)
342 return -1;
343 ret = gpio_register_read(reg->reg);
344 if((ret & 0x7) != reg->func_gpio)
345 {
346 gpio_log("Gpio set func [%d] [0x%x]!\n", reg->func_gpio, (ret & 0xfffffff8) | reg->func_gpio);
347 gpio_register_write(reg->reg, (ret & 0xfffffff8) | reg->func_gpio);
348 }
349 return 0;
350}
351/*
352设置GPIO 方向
353读取输入输出状态,读PDR寄存器:0x0c
354root@OpenWrt:/# hwacc r 0xD401900c
355Option = r Addr = d401900c
356Value read from 0xd401900c via MVA=0x0xb6f3900c is 0x00803800 //bit22为0,代表Input
357 */
358static void gpio_register_set_direction(int port, int dir)
359{
360 int ret;
361 int reg = 0xD4019000;
362
363 if(port > (32 - 1))
364 reg = 0xD4019004;
365 if(port > (32 * 2 - 1))
366 reg = 0xD4019008;
367 if(port > (32 * 3 - 1))
368 reg = 0xD4019100;
369
370 reg += 0x0c;
371 port = port % 0x20;
372 ret = gpio_register_read(reg);
373 // 设置 输出 0 && 1
374 if(!(ret & (0x1 << port)) && dir)
375 {
376 gpio_register_write(reg, ret | (0x1 << port));
377 }
378 // 设置 输入 1 && 0
379 if((ret & (0x1 << port)) && !dir)
380 {
381 gpio_register_write(reg, ret | !(0x1 << port));
382 }
383}
384/*
385设置GPIO 输出电平
386
387读取电平状态,先读PLR寄存器:0x00
388root@OpenWrt:/# hwacc r 0xD4019000
389Option = r Addr = d4019000
390Value read from 0xd4019000 via MVA=0x0xb6f1c000 is 0x81e82a30
391对应下面具体BIT
3921000 0001 1110 1000 0010 1010 0011 0000 BIT22默认电平高
393
394设置输出高:设置PSR寄存器:0x18(只写寄存器)
395root@OpenWrt:/# hwacc w 0xD4019018 0x400000
396Option = w Addr = d4019018 Data=00400000
397Value 00400000 written to 0xd4019018 via MVA=0x0xb6f56018 //bit22写1,输出高
398
399设置输出低:设置PCR寄存器:0x24
400root@OpenWrt:/# hwacc w 0xD4019024 0x400000
401Option = w Addr = d4019024 Data=00400000
402Value 00400000 written to 0xd4019024 via MVA=0x0xb6faa024 //Bit22写1,GPIO22输出低
403
404 */
405static void gpio_register_set_value(int port, int value)
406{
407 int ret;
408 int reg = 0xD4019000;
409
410 if(port > (32 - 1))
411 reg = 0xD4019004;
412 if(port > (32 * 2 - 1))
413 reg = 0xD4019008;
414 if(port > (32 * 3 - 1))
415 reg = 0xD4019100;
416
417 if(value)
418 {
419 reg += 0x18;
420 }
421 else
422 reg += 0x24;
423
424 port = port % 0x20;
425 ret = gpio_register_read(reg);
426 // 设置 高电平 0 && 1
427 if(value)
428 {
429 gpio_register_write(reg, ret | (0x1 << port));
430 return;
431 }
432 // 设置 低电平 1 && 0
433 if(!(ret & (0x1 << port)) && !value)
434 {
435 gpio_register_write(reg, ret | (0x1 << port));
436 }
437}
438/*
439读取电平状态,先读PLR寄存器:0x00
440root@OpenWrt:/# hwacc r 0xD4019000
441Option = r Addr = d4019000
442Value read from 0xd4019000 via MVA=0x0xb6f1c000 is 0x81e82a30
443对应下面具体BIT
4441000 0001 1110 1000 0010 1010 0011 0000 BIT22默认电平高
445 */
446static int gpio_register_get_value(int port)
447{
448 int ret = -1;
449 int reg = 0xD4019000;
450
451 if(port > (32 - 1))
452 reg = 0xD4019004;
453 if(port > (32 * 2 - 1))
454 reg = 0xD4019008;
455 if(port > (32 * 3 - 1))
456 reg = 0xD4019100;
457 port = port % 0x20;
458 ret = gpio_register_read(reg);
459 if(ret & (0x1 << port))
460 {
461 return 1;
462 }
463 return 0;
464}
465
466void gpio_debug_set(int enable)
467{
468 gpio_debug = enable;
469}
470
471int gpio_register_test_out(int port, int value)
472{
473 int ret;
474 gpio_log("Gpio port [%d] test start!\n", port);
475 ret = gpio_register_set_func_0(port);
476 if(ret)
477 {
478 printf("gpio_port can't support!\n");
479 return -1;
480 }
481
482 gpio_register_set_direction(port, 1);
483 ret = gpio_register_get_value(port);
484 gpio_log("gpio default value is : %d.\n", ret);
485
486 gpio_register_set_value(port, 1);
487 ret = gpio_register_get_value(port);
488 gpio_log("######gpio should is high: %d.######\n", ret);
489 if(1 != ret)
490 goto exit;
491 usleep(50);
492
493 gpio_register_set_value(port, 0);
494 ret = gpio_register_get_value(port);
495 gpio_log("######gpio should is low: %d.######\n", ret);
496 if(0 != ret)
497 {
498 goto exit;
499 }
500
501exit:
502 gpio_register_set_direction(port, 0);
503
504 return ret;
505}
506
507int mbtk_at_gpio(void* arg)
508{
509 int test_gpio[] = {33, 35, 36, 34, 82, 83, 81, /*41, 40, 39, 38, 37, 42,*/
510 21, 4, 122, 123, 20, 43, 13, 12, 14, 118, 19, 120,
511 49, 50, 32, 31, /*51, 52, */53, 54, 119, 23, 24, 27, 28, 26, 25, 5, 9,
512 0, 1, 2, 3, 6, 7, 15, 18, 16, 17,
513 126, 125, 56, 55, 58, 48, 57, 59, 117, 29, 30};
514
515 int i, ret, total, n = 0;
516 int *fail_io = (int *)arg;
517 total = (sizeof(test_gpio)/sizeof(int));
518 printf("Start test gpio total: %d\n", total);
519 for(i = 0; i < total; i++)
520 {
521 ret = gpio_register_test_out(test_gpio[i], 0);
522 if(-1 == ret)
523 {
524 LOGI("######gpio [%d] test failed!!!!!!######\n", test_gpio[i]);
525 fail_io[n] = test_gpio[i];
526 n++;
527 }else{
528 LOGI("######gpio [%d] test success!!!!!!######\n", test_gpio[i]);
529 }
530 }
531 return n;
532}