2 * Copyright (c) 2016 Daniel Wyatt <Daniel.Wyatt@gmail.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
31 * Nuvoton GPIO driver.
35 #include <sys/cdefs.h>
37 #include <sys/param.h>
38 #include <sys/kernel.h>
39 #include <sys/systm.h>
41 #include <sys/eventhandler.h>
44 #include <sys/module.h>
48 #include <isa/isavar.h>
50 #include <machine/bus.h>
51 #include <machine/resource.h>
53 #include <dev/gpio/gpiobusvar.h>
58 * Global configuration registers (CR).
60 #define NCT_CR_LDN 0x07 /* Logical Device Number */
61 #define NCT_CR_CHIP_ID 0x20 /* Chip ID */
62 #define NCT_CR_CHIP_ID_H 0x20 /* Chip ID (high byte) */
63 #define NCT_CR_CHIP_ID_L 0x21 /* Chip ID (low byte) */
64 #define NCT_CR_OPT_1 0x26 /* Global Options (1) */
66 /* Logical Device Numbers. */
67 #define NCT_LDN_GPIO 0x07
68 #define NCT_LDN_GPIO_CFG 0x08
69 #define NCT_LDN_GPIO_MODE 0x0f
71 /* Logical Device 7 */
72 #define NCT_LD7_GPIO_ENABLE 0x30
73 #define NCT_LD7_GPIO0_IOR 0xe0
74 #define NCT_LD7_GPIO0_DAT 0xe1
75 #define NCT_LD7_GPIO0_INV 0xe2
76 #define NCT_LD7_GPIO0_DST 0xe3
77 #define NCT_LD7_GPIO1_IOR 0xe4
78 #define NCT_LD7_GPIO1_DAT 0xe5
79 #define NCT_LD7_GPIO1_INV 0xe6
80 #define NCT_LD7_GPIO1_DST 0xe7
82 /* Logical Device F */
83 #define NCT_LDF_GPIO0_OUTCFG 0xe0
84 #define NCT_LDF_GPIO1_OUTCFG 0xe1
86 #define NCT_EXTFUNC_ENTER 0x87
87 #define NCT_EXTFUNC_EXIT 0xaa
89 #define NCT_MAX_PIN 15
90 #define NCT_IS_VALID_PIN(_p) ((_p) >= 0 && (_p) <= NCT_MAX_PIN)
92 #define NCT_PIN_BIT(_p) (1 << ((_p) % 8))
94 #define NCT_GPIO_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
95 GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL | \
96 GPIO_PIN_INVIN | GPIO_PIN_INVOUT)
102 struct resource *portres;
104 struct gpio_pin pins[NCT_MAX_PIN + 1];
107 #define GPIO_LOCK_INIT(_sc) mtx_init(&(_sc)->mtx, \
108 device_get_nameunit(dev), NULL, MTX_DEF)
109 #define GPIO_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->mtx)
110 #define GPIO_LOCK(_sc) mtx_lock(&(_sc)->mtx)
111 #define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
112 #define GPIO_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_OWNED)
113 #define GPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_NOTOWNED)
115 #define NCT_BARRIER_WRITE(_sc) \
116 bus_barrier((_sc)->portres, 0, 2, BUS_SPACE_BARRIER_WRITE)
118 #define NCT_BARRIER_READ_WRITE(_sc) \
119 bus_barrier((_sc)->portres, 0, 2, \
120 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)
122 static void ext_cfg_enter(struct nct_softc *);
123 static void ext_cfg_exit(struct nct_softc *);
126 * Potential Extended Function Enable Register addresses.
127 * Same address as EFIR.
129 uint8_t probe_addrs[] = {0x2e, 0x4e};
131 struct nuvoton_vendor_device_id {
137 .descr = "Nuvoton NCT5104D",
141 .descr = "Nuvoton NCT5104D (PC-Engines APU)",
146 write_cfg_reg_1(struct nct_softc *sc, uint8_t reg, uint8_t value)
148 GPIO_ASSERT_LOCKED(sc);
149 bus_write_1(sc->portres, 0, reg);
150 NCT_BARRIER_WRITE(sc);
151 bus_write_1(sc->portres, 1, value);
152 NCT_BARRIER_WRITE(sc);
156 read_cfg_reg_1(struct nct_softc *sc, uint8_t reg)
160 GPIO_ASSERT_LOCKED(sc);
161 bus_write_1(sc->portres, 0, reg);
162 NCT_BARRIER_READ_WRITE(sc);
163 value = bus_read_1(sc->portres, 1);
164 NCT_BARRIER_READ_WRITE(sc);
170 read_cfg_reg_2(struct nct_softc *sc, uint8_t reg)
174 value = read_cfg_reg_1(sc, reg) << 8;
175 value |= read_cfg_reg_1(sc, reg + 1);
181 * Enable extended function mode.
185 ext_cfg_enter(struct nct_softc *sc)
187 GPIO_ASSERT_LOCKED(sc);
188 bus_write_1(sc->portres, 0, NCT_EXTFUNC_ENTER);
189 NCT_BARRIER_WRITE(sc);
190 bus_write_1(sc->portres, 0, NCT_EXTFUNC_ENTER);
191 NCT_BARRIER_WRITE(sc);
195 * Disable extended function mode.
199 ext_cfg_exit(struct nct_softc *sc)
201 GPIO_ASSERT_LOCKED(sc);
202 bus_write_1(sc->portres, 0, NCT_EXTFUNC_EXIT);
203 NCT_BARRIER_WRITE(sc);
207 * Select a Logical Device.
210 select_ldn(struct nct_softc *sc, uint8_t ldn)
212 write_cfg_reg_1(sc, NCT_CR_LDN, ldn);
216 * Get the GPIO Input/Output register address
220 nct_ior_addr(uint32_t pin_num)
224 addr = NCT_LD7_GPIO0_IOR;
226 addr = NCT_LD7_GPIO1_IOR;
232 * Get the GPIO Data register address for a pin.
235 nct_dat_addr(uint32_t pin_num)
239 addr = NCT_LD7_GPIO0_DAT;
241 addr = NCT_LD7_GPIO1_DAT;
247 * Get the GPIO Inversion register address
251 nct_inv_addr(uint32_t pin_num)
255 addr = NCT_LD7_GPIO0_INV;
257 addr = NCT_LD7_GPIO1_INV;
263 * Get the GPIO Output Configuration/Mode
264 * register address for a pin.
267 nct_outcfg_addr(uint32_t pin_num)
271 addr = NCT_LDF_GPIO0_OUTCFG;
273 addr = NCT_LDF_GPIO1_OUTCFG;
279 * Set a pin to output mode.
282 nct_set_pin_is_output(struct nct_softc *sc, uint32_t pin_num)
287 reg = nct_ior_addr(pin_num);
288 select_ldn(sc, NCT_LDN_GPIO);
289 ior = read_cfg_reg_1(sc, reg);
290 ior &= ~(NCT_PIN_BIT(pin_num));
291 write_cfg_reg_1(sc, reg, ior);
295 * Set a pin to input mode.
298 nct_set_pin_is_input(struct nct_softc *sc, uint32_t pin_num)
303 reg = nct_ior_addr(pin_num);
304 select_ldn(sc, NCT_LDN_GPIO);
305 ior = read_cfg_reg_1(sc, reg);
306 ior |= NCT_PIN_BIT(pin_num);
307 write_cfg_reg_1(sc, reg, ior);
311 * Check whether a pin is configured as an input.
314 nct_pin_is_input(struct nct_softc *sc, uint32_t pin_num)
319 reg = nct_ior_addr(pin_num);
320 select_ldn(sc, NCT_LDN_GPIO);
321 ior = read_cfg_reg_1(sc, reg);
323 return (ior & NCT_PIN_BIT(pin_num));
327 * Write a value to an output pin.
330 nct_write_pin(struct nct_softc *sc, uint32_t pin_num, uint8_t data)
335 reg = nct_dat_addr(pin_num);
336 select_ldn(sc, NCT_LDN_GPIO);
337 value = read_cfg_reg_1(sc, reg);
339 value |= NCT_PIN_BIT(pin_num);
341 value &= ~(NCT_PIN_BIT(pin_num));
343 write_cfg_reg_1(sc, reg, value);
347 nct_read_pin(struct nct_softc *sc, uint32_t pin_num)
351 reg = nct_dat_addr(pin_num);
352 select_ldn(sc, NCT_LDN_GPIO);
354 return (read_cfg_reg_1(sc, reg) & NCT_PIN_BIT(pin_num));
358 nct_set_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num)
363 reg = nct_inv_addr(pin_num);
364 select_ldn(sc, NCT_LDN_GPIO);
365 inv = read_cfg_reg_1(sc, reg);
366 inv |= (NCT_PIN_BIT(pin_num));
367 write_cfg_reg_1(sc, reg, inv);
371 nct_set_pin_not_inverted(struct nct_softc *sc, uint32_t pin_num)
376 reg = nct_inv_addr(pin_num);
377 select_ldn(sc, NCT_LDN_GPIO);
378 inv = read_cfg_reg_1(sc, reg);
379 inv &= ~(NCT_PIN_BIT(pin_num));
380 write_cfg_reg_1(sc, reg, inv);
384 nct_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num)
389 reg = nct_inv_addr(pin_num);
390 select_ldn(sc, NCT_LDN_GPIO);
391 inv = read_cfg_reg_1(sc, reg);
393 return (inv & NCT_PIN_BIT(pin_num));
397 nct_set_pin_opendrain(struct nct_softc *sc, uint32_t pin_num)
402 reg = nct_outcfg_addr(pin_num);
403 select_ldn(sc, NCT_LDN_GPIO_MODE);
404 outcfg = read_cfg_reg_1(sc, reg);
405 outcfg |= (NCT_PIN_BIT(pin_num));
406 write_cfg_reg_1(sc, reg, outcfg);
410 nct_set_pin_pushpull(struct nct_softc *sc, uint32_t pin_num)
415 reg = nct_outcfg_addr(pin_num);
416 select_ldn(sc, NCT_LDN_GPIO_MODE);
417 outcfg = read_cfg_reg_1(sc, reg);
418 outcfg &= ~(NCT_PIN_BIT(pin_num));
419 write_cfg_reg_1(sc, reg, outcfg);
423 nct_pin_is_opendrain(struct nct_softc *sc, uint32_t pin_num)
428 reg = nct_outcfg_addr(pin_num);
429 select_ldn(sc, NCT_LDN_GPIO_MODE);
430 outcfg = read_cfg_reg_1(sc, reg);
432 return (outcfg & NCT_PIN_BIT(pin_num));
436 nct_identify(driver_t *driver, device_t parent)
438 if (device_find_child(parent, driver->name, 0) != NULL)
441 BUS_ADD_CHILD(parent, 0, driver->name, 0);
445 nct_probe(device_t dev)
449 struct nct_softc *sc;
452 /* Make sure we do not claim some ISA PNP device. */
453 if (isa_get_logicalid(dev) != 0)
456 sc = device_get_softc(dev);
458 for (i = 0; i < nitems(probe_addrs); i++) {
460 sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid,
461 probe_addrs[i], probe_addrs[i] + 1, 2, RF_ACTIVE);
462 if (sc->portres == NULL)
467 GPIO_ASSERT_UNLOCKED(sc);
470 chipid = read_cfg_reg_2(sc, NCT_CR_CHIP_ID);
474 GPIO_LOCK_DESTROY(sc);
476 bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres);
477 bus_delete_resource(dev, SYS_RES_IOPORT, sc->rid);
479 for (j = 0; j < nitems(nct_devs); j++) {
480 if (chipid == nct_devs[j].chip_id) {
481 rc = bus_set_resource(dev, SYS_RES_IOPORT, 0, probe_addrs[i], 2);
483 device_printf(dev, "bus_set_resource failed for address 0x%02X\n", probe_addrs[i]);
486 device_set_desc(dev, nct_devs[j].descr);
487 return (BUS_PROBE_DEFAULT);
495 nct_attach(device_t dev)
497 struct nct_softc *sc;
500 sc = device_get_softc(dev);
503 sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid,
504 0ul, ~0ul, 2, RF_ACTIVE);
505 if (sc->portres == NULL) {
506 device_printf(dev, "cannot allocate ioport\n");
512 GPIO_ASSERT_UNLOCKED(sc);
515 select_ldn(sc, NCT_LDN_GPIO);
516 /* Enable gpio0 and gpio1. */
517 write_cfg_reg_1(sc, NCT_LD7_GPIO_ENABLE,
518 read_cfg_reg_1(sc, NCT_LD7_GPIO_ENABLE) | 0x03);
520 for (i = 0; i <= NCT_MAX_PIN; i++) {
521 struct gpio_pin *pin;
525 pin->gp_caps = NCT_GPIO_CAPS;
528 snprintf(pin->gp_name, GPIOMAXNAME, "GPIO%02u", i);
529 pin->gp_name[GPIOMAXNAME - 1] = '\0';
531 if (nct_pin_is_input(sc, i))
532 pin->gp_flags |= GPIO_PIN_INPUT;
534 pin->gp_flags |= GPIO_PIN_OUTPUT;
536 if (nct_pin_is_opendrain(sc, i))
537 pin->gp_flags |= GPIO_PIN_OPENDRAIN;
539 pin->gp_flags |= GPIO_PIN_PUSHPULL;
541 if (nct_pin_is_inverted(sc, i))
542 pin->gp_flags |= (GPIO_PIN_INVIN | GPIO_PIN_INVOUT);
546 sc->busdev = gpiobus_attach_bus(dev);
547 if (sc->busdev == NULL) {
548 GPIO_ASSERT_UNLOCKED(sc);
552 bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres);
553 GPIO_LOCK_DESTROY(sc);
562 nct_detach(device_t dev)
564 struct nct_softc *sc;
566 sc = device_get_softc(dev);
567 gpiobus_detach_bus(dev);
569 GPIO_ASSERT_UNLOCKED(sc);
574 /* Cleanup resources. */
575 bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres);
577 GPIO_LOCK_DESTROY(sc);
583 nct_gpio_get_bus(device_t dev)
585 struct nct_softc *sc;
587 sc = device_get_softc(dev);
593 nct_gpio_pin_max(device_t dev, int *npins)
595 *npins = NCT_MAX_PIN;
601 nct_gpio_pin_set(device_t dev, uint32_t pin_num, uint32_t pin_value)
603 struct nct_softc *sc;
605 if (!NCT_IS_VALID_PIN(pin_num))
608 sc = device_get_softc(dev);
609 GPIO_ASSERT_UNLOCKED(sc);
611 nct_write_pin(sc, pin_num, pin_value);
618 nct_gpio_pin_get(device_t dev, uint32_t pin_num, uint32_t *pin_value)
620 struct nct_softc *sc;
622 if (!NCT_IS_VALID_PIN(pin_num))
625 sc = device_get_softc(dev);
626 GPIO_ASSERT_UNLOCKED(sc);
628 *pin_value = nct_read_pin(sc, pin_num);
635 nct_gpio_pin_toggle(device_t dev, uint32_t pin_num)
637 struct nct_softc *sc;
639 if (!NCT_IS_VALID_PIN(pin_num))
642 sc = device_get_softc(dev);
643 GPIO_ASSERT_UNLOCKED(sc);
645 if (nct_read_pin(sc, pin_num))
646 nct_write_pin(sc, pin_num, 0);
648 nct_write_pin(sc, pin_num, 1);
656 nct_gpio_pin_getcaps(device_t dev, uint32_t pin_num, uint32_t *caps)
658 struct nct_softc *sc;
660 if (!NCT_IS_VALID_PIN(pin_num))
663 sc = device_get_softc(dev);
664 GPIO_ASSERT_UNLOCKED(sc);
666 *caps = sc->pins[pin_num].gp_caps;
673 nct_gpio_pin_getflags(device_t dev, uint32_t pin_num, uint32_t *flags)
675 struct nct_softc *sc;
677 if (!NCT_IS_VALID_PIN(pin_num))
680 sc = device_get_softc(dev);
681 GPIO_ASSERT_UNLOCKED(sc);
683 *flags = sc->pins[pin_num].gp_flags;
690 nct_gpio_pin_getname(device_t dev, uint32_t pin_num, char *name)
692 struct nct_softc *sc;
694 if (!NCT_IS_VALID_PIN(pin_num))
697 sc = device_get_softc(dev);
698 GPIO_ASSERT_UNLOCKED(sc);
700 memcpy(name, sc->pins[pin_num].gp_name, GPIOMAXNAME);
707 nct_gpio_pin_setflags(device_t dev, uint32_t pin_num, uint32_t flags)
709 struct nct_softc *sc;
710 struct gpio_pin *pin;
712 if (!NCT_IS_VALID_PIN(pin_num))
715 sc = device_get_softc(dev);
716 pin = &sc->pins[pin_num];
717 if ((flags & pin->gp_caps) != flags)
720 GPIO_ASSERT_UNLOCKED(sc);
722 if (flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) {
723 if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) ==
724 (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) {
729 if (flags & GPIO_PIN_INPUT)
730 nct_set_pin_is_input(sc, pin_num);
732 nct_set_pin_is_output(sc, pin_num);
735 if (flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) {
736 if (flags & GPIO_PIN_INPUT) {
741 if ((flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) ==
742 (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) {
747 if (flags & GPIO_PIN_OPENDRAIN)
748 nct_set_pin_opendrain(sc, pin_num);
750 nct_set_pin_pushpull(sc, pin_num);
753 if (flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) {
754 if ((flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) !=
755 (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) {
760 if (flags & GPIO_PIN_INVIN)
761 nct_set_pin_is_inverted(sc, pin_num);
763 nct_set_pin_not_inverted(sc, pin_num);
766 pin->gp_flags = flags;
772 static device_method_t nct_methods[] = {
773 /* Device interface */
774 DEVMETHOD(device_identify, nct_identify),
775 DEVMETHOD(device_probe, nct_probe),
776 DEVMETHOD(device_attach, nct_attach),
777 DEVMETHOD(device_detach, nct_detach),
780 DEVMETHOD(gpio_get_bus, nct_gpio_get_bus),
781 DEVMETHOD(gpio_pin_max, nct_gpio_pin_max),
782 DEVMETHOD(gpio_pin_get, nct_gpio_pin_get),
783 DEVMETHOD(gpio_pin_set, nct_gpio_pin_set),
784 DEVMETHOD(gpio_pin_toggle, nct_gpio_pin_toggle),
785 DEVMETHOD(gpio_pin_getname, nct_gpio_pin_getname),
786 DEVMETHOD(gpio_pin_getcaps, nct_gpio_pin_getcaps),
787 DEVMETHOD(gpio_pin_getflags, nct_gpio_pin_getflags),
788 DEVMETHOD(gpio_pin_setflags, nct_gpio_pin_setflags),
793 static driver_t nct_isa_driver = {
796 sizeof(struct nct_softc)
799 static devclass_t nct_devclass;
801 DRIVER_MODULE(nctgpio, isa, nct_isa_driver, nct_devclass, NULL, NULL);
802 MODULE_DEPEND(nctgpio, gpiobus, 1, 1, 1);