1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
22a144dd0SLinus Walleij /*
32a144dd0SLinus Walleij * gpio-hammer - example swiss army knife to shake GPIO lines on a system
42a144dd0SLinus Walleij *
52a144dd0SLinus Walleij * Copyright (C) 2016 Linus Walleij
62a144dd0SLinus Walleij *
72a144dd0SLinus Walleij * Usage:
82a144dd0SLinus Walleij * gpio-hammer -n <device-name> -o <offset1> -o <offset2>
92a144dd0SLinus Walleij */
102a144dd0SLinus Walleij
112a144dd0SLinus Walleij #include <unistd.h>
122a144dd0SLinus Walleij #include <stdlib.h>
132a144dd0SLinus Walleij #include <stdbool.h>
142a144dd0SLinus Walleij #include <stdio.h>
152a144dd0SLinus Walleij #include <dirent.h>
162a144dd0SLinus Walleij #include <errno.h>
172a144dd0SLinus Walleij #include <string.h>
182a144dd0SLinus Walleij #include <poll.h>
192a144dd0SLinus Walleij #include <fcntl.h>
202a144dd0SLinus Walleij #include <getopt.h>
212a144dd0SLinus Walleij #include <sys/ioctl.h>
222a144dd0SLinus Walleij #include <linux/gpio.h>
2374100bb9SBamvor Jian Zhang #include "gpio-utils.h"
242a144dd0SLinus Walleij
hammer_device(const char * device_name,unsigned int * lines,int num_lines,unsigned int loops)25ed60aee0SKent Gibson int hammer_device(const char *device_name, unsigned int *lines, int num_lines,
262a144dd0SLinus Walleij unsigned int loops)
272a144dd0SLinus Walleij {
28*7ff6d1d2SKent Gibson struct gpio_v2_line_values values;
29*7ff6d1d2SKent Gibson struct gpio_v2_line_config config;
302a144dd0SLinus Walleij char swirr[] = "-\\|/";
312a144dd0SLinus Walleij int fd;
322a144dd0SLinus Walleij int ret;
332a144dd0SLinus Walleij int i, j;
342a144dd0SLinus Walleij unsigned int iteration = 0;
352a144dd0SLinus Walleij
36*7ff6d1d2SKent Gibson memset(&config, 0, sizeof(config));
37*7ff6d1d2SKent Gibson config.flags = GPIO_V2_LINE_FLAG_OUTPUT;
38*7ff6d1d2SKent Gibson
39*7ff6d1d2SKent Gibson ret = gpiotools_request_line(device_name, lines, num_lines,
40*7ff6d1d2SKent Gibson &config, "gpio-hammer");
412a144dd0SLinus Walleij if (ret < 0)
4274100bb9SBamvor Jian Zhang goto exit_error;
4374100bb9SBamvor Jian Zhang else
4474100bb9SBamvor Jian Zhang fd = ret;
452a144dd0SLinus Walleij
46*7ff6d1d2SKent Gibson values.mask = 0;
47*7ff6d1d2SKent Gibson values.bits = 0;
48*7ff6d1d2SKent Gibson for (i = 0; i < num_lines; i++)
49*7ff6d1d2SKent Gibson gpiotools_set_bit(&values.mask, i);
50*7ff6d1d2SKent Gibson
51*7ff6d1d2SKent Gibson ret = gpiotools_get_values(fd, &values);
5274100bb9SBamvor Jian Zhang if (ret < 0)
532a144dd0SLinus Walleij goto exit_close_error;
542a144dd0SLinus Walleij
552a144dd0SLinus Walleij fprintf(stdout, "Hammer lines [");
56ed60aee0SKent Gibson for (i = 0; i < num_lines; i++) {
572a144dd0SLinus Walleij fprintf(stdout, "%d", lines[i]);
58ed60aee0SKent Gibson if (i != (num_lines - 1))
592a144dd0SLinus Walleij fprintf(stdout, ", ");
602a144dd0SLinus Walleij }
612a144dd0SLinus Walleij fprintf(stdout, "] on %s, initial states: [", device_name);
62ed60aee0SKent Gibson for (i = 0; i < num_lines; i++) {
63*7ff6d1d2SKent Gibson fprintf(stdout, "%d", gpiotools_test_bit(values.bits, i));
64ed60aee0SKent Gibson if (i != (num_lines - 1))
652a144dd0SLinus Walleij fprintf(stdout, ", ");
662a144dd0SLinus Walleij }
672a144dd0SLinus Walleij fprintf(stdout, "]\n");
682a144dd0SLinus Walleij
692a144dd0SLinus Walleij /* Hammertime! */
702a144dd0SLinus Walleij j = 0;
712a144dd0SLinus Walleij while (1) {
722a144dd0SLinus Walleij /* Invert all lines so we blink */
73ed60aee0SKent Gibson for (i = 0; i < num_lines; i++)
74*7ff6d1d2SKent Gibson gpiotools_change_bit(&values.bits, i);
752a144dd0SLinus Walleij
76*7ff6d1d2SKent Gibson ret = gpiotools_set_values(fd, &values);
7774100bb9SBamvor Jian Zhang if (ret < 0)
782a144dd0SLinus Walleij goto exit_close_error;
7974100bb9SBamvor Jian Zhang
802a144dd0SLinus Walleij /* Re-read values to get status */
81*7ff6d1d2SKent Gibson ret = gpiotools_get_values(fd, &values);
8274100bb9SBamvor Jian Zhang if (ret < 0)
832a144dd0SLinus Walleij goto exit_close_error;
842a144dd0SLinus Walleij
852a144dd0SLinus Walleij fprintf(stdout, "[%c] ", swirr[j]);
862a144dd0SLinus Walleij j++;
872a144dd0SLinus Walleij if (j == sizeof(swirr) - 1)
882a144dd0SLinus Walleij j = 0;
892a144dd0SLinus Walleij
902a144dd0SLinus Walleij fprintf(stdout, "[");
91ed60aee0SKent Gibson for (i = 0; i < num_lines; i++) {
92*7ff6d1d2SKent Gibson fprintf(stdout, "%d: %d", lines[i],
93*7ff6d1d2SKent Gibson gpiotools_test_bit(values.bits, i));
94ed60aee0SKent Gibson if (i != (num_lines - 1))
952a144dd0SLinus Walleij fprintf(stdout, ", ");
962a144dd0SLinus Walleij }
972a144dd0SLinus Walleij fprintf(stdout, "]\r");
982a144dd0SLinus Walleij fflush(stdout);
992a144dd0SLinus Walleij sleep(1);
1002a144dd0SLinus Walleij iteration++;
1012a144dd0SLinus Walleij if (loops && iteration == loops)
1022a144dd0SLinus Walleij break;
1032a144dd0SLinus Walleij }
1042a144dd0SLinus Walleij fprintf(stdout, "\n");
1052a144dd0SLinus Walleij ret = 0;
1062a144dd0SLinus Walleij
1072a144dd0SLinus Walleij exit_close_error:
108*7ff6d1d2SKent Gibson gpiotools_release_line(fd);
10974100bb9SBamvor Jian Zhang exit_error:
1102a144dd0SLinus Walleij return ret;
1112a144dd0SLinus Walleij }
1122a144dd0SLinus Walleij
print_usage(void)1132a144dd0SLinus Walleij void print_usage(void)
1142a144dd0SLinus Walleij {
1152a144dd0SLinus Walleij fprintf(stderr, "Usage: gpio-hammer [options]...\n"
1162a144dd0SLinus Walleij "Hammer GPIO lines, 0->1->0->1...\n"
1172a144dd0SLinus Walleij " -n <name> Hammer GPIOs on a named device (must be stated)\n"
1182a144dd0SLinus Walleij " -o <n> Offset[s] to hammer, at least one, several can be stated\n"
1192a144dd0SLinus Walleij " [-c <n>] Do <n> loops (optional, infinite loop if not stated)\n"
1202a144dd0SLinus Walleij " -? This helptext\n"
1212a144dd0SLinus Walleij "\n"
1222a144dd0SLinus Walleij "Example:\n"
1232a144dd0SLinus Walleij "gpio-hammer -n gpiochip0 -o 4\n"
1242a144dd0SLinus Walleij );
1252a144dd0SLinus Walleij }
1262a144dd0SLinus Walleij
main(int argc,char ** argv)1272a144dd0SLinus Walleij int main(int argc, char **argv)
1282a144dd0SLinus Walleij {
1292a144dd0SLinus Walleij const char *device_name = NULL;
1302a144dd0SLinus Walleij unsigned int lines[GPIOHANDLES_MAX];
1312a144dd0SLinus Walleij unsigned int loops = 0;
132ed60aee0SKent Gibson int num_lines;
1332a144dd0SLinus Walleij int c;
1342a144dd0SLinus Walleij int i;
1352a144dd0SLinus Walleij
1362a144dd0SLinus Walleij i = 0;
1372a144dd0SLinus Walleij while ((c = getopt(argc, argv, "c:n:o:?")) != -1) {
1382a144dd0SLinus Walleij switch (c) {
1392a144dd0SLinus Walleij case 'c':
1402a144dd0SLinus Walleij loops = strtoul(optarg, NULL, 10);
1412a144dd0SLinus Walleij break;
1422a144dd0SLinus Walleij case 'n':
1432a144dd0SLinus Walleij device_name = optarg;
1442a144dd0SLinus Walleij break;
1452a144dd0SLinus Walleij case 'o':
146d1ee7e1fSGabriel Ravier /*
147d1ee7e1fSGabriel Ravier * Avoid overflow. Do not immediately error, we want to
148d1ee7e1fSGabriel Ravier * be able to accurately report on the amount of times
149d1ee7e1fSGabriel Ravier * '-o' was given to give an accurate error message
150d1ee7e1fSGabriel Ravier */
151d1ee7e1fSGabriel Ravier if (i < GPIOHANDLES_MAX)
1522a144dd0SLinus Walleij lines[i] = strtoul(optarg, NULL, 10);
153d1ee7e1fSGabriel Ravier
1542a144dd0SLinus Walleij i++;
1552a144dd0SLinus Walleij break;
1562a144dd0SLinus Walleij case '?':
1572a144dd0SLinus Walleij print_usage();
1582a144dd0SLinus Walleij return -1;
1592a144dd0SLinus Walleij }
1602a144dd0SLinus Walleij }
161d1ee7e1fSGabriel Ravier
162d1ee7e1fSGabriel Ravier if (i >= GPIOHANDLES_MAX) {
163d1ee7e1fSGabriel Ravier fprintf(stderr,
16455f17e2aSColin Ian King "Only %d occurrences of '-o' are allowed, %d were found\n",
165d1ee7e1fSGabriel Ravier GPIOHANDLES_MAX, i + 1);
166d1ee7e1fSGabriel Ravier return -1;
167d1ee7e1fSGabriel Ravier }
168d1ee7e1fSGabriel Ravier
169ed60aee0SKent Gibson num_lines = i;
1702a144dd0SLinus Walleij
171ed60aee0SKent Gibson if (!device_name || !num_lines) {
1722a144dd0SLinus Walleij print_usage();
1732a144dd0SLinus Walleij return -1;
1742a144dd0SLinus Walleij }
175ed60aee0SKent Gibson return hammer_device(device_name, lines, num_lines, loops);
1762a144dd0SLinus Walleij }
177