LCOV - code coverage report
Current view: top level - dev/isa - it.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 202 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 11 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: it.c,v 1.46 2015/03/14 03:38:47 jsg Exp $     */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2007-2008 Oleg Safiullin <form@pdp-11.org.ru>
       5             :  * Copyright (c) 2006-2007 Juan Romero Pardines <juan@xtrarom.org>
       6             :  * Copyright (c) 2003 Julien Bordet <zejames@greyhats.org>
       7             :  * 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 ``AS IS'' AND ANY EXPRESS OR
      19             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      20             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      21             :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      22             :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      23             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      24             :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      25             :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      26             :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      27             :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      28             :  */
      29             : 
      30             : #include <sys/param.h>
      31             : #include <sys/systm.h>
      32             : #include <sys/device.h>
      33             : #include <sys/sensors.h>
      34             : 
      35             : #include <machine/bus.h>
      36             : 
      37             : #include <dev/isa/isavar.h>
      38             : #include <dev/isa/itvar.h>
      39             : 
      40             : 
      41             : #if defined(ITDEBUG)
      42             : #define DPRINTF(x)              do { printf x; } while (0)
      43             : #else
      44             : #define DPRINTF(x)
      45             : #endif
      46             : 
      47             : 
      48             : int it_match(struct device *, void *, void *);
      49             : void it_attach(struct device *, struct device *, void *);
      50             : int it_activate(struct device *, int);
      51             : u_int8_t it_readreg(bus_space_tag_t, bus_space_handle_t, int);
      52             : void it_writereg(bus_space_tag_t, bus_space_handle_t, int, u_int8_t);
      53             : void it_enter(bus_space_tag_t, bus_space_handle_t, int);
      54             : void it_exit(bus_space_tag_t, bus_space_handle_t);
      55             : 
      56             : u_int8_t it_ec_readreg(struct it_softc *, int);
      57             : void it_ec_writereg(struct it_softc *, int, u_int8_t);
      58             : void it_ec_refresh(void *arg);
      59             : 
      60             : int it_wdog_cb(void *, int);
      61             : 
      62             : /*
      63             :  * IT87-compatible chips can typically measure voltages up to 4.096 V.
      64             :  * To measure higher voltages the input is attenuated with (external)
      65             :  * resistors.  Negative voltages are measured using a reference
      66             :  * voltage.  So we have to convert the sensor values back to real
      67             :  * voltages by applying the appropriate resistor factor.
      68             :  */
      69             : #define RFACT_NONE              10000
      70             : #define RFACT(x, y)             (RFACT_NONE * ((x) + (y)) / (y))
      71             : 
      72             : 
      73             : struct {
      74             :         enum sensor_type        type;
      75             :         const char              *desc;
      76             : } it_sensors[IT_EC_NUMSENSORS] = {
      77             : #define IT_TEMP_BASE            0
      78             : #define IT_TEMP_COUNT           3
      79             :         { SENSOR_TEMP,          NULL            },
      80             :         { SENSOR_TEMP,          NULL            },
      81             :         { SENSOR_TEMP,          NULL            },
      82             : 
      83             : #define IT_FAN_BASE             3
      84             : #define IT_FAN_COUNT            5
      85             :         { SENSOR_FANRPM,        NULL            },
      86             :         { SENSOR_FANRPM,        NULL            },
      87             :         { SENSOR_FANRPM,        NULL            },
      88             :         { SENSOR_FANRPM,        NULL            },
      89             :         { SENSOR_FANRPM,        NULL            },
      90             : 
      91             : #define IT_VOLT_BASE            8
      92             : #define IT_VOLT_COUNT           9
      93             :         { SENSOR_VOLTS_DC,      "VCORE_A"     },
      94             :         { SENSOR_VOLTS_DC,      "VCORE_B"     },
      95             :         { SENSOR_VOLTS_DC,      "+3.3V"               },
      96             :         { SENSOR_VOLTS_DC,      "+5V"         },
      97             :         { SENSOR_VOLTS_DC,      "+12V"                },
      98             :         { SENSOR_VOLTS_DC,      "-12V"                },
      99             :         { SENSOR_VOLTS_DC,      "-5V"         },
     100             :         { SENSOR_VOLTS_DC,      "+5VSB"               },
     101             :         { SENSOR_VOLTS_DC,      "VBAT"                }
     102             : };
     103             : 
     104             : /* rfact values for voltage sensors */
     105             : int it_vrfact[IT_VOLT_COUNT] = {
     106             :         RFACT_NONE,             /* VCORE_A      */
     107             :         RFACT_NONE,             /* VCORE_A      */
     108             :         RFACT_NONE,             /* +3.3V        */
     109             :         RFACT(68, 100),         /* +5V          */
     110             :         RFACT(30, 10),          /* +12V         */
     111             :         RFACT(83, 20),          /* -12V         */
     112             :         RFACT(21, 10),          /* -5V          */
     113             :         RFACT(68, 100),         /* +5VSB        */
     114             :         RFACT_NONE              /* VBAT         */
     115             : };
     116             : 
     117             : int it_fan_regs[] = {
     118             :         IT_EC_FAN_TAC1, IT_EC_FAN_TAC2, IT_EC_FAN_TAC3,
     119             :         IT_EC_FAN_TAC4_LSB, IT_EC_FAN_TAC5_LSB
     120             : };
     121             : 
     122             : int it_fan_ext_regs[] = {
     123             :         IT_EC_FAN_EXT_TAC1, IT_EC_FAN_EXT_TAC2, IT_EC_FAN_EXT_TAC3,
     124             :         IT_EC_FAN_TAC4_MSB, IT_EC_FAN_TAC5_MSB
     125             : };
     126             : 
     127             : LIST_HEAD(, it_softc) it_softc_list = LIST_HEAD_INITIALIZER(it_softc_list);
     128             : 
     129             : 
     130             : int
     131           0 : it_match(struct device *parent, void *match, void *aux)
     132             : {
     133           0 :         struct isa_attach_args *ia = aux;
     134             :         struct it_softc *sc;
     135           0 :         bus_space_handle_t ioh;
     136             :         int ec_iobase, found = 0;
     137             :         u_int16_t cr;
     138             : 
     139           0 :         if (ia->ipa_io[0].base != IO_IT1 && ia->ipa_io[0].base != IO_IT2)
     140           0 :                 return (0);
     141             : 
     142             :         /* map i/o space */
     143           0 :         if (bus_space_map(ia->ia_iot, ia->ipa_io[0].base, 2, 0, &ioh) != 0) {
     144             :                 DPRINTF(("it_match: can't map i/o space"));
     145           0 :                 return (0);
     146             :         }
     147             : 
     148             :         /* enter MB PnP mode */
     149           0 :         it_enter(ia->ia_iot, ioh, ia->ipa_io[0].base);
     150             : 
     151             :         /*
     152             :          * SMSC or similar SuperIO chips use 0x55 magic to enter PnP mode
     153             :          * and 0xaa to exit. These chips also enter PnP mode via ITE
     154             :          * `enter MB PnP mode' sequence, so force chip to exit PnP mode
     155             :          * if this is the case.
     156             :          */
     157           0 :         bus_space_write_1(ia->ia_iot, ioh, IT_IO_ADDR, 0xaa);
     158             : 
     159             :         /* get chip id */
     160           0 :         cr = it_readreg(ia->ia_iot, ioh, IT_CHIPID1) << 8;
     161           0 :         cr |= it_readreg(ia->ia_iot, ioh, IT_CHIPID2);
     162             : 
     163           0 :         switch (cr) {
     164             :         case IT_ID_8705:
     165             :         case IT_ID_8712:
     166             :         case IT_ID_8716:
     167             :         case IT_ID_8718:
     168             :         case IT_ID_8720:
     169             :         case IT_ID_8721:
     170             :         case IT_ID_8726:
     171             :         case IT_ID_8728:
     172             :         case IT_ID_8772:
     173             :                 /* get environment controller base address */
     174           0 :                 it_writereg(ia->ia_iot, ioh, IT_LDN, IT_EC_LDN);
     175           0 :                 ec_iobase = it_readreg(ia->ia_iot, ioh, IT_EC_MSB) << 8;
     176           0 :                 ec_iobase |= it_readreg(ia->ia_iot, ioh, IT_EC_LSB);
     177             : 
     178             :                 /* check if device already attached */
     179           0 :                 LIST_FOREACH(sc, &it_softc_list, sc_list)
     180           0 :                         if (sc->sc_ec_iobase == ec_iobase)
     181             :                                 break;
     182             : 
     183           0 :                 if (sc == NULL) {
     184           0 :                         ia->ipa_nio = 1;
     185           0 :                         ia->ipa_io[0].length = 2;
     186           0 :                         ia->ipa_nmem = ia->ipa_nirq = ia->ipa_ndrq = 0;
     187             :                         found++;
     188           0 :                 }
     189             : 
     190             :                 break;
     191             :         }
     192             : 
     193             :         /* exit MB PnP mode */
     194           0 :         it_exit(ia->ia_iot, ioh);
     195             : 
     196             :         /* unmap i/o space */
     197           0 :         bus_space_unmap(ia->ia_iot, ioh, 2);
     198             : 
     199           0 :         return (found);
     200           0 : }
     201             : 
     202             : void
     203           0 : it_attach(struct device *parent, struct device *self, void *aux)
     204             : {
     205           0 :         struct it_softc *sc = (void *)self;
     206           0 :         struct isa_attach_args *ia = aux;
     207             :         int i;
     208             : 
     209           0 :         sc->sc_iot = ia->ia_iot;
     210           0 :         sc->sc_iobase = ia->ipa_io[0].base;
     211           0 :         if (bus_space_map(sc->sc_iot, sc->sc_iobase, 2, 0, &sc->sc_ioh) != 0) {
     212           0 :                 printf(": can't map i/o space\n");
     213           0 :                 return;
     214             :         }
     215             : 
     216             :         /* enter MB PnP mode */
     217           0 :         it_enter(sc->sc_iot, sc->sc_ioh, sc->sc_iobase);
     218             : 
     219             :         /* get chip id and rev */
     220           0 :         sc->sc_chipid = it_readreg(sc->sc_iot, sc->sc_ioh, IT_CHIPID1) << 8;
     221           0 :         sc->sc_chipid |= it_readreg(sc->sc_iot, sc->sc_ioh, IT_CHIPID2);
     222           0 :         sc->sc_chiprev = it_readreg(sc->sc_iot, sc->sc_ioh, IT_CHIPREV) & 0x0f;
     223             : 
     224             :         /* get environment controller base address */
     225           0 :         it_writereg(sc->sc_iot, sc->sc_ioh, IT_LDN, IT_EC_LDN);
     226           0 :         sc->sc_ec_iobase = it_readreg(sc->sc_iot, sc->sc_ioh, IT_EC_MSB) << 8;
     227           0 :         sc->sc_ec_iobase |= it_readreg(sc->sc_iot, sc->sc_ioh, IT_EC_LSB);
     228             : 
     229             :         /* initialize watchdog timer */
     230           0 :         if (sc->sc_chipid != IT_ID_8705) {
     231           0 :                 it_writereg(sc->sc_iot, sc->sc_ioh, IT_LDN, IT_WDT_LDN);
     232           0 :                 it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_CSR, 0x00);
     233           0 :                 it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TCR, 0x00);
     234           0 :                 wdog_register(it_wdog_cb, sc);
     235           0 :         }
     236             : 
     237             :         /* exit MB PnP mode and unmap */
     238           0 :         it_exit(sc->sc_iot, sc->sc_ioh);
     239             : 
     240           0 :         LIST_INSERT_HEAD(&it_softc_list, sc, sc_list);
     241           0 :         printf(": IT%xF rev %X", sc->sc_chipid, sc->sc_chiprev);
     242             : 
     243           0 :         if (sc->sc_ec_iobase == 0) {
     244           0 :                 printf(", EC disabled\n");
     245           0 :                 return;
     246             :         }
     247             : 
     248           0 :         printf(", EC port 0x%x\n", sc->sc_ec_iobase);
     249             : 
     250             :         /* map environment controller i/o space */
     251           0 :         sc->sc_ec_iot = ia->ia_iot;
     252           0 :         if (bus_space_map(sc->sc_ec_iot, sc->sc_ec_iobase, 8, 0,
     253           0 :             &sc->sc_ec_ioh) != 0) {
     254           0 :                 printf("%s: can't map EC i/o space\n", sc->sc_dev.dv_xname);
     255           0 :                 return;
     256             :         }
     257             : 
     258             :         /* initialize sensor structures */
     259           0 :         for (i = 0; i < IT_EC_NUMSENSORS; i++) {
     260           0 :                 sc->sc_sensors[i].type = it_sensors[i].type;
     261             : 
     262           0 :                 if (it_sensors[i].desc != NULL)
     263           0 :                         strlcpy(sc->sc_sensors[i].desc, it_sensors[i].desc,
     264             :                             sizeof(sc->sc_sensors[i].desc));
     265             :         }
     266             : 
     267             :         /* register sensor update task */
     268           0 :         if (sensor_task_register(sc, it_ec_refresh, IT_EC_INTERVAL) == NULL) {
     269           0 :                 printf("%s: unable to register update task\n",
     270           0 :                     sc->sc_dev.dv_xname);
     271           0 :                 bus_space_unmap(sc->sc_ec_iot, sc->sc_ec_ioh, 8);
     272           0 :                 return;
     273             :         }
     274             : 
     275             :         /* use 16-bit FAN tachometer registers for newer chips */
     276           0 :         if (sc->sc_chipid != IT_ID_8705 && sc->sc_chipid != IT_ID_8712)
     277           0 :                 it_ec_writereg(sc, IT_EC_FAN_ECER,
     278           0 :                     it_ec_readreg(sc, IT_EC_FAN_ECER) | 0x07);
     279             : 
     280             :         /* activate monitoring */
     281           0 :         it_ec_writereg(sc, IT_EC_CFG,
     282           0 :             it_ec_readreg(sc, IT_EC_CFG) | IT_EC_CFG_START | IT_EC_CFG_INTCLR);
     283             : 
     284             :         /* initialize sensors */
     285           0 :         strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
     286             :             sizeof(sc->sc_sensordev.xname));
     287           0 :         for (i = 0; i < IT_EC_NUMSENSORS; i++)
     288           0 :                 sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
     289           0 :         sensordev_install(&sc->sc_sensordev);
     290           0 : }
     291             : 
     292             : int
     293           0 : it_activate(struct device *self, int act)
     294             : {
     295           0 :         switch (act) {
     296             :         case DVACT_POWERDOWN:
     297           0 :                 wdog_shutdown(self);
     298           0 :                 break;
     299             :         }
     300             : 
     301           0 :         return (0);
     302             : }
     303             : 
     304             : u_int8_t
     305           0 : it_readreg(bus_space_tag_t iot, bus_space_handle_t ioh, int r)
     306             : {
     307           0 :         bus_space_write_1(iot, ioh, IT_IO_ADDR, r);
     308           0 :         return (bus_space_read_1(iot, ioh, IT_IO_DATA));
     309             : }
     310             : 
     311             : void
     312           0 : it_writereg(bus_space_tag_t iot, bus_space_handle_t ioh, int r, u_int8_t v)
     313             : {
     314           0 :         bus_space_write_1(iot, ioh, IT_IO_ADDR, r);
     315           0 :         bus_space_write_1(iot, ioh, IT_IO_DATA, v);
     316           0 : }
     317             : 
     318             : void
     319           0 : it_enter(bus_space_tag_t iot, bus_space_handle_t ioh, int iobase)
     320             : {
     321           0 :         bus_space_write_1(iot, ioh, IT_IO_ADDR, 0x87);
     322           0 :         bus_space_write_1(iot, ioh, IT_IO_ADDR, 0x01);
     323           0 :         bus_space_write_1(iot, ioh, IT_IO_ADDR, 0x55);
     324           0 :         if (iobase == IO_IT1)
     325           0 :                 bus_space_write_1(iot, ioh, IT_IO_ADDR, 0x55);
     326             :         else
     327           0 :                 bus_space_write_1(iot, ioh, IT_IO_ADDR, 0xaa);
     328           0 : }
     329             : 
     330             : void
     331           0 : it_exit(bus_space_tag_t iot, bus_space_handle_t ioh)
     332             : {
     333           0 :         bus_space_write_1(iot, ioh, IT_IO_ADDR, IT_CCR);
     334           0 :         bus_space_write_1(iot, ioh, IT_IO_DATA, 0x02);
     335           0 : }
     336             : 
     337             : u_int8_t
     338           0 : it_ec_readreg(struct it_softc *sc, int r)
     339             : {
     340           0 :         bus_space_write_1(sc->sc_ec_iot, sc->sc_ec_ioh, IT_EC_ADDR, r);
     341           0 :         return (bus_space_read_1(sc->sc_ec_iot, sc->sc_ec_ioh, IT_EC_DATA));
     342             : }
     343             : 
     344             : void
     345           0 : it_ec_writereg(struct it_softc *sc, int r, u_int8_t v)
     346             : {
     347           0 :         bus_space_write_1(sc->sc_ec_iot, sc->sc_ec_ioh, IT_EC_ADDR, r);
     348           0 :         bus_space_write_1(sc->sc_ec_iot, sc->sc_ec_ioh, IT_EC_DATA, v);
     349           0 : }
     350             : 
     351             : void
     352           0 : it_ec_refresh(void *arg)
     353             : {
     354           0 :         struct it_softc *sc = arg;
     355             :         int i, sdata, divisor, odivisor, ndivisor;
     356             :         u_int8_t cr, ecr;
     357             : 
     358             :         /* refresh temp sensors */
     359           0 :         cr = it_ec_readreg(sc, IT_EC_ADC_TEMPER);
     360             : 
     361           0 :         for (i = 0; i < IT_TEMP_COUNT; i++) {
     362           0 :                 sc->sc_sensors[IT_TEMP_BASE + i].flags &=
     363             :                     SENSOR_FINVALID;
     364             : 
     365           0 :                 if (!(cr & (1 << i)) && !(cr & (1 << (i + 3)))) {
     366           0 :                         sc->sc_sensors[IT_TEMP_BASE + i].flags |=
     367             :                             SENSOR_FINVALID;
     368           0 :                         continue;
     369             :                 }
     370             : 
     371           0 :                 sdata = it_ec_readreg(sc, IT_EC_TEMPBASE + i);
     372             :                 /* convert to degF */
     373           0 :                 sc->sc_sensors[IT_TEMP_BASE + i].value =
     374           0 :                     sdata * 1000000 + 273150000;
     375           0 :         }
     376             : 
     377             :         /* refresh volt sensors */
     378           0 :         cr = it_ec_readreg(sc, IT_EC_ADC_VINER);
     379             : 
     380           0 :         for (i = 0; i < IT_VOLT_COUNT; i++) {
     381           0 :                 sc->sc_sensors[IT_VOLT_BASE + i].flags &=
     382             :                     SENSOR_FINVALID;
     383             : 
     384           0 :                 if ((i < 8) && !(cr & (1 << i))) {
     385           0 :                         sc->sc_sensors[IT_VOLT_BASE + i].flags |=
     386             :                             SENSOR_FINVALID;
     387           0 :                         continue;
     388             :                 }
     389             : 
     390           0 :                 sdata = it_ec_readreg(sc, IT_EC_VOLTBASE + i);
     391             :                 /* voltage returned as (mV >> 4) */
     392           0 :                 sc->sc_sensors[IT_VOLT_BASE + i].value = sdata << 4;
     393             :                 /* these two values are negative and formula is different */
     394           0 :                 if (i == 5 || i == 6)
     395           0 :                         sc->sc_sensors[IT_VOLT_BASE + i].value -= IT_EC_VREF;
     396             :                 /* rfact is (factor * 10^4) */
     397           0 :                 sc->sc_sensors[IT_VOLT_BASE + i].value *= it_vrfact[i];
     398             :                 /* division by 10 gets us back to uVDC */
     399           0 :                 sc->sc_sensors[IT_VOLT_BASE + i].value /= 10;
     400           0 :                 if (i == 5 || i == 6)
     401           0 :                         sc->sc_sensors[IT_VOLT_BASE + i].value +=
     402             :                             IT_EC_VREF * 1000;
     403             :         }
     404             : 
     405             :         /* refresh fan sensors */
     406           0 :         cr = it_ec_readreg(sc, IT_EC_FAN_MCR);
     407             : 
     408           0 :         if (sc->sc_chipid != IT_ID_8705 && sc->sc_chipid != IT_ID_8712) {
     409             :                 /* use 16-bit FAN tachometer registers */
     410           0 :                 ecr = it_ec_readreg(sc, IT_EC_FAN_ECER);
     411             : 
     412           0 :                 for (i = 0; i < IT_FAN_COUNT; i++) {
     413           0 :                         sc->sc_sensors[IT_FAN_BASE + i].flags &=
     414             :                             ~SENSOR_FINVALID;
     415             : 
     416           0 :                         if (i < 3 && !(cr & (1 << (i + 4)))) {
     417           0 :                                 sc->sc_sensors[IT_FAN_BASE + i].flags |=
     418             :                                     SENSOR_FINVALID;
     419           0 :                                 continue;
     420           0 :                         } else if (i > 2 && !(ecr & (1 << (i + 1)))) {
     421           0 :                                 sc->sc_sensors[IT_FAN_BASE + i].flags |=
     422             :                                     SENSOR_FINVALID;
     423           0 :                                 continue;
     424             :                         }
     425             : 
     426           0 :                         sdata = it_ec_readreg(sc, it_fan_regs[i]);
     427           0 :                         sdata |= it_ec_readreg(sc, it_fan_ext_regs[i]) << 8;
     428             : 
     429           0 :                         if (sdata == 0 || sdata == 0xffff)
     430           0 :                                 sc->sc_sensors[IT_FAN_BASE + i].value = 0;
     431             :                         else
     432           0 :                                 sc->sc_sensors[IT_FAN_BASE + i].value =
     433           0 :                                     675000 / sdata;
     434             :                 }
     435             :         } else {
     436             :                 /* use 8-bit FAN tachometer & FAN divisor registers */
     437             :                 odivisor = ndivisor = divisor =
     438           0 :                     it_ec_readreg(sc, IT_EC_FAN_DIV);
     439             : 
     440           0 :                 for (i = 0; i < IT_FAN_COUNT; i++) {
     441           0 :                         if (i > 2 || !(cr & (1 << (i + 4)))) {
     442           0 :                                 sc->sc_sensors[IT_FAN_BASE + i].flags |=
     443             :                                     SENSOR_FINVALID;
     444           0 :                                 continue;
     445             :                         }
     446             : 
     447           0 :                         sc->sc_sensors[IT_FAN_BASE + i].flags &=
     448             :                             ~SENSOR_FINVALID;
     449             : 
     450           0 :                         sdata = it_ec_readreg(sc, it_fan_regs[i]);
     451             : 
     452           0 :                         if (sdata == 0xff) {
     453           0 :                                 sc->sc_sensors[IT_FAN_BASE + i].value = 0;
     454             : 
     455           0 :                                 if (i == 2)
     456           0 :                                         ndivisor ^= 0x40;
     457             :                                 else {
     458           0 :                                         ndivisor &= ~(7 << (i * 3));
     459           0 :                                         ndivisor |= ((divisor + 1) & 7) <<
     460             :                                             (i * 3);
     461             :                                 }
     462           0 :                         } else if (sdata != 0) {
     463           0 :                                 if (i == 2)
     464           0 :                                         divisor = divisor & 1 ? 3 : 1;
     465           0 :                                 sc->sc_sensors[IT_FAN_BASE + i].value =
     466           0 :                                     1350000 / (sdata << (divisor & 7));
     467           0 :                         } else
     468           0 :                                 sc->sc_sensors[IT_FAN_BASE + i].value = 0;
     469             :                 }
     470             : 
     471           0 :                 if (ndivisor != odivisor)
     472           0 :                         it_ec_writereg(sc, IT_EC_FAN_DIV, ndivisor);
     473             :         }
     474           0 : }
     475             : 
     476             : int
     477           0 : it_wdog_cb(void *arg, int period)
     478             : {
     479           0 :         struct it_softc *sc = arg;
     480             :         int minutes = 0;
     481             : 
     482             :         /* enter MB PnP mode and select WDT device */
     483           0 :         it_enter(sc->sc_iot, sc->sc_ioh, sc->sc_iobase);
     484           0 :         it_writereg(sc->sc_iot, sc->sc_ioh, IT_LDN, IT_WDT_LDN);
     485             : 
     486             :         /* disable watchdog timer */
     487           0 :         it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TCR, 0x00);
     488             : 
     489             :         /* 1000s should be enough for everyone */
     490           0 :         if (period > 1000)
     491           0 :                 period = 1000;
     492           0 :         else if (period < 0)
     493           0 :                 period = 0;
     494             : 
     495           0 :         if (period > 0) {
     496             :                 /*
     497             :                  * Older IT8712F chips have 8-bit timeout counter.
     498             :                  * Use minutes for 16-bit values for these chips.
     499             :                  */
     500           0 :                 if (sc->sc_chipid == IT_ID_8712 && sc->sc_chiprev < 0x8 &&
     501           0 :                     period > 0xff) {
     502           0 :                         if (period % 60 >= 30)
     503           0 :                                 period += 60;
     504           0 :                         period /= 60;
     505             :                         minutes++;
     506           0 :                 }
     507             : 
     508             :                 /* set watchdog timeout (low byte) */
     509           0 :                 it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TMO_LSB,
     510           0 :                     period & 0xff);
     511             : 
     512           0 :                 if (minutes) {
     513             :                         /* enable watchdog timer */
     514           0 :                         it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TCR,
     515             :                             IT_WDT_TCR_KRST | IT_WDT_TCR_PWROK);
     516             : 
     517           0 :                         period *= 60;
     518           0 :                 } else {
     519             :                         /* set watchdog timeout (high byte) */
     520           0 :                         it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TMO_MSB,
     521           0 :                             period >> 8);
     522             : 
     523             :                         /* enable watchdog timer */
     524           0 :                         it_writereg(sc->sc_iot, sc->sc_ioh, IT_WDT_TCR,
     525             :                             IT_WDT_TCR_SECS | IT_WDT_TCR_KRST |
     526             :                             IT_WDT_TCR_PWROK);
     527             :                 }
     528             :         }
     529             : 
     530             :         /* exit MB PnP mode */
     531           0 :         it_exit(sc->sc_iot, sc->sc_ioh);
     532             : 
     533           0 :         return (period);
     534             : }
     535             : 
     536             : 
     537             : struct cfattach it_ca = {
     538             :         sizeof(struct it_softc),
     539             :         it_match,
     540             :         it_attach,
     541             :         NULL,
     542             :         it_activate
     543             : };
     544             : 
     545             : struct cfdriver it_cd = {
     546             :         NULL, "it", DV_DULL
     547             : };

Generated by: LCOV version 1.13