]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/qoriq/ls1046_gpio.c
zfs: merge openzfs/zfs@4f92fe0f5 (zfs-2.1-release) into stable/13
[FreeBSD/FreeBSD.git] / sys / arm64 / qoriq / ls1046_gpio.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2020 Alstom Group.
5  * Copyright (c) 2020 Semihalf.
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
34 #include <sys/bus.h>
35 #include <sys/endian.h>
36 #include <sys/gpio.h>
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <sys/mutex.h>
40
41 #include <dev/gpio/gpiobusvar.h>
42 #include <dev/ofw/ofw_bus.h>
43 #include <machine/bus.h>
44
45 #include "gpio_if.h"
46
47 /* constants */
48 enum {
49         DIRECTION  = 0x0,
50         OPEN_DRAIN = 0x4,
51         DATA       = 0x8,
52         INT_EV     = 0xC,
53         INT_MASK   = 0x10,
54         INT_CTRL   = 0x14
55 };
56
57 #define PIN_COUNT 32
58 #define DEFAULT_CAPS                            \
59         (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |     \
60         GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)
61 #define GPIO(n) (1 << (31 - (n)))
62
63 struct gpio_res {
64         int mem_rid;
65         struct resource *mem_res;
66 };
67
68 /* software context */
69 struct gpio_softc {
70         device_t           dev;
71         device_t           busdev;
72         struct gpio_res    res;
73         struct gpio_pin    setup[PIN_COUNT];
74         struct mtx         mutex;
75 };
76
77 #define QORIQ_GPIO_LOCK(_sc)          mtx_lock_spin(&(_sc)->mutex)
78 #define QORIQ_GPIO_UNLOCK(_sc)        mtx_unlock_spin(&(_sc)->mutex)
79 #define QORIQ_GPIO_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->mutex, MA_OWNED)
80
81 /* prototypes */
82 /* helpers */
83 static bool qoriq_make_gpio_res(device_t, struct gpio_res*);
84 static uint32_t qoriq_gpio_reg_read(device_t, uint32_t);
85 static void qoriq_gpio_reg_write(device_t, uint32_t, uint32_t);
86 static void qoriq_gpio_set(device_t, uint32_t, uint32_t, uint32_t);
87 static int qoriq_gpio_configure(device_t, uint32_t, uint32_t);
88
89 /* GPIO API */
90 static int qoriq_gpio_probe(device_t);
91 static int qoriq_gpio_attach(device_t);
92 static device_t qoriq_gpio_get_bus(device_t);
93 static int qoriq_gpio_pin_max(device_t, int*);
94 static int qoriq_gpio_pin_getname(device_t, uint32_t, char*);
95 static int qoriq_gpio_pin_getflags(device_t, uint32_t, uint32_t*);
96 static int qoriq_gpio_pin_setflags(device_t, uint32_t, uint32_t);
97 static int qoriq_gpio_pin_getcaps(device_t, uint32_t, uint32_t*);
98 static int qoriq_gpio_pin_get(device_t, uint32_t, uint32_t*);
99 static int qoriq_gpio_pin_set(device_t, uint32_t, uint32_t);
100 static int qoriq_gpio_pin_toggle(device_t, uint32_t);
101 static int qoriq_gpio_map_gpios(device_t, phandle_t, phandle_t,
102     int, pcell_t*, uint32_t*, uint32_t*);
103 static int qoriq_gpio_pin_access_32(device_t, uint32_t, uint32_t, uint32_t,
104     uint32_t*);
105 static int qoriq_gpio_pin_config_32(device_t, uint32_t, uint32_t, uint32_t*);
106
107 static device_method_t qoriq_gpio_methods[] = {
108         DEVMETHOD(device_probe,         qoriq_gpio_probe),
109         DEVMETHOD(device_attach,        qoriq_gpio_attach),
110
111         /* GPIO protocol */
112         DEVMETHOD(gpio_get_bus,         qoriq_gpio_get_bus),
113         DEVMETHOD(gpio_pin_max,         qoriq_gpio_pin_max),
114         DEVMETHOD(gpio_pin_getname,     qoriq_gpio_pin_getname),
115         DEVMETHOD(gpio_pin_getflags,    qoriq_gpio_pin_getflags),
116         DEVMETHOD(gpio_pin_setflags,    qoriq_gpio_pin_setflags),
117         DEVMETHOD(gpio_pin_getcaps,     qoriq_gpio_pin_getcaps),
118         DEVMETHOD(gpio_pin_get,         qoriq_gpio_pin_get),
119         DEVMETHOD(gpio_pin_set,         qoriq_gpio_pin_set),
120         DEVMETHOD(gpio_pin_toggle,      qoriq_gpio_pin_toggle),
121         DEVMETHOD(gpio_map_gpios,       qoriq_gpio_map_gpios),
122         DEVMETHOD(gpio_pin_access_32,   qoriq_gpio_pin_access_32),
123         DEVMETHOD(gpio_pin_config_32,   qoriq_gpio_pin_config_32),
124
125         DEVMETHOD_END
126 };
127
128 static driver_t gpio_driver = {
129         "gpio",
130         qoriq_gpio_methods,
131         sizeof(struct gpio_softc),
132 };
133
134 static devclass_t gpio_devclass;
135
136 DRIVER_MODULE(gpio, simplebus, gpio_driver, gpio_devclass, 0, 0);
137 MODULE_VERSION(gpio, 1);
138
139 /*
140  * helpers
141  */
142 static bool
143 qoriq_make_gpio_res(device_t dev, struct gpio_res *out)
144 {
145
146         out->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
147             &out->mem_rid, RF_ACTIVE | RF_SHAREABLE);
148
149         return (out->mem_res == NULL);
150 }
151
152 static uint32_t
153 qoriq_gpio_reg_read(device_t dev, uint32_t reg)
154 {
155         struct gpio_softc *sc = device_get_softc(dev);
156         uint32_t result;
157
158         QORIQ_GPIO_ASSERT_LOCKED(sc);
159         result = bus_read_4(sc->res.mem_res, reg);
160
161         return be32toh(result);
162 }
163
164 static void
165 qoriq_gpio_reg_write(device_t dev, uint32_t reg, uint32_t val)
166 {
167         struct gpio_softc *sc = device_get_softc(dev);
168
169         QORIQ_GPIO_ASSERT_LOCKED(sc);
170         val = htobe32(val);
171
172         bus_write_4(sc->res.mem_res, reg, val);
173         bus_barrier(sc->res.mem_res, reg, 4, BUS_SPACE_BARRIER_READ |
174             BUS_SPACE_BARRIER_WRITE);
175 }
176
177 static void
178 qoriq_gpio_set(device_t dev, uint32_t reg, uint32_t pin, uint32_t set)
179 {
180         uint32_t val;
181
182         set = set != 0;
183         val = (qoriq_gpio_reg_read(dev, reg) & ~(1U << pin)) | (set << pin);
184         qoriq_gpio_reg_write(dev, reg, val);
185 }
186
187 static int
188 qoriq_gpio_configure(device_t dev, uint32_t pin, uint32_t flags)
189 {
190         struct gpio_softc *sc = device_get_softc(dev);
191         uint32_t newflags;
192
193         if (pin >= PIN_COUNT)
194                 return (EINVAL);
195
196         /*
197          * Pin cannot function as input and output at the same time.
198          * The same applies to open-drain and push-pull functionality.
199          */
200         if (((flags & GPIO_PIN_INPUT) && (flags & GPIO_PIN_OUTPUT)) ||
201             ((flags & GPIO_PIN_OPENDRAIN) && (flags & GPIO_PIN_PUSHPULL)))
202                 return (EINVAL);
203
204         QORIQ_GPIO_ASSERT_LOCKED(sc);
205
206         if (flags & GPIO_PIN_INPUT) {
207                 newflags = GPIO_PIN_INPUT;
208                 qoriq_gpio_set(dev, DIRECTION, pin, 0);
209         }
210
211         if (flags & GPIO_PIN_OUTPUT) {
212                 newflags = GPIO_PIN_OUTPUT;
213                 qoriq_gpio_set(dev, DIRECTION, pin, 1);
214
215                 if (flags & GPIO_PIN_OPENDRAIN) {
216                         newflags |= GPIO_PIN_OPENDRAIN;
217                         qoriq_gpio_set(dev, OPEN_DRAIN, pin, 1);
218                 } else {
219                         newflags |= GPIO_PIN_PUSHPULL;
220                         qoriq_gpio_set(dev, OPEN_DRAIN, pin, 0);
221                 }
222         }
223
224         sc->setup[pin].gp_flags = newflags;
225
226         return (0);
227 }
228
229 /* GPIO API */
230 static int
231 qoriq_gpio_probe(device_t dev)
232 {
233
234         if (!ofw_bus_status_okay(dev))
235                 return (ENXIO);
236
237         if (!ofw_bus_is_compatible(dev, "fsl,qoriq-gpio"))
238                 return (ENXIO);
239
240         device_set_desc(dev, "Integrated GPIO Controller");
241
242         return (BUS_PROBE_DEFAULT);
243 }
244
245 static int
246 qoriq_gpio_attach(device_t dev)
247 {
248         struct gpio_softc *sc = device_get_softc(dev);
249         int i;
250
251         if (qoriq_make_gpio_res(dev, &sc->res))
252                 return (ENXIO);
253
254         for (i = 0; i < PIN_COUNT; i++)
255                 sc->setup[i].gp_caps = DEFAULT_CAPS;
256
257         sc->dev = dev;
258
259         sc->busdev = gpiobus_attach_bus(dev);
260         if (sc->busdev == NULL)
261                 return (ENXIO);
262
263         return (0);
264 }
265
266 static device_t
267 qoriq_gpio_get_bus(device_t dev)
268 {
269         struct gpio_softc *softc = device_get_softc(dev);
270
271         return (softc->busdev);
272 }
273
274 static int
275 qoriq_gpio_pin_max(device_t dev, int *maxpin)
276 {
277
278         if (maxpin == NULL)
279                 return (EINVAL);
280
281         *maxpin = PIN_COUNT - 1;
282
283         return (0);
284 }
285
286 static int
287 qoriq_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
288 {
289
290         if (name == NULL || pin >= PIN_COUNT)
291                 return (EINVAL);
292
293         snprintf(name, GPIOMAXNAME, "pin %d", pin);
294
295         return (0);
296 }
297
298 static int
299 qoriq_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *pflags)
300 {
301         struct gpio_softc *sc = device_get_softc(dev);
302
303         if (pflags == NULL || pin >= PIN_COUNT)
304                 return (EINVAL);
305
306         QORIQ_GPIO_LOCK(sc);
307         *pflags = sc->setup[pin].gp_flags;
308         QORIQ_GPIO_UNLOCK(sc);
309
310         return (0);
311 }
312
313 static int
314 qoriq_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
315 {
316         struct gpio_softc *sc = device_get_softc(dev);
317         int ret;
318
319         if (pin >= PIN_COUNT)
320                 return (EINVAL);
321
322         /* Check for unwanted flags. */
323         QORIQ_GPIO_LOCK(sc);
324
325         if ((flags & sc->setup[pin].gp_caps) != flags) {
326                 QORIQ_GPIO_UNLOCK(sc);
327                 return (EINVAL);
328         }
329
330         ret = qoriq_gpio_configure(dev, pin, flags);
331
332         QORIQ_GPIO_UNLOCK(sc);
333
334         return (ret);
335 }
336
337 static int
338 qoriq_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
339 {
340         struct gpio_softc *sc = device_get_softc(dev);
341
342         if (caps == NULL || pin >= PIN_COUNT)
343                 return (EINVAL);
344
345         QORIQ_GPIO_LOCK(sc);
346         *caps = sc->setup[pin].gp_caps;
347         QORIQ_GPIO_UNLOCK(sc);
348
349         return (0);
350 }
351
352 static int
353 qoriq_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *value)
354 {
355         struct gpio_softc *sc = device_get_softc(dev);
356
357         if (value == NULL || pin >= PIN_COUNT)
358                 return (EINVAL);
359
360         QORIQ_GPIO_LOCK(sc);
361         *value = (qoriq_gpio_reg_read(dev, DATA) & GPIO(pin)) != 0;
362         QORIQ_GPIO_UNLOCK(sc);
363
364         return (0);
365 }
366
367 static int
368 qoriq_gpio_pin_set(device_t dev, uint32_t pin, uint32_t value)
369 {
370         struct gpio_softc *sc = device_get_softc(dev);
371
372         if (pin >= PIN_COUNT)
373                 return (EINVAL);
374
375         QORIQ_GPIO_LOCK(sc);
376         qoriq_gpio_set(dev, DATA, pin, value);
377         QORIQ_GPIO_UNLOCK(sc);
378
379         return (0);
380 }
381
382 static int
383 qoriq_gpio_pin_toggle(device_t dev, uint32_t pin)
384 {
385         struct gpio_softc *sc;
386         uint32_t value;
387
388         if (pin >= PIN_COUNT)
389                 return (EINVAL);
390
391         sc = device_get_softc(dev);
392
393         QORIQ_GPIO_LOCK(sc);
394         value = qoriq_gpio_reg_read(dev, DATA) ^ (1 << pin);
395         qoriq_gpio_reg_write(dev, DATA, value);
396         QORIQ_GPIO_UNLOCK(sc);
397
398         return (0);
399 }
400
401 static int
402 qoriq_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
403     pcell_t *gpios, uint32_t *pin, uint32_t *flags)
404 {
405         struct gpio_softc *sc = device_get_softc(bus);
406         int err;
407
408         if (gpios[0] >= PIN_COUNT)
409                 return (EINVAL);
410
411         QORIQ_GPIO_LOCK(sc);
412         err = qoriq_gpio_configure(bus, gpios[0], gpios[1]);
413         QORIQ_GPIO_UNLOCK(sc);
414
415         if (err != 0)
416                 return (err);
417
418         *pin = gpios[0];
419         *flags = gpios[1];
420
421         return (0);
422 }
423
424 static int
425 qoriq_gpio_pin_access_32(device_t dev, uint32_t first_pin, uint32_t clear_pins,
426     uint32_t change_pins, uint32_t *orig_pins)
427 {
428         struct gpio_softc *sc;
429         uint32_t hwstate;
430
431         sc = device_get_softc(dev);
432
433         if (first_pin != 0)
434                 return (EINVAL);
435
436         QORIQ_GPIO_LOCK(sc);
437         hwstate = qoriq_gpio_reg_read(dev, DATA);
438         qoriq_gpio_reg_write(dev, DATA, (hwstate & ~clear_pins) ^ change_pins);
439         QORIQ_GPIO_UNLOCK(sc);
440
441         if (orig_pins != NULL)
442                 *orig_pins = hwstate;
443
444         return (0);
445 }
446
447 static int
448 qoriq_gpio_pin_config_32(device_t dev, uint32_t first_pin, uint32_t num_pins,
449     uint32_t *pin_flags)
450 {
451         uint32_t dir, odr, mask, reg;
452         struct gpio_softc *sc;
453         uint32_t newflags[32];
454         int i;
455
456         if (first_pin != 0 || num_pins > PIN_COUNT)
457                 return (EINVAL);
458
459         sc = device_get_softc(dev);
460
461         dir = odr = mask = 0;
462
463         for (i = 0; i < num_pins; i++) {
464                 newflags[i] = 0;
465                 mask |= (1 << i);
466
467                 if (pin_flags[i] & GPIO_PIN_INPUT) {
468                         newflags[i] = GPIO_PIN_INPUT;
469                         dir &= ~(1 << i);
470                 } else {
471                         newflags[i] = GPIO_PIN_OUTPUT;
472                         dir |= (1 << i);
473
474                         if (pin_flags[i] & GPIO_PIN_OPENDRAIN) {
475                                 newflags[i] |= GPIO_PIN_OPENDRAIN;
476                                 odr |= (1 << i);
477                         } else {
478                                 newflags[i] |= GPIO_PIN_PUSHPULL;
479                                 odr &= ~(1 << i);
480                         }
481                 }
482         }
483
484         QORIQ_GPIO_LOCK(sc);
485
486         reg = (qoriq_gpio_reg_read(dev, DIRECTION) & ~mask) | dir;
487         qoriq_gpio_reg_write(dev, DIRECTION, reg);
488
489         reg = (qoriq_gpio_reg_read(dev, OPEN_DRAIN) & ~mask) | odr;
490         qoriq_gpio_reg_write(dev, OPEN_DRAIN, reg);
491
492         for (i = 0; i < num_pins; i++)
493                 sc->setup[i].gp_flags = newflags[i];
494
495         QORIQ_GPIO_UNLOCK(sc);
496
497         return (0);
498 }