Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm/mv/mvebu_gpio.c
39507 views
1
/*-
2
* Copyright (c) 2020 Michal Meloun <[email protected]>
3
*
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
6
* are met:
7
* 1. Redistributions of source code must retain the above copyright
8
* notice, this list of conditions and the following disclaimer.
9
* 2. Redistributions in binary form must reproduce the above copyright
10
* notice, this list of conditions and the following disclaimer in the
11
* documentation and/or other materials provided with the distribution.
12
*
13
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23
* SUCH DAMAGE.
24
*/
25
26
#include <sys/cdefs.h>
27
/*
28
* ARMADA 8040 GPIO driver.
29
*/
30
#include "opt_platform.h"
31
#include <sys/param.h>
32
#include <sys/systm.h>
33
#include <sys/bus.h>
34
#include <sys/gpio.h>
35
#include <sys/kernel.h>
36
#include <sys/proc.h>
37
#include <sys/rman.h>
38
#include <sys/lock.h>
39
#include <sys/module.h>
40
#include <sys/mutex.h>
41
42
#include <machine/bus.h>
43
#include <machine/intr.h>
44
#include <machine/resource.h>
45
46
#include <dev/syscon/syscon.h>
47
48
#include <dev/gpio/gpiobusvar.h>
49
50
#include <dev/ofw/openfirm.h>
51
#include <dev/ofw/ofw_bus.h>
52
#include <dev/ofw/ofw_bus_subr.h>
53
54
#include "pic_if.h"
55
#include "syscon_if.h"
56
57
#define GPIO_LOCK(_sc) mtx_lock(&(_sc)->mtx)
58
#define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
59
#define GPIO_LOCK_INIT(_sc) mtx_init(&_sc->mtx, \
60
device_get_nameunit(_sc->dev), "mvebu_gpio", MTX_DEF)
61
#define GPIO_LOCK_DESTROY(_sc) mtx_destroy(&_sc->mtx);
62
#define GPIO_ASSERT_LOCKED(_sc) mtx_assert(&_sc->mtx, MA_OWNED);
63
#define GPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->mtx, MA_NOTOWNED);
64
65
#define GPIO_DATA_OUT 0x00
66
#define GPIO_CONTROL 0x04
67
#define GPIO_BLINK_ENA 0x08
68
#define GPIO_DATA_IN_POL 0x0C
69
#define GPIO_DATA_IN 0x10
70
#define GPIO_INT_CAUSE 0x14
71
#define GPIO_INT_MASK 0x18
72
#define GPIO_INT_LEVEL_MASK 0x1C
73
#define GPIO_CONTROL_SET 0x28
74
#define GPIO_CONTROL_CLR 0x2C
75
#define GPIO_DATA_SET 0x30
76
#define GPIO_DATA_CLR 0x34
77
78
#define GPIO_BIT(_p) ((_p) % 32)
79
#define GPIO_REGNUM(_p) ((_p) / 32)
80
81
#define MV_GPIO_MAX_NIRQS 4
82
#define MV_GPIO_MAX_NPINS 32
83
84
struct mvebu_gpio_irqsrc {
85
struct intr_irqsrc isrc;
86
u_int irq;
87
bool is_level;
88
bool is_inverted;
89
};
90
91
struct mvebu_gpio_softc;
92
struct mvebu_gpio_irq_cookie {
93
struct mvebu_gpio_softc *sc;
94
int bank_num;
95
};
96
97
struct mvebu_gpio_softc {
98
device_t dev;
99
device_t busdev;
100
struct mtx mtx;
101
struct syscon *syscon;
102
uint32_t offset;
103
struct resource *irq_res[MV_GPIO_MAX_NIRQS];
104
void *irq_ih[MV_GPIO_MAX_NIRQS];
105
struct mvebu_gpio_irq_cookie irq_cookies[MV_GPIO_MAX_NIRQS];
106
int gpio_npins;
107
struct gpio_pin gpio_pins[MV_GPIO_MAX_NPINS];
108
struct mvebu_gpio_irqsrc *isrcs;
109
};
110
111
static struct ofw_compat_data compat_data[] = {
112
{"marvell,armada-8k-gpio", 1},
113
{NULL, 0}
114
};
115
116
/* --------------------------------------------------------------------------
117
*
118
* GPIO
119
*
120
*/
121
static inline void
122
gpio_write(struct mvebu_gpio_softc *sc, bus_size_t reg,
123
struct gpio_pin *pin, uint32_t val)
124
{
125
int bit;
126
127
bit = GPIO_BIT(pin->gp_pin);
128
SYSCON_WRITE_4(sc->syscon, sc->offset + GPIO_REGNUM(pin->gp_pin) + reg,
129
(val & 1) << bit);
130
}
131
132
static inline uint32_t
133
gpio_read(struct mvebu_gpio_softc *sc, bus_size_t reg, struct gpio_pin *pin)
134
{
135
int bit;
136
uint32_t val;
137
138
bit = GPIO_BIT(pin->gp_pin);
139
val = SYSCON_READ_4(sc->syscon,
140
sc->offset + GPIO_REGNUM(pin->gp_pin) + reg);
141
142
return (val >> bit) & 1;
143
}
144
145
static inline void
146
gpio_modify(struct mvebu_gpio_softc *sc, bus_size_t reg,
147
struct gpio_pin *pin, uint32_t val)
148
{
149
int bit;
150
151
bit = GPIO_BIT(pin->gp_pin);
152
SYSCON_MODIFY_4(sc->syscon, sc->offset + GPIO_REGNUM(pin->gp_pin) + reg,
153
1 << bit, (val & 1) << bit);
154
}
155
156
static void
157
mvebu_gpio_pin_configure(struct mvebu_gpio_softc *sc, struct gpio_pin *pin,
158
unsigned int flags)
159
{
160
161
if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) == 0)
162
return;
163
164
/* Manage input/output */
165
pin->gp_flags &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT);
166
if (flags & GPIO_PIN_OUTPUT) {
167
pin->gp_flags |= GPIO_PIN_OUTPUT;
168
gpio_write(sc, GPIO_CONTROL_CLR, pin, 1);
169
} else {
170
pin->gp_flags |= GPIO_PIN_INPUT;
171
gpio_write(sc, GPIO_CONTROL_SET, pin, 1);
172
}
173
}
174
175
static device_t
176
mvebu_gpio_get_bus(device_t dev)
177
{
178
struct mvebu_gpio_softc *sc;
179
180
sc = device_get_softc(dev);
181
return (sc->busdev);
182
}
183
184
static int
185
mvebu_gpio_pin_max(device_t dev, int *maxpin)
186
{
187
struct mvebu_gpio_softc *sc;
188
189
sc = device_get_softc(dev);
190
*maxpin = sc->gpio_npins - 1;
191
return (0);
192
}
193
194
static int
195
mvebu_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
196
{
197
struct mvebu_gpio_softc *sc;
198
199
sc = device_get_softc(dev);
200
if (pin >= sc->gpio_npins)
201
return (EINVAL);
202
203
*caps = sc->gpio_pins[pin].gp_caps;
204
205
return (0);
206
}
207
208
static int
209
mvebu_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
210
{
211
struct mvebu_gpio_softc *sc;
212
213
sc = device_get_softc(dev);
214
if (pin >= sc->gpio_npins)
215
return (EINVAL);
216
217
*flags = sc->gpio_pins[pin].gp_flags;
218
219
return (0);
220
}
221
222
static int
223
mvebu_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
224
{
225
struct mvebu_gpio_softc *sc;
226
227
sc = device_get_softc(dev);
228
if (pin >= sc->gpio_npins)
229
return (EINVAL);
230
231
memcpy(name, sc->gpio_pins[pin].gp_name, GPIOMAXNAME);
232
233
return (0);
234
}
235
236
static int
237
mvebu_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
238
{
239
struct mvebu_gpio_softc *sc;
240
241
sc = device_get_softc(dev);
242
if (pin >= sc->gpio_npins)
243
return (EINVAL);
244
245
mvebu_gpio_pin_configure(sc, &sc->gpio_pins[pin], flags);
246
247
return (0);
248
}
249
250
static int
251
mvebu_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
252
{
253
struct mvebu_gpio_softc *sc;
254
255
sc = device_get_softc(dev);
256
if (pin >= sc->gpio_npins)
257
return (EINVAL);
258
259
if (value != 0)
260
gpio_write(sc, GPIO_DATA_SET, &sc->gpio_pins[pin], 1);
261
else
262
gpio_write(sc, GPIO_DATA_CLR, &sc->gpio_pins[pin], 1);
263
264
return (0);
265
}
266
267
static int
268
mvebu_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
269
{
270
struct mvebu_gpio_softc *sc;
271
272
sc = device_get_softc(dev);
273
if (pin >= sc->gpio_npins)
274
return (EINVAL);
275
276
GPIO_LOCK(sc);
277
*val = gpio_read(sc, GPIO_DATA_IN, &sc->gpio_pins[pin]);
278
*val ^= gpio_read(sc, GPIO_DATA_IN_POL, &sc->gpio_pins[pin]);
279
GPIO_UNLOCK(sc);
280
281
return (0);
282
}
283
284
static int
285
mvebu_gpio_pin_toggle(device_t dev, uint32_t pin)
286
{
287
struct mvebu_gpio_softc *sc;
288
uint32_t val;
289
290
sc = device_get_softc(dev);
291
if (pin >= sc->gpio_npins)
292
return (EINVAL);
293
294
GPIO_LOCK(sc);
295
mvebu_gpio_pin_get(sc->dev, pin, &val);
296
if (val != 0)
297
gpio_write(sc, GPIO_DATA_CLR, &sc->gpio_pins[pin], 1);
298
else
299
gpio_write(sc, GPIO_DATA_SET, &sc->gpio_pins[pin], 1);
300
GPIO_UNLOCK(sc);
301
302
return (0);
303
}
304
305
/* --------------------------------------------------------------------------
306
*
307
* Interrupts
308
*
309
*/
310
static inline void
311
intr_modify(struct mvebu_gpio_softc *sc, bus_addr_t reg,
312
struct mvebu_gpio_irqsrc *mgi, uint32_t val)
313
{
314
int bit;
315
316
bit = GPIO_BIT(mgi->irq);
317
SYSCON_MODIFY_4(sc->syscon,
318
sc->offset + GPIO_REGNUM(mgi->irq) + reg, 1 << bit,
319
(val & 1) << bit);
320
}
321
322
static inline void
323
mvebu_gpio_isrc_mask(struct mvebu_gpio_softc *sc,
324
struct mvebu_gpio_irqsrc *mgi, uint32_t val)
325
{
326
327
if (mgi->is_level)
328
intr_modify(sc, GPIO_INT_LEVEL_MASK, mgi, val);
329
else
330
intr_modify(sc, GPIO_INT_MASK, mgi, val);
331
}
332
333
static inline void
334
mvebu_gpio_isrc_eoi(struct mvebu_gpio_softc *sc,
335
struct mvebu_gpio_irqsrc *mgi)
336
{
337
int bit;
338
339
if (!mgi->is_level) {
340
bit = GPIO_BIT(mgi->irq);
341
SYSCON_WRITE_4(sc->syscon,
342
sc->offset + GPIO_REGNUM(mgi->irq) + GPIO_INT_CAUSE,
343
~(1 << bit));
344
}
345
}
346
347
static int
348
mvebu_gpio_pic_attach(struct mvebu_gpio_softc *sc)
349
{
350
int rv;
351
uint32_t irq;
352
const char *name;
353
354
sc->isrcs = malloc(sizeof(*sc->isrcs) * sc->gpio_npins, M_DEVBUF,
355
M_WAITOK | M_ZERO);
356
357
name = device_get_nameunit(sc->dev);
358
for (irq = 0; irq < sc->gpio_npins; irq++) {
359
sc->isrcs[irq].irq = irq;
360
sc->isrcs[irq].is_level = false;
361
sc->isrcs[irq].is_inverted = false;
362
rv = intr_isrc_register(&sc->isrcs[irq].isrc,
363
sc->dev, 0, "%s,%u", name, irq);
364
if (rv != 0)
365
return (rv); /* XXX deregister ISRCs */
366
}
367
if (intr_pic_register(sc->dev,
368
OF_xref_from_node(ofw_bus_get_node(sc->dev))) == NULL)
369
return (ENXIO);
370
371
return (0);
372
}
373
374
static int
375
mvebu_gpio_pic_detach(struct mvebu_gpio_softc *sc)
376
{
377
378
/*
379
* There has not been established any procedure yet
380
* how to detach PIC from living system correctly.
381
*/
382
device_printf(sc->dev, "%s: not implemented yet\n", __func__);
383
return (EBUSY);
384
}
385
386
static void
387
mvebu_gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
388
{
389
struct mvebu_gpio_softc *sc;
390
struct mvebu_gpio_irqsrc *mgi;
391
392
sc = device_get_softc(dev);
393
mgi = (struct mvebu_gpio_irqsrc *)isrc;
394
mvebu_gpio_isrc_mask(sc, mgi, 0);
395
}
396
397
static void
398
mvebu_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
399
{
400
struct mvebu_gpio_softc *sc;
401
struct mvebu_gpio_irqsrc *mgi;
402
403
sc = device_get_softc(dev);
404
mgi = (struct mvebu_gpio_irqsrc *)isrc;
405
mvebu_gpio_isrc_mask(sc, mgi, 1);
406
}
407
408
static int
409
mvebu_gpio_pic_map_fdt(struct mvebu_gpio_softc *sc, u_int ncells,
410
pcell_t *cells, u_int *irqp, bool *invertedp, bool *levelp)
411
{
412
bool inverted, level;
413
414
/*
415
* The first cell is the interrupt number.
416
* The second cell is used to specify flags:
417
* bits[3:0] trigger type and level flags:
418
* 1 = low-to-high edge triggered.
419
* 2 = high-to-low edge triggered.
420
* 4 = active high level-sensitive.
421
* 8 = active low level-sensitive.
422
*/
423
if (ncells != 2 || cells[0] >= sc->gpio_npins)
424
return (EINVAL);
425
426
switch (cells[1]) {
427
case 1:
428
inverted = false;
429
level = false;
430
break;
431
case 2:
432
inverted = true;
433
level = false;
434
break;
435
case 4:
436
inverted = false;
437
level = true;
438
break;
439
case 8:
440
inverted = true;
441
level = true;
442
break;
443
default:
444
return (EINVAL);
445
}
446
*irqp = cells[0];
447
if (invertedp != NULL)
448
*invertedp = inverted;
449
if (levelp != NULL)
450
*levelp = level;
451
return (0);
452
}
453
454
static int
455
mvebu_gpio_pic_map_gpio(struct mvebu_gpio_softc *sc, u_int gpio_pin_num,
456
u_int gpio_pin_flags, u_int intr_mode, u_int *irqp, bool *invertedp,
457
bool *levelp)
458
{
459
bool inverted, level;
460
461
if (gpio_pin_num >= sc->gpio_npins)
462
return (EINVAL);
463
464
switch (intr_mode) {
465
case GPIO_INTR_LEVEL_LOW:
466
inverted = true;
467
level = true;
468
break;
469
case GPIO_INTR_LEVEL_HIGH:
470
inverted = false;
471
level = true;
472
break;
473
case GPIO_INTR_CONFORM:
474
case GPIO_INTR_EDGE_RISING:
475
inverted = false;
476
level = false;
477
break;
478
case GPIO_INTR_EDGE_FALLING:
479
inverted = true;
480
level = false;
481
break;
482
default:
483
return (EINVAL);
484
}
485
*irqp = gpio_pin_num;
486
if (invertedp != NULL)
487
*invertedp = inverted;
488
if (levelp != NULL)
489
*levelp = level;
490
return (0);
491
}
492
493
static int
494
mvebu_gpio_pic_map_intr(device_t dev, struct intr_map_data *data,
495
struct intr_irqsrc **isrcp)
496
{
497
int rv;
498
u_int irq;
499
struct mvebu_gpio_softc *sc;
500
501
sc = device_get_softc(dev);
502
503
if (data->type == INTR_MAP_DATA_FDT) {
504
struct intr_map_data_fdt *daf;
505
506
daf = (struct intr_map_data_fdt *)data;
507
rv = mvebu_gpio_pic_map_fdt(sc, daf->ncells, daf->cells, &irq,
508
NULL, NULL);
509
} else if (data->type == INTR_MAP_DATA_GPIO) {
510
struct intr_map_data_gpio *dag;
511
512
dag = (struct intr_map_data_gpio *)data;
513
rv = mvebu_gpio_pic_map_gpio(sc, dag->gpio_pin_num,
514
dag->gpio_pin_flags, dag->gpio_intr_mode, &irq, NULL, NULL);
515
} else
516
return (ENOTSUP);
517
518
if (rv == 0)
519
*isrcp = &sc->isrcs[irq].isrc;
520
return (rv);
521
}
522
523
static void
524
mvebu_gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
525
{
526
struct mvebu_gpio_softc *sc;
527
struct mvebu_gpio_irqsrc *mgi;
528
529
sc = device_get_softc(dev);
530
mgi = (struct mvebu_gpio_irqsrc *)isrc;
531
if (mgi->is_level)
532
mvebu_gpio_isrc_eoi(sc, mgi);
533
}
534
535
static void
536
mvebu_gpio_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
537
{
538
struct mvebu_gpio_softc *sc;
539
struct mvebu_gpio_irqsrc *mgi;
540
541
sc = device_get_softc(dev);
542
mgi = (struct mvebu_gpio_irqsrc *)isrc;
543
mvebu_gpio_isrc_mask(sc, mgi, 1);
544
}
545
546
static void
547
mvebu_gpio_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
548
{
549
struct mvebu_gpio_softc *sc;
550
struct mvebu_gpio_irqsrc *mgi;
551
552
sc = device_get_softc(dev);
553
mgi = (struct mvebu_gpio_irqsrc *)isrc;
554
555
mvebu_gpio_isrc_mask(sc, mgi, 0);
556
if (mgi->is_level)
557
mvebu_gpio_isrc_eoi(sc, mgi);
558
}
559
560
static int
561
mvebu_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
562
struct resource *res, struct intr_map_data *data)
563
{
564
u_int irq;
565
bool inverted, level;
566
int rv;
567
struct mvebu_gpio_softc *sc;
568
struct mvebu_gpio_irqsrc *mgi;
569
570
sc = device_get_softc(dev);
571
mgi = (struct mvebu_gpio_irqsrc *)isrc;
572
573
if (data == NULL)
574
return (ENOTSUP);
575
576
/* Get and check config for an interrupt. */
577
if (data->type == INTR_MAP_DATA_FDT) {
578
struct intr_map_data_fdt *daf;
579
580
daf = (struct intr_map_data_fdt *)data;
581
rv = mvebu_gpio_pic_map_fdt(sc, daf->ncells, daf->cells, &irq,
582
&inverted, &level);
583
} else if (data->type == INTR_MAP_DATA_GPIO) {
584
struct intr_map_data_gpio *dag;
585
586
dag = (struct intr_map_data_gpio *)data;
587
rv = mvebu_gpio_pic_map_gpio(sc, dag->gpio_pin_num,
588
dag->gpio_pin_flags, dag->gpio_intr_mode, &irq,
589
&inverted, &level);
590
} else
591
return (ENOTSUP);
592
593
if (rv != 0)
594
return (EINVAL);
595
596
/*
597
* If this is a setup for another handler,
598
* only check that its configuration match.
599
*/
600
if (isrc->isrc_handlers != 0)
601
return (
602
mgi->is_level == level && mgi->is_inverted == inverted ?
603
0 : EINVAL);
604
605
mgi->is_level = level;
606
mgi->is_inverted = inverted;
607
608
GPIO_LOCK(sc);
609
intr_modify(sc, GPIO_DATA_IN_POL, mgi, inverted ? 1 : 0);
610
mvebu_gpio_pic_enable_intr(dev, isrc);
611
GPIO_UNLOCK(sc);
612
613
return (0);
614
}
615
616
static int
617
mvebu_gpio_pic_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
618
struct resource *res, struct intr_map_data *data)
619
{
620
struct mvebu_gpio_softc *sc;
621
struct mvebu_gpio_irqsrc *mgi;
622
623
sc = device_get_softc(dev);
624
mgi = (struct mvebu_gpio_irqsrc *)isrc;
625
626
if (isrc->isrc_handlers == 0)
627
mvebu_gpio_isrc_mask(sc, mgi, 0);
628
return (0);
629
}
630
631
/* --------------------------------------------------------------------------
632
*
633
* Bus
634
*
635
*/
636
637
static int
638
mvebu_gpio_intr(void *arg)
639
{
640
u_int i, lvl, edge;
641
struct mvebu_gpio_softc *sc;
642
struct trapframe *tf;
643
struct mvebu_gpio_irqsrc *mgi;
644
struct mvebu_gpio_irq_cookie *cookie;
645
646
cookie = (struct mvebu_gpio_irq_cookie *)arg;
647
sc = cookie->sc;
648
tf = curthread->td_intr_frame;
649
650
for (i = 0; i < sc->gpio_npins; i++) {
651
lvl = gpio_read(sc, GPIO_DATA_IN, &sc->gpio_pins[i]);
652
lvl &= gpio_read(sc, GPIO_INT_LEVEL_MASK, &sc->gpio_pins[i]);
653
edge = gpio_read(sc, GPIO_DATA_IN, &sc->gpio_pins[i]);
654
edge &= gpio_read(sc, GPIO_INT_LEVEL_MASK, &sc->gpio_pins[i]);
655
if (edge == 0 && lvl == 0)
656
continue;
657
658
mgi = &sc->isrcs[i];
659
if (!mgi->is_level)
660
mvebu_gpio_isrc_eoi(sc, mgi);
661
662
if (intr_isrc_dispatch(&mgi->isrc, tf) != 0) {
663
mvebu_gpio_isrc_mask(sc, mgi, 0);
664
if (mgi->is_level)
665
mvebu_gpio_isrc_eoi(sc, mgi);
666
device_printf(sc->dev,
667
"Stray irq %u disabled\n", mgi->irq);
668
}
669
}
670
return (FILTER_HANDLED);
671
}
672
673
static int
674
mvebu_gpio_probe(device_t dev)
675
{
676
677
if (!ofw_bus_status_okay(dev))
678
return (ENXIO);
679
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
680
return (ENXIO);
681
682
device_set_desc(dev, "Marvell Integrated GPIO Controller");
683
return (0);
684
}
685
686
static int
687
mvebu_gpio_detach(device_t dev)
688
{
689
struct mvebu_gpio_softc *sc;
690
int i;
691
692
sc = device_get_softc(dev);
693
694
KASSERT(mtx_initialized(&sc->mtx), ("gpio mutex not initialized"));
695
696
for (i = 0; i < MV_GPIO_MAX_NIRQS; i++) {
697
if (sc->irq_ih[i] != NULL)
698
bus_teardown_intr(dev, sc->irq_res[i], sc->irq_ih[i]);
699
}
700
701
if (sc->isrcs != NULL)
702
mvebu_gpio_pic_detach(sc);
703
704
gpiobus_detach_bus(dev);
705
706
for (i = 0; i < MV_GPIO_MAX_NIRQS; i++) {
707
if (sc->irq_res[i] != NULL)
708
bus_release_resource(dev, SYS_RES_IRQ, 0,
709
sc->irq_res[i]);
710
}
711
GPIO_LOCK_DESTROY(sc);
712
713
return(0);
714
}
715
716
static int
717
mvebu_gpio_attach(device_t dev)
718
{
719
struct mvebu_gpio_softc *sc;
720
phandle_t node;
721
struct gpio_pin *pin;
722
pcell_t pincnt;
723
int i, rv, rid;
724
725
sc = device_get_softc(dev);
726
sc->dev = dev;
727
node = ofw_bus_get_node(dev);
728
729
GPIO_LOCK_INIT(sc);
730
731
pincnt = 0;
732
rv = OF_getencprop(node, "ngpios", &pincnt, sizeof(pcell_t));
733
if (rv < 0) {
734
device_printf(dev,
735
"ERROR: no pin-count or ngpios entry found!\n");
736
return (ENXIO);
737
}
738
739
sc->gpio_npins = MIN(pincnt, MV_GPIO_MAX_NPINS);
740
if (bootverbose)
741
device_printf(dev,
742
"%d pins available\n", sc->gpio_npins);
743
744
rv = OF_getencprop(node, "offset", &sc->offset, sizeof(sc->offset));
745
if (rv == -1) {
746
device_printf(dev, "ERROR: no 'offset' property found!\n");
747
return (ENXIO);
748
}
749
750
if (SYSCON_GET_HANDLE(sc->dev, &sc->syscon) != 0 ||
751
sc->syscon == NULL) {
752
device_printf(dev, "ERROR: cannot get syscon handle!\n");
753
return (ENXIO);
754
}
755
756
/* Allocate interrupts. */
757
for (i = 0; i < MV_GPIO_MAX_NIRQS; i++) {
758
sc->irq_cookies[i].sc = sc;
759
sc->irq_cookies[i].bank_num = i;
760
rid = i;
761
sc->irq_res[i] = bus_alloc_resource_any(dev, SYS_RES_IRQ,
762
&rid, RF_ACTIVE);
763
if (sc->irq_res[i] == NULL)
764
break;
765
if ((bus_setup_intr(dev, sc->irq_res[i],
766
INTR_TYPE_MISC | INTR_MPSAFE, mvebu_gpio_intr, NULL,
767
&sc->irq_cookies[i], &sc->irq_ih[i]))) {
768
device_printf(dev,
769
"WARNING: unable to register interrupt handler\n");
770
mvebu_gpio_detach(dev);
771
return (ENXIO);
772
}
773
}
774
775
/* Init GPIO pins */
776
for (i = 0; i < sc->gpio_npins; i++) {
777
pin = sc->gpio_pins + i;
778
pin->gp_pin = i;
779
if (sc->irq_res[0] != NULL)
780
pin->gp_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |
781
GPIO_INTR_LEVEL_LOW | GPIO_INTR_LEVEL_HIGH |
782
GPIO_INTR_EDGE_RISING | GPIO_INTR_EDGE_FALLING;
783
else
784
pin->gp_caps = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
785
pin->gp_flags =
786
gpio_read(sc, GPIO_CONTROL, &sc->gpio_pins[i]) == 0 ?
787
GPIO_PIN_OUTPUT : GPIO_PIN_INPUT;
788
snprintf(pin->gp_name, GPIOMAXNAME, "gpio%d", i);
789
790
/* Init HW */
791
gpio_modify(sc, GPIO_INT_MASK, pin, 0);
792
gpio_modify(sc, GPIO_INT_LEVEL_MASK, pin, 0);
793
gpio_modify(sc, GPIO_INT_CAUSE, pin, 0);
794
gpio_modify(sc, GPIO_DATA_IN_POL, pin, 0);
795
gpio_modify(sc, GPIO_BLINK_ENA, pin, 0);
796
}
797
798
if (sc->irq_res[0] != NULL) {
799
rv = mvebu_gpio_pic_attach(sc);
800
if (rv != 0) {
801
device_printf(dev, "WARNING: unable to attach PIC\n");
802
mvebu_gpio_detach(dev);
803
return (rv);
804
}
805
}
806
807
sc->busdev = gpiobus_add_bus(dev);
808
if (sc->busdev == NULL) {
809
mvebu_gpio_detach(dev);
810
return (ENXIO);
811
}
812
813
bus_attach_children(dev);
814
return (0);
815
}
816
817
static int
818
mvebu_gpio_map_gpios(device_t dev, phandle_t pdev, phandle_t gparent,
819
int gcells, pcell_t *gpios, uint32_t *pin, uint32_t *flags)
820
{
821
822
if (gcells != 2)
823
return (ERANGE);
824
*pin = gpios[0];
825
*flags= gpios[1];
826
return (0);
827
}
828
829
static phandle_t
830
mvebu_gpio_get_node(device_t bus, device_t dev)
831
{
832
833
/* We only have one child, the GPIO bus, which needs our own node. */
834
return (ofw_bus_get_node(bus));
835
}
836
837
static device_method_t mvebu_gpio_methods[] = {
838
DEVMETHOD(device_probe, mvebu_gpio_probe),
839
DEVMETHOD(device_attach, mvebu_gpio_attach),
840
DEVMETHOD(device_detach, mvebu_gpio_detach),
841
842
/* Bus interface */
843
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
844
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
845
846
/* Interrupt controller interface */
847
DEVMETHOD(pic_disable_intr, mvebu_gpio_pic_disable_intr),
848
DEVMETHOD(pic_enable_intr, mvebu_gpio_pic_enable_intr),
849
DEVMETHOD(pic_map_intr, mvebu_gpio_pic_map_intr),
850
DEVMETHOD(pic_setup_intr, mvebu_gpio_pic_setup_intr),
851
DEVMETHOD(pic_teardown_intr, mvebu_gpio_pic_teardown_intr),
852
DEVMETHOD(pic_post_filter, mvebu_gpio_pic_post_filter),
853
DEVMETHOD(pic_post_ithread, mvebu_gpio_pic_post_ithread),
854
DEVMETHOD(pic_pre_ithread, mvebu_gpio_pic_pre_ithread),
855
856
/* GPIO protocol */
857
DEVMETHOD(gpio_get_bus, mvebu_gpio_get_bus),
858
DEVMETHOD(gpio_pin_max, mvebu_gpio_pin_max),
859
DEVMETHOD(gpio_pin_getname, mvebu_gpio_pin_getname),
860
DEVMETHOD(gpio_pin_getflags, mvebu_gpio_pin_getflags),
861
DEVMETHOD(gpio_pin_getcaps, mvebu_gpio_pin_getcaps),
862
DEVMETHOD(gpio_pin_setflags, mvebu_gpio_pin_setflags),
863
DEVMETHOD(gpio_pin_get, mvebu_gpio_pin_get),
864
DEVMETHOD(gpio_pin_set, mvebu_gpio_pin_set),
865
DEVMETHOD(gpio_pin_toggle, mvebu_gpio_pin_toggle),
866
DEVMETHOD(gpio_map_gpios, mvebu_gpio_map_gpios),
867
868
/* ofw_bus interface */
869
DEVMETHOD(ofw_bus_get_node, mvebu_gpio_get_node),
870
871
DEVMETHOD_END
872
};
873
874
static DEFINE_CLASS_0(gpio, mvebu_gpio_driver, mvebu_gpio_methods,
875
sizeof(struct mvebu_gpio_softc));
876
EARLY_DRIVER_MODULE(mvebu_gpio, simplebus, mvebu_gpio_driver, NULL, NULL,
877
BUS_PASS_TIMER + BUS_PASS_ORDER_LAST);
878
879