summaryrefslogtreecommitdiff
path: root/sys/dev/fdt
diff options
context:
space:
mode:
authorKlemens Nanni <kn@cvs.openbsd.org>2021-09-25 18:40:09 +0000
committerKlemens Nanni <kn@cvs.openbsd.org>2021-09-25 18:40:09 +0000
commit5e62f3dc2f2e820215d4c742ed3e815c08b5b133 (patch)
treedef8f033c9f62dbbcb5a0068490c93e4644f0eba /sys/dev/fdt
parent56b8112d6344bfc823f6b80ae3cd8990270344da (diff)
Add gpiocharger(4) for arm64
This driver provides support for battery chargers connected to GPIO pins, such as those found on the Pinebook Pro. OK kettenis
Diffstat (limited to 'sys/dev/fdt')
-rw-r--r--sys/dev/fdt/files.fdt6
-rw-r--r--sys/dev/fdt/gpiocharger.c117
2 files changed, 122 insertions, 1 deletions
diff --git a/sys/dev/fdt/files.fdt b/sys/dev/fdt/files.fdt
index 7d36eab3ef8..301500e9b0c 100644
--- a/sys/dev/fdt/files.fdt
+++ b/sys/dev/fdt/files.fdt
@@ -1,4 +1,4 @@
-# $OpenBSD: files.fdt,v 1.156 2021/09/25 10:43:24 kn Exp $
+# $OpenBSD: files.fdt,v 1.157 2021/09/25 18:40:08 kn Exp $
#
# Config file and device description for machine-independent FDT code.
# Included by ports that need it.
@@ -592,3 +592,7 @@ file dev/fdt/dapmic.c dapmic
device gpioleds
attach gpioleds at fdt
file dev/fdt/gpioleds.c gpioleds
+
+device gpiocharger
+attach gpiocharger at fdt
+file dev/fdt/gpiocharger.c gpiocharger
diff --git a/sys/dev/fdt/gpiocharger.c b/sys/dev/fdt/gpiocharger.c
new file mode 100644
index 00000000000..eae1dd64e38
--- /dev/null
+++ b/sys/dev/fdt/gpiocharger.c
@@ -0,0 +1,117 @@
+/* $OpenBSD: gpiocharger.c,v 1.1 2021/09/25 18:40:08 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>
+
+#include <sys/sensors.h>
+
+struct gpiocharger_softc {
+ struct device sc_dev;
+ int sc_node;
+ uint32_t *sc_charger_pin;
+ struct ksensor sc_sensor;
+ struct ksensordev sc_sensordev;
+};
+
+int gpiocharger_match(struct device *, void *, void *);
+void gpiocharger_attach(struct device *, struct device *, void *);
+
+struct cfattach gpiocharger_ca = {
+ sizeof (struct gpiocharger_softc), gpiocharger_match, gpiocharger_attach
+};
+
+struct cfdriver gpiocharger_cd = {
+ NULL, "gpiocharger", DV_DULL
+};
+
+void gpiocharger_update_charger(void *);
+
+int
+gpiocharger_match(struct device *parent, void *match, void *aux)
+{
+ const struct fdt_attach_args *faa = aux;
+
+ return OF_is_compatible(faa->fa_node, "gpio-charger");
+}
+
+void
+gpiocharger_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct gpiocharger_softc *sc = (struct gpiocharger_softc *)self;
+ struct fdt_attach_args *faa = aux;
+ char *charger_type, *gpios_property;
+ int charger_type_len, gpios_len;
+ int node = faa->fa_node;
+
+ pinctrl_byname(node, "default");
+
+ charger_type_len = OF_getproplen(node, "charger-type");
+ if (charger_type_len <= 0)
+ goto nocharger;
+ gpios_property = "gpios";
+ gpios_len = OF_getproplen(node, gpios_property);
+ if (gpios_len <= 0) {
+ gpios_property = "charger-status-gpios";
+ gpios_len = OF_getproplen(node, gpios_property);
+ if (gpios_len <= 0)
+ goto nocharger;
+ }
+
+ charger_type = malloc(charger_type_len, M_TEMP, M_WAITOK);
+ OF_getprop(node, "charger-type", charger_type, charger_type_len);
+ sc->sc_charger_pin = malloc(gpios_len, M_DEVBUF, M_WAITOK);
+ OF_getpropintarray(node, gpios_property, sc->sc_charger_pin, gpios_len);
+ gpio_controller_config_pin(sc->sc_charger_pin, GPIO_CONFIG_INPUT);
+
+ strlcpy(sc->sc_sensor.desc, charger_type, sizeof(sc->sc_sensor.desc));
+ strlcat(sc->sc_sensor.desc, " power supply",
+ sizeof(sc->sc_sensor.desc));
+ sc->sc_sensor.type = SENSOR_INDICATOR;
+ sensor_attach(&sc->sc_sensordev, &sc->sc_sensor);
+ strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
+ sizeof(sc->sc_sensordev.xname));
+ sensordev_install(&sc->sc_sensordev);
+ sensor_task_register(sc, gpiocharger_update_charger, 5);
+
+ printf(": \"%s\"\n", charger_type);
+ free(charger_type, M_TEMP, charger_type_len);
+ return;
+
+nocharger:
+ printf(": no charger\n");
+}
+
+void
+gpiocharger_update_charger(void *arg)
+{
+ struct gpiocharger_softc *sc = arg;
+
+ sc->sc_sensor.value = gpio_controller_get_pin(sc->sc_charger_pin);
+}