root/dev/isa/nsclpcsio_isa.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nsread
  2. nswrite
  3. nsclpcsio_isa_match
  4. nsclpcsio_isa_attach
  5. nsclpcsio_refresh
  6. nsclpcsio_tms_init
  7. nsclpcsio_tms_update
  8. nsclpcsio_vlm_init
  9. nsclpcsio_vlm_update
  10. nsclpcsio_gpio_pin_select
  11. nsclpcsio_gpio_init
  12. nsclpcsio_gpio_pin_read
  13. nsclpcsio_gpio_pin_write
  14. nsclpcsio_gpio_pin_ctl

    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 }

/* [<][>][^][v][top][bottom][index][help] */