The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/isa/nsclpcsio_isa.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $OpenBSD: nsclpcsio_isa.c,v 1.15 2022/04/06 18:59:28 naddy 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 const 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         int iobase;
  283         int i;
  284 
  285         iobase = ia->ipa_io[0].base;
  286         sc->sc_iot = ia->ia_iot;
  287         if (bus_space_map(ia->ia_iot, iobase, 2, 0, &sc->sc_ioh)) {
  288                 printf(": can't map i/o space\n");
  289                 return;
  290         }
  291         printf(": NSC PC87366 rev %d:",
  292             nsread(sc->sc_iot, sc->sc_ioh, SIO_REG_SRID));
  293 
  294         /* Configure all supported logical devices */
  295         for (i = 0; i < sizeof(sio_ld) / sizeof(sio_ld[0]); i++) {
  296                 sc->sc_ld_en[sio_ld[i].ld_num] = 0;
  297 
  298                 /* Select the device and check if it's activated */
  299                 nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, sio_ld[i].ld_num);
  300                 if ((nsread(sc->sc_iot, sc->sc_ioh,
  301                     SIO_REG_ACTIVE) & SIO_ACTIVE_EN) == 0)
  302                         continue;
  303 
  304                 /* Map I/O space if necessary */
  305                 if (sio_ld[i].ld_iosize != 0) {
  306                         iobase = (nsread(sc->sc_iot, sc->sc_ioh,
  307                             SIO_REG_IO_MSB) << 8);
  308                         iobase |= nsread(sc->sc_iot, sc->sc_ioh,
  309                             SIO_REG_IO_LSB);
  310                         if (bus_space_map(sc->sc_iot, iobase,
  311                             sio_ld[i].ld_iosize, 0,
  312                             &sc->sc_ld_ioh[sio_ld[i].ld_num]))
  313                                 continue;
  314                 }
  315 
  316                 sc->sc_ld_en[sio_ld[i].ld_num] = 1;
  317                 printf(" %s", sio_ld[i].ld_name);
  318         }
  319 
  320         printf("\n");
  321 
  322         nsclpcsio_gpio_init(sc);
  323         nsclpcsio_tms_init(sc);
  324         nsclpcsio_vlm_init(sc);
  325 
  326         /* Hook into hw.sensors sysctl */
  327         strlcpy(sc->sensordev.xname, sc->sc_dev.dv_xname,
  328             sizeof(sc->sensordev.xname));
  329         for (i = 0; i < SIO_NUM_SENSORS; i++) {
  330                 if (i < SIO_VLM_OFF && !sc->sc_ld_en[SIO_LDN_TMS])
  331                         continue;
  332                 if (i >= SIO_VLM_OFF && !sc->sc_ld_en[SIO_LDN_VLM])
  333                         continue;
  334                 sensor_attach(&sc->sensordev, &sc->sensors[i]);
  335         }
  336         sensordev_install(&sc->sensordev);
  337         if (sc->sc_ld_en[SIO_LDN_TMS] || sc->sc_ld_en[SIO_LDN_VLM]) {
  338                 timeout_set(&nsclpcsio_timeout, nsclpcsio_refresh, sc);
  339                 timeout_add_sec(&nsclpcsio_timeout, 2);
  340         }
  341 
  342         /* Attach GPIO framework */
  343         if (sc->sc_ld_en[SIO_LDN_GPIO]) {
  344                 gba.gba_name = "gpio";
  345                 gba.gba_gc = &sc->sc_gpio_gc;
  346                 gba.gba_pins = sc->sc_gpio_pins;
  347                 gba.gba_npins = SIO_GPIO_NPINS;
  348                 config_found(&sc->sc_dev, &gba, NULL);
  349         }
  350 }
  351 
  352 void
  353 nsclpcsio_refresh(void *arg)
  354 {
  355         struct nsclpcsio_softc *sc = (struct nsclpcsio_softc *)arg;
  356 
  357         if (sc->sc_ld_en[SIO_LDN_TMS])
  358                 nsclpcsio_tms_update(sc);
  359         if (sc->sc_ld_en[SIO_LDN_VLM])
  360                 nsclpcsio_vlm_update(sc);
  361         timeout_add_sec(&nsclpcsio_timeout, 2);
  362 }
  363 
  364 void
  365 nsclpcsio_tms_init(struct nsclpcsio_softc *sc)
  366 {
  367         int i;
  368 
  369         /* Initialisation, PC87366.pdf, page 208 */
  370         TMS_WRITE(sc, 0x08, 0x00);
  371         TMS_WRITE(sc, 0x09, 0x0f);
  372         TMS_WRITE(sc, 0x0a, 0x08);
  373         TMS_WRITE(sc, 0x0b, 0x04);
  374         TMS_WRITE(sc, 0x0c, 0x35);
  375         TMS_WRITE(sc, 0x0d, 0x05);
  376         TMS_WRITE(sc, 0x0e, 0x05);
  377 
  378         TMS_WRITE(sc, SIO_TMSCFG, 0x00);
  379 
  380         /* Enable the sensors */
  381         for (i = 0; i < 3; i++) {
  382                 TMS_WRITE(sc, SIO_TMSBS, i);
  383                 TMS_WRITE(sc, SIO_TCHCFST, 0x01);
  384 
  385                 sc->sensors[i].type = SENSOR_TEMP;
  386         }
  387 
  388         strlcpy(sc->sensors[0].desc, "Remote", sizeof(sc->sensors[0].desc));
  389         strlcpy(sc->sensors[1].desc, "Remote", sizeof(sc->sensors[1].desc));
  390         strlcpy(sc->sensors[2].desc, "Local", sizeof(sc->sensors[2].desc));
  391 
  392         nsclpcsio_tms_update(sc);
  393 }
  394 
  395 void
  396 nsclpcsio_tms_update(struct nsclpcsio_softc *sc)
  397 {
  398         u_int8_t status;
  399         int8_t sdata;
  400         int i;
  401 
  402         for (i = 0; i < 3; i++) {
  403                 TMS_WRITE(sc, SIO_TMSBS, i);
  404                 status = TMS_READ(sc, SIO_TCHCFST);
  405                 if (!(status & 0x01)) {
  406                         DPRINTF(("%s: status %d: disabled\n",
  407                             sc->sensors[i].desc, status));
  408                         sc->sensors[i].value = 0;
  409                         continue;
  410                 }
  411                 sdata = TMS_READ(sc, SIO_RDCHT);
  412                 DPRINTF(("%s: status %d C %d\n", sc->sensors[i].desc,
  413                     status, sdata));
  414                 sc->sensors[i].value = sdata * 1000000 + 273150000;
  415         }
  416 }
  417 
  418 void
  419 nsclpcsio_vlm_init(struct nsclpcsio_softc *sc)
  420 {
  421         int i;
  422         char *desc = NULL;
  423 
  424         VLM_WRITE(sc, SIO_VLMCFG, 0x00);
  425 
  426         /* Enable the sensors */
  427         for (i = 0; i < 14; i++) {
  428                 VLM_WRITE(sc, SIO_VLMBS, i);
  429                 VLM_WRITE(sc, SIO_VCHCFST, 0x01);
  430 
  431                 desc = NULL;
  432                 switch (i) {
  433                 case 7:
  434                         desc = "VSB";
  435                         break;
  436                 case 8:
  437                         desc = "VDD";
  438                         break;
  439                 case 9:
  440                         desc = "VBAT";
  441                         break;
  442                 case 10:
  443                         desc = "AVDD";
  444                         break;
  445                 case 11:
  446                         desc = "TS1";
  447                         break;
  448                 case 12:
  449                         desc = "TS2";
  450                         break;
  451                 case 13:
  452                         desc = "TS3";
  453                         break;
  454                 }
  455                 /* only init .desc if we have something meaningful to say */
  456                 if (desc != NULL)
  457                         strlcpy(sc->sensors[SIO_VLM_OFF + i].desc, desc,
  458                             sizeof(sc->sensors[SIO_VLM_OFF + i].desc));
  459                 sc->sensors[SIO_VLM_OFF + i].type = SENSOR_VOLTS_DC;
  460 
  461         }
  462         nsclpcsio_vlm_update(sc);
  463 }
  464 
  465 void
  466 nsclpcsio_vlm_update(struct nsclpcsio_softc *sc)
  467 {
  468         u_int8_t status;
  469         u_int8_t data;
  470         int scale, rfact, i;
  471 
  472         for (i = 0; i < 14; i++) {
  473                 VLM_WRITE(sc, SIO_VLMBS, i);
  474                 status = VLM_READ(sc, SIO_VCHCFST);
  475                 if (!(status & 0x01)) {
  476                         DPRINTF(("%s: status %d: disabled\n",
  477                             sc->sensors[SIO_VLM_OFF + i].desc, status));
  478                         sc->sensors[SIO_VLM_OFF + i].value = 0;
  479                         continue;
  480                 }
  481                 data = VLM_READ(sc, SIO_RDCHV);
  482                 DPRINTF(("%s: status %d V %d\n",
  483                     sc->sensors[SIO_VLM_OFF + i].desc, status, data));
  484 
  485                 scale = 1;
  486                 switch (i) {
  487                 case 7:
  488                 case 8:
  489                 case 10:
  490                         scale = 2;
  491                 }
  492 
  493                 /* Vi = (2.45±0.05)*VREF *RDCHVi / 256 */
  494                 rfact = 10 * scale * ((245 * SIO_VREF) >> 8);
  495                 sc->sensors[SIO_VLM_OFF + i].value = data * rfact;
  496         }
  497 }
  498 
  499 static __inline void
  500 nsclpcsio_gpio_pin_select(struct nsclpcsio_softc *sc, int pin)
  501 {
  502         int port, shift;
  503         u_int8_t data;
  504 
  505         port = pin / 8;
  506         shift = pin % 8;
  507         data = (port << 4) | shift;
  508 
  509         nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, SIO_LDN_GPIO);
  510         nswrite(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINSEL, data);
  511 }
  512 
  513 void
  514 nsclpcsio_gpio_init(struct nsclpcsio_softc *sc)
  515 {
  516         int i;
  517 
  518         for (i = 0; i < SIO_GPIO_NPINS; i++) {
  519                 sc->sc_gpio_pins[i].pin_num = i;
  520                 sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT |
  521                     GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN |
  522                     GPIO_PIN_PUSHPULL | GPIO_PIN_TRISTATE |
  523                     GPIO_PIN_PULLUP;
  524 
  525                 /* Read initial state */
  526                 sc->sc_gpio_pins[i].pin_state = nsclpcsio_gpio_pin_read(sc,
  527                     i) ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
  528         }
  529 
  530         /* Create controller tag */
  531         sc->sc_gpio_gc.gp_cookie = sc;
  532         sc->sc_gpio_gc.gp_pin_read = nsclpcsio_gpio_pin_read;
  533         sc->sc_gpio_gc.gp_pin_write = nsclpcsio_gpio_pin_write;
  534         sc->sc_gpio_gc.gp_pin_ctl = nsclpcsio_gpio_pin_ctl;
  535 }
  536 
  537 int
  538 nsclpcsio_gpio_pin_read(void *arg, int pin)
  539 {
  540         struct nsclpcsio_softc *sc = arg;
  541         int port, shift, reg;
  542         u_int8_t data;
  543 
  544         port = pin / 8;
  545         shift = pin % 8;
  546 
  547         switch (port) {
  548         case 0:
  549                 reg = SIO_GPDI0;
  550                 break;
  551         case 1:
  552                 reg = SIO_GPDI1;
  553                 break;
  554         case 2:
  555                 reg = SIO_GPDI2;
  556                 break;
  557         case 3:
  558                 reg = SIO_GPDI3;
  559                 break;
  560         }
  561 
  562         data = GPIO_READ(sc, reg);
  563 
  564         return ((data >> shift) & 0x1);
  565 }
  566 
  567 void
  568 nsclpcsio_gpio_pin_write(void *arg, int pin, int value)
  569 {
  570         struct nsclpcsio_softc *sc = arg;
  571         int port, shift, reg;
  572         u_int8_t data;
  573 
  574         port = pin / 8;
  575         shift = pin % 8;
  576 
  577         switch (port) {
  578         case 0:
  579                 reg = SIO_GPDO0;
  580                 break;
  581         case 1:
  582                 reg = SIO_GPDO1;
  583                 break;
  584         case 2:
  585                 reg = SIO_GPDO2;
  586                 break;
  587         case 3:
  588                 reg = SIO_GPDO3;
  589                 break;
  590         }
  591 
  592         data = GPIO_READ(sc, reg);
  593         if (value == 0)
  594                 data &= ~(1 << shift);
  595         else if (value == 1)
  596                 data |= (1 << shift);
  597 
  598         GPIO_WRITE(sc, reg, data);
  599 }
  600 
  601 void
  602 nsclpcsio_gpio_pin_ctl(void *arg, int pin, int flags)
  603 {
  604         struct nsclpcsio_softc *sc = arg;
  605         u_int8_t conf = 1;
  606 
  607         nswrite(sc->sc_iot, sc->sc_ioh, SIO_REG_LDN, SIO_LDN_GPIO);
  608         nsclpcsio_gpio_pin_select(sc, pin);
  609         conf = nsread(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINCFG);
  610 
  611         conf &= ~(SIO_GPIO_CONF_OUTPUTEN | SIO_GPIO_CONF_PUSHPULL |
  612             SIO_GPIO_CONF_PULLUP);
  613         if ((flags & GPIO_PIN_TRISTATE) == 0)
  614                 conf |= SIO_GPIO_CONF_OUTPUTEN;
  615         if (flags & GPIO_PIN_PUSHPULL)
  616                 conf |= SIO_GPIO_CONF_PUSHPULL;
  617         if (flags & GPIO_PIN_PULLUP)
  618                 conf |= SIO_GPIO_CONF_PULLUP;
  619 
  620         nswrite(sc->sc_iot, sc->sc_ioh, SIO_GPIO_PINCFG, conf);
  621 }

Cache object: 3ba97169e17aab0fe8765a1157dbd967


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.