summaryrefslogtreecommitdiffstats
path: root/meta-xilinx-demos/recipes-examples/gpio-demo/files/gpio-demo.c
diff options
context:
space:
mode:
authorMark Hatle <mark.hatle@amd.com>2024-11-11 11:24:08 -0700
committerMark Hatle <mark.hatle@amd.com>2024-11-11 11:24:08 -0700
commitee6e2f1f4fc8d438bfde7634e31657b52970fda9 (patch)
tree38b5366d82e15538ab3c5e4f9a3dd1dcac26ff20 /meta-xilinx-demos/recipes-examples/gpio-demo/files/gpio-demo.c
parent03d3b2ce359a1c2959f04588cf2c4a1b0dcb4de8 (diff)
parent7c79383570dc4182bb21cdee68598ccf47403150 (diff)
downloadmeta-xilinx-ee6e2f1f4fc8d438bfde7634e31657b52970fda9.tar.gz
Merge remote-tracking branch 'origin/rel-v2024.2' into scarthgap-next
Signed-off-by: Mark Hatle <mark.hatle@amd.com>
Diffstat (limited to 'meta-xilinx-demos/recipes-examples/gpio-demo/files/gpio-demo.c')
-rw-r--r--meta-xilinx-demos/recipes-examples/gpio-demo/files/gpio-demo.c355
1 files changed, 355 insertions, 0 deletions
diff --git a/meta-xilinx-demos/recipes-examples/gpio-demo/files/gpio-demo.c b/meta-xilinx-demos/recipes-examples/gpio-demo/files/gpio-demo.c
new file mode 100644
index 00000000..4e17779d
--- /dev/null
+++ b/meta-xilinx-demos/recipes-examples/gpio-demo/files/gpio-demo.c
@@ -0,0 +1,355 @@
1/*
2*
3* gpio-demo app
4*
5* Copyright (C) 2013 - 2016 Xilinx, Inc. All rights reserved.
6*
7* Permission is hereby granted, free of charge, to any person
8* obtaining a copy of this software and associated documentation
9* files (the "Software"), to deal in the Software without restriction,
10* including without limitation the rights to use, copy, modify, merge,
11* publish, distribute, sublicense, and/or sell copies of the Software,
12* and to permit persons to whom the Software is furnished to do so,
13* subject to the following conditions:
14*
15* The above copyright notice and this permission notice shall be included
16* in all copies or substantial portions of the Software.
17*
18* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21* IN NO EVENT SHALL XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24*
25* Except as contained in this notice, the name of the Xilinx shall not be used
26* in advertising or otherwise to promote the sale, use or other dealings in this
27* Software without prior written authorization from Xilinx.
28*
29*/
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <unistd.h>
34#include <string.h>
35#include <errno.h>
36#include <fcntl.h>
37#include <signal.h>
38
39#define GPIO_ROOT "/sys/class/gpio"
40#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
41
42static enum {NONE, IN, OUT, CYLON, KIT} gpio_opt = NONE;
43
44static const unsigned long cylon[] = {
45 0x00000080, 0x00000040, 0x00000020, 0x00000010,
46 0x00000008, 0x00000004, 0x00000002, 0x00000001,
47 0x00000002, 0x00000004, 0x00000008,
48 0x00000010, 0x00000020, 0x00000040, 0x00000080,
49};
50
51static const unsigned long kit[] = {
52 0x000000e0, 0x00000070, 0x00000038, 0x0000001c,
53 0x0000000e, 0x00000007, 0x00000003, 0x00000001,
54 0x00000003, 0x00000007, 0x0000000e,
55 0x0000001c, 0x00000038, 0x00000070, 0x000000e0,
56};
57
58static int gl_gpio_base = 0;
59
60static void usage (char *argv0)
61{
62 char *basename = strrchr(argv0, '/');
63 if (!basename)
64 basename = argv0;
65
66 fprintf(stderr,
67 "Usage: %s [-g GPIO_BASE] COMMAND\n"
68 "\twhere COMMAND is one of:\n"
69 "\t\t-i\t\tInput value from GPIO and print it\n"
70 "\t\t-o\tVALUE\tOutput value to GPIO\n"
71 "\t\t-c\t\tCylon test pattern\n"
72 "\t\t-k\t\t KIT test pattern\n"
73 "\tGPIO_BASE indicates which GPIO chip to talk to (The number can be \n"
74 "\tfound at /sys/class/gpio/gpiochipN).\n"
75 "\tThe highest gpiochipN is the first gpio listed in the dts file, \n"
76 "\tand the lowest gpiochipN is the last gpio listed in the dts file.\n"
77 "\tE.g.If the gpiochip240 is the LED_8bit gpio, and I want to output '1' \n"
78 "\tto the LED_8bit gpio, the command should be:\n"
79 "\t\tgpio-demo -g 240 -o 1\n"
80 "\n"
81 "\tgpio-demo written by Xilinx Inc.\n"
82 "\n"
83 , basename);
84 exit(-2);
85}
86
87static int open_gpio_channel(int gpio_base)
88{
89 char gpio_nchan_file[128];
90 int gpio_nchan_fd;
91 int gpio_max;
92 int nchannel;
93 char nchannel_str[5];
94 char *cptr;
95 int c;
96 char channel_str[5];
97
98 char *gpio_export_file = "/sys/class/gpio/export";
99 int export_fd=0;
100
101 /* Check how many channels the GPIO chip has */
102 sprintf(gpio_nchan_file, "%s/gpiochip%d/ngpio", GPIO_ROOT, gpio_base);
103 gpio_nchan_fd = open(gpio_nchan_file, O_RDONLY);
104 if (gpio_nchan_fd < 0) {
105 fprintf(stderr, "Failed to open %s: %s\n", gpio_nchan_file, strerror(errno));
106 return -1;
107 }
108 read(gpio_nchan_fd, nchannel_str, sizeof(nchannel_str));
109 close(gpio_nchan_fd);
110 nchannel=(int)strtoul(nchannel_str, &cptr, 0);
111 if (cptr == nchannel_str) {
112 fprintf(stderr, "Failed to change %s into GPIO channel number\n", nchannel_str);
113 exit(1);
114 }
115
116 /* Open files for each GPIO channel */
117 export_fd=open(gpio_export_file, O_WRONLY);
118 if (export_fd < 0) {
119 fprintf(stderr, "Cannot open GPIO to export %d\n", gpio_base);
120 return -1;
121 }
122
123 gpio_max = gpio_base + nchannel;
124 for(c = gpio_base; c < gpio_max; c++) {
125 sprintf(channel_str, "%d", c);
126 write(export_fd, channel_str, (strlen(channel_str)+1));
127 }
128 close(export_fd);
129 return nchannel;
130}
131
132static int close_gpio_channel(int gpio_base)
133{
134 char gpio_nchan_file[128];
135 int gpio_nchan_fd;
136 int gpio_max;
137 int nchannel;
138 char nchannel_str[5];
139 char *cptr;
140 int c;
141 char channel_str[5];
142
143 char *gpio_unexport_file = "/sys/class/gpio/unexport";
144 int unexport_fd=0;
145
146 /* Check how many channels the GPIO chip has */
147 sprintf(gpio_nchan_file, "%s/gpiochip%d/ngpio", GPIO_ROOT, gpio_base);
148 gpio_nchan_fd = open(gpio_nchan_file, O_RDONLY);
149 if (gpio_nchan_fd < 0) {
150 fprintf(stderr, "Failed to open %s: %s\n", gpio_nchan_file, strerror(errno));
151 return -1;
152 }
153 read(gpio_nchan_fd, nchannel_str, sizeof(nchannel_str));
154 close(gpio_nchan_fd);
155 nchannel=(int)strtoul(nchannel_str, &cptr, 0);
156 if (cptr == nchannel_str) {
157 fprintf(stderr, "Failed to change %s into GPIO channel number\n", nchannel_str);
158 exit(1);
159 }
160
161 /* Close opened files for each GPIO channel */
162 unexport_fd=open(gpio_unexport_file, O_WRONLY);
163 if (unexport_fd < 0) {
164 fprintf(stderr, "Cannot close GPIO by writing unexport %d\n", gpio_base);
165 return -1;
166 }
167
168 gpio_max = gpio_base + nchannel;
169 for(c = gpio_base; c < gpio_max; c++) {
170 sprintf(channel_str, "%d", c);
171 write(unexport_fd, channel_str, (strlen(channel_str)+1));
172 }
173 close(unexport_fd);
174 return 0;
175}
176
177static int set_gpio_direction(int gpio_base, int nchannel, char *direction)
178{
179 char gpio_dir_file[128];
180 int direction_fd=0;
181 int gpio_max;
182 int c;
183
184 gpio_max = gpio_base + nchannel;
185 for(c = gpio_base; c < gpio_max; c++) {
186 sprintf(gpio_dir_file, "/sys/class/gpio/gpio%d/direction",c);
187 direction_fd=open(gpio_dir_file, O_RDWR);
188 if (direction_fd < 0) {
189 fprintf(stderr, "Cannot open the direction file for GPIO %d\n", c);
190 return 1;
191 }
192 write(direction_fd, direction, (strlen(direction)+1));
193 close(direction_fd);
194 }
195 return 0;
196}
197
198static int set_gpio_value(int gpio_base, int nchannel, int value)
199{
200 char gpio_val_file[128];
201 int val_fd=0;
202 int gpio_max;
203 char val_str[2];
204 int c;
205
206 gpio_max = gpio_base + nchannel;
207
208 for(c = gpio_base; c < gpio_max; c++) {
209 sprintf(gpio_val_file, "/sys/class/gpio/gpio%d/value",c);
210 val_fd=open(gpio_val_file, O_RDWR);
211 if (val_fd < 0) {
212 fprintf(stderr, "Cannot open the value file of GPIO %d\n", c);
213 return -1;
214 }
215 sprintf(val_str,"%d", (value & 1));
216 write(val_fd, val_str, sizeof(val_str));
217 close(val_fd);
218 value >>= 1;
219 }
220 return 0;
221}
222
223static int get_gpio_value(int gpio_base, int nchannel)
224{
225 char gpio_val_file[128];
226 int val_fd=0;
227 int gpio_max;
228 char val_str[2];
229 char *cptr;
230 int value = 0;
231 int c;
232
233 gpio_max = gpio_base + nchannel;
234
235 for(c = gpio_max-1; c >= gpio_base; c--) {
236 sprintf(gpio_val_file, "/sys/class/gpio/gpio%d/value",c);
237 val_fd=open(gpio_val_file, O_RDWR);
238 if (val_fd < 0) {
239 fprintf(stderr, "Cannot open GPIO to export %d\n", c);
240 return -1;
241 }
242 read(val_fd, val_str, sizeof(val_str));
243 value <<= 1;
244 value += (int)strtoul(val_str, &cptr, 0);
245 if (cptr == optarg) {
246 fprintf(stderr, "Failed to change %s into integer", val_str);
247 }
248 close(val_fd);
249 }
250 return value;
251}
252
253void signal_handler(int sig)
254{
255 switch (sig) {
256 case SIGTERM:
257 case SIGHUP:
258 case SIGQUIT:
259 case SIGINT:
260 close_gpio_channel(gl_gpio_base);
261 exit(0) ;
262 default:
263 break;
264 }
265}
266
267int main(int argc, char *argv[])
268{
269 extern char *optarg;
270 char *cptr;
271 int gpio_value = 0;
272 int nchannel = 0;
273
274 int c;
275 int i;
276
277 opterr = 0;
278
279 while ((c = getopt(argc, argv, "g:io:ck")) != -1) {
280 switch (c) {
281 case 'g':
282 gl_gpio_base = (int)strtoul(optarg, &cptr, 0);
283 if (cptr == optarg)
284 usage(argv[0]);
285 break;
286 case 'i':
287 gpio_opt = IN;
288 break;
289 case 'o':
290 gpio_opt = OUT;
291 gpio_value = (int)strtoul(optarg, &cptr, 0);
292 if (cptr == optarg)
293 usage(argv[0]);
294 break;
295 case 'c':
296 gpio_opt = CYLON;
297 break;
298 case 'k':
299 gpio_opt = KIT;
300 break;
301 case '?':
302 usage(argv[0]);
303 default:
304 usage(argv[0]);
305
306 }
307 }
308
309 if (gl_gpio_base == 0) {
310 usage(argv[0]);
311 }
312
313 nchannel = open_gpio_channel(gl_gpio_base);
314 signal(SIGTERM, signal_handler); /* catch kill signal */
315 signal(SIGHUP, signal_handler); /* catch hang up signal */
316 signal(SIGQUIT, signal_handler); /* catch quit signal */
317 signal(SIGINT, signal_handler); /* catch a CTRL-c signal */
318 switch (gpio_opt) {
319 case IN:
320 set_gpio_direction(gl_gpio_base, nchannel, "in");
321 gpio_value=get_gpio_value(gl_gpio_base, nchannel);
322 fprintf(stdout,"0x%08X\n", gpio_value);
323 break;
324 case OUT:
325 set_gpio_direction(gl_gpio_base, nchannel, "out");
326 set_gpio_value(gl_gpio_base, nchannel, gpio_value);
327 break;
328 case CYLON:
329#define CYLON_DELAY_USECS (10000)
330 set_gpio_direction(gl_gpio_base, nchannel, "out");
331 for (;;) {
332 for(i=0; i < ARRAY_SIZE(cylon); i++) {
333 gpio_value=(int)cylon[i];
334 set_gpio_value(gl_gpio_base, nchannel, gpio_value);
335 }
336 usleep(CYLON_DELAY_USECS);
337 }
338 case KIT:
339#define KIT_DELAY_USECS (10000)
340 set_gpio_direction(gl_gpio_base, nchannel, "out");
341 for (;;) {
342 for (i=0; i<ARRAY_SIZE(kit); i++) {
343 gpio_value=(int)kit[i];
344 set_gpio_value(gl_gpio_base, nchannel, gpio_value);
345 }
346 usleep(KIT_DELAY_USECS);
347 }
348 default:
349 break;
350 }
351 close_gpio_channel(gl_gpio_base);
352 return 0;
353}
354
355