xref: /freebsd/sys/arm64/qoriq/qoriq_gpio_pic.c (revision 95eb4b873b6a8b527c5bd78d7191975dfca38998)
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
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
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
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
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
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*
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
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
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
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
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
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
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
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
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
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