xref: /freebsd/sys/dev/gpio/qoriq_gpio.c (revision f7c32ed617858bcd22f8d1b03199099d50125721)
1 /*-
2  * Copyright (c) 2020 Alstom Group.
3  * Copyright (c) 2020 Semihalf.
4  * Copyright (c) 2015 Justin Hibbits
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  * $FreeBSD$
29  */
30 
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/conf.h>
37 #include <sys/bus.h>
38 #include <sys/kernel.h>
39 #include <sys/module.h>
40 #include <sys/mutex.h>
41 #include <sys/rman.h>
42 #include <sys/gpio.h>
43 
44 #include <machine/bus.h>
45 #include <machine/resource.h>
46 #include <machine/stdarg.h>
47 
48 #include <dev/gpio/gpiobusvar.h>
49 #include <dev/gpio/qoriq_gpio.h>
50 #include <dev/ofw/ofw_bus.h>
51 #include <dev/ofw/ofw_bus_subr.h>
52 
53 #include "gpio_if.h"
54 
55 static device_t
56 qoriq_gpio_get_bus(device_t dev)
57 {
58 	struct qoriq_gpio_softc *sc;
59 
60 	sc = device_get_softc(dev);
61 
62 	return (sc->busdev);
63 }
64 
65 static int
66 qoriq_gpio_pin_max(device_t dev, int *maxpin)
67 {
68 
69 	*maxpin = MAXPIN;
70 	return (0);
71 }
72 
73 /* Get a specific pin's capabilities. */
74 static int
75 qoriq_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
76 {
77 	struct qoriq_gpio_softc *sc;
78 
79 	sc = device_get_softc(dev);
80 
81 	if (!VALID_PIN(pin))
82 		return (EINVAL);
83 
84 	GPIO_LOCK(sc);
85 	*caps = sc->sc_pins[pin].gp_caps;
86 	GPIO_UNLOCK(sc);
87 
88 	return (0);
89 }
90 
91 /* Get a specific pin's name. */
92 static int
93 qoriq_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
94 {
95 
96 	if (!VALID_PIN(pin))
97 		return (EINVAL);
98 
99 	snprintf(name, GPIOMAXNAME, "qoriq_gpio%d.%d",
100 	    device_get_unit(dev), pin);
101 	name[GPIOMAXNAME-1] = '\0';
102 
103 	return (0);
104 }
105 
106 static int
107 qoriq_gpio_pin_configure(device_t dev, uint32_t pin, uint32_t flags)
108 {
109 	struct qoriq_gpio_softc *sc;
110 	uint32_t reg;
111 
112 	sc = device_get_softc(dev);
113 
114 	if ((flags & sc->sc_pins[pin].gp_caps) != flags) {
115 		return (EINVAL);
116 	}
117 
118 	if (flags & GPIO_PIN_INPUT) {
119 		reg = bus_read_4(sc->sc_mem, GPIO_GPDIR);
120 		reg &= ~(1 << (31 - pin));
121 		bus_write_4(sc->sc_mem, GPIO_GPDIR, reg);
122 	}
123 	else if (flags & GPIO_PIN_OUTPUT) {
124 		reg = bus_read_4(sc->sc_mem, GPIO_GPDIR);
125 		reg |= (1 << (31 - pin));
126 		bus_write_4(sc->sc_mem, GPIO_GPDIR, reg);
127 		reg = bus_read_4(sc->sc_mem, GPIO_GPODR);
128 		if (flags & GPIO_PIN_OPENDRAIN)
129 			reg |= (1 << (31 - pin));
130 		else
131 			reg &= ~(1 << (31 - pin));
132 		bus_write_4(sc->sc_mem, GPIO_GPODR, reg);
133 	}
134 	sc->sc_pins[pin].gp_flags = flags;
135 
136 	return (0);
137 }
138 
139 /* Set flags for the pin. */
140 static int
141 qoriq_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
142 {
143 	struct qoriq_gpio_softc *sc = device_get_softc(dev);
144 	uint32_t ret;
145 
146 	if (!VALID_PIN(pin))
147 		return (EINVAL);
148 
149 	if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) ==
150 	    (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT))
151 		return (EINVAL);
152 
153 	GPIO_LOCK(sc);
154 	ret = qoriq_gpio_pin_configure(dev, pin, flags);
155 	GPIO_UNLOCK(sc);
156 	return (0);
157 }
158 
159 static int
160 qoriq_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *pflags)
161 {
162 	struct qoriq_gpio_softc *sc;
163 
164 	if (!VALID_PIN(pin))
165 		return (EINVAL);
166 
167 	sc = device_get_softc(dev);
168 
169 	GPIO_LOCK(sc);
170 	*pflags = sc->sc_pins[pin].gp_flags;
171 	GPIO_UNLOCK(sc);
172 
173 	return (0);
174 }
175 
176 /* Set a specific output pin's value. */
177 static int
178 qoriq_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
179 {
180 	struct qoriq_gpio_softc *sc = device_get_softc(dev);
181 	uint32_t outvals;
182 	uint8_t pinbit;
183 
184 	if (!VALID_PIN(pin) || value > 1)
185 		return (EINVAL);
186 
187 	GPIO_LOCK(sc);
188 	pinbit = 31 - pin;
189 
190 	outvals = bus_read_4(sc->sc_mem, GPIO_GPDAT);
191 	outvals &= ~(1 << pinbit);
192 	outvals |= (value << pinbit);
193 	bus_write_4(sc->sc_mem, GPIO_GPDAT, outvals);
194 
195 	GPIO_UNLOCK(sc);
196 
197 	return (0);
198 }
199 
200 /* Get a specific pin's input value. */
201 static int
202 qoriq_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
203 {
204 	struct qoriq_gpio_softc *sc = device_get_softc(dev);
205 
206 	if (!VALID_PIN(pin))
207 		return (EINVAL);
208 
209 	*value = (bus_read_4(sc->sc_mem, GPIO_GPDAT) >> (31 - pin)) & 1;
210 
211 	return (0);
212 }
213 
214 /* Toggle a pin's output value. */
215 static int
216 qoriq_gpio_pin_toggle(device_t dev, uint32_t pin)
217 {
218 	struct qoriq_gpio_softc *sc = device_get_softc(dev);
219 	uint32_t val;
220 
221 	if (!VALID_PIN(pin))
222 		return (EINVAL);
223 
224 	GPIO_LOCK(sc);
225 
226 	val = bus_read_4(sc->sc_mem, GPIO_GPDAT);
227 	val ^= (1 << (31 - pin));
228 	bus_write_4(sc->sc_mem, GPIO_GPDAT, val);
229 
230 	GPIO_UNLOCK(sc);
231 
232 	return (0);
233 }
234 
235 static struct ofw_compat_data gpio_matches[] = {
236     {"fsl,pq3-gpio", 1},
237     {"fsl,mpc8572-gpio", 1},
238     {0, 0}
239 };
240 
241 static int
242 qoriq_gpio_probe(device_t dev)
243 {
244 
245 	if (ofw_bus_search_compatible(dev, gpio_matches)->ocd_data == 0)
246 		return (ENXIO);
247 
248 	device_set_desc(dev, "Freescale QorIQ GPIO driver");
249 
250 	return (0);
251 }
252 
253 static int
254 qoriq_gpio_pin_access_32(device_t dev, uint32_t first_pin, uint32_t clear_pins,
255     uint32_t change_pins, uint32_t *orig_pins)
256 {
257 	struct qoriq_gpio_softc *sc;
258 	uint32_t hwstate;
259 
260 	sc = device_get_softc(dev);
261 
262 	if (first_pin != 0)
263 		return (EINVAL);
264 
265 	GPIO_LOCK(sc);
266 	hwstate = bus_read_4(sc->sc_mem, GPIO_GPDAT);
267 	bus_write_4(sc->sc_mem, GPIO_GPDAT,
268 	    (hwstate & ~clear_pins) ^ change_pins);
269 	GPIO_UNLOCK(sc);
270 
271 	if (orig_pins != NULL)
272 		*orig_pins = hwstate;
273 
274 	return (0);
275 }
276 
277 static int
278 qoriq_gpio_pin_config_32(device_t dev, uint32_t first_pin, uint32_t num_pins,
279     uint32_t *pin_flags)
280 {
281 	uint32_t dir, odr, mask, reg;
282 	struct qoriq_gpio_softc *sc;
283 	uint32_t newflags[32];
284 	int i;
285 
286 	if (first_pin != 0 || !VALID_PIN(num_pins))
287 		return (EINVAL);
288 
289 	sc = device_get_softc(dev);
290 
291 	dir = odr = mask = 0;
292 
293 	for (i = 0; i < num_pins; i++) {
294 		newflags[i] = 0;
295 		mask |= (1 << i);
296 
297 		if (pin_flags[i] & GPIO_PIN_INPUT) {
298 			newflags[i] = GPIO_PIN_INPUT;
299 			dir &= ~(1 << i);
300 		} else {
301 			newflags[i] = GPIO_PIN_OUTPUT;
302 			dir |= (1 << i);
303 
304 			if (pin_flags[i] & GPIO_PIN_OPENDRAIN) {
305 				newflags[i] |= GPIO_PIN_OPENDRAIN;
306 				odr |= (1 << i);
307 			} else {
308 				newflags[i] |= GPIO_PIN_PUSHPULL;
309 				odr &= ~(1 << i);
310 			}
311 		}
312 	}
313 
314 	GPIO_LOCK(sc);
315 
316 	reg = (bus_read_4(sc->sc_mem, GPIO_GPDIR) & ~mask) | dir;
317 	bus_write_4(sc->sc_mem, GPIO_GPDIR, reg);
318 
319 	reg = (bus_read_4(sc->sc_mem, GPIO_GPODR) & ~mask) | odr;
320 	bus_write_4(sc->sc_mem, GPIO_GPODR, reg);
321 
322 	for (i = 0; i < num_pins; i++)
323 		sc->sc_pins[i].gp_flags = newflags[i];
324 
325 	GPIO_UNLOCK(sc);
326 
327 	return (0);
328 }
329 
330 static int
331 qoriq_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
332     pcell_t *gpios, uint32_t *pin, uint32_t *flags)
333 {
334 	struct qoriq_gpio_softc *sc;
335 	int err;
336 
337 	if (!VALID_PIN(gpios[0]))
338 		return (EINVAL);
339 
340 	sc = device_get_softc(bus);
341 	GPIO_LOCK(sc);
342 	err = qoriq_gpio_pin_configure(bus, gpios[0], gpios[1]);
343 	GPIO_UNLOCK(sc);
344 
345 	if (err == 0) {
346 		*pin = gpios[0];
347 		*flags = gpios[1];
348 	}
349 
350 	return (err);
351 }
352 
353 int
354 qoriq_gpio_attach(device_t dev)
355 {
356 	struct qoriq_gpio_softc *sc = device_get_softc(dev);
357 	int i, rid;
358 
359 	sc->dev = dev;
360 
361 	GPIO_LOCK_INIT(sc);
362 
363 	/* Allocate memory. */
364 	rid = 0;
365 	sc->sc_mem = bus_alloc_resource_any(dev,
366 		     SYS_RES_MEMORY, &rid, RF_ACTIVE);
367 	if (sc->sc_mem == NULL) {
368 		device_printf(dev, "Can't allocate memory for device output port");
369 		qoriq_gpio_detach(dev);
370 		return (ENOMEM);
371 	}
372 
373 	for (i = 0; i <= MAXPIN; i++)
374 		sc->sc_pins[i].gp_caps = DEFAULT_CAPS;
375 
376 	sc->busdev = gpiobus_attach_bus(dev);
377 	if (sc->busdev == NULL) {
378 		qoriq_gpio_detach(dev);
379 		return (ENOMEM);
380 	}
381 	/*
382 	 * Enable the GPIO Input Buffer for all GPIOs.
383 	 * This is safe on devices without a GPIBE register, because those
384 	 * devices ignore writes and read 0's in undefined portions of the map.
385 	 */
386 	if (ofw_bus_is_compatible(dev, "fsl,qoriq-gpio"))
387 		bus_write_4(sc->sc_mem, GPIO_GPIBE, 0xffffffff);
388 
389 	OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev);
390 
391 	return (0);
392 }
393 
394 int
395 qoriq_gpio_detach(device_t dev)
396 {
397 	struct qoriq_gpio_softc *sc = device_get_softc(dev);
398 
399 	gpiobus_detach_bus(dev);
400 
401 	if (sc->sc_mem != NULL) {
402 		/* Release output port resource. */
403 		bus_release_resource(dev, SYS_RES_MEMORY,
404 				     rman_get_rid(sc->sc_mem), sc->sc_mem);
405 	}
406 
407 	GPIO_LOCK_DESTROY(sc);
408 
409 	return (0);
410 }
411 
412 static device_method_t qoriq_gpio_methods[] = {
413 	/* device_if */
414 	DEVMETHOD(device_probe, 	qoriq_gpio_probe),
415 	DEVMETHOD(device_attach, 	qoriq_gpio_attach),
416 	DEVMETHOD(device_detach, 	qoriq_gpio_detach),
417 
418 	/* GPIO protocol */
419 	DEVMETHOD(gpio_get_bus, 	qoriq_gpio_get_bus),
420 	DEVMETHOD(gpio_pin_max, 	qoriq_gpio_pin_max),
421 	DEVMETHOD(gpio_pin_getname, 	qoriq_gpio_pin_getname),
422 	DEVMETHOD(gpio_pin_getcaps, 	qoriq_gpio_pin_getcaps),
423 	DEVMETHOD(gpio_pin_get, 	qoriq_gpio_pin_get),
424 	DEVMETHOD(gpio_pin_set, 	qoriq_gpio_pin_set),
425 	DEVMETHOD(gpio_pin_getflags, 	qoriq_gpio_pin_getflags),
426 	DEVMETHOD(gpio_pin_setflags, 	qoriq_gpio_pin_setflags),
427 	DEVMETHOD(gpio_pin_toggle, 	qoriq_gpio_pin_toggle),
428 
429 	DEVMETHOD(gpio_map_gpios,	qoriq_gpio_map_gpios),
430 	DEVMETHOD(gpio_pin_access_32,	qoriq_gpio_pin_access_32),
431 	DEVMETHOD(gpio_pin_config_32,	qoriq_gpio_pin_config_32),
432 
433 	DEVMETHOD_END
434 };
435 
436 static devclass_t qoriq_gpio_devclass;
437 
438 DEFINE_CLASS_0(gpio, qoriq_gpio_driver, qoriq_gpio_methods,
439     sizeof(struct qoriq_gpio_softc));
440 
441 EARLY_DRIVER_MODULE(qoriq_gpio, simplebus, qoriq_gpio_driver,
442     qoriq_gpio_devclass, NULL, NULL,
443     BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
444