Index: head/sys/dev/nctgpio/nctgpio.c =================================================================== --- head/sys/dev/nctgpio/nctgpio.c (nonexistent) +++ head/sys/dev/nctgpio/nctgpio.c (revision 297443) @@ -0,0 +1,802 @@ +/*- + * Copyright (c) 2016 Daniel Wyatt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + * + */ + +/* + * Nuvoton GPIO driver. + * + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include + +#include "gpio_if.h" + +/* + * Global configuration registers (CR). + */ +#define NCT_CR_LDN 0x07 /* Logical Device Number */ +#define NCT_CR_CHIP_ID 0x20 /* Chip ID */ +#define NCT_CR_CHIP_ID_H 0x20 /* Chip ID (high byte) */ +#define NCT_CR_CHIP_ID_L 0x21 /* Chip ID (low byte) */ +#define NCT_CR_OPT_1 0x26 /* Global Options (1) */ + +/* Logical Device Numbers. */ +#define NCT_LDN_GPIO 0x07 +#define NCT_LDN_GPIO_CFG 0x08 +#define NCT_LDN_GPIO_MODE 0x0f + +/* Logical Device 7 */ +#define NCT_LD7_GPIO_ENABLE 0x30 +#define NCT_LD7_GPIO0_IOR 0xe0 +#define NCT_LD7_GPIO0_DAT 0xe1 +#define NCT_LD7_GPIO0_INV 0xe2 +#define NCT_LD7_GPIO0_DST 0xe3 +#define NCT_LD7_GPIO1_IOR 0xe4 +#define NCT_LD7_GPIO1_DAT 0xe5 +#define NCT_LD7_GPIO1_INV 0xe6 +#define NCT_LD7_GPIO1_DST 0xe7 + +/* Logical Device F */ +#define NCT_LDF_GPIO0_OUTCFG 0xe0 +#define NCT_LDF_GPIO1_OUTCFG 0xe1 + +#define NCT_EXTFUNC_ENTER 0x87 +#define NCT_EXTFUNC_EXIT 0xaa + +#define NCT_MAX_PIN 15 +#define NCT_IS_VALID_PIN(_p) ((_p) >= 0 && (_p) <= NCT_MAX_PIN) + +#define NCT_PIN_BIT(_p) (1 << ((_p) % 8)) + +#define NCT_GPIO_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \ + GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL | \ + GPIO_PIN_INVIN | GPIO_PIN_INVOUT) + +struct nct_softc { + device_t dev; + device_t busdev; + struct mtx mtx; + struct resource *portres; + int rid; + struct gpio_pin pins[NCT_MAX_PIN]; +}; + +#define GPIO_LOCK_INIT(_sc) mtx_init(&(_sc)->mtx, \ + device_get_nameunit(dev), NULL, MTX_DEF) +#define GPIO_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->mtx) +#define GPIO_LOCK(_sc) mtx_lock(&(_sc)->mtx) +#define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx) +#define GPIO_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_OWNED) +#define GPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&(_sc)->mtx, MA_NOTOWNED) + +#define NCT_BARRIER_WRITE(_sc) \ + bus_barrier((_sc)->portres, 0, 2, BUS_SPACE_BARRIER_WRITE) + +#define NCT_BARRIER_READ_WRITE(_sc) \ + bus_barrier((_sc)->portres, 0, 2, \ + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE) + +static void ext_cfg_enter(struct nct_softc *); +static void ext_cfg_exit(struct nct_softc *); + +/* + * Potential Extended Function Enable Register addresses. + * Same address as EFIR. + */ +uint8_t probe_addrs[] = {0x2e, 0x4e}; + +struct nuvoton_vendor_device_id { + uint16_t chip_id; + const char * descr; +} nct_devs[] = { + { + .chip_id = 0x1061, + .descr = "Nuvoton NCT5104D", + }, + { + .chip_id = 0xc452, + .descr = "Nuvoton NCT5104D (PC-Engines APU)", + }, +}; + +static void +write_cfg_reg_1(struct nct_softc *sc, uint8_t reg, uint8_t value) +{ + GPIO_ASSERT_LOCKED(sc); + bus_write_1(sc->portres, 0, reg); + NCT_BARRIER_WRITE(sc); + bus_write_1(sc->portres, 1, value); + NCT_BARRIER_WRITE(sc); +} + +static uint8_t +read_cfg_reg_1(struct nct_softc *sc, uint8_t reg) +{ + uint8_t value; + + GPIO_ASSERT_LOCKED(sc); + bus_write_1(sc->portres, 0, reg); + NCT_BARRIER_READ_WRITE(sc); + value = bus_read_1(sc->portres, 1); + NCT_BARRIER_READ_WRITE(sc); + + return (value); +} + +static uint16_t +read_cfg_reg_2(struct nct_softc *sc, uint8_t reg) +{ + uint16_t value; + + value = read_cfg_reg_1(sc, reg) << 8; + value |= read_cfg_reg_1(sc, reg + 1); + + return (value); +} + +/* + * Enable extended function mode. + * + */ +static void +ext_cfg_enter(struct nct_softc *sc) +{ + GPIO_ASSERT_LOCKED(sc); + bus_write_1(sc->portres, 0, NCT_EXTFUNC_ENTER); + NCT_BARRIER_WRITE(sc); + bus_write_1(sc->portres, 0, NCT_EXTFUNC_ENTER); + NCT_BARRIER_WRITE(sc); +} + +/* + * Disable extended function mode. + * + */ +static void +ext_cfg_exit(struct nct_softc *sc) +{ + GPIO_ASSERT_LOCKED(sc); + bus_write_1(sc->portres, 0, NCT_EXTFUNC_EXIT); + NCT_BARRIER_WRITE(sc); +} + +/* + * Select a Logical Device. + */ +static void +select_ldn(struct nct_softc *sc, uint8_t ldn) +{ + write_cfg_reg_1(sc, NCT_CR_LDN, ldn); +} + +/* + * Get the GPIO Input/Output register address + * for a pin. + */ +static uint8_t +nct_ior_addr(uint32_t pin_num) +{ + uint8_t addr; + + addr = NCT_LD7_GPIO0_IOR; + if (pin_num > 7) + addr = NCT_LD7_GPIO1_IOR; + + return (addr); +} + +/* + * Get the GPIO Data register address for a pin. + */ +static uint8_t +nct_dat_addr(uint32_t pin_num) +{ + uint8_t addr; + + addr = NCT_LD7_GPIO0_DAT; + if (pin_num > 7) + addr = NCT_LD7_GPIO1_DAT; + + return (addr); +} + +/* + * Get the GPIO Inversion register address + * for a pin. + */ +static uint8_t +nct_inv_addr(uint32_t pin_num) +{ + uint8_t addr; + + addr = NCT_LD7_GPIO0_INV; + if (pin_num > 7) + addr = NCT_LD7_GPIO1_INV; + + return (addr); +} + +/* + * Get the GPIO Output Configuration/Mode + * register address for a pin. + */ +static uint8_t +nct_outcfg_addr(uint32_t pin_num) +{ + uint8_t addr; + + addr = NCT_LDF_GPIO0_OUTCFG; + if (pin_num > 7) + addr = NCT_LDF_GPIO1_OUTCFG; + + return (addr); +} + +/* + * Set a pin to output mode. + */ +static void +nct_set_pin_is_output(struct nct_softc *sc, uint32_t pin_num) +{ + uint8_t reg; + uint8_t ior; + + reg = nct_ior_addr(pin_num); + select_ldn(sc, NCT_LDN_GPIO); + ior = read_cfg_reg_1(sc, reg); + ior &= ~(NCT_PIN_BIT(pin_num)); + write_cfg_reg_1(sc, reg, ior); +} + +/* + * Set a pin to input mode. + */ +static void +nct_set_pin_is_input(struct nct_softc *sc, uint32_t pin_num) +{ + uint8_t reg; + uint8_t ior; + + reg = nct_ior_addr(pin_num); + select_ldn(sc, NCT_LDN_GPIO); + ior = read_cfg_reg_1(sc, reg); + ior |= NCT_PIN_BIT(pin_num); + write_cfg_reg_1(sc, reg, ior); +} + +/* + * Check whether a pin is configured as an input. + */ +static bool +nct_pin_is_input(struct nct_softc *sc, uint32_t pin_num) +{ + uint8_t reg; + uint8_t ior; + + reg = nct_ior_addr(pin_num); + select_ldn(sc, NCT_LDN_GPIO); + ior = read_cfg_reg_1(sc, reg); + + return (ior & NCT_PIN_BIT(pin_num)); +} + +/* + * Write a value to an output pin. + */ +static void +nct_write_pin(struct nct_softc *sc, uint32_t pin_num, uint8_t data) +{ + uint8_t reg; + uint8_t value; + + reg = nct_dat_addr(pin_num); + select_ldn(sc, NCT_LDN_GPIO); + value = read_cfg_reg_1(sc, reg); + if (data) + value |= NCT_PIN_BIT(pin_num); + else + value &= ~(NCT_PIN_BIT(pin_num)); + + write_cfg_reg_1(sc, reg, value); +} + +static bool +nct_read_pin(struct nct_softc *sc, uint32_t pin_num) +{ + uint8_t reg; + + reg = nct_dat_addr(pin_num); + select_ldn(sc, NCT_LDN_GPIO); + + return (read_cfg_reg_1(sc, reg) & NCT_PIN_BIT(pin_num)); +} + +static void +nct_set_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num) +{ + uint8_t reg; + uint8_t inv; + + reg = nct_inv_addr(pin_num); + select_ldn(sc, NCT_LDN_GPIO); + inv = read_cfg_reg_1(sc, reg); + inv |= (NCT_PIN_BIT(pin_num)); + write_cfg_reg_1(sc, reg, inv); +} + +static void +nct_set_pin_not_inverted(struct nct_softc *sc, uint32_t pin_num) +{ + uint8_t reg; + uint8_t inv; + + reg = nct_inv_addr(pin_num); + select_ldn(sc, NCT_LDN_GPIO); + inv = read_cfg_reg_1(sc, reg); + inv &= ~(NCT_PIN_BIT(pin_num)); + write_cfg_reg_1(sc, reg, inv); +} + +static bool +nct_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num) +{ + uint8_t reg; + uint8_t inv; + + reg = nct_inv_addr(pin_num); + select_ldn(sc, NCT_LDN_GPIO); + inv = read_cfg_reg_1(sc, reg); + + return (inv & NCT_PIN_BIT(pin_num)); +} + +static void +nct_set_pin_opendrain(struct nct_softc *sc, uint32_t pin_num) +{ + uint8_t reg; + uint8_t outcfg; + + reg = nct_outcfg_addr(pin_num); + select_ldn(sc, NCT_LDN_GPIO_MODE); + outcfg = read_cfg_reg_1(sc, reg); + outcfg |= (NCT_PIN_BIT(pin_num)); + write_cfg_reg_1(sc, reg, outcfg); +} + +static void +nct_set_pin_pushpull(struct nct_softc *sc, uint32_t pin_num) +{ + uint8_t reg; + uint8_t outcfg; + + reg = nct_outcfg_addr(pin_num); + select_ldn(sc, NCT_LDN_GPIO_MODE); + outcfg = read_cfg_reg_1(sc, reg); + outcfg &= ~(NCT_PIN_BIT(pin_num)); + write_cfg_reg_1(sc, reg, outcfg); +} + +static bool +nct_pin_is_opendrain(struct nct_softc *sc, uint32_t pin_num) +{ + uint8_t reg; + uint8_t outcfg; + + reg = nct_outcfg_addr(pin_num); + select_ldn(sc, NCT_LDN_GPIO_MODE); + outcfg = read_cfg_reg_1(sc, reg); + + return (outcfg & NCT_PIN_BIT(pin_num)); +} + +static void +nct_identify(driver_t *driver, device_t parent) +{ + if (device_find_child(parent, driver->name, 0) != NULL) + return; + + BUS_ADD_CHILD(parent, 0, driver->name, 0); +} + +static int +nct_probe(device_t dev) +{ + int i, j; + int rc; + struct nct_softc *sc; + uint16_t chipid; + + /* Make sure we do not claim some ISA PNP device. */ + if (isa_get_logicalid(dev) != 0) + return (ENXIO); + + sc = device_get_softc(dev); + + for (i = 0; i < sizeof(probe_addrs) / sizeof(*probe_addrs); i++) { + sc->rid = 0; + sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid, + probe_addrs[i], probe_addrs[i] + 1, 2, RF_ACTIVE); + if (sc->portres == NULL) + continue; + + GPIO_LOCK_INIT(sc); + + GPIO_ASSERT_UNLOCKED(sc); + GPIO_LOCK(sc); + ext_cfg_enter(sc); + chipid = read_cfg_reg_2(sc, NCT_CR_CHIP_ID); + ext_cfg_exit(sc); + GPIO_UNLOCK(sc); + + GPIO_LOCK_DESTROY(sc); + + bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres); + bus_delete_resource(dev, SYS_RES_IOPORT, sc->rid); + + for (j = 0; j < sizeof(nct_devs) / sizeof(*nct_devs); j++) { + if (chipid == nct_devs[j].chip_id) { + rc = bus_set_resource(dev, SYS_RES_IOPORT, 0, probe_addrs[i], 2); + if (rc != 0) { + device_printf(dev, "bus_set_resource failed for address 0x%02X\n", probe_addrs[i]); + continue; + } + device_set_desc(dev, nct_devs[j].descr); + return (BUS_PROBE_DEFAULT); + } + } + } + return (ENXIO); +} + +static int +nct_attach(device_t dev) +{ + struct nct_softc *sc; + int i; + + sc = device_get_softc(dev); + + sc->rid = 0; + sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid, + 0ul, ~0ul, 2, RF_ACTIVE); + if (sc->portres == NULL) { + device_printf(dev, "cannot allocate ioport\n"); + return (ENXIO); + } + + GPIO_LOCK_INIT(sc); + + GPIO_ASSERT_UNLOCKED(sc); + GPIO_LOCK(sc); + ext_cfg_enter(sc); + select_ldn(sc, NCT_LDN_GPIO); + /* Enable gpio0 and gpio1. */ + write_cfg_reg_1(sc, NCT_LD7_GPIO_ENABLE, + read_cfg_reg_1(sc, NCT_LD7_GPIO_ENABLE) | 0x03); + + for (i = 0; i <= NCT_MAX_PIN; i++) { + struct gpio_pin *pin; + + pin = &sc->pins[i]; + pin->gp_pin = i; + pin->gp_caps = NCT_GPIO_CAPS; + pin->gp_flags = 0; + + snprintf(pin->gp_name, GPIOMAXNAME, "GPIO%02u", i); + pin->gp_name[GPIOMAXNAME - 1] = '\0'; + + if (nct_pin_is_input(sc, i)) + pin->gp_flags |= GPIO_PIN_INPUT; + else + pin->gp_flags |= GPIO_PIN_OUTPUT; + + if (nct_pin_is_opendrain(sc, i)) + pin->gp_flags |= GPIO_PIN_OPENDRAIN; + else + pin->gp_flags |= GPIO_PIN_PUSHPULL; + + if (nct_pin_is_inverted(sc, i)) + pin->gp_flags |= (GPIO_PIN_INVIN | GPIO_PIN_INVOUT); + } + GPIO_UNLOCK(sc); + + sc->busdev = gpiobus_attach_bus(dev); + if (sc->busdev == NULL) { + GPIO_ASSERT_UNLOCKED(sc); + GPIO_LOCK(sc); + ext_cfg_exit(sc); + GPIO_UNLOCK(sc); + bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres); + GPIO_LOCK_DESTROY(sc); + + return (ENXIO); + } + + return (0); +} + +static int +nct_detach(device_t dev) +{ + struct nct_softc *sc; + + sc = device_get_softc(dev); + gpiobus_detach_bus(dev); + + GPIO_ASSERT_UNLOCKED(sc); + GPIO_LOCK(sc); + ext_cfg_exit(sc); + GPIO_UNLOCK(sc); + + /* Cleanup resources. */ + bus_release_resource(dev, SYS_RES_IOPORT, sc->rid, sc->portres); + + GPIO_LOCK_DESTROY(sc); + + return (0); +} + +static device_t +nct_gpio_get_bus(device_t dev) +{ + struct nct_softc *sc; + + sc = device_get_softc(dev); + + return (sc->busdev); +} + +static int +nct_gpio_pin_max(device_t dev, int *npins) +{ + *npins = NCT_MAX_PIN; + + return (0); +} + +static int +nct_gpio_pin_set(device_t dev, uint32_t pin_num, uint32_t pin_value) +{ + struct nct_softc *sc; + + if (!NCT_IS_VALID_PIN(pin_num)) + return (EINVAL); + + sc = device_get_softc(dev); + GPIO_ASSERT_UNLOCKED(sc); + GPIO_LOCK(sc); + nct_write_pin(sc, pin_num, pin_value); + GPIO_UNLOCK(sc); + + return (0); +} + +static int +nct_gpio_pin_get(device_t dev, uint32_t pin_num, uint32_t *pin_value) +{ + struct nct_softc *sc; + + if (!NCT_IS_VALID_PIN(pin_num)) + return (EINVAL); + + sc = device_get_softc(dev); + GPIO_ASSERT_UNLOCKED(sc); + GPIO_LOCK(sc); + *pin_value = nct_read_pin(sc, pin_num); + GPIO_UNLOCK(sc); + + return (0); +} + +static int +nct_gpio_pin_toggle(device_t dev, uint32_t pin_num) +{ + struct nct_softc *sc; + + if (!NCT_IS_VALID_PIN(pin_num)) + return (EINVAL); + + sc = device_get_softc(dev); + GPIO_ASSERT_UNLOCKED(sc); + GPIO_LOCK(sc); + if (nct_read_pin(sc, pin_num)) + nct_write_pin(sc, pin_num, 0); + else + nct_write_pin(sc, pin_num, 1); + + GPIO_UNLOCK(sc); + + return (0); +} + +static int +nct_gpio_pin_getcaps(device_t dev, uint32_t pin_num, uint32_t *caps) +{ + struct nct_softc *sc; + + if (!NCT_IS_VALID_PIN(pin_num)) + return (EINVAL); + + sc = device_get_softc(dev); + GPIO_ASSERT_UNLOCKED(sc); + GPIO_LOCK(sc); + *caps = sc->pins[pin_num].gp_caps; + GPIO_UNLOCK(sc); + + return (0); +} + +static int +nct_gpio_pin_getflags(device_t dev, uint32_t pin_num, uint32_t *flags) +{ + struct nct_softc *sc; + + if (!NCT_IS_VALID_PIN(pin_num)) + return (EINVAL); + + sc = device_get_softc(dev); + GPIO_ASSERT_UNLOCKED(sc); + GPIO_LOCK(sc); + *flags = sc->pins[pin_num].gp_flags; + GPIO_UNLOCK(sc); + + return (0); +} + +static int +nct_gpio_pin_getname(device_t dev, uint32_t pin_num, char *name) +{ + struct nct_softc *sc; + + if (!NCT_IS_VALID_PIN(pin_num)) + return (EINVAL); + + sc = device_get_softc(dev); + GPIO_ASSERT_UNLOCKED(sc); + GPIO_LOCK(sc); + memcpy(name, sc->pins[pin_num].gp_name, GPIOMAXNAME); + GPIO_UNLOCK(sc); + + return (0); +} + +static int +nct_gpio_pin_setflags(device_t dev, uint32_t pin_num, uint32_t flags) +{ + struct nct_softc *sc; + struct gpio_pin *pin; + + if (!NCT_IS_VALID_PIN(pin_num)) + return (EINVAL); + + sc = device_get_softc(dev); + pin = &sc->pins[pin_num]; + if ((flags & pin->gp_caps) != flags) + return (EINVAL); + + GPIO_ASSERT_UNLOCKED(sc); + GPIO_LOCK(sc); + if (flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) { + if ((flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) == + (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) { + GPIO_UNLOCK(sc); + return (EINVAL); + } + + if (flags & GPIO_PIN_INPUT) + nct_set_pin_is_input(sc, pin_num); + else + nct_set_pin_is_output(sc, pin_num); + } + + if (flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) { + if (flags & GPIO_PIN_INPUT) { + GPIO_UNLOCK(sc); + return (EINVAL); + } + + if ((flags & (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) == + (GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)) { + GPIO_UNLOCK(sc); + return (EINVAL); + } + + if (flags & GPIO_PIN_OPENDRAIN) + nct_set_pin_opendrain(sc, pin_num); + else + nct_set_pin_pushpull(sc, pin_num); + } + + if (flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) { + if ((flags & (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) != + (GPIO_PIN_INVIN | GPIO_PIN_INVOUT)) { + GPIO_UNLOCK(sc); + return (EINVAL); + } + + if (flags & GPIO_PIN_INVIN) + nct_set_pin_is_inverted(sc, pin_num); + else + nct_set_pin_not_inverted(sc, pin_num); + } + + pin->gp_flags = flags; + GPIO_UNLOCK(sc); + + return (0); +} + +static device_method_t nct_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, nct_identify), + DEVMETHOD(device_probe, nct_probe), + DEVMETHOD(device_attach, nct_attach), + DEVMETHOD(device_detach, nct_detach), + + /* GPIO */ + DEVMETHOD(gpio_get_bus, nct_gpio_get_bus), + DEVMETHOD(gpio_pin_max, nct_gpio_pin_max), + DEVMETHOD(gpio_pin_get, nct_gpio_pin_get), + DEVMETHOD(gpio_pin_set, nct_gpio_pin_set), + DEVMETHOD(gpio_pin_toggle, nct_gpio_pin_toggle), + DEVMETHOD(gpio_pin_getname, nct_gpio_pin_getname), + DEVMETHOD(gpio_pin_getcaps, nct_gpio_pin_getcaps), + DEVMETHOD(gpio_pin_getflags, nct_gpio_pin_getflags), + DEVMETHOD(gpio_pin_setflags, nct_gpio_pin_setflags), + + DEVMETHOD_END +}; + +static driver_t nct_isa_driver = { + "gpio", + nct_methods, + sizeof(struct nct_softc) +}; + +static devclass_t nct_devclass; + +DRIVER_MODULE(nctgpio, isa, nct_isa_driver, nct_devclass, NULL, NULL); +MODULE_DEPEND(nctgpio, gpiobus, 1, 1, 1); Property changes on: head/sys/dev/nctgpio/nctgpio.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/sys/modules/Makefile =================================================================== --- head/sys/modules/Makefile (revision 297442) +++ head/sys/modules/Makefile (revision 297443) @@ -1,783 +1,785 @@ # $FreeBSD$ SYSDIR?=${.CURDIR}/.. .include "${SYSDIR}/conf/kern.opts.mk" SUBDIR_PARALLEL= # Modules that include binary-only blobs of microcode should be selectable by # MK_SOURCELESS_UCODE option (see below). .if defined(MODULES_OVERRIDE) && !defined(ALL_MODULES) SUBDIR=${MODULES_OVERRIDE} .else SUBDIR= \ ${_3dfx} \ ${_3dfx_linux} \ ${_aac} \ ${_aacraid} \ accf_data \ accf_dns \ accf_http \ acl_nfs4 \ acl_posix1e \ ${_acpi} \ ae \ ${_aesni} \ age \ ${_agp} \ aha \ ${_ahb} \ ahci \ ${_aic} \ aic7xxx \ alc \ ale \ alq \ ${_amdsbwd} \ ${_amdtemp} \ amr \ ${_an} \ ${_aout} \ ${_apm} \ ${_arcmsr} \ ${_arcnet} \ ${_asmc} \ ata \ ath \ ath_pci \ ${_autofs} \ ${_auxio} \ ${_bce} \ bfe \ bge \ ${_bxe} \ ${_bios} \ ${_bktr} \ ${_bm} \ bridgestp \ bwi \ bwn \ cam \ ${_canbepm} \ ${_canbus} \ ${_cardbus} \ ${_carp} \ cas \ ${_cbb} \ cc \ cd9660 \ cd9660_iconv \ ${_ce} \ ${_cfi} \ ${_ciss} \ cloudabi \ ${_cloudabi64} \ ${_cm} \ ${_cmx} \ ${_coff} \ ${_coretemp} \ ${_cp} \ ${_cpsw} \ ${_cpuctl} \ ${_cpufreq} \ ${_crypto} \ ${_cryptodev} \ ${_cs} \ ${_ct} \ ${_ctau} \ ctl \ ${_cxgb} \ ${_cxgbe} \ dc \ dcons \ dcons_crom \ de \ ${_dpms} \ ${_dpt} \ ${_drm} \ ${_drm2} \ dummynet \ ${_ed} \ ${_elink} \ ${_em} \ en \ ${_ep} \ ${_epic} \ esp \ ${_et} \ ${_ex} \ ${_exca} \ ext2fs \ ${_fatm} \ fdc \ fdescfs \ ${_fe} \ ${_filemon} \ firewire \ firmware \ fuse \ ${_fxp} \ gem \ geom \ ${_glxiic} \ ${_glxsb} \ hatm \ hifn \ hme \ ${_hpt27xx} \ ${_hptiop} \ ${_hptmv} \ ${_hptnr} \ ${_hptrr} \ hwpmc \ ${_hyperv} \ i2c \ ${_ibcore} \ ${_ibcs2} \ ${_ichwd} \ ${_ida} \ ${_ie} \ if_bridge \ if_disc \ if_edsc \ ${_if_enc} \ if_epair \ ${_if_gif} \ ${_if_gre} \ ${_if_me} \ if_lagg \ ${_if_ndis} \ ${_if_stf} \ if_tap \ if_tun \ if_vlan \ if_vxlan \ ${_igb} \ ${_iir} \ imgact_binmisc \ ${_io} \ ${_ioat} \ ${_ipoib} \ ${_ipdivert} \ ${_ipfilter} \ ${_ipfw} \ ipfw_nat \ ${_ipmi} \ ip6_mroute_mod \ ip_mroute_mod \ ${_ips} \ ${_ipw} \ ${_ipwfw} \ ${_isci} \ isp \ ${_ispfw} \ ${_iwi} \ ${_iwifw} \ ${_iwm} \ ${_iwmfw} \ ${_iwn} \ ${_iwnfw} \ ${_ix} \ ${_ixv} \ ${_ixgb} \ ${_ixl} \ ${_ixlv} \ jme \ joy \ kbdmux \ kgssapi \ kgssapi_krb5 \ khelp \ krpc \ ksyms \ le \ lge \ libalias \ libiconv \ libmbpool \ libmchain \ ${_linprocfs} \ ${_linsysfs} \ ${_linux} \ ${_linux_common} \ ${_linux64} \ linuxkpi \ lmc \ lpt \ mac_biba \ mac_bsdextended \ mac_ifoff \ mac_lomac \ mac_mls \ mac_none \ mac_partition \ mac_portacl \ mac_seeotheruids \ mac_stub \ mac_test \ malo \ mcd \ md \ mdio \ mem \ mfi \ mii \ mlx \ ${_mlx4} \ ${_mlx4ib} \ ${_mlxen} \ ${_mlx5} \ ${_mlx5en} \ ${_mly} \ mmc \ mmcsd \ mpr \ mps \ mpt \ mqueue \ mrsas \ msdosfs \ msdosfs_iconv \ ${_mse} \ msk \ ${_mthca} \ mvs \ mwl \ ${_mwlfw} \ mxge \ my \ ${_nandfs} \ ${_nandsim} \ ${_ncr} \ + ${_nctgpio} \ ${_ncv} \ ${_ndis} \ netfpga10g \ ${_netgraph} \ ${_nfe} \ nfscl \ nfscommon \ nfsd \ nfslock \ nfslockd \ nfssvc \ nge \ nmdm \ ${_nsp} \ nullfs \ ${_ntb} \ ${_nvd} \ ${_nvme} \ ${_nvram} \ ${_nxge} \ oce \ otus \ otusfw \ ow \ ${_padlock} \ ${_padlock_rng} \ patm \ ${_pccard} \ ${_pcfclock} \ pcn \ ${_pf} \ ${_pflog} \ ${_pfsync} \ plip \ ${_pmc} \ ${_pms} \ ppbus \ ppc \ ppi \ pps \ procfs \ proto \ pseudofs \ ${_pst} \ pty \ puc \ ${_qlxge} \ ${_qlxgb} \ ${_qlxgbe} \ ral \ ${_ralfw} \ ${_random_fortuna} \ ${_random_yarrow} \ ${_random_other} \ rc4 \ ${_rdma} \ ${_rdrand_rng} \ re \ reiserfs \ rl \ rtwn \ ${_rtwnfw} \ ${_s3} \ ${_safe} \ ${_sbni} \ scc \ scd \ ${_scsi_low} \ sdhci \ sdhci_pci \ sem \ send \ ${_sf} \ ${_sfxge} \ sge \ ${_si} \ siba_bwn \ siftr \ siis \ sis \ sk \ smbfs \ sn \ ${_snc} \ snp \ sound \ ${_speaker} \ ${_splash} \ ${_sppp} \ ste \ ${_stg} \ stge \ ${_streams} \ ${_svr4} \ ${_sym} \ ${_syscons} \ sysvipc \ ${_ti} \ tcp/fastpath \ tests/framework \ tests/callout_test \ tl \ tmpfs \ ${_toecore} \ ${_tpm} \ trm \ ${_twa} \ twe \ tws \ tx \ ${_txp} \ uart \ ubsec \ udf \ udf_iconv \ ufs \ unionfs \ urtwn \ ${_urtwnfw} \ usb \ utopia \ ${_vesa} \ ${_virtio} \ vge \ ${_viawd} \ videomode \ vkbd \ ${_vmm} \ ${_vmware} \ ${_vpo} \ vr \ vte \ vx \ ${_vxge} \ wb \ ${_wbwd} \ ${_wds} \ ${_wi} \ ${_wl} \ wlan \ wlan_acl \ wlan_amrr \ wlan_ccmp \ wlan_rssadapt \ wlan_tkip \ wlan_wep \ wlan_xauth \ ${_wpi} \ ${_wpifw} \ ${_x86bios} \ ${_xe} \ xl \ zlib .if ${MK_AUTOFS} != "no" || defined(ALL_MODULES) _autofs= autofs .endif .if ${MK_CDDL} != "no" || defined(ALL_MODULES) .if (${MACHINE_CPUARCH} != "arm" || ${MACHINE_ARCH:Marmv6*} != "") && \ ${MACHINE_CPUARCH} != "mips" && \ ${MACHINE_CPUARCH} != "sparc64" SUBDIR+= dtrace .endif SUBDIR+= opensolaris .endif .if ${MK_CRYPT} != "no" || defined(ALL_MODULES) .if exists(${.CURDIR}/../opencrypto) _crypto= crypto _cryptodev= cryptodev _random_fortuna=random_fortuna _random_yarrow= random_yarrow _random_other= random_other .endif .endif .if ${MK_CUSE} != "no" || defined(ALL_MODULES) SUBDIR+= cuse .endif .if (${MK_INET_SUPPORT} != "no" || ${MK_INET6_SUPPORT} != "no") || \ defined(ALL_MODULES) _carp= carp _toecore= toecore _if_enc= if_enc _if_gif= if_gif _if_gre= if_gre .endif .if (${MK_INET_SUPPORT} != "no" && ${MK_INET6_SUPPORT} != "no") || \ defined(ALL_MODULES) _if_stf= if_stf .endif .if ${MK_INET_SUPPORT} != "no" || defined(ALL_MODULES) _if_me= if_me _ipdivert= ipdivert _ipfw= ipfw .endif .if ${MK_IPFILTER} != "no" || defined(ALL_MODULES) _ipfilter= ipfilter .endif .if ${MK_ISCSI} != "no" || defined(ALL_MODULES) SUBDIR+= iscsi SUBDIR+= iscsi_initiator .endif .if ${MK_NAND} != "no" || defined(ALL_MODULES) _nandfs= nandfs _nandsim= nandsim .endif .if ${MK_NETGRAPH} != "no" || defined(ALL_MODULES) _netgraph= netgraph .endif .if (${MK_PF} != "no" && (${MK_INET_SUPPORT} != "no" || \ ${MK_INET6_SUPPORT} != "no")) || defined(ALL_MODULES) _pf= pf _pflog= pflog .if ${MK_INET_SUPPORT} != "no" _pfsync= pfsync .endif .endif .if ${MK_SOURCELESS_UCODE} != "no" _bce= bce _fatm= fatm _fxp= fxp _ispfw= ispfw _mwlfw= mwlfw _ralfw= ralfw _rtwnfw= rtwnfw _urtwnfw= urtwnfw _sf= sf _ti= ti _txp= txp .endif .if ${MK_SOURCELESS_UCODE} != "no" && ${MACHINE_CPUARCH} != "arm" && \ ${MACHINE_ARCH:C/mips(el)?/mips/} != "mips" && \ ${MACHINE_ARCH} != "powerpc" _cxgbe= cxgbe .endif .if ${MK_ZFS} != "no" || defined(ALL_MODULES) SUBDIR+= zfs .endif .if ${MACHINE_CPUARCH} != "aarch64" && ${MACHINE_CPUARCH} != "arm" && \ ${MACHINE_CPUARCH} != "mips" && ${MACHINE_CPUARCH} != "powerpc" _syscons= syscons _vpo= vpo .endif .if ${MACHINE_CPUARCH} != "mips" # no BUS_SPACE_UNSPECIFIED # No barrier instruction support (specific to this driver) _sym= sym # intr_disable() is a macro, causes problems .if ${MK_SOURCELESS_UCODE} != "no" _cxgb= cxgb .endif .endif .if ${MACHINE_CPUARCH} == "aarch64" _em= em _igb= igb .endif .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" _agp= agp _an= an _aout= aout _bktr= bktr _bxe= bxe _cardbus= cardbus _cbb= cbb _cpuctl= cpuctl _cpufreq= cpufreq _cs= cs _dpms= dpms _drm= drm _drm2= drm2 _ed= ed _em= em _ep= ep _et= et _exca= exca _fe= fe _filemon= filemon .if ${MK_OFED} != "no" || defined(ALL_MODULES) _ibcore= ibcore .endif _if_ndis= if_ndis _igb= igb _io= io .if ${MK_OFED} != "no" || defined(ALL_MODULES) _ipoib= ipoib .endif _ix= ix _ixv= ixv _linprocfs= linprocfs _linsysfs= linsysfs _linux= linux +_nctgpio= nctgpio _ndis= ndis _pccard= pccard .if ${MK_OFED} != "no" || defined(ALL_MODULES) _rdma= rdma .endif _safe= safe _scsi_low= scsi_low _si= si _speaker= speaker _splash= splash _sppp= sppp _vmware= vmware _vxge= vxge _wbwd= wbwd _wi= wi _xe= xe .if ${MACHINE} != "pc98" _aac= aac _aacraid= aacraid _acpi= acpi .if ${MK_CRYPT} != "no" || defined(ALL_MODULES) _aesni= aesni .endif _amdsbwd= amdsbwd _amdtemp= amdtemp _arcmsr= arcmsr _asmc= asmc _ciss= ciss _cmx= cmx _coretemp= coretemp .if ${MK_SOURCELESS_HOST} != "no" _hpt27xx= hpt27xx .endif _hptiop= hptiop .if ${MK_SOURCELESS_HOST} != "no" _hptmv= hptmv _hptnr= hptnr _hptrr= hptrr .endif _hyperv= hyperv _ichwd= ichwd _ida= ida _iir= iir _ipmi= ipmi _ips= ips _isci= isci _ipw= ipw _iwi= iwi _iwm= iwm _iwn= iwn _ixgb= ixgb .if ${MK_SOURCELESS_UCODE} != "no" _ipwfw= ipwfw _iwifw= iwifw _iwmfw= iwmfw _iwnfw= iwnfw .endif .if ${MK_OFED} != "no" || defined(ALL_MODULES) _mlx4= mlx4 _mlx4ib= mlx4ib _mlxen= mlxen .endif _mlx5= mlx5 .if (${MK_INET_SUPPORT} != "no" && ${MK_INET6_SUPPORT} != "no") || \ defined(ALL_MODULES) _mlx5en= mlx5en .endif _mly= mly .if ${MK_OFED} != "no" || defined(ALL_MODULES) _mthca= mthca .endif _nfe= nfe _nvd= nvd _nvme= nvme _nvram= nvram _nxge= nxge .if ${MK_CRYPT} != "no" || defined(ALL_MODULES) _padlock= padlock _padlock_rng= padlock_rng _rdrand_rng= rdrand_rng .endif _s3= s3 _tpm= tpm _twa= twa _vesa= vesa _viawd= viawd _virtio= virtio _wpi= wpi .if ${MK_SOURCELESS_UCODE} != "no" _wpifw= wpifw .endif _x86bios= x86bios .endif .endif .if ${MACHINE_CPUARCH} == "amd64" _ioat= ioat _ixl= ixl _ixlv= ixlv _linux64= linux64 _linux_common= linux_common _ntb= ntb _pms= pms _qlxge= qlxge _qlxgb= qlxgb _qlxgbe= qlxgbe _sfxge= sfxge .if ${MK_BHYVE} != "no" || defined(ALL_MODULES) _vmm= vmm .endif .endif .if ${MACHINE_CPUARCH} == "i386" # XXX some of these can move to the general case when de-i386'ed # XXX some of these can move now, but are untested on other architectures. _3dfx= 3dfx _3dfx_linux= 3dfx_linux _aic= aic _apm= apm _arcnet= arcnet .if ${MK_SOURCELESS_UCODE} != "no" _ce= ce .endif _coff= coff .if ${MK_SOURCELESS_UCODE} != "no" _cp= cp .endif _elink= elink _glxiic= glxiic _glxsb= glxsb #_ibcs2= ibcs2 _ie= ie _mse= mse _ncr= ncr _ncv= ncv _nsp= nsp _pcfclock= pcfclock _pst= pst _sbni= sbni _streams= streams _stg= stg _svr4= svr4 _wds= wds .if ${MACHINE} == "i386" .if ${MK_EISA} != "no" _ahb= ahb .endif _bios= bios _cm= cm .if ${MK_SOURCELESS_UCODE} != "no" _ctau= ctau .endif _dpt= dpt _ex= ex _wl= wl .elif ${MACHINE} == "pc98" _canbepm= canbepm _canbus= canbus _ct= ct _pmc= pmc _snc= snc .endif .endif .if ${MACHINE_CPUARCH} == "arm" _cfi= cfi _cpsw= cpsw .endif .if ${MACHINE_CPUARCH} == "powerpc" _agp= agp _an= an _bm= bm _cardbus= cardbus _cbb= cbb _cfi= cfi _cpufreq= cpufreq _drm= drm _exca= exca _nvram= powermac_nvram _pccard= pccard _wi= wi .endif .if ${MACHINE_ARCH} == "powerpc64" _drm2= drm2 .endif .if ${MACHINE_CPUARCH} == "sparc64" _auxio= auxio _em= em _epic= epic _igb= igb .endif .if ${MACHINE_CPUARCH} == "aarch64" || ${MACHINE_CPUARCH} == "amd64" _cloudabi64= cloudabi64 .endif .endif SUBDIR+=${MODULES_EXTRA} .for reject in ${WITHOUT_MODULES} SUBDIR:= ${SUBDIR:N${reject}} .endfor # Calling kldxref(8) for each module is expensive. .if !defined(NO_XREF) .MAKEFLAGS+= -DNO_XREF afterinstall: @if type kldxref >/dev/null 2>&1; then \ ${ECHO} kldxref ${DESTDIR}${KMODDIR}; \ kldxref ${DESTDIR}${KMODDIR}; \ fi .endif .include "${SYSDIR}/conf/config.mk" SUBDIR:= ${SUBDIR:u:O} .include Index: head/sys/modules/nctgpio/Makefile =================================================================== --- head/sys/modules/nctgpio/Makefile (nonexistent) +++ head/sys/modules/nctgpio/Makefile (revision 297443) @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../dev/nctgpio +KMOD= nctgpio +SRCS= nctgpio.c +SRCS+= device_if.h bus_if.h isa_if.h gpio_if.h opt_platform.h + +.include Property changes on: head/sys/modules/nctgpio/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property