1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2021 Alstom Group.
5 * Copyright (c) 2021 Semihalf.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/conf.h>
31 #include <sys/bus.h>
32 #include <sys/kernel.h>
33 #include <sys/module.h>
34 #include <sys/mutex.h>
35 #include <sys/proc.h>
36 #include <sys/rman.h>
37 #include <sys/gpio.h>
38
39 #include <machine/bus.h>
40 #include <machine/resource.h>
41 #include <machine/stdarg.h>
42
43 #include <dev/gpio/gpiobusvar.h>
44 #include <dev/gpio/qoriq_gpio.h>
45 #include <dev/ofw/ofw_bus.h>
46 #include <dev/ofw/ofw_bus_subr.h>
47
48 #include <dt-bindings/interrupt-controller/irq.h>
49
50 #include "gpio_if.h"
51 #include "pic_if.h"
52
53 struct qoriq_gpio_pic_irqsrc {
54 struct intr_irqsrc isrc;
55 int pin;
56 };
57
58 struct qoriq_gpio_pic_softc {
59 struct qoriq_gpio_softc base;
60
61 struct resource *res_irq;
62 void *irq_cookie;
63 struct qoriq_gpio_pic_irqsrc isrcs[MAXPIN + 1];
64 struct intr_map_data_gpio gdata;
65 };
66
67 #define RD4(sc, off) bus_read_4((sc)->base.sc_mem, (off))
68 #define WR4(sc, off, data) bus_write_4((sc)->base.sc_mem, (off), (data))
69
70 static device_probe_t qoriq_gpio_pic_probe;
71 static device_attach_t qoriq_gpio_pic_attach;
72 static device_detach_t qoriq_gpio_pic_detach;
73
74 static void
qoriq_gpio_pic_set_intr(struct qoriq_gpio_pic_softc * sc,int pin,bool enable)75 qoriq_gpio_pic_set_intr(struct qoriq_gpio_pic_softc *sc, int pin, bool enable)
76 {
77 uint32_t reg;
78
79 reg = RD4(sc, GPIO_GPIMR);
80 if (enable)
81 reg |= BIT(31 - pin);
82 else
83 reg &= ~BIT(31 - pin);
84 WR4(sc, GPIO_GPIMR, reg);
85 }
86
87 static void
qoriq_gpio_pic_ack_intr(struct qoriq_gpio_pic_softc * sc,int pin)88 qoriq_gpio_pic_ack_intr(struct qoriq_gpio_pic_softc *sc, int pin)
89 {
90 uint32_t reg;
91
92 reg = BIT(31 - pin);
93 WR4(sc, GPIO_GPIER, reg);
94 }
95
96 static int
qoriq_gpio_pic_intr(void * arg)97 qoriq_gpio_pic_intr(void *arg)
98 {
99 struct qoriq_gpio_pic_softc *sc;
100 struct trapframe *tf;
101 uint32_t status;
102 int pin;
103
104 sc = (struct qoriq_gpio_pic_softc *)arg;
105 tf = curthread->td_intr_frame;
106
107 status = RD4(sc, GPIO_GPIER);
108 status &= RD4(sc, GPIO_GPIMR);
109 while (status != 0) {
110 pin = ffs(status) - 1;
111 status &= ~BIT(pin);
112 pin = 31 - pin;
113
114 if (intr_isrc_dispatch(&sc->isrcs[pin].isrc, tf) != 0) {
115 GPIO_LOCK(&sc->base);
116 qoriq_gpio_pic_set_intr(sc, pin, false);
117 qoriq_gpio_pic_ack_intr(sc, pin);
118 GPIO_UNLOCK(&sc->base);
119 device_printf(sc->base.dev,
120 "Masking spurious pin interrupt %d\n",
121 pin);
122 }
123 }
124
125 return (FILTER_HANDLED);
126 }
127
128 static void
qoriq_gpio_pic_disable_intr(device_t dev,struct intr_irqsrc * isrc)129 qoriq_gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
130 {
131 struct qoriq_gpio_pic_softc *sc;
132 struct qoriq_gpio_pic_irqsrc *qisrc;
133
134 sc = device_get_softc(dev);
135 qisrc = (struct qoriq_gpio_pic_irqsrc *)isrc;
136
137 GPIO_LOCK(&sc->base);
138 qoriq_gpio_pic_set_intr(sc, qisrc->pin, false);
139 GPIO_UNLOCK(&sc->base);
140 }
141
142 static void
qoriq_gpio_pic_enable_intr(device_t dev,struct intr_irqsrc * isrc)143 qoriq_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
144 {
145 struct qoriq_gpio_pic_softc *sc;
146 struct qoriq_gpio_pic_irqsrc *qisrc;
147
148 sc = device_get_softc(dev);
149 qisrc = (struct qoriq_gpio_pic_irqsrc *)isrc;
150
151 GPIO_LOCK(&sc->base);
152 qoriq_gpio_pic_set_intr(sc, qisrc->pin, true);
153 GPIO_UNLOCK(&sc->base);
154 }
155
156 static struct intr_map_data_gpio*
qoriq_gpio_pic_convert_map_data(struct qoriq_gpio_pic_softc * sc,struct intr_map_data * data)157 qoriq_gpio_pic_convert_map_data(struct qoriq_gpio_pic_softc *sc, struct intr_map_data *data)
158 {
159 struct intr_map_data_gpio *gdata;
160 struct intr_map_data_fdt *daf;
161
162 switch (data->type) {
163 case INTR_MAP_DATA_GPIO:
164 gdata = (struct intr_map_data_gpio *)data;
165 break;
166 case INTR_MAP_DATA_FDT:
167 daf = (struct intr_map_data_fdt *)data;
168 if (daf->ncells != 2)
169 return (NULL);
170
171 gdata = &sc->gdata;
172 gdata->gpio_pin_num = daf->cells[0];
173 switch (daf->cells[1]) {
174 case IRQ_TYPE_LEVEL_LOW:
175 gdata->gpio_intr_mode = GPIO_INTR_LEVEL_LOW;
176 break;
177 case IRQ_TYPE_LEVEL_HIGH:
178 gdata->gpio_intr_mode = GPIO_INTR_LEVEL_HIGH;
179 break;
180 case IRQ_TYPE_EDGE_RISING:
181 gdata->gpio_intr_mode = GPIO_INTR_EDGE_RISING;
182 break;
183 case IRQ_TYPE_EDGE_FALLING:
184 gdata->gpio_intr_mode = GPIO_INTR_EDGE_FALLING;
185 break;
186 case IRQ_TYPE_EDGE_BOTH:
187 gdata->gpio_intr_mode = GPIO_INTR_EDGE_BOTH;
188 break;
189 default:
190 return (NULL);
191 }
192 break;
193 default:
194 return (NULL);
195 }
196
197 return (gdata);
198 }
199
200
201 static int
qoriq_gpio_pic_map_intr(device_t dev,struct intr_map_data * data,struct intr_irqsrc ** isrcp)202 qoriq_gpio_pic_map_intr(device_t dev, struct intr_map_data *data,
203 struct intr_irqsrc **isrcp)
204 {
205 struct qoriq_gpio_pic_softc *sc;
206 struct intr_map_data_gpio *gdata;
207 int pin;
208
209 sc = device_get_softc(dev);
210
211 gdata = qoriq_gpio_pic_convert_map_data(sc, data);
212 if (gdata == NULL)
213 return (EINVAL);
214
215 pin = gdata->gpio_pin_num;
216 if (pin > MAXPIN)
217 return (EINVAL);
218
219 *isrcp = &sc->isrcs[pin].isrc;
220 return (0);
221 }
222
223 static int
qoriq_gpio_pic_setup_intr(device_t dev,struct intr_irqsrc * isrc,struct resource * res,struct intr_map_data * data)224 qoriq_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
225 struct resource *res, struct intr_map_data *data)
226 {
227 struct qoriq_gpio_pic_softc *sc;
228 struct intr_map_data_gpio *gdata;
229 struct qoriq_gpio_pic_irqsrc *qisrc;
230 bool falling;
231 uint32_t reg;
232
233 sc = device_get_softc(dev);
234 qisrc = (struct qoriq_gpio_pic_irqsrc *)isrc;
235
236 gdata = qoriq_gpio_pic_convert_map_data(sc, data);
237 if (gdata == NULL)
238 return (EINVAL);
239
240 if (gdata->gpio_intr_mode & GPIO_INTR_EDGE_BOTH)
241 falling = false;
242 else if (gdata->gpio_intr_mode & GPIO_INTR_EDGE_FALLING)
243 falling = true;
244 else
245 return (EOPNOTSUPP);
246
247 GPIO_LOCK(&sc->base);
248 reg = RD4(sc, GPIO_GPICR);
249 if (falling)
250 reg |= BIT(31 - qisrc->pin);
251 else
252 reg &= ~BIT(31 - qisrc->pin);
253 WR4(sc, GPIO_GPICR, reg);
254 GPIO_UNLOCK(&sc->base);
255
256 return (0);
257 }
258
259 static int
qoriq_gpio_pic_teardown_intr(device_t dev,struct intr_irqsrc * isrc,struct resource * res,struct intr_map_data * data)260 qoriq_gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
261 struct resource *res, struct intr_map_data *data)
262 {
263 struct qoriq_gpio_pic_softc *sc;
264 struct qoriq_gpio_pic_irqsrc *qisrc;
265
266 sc = device_get_softc(dev);
267 qisrc = (struct qoriq_gpio_pic_irqsrc *)isrc;
268
269 if (isrc->isrc_handlers > 0)
270 return (0);
271
272 GPIO_LOCK(&sc->base);
273 qoriq_gpio_pic_set_intr(sc, qisrc->pin, false);
274 GPIO_UNLOCK(&sc->base);
275 return (0);
276 }
277
278 static void
qoriq_gpio_pic_post_filter(device_t dev,struct intr_irqsrc * isrc)279 qoriq_gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
280 {
281 struct qoriq_gpio_pic_softc *sc;
282 struct qoriq_gpio_pic_irqsrc *qisrc;
283
284 sc = device_get_softc(dev);
285 qisrc = (struct qoriq_gpio_pic_irqsrc *)isrc;
286
287 GPIO_LOCK(&sc->base);
288 qoriq_gpio_pic_ack_intr(sc, qisrc->pin);
289 GPIO_UNLOCK(&sc->base);
290 }
291
292
293 static void
qoriq_gpio_pic_post_ithread(device_t dev,struct intr_irqsrc * isrc)294 qoriq_gpio_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
295 {
296 struct qoriq_gpio_pic_softc *sc;
297 struct qoriq_gpio_pic_irqsrc *qisrc;
298
299 sc = device_get_softc(dev);
300 qisrc = (struct qoriq_gpio_pic_irqsrc *)isrc;
301
302 GPIO_LOCK(&sc->base);
303 qoriq_gpio_pic_ack_intr(sc, qisrc->pin);
304 qoriq_gpio_pic_set_intr(sc, qisrc->pin, true);
305 GPIO_UNLOCK(&sc->base);
306 }
307
308 static void
qoriq_gpio_pic_pre_ithread(device_t dev,struct intr_irqsrc * isrc)309 qoriq_gpio_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
310 {
311 struct qoriq_gpio_pic_softc *sc;
312 struct qoriq_gpio_pic_irqsrc *qisrc;
313
314 sc = device_get_softc(dev);
315 qisrc = (struct qoriq_gpio_pic_irqsrc *)isrc;
316
317 GPIO_LOCK(&sc->base);
318 qoriq_gpio_pic_set_intr(sc, qisrc->pin, false);
319 GPIO_UNLOCK(&sc->base);
320
321 }
322 static int
qoriq_gpio_pic_probe(device_t dev)323 qoriq_gpio_pic_probe(device_t dev)
324 {
325 if (!ofw_bus_status_okay(dev))
326 return (ENXIO);
327
328 if (!ofw_bus_is_compatible(dev, "fsl,qoriq-gpio"))
329 return (ENXIO);
330
331 device_set_desc(dev, "Freescale QorIQ GPIO PIC driver");
332
333 return (BUS_PROBE_DEFAULT);
334 }
335
336 static int
qoriq_gpio_pic_attach(device_t dev)337 qoriq_gpio_pic_attach(device_t dev)
338 {
339 struct qoriq_gpio_pic_softc *sc;
340 int error, rid, i;
341 const char *name;
342 intptr_t xref;
343
344 sc = device_get_softc(dev);
345
346 error = qoriq_gpio_attach(dev);
347 if (error != 0)
348 return (error);
349
350 rid = 0;
351 sc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
352 RF_ACTIVE | RF_SHAREABLE);
353 if (sc->res_irq == NULL) {
354 device_printf(dev, "Can't allocate interrupt resource.\n");
355 error = ENOMEM;
356 goto fail;
357 }
358
359 error = bus_setup_intr(dev, sc->res_irq, INTR_TYPE_MISC | INTR_MPSAFE,
360 qoriq_gpio_pic_intr, NULL, sc, &sc->irq_cookie);
361 if (error != 0) {
362 device_printf(dev, "Failed to setup interrupt.\n");
363 goto fail;
364 }
365
366 name = device_get_nameunit(dev);
367 for (i = 0; i <= MAXPIN; i++) {
368 sc->isrcs[i].pin = i;
369 error = intr_isrc_register(&sc->isrcs[i].isrc,
370 dev, 0, "%s,%u", name, i);
371 if (error != 0)
372 goto fail;
373 }
374
375 xref = OF_xref_from_node(ofw_bus_get_node(dev));
376 if (intr_pic_register(dev, xref) == NULL) {
377 error = ENXIO;
378 goto fail;
379 }
380
381 /* ACK and mask all interrupts. */
382 WR4(sc, GPIO_GPIER, 0xffffffff);
383 WR4(sc, GPIO_GPIMR, 0);
384
385 return (0);
386 fail:
387 qoriq_gpio_pic_detach(dev);
388 return (error);
389 }
390
391 static int
qoriq_gpio_pic_detach(device_t dev)392 qoriq_gpio_pic_detach(device_t dev)
393 {
394 struct qoriq_gpio_pic_softc *sc;
395
396 sc = device_get_softc(dev);
397
398 if (sc->irq_cookie != NULL)
399 bus_teardown_intr(dev, sc->res_irq, sc->irq_cookie);
400
401 if (sc->res_irq != NULL)
402 bus_release_resource(dev, SYS_RES_IRQ,
403 rman_get_rid(sc->res_irq), sc->res_irq);
404
405 return (qoriq_gpio_detach(dev));
406 }
407
408
409 static device_method_t qoriq_gpio_pic_methods[] = {
410 DEVMETHOD(device_probe, qoriq_gpio_pic_probe),
411 DEVMETHOD(device_attach, qoriq_gpio_pic_attach),
412 DEVMETHOD(device_detach, qoriq_gpio_pic_detach),
413
414 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
415 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
416 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
417
418 DEVMETHOD(pic_disable_intr, qoriq_gpio_pic_disable_intr),
419 DEVMETHOD(pic_enable_intr, qoriq_gpio_pic_enable_intr),
420 DEVMETHOD(pic_map_intr, qoriq_gpio_pic_map_intr),
421 DEVMETHOD(pic_setup_intr, qoriq_gpio_pic_setup_intr),
422 DEVMETHOD(pic_teardown_intr, qoriq_gpio_pic_teardown_intr),
423 DEVMETHOD(pic_post_filter, qoriq_gpio_pic_post_filter),
424 DEVMETHOD(pic_post_ithread, qoriq_gpio_pic_post_ithread),
425 DEVMETHOD(pic_pre_ithread, qoriq_gpio_pic_pre_ithread),
426
427 DEVMETHOD_END
428 };
429
430 DEFINE_CLASS_1(gpio, qoriq_gpio_pic_driver, qoriq_gpio_pic_methods,
431 sizeof(struct qoriq_gpio_pic_softc), qoriq_gpio_driver);
432 EARLY_DRIVER_MODULE(qoriq_gpio_pic, simplebus, qoriq_gpio_pic_driver, NULL, NULL,
433 BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
434