diff --git a/sys/dev/nctgpio/nctgpio.c b/sys/dev/nctgpio/nctgpio.c --- a/sys/dev/nctgpio/nctgpio.c +++ b/sys/dev/nctgpio/nctgpio.c @@ -71,6 +71,7 @@ GPIO_PIN_INVIN | GPIO_PIN_INVOUT) #define NCT_PREFER_INDIRECT_CHANNEL 2 +#define NCT_NO_ENABLE 4 #define NCT_VERBOSE_PRINTF(dev, ...) \ do { \ @@ -144,6 +145,7 @@ struct nct_device { uint16_t devid; int extid; + uint8_t ldn; const char *descr; int ngroups; struct nct_gpio_group groups[NCT_MAX_GROUP + 1]; @@ -747,6 +749,168 @@ }, }, }, + { + .devid = 0xd284, + .ldn = 7, + .descr = "GPIO on Nuvoton NCT6122D/NCT6126D", + .ngroups = 8, + .groups = { + // LDN7, GPIO0-7 + { + .grpnum = 0, + .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, + .enable_ldn = 0x07, + .enable_reg = 0x30, + .enable_mask = 0x01, + .data_ldn = 0x07, + .ppod_reg = 0xe0, + .caps = NCT_GPIO_CAPS, + .npins = 8, + .iobase = 0xe0, + }, + { + .grpnum = 1, + .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, + .enable_ldn = 0x07, + .enable_reg = 0x30, + .enable_mask = 0x02, + .data_ldn = 0x07, + .ppod_reg = 0xe1, + .caps = NCT_GPIO_CAPS, + .npins = 8, + .iobase = 0xe4, + }, + { + .grpnum = 2, + .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, + .enable_ldn = 0x07, + .enable_reg = 0x30, + .enable_mask = 0x04, + .data_ldn = 0x07, + .ppod_reg = 0xe2, + .caps = NCT_GPIO_CAPS, + .npins = 8, + .iobase = 0xe8, + }, + { + .grpnum = 3, + .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, + .enable_ldn = 0x07, + .enable_reg = 0x30, + .enable_mask = 0x08, + .data_ldn = 0x07, + .ppod_reg = 0xe3, + .caps = NCT_GPIO_CAPS, + .npins = 8, + .iobase = 0xec, + }, + { + .grpnum = 4, + .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, + .enable_ldn = 0x07, + .enable_reg = 0x30, + .enable_mask = 0x10, + .data_ldn = 0x07, + .ppod_reg = 0xe4, + .caps = NCT_GPIO_CAPS, + .npins = 8, + .iobase = 0xf0, + }, + { + .grpnum = 5, + .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, + .enable_ldn = 0x07, + .enable_reg = 0x30, + .enable_mask = 0x20, + .data_ldn = 0x07, + .ppod_reg = 0xe5, + .caps = NCT_GPIO_CAPS, + .npins = 8, + .iobase = 0xf4, + }, + { + .grpnum = 6, + .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, + .enable_ldn = 0x07, + .enable_reg = 0x30, + .enable_mask = 0x40, + .data_ldn = 0x07, + .ppod_reg = 0xe6, + .caps = NCT_GPIO_CAPS, + .npins = 8, + .iobase = 0xf8, + }, + { + .grpnum = 7, + .pinbits = { 0, 1 }, + .enable_ldn = 0x07, + .enable_reg = 0x30, + .enable_mask = 0x80, + .data_ldn = 0x07, + .ppod_reg = 0xe7, + .caps = NCT_GPIO_CAPS, + .npins = 2, + .iobase = 0xfc, + }, + }, + }, + { + // LDN9, GPIO8,GPIO9,GPIOA,GPIOB + .devid = 0xd284, + .ldn = 9, + .descr = "GPIO on Nuvoton NCT6122D/NCT6126D", + .ngroups = 4, + .groups = { + { + .grpnum = 8, + .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, + .enable_ldn = 0x09, + .enable_reg = 0x30, + .enable_mask = 0x01, + .data_ldn = 0x09, + .ppod_reg = 0xe8, + .caps = NCT_GPIO_CAPS, + .npins = 8, + .iobase = 0xf0, + }, + { + .grpnum = 9, + .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, + .enable_ldn = 0x09, + .enable_reg = 0x30, + .enable_mask = 0x02, + .data_ldn = 0x09, + .ppod_reg = 0xe9, + .caps = NCT_GPIO_CAPS, + .npins = 8, + .iobase = 0xf4, + }, + { + .grpnum = 0xa, + .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, + .enable_ldn = 0x09, + .enable_reg = 0x30, + .enable_mask = 0x04, + .data_ldn = 0x09, + .ppod_reg = 0xea, + .caps = NCT_GPIO_CAPS, + .npins = 8, + .iobase = 0xf8, + }, + { + .grpnum = 0xb, + .pinbits = { 0, 1, 2, 3, 4, 5, 6, 7 }, + .enable_ldn = 0x09, + .enable_reg = 0x30, + .enable_mask = 0x08, + .data_ldn = 0x09, + .ppod_reg = 0xeb, + .caps = NCT_GPIO_CAPS, + .npins = 8, + .iobase = 0xfc, + }, + }, + }, }; static const char * @@ -1092,12 +1256,20 @@ struct nct_device *nctdevp; uint16_t devid; int i, extid; + uint8_t ldn; devid = superio_devid(dev); extid = superio_extid(dev); + ldn = superio_get_ldn(dev); for (i = 0, nctdevp = nct_devices; i < nitems(nct_devices); i++, nctdevp++) { - if (devid == nctdevp->devid && nctdevp->extid == extid) - return (nctdevp); + if (nctdevp->devid != devid) + continue; + if (nctdevp->extid && (nctdevp->extid != extid)) + continue; + if (nctdevp->ldn && (nctdevp->ldn != ldn)) + continue; + + return (nctdevp); } return (NULL); } @@ -1128,6 +1300,27 @@ return (BUS_PROBE_DEFAULT); } +static void +nct_enable_gpios (device_t dev, struct nct_softc *sc) +{ + struct nct_softc *sc; + struct nct_gpio_group *gp; + uint8_t v; + int g; + + /* Enable GPIO groups */ + for (g = 0, gp = sc->nctdevp->groups; g < sc->nctdevp->ngroups; g++, gp++) { + NCT_VERBOSE_PRINTF(dev, + "GPIO%d: %d pins, enable with mask 0x%x via ldn 0x%x reg 0x%x\n", + gp->grpnum, gp->npins, gp->enable_mask, gp->enable_ldn, + gp->enable_reg); + v = superio_ldn_read(dev, gp->enable_ldn, gp->enable_reg); + v |= gp->enable_mask; + superio_ldn_write(dev, gp->enable_ldn, gp->enable_reg, v); + } + return; +} + static int nct_attach(device_t dev) { @@ -1167,7 +1360,7 @@ iobase, 7); /* FIXME NCT6796D-E have 8 registers according to table 18.3. */ if (err == 0) { sc->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, - &sc->iorid, RF_ACTIVE); + &sc->iorid, RF_ACTIVE|RF_SHAREABLE); if (sc->iores == NULL) { device_printf(dev, "can't map i/o space, " "iobase=%#x\n", iobase); @@ -1181,15 +1374,10 @@ NCT_VERBOSE_PRINTF(dev, "iores %p %s channel\n", sc->iores, (sc->iores ? "direct" : "indirect")); - /* Enable GPIO groups */ - for (g = 0, gp = sc->nctdevp->groups; g < sc->nctdevp->ngroups; g++, gp++) { - NCT_VERBOSE_PRINTF(dev, - "GPIO%d: %d pins, enable with mask 0x%x via ldn 0x%x reg 0x%x\n", - gp->grpnum, gp->npins, gp->enable_mask, gp->enable_ldn, - gp->enable_reg); - v = superio_ldn_read(dev, gp->enable_ldn, gp->enable_reg); - v |= gp->enable_mask; - superio_ldn_write(dev, gp->enable_ldn, gp->enable_reg, v); + if (flags & NCT_NO_ENABLE) { + NCT_VERBOSE_PRINTF(dev, "skipping enable.\n"); + } else { + nct_enable_gpios(dev, sc); } GPIO_LOCK_INIT(sc); @@ -1201,6 +1389,12 @@ sc->grpmap[gp->grpnum] = gp; + if (flags & NCT_NO_ENABLE) { + v = superio_ldn_read(dev, gp->enable_ldn, gp->enable_reg); + if ((v & gp->enable_mask) == 0) + continue; + } + /* * Caching input values is meaningless as an input can be changed at any * time by an external agent. But outputs are controlled by this diff --git a/sys/dev/ncthwm/ncthwm.c b/sys/dev/ncthwm/ncthwm.c --- a/sys/dev/ncthwm/ncthwm.c +++ b/sys/dev/ncthwm/ncthwm.c @@ -43,7 +43,7 @@ #define NCTHWM_FAN_MAX 5 #define NCTHWM_BANK_SELECT 0x4e -#define NCTHWM_VENDOR_ID 0x4f +#define THWM_BANK_SELECT #define NCTHWM_VERBOSE_PRINTF(dev, ...) \ do { \ @@ -99,6 +99,19 @@ { .name = "AUXFAN1", .low_byte_offset = 0xc7, .high_byte_offset = 0xc6 }, { .name = "AUXFAN2", .low_byte_offset = 0xc9, .high_byte_offset = 0xc8 }, }, + }, { + .devid = 0xd284, + .descr = "HWM on Nuvoton NCT6122D/NCT6126D", + .base_offset = 5, + .fan_bank = 0, + .fan_count = 5, + .fan_info = { + { .name = "SYSFAN", .low_byte_offset = 0x31, .high_byte_offset = 0x30 }, + { .name = "CPUFAN", .low_byte_offset = 0x33, .high_byte_offset = 0x32 }, + { .name = "AUXFAN0", .low_byte_offset = 0x35, .high_byte_offset = 0x34 }, + { .name = "AUXFAN1", .low_byte_offset = 0x37, .high_byte_offset = 0x36 }, + { .name = "AUXFAN2", .low_byte_offset = 0x39, .high_byte_offset = 0x38 }, + }, } }; diff --git a/sys/dev/superio/superio.c b/sys/dev/superio/superio.c --- a/sys/dev/superio/superio.c +++ b/sys/dev/superio/superio.c @@ -296,6 +296,14 @@ { .type = SUPERIO_DEV_NONE }, }; +const struct sio_device nct612x_devices[] = { + { .ldn = 0x7, .type = SUPERIO_DEV_GPIO }, + { .ldn = 0x8, .type = SUPERIO_DEV_WDT }, + { .ldn = 0x9, .type = SUPERIO_DEV_GPIO }, + { .ldn = 0xb, .type = SUPERIO_DEV_HWM }, + { .type = SUPERIO_DEV_NONE }, +}; + const struct sio_device nct67xx_devices[] = { { .ldn = 0x8, .type = SUPERIO_DEV_WDT }, { .ldn = 0x9, .type = SUPERIO_DEV_GPIO }, @@ -469,7 +477,17 @@ .devices = nvt_devices, }, { - .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0xd200, .mask = 0xff, + .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0xd284, + .descr = "Nuvoton NCT6122D/NCT6126D", + .devices = nct612x_devices, + }, + /* + * NCT6112D 0xd281? + * NCT6114D 0xd282? + * NCT6116D 0xd283 + */ + { + .vendor = SUPERIO_VENDOR_NUVOTON, .devid = 0xd280, .mask = 0x3f, .descr = "Nuvoton NCT6112D/NCT6114D/NCT6116D", .devices = nct611x_devices, },