Line data Source code
1 : /* $OpenBSD: bytgpio.c,v 1.13 2018/04/30 18:47:48 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(int, 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 0 : bytgpio_match(struct device *parent, void *match, void *aux)
115 : {
116 0 : struct acpi_attach_args *aaa = aux;
117 0 : struct cfdata *cf = match;
118 :
119 0 : return acpi_matchhids(aaa, bytgpio_hids, cf->cf_driver->cd_name);
120 : }
121 :
122 : void
123 0 : bytgpio_attach(struct device *parent, struct device *self, void *aux)
124 : {
125 0 : struct acpi_attach_args *aaa = aux;
126 0 : struct bytgpio_softc *sc = (struct bytgpio_softc *)self;
127 0 : struct aml_value res;
128 0 : int64_t uid;
129 : uint32_t reg;
130 : int i;
131 :
132 0 : sc->sc_acpi = (struct acpi_softc *)parent;
133 0 : sc->sc_node = aaa->aaa_node;
134 0 : printf(": %s", sc->sc_node->name);
135 :
136 0 : if (aml_evalinteger(sc->sc_acpi, sc->sc_node, "_UID", 0, NULL, &uid)) {
137 0 : printf(", can't find uid\n");
138 0 : return;
139 : }
140 :
141 0 : printf(" uid %lld", uid);
142 :
143 0 : switch (uid) {
144 : case 1:
145 0 : sc->sc_pins = byt_score_pins;
146 0 : sc->sc_npins = nitems(byt_score_pins);
147 0 : break;
148 : case 2:
149 0 : sc->sc_pins = byt_ncore_pins;
150 0 : sc->sc_npins = nitems(byt_ncore_pins);
151 0 : break;
152 : case 3:
153 0 : sc->sc_pins = byt_sus_pins;
154 0 : sc->sc_npins = nitems(byt_sus_pins);
155 0 : break;
156 : default:
157 0 : printf("\n");
158 0 : return;
159 : }
160 :
161 0 : if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) {
162 0 : printf(", can't find registers\n");
163 0 : return;
164 : }
165 :
166 0 : aml_parse_resource(&res, bytgpio_parse_resources, sc);
167 0 : printf(" addr 0x%lx/0x%lx", sc->sc_addr, sc->sc_size);
168 0 : if (sc->sc_addr == 0 || sc->sc_size == 0) {
169 0 : printf("\n");
170 0 : return;
171 : }
172 0 : aml_freevalue(&res);
173 :
174 0 : sc->sc_pin_ih = mallocarray(sc->sc_npins, sizeof(*sc->sc_pin_ih),
175 : M_DEVBUF, M_NOWAIT | M_ZERO);
176 0 : if (sc->sc_pin_ih == NULL) {
177 0 : printf("\n");
178 0 : return;
179 : }
180 :
181 0 : printf(" irq %d", sc->sc_irq);
182 :
183 0 : sc->sc_memt = aaa->aaa_memt;
184 0 : if (bus_space_map(sc->sc_memt, sc->sc_addr, sc->sc_size, 0,
185 0 : &sc->sc_memh)) {
186 0 : printf(", can't map registers\n");
187 0 : goto free;
188 : }
189 :
190 0 : sc->sc_ih = acpi_intr_establish(sc->sc_irq, sc->sc_irq_flags, IPL_BIO,
191 0 : bytgpio_intr, sc, sc->sc_dev.dv_xname);
192 0 : if (sc->sc_ih == NULL) {
193 0 : printf(", can't establish interrupt\n");
194 : goto unmap;
195 : }
196 :
197 0 : sc->sc_gpio.cookie = sc;
198 0 : sc->sc_gpio.read_pin = bytgpio_read_pin;
199 0 : sc->sc_gpio.write_pin = bytgpio_write_pin;
200 0 : sc->sc_gpio.intr_establish = bytgpio_intr_establish;
201 0 : sc->sc_node->gpio = &sc->sc_gpio;
202 :
203 : /* Mask all interrupts. */
204 0 : for (i = 0; i < sc->sc_npins; i++) {
205 0 : reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[i] * 16);
206 :
207 : /*
208 : * Skip pins configured as direct IRQ. Those are tied
209 : * directly to the APIC.
210 : */
211 0 : if (reg & BYTGPIO_CONF_DIRECT_IRQ_EN)
212 : continue;
213 :
214 0 : reg &= ~BYTGPIO_CONF_GD_MASK;
215 0 : bus_space_write_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[i] * 16, reg);
216 0 : }
217 :
218 0 : printf(", %d pins\n", sc->sc_npins);
219 :
220 0 : acpi_register_gpio(sc->sc_acpi, sc->sc_node);
221 0 : return;
222 :
223 : unmap:
224 0 : bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_size);
225 : free:
226 0 : free(sc->sc_pin_ih, M_DEVBUF, sc->sc_npins * sizeof(*sc->sc_pin_ih));
227 0 : }
228 :
229 : int
230 0 : bytgpio_parse_resources(int crsidx, union acpi_resource *crs, void *arg)
231 : {
232 0 : struct bytgpio_softc *sc = arg;
233 0 : int type = AML_CRSTYPE(crs);
234 :
235 0 : switch (type) {
236 : case LR_MEM32FIXED:
237 0 : sc->sc_addr = crs->lr_m32fixed._bas;
238 0 : sc->sc_size = crs->lr_m32fixed._len;
239 0 : break;
240 : case LR_EXTIRQ:
241 0 : sc->sc_irq = crs->lr_extirq.irq[0];
242 0 : sc->sc_irq_flags = crs->lr_extirq.flags;
243 0 : break;
244 : default:
245 0 : printf(" type 0x%x\n", type);
246 0 : break;
247 : }
248 :
249 0 : return 0;
250 : }
251 :
252 : int
253 0 : bytgpio_read_pin(void *cookie, int pin)
254 : {
255 0 : struct bytgpio_softc *sc = cookie;
256 : uint32_t reg;
257 :
258 0 : reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16 + 8);
259 0 : return (reg & BYTGPIO_PAD_VAL);
260 : }
261 :
262 : void
263 0 : bytgpio_write_pin(void *cookie, int pin, int value)
264 : {
265 0 : struct bytgpio_softc *sc = cookie;
266 : uint32_t reg;
267 :
268 0 : reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16 + 8);
269 0 : if (value)
270 0 : reg |= BYTGPIO_PAD_VAL;
271 : else
272 0 : reg &= ~BYTGPIO_PAD_VAL;
273 0 : bus_space_write_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16 + 8, reg);
274 0 : }
275 :
276 : void
277 0 : bytgpio_intr_establish(void *cookie, int pin, int flags,
278 : int (*func)(void *), void *arg)
279 : {
280 0 : struct bytgpio_softc *sc = cookie;
281 : uint32_t reg;
282 :
283 0 : KASSERT(pin >= 0 && pin < sc->sc_npins);
284 :
285 0 : sc->sc_pin_ih[pin].ih_func = func;
286 0 : sc->sc_pin_ih[pin].ih_arg = arg;
287 :
288 0 : reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16);
289 0 : reg &= ~BYTGPIO_CONF_GD_MASK;
290 0 : if ((flags & LR_GPIO_MODE) == 0)
291 0 : reg |= BYTGPIO_CONF_GD_LEVEL;
292 0 : if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTLO)
293 0 : reg |= BYTGPIO_CONF_GD_TNE;
294 0 : if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTHI)
295 0 : reg |= BYTGPIO_CONF_GD_TPE;
296 0 : if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTBOTH)
297 0 : reg |= BYTGPIO_CONF_GD_TNE | BYTGPIO_CONF_GD_TPE;
298 0 : bus_space_write_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16, reg);
299 0 : }
300 :
301 : int
302 0 : bytgpio_intr(void *arg)
303 : {
304 0 : struct bytgpio_softc *sc = arg;
305 : uint32_t reg;
306 : int rc = 0;
307 : int pin;
308 :
309 0 : for (pin = 0; pin < sc->sc_npins; pin++) {
310 0 : if (pin % 32 == 0) {
311 0 : reg = bus_space_read_4(sc->sc_memt, sc->sc_memh,
312 : BYTGPIO_IRQ_TS_0 + (pin / 8));
313 0 : bus_space_write_4(sc->sc_memt, sc->sc_memh,
314 : BYTGPIO_IRQ_TS_0 + (pin / 8), reg);
315 0 : }
316 0 : if (reg & (1 << (pin % 32))) {
317 0 : if (sc->sc_pin_ih[pin].ih_func)
318 0 : sc->sc_pin_ih[pin].ih_func(sc->sc_pin_ih[pin].ih_arg);
319 : rc = 1;
320 0 : }
321 : }
322 :
323 0 : return rc;
324 : }
|