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 (ret);
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 {"fsl,qoriq-gpio", 1},
239 {0, 0}
240 };
241
242 static int
243 qoriq_gpio_probe(device_t dev)
244 {
245
246 if (ofw_bus_search_compatible(dev, gpio_matches)->ocd_data == 0)
247 return (ENXIO);
248
249 device_set_desc(dev, "Freescale QorIQ GPIO driver");
250
251 return (0);
252 }
253
254 static int
255 qoriq_gpio_pin_access_32(device_t dev, uint32_t first_pin, uint32_t clear_pins,
256 uint32_t change_pins, uint32_t *orig_pins)
257 {
258 struct qoriq_gpio_softc *sc;
259 uint32_t hwstate;
260
261 sc = device_get_softc(dev);
262
263 if (first_pin != 0)
264 return (EINVAL);
265
266 GPIO_LOCK(sc);
267 hwstate = bus_read_4(sc->sc_mem, GPIO_GPDAT);
268 bus_write_4(sc->sc_mem, GPIO_GPDAT,
269 (hwstate & ~clear_pins) ^ change_pins);
270 GPIO_UNLOCK(sc);
271
272 if (orig_pins != NULL)
273 *orig_pins = hwstate;
274
275 return (0);
276 }
277
278 static int
279 qoriq_gpio_pin_config_32(device_t dev, uint32_t first_pin, uint32_t num_pins,
280 uint32_t *pin_flags)
281 {
282 uint32_t dir, odr, mask, reg;
283 struct qoriq_gpio_softc *sc;
284 uint32_t newflags[32];
285 int i;
286
287 if (first_pin != 0 || !VALID_PIN(num_pins))
288 return (EINVAL);
289
290 sc = device_get_softc(dev);
291
292 dir = odr = mask = 0;
293
294 for (i = 0; i < num_pins; i++) {
295 newflags[i] = 0;
296 mask |= (1 << i);
297
298 if (pin_flags[i] & GPIO_PIN_INPUT) {
299 newflags[i] = GPIO_PIN_INPUT;
300 dir &= ~(1 << i);
301 } else {
302 newflags[i] = GPIO_PIN_OUTPUT;
303 dir |= (1 << i);
304
305 if (pin_flags[i] & GPIO_PIN_OPENDRAIN) {
306 newflags[i] |= GPIO_PIN_OPENDRAIN;
307 odr |= (1 << i);
308 } else {
309 newflags[i] |= GPIO_PIN_PUSHPULL;
310 odr &= ~(1 << i);
311 }
312 }
313 }
314
315 GPIO_LOCK(sc);
316
317 reg = (bus_read_4(sc->sc_mem, GPIO_GPDIR) & ~mask) | dir;
318 bus_write_4(sc->sc_mem, GPIO_GPDIR, reg);
319
320 reg = (bus_read_4(sc->sc_mem, GPIO_GPODR) & ~mask) | odr;
321 bus_write_4(sc->sc_mem, GPIO_GPODR, reg);
322
323 for (i = 0; i < num_pins; i++)
324 sc->sc_pins[i].gp_flags = newflags[i];
325
326 GPIO_UNLOCK(sc);
327
328 return (0);
329 }
330
331 static int
332 qoriq_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
333 pcell_t *gpios, uint32_t *pin, uint32_t *flags)
334 {
335 struct qoriq_gpio_softc *sc;
336 int err;
337
338 if (!VALID_PIN(gpios[0]))
339 return (EINVAL);
340
341 sc = device_get_softc(bus);
342 GPIO_LOCK(sc);
343 err = qoriq_gpio_pin_configure(bus, gpios[0], gpios[1]);
344 GPIO_UNLOCK(sc);
345
346 if (err == 0) {
347 *pin = gpios[0];
348 *flags = gpios[1];
349 }
350
351 return (err);
352 }
353
354 int
355 qoriq_gpio_attach(device_t dev)
356 {
357 struct qoriq_gpio_softc *sc = device_get_softc(dev);
358 int i, rid;
359
360 sc->dev = dev;
361
362 GPIO_LOCK_INIT(sc);
363
364 /* Allocate memory. */
365 rid = 0;
366 sc->sc_mem = bus_alloc_resource_any(dev,
367 SYS_RES_MEMORY, &rid, RF_ACTIVE);
368 if (sc->sc_mem == NULL) {
369 device_printf(dev, "Can't allocate memory for device output port");
370 qoriq_gpio_detach(dev);
371 return (ENOMEM);
372 }
373
374 for (i = 0; i <= MAXPIN; i++)
375 sc->sc_pins[i].gp_caps = DEFAULT_CAPS;
376
377 sc->busdev = gpiobus_attach_bus(dev);
378 if (sc->busdev == NULL) {
379 qoriq_gpio_detach(dev);
380 return (ENOMEM);
381 }
382 /*
383 * Enable the GPIO Input Buffer for all GPIOs.
384 * This is safe on devices without a GPIBE register, because those
385 * devices ignore writes and read 0's in undefined portions of the map.
386 */
387 if (ofw_bus_is_compatible(dev, "fsl,qoriq-gpio"))
388 bus_write_4(sc->sc_mem, GPIO_GPIBE, 0xffffffff);
389
390 OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev);
391
392 return (0);
393 }
394
395 int
396 qoriq_gpio_detach(device_t dev)
397 {
398 struct qoriq_gpio_softc *sc = device_get_softc(dev);
399
400 gpiobus_detach_bus(dev);
401
402 if (sc->sc_mem != NULL) {
403 /* Release output port resource. */
404 bus_release_resource(dev, SYS_RES_MEMORY,
405 rman_get_rid(sc->sc_mem), sc->sc_mem);
406 }
407
408 GPIO_LOCK_DESTROY(sc);
409
410 return (0);
411 }
412
413 static device_method_t qoriq_gpio_methods[] = {
414 /* device_if */
415 DEVMETHOD(device_probe, qoriq_gpio_probe),
416 DEVMETHOD(device_attach, qoriq_gpio_attach),
417 DEVMETHOD(device_detach, qoriq_gpio_detach),
418
419 /* GPIO protocol */
420 DEVMETHOD(gpio_get_bus, qoriq_gpio_get_bus),
421 DEVMETHOD(gpio_pin_max, qoriq_gpio_pin_max),
422 DEVMETHOD(gpio_pin_getname, qoriq_gpio_pin_getname),
423 DEVMETHOD(gpio_pin_getcaps, qoriq_gpio_pin_getcaps),
424 DEVMETHOD(gpio_pin_get, qoriq_gpio_pin_get),
425 DEVMETHOD(gpio_pin_set, qoriq_gpio_pin_set),
426 DEVMETHOD(gpio_pin_getflags, qoriq_gpio_pin_getflags),
427 DEVMETHOD(gpio_pin_setflags, qoriq_gpio_pin_setflags),
428 DEVMETHOD(gpio_pin_toggle, qoriq_gpio_pin_toggle),
429
430 DEVMETHOD(gpio_map_gpios, qoriq_gpio_map_gpios),
431 DEVMETHOD(gpio_pin_access_32, qoriq_gpio_pin_access_32),
432 DEVMETHOD(gpio_pin_config_32, qoriq_gpio_pin_config_32),
433
434 DEVMETHOD_END
435 };
436
437 DEFINE_CLASS_0(gpio, qoriq_gpio_driver, qoriq_gpio_methods,
438 sizeof(struct qoriq_gpio_softc));
439
440 EARLY_DRIVER_MODULE(qoriq_gpio, simplebus, qoriq_gpio_driver, NULL, NULL,
441 BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
Cache object: 9d0efc79b6e4de7402fa026ca9904b73
|