1 /* $OpenBSD: gpiocharger.c,v 1.1 2021/09/25 18:40:08 kn Exp $ */ 2 /* 3 * Copyright (c) 2021 Klemens Nanni <kn@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/device.h> 21 #include <sys/gpio.h> 22 #include <sys/malloc.h> 23 24 #include <machine/bus.h> 25 #include <machine/fdt.h> 26 27 #include <dev/gpio/gpiovar.h> 28 #include <dev/ofw/ofw_gpio.h> 29 #include <dev/ofw/ofw_pinctrl.h> 30 #include <dev/ofw/openfirm.h> 31 #include <dev/ofw/fdt.h> 32 33 #include <sys/sensors.h> 34 35 struct gpiocharger_softc { 36 struct device sc_dev; 37 int sc_node; 38 uint32_t *sc_charger_pin; 39 struct ksensor sc_sensor; 40 struct ksensordev sc_sensordev; 41 }; 42 43 int gpiocharger_match(struct device *, void *, void *); 44 void gpiocharger_attach(struct device *, struct device *, void *); 45 46 struct cfattach gpiocharger_ca = { 47 sizeof (struct gpiocharger_softc), gpiocharger_match, gpiocharger_attach 48 }; 49 50 struct cfdriver gpiocharger_cd = { 51 NULL, "gpiocharger", DV_DULL 52 }; 53 54 void gpiocharger_update_charger(void *); 55 56 int 57 gpiocharger_match(struct device *parent, void *match, void *aux) 58 { 59 const struct fdt_attach_args *faa = aux; 60 61 return OF_is_compatible(faa->fa_node, "gpio-charger"); 62 } 63 64 void 65 gpiocharger_attach(struct device *parent, struct device *self, void *aux) 66 { 67 struct gpiocharger_softc *sc = (struct gpiocharger_softc *)self; 68 struct fdt_attach_args *faa = aux; 69 char *charger_type, *gpios_property; 70 int charger_type_len, gpios_len; 71 int node = faa->fa_node; 72 73 pinctrl_byname(node, "default"); 74 75 charger_type_len = OF_getproplen(node, "charger-type"); 76 if (charger_type_len <= 0) 77 goto nocharger; 78 gpios_property = "gpios"; 79 gpios_len = OF_getproplen(node, gpios_property); 80 if (gpios_len <= 0) { 81 gpios_property = "charger-status-gpios"; 82 gpios_len = OF_getproplen(node, gpios_property); 83 if (gpios_len <= 0) 84 goto nocharger; 85 } 86 87 charger_type = malloc(charger_type_len, M_TEMP, M_WAITOK); 88 OF_getprop(node, "charger-type", charger_type, charger_type_len); 89 sc->sc_charger_pin = malloc(gpios_len, M_DEVBUF, M_WAITOK); 90 OF_getpropintarray(node, gpios_property, sc->sc_charger_pin, gpios_len); 91 gpio_controller_config_pin(sc->sc_charger_pin, GPIO_CONFIG_INPUT); 92 93 strlcpy(sc->sc_sensor.desc, charger_type, sizeof(sc->sc_sensor.desc)); 94 strlcat(sc->sc_sensor.desc, " power supply", 95 sizeof(sc->sc_sensor.desc)); 96 sc->sc_sensor.type = SENSOR_INDICATOR; 97 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor); 98 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 99 sizeof(sc->sc_sensordev.xname)); 100 sensordev_install(&sc->sc_sensordev); 101 sensor_task_register(sc, gpiocharger_update_charger, 5); 102 103 printf(": \"%s\"\n", charger_type); 104 free(charger_type, M_TEMP, charger_type_len); 105 return; 106 107 nocharger: 108 printf(": no charger\n"); 109 } 110 111 void 112 gpiocharger_update_charger(void *arg) 113 { 114 struct gpiocharger_softc *sc = arg; 115 116 sc->sc_sensor.value = gpio_controller_get_pin(sc->sc_charger_pin); 117 } 118