summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2019-08-26 09:22:27 +0000
committerkettenis <kettenis@openbsd.org>2019-08-26 09:22:27 +0000
commit7aaa685ebcdd19b65720d69f56f08449c3a71c54 (patch)
tree01b4e7db68efbd3e3db0064462c62252e07a00df /sys
parentpf.conf "set timeout interval 1" causes kernel crash (diff)
downloadwireguard-openbsd-7aaa685ebcdd19b65720d69f56f08449c3a71c54.tar.xz
wireguard-openbsd-7aaa685ebcdd19b65720d69f56f08449c3a71c54.zip
Implement GPIO hogging.
ok patrick@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ofw/ofw_gpio.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/sys/dev/ofw/ofw_gpio.c b/sys/dev/ofw/ofw_gpio.c
index 5f814ac7322..f8f818e8fb1 100644
--- a/sys/dev/ofw/ofw_gpio.c
+++ b/sys/dev/ofw/ofw_gpio.c
@@ -1,6 +1,6 @@
-/* $OpenBSD: ofw_gpio.c,v 1.2 2016/07/27 21:13:49 kettenis Exp $ */
+/* $OpenBSD: ofw_gpio.c,v 1.3 2019/08/26 09:22:27 kettenis Exp $ */
/*
- * Copyright (c) 2016 Mark Kettenis
+ * Copyright (c) 2016, 2019 Mark Kettenis
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -17,6 +17,7 @@
#include <sys/types.h>
#include <sys/systm.h>
+#include <sys/malloc.h>
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_gpio.h>
@@ -27,12 +28,57 @@ LIST_HEAD(, gpio_controller) gpio_controllers =
void
gpio_controller_register(struct gpio_controller *gc)
{
+ int child;
+
gc->gc_cells = OF_getpropint(gc->gc_node, "#gpio-cells", 2);
gc->gc_phandle = OF_getpropint(gc->gc_node, "phandle", 0);
if (gc->gc_phandle == 0)
return;
LIST_INSERT_HEAD(&gpio_controllers, gc, gc_list);
+
+ /* Process GPIO hogs. */
+ for (child = OF_child(gc->gc_node); child; child = OF_peer(child)) {
+ uint32_t *gpios;
+ uint32_t *gpio;
+ int len, config, active;
+
+ if (OF_getproplen(child, "gpio-hog") != 0)
+ continue;
+
+ len = OF_getproplen(child, "gpios");
+ if (len <= 0)
+ continue;
+
+ /*
+ * These need to be processed in the order prescribed
+ * by the device tree binding. First match wins.
+ */
+ if (OF_getproplen(child, "input") == 0) {
+ config = GPIO_CONFIG_INPUT;
+ active = 0;
+ } else if (OF_getproplen(child, "output-low") == 0) {
+ config = GPIO_CONFIG_OUTPUT;
+ active = 0;
+ } else if (OF_getproplen(child, "output-high") == 0) {
+ config = GPIO_CONFIG_OUTPUT;
+ active = 1;
+ } else
+ continue;
+
+ gpios = malloc(len, M_TEMP, M_WAITOK);
+ OF_getpropintarray(child, "gpios", gpios, len);
+
+ gpio = gpios;
+ while (gpio && gpio < gpios + (len / sizeof(uint32_t))) {
+ gc->gc_config_pin(gc->gc_cookie, gpio, config);
+ if (config & GPIO_CONFIG_OUTPUT)
+ gc->gc_set_pin(gc->gc_cookie, gpio, active);
+ gpio += gc->gc_cells;
+ }
+
+ free(gpios, M_TEMP, len);
+ }
}
void