[BACK]Return to nsclpcsio_isa.c CVS log [TXT][DIR] Up to [local] / sys / dev / isa

Annotation of sys/dev/isa/nsclpcsio_isa.c, Revision 1.1.1.1

1.1       nbrk        1: /* $OpenBSD: nsclpcsio_isa.c,v 1.12 2007/06/01 21:30:31 cnst Exp $ */
                      2: /* $NetBSD: nsclpcsio_isa.c,v 1.5 2002/10/22 16:18:26 drochner Exp $ */
                      3:
                      4: /*
                      5:  * Copyright (c) 2002 Matthias Drochner.  All rights reserved.
                      6:  * Copyright (c) 2004 Markus Friedl.  All rights reserved.
                      7:  * Copyright (c) 2004 Alexander Yurchenko.  All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions, and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     19:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     20:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     21:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     22:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     23:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     24:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     25:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     26:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     27:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     28:  * SUCH DAMAGE.
                     29:  */
                     30:
                     31: /*
                     32:  * National Semiconductor PC87366 LPC Super I/O.
                     33:  * Supported logical devices: GPIO, TMS, VLM.
                     34:  */
                     35:
                     36: #include <sys/param.h>
                     37: #include <sys/systm.h>
                     38: #include <sys/device.h>
                     39: #include <sys/gpio.h>
                     40: #include <sys/kernel.h>
                     41: #include <sys/sensors.h>
                     42: #include <sys/timeout.h>
                     43:
                     44: #include <machine/bus.h>
                     45:
                     46: #include <dev/isa/isareg.h>
                     47: #include <dev/isa/isavar.h>
                     48:
                     49: #include <dev/gpio/gpiovar.h>
                     50:
                     51: #if defined(NSC_LPC_SIO_DEBUG)
                     52: #define DPRINTF(x)              do { printf x; } while (0)
                     53: #else
                     54: #define DPRINTF(x)
                     55: #endif
                     56:
                     57: #define SIO_REG_SID    0x20    /* Super I/O ID */
                     58: #define SIO_SID_PC87366        0xE9    /* PC87366 is identified by 0xE9.*/
                     59:
                     60: #define SIO_REG_SRID   0x27    /* Super I/O Revision */
                     61:
                     62: #define SIO_REG_LDN    0x07    /* Logical Device Number */
                     63: #define SIO_LDN_FDC    0x00    /* Floppy Disk Controller (FDC) */
                     64: #define SIO_LDN_PP     0x01    /* Parallel Port (PP) */
                     65: #define SIO_LDN_SP2    0x02    /* Serial Port 2 with IR (SP2) */
                     66: #define SIO_LDN_SP1    0x03    /* Serial Port 1 (SP1) */
                     67: #define SIO_LDN_SWC    0x04    /* System Wake-Up Control (SWC) */
                     68: #define SIO_LDN_KBCM   0x05    /* Mouse Controller (KBC) */
                     69: #define SIO_LDN_KBCK   0x06    /* Keyboard Controller (KBC) */
                     70: #define SIO_LDN_GPIO   0x07    /* General-Purpose I/O (GPIO) Ports */
                     71: #define SIO_LDN_ACB    0x08    /* ACCESS.bus Interface (ACB) */
                     72: #define SIO_LDN_FSCM   0x09    /* Fan Speed Control and Monitor (FSCM) */
                     73: #define SIO_LDN_WDT    0x0A    /* WATCHDOG Timer (WDT) */
                     74: #define SIO_LDN_GMP    0x0B    /* Game Port (GMP) */
                     75: #define SIO_LDN_MIDI   0x0C    /* Musical Instrument Digital Interface */
                     76: #define SIO_LDN_VLM    0x0D    /* Voltage Level Monitor (VLM) */
                     77: #define SIO_LDN_TMS    0x0E    /* Temperature Sensor (TMS) */
                     78:
                     79: #define SIO_REG_ACTIVE 0x30    /* Logical Device Activate Register */
                     80: #define SIO_ACTIVE_EN          0x01    /* enabled */
                     81:
                     82: #define SIO_REG_IO_MSB 0x60    /* I/O Port Base, bits 15-8 */
                     83: #define SIO_REG_IO_LSB 0x61    /* I/O Port Base, bits 7-0 */
                     84:
                     85: #define SIO_LDNUM      15      /* total number of logical devices */
                     86:
                     87: /* Supported logical devices description */
                     88: static const struct {
                     89:        const char *ld_name;
                     90:        int ld_num;
                     91:        int ld_iosize;
                     92: } sio_ld[] = {
                     93:        { "GPIO", SIO_LDN_GPIO, 16 },
                     94:        { "VLM", SIO_LDN_VLM, 16 },
                     95:        { "TMS", SIO_LDN_TMS, 16 },
                     96: };
                     97:
                     98: /* GPIO */
                     99: #define SIO_GPIO_PINSEL        0xf0
                    100: #define SIO_GPIO_PINCFG        0xf1
                    101: #define SIO_GPIO_PINEV 0xf2
                    102:
                    103: #define SIO_GPIO_CONF_OUTPUTEN (1 << 0)
                    104: #define SIO_GPIO_CONF_PUSHPULL (1 << 1)
                    105: #define SIO_GPIO_CONF_PULLUP   (1 << 2)
                    106:
                    107: #define SIO_GPDO0      0x00
                    108: #define SIO_GPDI0      0x01
                    109: #define SIO_GPEVEN0    0x02
                    110: #define SIO_GPEVST0    0x03
                    111: #define SIO_GPDO1      0x04
                    112: #define SIO_GPDI1      0x05
                    113: #define SIO_GPEVEN1    0x06
                    114: #define SIO_GPEVST1    0x07
                    115: #define SIO_GPDO2      0x08
                    116: #define SIO_GPDI2      0x09
                    117: #define SIO_GPDO3      0x0a
                    118: #define SIO_GPDI3      0x0b
                    119:
                    120: #define SIO_GPIO_NPINS 29
                    121:
                    122: /* TMS */
                    123: #define SIO_TEVSTS     0x00    /* Temperature Event Status */
                    124: #define SIO_TEVSMI     0x02    /* Temperature Event to SMI */
                    125: #define SIO_TEVIRQ     0x04    /* Temperature Event to IRQ */
                    126: #define SIO_TMSCFG     0x08    /* TMS Configuration */
                    127: #define SIO_TMSBS      0x09    /* TMS Bank Select */
                    128: #define SIO_TCHCFST    0x0A    /* Temperature Channel Config and Status */
                    129: #define SIO_RDCHT      0x0B    /* Read Channel Temperature */
                    130: #define SIO_CHTH       0x0C    /* Channel Temperature High Limit */
                    131: #define SIO_CHTL       0x0D    /* Channel Temperature Low Limit */
                    132: #define SIO_CHOTL      0x0E    /* Channel Overtemperature Limit */
                    133:
                    134: /* VLM */
                    135: #define SIO_VEVSTS0    0x00    /* Voltage Event Status 0 */
                    136: #define SIO_VEVSTS1    0x01    /* Voltage Event Status 1 */
                    137: #define SIO_VEVSMI0    0x02    /* Voltage Event to SMI 0 */
                    138: #define SIO_VEVSMI1    0x03    /* Voltage Event to SMI 1 */
                    139: #define SIO_VEVIRQ0    0x04    /* Voltage Event to IRQ 0 */
                    140: #define SIO_VEVIRQ1    0x05    /* Voltage Event to IRQ 1 */
                    141: #define SIO_VID                0x06    /* Voltage ID */
                    142: #define SIO_VCNVR      0x07    /* Voltage Conversion Rate */
                    143: #define SIO_VLMCFG     0x08    /* VLM Configuration */
                    144: #define SIO_VLMBS      0x09    /* VLM Bank Select */
                    145: #define SIO_VCHCFST    0x0A    /* Voltage Channel Config and Status */
                    146: #define SIO_RDCHV      0x0B    /* Read Channel Voltage */
                    147: #define SIO_CHVH       0x0C    /* Channel Voltage High Limit */
                    148: #define SIO_CHVL       0x0D    /* Channel Voltage Low Limit */
                    149: #define SIO_OTSL       0x0E    /* Overtemperature Shutdown Limit */
                    150:
                    151: #define SIO_REG_SIOCF1 0x21
                    152: #define SIO_REG_SIOCF2 0x22
                    153: #define SIO_REG_SIOCF3 0x23
                    154: #define SIO_REG_SIOCF4 0x24
                    155: #define SIO_REG_SIOCF5 0x25
                    156: #define SIO_REG_SIOCF8 0x28
                    157: #define SIO_REG_SIOCFA 0x2A
                    158: #define SIO_REG_SIOCFB 0x2B
                    159: #define SIO_REG_SIOCFC 0x2C
                    160: #define SIO_REG_SIOCFD 0x2D
                    161:
                    162: #define        SIO_NUM_SENSORS (3+14)
                    163: #define SIO_VLM_OFF    3
                    164: #define SIO_VREF       1235    /* 1000.0 * VREF */
                    165:
                    166: struct nsclpcsio_softc {
                    167:        struct device sc_dev;
                    168:        bus_space_tag_t sc_iot;
                    169:        bus_space_handle_t sc_ioh;
                    170:
                    171:        bus_space_handle_t sc_ld_ioh[SIO_LDNUM];
                    172:        int sc_ld_en[SIO_LDNUM];
                    173:
                    174:        /* GPIO */
                    175:        struct gpio_chipset_tag sc_gpio_gc;
                    176:        struct gpio_pin sc_gpio_pins[SIO_GPIO_NPINS];
                    177:
                    178:        /* TMS and VLM */
                    179:        struct ksensor sensors[SIO_NUM_SENSORS];
                    180:        struct ksensordev sensordev;
                    181: };
                    182:
                    183: #define GPIO_READ(sc, reg) \
                    184:        bus_space_read_1((sc)->sc_iot,                          \
                    185:            (sc)->sc_ld_ioh[SIO_LDN_GPIO], (reg))
                    186: #define GPIO_WRITE(sc, reg, val) \
                    187:        bus_space_write_1((sc)->sc_iot,                         \
                    188:            (sc)->sc_ld_ioh[SIO_LDN_GPIO], (reg), (val))
                    189: #define TMS_WRITE(sc, reg, val) \
                    190:        bus_space_write_1((sc)->sc_iot,                         \
                    191:            (sc)->sc_ld_ioh[SIO_LDN_TMS], (reg), (val))
                    192: #define TMS_READ(sc, reg) \
                    193:        bus_space_read_1((sc)->sc_iot,                          \
                    194:            (sc)->sc_ld_ioh[SIO_LDN_TMS], (reg))
                    195: #define VLM_WRITE(sc, reg, val) \
                    196:        bus_space_write_1((sc)->sc_iot,                         \
                    197:            (sc)->sc_ld_ioh[SIO_LDN_VLM], (reg), (val))
                    198: #define VLM_READ(sc, reg) \
                    199:        bus_space_read_1((sc)->sc_iot,                          \
                    200:            (sc)->sc_ld_ioh[SIO_LDN_VLM], (reg))
                    201:
                    202: int     nsclpcsio_isa_match(struct device *, void *, void *);
                    203: void    nsclpcsio_isa_attach(struct device *, struct device *, void *);
                    204:
                    205: struct cfattach nsclpcsio_isa_ca = {
                    206:        sizeof(struct nsclpcsio_softc),
                    207:        nsclpcsio_isa_match,
                    208:        nsclpcsio_isa_attach
                    209: };
                    210:
                    211: struct cfdriver nsclpcsio_cd = {
                    212:        NULL, "nsclpcsio", DV_DULL
                    213: };
                    214:
                    215: struct timeout  nsclpcsio_timeout;
                    216:
                    217: static u_int8_t        nsread(bus_space_tag_t, bus_space_handle_t, int);
                    218: static void    nswrite(bus_space_tag_t, bus_space_handle_t, int, u_int8_t);
                    219:
                    220: void   nsclpcsio_gpio_init(struct nsclpcsio_softc *);
                    221: int    nsclpcsio_gpio_pin_read(void *, int);
                    222: void   nsclpcsio_gpio_pin_write(void *, int, int);
                    223: void   nsclpcsio_gpio_pin_ctl(void *, int, int);
                    224:
                    225: void   nsclpcsio_tms_init(struct nsclpcsio_softc *);
                    226: void   nsclpcsio_vlm_init(struct nsclpcsio_softc *);
                    227: void   nsclpcsio_tms_update(struct nsclpcsio_softc *);
                    228: void   nsclpcsio_vlm_update(struct nsclpcsio_softc *);
                    229: void   nsclpcsio_refresh(void *);
                    230:
                    231: static u_int8_t
                    232: nsread(bus_space_tag_t iot, bus_space_handle_t ioh, int idx)
                    233: {
                    234:        bus_space_write_1(iot, ioh, 0, idx);
                    235:        return (bus_space_read_1(iot, ioh, 1));
                    236: }
                    237:
                    238: static void
                    239: nswrite(bus_space_tag_t iot, bus_space_handle_t ioh, int idx, u_int8_t data)
                    240: {
                    241:        bus_space_write_1(iot, ioh, 0, idx);
                    242:        bus_space_write_1(iot, ioh, 1, data);
                    243: }
                    244:
                    245: int
                    246: nsclpcsio_isa_match(struct device *parent, void *match, void *aux)
                    247: {
                    248:        struct isa_attach_args *ia = aux;
                    249:        bus_space_tag_t iot;
                    250:        bus_space_handle_t ioh;
                    251:        int iobase;
                    252:        int rv = 0;
                    253:
                    254:        iot = ia->ia_iot;
                    255:        iobase = ia->ipa_io[0].base;
                    256:        if (bus_space_map(iot, iobase, 2, 0, &ioh))
                    257:                return (0);
                    258:
                    259:        if (nsread(iot, ioh, SIO_REG_SID) == SIO_SID_PC87366)
                    260:                rv = 1;
                    261:
                    262:        bus_space_unmap(iot, ioh, 2);
                    263:
                    264:        if (rv) {
                    265:                ia->ipa_nio = 1;
                    266:                ia->ipa_io[0].length = 2;
                    267:
                    268:                ia->ipa_nmem = 0;
                    269:                ia->ipa_nirq = 0;
                    270:                ia->ipa_ndrq = 0;
                    271:        }
                    272:
                    273:        return (rv);
                    274: }
                    275:
                    276: void
                    277: nsclpcsio_isa_attach(struct device *parent, struct device *self, void *aux)
                    278: {
                    279:        struct nsclpcsio_softc *sc = (void *)self;
                    280:        struct isa_attach_args *ia = aux;
                    281:        struct gpiobus_attach_args gba;
                    282:        bus_space_tag_t iot;
                    283:        int iobase;
                    284:        int i;
                    285:
                    286:        iobase = ia->ipa_io[0].base;
                    287:        sc->sc_iot = iot = ia->ia_iot;
                    288:        if (bus_space_map(ia->ia_iot, iobase, 2, 0, &sc->sc_ioh)) {
                    289:                printf(": can't map i/o space\n");
                    290:                return;
                    291:        }
                    292:        printf(": NSC PC87366 rev %d:",
                    293:            nsread(sc->sc_iot, sc->sc_ioh, SIO_REG_SRID));
                    294:
                    295:        /* Configure all supported logical devices */
                    296:        for (i = 0; i < sizeof(sio_ld) / sizeof(sio_ld[0]); i++) {
                    297:                sc->sc_ld_en[sio_ld[i].ld_num] = 0;
                    298:
                    299:                /* Select the device and check if it's activated */
                    300:                nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, sio_ld[i].ld_num);
                    301:                if ((nsread(sc->sc_iot, sc->sc_ioh,
                    302:                    SIO_REG_ACTIVE) & SIO_ACTIVE_EN) == 0)
                    303:                        continue;
                    304:
                    305:                /* Map I/O space if necessary */
                    306:                if (sio_ld[i].ld_iosize != 0) {
                    307:                        iobase = (nsread(sc->sc_iot, sc->sc_ioh,
                    308:                            SIO_REG_IO_MSB) << 8);
                    309:                        iobase |= nsread(sc->sc_iot, sc->sc_ioh,
                    310:                            SIO_REG_IO_LSB);
                    311:                        if (bus_space_map(sc->sc_iot, iobase,
                    312:                            sio_ld[i].ld_iosize, 0,
                    313:                            &sc->sc_ld_ioh[sio_ld[i].ld_num]))
                    314:                                continue;
                    315:                }
                    316:
                    317:                sc->sc_ld_en[sio_ld[i].ld_num] = 1;
                    318:                printf(" %s", sio_ld[i].ld_name);
                    319:        }
                    320:
                    321:        printf("\n");
                    322:
                    323:        nsclpcsio_gpio_init(sc);
                    324:        nsclpcsio_tms_init(sc);
                    325:        nsclpcsio_vlm_init(sc);
                    326:
                    327:        /* Hook into hw.sensors sysctl */
                    328:        strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname,
                    329:            sizeof(sc->sensordev.xname));
                    330:        for (i = 0; i < SIO_NUM_SENSORS; i++) {
                    331:                if (i < SIO_VLM_OFF && !sc->sc_ld_en[SIO_LDN_TMS])
                    332:                        continue;
                    333:                if (i >= SIO_VLM_OFF && !sc->sc_ld_en[SIO_LDN_VLM])
                    334:                        continue;
                    335:                sensor_attach(&sc->sensordev, &sc->sensors[i]);
                    336:        }
                    337:        sensordev_install(&sc->sensordev);
                    338:        if (sc->sc_ld_en[SIO_LDN_TMS] || sc->sc_ld_en[SIO_LDN_VLM]) {
                    339:                timeout_set(&nsclpcsio_timeout, nsclpcsio_refresh, sc);
                    340:                timeout_add(&nsclpcsio_timeout, (20 * hz) / 10);
                    341:        }
                    342:
                    343:        /* Attach GPIO framework */
                    344:        if (sc->sc_ld_en[SIO_LDN_GPIO]) {
                    345:                gba.gba_name = "gpio";
                    346:                gba.gba_gc = &sc->sc_gpio_gc;
                    347:                gba.gba_pins = sc->sc_gpio_pins;
                    348:                gba.gba_npins = SIO_GPIO_NPINS;
                    349:                config_found(&sc->sc_dev, &gba, NULL);
                    350:        }
                    351: }
                    352:
                    353: void
                    354: nsclpcsio_refresh(void *arg)
                    355: {
                    356:        struct nsclpcsio_softc *sc = (struct nsclpcsio_softc *)arg;
                    357:
                    358:        if (sc->sc_ld_en[SIO_LDN_TMS])
                    359:                nsclpcsio_tms_update(sc);
                    360:        if (sc->sc_ld_en[SIO_LDN_VLM])
                    361:                nsclpcsio_vlm_update(sc);
                    362:        timeout_add(&nsclpcsio_timeout, (20 * hz) / 10);
                    363: }
                    364:
                    365: void
                    366: nsclpcsio_tms_init(struct nsclpcsio_softc *sc)
                    367: {
                    368:        int i;
                    369:
                    370:        /* Initialisation, PC87366.pdf, page 208 */
                    371:        TMS_WRITE(sc, 0x08, 0x00);
                    372:        TMS_WRITE(sc, 0x09, 0x0f);
                    373:        TMS_WRITE(sc, 0x0a, 0x08);
                    374:        TMS_WRITE(sc, 0x0b, 0x04);
                    375:        TMS_WRITE(sc, 0x0c, 0x35);
                    376:        TMS_WRITE(sc, 0x0d, 0x05);
                    377:        TMS_WRITE(sc, 0x0e, 0x05);
                    378:
                    379:        TMS_WRITE(sc, SIO_TMSCFG, 0x00);
                    380:
                    381:        /* Enable the sensors */
                    382:        for (i = 0; i < 3; i++) {
                    383:                TMS_WRITE(sc, SIO_TMSBS, i);
                    384:                TMS_WRITE(sc, SIO_TCHCFST, 0x01);
                    385:
                    386:                sc->sensors[i].type = SENSOR_TEMP;
                    387:        }
                    388:
                    389:        strlcpy(sc->sensors[0].desc, "Remote", sizeof(sc->sensors[0].desc));
                    390:        strlcpy(sc->sensors[1].desc, "Remote", sizeof(sc->sensors[1].desc));
                    391:        strlcpy(sc->sensors[2].desc, "Local", sizeof(sc->sensors[2].desc));
                    392:
                    393:        nsclpcsio_tms_update(sc);
                    394: }
                    395:
                    396: void
                    397: nsclpcsio_tms_update(struct nsclpcsio_softc *sc)
                    398: {
                    399:        u_int8_t status;
                    400:        int8_t sdata;
                    401:        int i;
                    402:
                    403:        for (i = 0; i < 3; i++) {
                    404:                TMS_WRITE(sc, SIO_TMSBS, i);
                    405:                status = TMS_READ(sc, SIO_TCHCFST);
                    406:                if (!(status & 0x01)) {
                    407:                        DPRINTF(("%s: status %d: disabled\n",
                    408:                            sc->sensors[i].desc, status));
                    409:                        sc->sensors[i].value = 0;
                    410:                        continue;
                    411:                }
                    412:                sdata = TMS_READ(sc, SIO_RDCHT);
                    413:                DPRINTF(("%s: status %d C %d\n", sc->sensors[i].desc,
                    414:                    status, sdata));
                    415:                sc->sensors[i].value = sdata * 1000000 + 273150000;
                    416:        }
                    417: }
                    418:
                    419: void
                    420: nsclpcsio_vlm_init(struct nsclpcsio_softc *sc)
                    421: {
                    422:        int i;
                    423:        char *desc = NULL;
                    424:
                    425:        VLM_WRITE(sc, SIO_VLMCFG, 0x00);
                    426:
                    427:        /* Enable the sensors */
                    428:        for (i = 0; i < 14; i++) {
                    429:                VLM_WRITE(sc, SIO_VLMBS, i);
                    430:                VLM_WRITE(sc, SIO_VCHCFST, 0x01);
                    431:
                    432:                desc = NULL;
                    433:                switch (i) {
                    434:                case 7:
                    435:                        desc = "VSB";
                    436:                        break;
                    437:                case 8:
                    438:                        desc = "VDD";
                    439:                        break;
                    440:                case 9:
                    441:                        desc = "VBAT";
                    442:                        break;
                    443:                case 10:
                    444:                        desc = "AVDD";
                    445:                        break;
                    446:                case 11:
                    447:                        desc = "TS1";
                    448:                        break;
                    449:                case 12:
                    450:                        desc = "TS2";
                    451:                        break;
                    452:                case 13:
                    453:                        desc = "TS3";
                    454:                        break;
                    455:                }
                    456:                /* only init .desc if we have something meaningful to say */
                    457:                if (desc != NULL)
                    458:                        strlcpy(sc->sensors[SIO_VLM_OFF + i].desc, desc,
                    459:                            sizeof(sc->sensors[SIO_VLM_OFF + i].desc));
                    460:                sc->sensors[SIO_VLM_OFF + i].type = SENSOR_VOLTS_DC;
                    461:
                    462:        }
                    463:        nsclpcsio_vlm_update(sc);
                    464: }
                    465:
                    466: void
                    467: nsclpcsio_vlm_update(struct nsclpcsio_softc *sc)
                    468: {
                    469:        u_int8_t status;
                    470:        u_int8_t data;
                    471:        int scale, rfact, i;
                    472:
                    473:        for (i = 0; i < 14; i++) {
                    474:                VLM_WRITE(sc, SIO_VLMBS, i);
                    475:                status = VLM_READ(sc, SIO_VCHCFST);
                    476:                if (!(status & 0x01)) {
                    477:                        DPRINTF(("%s: status %d: disabled\n",
                    478:                            sc->sensors[SIO_VLM_OFF + i].desc, status));
                    479:                        sc->sensors[SIO_VLM_OFF + i].value = 0;
                    480:                        continue;
                    481:                }
                    482:                data = VLM_READ(sc, SIO_RDCHV);
                    483:                DPRINTF(("%s: status %d V %d\n",
                    484:                    sc->sensors[SIO_VLM_OFF + i].desc, status, data));
                    485:
                    486:                scale = 1;
                    487:                switch (i) {
                    488:                case 7:
                    489:                case 8:
                    490:                case 10:
                    491:                        scale = 2;
                    492:                }
                    493:
                    494:                /* Vi = (2.45±0.05)*VREF *RDCHVi / 256 */
                    495:                rfact = 10 * scale * ((245 * SIO_VREF) >> 8);
                    496:                sc->sensors[SIO_VLM_OFF + i].value = data * rfact;
                    497:        }
                    498: }
                    499:
                    500: static __inline void
                    501: nsclpcsio_gpio_pin_select(struct nsclpcsio_softc *sc, int pin)
                    502: {
                    503:        int port, shift;
                    504:        u_int8_t data;
                    505:
                    506:        port = pin / 8;
                    507:        shift = pin % 8;
                    508:        data = (port << 4) | shift;
                    509:
                    510:        nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, SIO_LDN_GPIO);
                    511:        nswrite(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINSEL, data);
                    512: }
                    513:
                    514: void
                    515: nsclpcsio_gpio_init(struct nsclpcsio_softc *sc)
                    516: {
                    517:        int i;
                    518:
                    519:        for (i = 0; i < SIO_GPIO_NPINS; i++) {
                    520:                sc->sc_gpio_pins[i].pin_num = i;
                    521:                sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT |
                    522:                    GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN |
                    523:                    GPIO_PIN_PUSHPULL | GPIO_PIN_TRISTATE |
                    524:                    GPIO_PIN_PULLUP;
                    525:
                    526:                /* Read initial state */
                    527:                sc->sc_gpio_pins[i].pin_state = nsclpcsio_gpio_pin_read(sc,
                    528:                    i) ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
                    529:        }
                    530:
                    531:        /* Create controller tag */
                    532:        sc->sc_gpio_gc.gp_cookie = sc;
                    533:        sc->sc_gpio_gc.gp_pin_read = nsclpcsio_gpio_pin_read;
                    534:        sc->sc_gpio_gc.gp_pin_write = nsclpcsio_gpio_pin_write;
                    535:        sc->sc_gpio_gc.gp_pin_ctl = nsclpcsio_gpio_pin_ctl;
                    536: }
                    537:
                    538: int
                    539: nsclpcsio_gpio_pin_read(void *arg, int pin)
                    540: {
                    541:        struct nsclpcsio_softc *sc = arg;
                    542:        int port, shift, reg;
                    543:        u_int8_t data;
                    544:
                    545:        port = pin / 8;
                    546:        shift = pin % 8;
                    547:
                    548:        switch (port) {
                    549:        case 0:
                    550:                reg = SIO_GPDI0;
                    551:                break;
                    552:        case 1:
                    553:                reg = SIO_GPDI1;
                    554:                break;
                    555:        case 2:
                    556:                reg = SIO_GPDI2;
                    557:                break;
                    558:        case 3:
                    559:                reg = SIO_GPDI3;
                    560:                break;
                    561:        }
                    562:
                    563:        data = GPIO_READ(sc, reg);
                    564:
                    565:        return ((data >> shift) & 0x1);
                    566: }
                    567:
                    568: void
                    569: nsclpcsio_gpio_pin_write(void *arg, int pin, int value)
                    570: {
                    571:        struct nsclpcsio_softc *sc = arg;
                    572:        int port, shift, reg;
                    573:        u_int8_t data;
                    574:
                    575:        port = pin / 8;
                    576:        shift = pin % 8;
                    577:
                    578:        switch (port) {
                    579:        case 0:
                    580:                reg = SIO_GPDO0;
                    581:                break;
                    582:        case 1:
                    583:                reg = SIO_GPDO1;
                    584:                break;
                    585:        case 2:
                    586:                reg = SIO_GPDO2;
                    587:                break;
                    588:        case 3:
                    589:                reg = SIO_GPDO3;
                    590:                break;
                    591:        }
                    592:
                    593:        data = GPIO_READ(sc, reg);
                    594:        if (value == 0)
                    595:                data &= ~(1 << shift);
                    596:        else if (value == 1)
                    597:                data |= (1 << shift);
                    598:
                    599:        GPIO_WRITE(sc, reg, data);
                    600: }
                    601:
                    602: void
                    603: nsclpcsio_gpio_pin_ctl(void *arg, int pin, int flags)
                    604: {
                    605:        struct nsclpcsio_softc *sc = arg;
                    606:        u_int8_t conf = 1;
                    607:
                    608:        nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, SIO_LDN_GPIO);
                    609:        nsclpcsio_gpio_pin_select(sc, pin);
                    610:        conf = nsread(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINCFG);
                    611:
                    612:        conf &= ~(SIO_GPIO_CONF_OUTPUTEN | SIO_GPIO_CONF_PUSHPULL |
                    613:            SIO_GPIO_CONF_PULLUP);
                    614:        if ((flags & GPIO_PIN_TRISTATE) == 0)
                    615:                conf |= SIO_GPIO_CONF_OUTPUTEN;
                    616:        if (flags & GPIO_PIN_PUSHPULL)
                    617:                conf |= SIO_GPIO_CONF_PUSHPULL;
                    618:        if (flags & GPIO_PIN_PULLUP)
                    619:                conf |= SIO_GPIO_CONF_PULLUP;
                    620:
                    621:        nswrite(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINCFG, conf);
                    622: }

CVSweb