xref: /freebsd/sys/arm64/qoriq/qoriq_gpio_pic.c (revision 1323ec571215a77ddd21294f0871979d5ad6b992)
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 static devclass_t qoriq_gpio_pic_devclass;
434 
435 DEFINE_CLASS_1(gpio, qoriq_gpio_pic_driver, qoriq_gpio_pic_methods,
436     sizeof(struct qoriq_gpio_pic_softc), qoriq_gpio_driver);
437 EARLY_DRIVER_MODULE(qoriq_gpio_pic, simplebus, qoriq_gpio_pic_driver,
438     qoriq_gpio_pic_devclass, NULL, NULL,
439     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
440