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