xref: /freebsd/sys/arm/xilinx/zy7_gpio.c (revision d0b2dbfa0ecf2bbc9709efc5e20baf8e4b44bbbf)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2013 Thomas Skibo
5  * All rights reserved.
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 AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 /*
30  * A GPIO driver for Xilinx Zynq-7000.
31  *
32  * The GPIO peripheral on Zynq allows controlling 114 general purpose I/Os.
33  *
34  * Pins 53-0 are sent to the MIO.  Any MIO pins not used by a PS peripheral are
35  * available as a GPIO pin.  Pins 64-127 are sent to the PL (FPGA) section of
36  * Zynq as EMIO signals.
37  *
38  * The hardware provides a way to use IOs as interrupt sources but the
39  * gpio framework doesn't seem to have hooks for this.
40  *
41  * Reference: Zynq-7000 All Programmable SoC Technical Reference Manual.
42  * (v1.4) November 16, 2012.  Xilinx doc UG585.  GPIO is covered in
43  * chater 14.  Register definitions are in appendix B.19.
44  */
45 
46 #include <sys/cdefs.h>
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/conf.h>
50 #include <sys/bus.h>
51 #include <sys/kernel.h>
52 #include <sys/module.h>
53 #include <sys/lock.h>
54 #include <sys/mutex.h>
55 #include <sys/resource.h>
56 #include <sys/rman.h>
57 #include <sys/gpio.h>
58 
59 #include <machine/bus.h>
60 #include <machine/resource.h>
61 #include <machine/stdarg.h>
62 
63 #include <dev/gpio/gpiobusvar.h>
64 #include <dev/ofw/ofw_bus.h>
65 #include <dev/ofw/ofw_bus_subr.h>
66 
67 #include "gpio_if.h"
68 
69 #define	ZYNQ7_MAX_BANK		4
70 #define	ZYNQMP_MAX_BANK		6
71 
72 /* Zynq 7000 */
73 #define	ZYNQ7_BANK0_PIN_MIN	0
74 #define	ZYNQ7_BANK0_NPIN	32
75 #define	ZYNQ7_BANK1_PIN_MIN	32
76 #define	ZYNQ7_BANK1_NPIN	22
77 #define	ZYNQ7_BANK2_PIN_MIN	64
78 #define	ZYNQ7_BANK2_NPIN	32
79 #define	ZYNQ7_BANK3_PIN_MIN	96
80 #define	ZYNQ7_BANK3_NPIN	32
81 #define	ZYNQ7_PIN_MIO_MIN	0
82 #define	ZYNQ7_PIN_MIO_MAX	54
83 #define	ZYNQ7_PIN_EMIO_MIN	64
84 #define	ZYNQ7_PIN_EMIO_MAX	118
85 
86 /* ZynqMP */
87 #define	ZYNQMP_BANK0_PIN_MIN	0
88 #define	ZYNQMP_BANK0_NPIN	26
89 #define	ZYNQMP_BANK1_PIN_MIN	26
90 #define	ZYNQMP_BANK1_NPIN	26
91 #define	ZYNQMP_BANK2_PIN_MIN	52
92 #define	ZYNQMP_BANK2_NPIN	26
93 #define	ZYNQMP_BANK3_PIN_MIN	78
94 #define	ZYNQMP_BANK3_NPIN	32
95 #define	ZYNQMP_BANK4_PIN_MIN	110
96 #define	ZYNQMP_BANK4_NPIN	32
97 #define	ZYNQMP_BANK5_PIN_MIN	142
98 #define	ZYNQMP_BANK5_NPIN	32
99 #define	ZYNQMP_PIN_MIO_MIN	0
100 #define	ZYNQMP_PIN_MIO_MAX	77
101 #define	ZYNQMP_PIN_EMIO_MIN	78
102 #define	ZYNQMP_PIN_EMIO_MAX	174
103 
104 #define	ZYNQ_BANK_NPIN(type, bank)	(ZYNQ##type##_BANK##bank##_NPIN)
105 #define	ZYNQ_BANK_PIN_MIN(type, bank)	(ZYNQ##type##_BANK##bank##_PIN_MIN)
106 #define	ZYNQ_BANK_PIN_MAX(type, bank)	(ZYNQ##type##_BANK##bank##_PIN_MIN + ZYNQ##type##_BANK##bank##_NPIN - 1)
107 
108 #define	ZYNQ_PIN_IS_MIO(type, pin)	(pin >= ZYNQ##type##_PIN_MIO_MIN &&	\
109 	  pin <= ZYNQ##type##_PIN_MIO_MAX)
110 #define	ZYNQ_PIN_IS_EMIO(type, pin)	(pin >= ZYNQ##type##_PIN_EMIO_MIN &&	\
111 	  pin <= ZYNQ##type##_PIN_EMIO_MAX)
112 
113 #define ZGPIO_LOCK(sc)			mtx_lock(&(sc)->sc_mtx)
114 #define	ZGPIO_UNLOCK(sc)		mtx_unlock(&(sc)->sc_mtx)
115 #define ZGPIO_LOCK_INIT(sc) \
116 	mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->dev),	\
117 	    "gpio", MTX_DEF)
118 #define ZGPIO_LOCK_DESTROY(_sc)	mtx_destroy(&_sc->sc_mtx);
119 
120 enum zynq_gpio_type {
121 	ZYNQ_7000 = 0,
122 	ZYNQMP,
123 };
124 
125 struct zynq_gpio_conf {
126 	char			*name;
127 	enum zynq_gpio_type	type;
128 	uint32_t		nbanks;
129 	uint32_t		maxpin;
130 	uint32_t		bank_min[ZYNQMP_MAX_BANK];
131 	uint32_t		bank_max[ZYNQMP_MAX_BANK];
132 };
133 
134 struct zy7_gpio_softc {
135 	device_t		dev;
136 	device_t		busdev;
137 	struct mtx		sc_mtx;
138 	struct resource		*mem_res;	/* Memory resource */
139 	struct zynq_gpio_conf	*conf;
140 };
141 
142 static struct zynq_gpio_conf z7_gpio_conf = {
143 	.name = "Zynq-7000 GPIO Controller",
144 	.type = ZYNQ_7000,
145 	.nbanks = ZYNQ7_MAX_BANK,
146 	.maxpin = ZYNQ7_PIN_EMIO_MAX,
147 	.bank_min[0] = ZYNQ_BANK_PIN_MIN(7, 0),
148 	.bank_max[0] = ZYNQ_BANK_PIN_MAX(7, 0),
149 	.bank_min[1] = ZYNQ_BANK_PIN_MIN(7, 1),
150 	.bank_max[1] = ZYNQ_BANK_PIN_MAX(7, 1),
151 	.bank_min[2] = ZYNQ_BANK_PIN_MIN(7, 2),
152 	.bank_max[2] = ZYNQ_BANK_PIN_MAX(7, 2),
153 	.bank_min[3] = ZYNQ_BANK_PIN_MIN(7, 3),
154 	.bank_max[3] = ZYNQ_BANK_PIN_MAX(7, 3),
155 };
156 
157 static struct zynq_gpio_conf zynqmp_gpio_conf = {
158 	.name = "ZynqMP GPIO Controller",
159 	.type = ZYNQMP,
160 	.nbanks = ZYNQMP_MAX_BANK,
161 	.maxpin = ZYNQMP_PIN_EMIO_MAX,
162 	.bank_min[0] = ZYNQ_BANK_PIN_MIN(MP, 0),
163 	.bank_max[0] = ZYNQ_BANK_PIN_MAX(MP, 0),
164 	.bank_min[1] = ZYNQ_BANK_PIN_MIN(MP, 1),
165 	.bank_max[1] = ZYNQ_BANK_PIN_MAX(MP, 1),
166 	.bank_min[2] = ZYNQ_BANK_PIN_MIN(MP, 2),
167 	.bank_max[2] = ZYNQ_BANK_PIN_MAX(MP, 2),
168 	.bank_min[3] = ZYNQ_BANK_PIN_MIN(MP, 3),
169 	.bank_max[3] = ZYNQ_BANK_PIN_MAX(MP, 3),
170 	.bank_min[4] = ZYNQ_BANK_PIN_MIN(MP, 4),
171 	.bank_max[4] = ZYNQ_BANK_PIN_MAX(MP, 4),
172 	.bank_min[5] = ZYNQ_BANK_PIN_MIN(MP, 5),
173 	.bank_max[5] = ZYNQ_BANK_PIN_MAX(MP, 5),
174 };
175 
176 static struct ofw_compat_data compat_data[] = {
177 	{"xlnx,zy7_gpio",		(uintptr_t)&z7_gpio_conf},
178 	{"xlnx,zynqmp-gpio-1.0",	(uintptr_t)&zynqmp_gpio_conf},
179 	{NULL, 0},
180 };
181 
182 #define WR4(sc, off, val)	bus_write_4((sc)->mem_res, (off), (val))
183 #define RD4(sc, off)		bus_read_4((sc)->mem_res, (off))
184 
185 /* Xilinx Zynq-7000 GPIO register definitions:
186  */
187 #define ZY7_GPIO_MASK_DATA_LSW(b)	(0x0000+8*(b))	/* maskable wr lo */
188 #define ZY7_GPIO_MASK_DATA_MSW(b)	(0x0004+8*(b))	/* maskable wr hi */
189 #define ZY7_GPIO_DATA(b)		(0x0040+4*(b))	/* in/out data */
190 #define ZY7_GPIO_DATA_RO(b)		(0x0060+4*(b))	/* input data */
191 
192 #define ZY7_GPIO_DIRM(b)		(0x0204+0x40*(b)) /* direction mode */
193 #define ZY7_GPIO_OEN(b)			(0x0208+0x40*(b)) /* output enable */
194 #define ZY7_GPIO_INT_MASK(b)		(0x020c+0x40*(b)) /* int mask */
195 #define ZY7_GPIO_INT_EN(b)		(0x0210+0x40*(b)) /* int enable */
196 #define ZY7_GPIO_INT_DIS(b)		(0x0214+0x40*(b)) /* int disable */
197 #define ZY7_GPIO_INT_STAT(b)		(0x0218+0x40*(b)) /* int status */
198 #define ZY7_GPIO_INT_TYPE(b)		(0x021c+0x40*(b)) /* int type */
199 #define ZY7_GPIO_INT_POLARITY(b)	(0x0220+0x40*(b)) /* int polarity */
200 #define ZY7_GPIO_INT_ANY(b)		(0x0224+0x40*(b)) /* any edge */
201 
202 static device_t
203 zy7_gpio_get_bus(device_t dev)
204 {
205 	struct zy7_gpio_softc *sc;
206 
207 	sc = device_get_softc(dev);
208 
209 	return (sc->busdev);
210 }
211 
212 static int
213 zy7_gpio_pin_max(device_t dev, int *maxpin)
214 {
215 	struct zy7_gpio_softc *sc;
216 
217 	sc = device_get_softc(dev);
218 	*maxpin = sc->conf->maxpin;
219 	return (0);
220 }
221 
222 static inline bool
223 zy7_pin_valid(device_t dev, uint32_t pin)
224 {
225 	struct zy7_gpio_softc *sc;
226 	int i;
227 	bool found = false;
228 
229 	sc = device_get_softc(dev);
230 	for (i = 0; i < sc->conf->nbanks; i++) {
231 		if (pin >= sc->conf->bank_min[i] && pin <= sc->conf->bank_max[i]) {
232 			found = true;
233 			break;
234 		}
235 	}
236 
237 	return (found);
238 }
239 
240 /* Get a specific pin's capabilities. */
241 static int
242 zy7_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
243 {
244 
245 	if (!zy7_pin_valid(dev, pin))
246 		return (EINVAL);
247 
248 	*caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE);
249 
250 	return (0);
251 }
252 
253 /* Get a specific pin's name. */
254 static int
255 zy7_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
256 {
257 	struct zy7_gpio_softc *sc;
258 	uint32_t emio_min;
259 	bool is_mio;
260 
261 	sc = device_get_softc(dev);
262 	if (!zy7_pin_valid(dev, pin))
263 		return (EINVAL);
264 
265 	switch (sc->conf->type) {
266 	case ZYNQ_7000:
267 		is_mio = ZYNQ_PIN_IS_MIO(7, pin);
268 		emio_min = ZYNQ7_PIN_EMIO_MIN;
269 		break;
270 	case ZYNQMP:
271 		is_mio = ZYNQ_PIN_IS_MIO(MP, pin);
272 		emio_min = ZYNQMP_PIN_EMIO_MIN;
273 		break;
274 	default:
275 		return (EINVAL);
276 	}
277 	if (is_mio) {
278 		snprintf(name, GPIOMAXNAME, "MIO_%d", pin);
279 		name[GPIOMAXNAME - 1] = '\0';
280 	} else {
281 		snprintf(name, GPIOMAXNAME, "EMIO_%d", pin - emio_min);
282 		name[GPIOMAXNAME - 1] = '\0';
283 	}
284 
285 	return (0);
286 }
287 
288 /* Get a specific pin's current in/out/tri state. */
289 static int
290 zy7_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
291 {
292 	struct zy7_gpio_softc *sc = device_get_softc(dev);
293 
294 	if (!zy7_pin_valid(dev, pin))
295 		return (EINVAL);
296 
297 	ZGPIO_LOCK(sc);
298 
299 	if ((RD4(sc, ZY7_GPIO_DIRM(pin >> 5)) & (1 << (pin & 31))) != 0) {
300 		/* output */
301 		if ((RD4(sc, ZY7_GPIO_OEN(pin >> 5)) & (1 << (pin & 31))) == 0)
302 			*flags = (GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE);
303 		else
304 			*flags = GPIO_PIN_OUTPUT;
305 	} else
306 		/* input */
307 		*flags = GPIO_PIN_INPUT;
308 
309 	ZGPIO_UNLOCK(sc);
310 
311 	return (0);
312 }
313 
314 /* Set a specific pin's in/out/tri state. */
315 static int
316 zy7_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
317 {
318 	struct zy7_gpio_softc *sc = device_get_softc(dev);
319 
320 	if (!zy7_pin_valid(dev, pin))
321 		return (EINVAL);
322 
323 	ZGPIO_LOCK(sc);
324 
325 	if ((flags & GPIO_PIN_OUTPUT) != 0) {
326 		/* Output.  Set or reset OEN too. */
327 		WR4(sc, ZY7_GPIO_DIRM(pin >> 5),
328 		    RD4(sc, ZY7_GPIO_DIRM(pin >> 5)) | (1 << (pin & 31)));
329 
330 		if ((flags & GPIO_PIN_TRISTATE) != 0)
331 			WR4(sc, ZY7_GPIO_OEN(pin >> 5),
332 			    RD4(sc, ZY7_GPIO_OEN(pin >> 5)) &
333 			    ~(1 << (pin & 31)));
334 		else
335 			WR4(sc, ZY7_GPIO_OEN(pin >> 5),
336 			    RD4(sc, ZY7_GPIO_OEN(pin >> 5)) |
337 			    (1 << (pin & 31)));
338 	} else {
339 		/* Input.  Turn off OEN. */
340 		WR4(sc, ZY7_GPIO_DIRM(pin >> 5),
341 		    RD4(sc, ZY7_GPIO_DIRM(pin >> 5)) & ~(1 << (pin & 31)));
342 		WR4(sc, ZY7_GPIO_OEN(pin >> 5),
343 		    RD4(sc, ZY7_GPIO_OEN(pin >> 5)) & ~(1 << (pin & 31)));
344 	}
345 
346 	ZGPIO_UNLOCK(sc);
347 
348 	return (0);
349 }
350 
351 /* Set a specific output pin's value. */
352 static int
353 zy7_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
354 {
355 	struct zy7_gpio_softc *sc = device_get_softc(dev);
356 
357 	if (!zy7_pin_valid(dev, pin) || value > 1)
358 		return (EINVAL);
359 
360 	/* Fancy register tricks allow atomic set or reset. */
361 	if ((pin & 16) != 0)
362 		WR4(sc, ZY7_GPIO_MASK_DATA_MSW(pin >> 5),
363 		    (0xffff0000 ^ (0x10000 << (pin & 15))) |
364 		    (value << (pin & 15)));
365 	else
366 		WR4(sc, ZY7_GPIO_MASK_DATA_LSW(pin >> 5),
367 		    (0xffff0000 ^ (0x10000 << (pin & 15))) |
368 		    (value << (pin & 15)));
369 
370 	return (0);
371 }
372 
373 /* Get a specific pin's input value. */
374 static int
375 zy7_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
376 {
377 	struct zy7_gpio_softc *sc = device_get_softc(dev);
378 
379 	if (!zy7_pin_valid(dev, pin))
380 		return (EINVAL);
381 
382 	*value = (RD4(sc, ZY7_GPIO_DATA_RO(pin >> 5)) >> (pin & 31)) & 1;
383 
384 	return (0);
385 }
386 
387 /* Toggle a pin's output value. */
388 static int
389 zy7_gpio_pin_toggle(device_t dev, uint32_t pin)
390 {
391 	struct zy7_gpio_softc *sc = device_get_softc(dev);
392 
393 	if (!zy7_pin_valid(dev, pin))
394 		return (EINVAL);
395 
396 	ZGPIO_LOCK(sc);
397 
398 	WR4(sc, ZY7_GPIO_DATA(pin >> 5),
399 	    RD4(sc, ZY7_GPIO_DATA(pin >> 5)) ^ (1 << (pin & 31)));
400 
401 	ZGPIO_UNLOCK(sc);
402 
403 	return (0);
404 }
405 
406 static int
407 zy7_gpio_probe(device_t dev)
408 {
409 	struct zynq_gpio_conf *conf;
410 
411 	if (!ofw_bus_status_okay(dev))
412 		return (ENXIO);
413 
414 	conf = (struct zynq_gpio_conf *)ofw_bus_search_compatible(dev, compat_data)->ocd_data;
415 	if (conf == 0)
416 		return (ENXIO);
417 
418 	device_set_desc(dev, conf->name);
419 	return (0);
420 }
421 
422 static int zy7_gpio_detach(device_t dev);
423 
424 static int
425 zy7_gpio_attach(device_t dev)
426 {
427 	struct zy7_gpio_softc *sc = device_get_softc(dev);
428 	int rid;
429 
430 	sc->dev = dev;
431 	sc->conf = (struct zynq_gpio_conf *)ofw_bus_search_compatible(dev, compat_data)->ocd_data;
432 
433 	ZGPIO_LOCK_INIT(sc);
434 
435 	/* Allocate memory. */
436 	rid = 0;
437 	sc->mem_res = bus_alloc_resource_any(dev,
438 		     SYS_RES_MEMORY, &rid, RF_ACTIVE);
439 	if (sc->mem_res == NULL) {
440 		device_printf(dev, "Can't allocate memory for device");
441 		zy7_gpio_detach(dev);
442 		return (ENOMEM);
443 	}
444 
445 	sc->busdev = gpiobus_attach_bus(dev);
446 	if (sc->busdev == NULL) {
447 		zy7_gpio_detach(dev);
448 		return (ENOMEM);
449 	}
450 
451 	return (0);
452 }
453 
454 static int
455 zy7_gpio_detach(device_t dev)
456 {
457 	struct zy7_gpio_softc *sc = device_get_softc(dev);
458 
459 	gpiobus_detach_bus(dev);
460 
461 	if (sc->mem_res != NULL) {
462 		/* Release memory resource. */
463 		bus_release_resource(dev, SYS_RES_MEMORY,
464 				     rman_get_rid(sc->mem_res), sc->mem_res);
465 	}
466 
467 	ZGPIO_LOCK_DESTROY(sc);
468 
469 	return (0);
470 }
471 
472 static device_method_t zy7_gpio_methods[] = {
473 	/* device_if */
474 	DEVMETHOD(device_probe, 	zy7_gpio_probe),
475 	DEVMETHOD(device_attach, 	zy7_gpio_attach),
476 	DEVMETHOD(device_detach, 	zy7_gpio_detach),
477 
478 	/* GPIO protocol */
479 	DEVMETHOD(gpio_get_bus, 	zy7_gpio_get_bus),
480 	DEVMETHOD(gpio_pin_max, 	zy7_gpio_pin_max),
481 	DEVMETHOD(gpio_pin_getname, 	zy7_gpio_pin_getname),
482 	DEVMETHOD(gpio_pin_getflags, 	zy7_gpio_pin_getflags),
483 	DEVMETHOD(gpio_pin_getcaps, 	zy7_gpio_pin_getcaps),
484 	DEVMETHOD(gpio_pin_setflags, 	zy7_gpio_pin_setflags),
485 	DEVMETHOD(gpio_pin_get, 	zy7_gpio_pin_get),
486 	DEVMETHOD(gpio_pin_set, 	zy7_gpio_pin_set),
487 	DEVMETHOD(gpio_pin_toggle, 	zy7_gpio_pin_toggle),
488 
489 	DEVMETHOD_END
490 };
491 
492 static driver_t zy7_gpio_driver = {
493 	"gpio",
494 	zy7_gpio_methods,
495 	sizeof(struct zy7_gpio_softc),
496 };
497 
498 EARLY_DRIVER_MODULE(zy7_gpio, simplebus, zy7_gpio_driver, 0, 0,
499     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
500