diff options
author | Evgeny Zinoviev <me@ch1p.io> | 2021-02-09 04:36:35 +0300 |
---|---|---|
committer | Evgeny Zinoviev <me@ch1p.io> | 2021-02-09 04:37:24 +0300 |
commit | 030ca19eebff382d8767b5d5520e7e7043a22011 (patch) | |
tree | 7ec5f9e4cf6ff6abaae64aebd032fd02d3146457 |
initial
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 25 | ||||
-rw-r--r-- | intelgpio.c | 89 |
3 files changed, 116 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1d5825c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +intelgpio diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..66f60bb --- /dev/null +++ b/Makefile @@ -0,0 +1,25 @@ +## SPDX-License-Identifier: GPL-2.0-only + +CC = gcc +CFLAGS = -O2 -Wall -Wextra -Werror +PROGRAM = intelgpio +INSTALL = /usr/bin/env install +PREFIX = /usr/local + +all: $(PROGRAM) + +$(PROGRAM): intelgpio.o + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +install: $(PROGRAM) + $(INSTALL) $(PROGRAM) $(PREFIX)/sbin + +clean: + rm -f *.o $(PROGRAM) + +distclean: clean + +%.o: %.c + $(CC) $(CFLAGS) -c $^ -I. -o $@ + +.PHONY: all install clean distclean diff --git a/intelgpio.c b/intelgpio.c new file mode 100644 index 0000000..0f4011d --- /dev/null +++ b/intelgpio.c @@ -0,0 +1,89 @@ +#include <stdio.h> +#include <getopt.h> +#include <sys/io.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> + +#define GPIO_BASE 0x48 +#define GP_LVL 0x0c +#define GP_LVL2 0x38 +#define GP_LVL3 0x48 +#define MAX_GPIO_NUMBER 75 +#define LPC_DEV_CONFIG "/sys/bus/pci/devices/0000:00:1f.0/config" + +void usage(const char *name) +{ + printf("usage: %s OPTIONS\n", name); + printf("Options:\n" + " -h: Print this help\n" + " -n: GPIO pin number\n"); +} + +int get_gpio(int base, int num) +{ + static const int gpio_reg_offsets[] = {GP_LVL, GP_LVL2, GP_LVL3}; + int index, bit; + + index = num / 32; + bit = num % 32; + + return (inl(base + gpio_reg_offsets[index]) >> bit) & 1; +} + +int main(int argc, char *argv[]) +{ + int c; + int num = -1; + uint16_t base; + while ((c = getopt(argc, argv, "hn:")) != -1) { + switch (c) { + case 'h': + usage(argv[0]); + return 0; + case 'n': + num = strtoul(optarg, NULL, 10); + if (num > MAX_GPIO_NUMBER) { + fprintf(stderr, "error: invalid number\n"); + return 1; + } + break; + case '?': + return -1; + } + } + + if (num == -1) { + usage(argv[0]); + return 0; + } + + if (geteuid() != 0) { + fprintf(stderr, "error: you must be root\n"); + return 1; + } + + FILE *f = fopen(LPC_DEV_CONFIG, "r"); + if (!f) { + fprintf(stderr, "failed to open %s: %s\n", LPC_DEV_CONFIG, strerror(errno)); + return 1; + } + + fseek(f, GPIO_BASE, SEEK_SET); + fread(&base, 2, 1, f); + fclose(f); + + base &= 0xfffe; + + if (ioperm(base, 0x100, 1)) { + fprintf(stderr, "ioperm: %s\n", strerror(errno)); + exit(1); + } + + int val = get_gpio(base, num); + printf("%d\n", val); + + return 0; +}
\ No newline at end of file |