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