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