Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm/mv/gpio.c
39534 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2006 Benno Rice.
5
* Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
6
* Copyright (c) 2017 Semihalf.
7
* All rights reserved.
8
*
9
* Adapted and extended for Marvell SoCs by Semihalf.
10
*
11
* Redistribution and use in source and binary forms, with or without
12
* modification, are permitted provided that the following conditions
13
* are met:
14
* 1. Redistributions of source code must retain the above copyright
15
* notice, this list of conditions and the following disclaimer.
16
* 2. Redistributions in binary form must reproduce the above copyright
17
* notice, this list of conditions and the following disclaimer in the
18
* documentation and/or other materials provided with the distribution.
19
*
20
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
*
31
* from: FreeBSD: //depot/projects/arm/src/sys/arm/xscale/pxa2x0/pxa2x0_gpio.c, rev 1
32
*/
33
34
#include <sys/param.h>
35
#include <sys/systm.h>
36
#include <sys/bus.h>
37
#include <sys/kernel.h>
38
#include <sys/lock.h>
39
#include <sys/interrupt.h>
40
#include <sys/module.h>
41
#include <sys/malloc.h>
42
#include <sys/mutex.h>
43
#include <sys/rman.h>
44
#include <sys/queue.h>
45
#include <sys/timetc.h>
46
#include <sys/callout.h>
47
#include <sys/gpio.h>
48
#include <machine/bus.h>
49
#include <machine/intr.h>
50
51
#include <dev/gpio/gpiobusvar.h>
52
#include <dev/ofw/ofw_bus.h>
53
#include <dev/ofw/ofw_bus_subr.h>
54
55
#include <arm/mv/mvvar.h>
56
#include <arm/mv/mvreg.h>
57
58
#include "gpio_if.h"
59
60
#define GPIO_MAX_INTR_COUNT 8
61
#define GPIO_PINS_PER_REG 32
62
#define GPIO_GENERIC_CAP (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
63
GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL | \
64
GPIO_PIN_TRISTATE | GPIO_PIN_PULLUP | \
65
GPIO_PIN_PULLDOWN | GPIO_PIN_INVIN | \
66
GPIO_PIN_INVOUT)
67
68
#define DEBOUNCE_CHECK_MS 1
69
#define DEBOUNCE_LO_HI_MS 2
70
#define DEBOUNCE_HI_LO_MS 2
71
#define DEBOUNCE_CHECK_TICKS ((hz / 1000) * DEBOUNCE_CHECK_MS)
72
73
struct mv_gpio_softc {
74
device_t dev;
75
device_t sc_busdev;
76
struct resource * mem_res;
77
int mem_rid;
78
struct resource * irq_res[GPIO_MAX_INTR_COUNT];
79
int irq_rid[GPIO_MAX_INTR_COUNT];
80
struct intr_event * gpio_events[MV_GPIO_MAX_NPINS];
81
void *ih_cookie[GPIO_MAX_INTR_COUNT];
82
bus_space_tag_t bst;
83
bus_space_handle_t bsh;
84
uint32_t offset;
85
struct mtx mutex;
86
uint8_t pin_num; /* number of GPIO pins */
87
uint8_t irq_num; /* number of real IRQs occupied by GPIO controller */
88
struct gpio_pin gpio_setup[MV_GPIO_MAX_NPINS];
89
90
/* Used for debouncing. */
91
uint32_t debounced_state_lo;
92
uint32_t debounced_state_hi;
93
struct callout **debounce_callouts;
94
int *debounce_counters;
95
};
96
97
struct mv_gpio_pindev {
98
device_t dev;
99
int pin;
100
};
101
102
static int mv_gpio_probe(device_t);
103
static int mv_gpio_attach(device_t);
104
static int mv_gpio_intr(device_t, void *);
105
106
static void mv_gpio_double_edge_init(device_t, int);
107
108
static int mv_gpio_debounce_setup(device_t, int);
109
static int mv_gpio_debounce_prepare(device_t, int);
110
static int mv_gpio_debounce_init(device_t, int);
111
static void mv_gpio_debounce_start(device_t, int);
112
static void mv_gpio_debounce(void *);
113
static void mv_gpio_debounced_state_set(device_t, int, uint8_t);
114
static uint32_t mv_gpio_debounced_state_get(device_t, int);
115
116
static void mv_gpio_exec_intr_handlers(device_t, uint32_t, int);
117
static void mv_gpio_intr_handler(device_t, int);
118
static uint32_t mv_gpio_reg_read(device_t, uint32_t);
119
static void mv_gpio_reg_write(device_t, uint32_t, uint32_t);
120
static void mv_gpio_reg_set(device_t, uint32_t, uint32_t);
121
static void mv_gpio_reg_clear(device_t, uint32_t, uint32_t);
122
123
static void mv_gpio_blink(device_t, uint32_t, uint8_t);
124
static void mv_gpio_polarity(device_t, uint32_t, uint8_t, uint8_t);
125
static void mv_gpio_level(device_t, uint32_t, uint8_t);
126
static void mv_gpio_edge(device_t, uint32_t, uint8_t);
127
static void mv_gpio_out_en(device_t, uint32_t, uint8_t);
128
static void mv_gpio_int_ack(struct mv_gpio_pindev *);
129
static void mv_gpio_value_set(device_t, uint32_t, uint8_t);
130
static uint32_t mv_gpio_value_get(device_t, uint32_t, uint8_t);
131
132
static void mv_gpio_intr_mask(struct mv_gpio_pindev *);
133
static void mv_gpio_intr_unmask(struct mv_gpio_pindev *);
134
135
void mv_gpio_finish_intrhandler(struct mv_gpio_pindev *);
136
int mv_gpio_setup_intrhandler(device_t, const char *,
137
driver_filter_t *, void (*)(void *), void *,
138
int, int, void **);
139
int mv_gpio_configure(device_t, uint32_t, uint32_t, uint32_t);
140
void mv_gpio_out(device_t, uint32_t, uint8_t, uint8_t);
141
uint8_t mv_gpio_in(device_t, uint32_t);
142
143
/*
144
* GPIO interface
145
*/
146
static device_t mv_gpio_get_bus(device_t);
147
static int mv_gpio_pin_max(device_t, int *);
148
static int mv_gpio_pin_getcaps(device_t, uint32_t, uint32_t *);
149
static int mv_gpio_pin_getflags(device_t, uint32_t, uint32_t *);
150
static int mv_gpio_pin_getname(device_t, uint32_t, char *);
151
static int mv_gpio_pin_setflags(device_t, uint32_t, uint32_t);
152
static int mv_gpio_pin_set(device_t, uint32_t, unsigned int);
153
static int mv_gpio_pin_get(device_t, uint32_t, unsigned int *);
154
static int mv_gpio_pin_toggle(device_t, uint32_t);
155
static int mv_gpio_map_gpios(device_t, phandle_t, phandle_t,
156
int, pcell_t *, uint32_t *, uint32_t *);
157
158
#define MV_GPIO_LOCK() mtx_lock_spin(&sc->mutex)
159
#define MV_GPIO_UNLOCK() mtx_unlock_spin(&sc->mutex)
160
#define MV_GPIO_ASSERT_LOCKED() mtx_assert(&sc->mutex, MA_OWNED)
161
162
static device_method_t mv_gpio_methods[] = {
163
DEVMETHOD(device_probe, mv_gpio_probe),
164
DEVMETHOD(device_attach, mv_gpio_attach),
165
166
/* GPIO protocol */
167
DEVMETHOD(gpio_get_bus, mv_gpio_get_bus),
168
DEVMETHOD(gpio_pin_max, mv_gpio_pin_max),
169
DEVMETHOD(gpio_pin_getname, mv_gpio_pin_getname),
170
DEVMETHOD(gpio_pin_getflags, mv_gpio_pin_getflags),
171
DEVMETHOD(gpio_pin_getcaps, mv_gpio_pin_getcaps),
172
DEVMETHOD(gpio_pin_setflags, mv_gpio_pin_setflags),
173
DEVMETHOD(gpio_pin_get, mv_gpio_pin_get),
174
DEVMETHOD(gpio_pin_set, mv_gpio_pin_set),
175
DEVMETHOD(gpio_pin_toggle, mv_gpio_pin_toggle),
176
DEVMETHOD(gpio_map_gpios, mv_gpio_map_gpios),
177
178
DEVMETHOD_END
179
};
180
181
static driver_t mv_gpio_driver = {
182
"gpio",
183
mv_gpio_methods,
184
sizeof(struct mv_gpio_softc),
185
};
186
187
EARLY_DRIVER_MODULE(mv_gpio, simplebus, mv_gpio_driver, 0, 0,
188
BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST);
189
190
struct ofw_compat_data compat_data[] = {
191
{ "mrvl,gpio", 1 },
192
{ "marvell,orion-gpio", 1 },
193
{ NULL, 0 }
194
};
195
196
static int
197
mv_gpio_probe(device_t dev)
198
{
199
if (!ofw_bus_status_okay(dev))
200
return (ENXIO);
201
202
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
203
return (ENXIO);
204
205
device_set_desc(dev, "Marvell Integrated GPIO Controller");
206
return (0);
207
}
208
209
static int
210
mv_gpio_setup_interrupts(struct mv_gpio_softc *sc, phandle_t node)
211
{
212
phandle_t iparent;
213
pcell_t irq_cells;
214
int i, size;
215
216
/* Find root interrupt controller */
217
iparent = ofw_bus_find_iparent(node);
218
if (iparent == 0) {
219
device_printf(sc->dev, "No interrupt-parrent found. "
220
"Error in DTB\n");
221
return (ENXIO);
222
} else {
223
/* While at parent - store interrupt cells prop */
224
if (OF_searchencprop(OF_node_from_xref(iparent),
225
"#interrupt-cells", &irq_cells, sizeof(irq_cells)) == -1) {
226
device_printf(sc->dev, "DTB: Missing #interrupt-cells "
227
"property in interrupt parent node\n");
228
return (ENXIO);
229
}
230
}
231
232
size = OF_getproplen(node, "interrupts");
233
if (size != -1) {
234
size = size / sizeof(pcell_t);
235
size = size / irq_cells;
236
sc->irq_num = size;
237
device_printf(sc->dev, "%d IRQs available\n", sc->irq_num);
238
} else {
239
device_printf(sc->dev, "ERROR: no interrupts entry found!\n");
240
return (ENXIO);
241
}
242
243
for (i = 0; i < sc->irq_num; i++) {
244
sc->irq_rid[i] = i;
245
sc->irq_res[i] = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ,
246
&sc->irq_rid[i], RF_ACTIVE);
247
if (!sc->irq_res[i]) {
248
mtx_destroy(&sc->mutex);
249
device_printf(sc->dev,
250
"could not allocate gpio%d interrupt\n", i+1);
251
return (ENXIO);
252
}
253
}
254
255
device_printf(sc->dev, "Disable interrupts (offset = %x + EDGE(0x18)\n", sc->offset);
256
/* Disable all interrupts */
257
bus_space_write_4(sc->bst, sc->bsh, sc->offset + GPIO_INT_EDGE_MASK, 0);
258
device_printf(sc->dev, "Disable interrupts (offset = %x + LEV(0x1C))\n", sc->offset);
259
bus_space_write_4(sc->bst, sc->bsh, sc->offset + GPIO_INT_LEV_MASK, 0);
260
261
for (i = 0; i < sc->irq_num; i++) {
262
device_printf(sc->dev, "Setup intr %d\n", i);
263
if (bus_setup_intr(sc->dev, sc->irq_res[i],
264
INTR_TYPE_MISC,
265
(driver_filter_t *)mv_gpio_intr, NULL,
266
sc, &sc->ih_cookie[i]) != 0) {
267
mtx_destroy(&sc->mutex);
268
bus_release_resource(sc->dev, SYS_RES_IRQ,
269
sc->irq_rid[i], sc->irq_res[i]);
270
device_printf(sc->dev, "could not set up intr %d\n", i);
271
return (ENXIO);
272
}
273
}
274
275
/* Clear interrupt status. */
276
device_printf(sc->dev, "Clear int status (offset = %x)\n", sc->offset);
277
bus_space_write_4(sc->bst, sc->bsh, sc->offset + GPIO_INT_CAUSE, 0);
278
279
sc->debounce_callouts = (struct callout **)malloc(sc->pin_num *
280
sizeof(struct callout *), M_DEVBUF, M_WAITOK | M_ZERO);
281
if (sc->debounce_callouts == NULL)
282
return (ENOMEM);
283
284
sc->debounce_counters = (int *)malloc(sc->pin_num * sizeof(int),
285
M_DEVBUF, M_WAITOK);
286
if (sc->debounce_counters == NULL)
287
return (ENOMEM);
288
289
return (0);
290
}
291
292
static int
293
mv_gpio_attach(device_t dev)
294
{
295
int i, rv;
296
struct mv_gpio_softc *sc;
297
phandle_t node;
298
pcell_t pincnt = 0;
299
300
sc = (struct mv_gpio_softc *)device_get_softc(dev);
301
if (sc == NULL)
302
return (ENXIO);
303
304
node = ofw_bus_get_node(dev);
305
sc->dev = dev;
306
307
if (OF_getencprop(node, "pin-count", &pincnt, sizeof(pcell_t)) >= 0 ||
308
OF_getencprop(node, "ngpios", &pincnt, sizeof(pcell_t)) >= 0) {
309
sc->pin_num = MIN(pincnt, MV_GPIO_MAX_NPINS);
310
if (bootverbose)
311
device_printf(dev, "%d pins available\n", sc->pin_num);
312
} else {
313
device_printf(dev, "ERROR: no pin-count or ngpios entry found!\n");
314
return (ENXIO);
315
}
316
317
if (OF_getencprop(node, "offset", &sc->offset, sizeof(sc->offset)) == -1)
318
sc->offset = 0;
319
320
/* Assign generic capabilities to every gpio pin */
321
for(i = 0; i < sc->pin_num; i++)
322
sc->gpio_setup[i].gp_caps = GPIO_GENERIC_CAP;
323
324
mtx_init(&sc->mutex, device_get_nameunit(dev), NULL, MTX_SPIN);
325
326
sc->mem_rid = 0;
327
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid,
328
RF_ACTIVE | RF_SHAREABLE );
329
330
if (!sc->mem_res) {
331
mtx_destroy(&sc->mutex);
332
device_printf(dev, "could not allocate memory window\n");
333
return (ENXIO);
334
}
335
336
sc->bst = rman_get_bustag(sc->mem_res);
337
sc->bsh = rman_get_bushandle(sc->mem_res);
338
339
rv = mv_gpio_setup_interrupts(sc, node);
340
if (rv != 0)
341
return (rv);
342
343
sc->sc_busdev = gpiobus_add_bus(dev);
344
if (sc->sc_busdev == NULL) {
345
mtx_destroy(&sc->mutex);
346
bus_release_resource(dev, SYS_RES_IRQ,
347
sc->irq_rid[i], sc->irq_res[i]);
348
return (ENXIO);
349
}
350
351
bus_attach_children(dev);
352
return (0);
353
}
354
355
static int
356
mv_gpio_intr(device_t dev, void *arg)
357
{
358
uint32_t int_cause, gpio_val;
359
struct mv_gpio_softc *sc;
360
sc = (struct mv_gpio_softc *)device_get_softc(dev);
361
362
MV_GPIO_LOCK();
363
364
/*
365
* According to documentation, edge sensitive interrupts are asserted
366
* when unmasked GPIO_INT_CAUSE register bits are set.
367
*/
368
int_cause = mv_gpio_reg_read(dev, GPIO_INT_CAUSE);
369
int_cause &= mv_gpio_reg_read(dev, GPIO_INT_EDGE_MASK);
370
371
/*
372
* Level sensitive interrupts are asserted when unmasked GPIO_DATA_IN
373
* register bits are set.
374
*/
375
gpio_val = mv_gpio_reg_read(dev, GPIO_DATA_IN);
376
gpio_val &= mv_gpio_reg_read(dev, GPIO_INT_LEV_MASK);
377
378
mv_gpio_exec_intr_handlers(dev, int_cause | gpio_val, 0);
379
380
MV_GPIO_UNLOCK();
381
382
return (FILTER_HANDLED);
383
}
384
385
/*
386
* GPIO interrupt handling
387
*/
388
389
void
390
mv_gpio_finish_intrhandler(struct mv_gpio_pindev *s)
391
{
392
/* When we acheive full interrupt support
393
* This function will be opposite to
394
* mv_gpio_setup_intrhandler
395
*/
396
397
/* Now it exists only to remind that
398
* there should be place to free mv_gpio_pindev
399
* allocated by mv_gpio_setup_intrhandler
400
*/
401
free(s, M_DEVBUF);
402
}
403
404
int
405
mv_gpio_setup_intrhandler(device_t dev, const char *name, driver_filter_t *filt,
406
void (*hand)(void *), void *arg, int pin, int flags, void **cookiep)
407
{
408
struct intr_event *event;
409
int error;
410
struct mv_gpio_pindev *s;
411
struct mv_gpio_softc *sc;
412
sc = (struct mv_gpio_softc *)device_get_softc(dev);
413
s = malloc(sizeof(struct mv_gpio_pindev), M_DEVBUF, M_NOWAIT | M_ZERO);
414
415
if (pin < 0 || pin >= sc->pin_num)
416
return (ENXIO);
417
event = sc->gpio_events[pin];
418
if (event == NULL) {
419
MV_GPIO_LOCK();
420
if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_DEBOUNCE) {
421
error = mv_gpio_debounce_init(dev, pin);
422
if (error != 0) {
423
MV_GPIO_UNLOCK();
424
return (error);
425
}
426
} else if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE)
427
mv_gpio_double_edge_init(dev, pin);
428
MV_GPIO_UNLOCK();
429
error = intr_event_create(&event, (void *)s, 0, pin,
430
(void (*)(void *))mv_gpio_intr_mask,
431
(void (*)(void *))mv_gpio_intr_unmask,
432
(void (*)(void *))mv_gpio_int_ack,
433
NULL,
434
"gpio%d:", pin);
435
if (error != 0)
436
return (error);
437
sc->gpio_events[pin] = event;
438
}
439
440
intr_event_add_handler(event, name, filt, hand, arg,
441
intr_priority(flags), flags, cookiep);
442
return (0);
443
}
444
445
static void
446
mv_gpio_intr_mask(struct mv_gpio_pindev *s)
447
{
448
struct mv_gpio_softc *sc;
449
sc = (struct mv_gpio_softc *)device_get_softc(s->dev);
450
451
if (s->pin >= sc->pin_num)
452
return;
453
454
MV_GPIO_LOCK();
455
456
if (sc->gpio_setup[s->pin].gp_flags & (MV_GPIO_IN_IRQ_EDGE |
457
MV_GPIO_IN_IRQ_DOUBLE_EDGE))
458
mv_gpio_edge(s->dev, s->pin, 0);
459
else
460
mv_gpio_level(s->dev, s->pin, 0);
461
462
/*
463
* The interrupt has to be acknowledged before scheduling an interrupt
464
* thread. This way we allow for interrupt source to trigger again
465
* (which can happen with shared IRQs e.g. PCI) while processing the
466
* current event.
467
*/
468
mv_gpio_int_ack(s);
469
470
MV_GPIO_UNLOCK();
471
472
return;
473
}
474
475
static void
476
mv_gpio_intr_unmask(struct mv_gpio_pindev *s)
477
{
478
struct mv_gpio_softc *sc;
479
sc = (struct mv_gpio_softc *)device_get_softc(s->dev);
480
481
if (s->pin >= sc->pin_num)
482
return;
483
484
MV_GPIO_LOCK();
485
486
if (sc->gpio_setup[s->pin].gp_flags & (MV_GPIO_IN_IRQ_EDGE |
487
MV_GPIO_IN_IRQ_DOUBLE_EDGE))
488
mv_gpio_edge(s->dev, s->pin, 1);
489
else
490
mv_gpio_level(s->dev, s->pin, 1);
491
492
MV_GPIO_UNLOCK();
493
494
return;
495
}
496
497
static void
498
mv_gpio_exec_intr_handlers(device_t dev, uint32_t status, int high)
499
{
500
int i, pin;
501
struct mv_gpio_softc *sc;
502
sc = (struct mv_gpio_softc *)device_get_softc(dev);
503
504
MV_GPIO_ASSERT_LOCKED();
505
506
i = 0;
507
while (status != 0) {
508
if (status & 1) {
509
pin = (high ? (i + GPIO_PINS_PER_REG) : i);
510
if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_DEBOUNCE)
511
mv_gpio_debounce_start(dev, pin);
512
else if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE) {
513
mv_gpio_polarity(dev, pin, 0, 1);
514
mv_gpio_intr_handler(dev, pin);
515
} else
516
mv_gpio_intr_handler(dev, pin);
517
}
518
status >>= 1;
519
i++;
520
}
521
}
522
523
static void
524
mv_gpio_intr_handler(device_t dev, int pin)
525
{
526
struct intr_irqsrc isrc;
527
struct mv_gpio_softc *sc;
528
sc = (struct mv_gpio_softc *)device_get_softc(dev);
529
530
MV_GPIO_ASSERT_LOCKED();
531
532
#ifdef INTR_SOLO
533
isrc.isrc_filter = NULL;
534
#endif
535
isrc.isrc_event = sc->gpio_events[pin];
536
537
if (isrc.isrc_event == NULL ||
538
CK_SLIST_EMPTY(&isrc.isrc_event->ie_handlers))
539
return;
540
541
intr_isrc_dispatch(&isrc, NULL);
542
}
543
544
int
545
mv_gpio_configure(device_t dev, uint32_t pin, uint32_t flags, uint32_t mask)
546
{
547
int error;
548
struct mv_gpio_softc *sc;
549
sc = (struct mv_gpio_softc *)device_get_softc(dev);
550
error = 0;
551
552
if (pin >= sc->pin_num)
553
return (EINVAL);
554
555
/* check flags consistency */
556
if (((flags & mask) & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) ==
557
(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT))
558
return (EINVAL);
559
560
if (mask & MV_GPIO_IN_DEBOUNCE) {
561
if (sc->irq_num == 0)
562
return (EINVAL);
563
error = mv_gpio_debounce_prepare(dev, pin);
564
if (error != 0)
565
return (error);
566
}
567
568
MV_GPIO_LOCK();
569
570
if ((mask & flags) & GPIO_PIN_INPUT)
571
mv_gpio_out_en(dev, pin, 0);
572
if ((mask & flags) & GPIO_PIN_OUTPUT) {
573
if ((flags & mask) & GPIO_PIN_OPENDRAIN)
574
mv_gpio_value_set(dev, pin, 0);
575
else
576
mv_gpio_value_set(dev, pin, 1);
577
mv_gpio_out_en(dev, pin, 1);
578
}
579
580
if (mask & MV_GPIO_OUT_BLINK)
581
mv_gpio_blink(dev, pin, flags & MV_GPIO_OUT_BLINK);
582
if (mask & MV_GPIO_IN_POL_LOW)
583
mv_gpio_polarity(dev, pin, flags & MV_GPIO_IN_POL_LOW, 0);
584
if (mask & MV_GPIO_IN_DEBOUNCE) {
585
error = mv_gpio_debounce_setup(dev, pin);
586
if (error) {
587
MV_GPIO_UNLOCK();
588
return (error);
589
}
590
}
591
592
sc->gpio_setup[pin].gp_flags &= ~(mask);
593
sc->gpio_setup[pin].gp_flags |= (flags & mask);
594
595
MV_GPIO_UNLOCK();
596
597
return (0);
598
}
599
600
static void
601
mv_gpio_double_edge_init(device_t dev, int pin)
602
{
603
uint8_t raw_read;
604
struct mv_gpio_softc *sc __unused;
605
sc = (struct mv_gpio_softc *)device_get_softc(dev);
606
607
MV_GPIO_ASSERT_LOCKED();
608
609
raw_read = (mv_gpio_value_get(dev, pin, 1) ? 1 : 0);
610
611
if (raw_read)
612
mv_gpio_polarity(dev, pin, 1, 0);
613
else
614
mv_gpio_polarity(dev, pin, 0, 0);
615
}
616
617
static int
618
mv_gpio_debounce_setup(device_t dev, int pin)
619
{
620
struct callout *c;
621
struct mv_gpio_softc *sc;
622
623
sc = (struct mv_gpio_softc *)device_get_softc(dev);
624
625
MV_GPIO_ASSERT_LOCKED();
626
627
c = sc->debounce_callouts[pin];
628
if (c == NULL)
629
return (ENXIO);
630
631
if (callout_active(c))
632
callout_deactivate(c);
633
634
callout_stop(c);
635
636
return (0);
637
}
638
639
static int
640
mv_gpio_debounce_prepare(device_t dev, int pin)
641
{
642
struct callout *c;
643
struct mv_gpio_softc *sc;
644
645
sc = (struct mv_gpio_softc *)device_get_softc(dev);
646
647
c = sc->debounce_callouts[pin];
648
if (c == NULL) {
649
c = (struct callout *)malloc(sizeof(struct callout),
650
M_DEVBUF, M_WAITOK);
651
sc->debounce_callouts[pin] = c;
652
if (c == NULL)
653
return (ENOMEM);
654
callout_init(c, 1);
655
}
656
657
return (0);
658
}
659
660
static int
661
mv_gpio_debounce_init(device_t dev, int pin)
662
{
663
uint8_t raw_read;
664
int *cnt;
665
struct mv_gpio_softc *sc;
666
667
sc = (struct mv_gpio_softc *)device_get_softc(dev);
668
669
MV_GPIO_ASSERT_LOCKED();
670
671
cnt = &sc->debounce_counters[pin];
672
raw_read = (mv_gpio_value_get(dev, pin, 1) ? 1 : 0);
673
if (raw_read) {
674
mv_gpio_polarity(dev, pin, 1, 0);
675
*cnt = DEBOUNCE_HI_LO_MS / DEBOUNCE_CHECK_MS;
676
} else {
677
mv_gpio_polarity(dev, pin, 0, 0);
678
*cnt = DEBOUNCE_LO_HI_MS / DEBOUNCE_CHECK_MS;
679
}
680
681
mv_gpio_debounced_state_set(dev, pin, raw_read);
682
683
return (0);
684
}
685
686
static void
687
mv_gpio_debounce_start(device_t dev, int pin)
688
{
689
struct callout *c;
690
struct mv_gpio_pindev s = {dev, pin};
691
struct mv_gpio_pindev *sd;
692
struct mv_gpio_softc *sc;
693
sc = (struct mv_gpio_softc *)device_get_softc(dev);
694
695
MV_GPIO_ASSERT_LOCKED();
696
697
c = sc->debounce_callouts[pin];
698
if (c == NULL) {
699
mv_gpio_int_ack(&s);
700
return;
701
}
702
703
if (callout_pending(c) || callout_active(c)) {
704
mv_gpio_int_ack(&s);
705
return;
706
}
707
708
sd = (struct mv_gpio_pindev *)malloc(sizeof(struct mv_gpio_pindev),
709
M_DEVBUF, M_WAITOK);
710
if (sd == NULL) {
711
mv_gpio_int_ack(&s);
712
return;
713
}
714
sd->pin = pin;
715
sd->dev = dev;
716
717
callout_reset(c, DEBOUNCE_CHECK_TICKS, mv_gpio_debounce, sd);
718
}
719
720
static void
721
mv_gpio_debounce(void *arg)
722
{
723
uint8_t raw_read, last_state;
724
int pin;
725
device_t dev;
726
int *debounce_counter;
727
struct mv_gpio_softc *sc;
728
struct mv_gpio_pindev *s;
729
730
s = (struct mv_gpio_pindev *)arg;
731
dev = s->dev;
732
pin = s->pin;
733
sc = (struct mv_gpio_softc *)device_get_softc(dev);
734
735
MV_GPIO_LOCK();
736
737
raw_read = (mv_gpio_value_get(dev, pin, 1) ? 1 : 0);
738
last_state = (mv_gpio_debounced_state_get(dev, pin) ? 1 : 0);
739
debounce_counter = &sc->debounce_counters[pin];
740
741
if (raw_read == last_state) {
742
if (last_state)
743
*debounce_counter = DEBOUNCE_HI_LO_MS /
744
DEBOUNCE_CHECK_MS;
745
else
746
*debounce_counter = DEBOUNCE_LO_HI_MS /
747
DEBOUNCE_CHECK_MS;
748
749
callout_reset(sc->debounce_callouts[pin],
750
DEBOUNCE_CHECK_TICKS, mv_gpio_debounce, arg);
751
} else {
752
*debounce_counter = *debounce_counter - 1;
753
if (*debounce_counter != 0)
754
callout_reset(sc->debounce_callouts[pin],
755
DEBOUNCE_CHECK_TICKS, mv_gpio_debounce, arg);
756
else {
757
mv_gpio_debounced_state_set(dev, pin, raw_read);
758
759
if (last_state)
760
*debounce_counter = DEBOUNCE_HI_LO_MS /
761
DEBOUNCE_CHECK_MS;
762
else
763
*debounce_counter = DEBOUNCE_LO_HI_MS /
764
DEBOUNCE_CHECK_MS;
765
766
if (((sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW) &&
767
(raw_read == 0)) ||
768
(((sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW) == 0) &&
769
raw_read) ||
770
(sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE))
771
mv_gpio_intr_handler(dev, pin);
772
773
/* Toggle polarity for next edge. */
774
mv_gpio_polarity(dev, pin, 0, 1);
775
776
free(arg, M_DEVBUF);
777
callout_deactivate(sc->debounce_callouts[pin]);
778
}
779
}
780
781
MV_GPIO_UNLOCK();
782
}
783
784
static void
785
mv_gpio_debounced_state_set(device_t dev, int pin, uint8_t new_state)
786
{
787
uint32_t *old_state;
788
struct mv_gpio_softc *sc;
789
sc = (struct mv_gpio_softc *)device_get_softc(dev);
790
791
MV_GPIO_ASSERT_LOCKED();
792
793
if (pin >= GPIO_PINS_PER_REG) {
794
old_state = &sc->debounced_state_hi;
795
pin -= GPIO_PINS_PER_REG;
796
} else
797
old_state = &sc->debounced_state_lo;
798
799
if (new_state)
800
*old_state |= (1 << pin);
801
else
802
*old_state &= ~(1 << pin);
803
}
804
805
static uint32_t
806
mv_gpio_debounced_state_get(device_t dev, int pin)
807
{
808
uint32_t *state;
809
struct mv_gpio_softc *sc;
810
sc = (struct mv_gpio_softc *)device_get_softc(dev);
811
812
MV_GPIO_ASSERT_LOCKED();
813
814
if (pin >= GPIO_PINS_PER_REG) {
815
state = &sc->debounced_state_hi;
816
pin -= GPIO_PINS_PER_REG;
817
} else
818
state = &sc->debounced_state_lo;
819
820
return (*state & (1 << pin));
821
}
822
823
void
824
mv_gpio_out(device_t dev, uint32_t pin, uint8_t val, uint8_t enable)
825
{
826
struct mv_gpio_softc *sc;
827
sc = (struct mv_gpio_softc *)device_get_softc(dev);
828
829
MV_GPIO_LOCK();
830
831
mv_gpio_value_set(dev, pin, val);
832
mv_gpio_out_en(dev, pin, enable);
833
834
MV_GPIO_UNLOCK();
835
}
836
837
uint8_t
838
mv_gpio_in(device_t dev, uint32_t pin)
839
{
840
uint8_t state;
841
struct mv_gpio_softc *sc;
842
sc = (struct mv_gpio_softc *)device_get_softc(dev);
843
844
MV_GPIO_ASSERT_LOCKED();
845
846
if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_DEBOUNCE) {
847
if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW)
848
state = (mv_gpio_debounced_state_get(dev, pin) ? 0 : 1);
849
else
850
state = (mv_gpio_debounced_state_get(dev, pin) ? 1 : 0);
851
} else if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_IRQ_DOUBLE_EDGE) {
852
if (sc->gpio_setup[pin].gp_flags & MV_GPIO_IN_POL_LOW)
853
state = (mv_gpio_value_get(dev, pin, 1) ? 0 : 1);
854
else
855
state = (mv_gpio_value_get(dev, pin, 1) ? 1 : 0);
856
} else
857
state = (mv_gpio_value_get(dev, pin, 0) ? 1 : 0);
858
859
return (state);
860
}
861
862
static uint32_t
863
mv_gpio_reg_read(device_t dev, uint32_t reg)
864
{
865
struct mv_gpio_softc *sc;
866
sc = (struct mv_gpio_softc *)device_get_softc(dev);
867
868
return (bus_space_read_4(sc->bst, sc->bsh, sc->offset + reg));
869
}
870
871
static void
872
mv_gpio_reg_write(device_t dev, uint32_t reg, uint32_t val)
873
{
874
struct mv_gpio_softc *sc;
875
sc = (struct mv_gpio_softc *)device_get_softc(dev);
876
877
bus_space_write_4(sc->bst, sc->bsh, sc->offset + reg, val);
878
}
879
880
static void
881
mv_gpio_reg_set(device_t dev, uint32_t reg, uint32_t pin)
882
{
883
uint32_t reg_val;
884
885
reg_val = mv_gpio_reg_read(dev, reg);
886
reg_val |= GPIO(pin);
887
mv_gpio_reg_write(dev, reg, reg_val);
888
}
889
890
static void
891
mv_gpio_reg_clear(device_t dev, uint32_t reg, uint32_t pin)
892
{
893
uint32_t reg_val;
894
895
reg_val = mv_gpio_reg_read(dev, reg);
896
reg_val &= ~(GPIO(pin));
897
mv_gpio_reg_write(dev, reg, reg_val);
898
}
899
900
static void
901
mv_gpio_out_en(device_t dev, uint32_t pin, uint8_t enable)
902
{
903
uint32_t reg;
904
struct mv_gpio_softc *sc;
905
sc = (struct mv_gpio_softc *)device_get_softc(dev);
906
907
if (pin >= sc->pin_num)
908
return;
909
910
reg = GPIO_DATA_OUT_EN_CTRL;
911
912
if (enable)
913
mv_gpio_reg_clear(dev, reg, pin);
914
else
915
mv_gpio_reg_set(dev, reg, pin);
916
}
917
918
static void
919
mv_gpio_blink(device_t dev, uint32_t pin, uint8_t enable)
920
{
921
uint32_t reg;
922
struct mv_gpio_softc *sc;
923
sc = (struct mv_gpio_softc *)device_get_softc(dev);
924
925
if (pin >= sc->pin_num)
926
return;
927
928
reg = GPIO_BLINK_EN;
929
930
if (enable)
931
mv_gpio_reg_set(dev, reg, pin);
932
else
933
mv_gpio_reg_clear(dev, reg, pin);
934
}
935
936
static void
937
mv_gpio_polarity(device_t dev, uint32_t pin, uint8_t enable, uint8_t toggle)
938
{
939
uint32_t reg, reg_val;
940
struct mv_gpio_softc *sc;
941
sc = (struct mv_gpio_softc *)device_get_softc(dev);
942
943
if (pin >= sc->pin_num)
944
return;
945
946
reg = GPIO_DATA_IN_POLAR;
947
948
if (toggle) {
949
reg_val = mv_gpio_reg_read(dev, reg) & GPIO(pin);
950
if (reg_val)
951
mv_gpio_reg_clear(dev, reg, pin);
952
else
953
mv_gpio_reg_set(dev, reg, pin);
954
} else if (enable)
955
mv_gpio_reg_set(dev, reg, pin);
956
else
957
mv_gpio_reg_clear(dev, reg, pin);
958
}
959
960
static void
961
mv_gpio_level(device_t dev, uint32_t pin, uint8_t enable)
962
{
963
uint32_t reg;
964
struct mv_gpio_softc *sc;
965
sc = (struct mv_gpio_softc *)device_get_softc(dev);
966
967
if (pin >= sc->pin_num)
968
return;
969
970
reg = GPIO_INT_LEV_MASK;
971
972
if (enable)
973
mv_gpio_reg_set(dev, reg, pin);
974
else
975
mv_gpio_reg_clear(dev, reg, pin);
976
}
977
978
static void
979
mv_gpio_edge(device_t dev, uint32_t pin, uint8_t enable)
980
{
981
uint32_t reg;
982
struct mv_gpio_softc *sc;
983
sc = (struct mv_gpio_softc *)device_get_softc(dev);
984
985
if (pin >= sc->pin_num)
986
return;
987
988
reg = GPIO_INT_EDGE_MASK;
989
990
if (enable)
991
mv_gpio_reg_set(dev, reg, pin);
992
else
993
mv_gpio_reg_clear(dev, reg, pin);
994
}
995
996
static void
997
mv_gpio_int_ack(struct mv_gpio_pindev *s)
998
{
999
uint32_t reg, pin;
1000
struct mv_gpio_softc *sc;
1001
sc = (struct mv_gpio_softc *)device_get_softc(s->dev);
1002
pin = s->pin;
1003
1004
if (pin >= sc->pin_num)
1005
return;
1006
1007
reg = GPIO_INT_CAUSE;
1008
1009
mv_gpio_reg_clear(s->dev, reg, pin);
1010
}
1011
1012
static uint32_t
1013
mv_gpio_value_get(device_t dev, uint32_t pin, uint8_t exclude_polar)
1014
{
1015
uint32_t reg, polar_reg, reg_val, polar_reg_val;
1016
struct mv_gpio_softc *sc;
1017
sc = (struct mv_gpio_softc *)device_get_softc(dev);
1018
1019
if (pin >= sc->pin_num)
1020
return (0);
1021
1022
reg = GPIO_DATA_IN;
1023
polar_reg = GPIO_DATA_IN_POLAR;
1024
1025
reg_val = mv_gpio_reg_read(dev, reg);
1026
1027
if (exclude_polar) {
1028
polar_reg_val = mv_gpio_reg_read(dev, polar_reg);
1029
return ((reg_val & GPIO(pin)) ^ (polar_reg_val & GPIO(pin)));
1030
} else
1031
return (reg_val & GPIO(pin));
1032
}
1033
1034
static void
1035
mv_gpio_value_set(device_t dev, uint32_t pin, uint8_t val)
1036
{
1037
uint32_t reg;
1038
struct mv_gpio_softc *sc;
1039
sc = (struct mv_gpio_softc *)device_get_softc(dev);
1040
1041
MV_GPIO_ASSERT_LOCKED();
1042
1043
if (pin >= sc->pin_num)
1044
return;
1045
1046
reg = GPIO_DATA_OUT;
1047
1048
if (val)
1049
mv_gpio_reg_set(dev, reg, pin);
1050
else
1051
mv_gpio_reg_clear(dev, reg, pin);
1052
}
1053
1054
/*
1055
* GPIO interface methods
1056
*/
1057
1058
static int
1059
mv_gpio_pin_max(device_t dev, int *maxpin)
1060
{
1061
struct mv_gpio_softc *sc;
1062
if (maxpin == NULL)
1063
return (EINVAL);
1064
1065
sc = device_get_softc(dev);
1066
*maxpin = sc->pin_num;
1067
1068
return (0);
1069
}
1070
1071
static int
1072
mv_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
1073
{
1074
struct mv_gpio_softc *sc = device_get_softc(dev);
1075
if (caps == NULL)
1076
return (EINVAL);
1077
1078
if (pin >= sc->pin_num)
1079
return (EINVAL);
1080
1081
MV_GPIO_LOCK();
1082
*caps = sc->gpio_setup[pin].gp_caps;
1083
MV_GPIO_UNLOCK();
1084
1085
return (0);
1086
}
1087
1088
static int
1089
mv_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
1090
{
1091
struct mv_gpio_softc *sc = device_get_softc(dev);
1092
if (flags == NULL)
1093
return (EINVAL);
1094
1095
if (pin >= sc->pin_num)
1096
return (EINVAL);
1097
1098
MV_GPIO_LOCK();
1099
*flags = sc->gpio_setup[pin].gp_flags;
1100
MV_GPIO_UNLOCK();
1101
1102
return (0);
1103
}
1104
1105
static int
1106
mv_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
1107
{
1108
struct mv_gpio_softc *sc = device_get_softc(dev);
1109
if (name == NULL)
1110
return (EINVAL);
1111
1112
if (pin >= sc->pin_num)
1113
return (EINVAL);
1114
1115
MV_GPIO_LOCK();
1116
memcpy(name, sc->gpio_setup[pin].gp_name, GPIOMAXNAME);
1117
MV_GPIO_UNLOCK();
1118
1119
return (0);
1120
}
1121
1122
static int
1123
mv_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
1124
{
1125
int ret;
1126
struct mv_gpio_softc *sc = device_get_softc(dev);
1127
if (pin >= sc->pin_num)
1128
return (EINVAL);
1129
1130
/* Check for unwanted flags. */
1131
if ((flags & sc->gpio_setup[pin].gp_caps) != flags)
1132
return (EINVAL);
1133
1134
ret = mv_gpio_configure(dev, pin, flags, ~0);
1135
1136
return (ret);
1137
}
1138
1139
static int
1140
mv_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
1141
{
1142
struct mv_gpio_softc *sc = device_get_softc(dev);
1143
if (pin >= sc->pin_num)
1144
return (EINVAL);
1145
1146
MV_GPIO_LOCK();
1147
mv_gpio_value_set(dev, pin, value);
1148
MV_GPIO_UNLOCK();
1149
1150
return (0);
1151
}
1152
1153
static int
1154
mv_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
1155
{
1156
struct mv_gpio_softc *sc = device_get_softc(dev);
1157
if (value == NULL)
1158
return (EINVAL);
1159
1160
if (pin >= sc->pin_num)
1161
return (EINVAL);
1162
1163
MV_GPIO_LOCK();
1164
*value = mv_gpio_in(dev, pin);
1165
MV_GPIO_UNLOCK();
1166
1167
return (0);
1168
}
1169
1170
static int
1171
mv_gpio_pin_toggle(device_t dev, uint32_t pin)
1172
{
1173
struct mv_gpio_softc *sc = device_get_softc(dev);
1174
uint32_t value;
1175
if (pin >= sc->pin_num)
1176
return (EINVAL);
1177
1178
MV_GPIO_LOCK();
1179
value = mv_gpio_in(dev, pin);
1180
value = (~value) & 1;
1181
mv_gpio_value_set(dev, pin, value);
1182
MV_GPIO_UNLOCK();
1183
1184
return (0);
1185
}
1186
1187
static device_t
1188
mv_gpio_get_bus(device_t dev)
1189
{
1190
struct mv_gpio_softc *sc = device_get_softc(dev);
1191
1192
return (sc->sc_busdev);
1193
}
1194
1195
static int
1196
mv_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
1197
pcell_t *gpios, uint32_t *pin, uint32_t *flags)
1198
{
1199
struct mv_gpio_softc *sc = device_get_softc(bus);
1200
1201
if (gpios[0] >= sc->pin_num)
1202
return (EINVAL);
1203
1204
*pin = gpios[0];
1205
*flags = gpios[1];
1206
mv_gpio_configure(bus, *pin, *flags, ~0);
1207
1208
return (0);
1209
}
1210
1211