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