summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorKlemens Nanni <kn@cvs.openbsd.org>2021-09-25 10:43:25 +0000
committerKlemens Nanni <kn@cvs.openbsd.org>2021-09-25 10:43:25 +0000
commit56b8112d6344bfc823f6b80ae3cd8990270344da (patch)
treefcc182c9df0f4c9408a50aa29d273b7ebf5f7453 /sys
parenta62a0892b022a6b9609cc58dd3ca63cb2641e6a5 (diff)
Add gpioleds(4) for arm64
This driver provides support for LEDs connected to GPIO pins, such as those found on the Pinebook Pro. OK kettenis
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/arm64/conf/GENERIC4
-rw-r--r--sys/dev/fdt/files.fdt6
-rw-r--r--sys/dev/fdt/gpioleds.c102
3 files changed, 110 insertions, 2 deletions
diff --git a/sys/arch/arm64/conf/GENERIC b/sys/arch/arm64/conf/GENERIC
index 2cbabe0629f..bcc95cdab63 100644
--- a/sys/arch/arm64/conf/GENERIC
+++ b/sys/arch/arm64/conf/GENERIC
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.206 2021/09/03 14:53:09 patrick Exp $
+# $OpenBSD: GENERIC,v 1.207 2021/09/25 10:43:24 kn Exp $
#
# GENERIC machine description file
#
@@ -131,6 +131,8 @@ amdgpu* at pci?
drm* at amdgpu?
wsdisplay* at amdgpu?
+gpioleds* at fdt?
+
# Apple
apldart* at fdt?
apldog* at fdt? early 1
diff --git a/sys/dev/fdt/files.fdt b/sys/dev/fdt/files.fdt
index 3b23523493a..7d36eab3ef8 100644
--- a/sys/dev/fdt/files.fdt
+++ b/sys/dev/fdt/files.fdt
@@ -1,4 +1,4 @@
-# $OpenBSD: files.fdt,v 1.155 2021/06/29 12:43:09 patrick Exp $
+# $OpenBSD: files.fdt,v 1.156 2021/09/25 10:43:24 kn Exp $
#
# Config file and device description for machine-independent FDT code.
# Included by ports that need it.
@@ -588,3 +588,7 @@ file dev/fdt/cwfg.c cwfg
device dapmic
attach dapmic at i2c
file dev/fdt/dapmic.c dapmic
+
+device gpioleds
+attach gpioleds at fdt
+file dev/fdt/gpioleds.c gpioleds
diff --git a/sys/dev/fdt/gpioleds.c b/sys/dev/fdt/gpioleds.c
new file mode 100644
index 00000000000..889d30f1941
--- /dev/null
+++ b/sys/dev/fdt/gpioleds.c
@@ -0,0 +1,102 @@
+/* $OpenBSD: gpioleds.c,v 1.1 2021/09/25 10:43:24 kn Exp $ */
+/*
+ * Copyright (c) 2021 Klemens Nanni <kn@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/gpio.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/gpio/gpiovar.h>
+#include <dev/ofw/ofw_gpio.h>
+#include <dev/ofw/ofw_pinctrl.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/fdt.h>
+
+struct gpioleds_softc {
+ struct device sc_dev;
+ int sc_node;
+};
+
+int gpioleds_match(struct device *, void *, void *);
+void gpioleds_attach(struct device *, struct device *, void *);
+
+struct cfattach gpioleds_ca = {
+ sizeof (struct gpioleds_softc), gpioleds_match, gpioleds_attach
+};
+
+struct cfdriver gpioleds_cd = {
+ NULL, "gpioleds", DV_DULL
+};
+
+int
+gpioleds_match(struct device *parent, void *match, void *aux)
+{
+ const struct fdt_attach_args *faa = aux;
+
+ return OF_is_compatible(faa->fa_node, "gpio-leds");
+}
+
+void
+gpioleds_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct fdt_attach_args *faa = aux;
+ uint32_t *led_pin;
+ char *function, *default_state;
+ int function_len, default_state_len, gpios_len;
+ int node, leds = 0;
+
+ pinctrl_byname(faa->fa_node, "default");
+
+ for (node = OF_child(faa->fa_node); node; node = OF_peer(node)) {
+ function_len = OF_getproplen(node, "function");
+ if (function_len <= 0)
+ continue;
+ default_state_len = OF_getproplen(node, "default-state");
+ if (default_state_len <= 0)
+ continue;
+ gpios_len = OF_getproplen(node, "gpios");
+ if (gpios_len <= 0)
+ continue;
+
+ function = malloc(function_len, M_TEMP, M_WAITOK);
+ OF_getprop(node, "function", function, function_len);
+ default_state = malloc(default_state_len, M_TEMP, M_WAITOK);
+ OF_getprop(node, "default-state", default_state, default_state_len);
+ led_pin = malloc(gpios_len, M_TEMP, M_WAITOK);
+ OF_getpropintarray(node, "gpios", led_pin, gpios_len);
+ gpio_controller_config_pin(led_pin, GPIO_CONFIG_OUTPUT);
+ if (strcmp(default_state, "on") == 0)
+ gpio_controller_set_pin(led_pin, 1);
+ else if (strcmp(default_state, "off") == 0)
+ gpio_controller_set_pin(led_pin, 0);
+
+ printf("%s \"%s\"", leds++ ? "," : ":", function);
+ free(function, M_TEMP, function_len);
+ free(default_state, M_TEMP, default_state_len);
+ free(led_pin, M_TEMP, gpios_len);
+ }
+
+ if (leds == 0) {
+ printf(": no LEDs\n");
+ return;
+ }
+ printf("\n");
+}