View | Details | Raw Unified | Return to bug 207405
Collapse All | Expand All

(-)sys/dev/nctgpio/nctgpio.c (+741 lines)
Line 0 Link Here
1
/*-
2
 * Copyright (c) 2016 Daniel Wyatt <Daniel.Wyatt@gmail.com>
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
 * SUCH DAMAGE.
25
 */
26
/*
27
 * Nuvoton GPIO driver.
28
 *
29
 */
30
31
#include <sys/cdefs.h>
32
33
#include <sys/param.h>
34
#include <sys/kernel.h>
35
#include <sys/systm.h>
36
#include <sys/bus.h>
37
#include <sys/eventhandler.h>
38
#include <sys/lock.h>
39
40
#include <sys/module.h>
41
#include <sys/rman.h>
42
#include <sys/gpio.h>
43
44
#include <isa/isavar.h>
45
46
#include <machine/bus.h>
47
#include <machine/resource.h>
48
49
#include <dev/gpio/gpiobusvar.h>
50
51
#include "gpio_if.h"
52
53
/*
54
 * Global configuration registers (CR).
55
 */
56
#define NCT_CR_LDN			0x07	/* Logical Device Number */
57
#define NCT_CR_CHIP_ID			0x20 	/* Chip ID */
58
#define NCT_CR_CHIP_ID_H		0x20 	/* Chip ID (high byte) */
59
#define NCT_CR_CHIP_ID_L		0x21 	/* Chip ID (low byte) */
60
#define NCT_CR_OPT_1			0x26	/* Global Options (1) */
61
62
/* Logical Device Numbers. */
63
#define NCT_LDN_GPIO			0x07
64
#define NCT_LDN_GPIO_CFG		0x08
65
#define NCT_LDN_GPIO_MODE		0x0f
66
67
/* Logical Device 7 */
68
#define NCT_LD7_GPIO_ENABLE		0x30
69
#define NCT_LD7_GPIO0_IOR		0xe0
70
#define NCT_LD7_GPIO0_DAT		0xe1
71
#define NCT_LD7_GPIO0_INV		0xe2
72
#define NCT_LD7_GPIO0_DST		0xe3
73
#define NCT_LD7_GPIO1_IOR		0xe4
74
#define NCT_LD7_GPIO1_DAT		0xe5
75
#define NCT_LD7_GPIO1_INV		0xe6
76
#define NCT_LD7_GPIO1_DST		0xe7
77
78
/* Logical Device F */
79
#define NCT_LDF_GPIO0_OUTCFG		0xe0
80
#define NCT_LDF_GPIO1_OUTCFG		0xe1
81
82
#define NCT_EXTFUNC_ENTER		0x87
83
#define NCT_EXTFUNC_EXIT		0xaa
84
85
#define NCT_MAX_PIN			15
86
#define NCT_IS_VALID_PIN(_p)	((_p) >= 0 && (_p) <= NCT_MAX_PIN)
87
88
#define NCT_PIN_BIT(_p)         (1 << ((_p) % 8))
89
90
#define NCT_GPIO_CAPS	(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
91
	GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL | \
92
	GPIO_PIN_INVIN | GPIO_PIN_INVOUT)
93
94
struct nct_softc {
95
	device_t			dev;
96
	device_t			busdev;
97
	struct mtx			mtx;
98
	struct resource			*portres;
99
	int				rid;
100
	struct gpio_pin			pins[NCT_MAX_PIN];
101
};
102
103
#define	GPIO_LOCK(_sc)		mtx_lock(&(_sc)->mtx)
104
#define GPIO_UNLOCK(_sc)	mtx_unlock(&(_sc)->mtx)
105
106
static void	ext_cfg_enter(struct nct_softc *);
107
static void	ext_cfg_exit(struct nct_softc *);
108
109
/*
110
 * Potential Extended Function Enable Register addresses.
111
 * Same address as EFIR.
112
 */
113
uint8_t probe_addrs[] = {0x2e, 0x4e};
114
115
struct nuvoton_vendor_device_id {
116
	uint16_t		chip_id;
117
	const char *		descr;
118
} nct_devs[] = {
119
	{
120
		.chip_id	= 0x1061,
121
		.descr		= "Nuvoton NCT5104D",
122
	},
123
	{
124
		.chip_id	= 0xc452,
125
		.descr		= "Nuvoton NCT5104D (PC-Engines APU)",
126
	},
127
};
128
129
static void
130
write_cfg_reg_1(struct nct_softc *sc, uint8_t reg, uint8_t value)
131
{
132
	bus_write_1(sc->portres, 0, reg);
133
	bus_write_1(sc->portres, 1, value);
134
}
135
136
static uint8_t
137
read_cfg_reg_1(struct nct_softc *sc, uint8_t reg)
138
{
139
	bus_write_1(sc->portres, 0, reg);
140
141
	return (bus_read_1(sc->portres, 1));
142
}
143
144
static uint16_t
145
read_cfg_reg_2(struct nct_softc *sc, uint8_t reg)
146
{
147
	uint16_t value;
148
149
	value = read_cfg_reg_1(sc, reg) << 8;
150
	value |= read_cfg_reg_1(sc, reg + 1);
151
152
	return (value);
153
}
154
155
/*
156
 * Enable extended function mode.
157
 *
158
 */
159
static void
160
ext_cfg_enter(struct nct_softc *sc)
161
{
162
	bus_write_1(sc->portres, 0, NCT_EXTFUNC_ENTER);
163
	bus_write_1(sc->portres, 0, NCT_EXTFUNC_ENTER);
164
}
165
166
/*
167
 * Disable extended function mode.
168
 *
169
 */
170
static void
171
ext_cfg_exit(struct nct_softc *sc)
172
{
173
	bus_write_1(sc->portres, 0, NCT_EXTFUNC_EXIT);
174
}
175
176
/*
177
 * Select a Logical Device.
178
 */
179
static void
180
select_ldn(struct nct_softc *sc, uint8_t ldn)
181
{
182
	write_cfg_reg_1(sc, NCT_CR_LDN, ldn);
183
}
184
185
/*
186
 * Get the GPIO Input/Output register address
187
 * for a pin.
188
 */
189
static uint8_t
190
nct_ior_addr(uint32_t pin_num)
191
{
192
	uint8_t addr;
193
194
	addr = NCT_LD7_GPIO0_IOR;
195
	if (pin_num > 7)
196
		addr = NCT_LD7_GPIO1_IOR;
197
198
	return (addr);
199
}
200
201
/*
202
 * Get the GPIO Data register address for a pin.
203
 */
204
static uint8_t
205
nct_dat_addr(uint32_t pin_num)
206
{
207
	uint8_t addr;
208
209
	addr = NCT_LD7_GPIO0_DAT;
210
	if (pin_num > 7)
211
		addr = NCT_LD7_GPIO1_DAT;
212
213
	return (addr);
214
}
215
216
/*
217
 * Get the GPIO Inversion register address
218
 * for a pin.
219
 */
220
static uint8_t
221
nct_inv_addr(uint32_t pin_num)
222
{
223
	uint8_t addr;
224
225
	addr = NCT_LD7_GPIO0_INV;
226
	if (pin_num > 7)
227
		addr = NCT_LD7_GPIO1_INV;
228
229
	return (addr);
230
}
231
232
/*
233
 * Get the GPIO Output Configuration/Mode
234
 * register address for a pin.
235
 */
236
static uint8_t
237
nct_outcfg_addr(uint32_t pin_num)
238
{
239
	uint8_t addr;
240
241
	addr = NCT_LDF_GPIO0_OUTCFG;
242
	if (pin_num > 7)
243
		addr = NCT_LDF_GPIO1_OUTCFG;
244
245
	return (addr);
246
}
247
248
/*
249
 * Set a pin to output mode.
250
 */
251
static void
252
nct_set_pin_is_output(struct nct_softc *sc, uint32_t pin_num)
253
{
254
	uint8_t reg;
255
	uint8_t ior;
256
257
	reg = nct_ior_addr(pin_num);
258
	select_ldn(sc, NCT_LDN_GPIO);
259
	ior = read_cfg_reg_1(sc, reg);
260
	ior &= ~(NCT_PIN_BIT(pin_num));
261
	write_cfg_reg_1(sc, reg, ior);
262
}
263
264
/*
265
 * Set a pin to input mode.
266
 */
267
static void
268
nct_set_pin_is_input(struct nct_softc *sc, uint32_t pin_num)
269
{
270
	uint8_t reg;
271
	uint8_t ior;
272
273
	reg = nct_ior_addr(pin_num);
274
	select_ldn(sc, NCT_LDN_GPIO);
275
	ior = read_cfg_reg_1(sc, reg);
276
	ior |= NCT_PIN_BIT(pin_num);
277
	write_cfg_reg_1(sc, reg, ior);
278
}
279
280
/*
281
 * Check whether a pin is configured as an input.
282
 */
283
static bool
284
nct_pin_is_input(struct nct_softc *sc, uint32_t pin_num)
285
{
286
	uint8_t reg;
287
	uint8_t ior;
288
289
	reg = nct_ior_addr(pin_num);
290
	select_ldn(sc, NCT_LDN_GPIO);
291
	ior = read_cfg_reg_1(sc, reg);
292
293
	return (ior & NCT_PIN_BIT(pin_num));
294
}
295
296
/*
297
 * Write a value to an output pin.
298
 */
299
static void
300
nct_write_pin(struct nct_softc *sc, uint32_t pin_num, uint8_t data)
301
{
302
	uint8_t reg;
303
304
	reg = nct_dat_addr(pin_num);
305
	select_ldn(sc, NCT_LDN_GPIO);
306
	write_cfg_reg_1(sc, reg, data);
307
}
308
309
static bool
310
nct_read_pin(struct nct_softc *sc, uint32_t pin_num)
311
{
312
	uint8_t reg;
313
314
	reg = nct_dat_addr(pin_num);
315
	select_ldn(sc, NCT_LDN_GPIO);
316
317
	return (read_cfg_reg_1(sc, reg) == 0);
318
}
319
320
static void
321
nct_set_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num)
322
{
323
	uint8_t reg;
324
	uint8_t inv;
325
326
	reg = nct_inv_addr(pin_num);
327
	select_ldn(sc, NCT_LDN_GPIO);
328
	inv = read_cfg_reg_1(sc, reg);
329
	inv |= (NCT_PIN_BIT(pin_num));
330
	write_cfg_reg_1(sc, reg, inv);
331
}
332
333
static void
334
nct_set_pin_not_inverted(struct nct_softc *sc, uint32_t pin_num)
335
{
336
	uint8_t reg;
337
	uint8_t inv;
338
339
	reg = nct_inv_addr(pin_num);
340
	select_ldn(sc, NCT_LDN_GPIO);
341
	inv = read_cfg_reg_1(sc, reg);
342
	inv &= ~(NCT_PIN_BIT(pin_num));
343
	write_cfg_reg_1(sc, reg, inv);
344
}
345
346
static bool
347
nct_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num)
348
{
349
	uint8_t reg;
350
	uint8_t inv;
351
352
	reg = nct_inv_addr(pin_num);
353
	select_ldn(sc, NCT_LDN_GPIO);
354
	inv = read_cfg_reg_1(sc, reg);
355
356
	return (inv & NCT_PIN_BIT(pin_num));
357
}
358
359
static void
360
nct_set_pin_opendrain(struct nct_softc *sc, uint32_t pin_num)
361
{
362
	uint8_t reg;
363
	uint8_t outcfg;
364
365
	reg = nct_outcfg_addr(pin_num);
366
	select_ldn(sc, NCT_LDN_GPIO_MODE);
367
	outcfg = read_cfg_reg_1(sc, reg);
368
	outcfg |= (NCT_PIN_BIT(pin_num));
369
	write_cfg_reg_1(sc, reg, outcfg);
370
}
371
372
static void
373
nct_set_pin_pushpull(struct nct_softc *sc, uint32_t pin_num)
374
{
375
	uint8_t reg;
376
	uint8_t outcfg;
377
378
	reg = nct_outcfg_addr(pin_num);
379
	select_ldn(sc, NCT_LDN_GPIO_MODE);
380
	outcfg = read_cfg_reg_1(sc, reg);
381
	outcfg &= ~(NCT_PIN_BIT(pin_num));
382
	write_cfg_reg_1(sc, reg, outcfg);
383
}
384
385
static bool
386
nct_pin_is_opendrain(struct nct_softc *sc, uint32_t pin_num)
387
{
388
	uint8_t reg;
389
	uint8_t outcfg;
390
391
	reg = nct_outcfg_addr(pin_num);
392
	select_ldn(sc, NCT_LDN_GPIO_MODE);
393
	outcfg = read_cfg_reg_1(sc, reg);
394
395
	return (outcfg & NCT_PIN_BIT(pin_num));
396
}
397
398
static void
399
nct_identify(driver_t *driver, device_t parent)
400
{
401
	if (device_find_child(parent, driver->name, 0) != NULL)
402
		return;
403
404
	BUS_ADD_CHILD(parent, 0, driver->name, 0);
405
}
406
407
static int
408
nct_probe(device_t dev)
409
{
410
	int i, j;
411
	int rc;
412
	struct nct_softc *sc;
413
	uint16_t chipid;
414
415
	/* Make sure we do not claim some ISA PNP device. */
416
	if (isa_get_logicalid(dev) != 0)
417
		return (ENXIO);
418
419
	sc = device_get_softc(dev);
420
421
	for (i = 0; i < sizeof(probe_addrs) / sizeof(*probe_addrs); i++) {
422
		sc->rid = 0;
423
		sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid,
424
			probe_addrs[i], probe_addrs[i] + 1, 2, RF_ACTIVE);
425
		if (sc->portres == NULL)
426
			continue;
427
428
		ext_cfg_enter(sc);
429
		chipid = read_cfg_reg_2(sc, NCT_CR_CHIP_ID);
430
		ext_cfg_exit(sc);
431
432
		bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres);
433
		bus_delete_resource(dev, SYS_RES_IOPORT, sc->rid);
434
435
		for (j = 0; j < sizeof(nct_devs) / sizeof(*nct_devs); j++) {
436
			if (chipid == nct_devs[j].chip_id) {
437
				rc = bus_set_resource(dev, SYS_RES_IOPORT, 0, probe_addrs[i], 2);
438
				if (rc != 0) {
439
					device_printf(dev, "bus_set_resource failed for address 0x%02X\n", probe_addrs[i]);
440
					continue;
441
				}
442
				device_set_desc(dev, nct_devs[j].descr);
443
				return (BUS_PROBE_DEFAULT);
444
			}
445
		}
446
	}
447
	return (ENXIO);
448
}
449
450
static int
451
nct_attach(device_t dev)
452
{
453
	struct nct_softc *sc;
454
	int i;
455
456
	sc = device_get_softc(dev);
457
458
	sc->rid = 0;
459
	sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid,
460
		0ul, ~0ul, 2, RF_ACTIVE);
461
	if (sc->portres == NULL) {
462
		device_printf(dev, "cannot allocate ioport\n");
463
		return (ENXIO);
464
	}
465
466
	ext_cfg_enter(sc);
467
	select_ldn(sc, NCT_LDN_GPIO);
468
	/* Enable gpio0 and gpio1. */
469
	write_cfg_reg_1(sc, NCT_LD7_GPIO_ENABLE,
470
		read_cfg_reg_1(sc, NCT_LD7_GPIO_ENABLE) | 0x02);
471
472
	mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
473
474
	for (i = 0; i < NCT_MAX_PIN; i++) {
475
		struct gpio_pin *pin;
476
477
		pin = &sc->pins[i];
478
		pin->gp_pin = i;
479
		pin->gp_caps = NCT_GPIO_CAPS;
480
		pin->gp_flags = 0;
481
482
		snprintf(pin->gp_name, GPIOMAXNAME, "GPIO%02u", i);
483
		pin->gp_name[GPIOMAXNAME - 1] = '\0';
484
485
		if (nct_pin_is_input(sc, i))
486
			pin->gp_flags |= GPIO_PIN_INPUT;
487
		else
488
			pin->gp_flags |= GPIO_PIN_OUTPUT;
489
490
		if (nct_pin_is_opendrain(sc, i))
491
			pin->gp_flags |= GPIO_PIN_OPENDRAIN;
492
		else
493
			pin->gp_flags |= GPIO_PIN_PUSHPULL;
494
495
		if (nct_pin_is_inverted(sc, i))
496
			pin->gp_flags |= (GPIO_PIN_INVIN | GPIO_PIN_INVOUT);
497
	}
498
499
	sc->busdev = gpiobus_attach_bus(dev);
500
	if (sc->busdev == NULL) {
501
		ext_cfg_exit(sc);
502
		bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres);
503
		mtx_destroy(&sc->mtx);
504
		return (ENXIO);
505
	}
506
507
	return (0);
508
}
509
510
static int
511
nct_detach(device_t dev)
512
{
513
	struct nct_softc *sc;
514
515
	sc = device_get_softc(dev);
516
	gpiobus_detach_bus(dev);
517
518
	ext_cfg_exit(sc);
519
520
	/* Cleanup resources. */
521
	bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres);
522
523
	mtx_destroy(&sc->mtx);
524
525
	return (0);
526
}
527
528
static device_t
529
nct_gpio_get_bus(device_t dev)
530
{
531
	struct nct_softc *sc;
532
533
	sc = device_get_softc(dev);
534
535
	return (sc->busdev);
536
}
537
538
static int
539
nct_gpio_pin_max(device_t dev, int *npins)
540
{
541
	*npins = NCT_MAX_PIN;
542
543
	return (0);
544
}
545
546
static int
547
nct_gpio_pin_set(device_t dev, uint32_t pin_num, uint32_t pin_value)
548
{
549
	struct nct_softc *sc;
550
551
	if (!NCT_IS_VALID_PIN(pin_num))
552
		return (EINVAL);
553
554
	sc = device_get_softc(dev);
555
	GPIO_LOCK(sc);
556
	nct_write_pin(sc, pin_num, pin_value);
557
	GPIO_UNLOCK(sc);
558
559
	return (0);
560
}
561
562
static int
563
nct_gpio_pin_get(device_t dev, uint32_t pin_num, uint32_t *pin_value)
564
{
565
	struct nct_softc *sc;
566
567
	if (!NCT_IS_VALID_PIN(pin_num))
568
		return (EINVAL);
569
570
	sc = device_get_softc(dev);
571
	GPIO_LOCK(sc);
572
	*pin_value = nct_read_pin(sc, pin_num);
573
	GPIO_UNLOCK(sc);
574
575
	return (0);
576
}
577
578
static int
579
nct_gpio_pin_toggle(device_t dev, uint32_t pin_num)
580
{
581
	struct nct_softc *sc;
582
583
	if (!NCT_IS_VALID_PIN(pin_num))
584
		return (EINVAL);
585
586
	sc = device_get_softc(dev);
587
	GPIO_LOCK(sc);
588
	if (nct_read_pin(sc, pin_num))
589
		nct_write_pin(sc, pin_num, 0);
590
	else
591
		nct_write_pin(sc, pin_num, 1);
592
593
	GPIO_UNLOCK(sc);
594
595
	return (0);
596
}
597
598
static int
599
nct_gpio_pin_getcaps(device_t dev, uint32_t pin_num, uint32_t *caps)
600
{
601
	struct nct_softc *sc;
602
603
	if (!NCT_IS_VALID_PIN(pin_num))
604
		return (EINVAL);
605
606
	sc = device_get_softc(dev);
607
	GPIO_LOCK(sc);
608
	*caps = sc->pins[pin_num].gp_caps;
609
	GPIO_UNLOCK(sc);
610
611
	return (0);
612
}
613
614
static int
615
nct_gpio_pin_getflags(device_t dev, uint32_t pin_num, uint32_t *flags)
616
{
617
	struct nct_softc *sc;
618
619
	if (!NCT_IS_VALID_PIN(pin_num))
620
		return (EINVAL);
621
622
	sc = device_get_softc(dev);
623
	GPIO_LOCK(sc);
624
	*flags = sc->pins[pin_num].gp_flags;
625
	GPIO_UNLOCK(sc);
626
627
	return (0);
628
}
629
630
static int
631
nct_gpio_pin_getname(device_t dev, uint32_t pin_num, char *name)
632
{
633
	struct nct_softc *sc;
634
635
	if (!NCT_IS_VALID_PIN(pin_num))
636
		return (EINVAL);
637
638
	sc = device_get_softc(dev);
639
	GPIO_LOCK(sc);
640
	memcpy(name, sc->pins[pin_num].gp_name, GPIOMAXNAME);
641
	GPIO_UNLOCK(sc);
642
643
	return (0);
644
}
645
646
static int
647
nct_gpio_pin_setflags(device_t dev, uint32_t pin_num, uint32_t flags)
648
{
649
	struct nct_softc *sc;
650
	struct gpio_pin *pin;
651
652
	if (!NCT_IS_VALID_PIN(pin_num))
653
		return (EINVAL);
654
655
	sc = device_get_softc(dev);
656
	pin = &sc->pins[pin_num];
657
	if ((flags & pin->gp_caps) != flags)
658
		return (EINVAL);
659
660
	GPIO_LOCK(sc);
661
	if (flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) {
662
		if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) ==
663
			(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) {
664
				GPIO_UNLOCK(sc);
665
				return (EINVAL);
666
		}
667
668
		if (flags & GPIO_PIN_INPUT)
669
			nct_set_pin_is_input(sc, pin_num);
670
		else
671
			nct_set_pin_is_output(sc, pin_num);
672
	}
673
674
	if (flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) {
675
		if (flags & GPIO_PIN_INPUT) {
676
			GPIO_UNLOCK(sc);
677
			return (EINVAL);
678
		}
679
680
		if ((flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) ==
681
			(GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) {
682
				GPIO_UNLOCK(sc);
683
				return (EINVAL);
684
		}
685
686
		if (flags & GPIO_PIN_OPENDRAIN)
687
			nct_set_pin_opendrain(sc, pin_num);
688
		else
689
			nct_set_pin_pushpull(sc, pin_num);
690
	}
691
692
	if (flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) {
693
		if ((flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) !=
694
			(GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) {
695
				GPIO_UNLOCK(sc);
696
				return (EINVAL);
697
		}
698
699
		if (flags & GPIO_PIN_INVIN)
700
			nct_set_pin_is_inverted(sc, pin_num);
701
		else
702
			nct_set_pin_not_inverted(sc, pin_num);
703
	}
704
705
	pin->gp_flags = flags;
706
	GPIO_UNLOCK(sc);
707
708
	return (0);
709
}
710
711
static device_method_t nct_methods[] = {
712
	/* Device interface */
713
	DEVMETHOD(device_identify,	nct_identify),
714
	DEVMETHOD(device_probe,		nct_probe),
715
	DEVMETHOD(device_attach,	nct_attach),
716
	DEVMETHOD(device_detach,	nct_detach),
717
718
	/* GPIO */
719
	DEVMETHOD(gpio_get_bus,			nct_gpio_get_bus),
720
	DEVMETHOD(gpio_pin_max,			nct_gpio_pin_max),
721
	DEVMETHOD(gpio_pin_get,			nct_gpio_pin_get),
722
	DEVMETHOD(gpio_pin_set,			nct_gpio_pin_set),
723
	DEVMETHOD(gpio_pin_toggle,		nct_gpio_pin_toggle),
724
	DEVMETHOD(gpio_pin_getname,		nct_gpio_pin_getname),
725
	DEVMETHOD(gpio_pin_getcaps,		nct_gpio_pin_getcaps),
726
	DEVMETHOD(gpio_pin_getflags,	nct_gpio_pin_getflags),
727
	DEVMETHOD(gpio_pin_setflags,	nct_gpio_pin_setflags),
728
729
	DEVMETHOD_END
730
};
731
732
static driver_t nct_isa_driver = {
733
	"gpio",
734
	nct_methods,
735
	sizeof(struct nct_softc)
736
};
737
738
static devclass_t nct_devclass;
739
740
DRIVER_MODULE(nctgpio, isa, nct_isa_driver, nct_devclass, NULL, NULL);
741
MODULE_DEPEND(nctgpio, gpiobus, 1, 1, 1);
(-)sys/modules/nctgpio/Makefile (+6 lines)
Line 0 Link Here
1
.PATH:	${.CURDIR}/../../dev/nctgpio
2
KMOD=	nctgpio
3
SRCS=	nctgpio.c
4
SRCS+=	device_if.h bus_if.h isa_if.h gpio_if.h opt_platform.h
5
6
.include <bsd.kmod.mk>

Return to bug 207405