xref: /openbsd/sys/dev/acpi/bytgpio.c (revision 244d7b17)
1 /*	$OpenBSD: bytgpio.c,v 1.18 2022/10/20 20:40:57 kettenis Exp $	*/
2 /*
3  * Copyright (c) 2016 Mark Kettenis
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/malloc.h>
20 #include <sys/systm.h>
21 
22 #include <dev/acpi/acpireg.h>
23 #include <dev/acpi/acpivar.h>
24 #include <dev/acpi/acpidev.h>
25 #include <dev/acpi/amltypes.h>
26 #include <dev/acpi/dsdt.h>
27 
28 #define BYTGPIO_CONF_GD_LEVEL	0x01000000
29 #define BYTGPIO_CONF_GD_TPE	0x02000000
30 #define BYTGPIO_CONF_GD_TNE	0x04000000
31 #define BYTGPIO_CONF_GD_MASK	0x07000000
32 #define BYTGPIO_CONF_DIRECT_IRQ_EN	0x08000000
33 
34 #define BYTGPIO_PAD_VAL		0x00000001
35 
36 #define BYTGPIO_IRQ_TS_0	0x800
37 #define BYTGPIO_IRQ_TS_1	0x804
38 #define BYTGPIO_IRQ_TS_2	0x808
39 
40 struct bytgpio_intrhand {
41 	int (*ih_func)(void *);
42 	void *ih_arg;
43 	int ih_tflags;
44 };
45 
46 struct bytgpio_softc {
47 	struct device sc_dev;
48 	struct acpi_softc *sc_acpi;
49 	struct aml_node *sc_node;
50 
51 	bus_space_tag_t sc_memt;
52 	bus_space_handle_t sc_memh;
53 	void *sc_ih;
54 
55 	const int *sc_pins;
56 	int sc_npins;
57 	struct bytgpio_intrhand *sc_pin_ih;
58 
59 	struct acpi_gpio sc_gpio;
60 };
61 
62 int	bytgpio_match(struct device *, void *, void *);
63 void	bytgpio_attach(struct device *, struct device *, void *);
64 
65 const struct cfattach bytgpio_ca = {
66 	sizeof(struct bytgpio_softc), bytgpio_match, bytgpio_attach
67 };
68 
69 struct cfdriver bytgpio_cd = {
70 	NULL, "bytgpio", DV_DULL
71 };
72 
73 const char *bytgpio_hids[] = {
74 	"INT33FC",
75 	NULL
76 };
77 
78 /*
79  * The pads for the pins are randomly ordered.
80  */
81 
82 const int byt_score_pins[] = {
83 	85, 89, 93, 96, 99, 102, 98, 101, 34, 37, 36, 38, 39, 35, 40,
84 	84, 62, 61, 64, 59, 54, 56, 60, 55, 63, 57, 51, 50, 53, 47,
85 	52, 49, 48, 43, 46, 41, 45, 42, 58, 44, 95, 105, 70, 68, 67,
86 	66, 69, 71, 65, 72, 86, 90, 88, 92, 103, 77, 79, 83, 78, 81,
87 	80, 82, 13, 12, 15, 14, 17, 18, 19, 16, 2, 1, 0, 4, 6, 7, 9,
88 	8, 33, 32, 31, 30, 29, 27, 25, 28, 26, 23, 21, 20, 24, 22, 5,
89 	3, 10, 11, 106, 87, 91, 104, 97, 100
90 };
91 
92 const int byt_ncore_pins[] = {
93 	19, 18, 17, 20, 21, 22, 24, 25, 23, 16, 14, 15, 12, 26, 27,
94 	1, 4, 8, 11, 0, 3, 6, 10, 13, 2, 5, 9, 7
95 };
96 
97 const int byt_sus_pins[] = {
98         29, 33, 30, 31, 32, 34, 36, 35, 38, 37, 18, 7, 11, 20, 17, 1,
99 	8, 10, 19, 12, 0, 2, 23, 39, 28, 27, 22, 21, 24, 25, 26, 51,
100 	56, 54, 49, 55, 48, 57, 50, 58, 52, 53, 59, 40
101 };
102 
103 int	bytgpio_read_pin(void *, int);
104 void	bytgpio_write_pin(void *, int, int);
105 void	bytgpio_intr_establish(void *, int, int, int (*)(void *), void *);
106 void	bytgpio_intr_enable(void *, int);
107 void	bytgpio_intr_disable(void *, int);
108 int	bytgpio_intr(void *);
109 
110 int
bytgpio_match(struct device * parent,void * match,void * aux)111 bytgpio_match(struct device *parent, void *match, void *aux)
112 {
113 	struct acpi_attach_args *aaa = aux;
114 	struct cfdata *cf = match;
115 
116 	if (aaa->aaa_naddr < 1 || aaa->aaa_nirq < 1)
117 		return 0;
118 	return acpi_matchhids(aaa, bytgpio_hids, cf->cf_driver->cd_name);
119 }
120 
121 void
bytgpio_attach(struct device * parent,struct device * self,void * aux)122 bytgpio_attach(struct device *parent, struct device *self, void *aux)
123 {
124 	struct bytgpio_softc *sc = (struct bytgpio_softc *)self;
125 	struct acpi_attach_args *aaa = aux;
126 	int64_t uid;
127 	uint32_t reg;
128 	int i;
129 
130 	sc->sc_acpi = (struct acpi_softc *)parent;
131 	sc->sc_node = aaa->aaa_node;
132 	printf(" %s", sc->sc_node->name);
133 
134 	if (aml_evalinteger(sc->sc_acpi, sc->sc_node, "_UID", 0, NULL, &uid)) {
135 		printf(": can't find uid\n");
136 		return;
137 	}
138 
139 	printf(" uid %lld", uid);
140 
141 	switch (uid) {
142 	case 1:
143 		sc->sc_pins = byt_score_pins;
144 		sc->sc_npins = nitems(byt_score_pins);
145 		break;
146 	case 2:
147 		sc->sc_pins = byt_ncore_pins;
148 		sc->sc_npins = nitems(byt_ncore_pins);
149 		break;
150 	case 3:
151 		sc->sc_pins = byt_sus_pins;
152 		sc->sc_npins = nitems(byt_sus_pins);
153 		break;
154 	default:
155 		printf("\n");
156 		return;
157 	}
158 
159 	printf(" addr 0x%llx/0x%llx", aaa->aaa_addr[0], aaa->aaa_size[0]);
160 	printf(" irq %d", aaa->aaa_irq[0]);
161 
162 	sc->sc_memt = aaa->aaa_bst[0];
163 	if (bus_space_map(sc->sc_memt, aaa->aaa_addr[0], aaa->aaa_size[0],
164 	    0, &sc->sc_memh)) {
165 		printf(": can't map registers\n");
166 		return;
167 	}
168 
169 	sc->sc_pin_ih = mallocarray(sc->sc_npins, sizeof(*sc->sc_pin_ih),
170 	    M_DEVBUF, M_WAITOK | M_ZERO);
171 
172 	sc->sc_ih = acpi_intr_establish(aaa->aaa_irq[0], aaa->aaa_irq_flags[0],
173 	    IPL_BIO, bytgpio_intr, sc, sc->sc_dev.dv_xname);
174 	if (sc->sc_ih == NULL) {
175 		printf(": can't establish interrupt\n");
176 		goto unmap;
177 	}
178 
179 	sc->sc_gpio.cookie = sc;
180 	sc->sc_gpio.read_pin = bytgpio_read_pin;
181 	sc->sc_gpio.write_pin = bytgpio_write_pin;
182 	sc->sc_gpio.intr_establish = bytgpio_intr_establish;
183 	sc->sc_gpio.intr_enable = bytgpio_intr_enable;
184 	sc->sc_gpio.intr_disable = bytgpio_intr_disable;
185 	sc->sc_node->gpio = &sc->sc_gpio;
186 
187 	/* Mask all interrupts. */
188 	for (i = 0; i < sc->sc_npins; i++) {
189 		reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[i] * 16);
190 
191 		/*
192 		 * Skip pins configured as direct IRQ.  Those are tied
193 		 * directly to the APIC.
194 		 */
195 		if (reg & BYTGPIO_CONF_DIRECT_IRQ_EN)
196 			continue;
197 
198 		reg &= ~BYTGPIO_CONF_GD_MASK;
199 		bus_space_write_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[i] * 16, reg);
200 	}
201 
202 	printf(", %d pins\n", sc->sc_npins);
203 
204 	acpi_register_gpio(sc->sc_acpi, sc->sc_node);
205 	return;
206 
207 unmap:
208 	free(sc->sc_pin_ih, M_DEVBUF, sc->sc_npins * sizeof(*sc->sc_pin_ih));
209 	bus_space_unmap(sc->sc_memt, sc->sc_memh, aaa->aaa_size[0]);
210 }
211 
212 int
bytgpio_read_pin(void * cookie,int pin)213 bytgpio_read_pin(void *cookie, int pin)
214 {
215 	struct bytgpio_softc *sc = cookie;
216 	uint32_t reg;
217 
218 	reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16 + 8);
219 	return (reg & BYTGPIO_PAD_VAL);
220 }
221 
222 void
bytgpio_write_pin(void * cookie,int pin,int value)223 bytgpio_write_pin(void *cookie, int pin, int value)
224 {
225 	struct bytgpio_softc *sc = cookie;
226 	uint32_t reg;
227 
228 	reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16 + 8);
229 	if (value)
230 		reg |= BYTGPIO_PAD_VAL;
231 	else
232 		reg &= ~BYTGPIO_PAD_VAL;
233 	bus_space_write_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16 + 8, reg);
234 }
235 
236 void
bytgpio_intr_establish(void * cookie,int pin,int flags,int (* func)(void *),void * arg)237 bytgpio_intr_establish(void *cookie, int pin, int flags,
238     int (*func)(void *), void *arg)
239 {
240 	struct bytgpio_softc *sc = cookie;
241 
242 	KASSERT(pin >= 0 && pin < sc->sc_npins);
243 
244 	sc->sc_pin_ih[pin].ih_func = func;
245 	sc->sc_pin_ih[pin].ih_arg = arg;
246 	sc->sc_pin_ih[pin].ih_tflags = flags;
247 
248 	bytgpio_intr_enable(cookie, pin);
249 }
250 
251 void
bytgpio_intr_enable(void * cookie,int pin)252 bytgpio_intr_enable(void *cookie, int pin)
253 {
254 	struct bytgpio_softc *sc = cookie;
255 	uint32_t reg;
256 	int flags;
257 
258 	KASSERT(pin >= 0 && pin < sc->sc_npins);
259 
260 	flags = sc->sc_pin_ih[pin].ih_tflags;
261 
262 	reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16);
263 	reg &= ~BYTGPIO_CONF_GD_MASK;
264 	if ((flags & LR_GPIO_MODE) == 0)
265 		reg |= BYTGPIO_CONF_GD_LEVEL;
266 	if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTLO)
267 		reg |= BYTGPIO_CONF_GD_TNE;
268 	if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTHI)
269 		reg |= BYTGPIO_CONF_GD_TPE;
270 	if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTBOTH)
271 		reg |= BYTGPIO_CONF_GD_TNE | BYTGPIO_CONF_GD_TPE;
272 	bus_space_write_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16, reg);
273 }
274 
275 void
bytgpio_intr_disable(void * cookie,int pin)276 bytgpio_intr_disable(void *cookie, int pin)
277 {
278 	struct bytgpio_softc *sc = cookie;
279 	uint32_t reg;
280 
281 	KASSERT(pin >= 0 && pin < sc->sc_npins);
282 
283 	reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16);
284 	reg &= ~BYTGPIO_CONF_GD_MASK;
285 	bus_space_write_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16, reg);
286 }
287 
288 int
bytgpio_intr(void * arg)289 bytgpio_intr(void *arg)
290 {
291 	struct bytgpio_softc *sc = arg;
292 	uint32_t reg;
293 	int rc = 0;
294 	int pin;
295 
296 	for (pin = 0; pin < sc->sc_npins; pin++) {
297 		if (pin % 32 == 0) {
298 			reg = bus_space_read_4(sc->sc_memt, sc->sc_memh,
299 			    BYTGPIO_IRQ_TS_0 + (pin / 8));
300 			bus_space_write_4(sc->sc_memt, sc->sc_memh,
301 			    BYTGPIO_IRQ_TS_0 + (pin / 8), reg);
302 		}
303 		if (reg & (1 << (pin % 32))) {
304 			if (sc->sc_pin_ih[pin].ih_func)
305 				sc->sc_pin_ih[pin].ih_func(sc->sc_pin_ih[pin].ih_arg);
306 			rc = 1;
307 		}
308 	}
309 
310 	return rc;
311 }
312