diff --git a/sys/dev/nctgpio/nctgpio.c b/sys/dev/nctgpio/nctgpio.c index eb86b0a9e5eb..e6edcedfd2a7 100644 --- a/sys/dev/nctgpio/nctgpio.c +++ b/sys/dev/nctgpio/nctgpio.c @@ -42,34 +42,20 @@ #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 @@ -83,8 +69,6 @@ #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) @@ -97,10 +81,9 @@ struct nct_softc { device_t dev; + device_t dev_f; device_t busdev; struct mtx mtx; - struct resource *portres; - int rid; struct gpio_pin pins[NCT_MAX_PIN + 1]; }; @@ -112,22 +95,6 @@ struct nct_softc { #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; @@ -146,76 +113,6 @@ struct nuvoton_vendor_device_id { }, }; -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. @@ -289,10 +186,9 @@ nct_set_pin_is_output(struct nct_softc *sc, uint32_t pin_num) uint8_t ior; reg = nct_ior_addr(pin_num); - select_ldn(sc, NCT_LDN_GPIO); - ior = read_cfg_reg_1(sc, reg); + ior = superio_read(sc->dev, reg); ior &= ~(NCT_PIN_BIT(pin_num)); - write_cfg_reg_1(sc, reg, ior); + superio_write(sc->dev, reg, ior); } /* @@ -305,10 +201,9 @@ nct_set_pin_is_input(struct nct_softc *sc, uint32_t pin_num) uint8_t ior; reg = nct_ior_addr(pin_num); - select_ldn(sc, NCT_LDN_GPIO); - ior = read_cfg_reg_1(sc, reg); + ior = superio_read(sc->dev, reg); ior |= NCT_PIN_BIT(pin_num); - write_cfg_reg_1(sc, reg, ior); + superio_write(sc->dev, reg, ior); } /* @@ -321,8 +216,7 @@ nct_pin_is_input(struct nct_softc *sc, uint32_t pin_num) uint8_t ior; reg = nct_ior_addr(pin_num); - select_ldn(sc, NCT_LDN_GPIO); - ior = read_cfg_reg_1(sc, reg); + ior = superio_read(sc->dev, reg); return (ior & NCT_PIN_BIT(pin_num)); } @@ -337,14 +231,13 @@ nct_write_pin(struct nct_softc *sc, uint32_t pin_num, uint8_t data) uint8_t value; reg = nct_dat_addr(pin_num); - select_ldn(sc, NCT_LDN_GPIO); - value = read_cfg_reg_1(sc, reg); + value = superio_read(sc->dev, reg); if (data) value |= NCT_PIN_BIT(pin_num); else value &= ~(NCT_PIN_BIT(pin_num)); - write_cfg_reg_1(sc, reg, value); + superio_write(sc->dev, reg, value); } static bool @@ -353,9 +246,8 @@ 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)); + return (superio_read(sc->dev, reg) & NCT_PIN_BIT(pin_num)); } static void @@ -365,10 +257,9 @@ nct_set_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num) uint8_t inv; reg = nct_inv_addr(pin_num); - select_ldn(sc, NCT_LDN_GPIO); - inv = read_cfg_reg_1(sc, reg); + inv = superio_read(sc->dev, reg); inv |= (NCT_PIN_BIT(pin_num)); - write_cfg_reg_1(sc, reg, inv); + superio_write(sc->dev, reg, inv); } static void @@ -378,10 +269,9 @@ nct_set_pin_not_inverted(struct nct_softc *sc, uint32_t pin_num) uint8_t inv; reg = nct_inv_addr(pin_num); - select_ldn(sc, NCT_LDN_GPIO); - inv = read_cfg_reg_1(sc, reg); + inv = superio_read(sc->dev, reg); inv &= ~(NCT_PIN_BIT(pin_num)); - write_cfg_reg_1(sc, reg, inv); + superio_write(sc->dev, reg, inv); } static bool @@ -391,8 +281,7 @@ nct_pin_is_inverted(struct nct_softc *sc, uint32_t pin_num) uint8_t inv; reg = nct_inv_addr(pin_num); - select_ldn(sc, NCT_LDN_GPIO); - inv = read_cfg_reg_1(sc, reg); + inv = superio_read(sc->dev, reg); return (inv & NCT_PIN_BIT(pin_num)); } @@ -404,10 +293,9 @@ nct_set_pin_opendrain(struct nct_softc *sc, uint32_t pin_num) 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); + outcfg = superio_read(sc->dev_f, reg); + outcfg |= NCT_PIN_BIT(pin_num); + superio_write(sc->dev_f, reg, outcfg); } static void @@ -417,10 +305,9 @@ nct_set_pin_pushpull(struct nct_softc *sc, uint32_t pin_num) 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); + outcfg = superio_read(sc->dev_f, reg); + outcfg &= ~NCT_PIN_BIT(pin_num); + superio_write(sc->dev_f, reg, outcfg); } static bool @@ -430,66 +317,33 @@ nct_pin_is_opendrain(struct nct_softc *sc, uint32_t pin_num) uint8_t outcfg; reg = nct_outcfg_addr(pin_num); - select_ldn(sc, NCT_LDN_GPIO_MODE); - outcfg = read_cfg_reg_1(sc, reg); - + outcfg = superio_read(sc->dev_f, 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; + int j; uint16_t chipid; - /* Make sure we do not claim some ISA PNP device. */ - if (isa_get_logicalid(dev) != 0) + if (superio_vendor(dev) != SUPERIO_VENDOR_NUVOTON) + return (ENXIO); + if (superio_get_type(dev) != SUPERIO_DEV_GPIO) return (ENXIO); - sc = device_get_softc(dev); + /* + * There are several GPIO devices, we attach only to one of them + * and use the rest without attaching. + */ + if (superio_get_ldn(dev) != NCT_LDN_GPIO) + return (ENXIO); - for (i = 0; i < nitems(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 < nitems(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); - } + chipid = superio_devid(dev); + for (j = 0; j < nitems(nct_devs); j++) { + if (chipid == nct_devs[j].chip_id) { + device_set_desc(dev, "Nuvoton GPIO controller"); + return (BUS_PROBE_DEFAULT); } } return (ENXIO); @@ -502,24 +356,19 @@ nct_attach(device_t dev) 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"); + sc->dev = dev; + sc->dev_f = superio_find_dev(device_get_parent(dev), SUPERIO_DEV_GPIO, + NCT_LDN_GPIO_MODE); + if (sc->dev_f == NULL) { + device_printf(dev, "failed to find LDN F\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); + superio_dev_enable(dev, 0x03); + + GPIO_LOCK_INIT(sc); + GPIO_LOCK(sc); for (i = 0; i <= NCT_MAX_PIN; i++) { struct gpio_pin *pin; @@ -550,12 +399,7 @@ nct_attach(device_t dev) 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); } @@ -571,13 +415,6 @@ nct_detach(device_t 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); @@ -775,26 +612,25 @@ nct_gpio_pin_setflags(device_t dev, uint32_t pin_num, uint32_t flags) 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_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 = { +static driver_t nct_driver = { "gpio", nct_methods, sizeof(struct nct_softc) @@ -802,5 +638,8 @@ static driver_t nct_isa_driver = { static devclass_t nct_devclass; -DRIVER_MODULE(nctgpio, isa, nct_isa_driver, nct_devclass, NULL, NULL); +DRIVER_MODULE(nctgpio, superio, nct_driver, nct_devclass, NULL, NULL); MODULE_DEPEND(nctgpio, gpiobus, 1, 1, 1); +MODULE_DEPEND(nctgpio, superio, 1, 1, 1); +MODULE_VERSION(nctgpio, 1); +