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