/* * Copyright (C) 2021 Denis 'GNUtoo' Carikli * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #define _GNU_SOURCE /* For asprintf */ #include #include #include #include #include #include #include #include "compatible_devices.h" #include "exynos4412_gpios.h" #include "exynos4412_gpios_data.h" #include "tests.h" static int run_command(int debug, char *command) { char *silent_command; int rc; if (debug) { return system(command); } else { rc = asprintf(&silent_command, "%s 1>/dev/null", command); if (rc == -1) { rc = errno; printf("%s: asprintf failed with error %d: %s\n", __func__, rc, strerror(rc)); assert(false); } rc = system(silent_command); free(silent_command); return rc; } } static int test_output_value_with_libgpiod(int debug, char *devmem, int fd, size_t page_size, char *bank, int gpio_offset) { char *gpioset_high_command; char *gpioset_low_command; int rc; rc = asprintf(&gpioset_high_command, "gpioset %s %d=1", bank, gpio_offset); if (rc == -1) { rc = errno; printf("%s: asprintf failed with error %d: %s\n", __func__, rc, strerror(rc)); assert(false); } rc = run_command(debug, gpioset_high_command); assert(rc == 0); free(gpioset_high_command); rc = gpio_get_direction(devmem, fd, page_size, bank, gpio_offset); assert (rc == GPIO_OUTPUT); rc = gpio_get_output_value(devmem, fd, page_size, bank, gpio_offset); assert (rc == GPIO_VALUE_HIGH); rc = asprintf(&gpioset_low_command, "gpioset %s %d=0", bank, gpio_offset); if (rc == -1) { rc = errno; printf("%s: asprintf failed with error %d: %s\n", __func__, rc, strerror(rc)); assert(false); } rc = run_command(debug, gpioset_low_command); assert(rc == 0); rc = gpio_get_direction(devmem, fd, page_size, bank, gpio_offset); assert (rc == GPIO_OUTPUT); rc = gpio_get_output_value(devmem, fd, page_size, bank, gpio_offset); assert (rc == GPIO_VALUE_LOW); free(gpioset_low_command); return 0; } static int test_flash_with_devmem2(int debug, char *devmem, int fd, size_t page_size) { int rc; /* On Parabola with the nonfree u-boot and the Replicant 11 kernel, * the gpio value register is 0x0 after boot, so I hope that it is safe * to set it to 0x0 too on Replicant 6, even if after boot, its value * is 0x1. * We also used the default values after booting Parabola for the gpio * direction register. */ /* Set the GPIO to input */ if (debug) printf(" Starting devmem2 GPIO input test\n"); rc = run_command(debug, "devmem2 0x11400260 w 0x2000"); assert(rc == 0); rc = gpio_get_direction(devmem, fd, page_size, "gpj1", 1); assert (rc == GPIO_INPUT); printf("[ OK ] devmem2 GPIO input test\n"); /* Set the GPIO to output */ if (debug) printf(" Starting devmem2 GPIO output test\n"); rc = run_command(debug, "devmem2 0x11400260 w 0x2002"); assert(rc == 0); rc = gpio_get_direction(devmem, fd, page_size, "gpj1", 1); assert (rc == GPIO_OUTPUT); printf("[ OK ] devmem2 GPIO output test\n"); /* Set the pin LOW */ if (debug) printf(" Starting devmem2 GPIO output low test\n"); rc = run_command(debug, "devmem2 0x11400264 w 0"); assert(rc == 0); rc = gpio_get_output_value(devmem, fd, page_size, "gpj1", 1); assert (rc == GPIO_VALUE_LOW); printf("[ OK ] devmem2 GPIO output low test\n"); /* Set the pin HIGH */ if (debug) printf(" Starting devmem2 GPIO output high test\n"); rc = run_command(debug, "devmem2 0x11400264 w 2"); assert(rc == 0); rc = gpio_get_output_value(devmem, fd, page_size, "gpj1", 1); assert (rc == GPIO_VALUE_HIGH); printf("[ OK ] devmem2 GPIO output high test\n"); /* Set it to low again */ if (debug) printf(" Starting devmem2 GPIO output low test\n"); rc = run_command(debug, "devmem2 0x11400264 w 0"); assert(rc == 0); rc = gpio_get_output_value(devmem, fd, page_size, "gpj1", 1); assert (rc == GPIO_VALUE_LOW); printf("[ OK ] devmem2 GPIO output low test\n"); return 0; } static int test_direction_with_libgpiod(int debug, char *devmem, int fd, size_t page_size, char *bank, int gpio_offset) { char *gpioget_command; char *gpioset_command; int rc; rc = asprintf(&gpioget_command, "gpioget %s %d", bank, gpio_offset); if (rc == -1) { rc = errno; printf("%s: asprintf failed with error %d: %s\n", __func__, rc, strerror(rc)); assert(false); } rc = run_command(debug, gpioget_command); assert(rc == 0); free(gpioget_command); rc = gpio_get_direction(devmem, fd, page_size, bank, gpio_offset); assert (rc == GPIO_INPUT); rc = asprintf(&gpioset_command, "gpioset %s %d=1", bank, gpio_offset); if (rc == -1) { rc = errno; printf("%s: asprintf failed with error %d: %s\n", __func__, rc, strerror(rc)); assert(false); } rc = run_command(debug, gpioset_command); assert(rc == 0); rc = gpio_get_direction(devmem, fd, page_size, bank, gpio_offset); assert (rc == GPIO_OUTPUT); free(gpioset_command); return 0; } int run_tests(int debug, char *devmem, int fd, size_t page_size) { bool has_devmem2; bool has_gpioget; bool has_gpioset; has_devmem2 = device_has_devmem2(debug); has_gpioget = device_has_gpioget(debug); has_gpioset = device_has_gpioset(debug); if (has_gpioget && has_gpioset) { test_direction_with_libgpiod(debug, devmem, fd, page_size, "gpj1", 1); printf("[ OK ] libgpiod GPIO direction test\n"); test_output_value_with_libgpiod(debug, devmem, fd, page_size, "gpj1", 1); printf("[ OK ] libgpiod GPIO output value test\n"); } else { if (!has_gpioget) printf("[ !! ] gpioget not found: skipping" " libgpiod direction and output tests\n"); if (!has_gpioset) printf("[ !! ] gpioset not found: skipping" " libgpiod direction and output tests\n"); } if (has_devmem2) { test_flash_with_devmem2(debug, devmem, fd, page_size); } else { printf("[ !! ] devmem2 not found: skipping" " devmem2 direction and output tests\n"); } return 0; }