summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeny Zinoviev <me@ch1p.io>2021-02-09 04:36:35 +0300
committerEvgeny Zinoviev <me@ch1p.io>2021-02-09 04:37:24 +0300
commit030ca19eebff382d8767b5d5520e7e7043a22011 (patch)
tree7ec5f9e4cf6ff6abaae64aebd032fd02d3146457
initial
-rw-r--r--.gitignore2
-rw-r--r--Makefile25
-rw-r--r--intelgpio.c89
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