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/ic/nslm7x.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 /*      $NetBSD: nslm7x.c,v 1.17 2002/11/15 14:55:41 ad Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Bill Squier.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: nslm7x.c,v 1.17 2002/11/15 14:55:41 ad Exp $");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/proc.h>
   46 #include <sys/device.h>
   47 #include <sys/malloc.h>
   48 #include <sys/errno.h>
   49 #include <sys/queue.h>
   50 #include <sys/lock.h>
   51 #include <sys/ioctl.h>
   52 #include <sys/conf.h>
   53 #include <sys/time.h>
   54 
   55 #include <machine/bus.h>
   56 
   57 #include <dev/isa/isareg.h>
   58 #include <dev/isa/isavar.h>
   59 
   60 #include <dev/sysmon/sysmonvar.h>
   61 
   62 #include <dev/ic/nslm7xvar.h>
   63 
   64 #include <machine/intr.h>
   65 #include <machine/bus.h>
   66 
   67 #if defined(LMDEBUG)
   68 #define DPRINTF(x)              do { printf x; } while (0)
   69 #else
   70 #define DPRINTF(x)
   71 #endif
   72 
   73 const struct envsys_range lm_ranges[] = {       /* sc->sensors sub-intervals */
   74                                         /* for each unit type */
   75         { 7, 7,    ENVSYS_STEMP   },
   76         { 8, 10,   ENVSYS_SFANRPM },
   77         { 1, 0,    ENVSYS_SVOLTS_AC },  /* None */
   78         { 0, 6,    ENVSYS_SVOLTS_DC },
   79         { 1, 0,    ENVSYS_SOHMS },      /* None */
   80         { 1, 0,    ENVSYS_SWATTS },     /* None */
   81         { 1, 0,    ENVSYS_SAMPS }       /* None */
   82 };
   83 
   84 
   85 static void setup_fan __P((struct lm_softc *, int, int));
   86 static void setup_temp __P((struct lm_softc *, int, int));
   87 static void wb_setup_volt __P((struct lm_softc *));
   88 
   89 int lm_match __P((struct lm_softc *));
   90 int wb_match __P((struct lm_softc *));
   91 int def_match __P((struct lm_softc *));
   92 void lm_common_match __P((struct lm_softc *));
   93 static int lm_generic_banksel __P((struct lm_softc *, int));
   94 
   95 static void generic_stemp __P((struct lm_softc *, struct envsys_tre_data *));
   96 static void generic_svolt __P((struct lm_softc *, struct envsys_tre_data *,
   97     struct envsys_basic_info *));
   98 static void generic_fanrpm __P((struct lm_softc *, struct envsys_tre_data *));
   99 
  100 void lm_refresh_sensor_data __P((struct lm_softc *));
  101 
  102 static void wb_svolt __P((struct lm_softc *));
  103 static void wb_stemp __P((struct lm_softc *, struct envsys_tre_data *, int));
  104 static void wb781_fanrpm __P((struct lm_softc *, struct envsys_tre_data *));
  105 static void wb_fanrpm __P((struct lm_softc *, struct envsys_tre_data *));
  106 
  107 void wb781_refresh_sensor_data __P((struct lm_softc *));
  108 void wb782_refresh_sensor_data __P((struct lm_softc *));
  109 void wb697_refresh_sensor_data __P((struct lm_softc *));
  110 
  111 int lm_gtredata __P((struct sysmon_envsys *, struct envsys_tre_data *));
  112 
  113 int generic_streinfo_fan __P((struct lm_softc *, struct envsys_basic_info *,
  114            int, struct envsys_basic_info *));
  115 int lm_streinfo __P((struct sysmon_envsys *, struct envsys_basic_info *));
  116 int wb781_streinfo __P((struct sysmon_envsys *, struct envsys_basic_info *));
  117 int wb782_streinfo __P((struct sysmon_envsys *, struct envsys_basic_info *));
  118 
  119 struct lm_chip {
  120         int (*chip_match) __P((struct lm_softc *));
  121 };
  122 
  123 struct lm_chip lm_chips[] = {
  124         { wb_match },
  125         { lm_match },
  126         { def_match } /* Must be last */
  127 };
  128 
  129 
  130 int
  131 lm_generic_banksel(lmsc, bank)
  132         struct lm_softc *lmsc;
  133         int bank;
  134 {
  135 
  136         (*lmsc->lm_writereg)(lmsc, WB_BANKSEL, bank);
  137         return (0);
  138 }
  139 
  140 
  141 /*
  142  * bus independent probe
  143  */
  144 int
  145 lm_probe(iot, ioh)
  146         bus_space_tag_t iot;
  147         bus_space_handle_t ioh;
  148 {
  149         u_int8_t cr;
  150         int rv;
  151 
  152         /* Check for some power-on defaults */
  153         bus_space_write_1(iot, ioh, LMC_ADDR, LMD_CONFIG);
  154 
  155         /* Perform LM78 reset */
  156         bus_space_write_1(iot, ioh, LMC_DATA, 0x80);
  157 
  158         /* XXX - Why do I have to reselect the register? */
  159         bus_space_write_1(iot, ioh, LMC_ADDR, LMD_CONFIG);
  160         cr = bus_space_read_1(iot, ioh, LMC_DATA);
  161 
  162         /* XXX - spec says *only* 0x08! */
  163         if ((cr == 0x08) || (cr == 0x01))
  164                 rv = 1;
  165         else
  166                 rv = 0;
  167 
  168         DPRINTF(("lm: rv = %d, cr = %x\n", rv, cr));
  169 
  170         return (rv);
  171 }
  172 
  173 
  174 /*
  175  * pre:  lmsc contains valid busspace tag and handle
  176  */
  177 void
  178 lm_attach(lmsc)
  179         struct lm_softc *lmsc;
  180 {
  181         u_int i;
  182 
  183         /* Install default bank selection routine, if none given. */
  184         if (lmsc->lm_banksel == NULL)
  185                 lmsc->lm_banksel = lm_generic_banksel;
  186 
  187         for (i = 0; i < sizeof(lm_chips) / sizeof(lm_chips[0]); i++)
  188                 if (lm_chips[i].chip_match(lmsc))
  189                         break;
  190 
  191         /* Start the monitoring loop */
  192         (*lmsc->lm_writereg)(lmsc, LMD_CONFIG, 0x01);
  193 
  194         /* Indicate we have never read the registers */
  195         timerclear(&lmsc->lastread);
  196 
  197         /* Initialize sensors */
  198         for (i = 0; i < lmsc->numsensors; ++i) {
  199                 lmsc->sensors[i].sensor = lmsc->info[i].sensor = i;
  200                 lmsc->sensors[i].validflags = (ENVSYS_FVALID|ENVSYS_FCURVALID);
  201                 lmsc->info[i].validflags = ENVSYS_FVALID;
  202                 lmsc->sensors[i].warnflags = ENVSYS_WARN_OK;
  203         }
  204         /*
  205          * Hook into the System Monitor.
  206          */
  207         lmsc->sc_sysmon.sme_ranges = lm_ranges;
  208         lmsc->sc_sysmon.sme_sensor_info = lmsc->info;
  209         lmsc->sc_sysmon.sme_sensor_data = lmsc->sensors;
  210         lmsc->sc_sysmon.sme_cookie = lmsc;
  211 
  212         lmsc->sc_sysmon.sme_gtredata = lm_gtredata;
  213         /* sme_streinfo set in chip-specific attach */
  214 
  215         lmsc->sc_sysmon.sme_nsensors = lmsc->numsensors;
  216         lmsc->sc_sysmon.sme_envsys_version = 1000;
  217 
  218         if (sysmon_envsys_register(&lmsc->sc_sysmon))
  219                 printf("%s: unable to register with sysmon\n",
  220                     lmsc->sc_dev.dv_xname);
  221 }
  222 
  223 int
  224 lm_match(sc)
  225         struct lm_softc *sc;
  226 {
  227         int i;
  228 
  229         /* See if we have an LM78 or LM79 */
  230         i = (*sc->lm_readreg)(sc, LMD_CHIPID) & LM_ID_MASK;
  231         switch(i) {
  232         case LM_ID_LM78:
  233                 printf(": LM78\n");
  234                 break;
  235         case LM_ID_LM78J:
  236                 printf(": LM78J\n");
  237                 break;
  238         case LM_ID_LM79:
  239                 printf(": LM79\n");
  240                 break;
  241         case LM_ID_LM81:
  242                 printf(": LM81\n");
  243                 break;
  244         default:
  245                 return 0;
  246         }
  247         lm_common_match(sc);
  248         return 1;
  249 }
  250 
  251 int
  252 def_match(sc)
  253         struct lm_softc *sc;
  254 {
  255         int i;
  256 
  257         i = (*sc->lm_readreg)(sc, LMD_CHIPID) & LM_ID_MASK;
  258         printf(": Unknown chip (ID %d)\n", i);
  259         lm_common_match(sc);
  260         return 1;
  261 }
  262 
  263 void
  264 lm_common_match(sc)
  265         struct lm_softc *sc;
  266 {
  267         int i;
  268         sc->numsensors = LM_NUM_SENSORS;
  269         sc->refresh_sensor_data = lm_refresh_sensor_data;
  270 
  271         for (i = 0; i < 7; ++i) {
  272                 sc->sensors[i].units = sc->info[i].units =
  273                     ENVSYS_SVOLTS_DC;
  274                 sprintf(sc->info[i].desc, "IN %d", i);
  275         }
  276 
  277         /* default correction factors for resistors on higher voltage inputs */
  278         sc->info[0].rfact = sc->info[1].rfact =
  279             sc->info[2].rfact = 10000;
  280         sc->info[3].rfact = (int)(( 90.9 / 60.4) * 10000);
  281         sc->info[4].rfact = (int)(( 38.0 / 10.0) * 10000);
  282         sc->info[5].rfact = (int)((210.0 / 60.4) * 10000);
  283         sc->info[6].rfact = (int)(( 90.9 / 60.4) * 10000);
  284 
  285         sc->sensors[7].units = ENVSYS_STEMP;
  286         strcpy(sc->info[7].desc, "Temp");
  287 
  288         setup_fan(sc, 8, 3);
  289         sc->sc_sysmon.sme_streinfo = lm_streinfo;
  290 }
  291 
  292 int
  293 wb_match(sc)
  294         struct lm_softc *sc;
  295 {
  296         int i, j;
  297 
  298         (*sc->lm_writereg)(sc, WB_BANKSEL, WB_BANKSEL_HBAC);
  299         j = (*sc->lm_readreg)(sc, WB_VENDID) << 8;
  300         (*sc->lm_writereg)(sc, WB_BANKSEL, 0);
  301         j |= (*sc->lm_readreg)(sc, WB_VENDID);
  302         DPRINTF(("winbond vend id 0x%x\n", j));
  303         if (j != WB_VENDID_WINBOND)
  304                 return 0;
  305         /* read device ID */
  306         (*sc->lm_banksel)(sc, 0);
  307         j = (*sc->lm_readreg)(sc, WB_BANK0_CHIPID);
  308         DPRINTF(("winbond chip id 0x%x\n", j));
  309         switch(j) {
  310         case WB_CHIPID_83781:
  311         case WB_CHIPID_83781_2:
  312                 printf(": W83781D\n");
  313 
  314                 for (i = 0; i < 7; ++i) {
  315                         sc->sensors[i].units = sc->info[i].units =
  316                             ENVSYS_SVOLTS_DC;
  317                         sprintf(sc->info[i].desc, "IN %d", i);
  318                 }
  319 
  320                 /* default correction factors for higher voltage inputs */
  321                 sc->info[0].rfact = sc->info[1].rfact =
  322                     sc->info[2].rfact = 10000;
  323                 sc->info[3].rfact = (int)(( 90.9 / 60.4) * 10000);
  324                 sc->info[4].rfact = (int)(( 38.0 / 10.0) * 10000);
  325                 sc->info[5].rfact = (int)((210.0 / 60.4) * 10000);
  326                 sc->info[6].rfact = (int)(( 90.9 / 60.4) * 10000);
  327 
  328                 setup_temp(sc, 7, 3);
  329                 setup_fan(sc, 10, 3);
  330 
  331                 sc->numsensors = WB83781_NUM_SENSORS;
  332                 sc->refresh_sensor_data = wb781_refresh_sensor_data;
  333                 sc->sc_sysmon.sme_streinfo = wb781_streinfo;
  334                 return 1;
  335         case WB_CHIPID_83697:
  336                 printf(": W83697HF\n");
  337                 wb_setup_volt(sc);
  338                 setup_temp(sc, 9, 2);
  339                 setup_fan(sc, 11, 3);
  340                 sc->numsensors = WB83697_NUM_SENSORS;
  341                 sc->refresh_sensor_data = wb697_refresh_sensor_data;
  342                 sc->sc_sysmon.sme_streinfo = wb782_streinfo;
  343                 return 1;
  344         case WB_CHIPID_83782:
  345                 printf(": W83782D\n");
  346                 break;
  347         case WB_CHIPID_83627:
  348                 printf(": W83627HF\n");
  349                 break;
  350         default:
  351                 printf(": unknow winbond chip ID 0x%x\n", j);
  352                 /* handle as a standart lm7x */
  353                 lm_common_match(sc);
  354                 return 1;
  355         }
  356         /* common code for the W83782D and W83627HF */
  357         wb_setup_volt(sc);
  358         setup_temp(sc, 9, 3);
  359         setup_fan(sc, 12, 3);
  360         sc->numsensors = WB_NUM_SENSORS;
  361         sc->refresh_sensor_data = wb782_refresh_sensor_data;
  362         sc->sc_sysmon.sme_streinfo = wb782_streinfo;
  363         return 1;
  364 }
  365 
  366 static void
  367 wb_setup_volt(sc)
  368         struct lm_softc *sc;
  369 {
  370         sc->sensors[0].units = sc->info[0].units = ENVSYS_SVOLTS_DC;
  371         sprintf(sc->info[0].desc, "VCORE A");
  372         sc->info[0].rfact = 10000;
  373         sc->sensors[1].units = sc->info[1].units = ENVSYS_SVOLTS_DC;
  374         sprintf(sc->info[1].desc, "VCORE B");
  375         sc->info[1].rfact = 10000;
  376         sc->sensors[2].units = sc->info[2].units = ENVSYS_SVOLTS_DC;
  377         sprintf(sc->info[2].desc, "+3.3V");
  378         sc->info[2].rfact = 10000;
  379         sc->sensors[3].units = sc->info[3].units = ENVSYS_SVOLTS_DC;
  380         sprintf(sc->info[3].desc, "+5V");
  381         sc->info[3].rfact = 16778;
  382         sc->sensors[4].units = sc->info[4].units = ENVSYS_SVOLTS_DC;
  383         sprintf(sc->info[4].desc, "+12V");
  384         sc->info[4].rfact = 38000;
  385         sc->sensors[5].units = sc->info[5].units = ENVSYS_SVOLTS_DC;
  386         sprintf(sc->info[5].desc, "-12V");
  387         sc->info[5].rfact = 10000;
  388         sc->sensors[6].units = sc->info[6].units = ENVSYS_SVOLTS_DC;
  389         sprintf(sc->info[6].desc, "-5V");
  390         sc->info[6].rfact = 10000;
  391         sc->sensors[7].units = sc->info[7].units = ENVSYS_SVOLTS_DC;
  392         sprintf(sc->info[7].desc, "+5VSB");
  393         sc->info[7].rfact = 15151;
  394         sc->sensors[8].units = sc->info[8].units = ENVSYS_SVOLTS_DC;
  395         sprintf(sc->info[8].desc, "VBAT");
  396         sc->info[8].rfact = 10000;
  397 }
  398 
  399 static void
  400 setup_temp(sc, start, n)
  401         struct lm_softc *sc;
  402         int start, n;
  403 {
  404         int i;
  405 
  406         for (i = 0; i < n; i++) {
  407                 sc->sensors[start + i].units = ENVSYS_STEMP;
  408                 sprintf(sc->info[start + i].desc, "Temp %d", i + 1);
  409         }
  410 }
  411 
  412 
  413 static void
  414 setup_fan(sc, start, n)
  415         struct lm_softc *sc;
  416         int start, n;
  417 {
  418         int i;
  419         for (i = 0; i < n; ++i) {
  420                 sc->sensors[start + i].units = ENVSYS_SFANRPM;
  421                 sc->info[start + i].units = ENVSYS_SFANRPM;
  422                 sprintf(sc->info[start + i].desc, "Fan %d", i + 1);
  423         }
  424 }
  425 
  426 int
  427 lm_gtredata(sme, tred)
  428          struct sysmon_envsys *sme;
  429          struct envsys_tre_data *tred;
  430 {
  431          static const struct timeval onepointfive = { 1, 500000 };
  432          struct timeval t;
  433          struct lm_softc *sc = sme->sme_cookie;
  434          int i, s;
  435 
  436          /* read new values at most once every 1.5 seconds */
  437          timeradd(&sc->lastread, &onepointfive, &t);
  438          s = splclock();
  439          i = timercmp(&mono_time, &t, >);
  440          if (i) {
  441                   sc->lastread.tv_sec  = mono_time.tv_sec;
  442                   sc->lastread.tv_usec = mono_time.tv_usec;
  443          }
  444          splx(s);
  445 
  446          if (i)
  447                   sc->refresh_sensor_data(sc);
  448 
  449          *tred = sc->sensors[tred->sensor];
  450 
  451          return (0);
  452 }
  453 
  454 int
  455 generic_streinfo_fan(sc, info, n, binfo)
  456         struct lm_softc *sc;
  457         struct envsys_basic_info *info;
  458         int n;
  459         struct envsys_basic_info *binfo;
  460 {
  461         u_int8_t sdata;
  462         int divisor;
  463 
  464         /* FAN1 and FAN2 can have divisors set, but not FAN3 */
  465         if ((sc->info[binfo->sensor].units == ENVSYS_SFANRPM)
  466             && (n < 2)) {
  467                 if (binfo->rpms == 0) {
  468                         binfo->validflags = 0;
  469                         return (0);
  470                 }
  471 
  472                 /* write back the nominal FAN speed  */
  473                 info->rpms = binfo->rpms;
  474 
  475                 /* 153 is the nominal FAN speed value */
  476                 divisor = 1350000 / (binfo->rpms * 153);
  477 
  478                 /* ...but we need lg(divisor) */
  479                 if (divisor <= 1)
  480                     divisor = 0;
  481                 else if (divisor <= 2)
  482                     divisor = 1;
  483                 else if (divisor <= 4)
  484                     divisor = 2;
  485                 else
  486                     divisor = 3;
  487 
  488                 /*
  489                  * FAN1 div is in bits <5:4>, FAN2 div is
  490                  * in <7:6>
  491                  */
  492                 sdata = (*sc->lm_readreg)(sc, LMD_VIDFAN);
  493                 if ( n == 0 ) {  /* FAN1 */
  494                     divisor <<= 4;
  495                     sdata = (sdata & 0xCF) | divisor;
  496                 } else { /* FAN2 */
  497                     divisor <<= 6;
  498                     sdata = (sdata & 0x3F) | divisor;
  499                 }
  500 
  501                 (*sc->lm_writereg)(sc, LMD_VIDFAN, sdata);
  502         }
  503         return (0);
  504 
  505 }
  506 
  507 int
  508 lm_streinfo(sme, binfo)
  509          struct sysmon_envsys *sme;
  510          struct envsys_basic_info *binfo;
  511 {
  512          struct lm_softc *sc = sme->sme_cookie;
  513 
  514          if (sc->info[binfo->sensor].units == ENVSYS_SVOLTS_DC)
  515                   sc->info[binfo->sensor].rfact = binfo->rfact;
  516          else {
  517                 if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) {
  518                         generic_streinfo_fan(sc, &sc->info[binfo->sensor],
  519                             binfo->sensor - 8, binfo);
  520                 }
  521                 memcpy(sc->info[binfo->sensor].desc, binfo->desc,
  522                     sizeof(sc->info[binfo->sensor].desc));
  523                 sc->info[binfo->sensor].desc[
  524                     sizeof(sc->info[binfo->sensor].desc) - 1] = '\0';
  525 
  526                 binfo->validflags = ENVSYS_FVALID;
  527          }
  528          return (0);
  529 }
  530 
  531 int
  532 wb781_streinfo(sme, binfo)
  533          struct sysmon_envsys *sme;
  534          struct envsys_basic_info *binfo;
  535 {
  536          struct lm_softc *sc = sme->sme_cookie;
  537          int divisor;
  538          u_int8_t sdata;
  539          int i;
  540 
  541          if (sc->info[binfo->sensor].units == ENVSYS_SVOLTS_DC)
  542                   sc->info[binfo->sensor].rfact = binfo->rfact;
  543          else {
  544                 if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) {
  545                         if (binfo->rpms == 0) {
  546                                 binfo->validflags = 0;
  547                                 return (0);
  548                         }
  549 
  550                         /* write back the nominal FAN speed  */
  551                         sc->info[binfo->sensor].rpms = binfo->rpms;
  552 
  553                         /* 153 is the nominal FAN speed value */
  554                         divisor = 1350000 / (binfo->rpms * 153);
  555 
  556                         /* ...but we need lg(divisor) */
  557                         for (i = 0; i < 7; i++) {
  558                                 if (divisor <= (1 << i))
  559                                         break;
  560                         }
  561                         divisor = i;
  562 
  563                         if (binfo->sensor == 10 || binfo->sensor == 11) {
  564                                 /*
  565                                  * FAN1 div is in bits <5:4>, FAN2 div
  566                                  * is in <7:6>
  567                                  */
  568                                 sdata = (*sc->lm_readreg)(sc, LMD_VIDFAN);
  569                                 if ( binfo->sensor == 10 ) {  /* FAN1 */
  570                                          sdata = (sdata & 0xCF) |
  571                                              ((divisor & 0x3) << 4);
  572                                 } else { /* FAN2 */
  573                                          sdata = (sdata & 0x3F) |
  574                                              ((divisor & 0x3) << 6);
  575                                 }
  576                                 (*sc->lm_writereg)(sc, LMD_VIDFAN, sdata);
  577                         } else {
  578                                 /* FAN3 is in WB_PIN <7:6> */
  579                                 sdata = (*sc->lm_readreg)(sc, WB_PIN);
  580                                 sdata = (sdata & 0x3F) |
  581                                      ((divisor & 0x3) << 6);
  582                                 (*sc->lm_writereg)(sc, WB_PIN, sdata);
  583                         }
  584                 }
  585                 memcpy(sc->info[binfo->sensor].desc, binfo->desc,
  586                     sizeof(sc->info[binfo->sensor].desc));
  587                 sc->info[binfo->sensor].desc[
  588                     sizeof(sc->info[binfo->sensor].desc) - 1] = '\0';
  589 
  590                 binfo->validflags = ENVSYS_FVALID;
  591          }
  592          return (0);
  593 }
  594 
  595 int
  596 wb782_streinfo(sme, binfo)
  597          struct sysmon_envsys *sme;
  598          struct envsys_basic_info *binfo;
  599 {
  600          struct lm_softc *sc = sme->sme_cookie;
  601          int divisor;
  602          u_int8_t sdata;
  603          int i;
  604 
  605          if (sc->info[binfo->sensor].units == ENVSYS_SVOLTS_DC)
  606                   sc->info[binfo->sensor].rfact = binfo->rfact;
  607          else {
  608                 if (sc->info[binfo->sensor].units == ENVSYS_SFANRPM) {
  609                         if (binfo->rpms == 0) {
  610                                 binfo->validflags = 0;
  611                                 return (0);
  612                         }
  613 
  614                         /* write back the nominal FAN speed  */
  615                         sc->info[binfo->sensor].rpms = binfo->rpms;
  616 
  617                         /* 153 is the nominal FAN speed value */
  618                         divisor = 1350000 / (binfo->rpms * 153);
  619 
  620                         /* ...but we need lg(divisor) */
  621                         for (i = 0; i < 7; i++) {
  622                                 if (divisor <= (1 << i))
  623                                         break;
  624                         }
  625                         divisor = i;
  626 
  627                         if (binfo->sensor == 12 || binfo->sensor == 13) {
  628                                 /*
  629                                  * FAN1 div is in bits <5:4>, FAN2 div
  630                                  * is in <7:6>
  631                                  */
  632                                 sdata = (*sc->lm_readreg)(sc, LMD_VIDFAN);
  633                                 if ( binfo->sensor == 12 ) {  /* FAN1 */
  634                                          sdata = (sdata & 0xCF) |
  635                                              ((divisor & 0x3) << 4);
  636                                 } else { /* FAN2 */
  637                                          sdata = (sdata & 0x3F) |
  638                                              ((divisor & 0x3) << 6);
  639                                 }
  640                                 (*sc->lm_writereg)(sc, LMD_VIDFAN, sdata);
  641                         } else {
  642                                 /* FAN3 is in WB_PIN <7:6> */
  643                                 sdata = (*sc->lm_readreg)(sc, WB_PIN);
  644                                 sdata = (sdata & 0x3F) |
  645                                      ((divisor & 0x3) << 6);
  646                                 (*sc->lm_writereg)(sc, WB_PIN, sdata);
  647                         }
  648                         /* Bit 2 of divisor is in WB_BANK0_FANBAT */
  649                         (*sc->lm_banksel)(sc, 0);
  650                         sdata = (*sc->lm_readreg)(sc, WB_BANK0_FANBAT);
  651                         sdata &= ~(0x20 << (binfo->sensor - 12));
  652                         sdata |= (divisor & 0x4) << (binfo->sensor - 9);
  653                         (*sc->lm_writereg)(sc, WB_BANK0_FANBAT, sdata);
  654                 }
  655 
  656                 memcpy(sc->info[binfo->sensor].desc, binfo->desc,
  657                     sizeof(sc->info[binfo->sensor].desc));
  658                 sc->info[binfo->sensor].desc[
  659                     sizeof(sc->info[binfo->sensor].desc) - 1] = '\0';
  660 
  661                 binfo->validflags = ENVSYS_FVALID;
  662         }
  663         return (0);
  664 }
  665 
  666 static void
  667 generic_stemp(sc, sensor)
  668         struct lm_softc *sc;
  669         struct envsys_tre_data *sensor;
  670 {
  671         int sdata = (*sc->lm_readreg)(sc, LMD_SENSORBASE + 7);
  672         DPRINTF(("sdata[temp] 0x%x\n", sdata));
  673         /* temp is given in deg. C, we convert to uK */
  674         sensor->cur.data_us = sdata * 1000000 + 273150000;
  675 }
  676 
  677 static void
  678 generic_svolt(sc, sensors, infos)
  679         struct lm_softc *sc;
  680         struct envsys_tre_data *sensors;
  681         struct envsys_basic_info *infos;
  682 {
  683         int i, sdata;
  684 
  685         for (i = 0; i < 7; i++) {
  686                 sdata = (*sc->lm_readreg)(sc, LMD_SENSORBASE + i);
  687                 DPRINTF(("sdata[volt%d] 0x%x\n", i, sdata));
  688                 /* voltage returned as (mV >> 4), we convert to uVDC */
  689                 sensors[i].cur.data_s = (sdata << 4);
  690                 /* rfact is (factor * 10^4) */
  691                 sensors[i].cur.data_s *= infos[i].rfact;
  692                 /* division by 10 gets us back to uVDC */
  693                 sensors[i].cur.data_s /= 10;
  694 
  695                 /* these two are negative voltages */
  696                 if ( (i == 5) || (i == 6) )
  697                         sensors[i].cur.data_s *= -1;
  698         }
  699 }
  700 
  701 static void
  702 generic_fanrpm(sc, sensors)
  703         struct lm_softc *sc;
  704         struct envsys_tre_data *sensors;
  705 {
  706         int i, sdata, divisor;
  707         for (i = 0; i < 3; i++) {
  708                 sdata = (*sc->lm_readreg)(sc, LMD_SENSORBASE + 8 + i);
  709                 DPRINTF(("sdata[fan%d] 0x%x\n", i, sdata));
  710                 if (i == 2)
  711                         divisor = 2;    /* Fixed divisor for FAN3 */
  712                 else if (i == 1)        /* Bits 7 & 6 of VID/FAN  */
  713                         divisor = ((*sc->lm_readreg)(sc, LMD_VIDFAN) >> 6) & 0x3;
  714                 else
  715                         divisor = ((*sc->lm_readreg)(sc, LMD_VIDFAN) >> 4) & 0x3;
  716 
  717                 if (sdata == 0xff || sdata == 0x00) {
  718                         sensors[i].cur.data_us = 0;
  719                 } else {
  720                         sensors[i].cur.data_us = 1350000 / (sdata << divisor);
  721                 }
  722         }
  723 }
  724 
  725 /*
  726  * pre:  last read occurred >= 1.5 seconds ago
  727  * post: sensors[] current data are the latest from the chip
  728  */
  729 void
  730 lm_refresh_sensor_data(sc)
  731         struct lm_softc *sc;
  732 {
  733         /* Refresh our stored data for every sensor */
  734         generic_stemp(sc, &sc->sensors[7]);
  735         generic_svolt(sc, &sc->sensors[0], &sc->info[0]);
  736         generic_fanrpm(sc, &sc->sensors[8]);
  737 }
  738 
  739 static void
  740 wb_svolt(sc)
  741         struct lm_softc *sc;
  742 {
  743         int i, sdata;
  744         for (i = 0; i < 9; ++i) {
  745                 if (i < 7) {
  746                         sdata = (*sc->lm_readreg)(sc, LMD_SENSORBASE + i);
  747                 } else {
  748                         /* from bank5 */
  749                         (*sc->lm_banksel)(sc, 5);
  750                         sdata = (*sc->lm_readreg)(sc, (i == 7) ?
  751                             WB_BANK5_5VSB : WB_BANK5_VBAT);
  752                 }
  753                 DPRINTF(("sdata[volt%d] 0x%x\n", i, sdata));
  754                 /* voltage returned as (mV >> 4), we convert to uV */
  755                 sdata =  sdata << 4;
  756                 /* special case for negative voltages */
  757                 if (i == 5) {
  758                         /*
  759                          * -12Vdc, assume Winbond recommended values for
  760                          * resistors
  761                          */
  762                         sdata = ((sdata * 1000) - (3600 * 805)) / 195;
  763                 } else if (i == 6) {
  764                         /*
  765                          * -5Vdc, assume Winbond recommended values for
  766                          * resistors
  767                          */
  768                         sdata = ((sdata * 1000) - (3600 * 682)) / 318;
  769                 }
  770                 /* rfact is (factor * 10^4) */
  771                 sc->sensors[i].cur.data_s = sdata * sc->info[i].rfact;
  772                 /* division by 10 gets us back to uVDC */
  773                 sc->sensors[i].cur.data_s /= 10;
  774         }
  775 }
  776 
  777 static void
  778 wb_stemp(sc, sensors, n)
  779         struct lm_softc *sc;
  780         struct  envsys_tre_data *sensors;
  781         int n;
  782 {
  783         int sdata;
  784         /* temperatures. Given in dC, we convert to uK */
  785         sdata = (*sc->lm_readreg)(sc, LMD_SENSORBASE + 7);
  786         DPRINTF(("sdata[temp0] 0x%x\n", sdata));
  787         sensors[0].cur.data_us = sdata * 1000000 + 273150000;
  788         /* from bank1 */
  789         if ((*sc->lm_banksel)(sc, 1))
  790                 sensors[1].validflags &= ~ENVSYS_FCURVALID;
  791         else {
  792                 sdata = (*sc->lm_readreg)(sc, WB_BANK1_T2H) << 1;
  793                 sdata |=  ((*sc->lm_readreg)(sc, WB_BANK1_T2L) & 0x80) >> 7;
  794                 DPRINTF(("sdata[temp1] 0x%x\n", sdata));
  795                 sensors[1].cur.data_us = (sdata * 1000000) / 2 + 273150000;
  796         }
  797         if (n < 3)
  798                 return;
  799         /* from bank2 */
  800         if ((*sc->lm_banksel)(sc, 2))
  801                 sensors[2].validflags &= ~ENVSYS_FCURVALID;
  802         else {
  803                 sdata = (*sc->lm_readreg)(sc, WB_BANK2_T3H) << 1;
  804                 sdata |=  ((*sc->lm_readreg)(sc, WB_BANK2_T3L) & 0x80) >> 7;
  805                 DPRINTF(("sdata[temp2] 0x%x\n", sdata));
  806                 sensors[2].cur.data_us = (sdata * 1000000) / 2 + 273150000;
  807         }
  808 }
  809 
  810 static void
  811 wb781_fanrpm(sc, sensors)
  812         struct lm_softc *sc;
  813         struct envsys_tre_data *sensors;
  814 {
  815         int i, divisor, sdata;
  816         (*sc->lm_banksel)(sc, 0);
  817         for (i = 0; i < 3; i++) {
  818                 sdata = (*sc->lm_readreg)(sc, LMD_SENSORBASE + i + 8);
  819                 DPRINTF(("sdata[fan%d] 0x%x\n", i, sdata));
  820                 if (i == 0)
  821                         divisor = ((*sc->lm_readreg)(sc, LMD_VIDFAN) >> 4) & 0x3;
  822                 else if (i == 1)
  823                         divisor = ((*sc->lm_readreg)(sc, LMD_VIDFAN) >> 6) & 0x3;
  824                 else
  825                         divisor = ((*sc->lm_readreg)(sc, WB_PIN) >> 6) & 0x3;
  826 
  827                 DPRINTF(("sdata[%d] 0x%x div 0x%x\n", i, sdata, divisor));
  828                 if (sdata == 0xff || sdata == 0x00) {
  829                         sensors[i].cur.data_us = 0;
  830                 } else {
  831                         sensors[i].cur.data_us = 1350000 /
  832                             (sdata << divisor);
  833                 }
  834         }
  835 }
  836 
  837 static void
  838 wb_fanrpm(sc, sensors)
  839         struct lm_softc *sc;
  840         struct envsys_tre_data *sensors;
  841 {
  842         int i, divisor, sdata;
  843         (*sc->lm_banksel)(sc, 0);
  844         for (i = 0; i < 3; i++) {
  845                 sdata = (*sc->lm_readreg)(sc, LMD_SENSORBASE + i + 8);
  846                 DPRINTF(("sdata[fan%d] 0x%x\n", i, sdata));
  847                 if (i == 0)
  848                         divisor = ((*sc->lm_readreg)(sc, LMD_VIDFAN) >> 4) & 0x3;
  849                 else if (i == 1)
  850                         divisor = ((*sc->lm_readreg)(sc, LMD_VIDFAN) >> 6) & 0x3;
  851                 else
  852                         divisor = ((*sc->lm_readreg)(sc, WB_PIN) >> 6) & 0x3;
  853                 divisor |= ((*sc->lm_readreg)(sc, WB_BANK0_FANBAT) >> (i + 3)) & 0x4;
  854 
  855                 DPRINTF(("sdata[%d] 0x%x div 0x%x\n", i, sdata, divisor));
  856                 if (sdata == 0xff || sdata == 0x00) {
  857                         sensors[i].cur.data_us = 0;
  858                 } else {
  859                         sensors[i].cur.data_us = 1350000 /
  860                             (sdata << divisor);
  861                 }
  862         }
  863 }
  864 
  865 void
  866 wb781_refresh_sensor_data(sc)
  867         struct lm_softc *sc;
  868 {
  869         /* Refresh our stored data for every sensor */
  870         /* we need to reselect bank0 to access common registers */
  871         (*sc->lm_banksel)(sc, 0);
  872         generic_svolt(sc, &sc->sensors[0], &sc->info[0]);
  873         (*sc->lm_banksel)(sc, 0);
  874         wb_stemp(sc, &sc->sensors[7], 3);
  875         (*sc->lm_banksel)(sc, 0);
  876         wb781_fanrpm(sc, &sc->sensors[10]);
  877 }
  878 
  879 void
  880 wb782_refresh_sensor_data(sc)
  881         struct lm_softc *sc;
  882 {
  883         /* Refresh our stored data for every sensor */
  884         wb_svolt(sc);
  885         wb_stemp(sc, &sc->sensors[9], 3);
  886         wb_fanrpm(sc, &sc->sensors[12]);
  887 }
  888 
  889 void
  890 wb697_refresh_sensor_data(sc)
  891         struct lm_softc *sc;
  892 {
  893         /* Refresh our stored data for every sensor */
  894         wb_svolt(sc);
  895         wb_stemp(sc, &sc->sensors[9], 2);
  896         wb_fanrpm(sc, &sc->sensors[11]);
  897 }

Cache object: d6e594d6cf574fef4502dff02042a52e


[ 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.