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