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