xref: /openbsd-src/sys/dev/fdt/gpiocharger.c (revision 471aeecfc619bc9b69519928152daf993376c2a1)
1 /*	$OpenBSD: gpiocharger.c,v 1.2 2022/04/06 18:59:28 naddy 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 const 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
gpiocharger_match(struct device * parent,void * match,void * aux)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
gpiocharger_attach(struct device * parent,struct device * self,void * aux)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
gpiocharger_update_charger(void * arg)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