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

          Line data    Source code
       1             : /*      $OpenBSD: adt7460.c,v 1.21 2007/12/12 16:56:59 deraadt Exp $    */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2005 Mark Kettenis
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : #include <sys/param.h>
      20             : #include <sys/systm.h>
      21             : #include <sys/device.h>
      22             : #include <sys/sensors.h>
      23             : 
      24             : #include <dev/i2c/i2cvar.h>
      25             : 
      26             : /* ADT7460 registers */
      27             : #define ADT7460_2_5V            0x20
      28             : #define ADT7460_VCCP            0x21
      29             : #define ADT7460_VCC             0x22
      30             : #define ADT7460_V5              0x23
      31             : #define ADT7460_V12             0x24
      32             : #define ADT7460_VTR             0x99
      33             : #define ADT7460_VBAT            0x9a
      34             : #define ADT7460_REM1_TEMP       0x25
      35             : #define ADT7460_LOCAL_TEMP      0x26
      36             : #define ADT7460_REM2_TEMP       0x27
      37             : #define ADT7460_TACH1L          0x28
      38             : #define ADT7460_TACH1H          0x29
      39             : #define ADT7460_TACH2L          0x2a
      40             : #define ADT7460_TACH2H          0x2b
      41             : #define ADT7460_TACH3L          0x2c
      42             : #define ADT7460_TACH3H          0x2d
      43             : #define ADT7460_TACH4L          0x2e
      44             : #define ADT7460_TACH4H          0x2f
      45             : #define ADT7460_TACH5L          0xa9
      46             : #define ADT7460_TACH5H          0xaa
      47             : #define ADT7460_TACH6L          0xab
      48             : #define ADT7460_TACH6H          0xac
      49             : #define ADT7460_REVISION        0x3f
      50             : #define ADT7460_CONFIG          0x40
      51             : #define ADT7460_CONFIG_Vcc      0x80
      52             : 
      53             : /* Sensors */
      54             : #define ADT_2_5V                0
      55             : #define ADT_VCCP                1
      56             : #define ADT_VCC                 2
      57             : #define ADT_V5                  3
      58             : #define ADT_V12                 4
      59             : #define ADT_VTR                 5
      60             : #define ADT_VBAT                6
      61             : #define ADT_REM1_TEMP           7
      62             : #define ADT_LOCAL_TEMP          8
      63             : #define ADT_REM2_TEMP           9
      64             : #define ADT_TACH1               10
      65             : #define ADT_TACH2               11
      66             : #define ADT_TACH3               12
      67             : #define ADT_TACH4               13
      68             : #define ADT_TACH5               14
      69             : #define ADT_TACH6               15
      70             : #define ADT_NUM_SENSORS         16
      71             : 
      72             : struct adt_chip {
      73             :         const char      *name;
      74             :         short           ratio[7];
      75             :         int             type;
      76             :         short           vcc;
      77             : } adt_chips[] = {
      78             :         /* register     0x20  0x21  0x22  0x23  0x24  0xa8  0xaa        type    */
      79             :         /*              2.5v  vccp   vcc    5v   12v   vtr  vbat                */
      80             : 
      81             :         { "adt7460",  { 2500,    0, 3300,    0,     0,    0,    0 },  7460,   5000 },
      82             :         { "adt7467",  { 2500, 2250, 3300, 5000, 12000,    0,    0 },  7467,   5000 },
      83             :         { "adt7475",  {    0, 2250, 3300,    0,     0,    0,    0 },  7475,      0 },
      84             :         { "adt7476",  { 2500, 2250, 3300, 5000, 12000,    0,    0 },  7476,      0 },
      85             :         { "adm1027",  { 2500, 2250, 3300, 5000, 12000,    0,    0 },  1027,   5000 },
      86             :         { "lm85",     { 2500, 2250, 3300, 5000, 12000,    0,    0 },  7467,      0 },
      87             :         { "emc6d100", { 2500, 2250, 3300, 5000, 12000,    0,    0 },  6100,      0 },
      88             :         { "emc6w201", { 2500, 2250, 3300, 5000, 12000,    0,    0 },  6201,      0 },
      89             :         { "lm96000",  { 2500, 2250, 3300, 5000, 12000,    0,    0 },  96000,     0 },
      90             :         { "sch5017",  { 5000, 2250, 3300, 5000, 12000,    0,    0 },  5017,      0 },
      91             :         { "sch5027",  { 5000, 2250, 3300, 5000, 12000, 3300, 3300 },  5027,      0 }
      92             : };
      93             : 
      94             : struct {
      95             :         char            sensor;
      96             :         u_int8_t        cmd;
      97             :         u_short         index;
      98             : } worklist[] = {
      99             :         { ADT_2_5V, ADT7460_2_5V, 32768 + 0 },
     100             :         { ADT_VCCP, ADT7460_VCCP, 32768 + 1 },
     101             :         { ADT_VCC, ADT7460_VCC, 32768 + 2 },
     102             :         { ADT_V5, ADT7460_V5, 32768 + 3 },
     103             :         { ADT_V12, ADT7460_V12, 32768 + 4 },
     104             :         { ADT_VTR, ADT7460_VTR, 32768 + 5 },
     105             :         { ADT_VBAT, ADT7460_VBAT, 32768 + 6 },
     106             :         { ADT_REM1_TEMP, ADT7460_REM1_TEMP },
     107             :         { ADT_LOCAL_TEMP, ADT7460_LOCAL_TEMP },
     108             :         { ADT_REM2_TEMP, ADT7460_REM2_TEMP },
     109             :         { ADT_TACH1, ADT7460_TACH1L },
     110             :         { ADT_TACH2, ADT7460_TACH2L },
     111             :         { ADT_TACH3, ADT7460_TACH3L },
     112             :         { ADT_TACH4, ADT7460_TACH4L },
     113             :         { ADT_TACH5, ADT7460_TACH5L },
     114             :         { ADT_TACH6, ADT7460_TACH6L },
     115             : };
     116             : 
     117             : struct adt_softc {
     118             :         struct device sc_dev;
     119             :         i2c_tag_t sc_tag;
     120             :         i2c_addr_t sc_addr;
     121             :         u_int8_t sc_conf;
     122             :         struct adt_chip *chip;
     123             : 
     124             :         struct ksensor sc_sensor[ADT_NUM_SENSORS];
     125             :         struct ksensordev sc_sensordev;
     126             : };
     127             : 
     128             : int     adt_match(struct device *, void *, void *);
     129             : void    adt_attach(struct device *, struct device *, void *);
     130             : 
     131             : void    adt_refresh(void *);
     132             : 
     133             : struct cfattach adt_ca = {
     134             :         sizeof(struct adt_softc), adt_match, adt_attach
     135             : };
     136             : 
     137             : struct cfdriver adt_cd = {
     138             :         NULL, "adt", DV_DULL
     139             : };
     140             : 
     141             : int
     142           0 : adt_match(struct device *parent, void *match, void *aux)
     143             : {
     144           0 :         struct i2c_attach_args *ia = aux;
     145             :         int i;
     146             : 
     147           0 :         for (i = 0; i < sizeof(adt_chips) / sizeof(adt_chips[0]); i++)
     148           0 :                 if (strcmp(ia->ia_name, adt_chips[i].name) == 0)
     149           0 :                         return (1);
     150           0 :         return (0);
     151           0 : }
     152             : 
     153             : void
     154           0 : adt_attach(struct device *parent, struct device *self, void *aux)
     155             : {
     156           0 :         struct adt_softc *sc = (struct adt_softc *)self;
     157           0 :         struct i2c_attach_args *ia = aux;
     158           0 :         u_int8_t cmd, rev, data;
     159             :         int i;
     160             : 
     161           0 :         sc->sc_tag = ia->ia_tag;
     162           0 :         sc->sc_addr = ia->ia_addr;
     163             : 
     164           0 :         iic_acquire_bus(sc->sc_tag, 0);
     165             : 
     166           0 :         for (i = 0; i < sizeof(adt_chips) / sizeof(adt_chips[0]); i++) {
     167           0 :                 if (strcmp(ia->ia_name, adt_chips[i].name) == 0) {
     168           0 :                         sc->chip = &adt_chips[i];
     169           0 :                         break;
     170             :                 }
     171             :         }
     172             : 
     173           0 :         cmd = ADT7460_REVISION;
     174           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     175           0 :             sc->sc_addr, &cmd, sizeof cmd, &rev, sizeof rev, 0)) {
     176           0 :                 iic_release_bus(sc->sc_tag, 0);
     177           0 :                 printf(": cannot read REV register\n");
     178           0 :                 return;
     179             :         }
     180             : 
     181           0 :         cmd = ADT7460_CONFIG;
     182           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     183           0 :             sc->sc_addr, &cmd, sizeof cmd, &sc->sc_conf, sizeof sc->sc_conf, 0)) {
     184           0 :                 iic_release_bus(sc->sc_tag, 0);
     185           0 :                 printf(": cannot read config register\n");
     186           0 :                 return;
     187             :         }
     188             : 
     189           0 :         if (sc->chip->type == 7460) {
     190           0 :                 data = 1;
     191           0 :                 cmd = ADT7460_CONFIG;
     192           0 :                 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
     193           0 :                     sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
     194           0 :                         iic_release_bus(sc->sc_tag, 0);
     195           0 :                         printf(": cannot set control register\n");
     196           0 :                         return;
     197             :                 }
     198             :         }
     199             : 
     200           0 :         iic_release_bus(sc->sc_tag, 0);
     201             : 
     202           0 :         printf(": %s rev 0x%02x", ia->ia_name, rev);
     203             : 
     204             :         /* Initialize sensor data. */
     205           0 :         strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
     206             :             sizeof(sc->sc_sensordev.xname));
     207             : 
     208           0 :         sc->sc_sensor[ADT_2_5V].type = SENSOR_VOLTS_DC;
     209           0 :         strlcpy(sc->sc_sensor[ADT_2_5V].desc, "+2.5Vin",
     210             :             sizeof(sc->sc_sensor[ADT_2_5V].desc));
     211             :                 
     212           0 :         if (sc->chip->type == 5017)
     213           0 :                 strlcpy(sc->sc_sensor[ADT_2_5V].desc, "+5VTR",
     214             :                     sizeof(sc->sc_sensor[ADT_2_5V].desc));
     215           0 :         if (sc->chip->type == 5027)
     216           0 :                 strlcpy(sc->sc_sensor[ADT_2_5V].desc, "+5V",
     217             :                     sizeof(sc->sc_sensor[ADT_2_5V].desc));
     218             : 
     219           0 :         sc->sc_sensor[ADT_VCCP].type = SENSOR_VOLTS_DC;
     220           0 :         strlcpy(sc->sc_sensor[ADT_VCCP].desc, "Vccp",
     221             :             sizeof(sc->sc_sensor[ADT_VCCP].desc));
     222             : 
     223           0 :         sc->sc_sensor[ADT_VCC].type = SENSOR_VOLTS_DC;
     224           0 :         strlcpy(sc->sc_sensor[ADT_VCC].desc, "Vcc",
     225             :             sizeof(sc->sc_sensor[ADT_VCC].desc));
     226             : 
     227           0 :         sc->sc_sensor[ADT_V5].type = SENSOR_VOLTS_DC;
     228           0 :         strlcpy(sc->sc_sensor[ADT_V5].desc, "+5V",
     229             :             sizeof(sc->sc_sensor[ADT_V5].desc));
     230             : 
     231           0 :         sc->sc_sensor[ADT_V12].type = SENSOR_VOLTS_DC;
     232           0 :         strlcpy(sc->sc_sensor[ADT_V12].desc, "+12V",
     233             :             sizeof(sc->sc_sensor[ADT_V12].desc));
     234             : 
     235           0 :         sc->sc_sensor[ADT_VTR].type = SENSOR_VOLTS_DC;
     236           0 :         strlcpy(sc->sc_sensor[ADT_VTR].desc, "+Vtr",
     237             :             sizeof(sc->sc_sensor[ADT_VTR].desc));
     238             : 
     239           0 :         sc->sc_sensor[ADT_VBAT].type = SENSOR_VOLTS_DC;
     240           0 :         strlcpy(sc->sc_sensor[ADT_VBAT].desc, "+Vbat",
     241             :             sizeof(sc->sc_sensor[ADT_VBAT].desc));
     242             : 
     243           0 :         sc->sc_sensor[ADT_REM1_TEMP].type = SENSOR_TEMP;
     244           0 :         strlcpy(sc->sc_sensor[ADT_REM1_TEMP].desc, "Remote",
     245             :             sizeof(sc->sc_sensor[ADT_REM1_TEMP].desc));
     246             : 
     247           0 :         sc->sc_sensor[ADT_LOCAL_TEMP].type = SENSOR_TEMP;
     248           0 :         strlcpy(sc->sc_sensor[ADT_LOCAL_TEMP].desc, "Internal",
     249             :             sizeof(sc->sc_sensor[ADT_LOCAL_TEMP].desc));
     250             : 
     251           0 :         sc->sc_sensor[ADT_REM2_TEMP].type = SENSOR_TEMP;
     252           0 :         strlcpy(sc->sc_sensor[ADT_REM2_TEMP].desc, "Remote",
     253             :             sizeof(sc->sc_sensor[ADT_REM2_TEMP].desc));
     254             : 
     255           0 :         sc->sc_sensor[ADT_TACH1].type = SENSOR_FANRPM;
     256           0 :         sc->sc_sensor[ADT_TACH2].type = SENSOR_FANRPM;
     257           0 :         sc->sc_sensor[ADT_TACH3].type = SENSOR_FANRPM;
     258           0 :         sc->sc_sensor[ADT_TACH4].type = SENSOR_FANRPM;
     259           0 :         sc->sc_sensor[ADT_TACH5].type = SENSOR_FANRPM;
     260           0 :         sc->sc_sensor[ADT_TACH6].type = SENSOR_FANRPM;
     261             : 
     262           0 :         if (sensor_task_register(sc, adt_refresh, 5) == NULL) {
     263           0 :                 printf(", unable to register update task\n");
     264           0 :                 return;
     265             :         }
     266             : 
     267           0 :         for (i = 0; i < ADT_NUM_SENSORS; i++) {
     268           0 :                 if (worklist[i].index >= 32768 &&
     269           0 :                     sc->chip->ratio[worklist[i].index - 32768] == 0)
     270             :                         continue;
     271           0 :                 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
     272           0 :         }
     273           0 :         sensordev_install(&sc->sc_sensordev);
     274             : 
     275             : 
     276           0 :         printf("\n");
     277           0 : }
     278             : 
     279             : void
     280           0 : adt_refresh(void *arg)
     281             : {
     282           0 :         struct adt_softc *sc = arg;
     283           0 :         u_int8_t cmd, data, data2;
     284             :         u_int16_t fan;
     285             :         int i, ratio;
     286             : 
     287           0 :         iic_acquire_bus(sc->sc_tag, 0);
     288             : 
     289           0 :         for (i = 0; i < sizeof worklist / sizeof(worklist[0]); i++) {
     290             : 
     291           0 :                 if (worklist[i].index >= 32768) {
     292           0 :                         ratio = sc->chip->ratio[worklist[i].index - 32768];
     293           0 :                         if (ratio == 0) /* do not read a dead register */
     294             :                                 continue;
     295             :                 }
     296           0 :                 cmd = worklist[i].cmd;
     297           0 :                 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     298           0 :                     sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
     299           0 :                         sc->sc_sensor[i].flags |= SENSOR_FINVALID;
     300           0 :                         continue;
     301             :                 }
     302             : 
     303           0 :                 sc->sc_sensor[i].flags &= ~SENSOR_FINVALID;
     304           0 :                 switch (worklist[i].sensor) {
     305             :                 case ADT_VCC:
     306           0 :                         if (sc->chip->vcc && (sc->sc_conf & ADT7460_CONFIG_Vcc))
     307           0 :                                 ratio = sc->chip->vcc;
     308             :                         /* FALLTHROUGH */
     309             :                 case ADT_2_5V:
     310             :                 case ADT_VCCP:
     311             :                 case ADT_V5:
     312             :                 case ADT_V12:
     313             :                 case ADT_VTR:
     314             :                 case ADT_VBAT:
     315           0 :                         sc->sc_sensor[i].value = ratio * 1000 * (u_int)data / 192;
     316           0 :                         break;
     317             :                 case ADT_LOCAL_TEMP:
     318             :                 case ADT_REM1_TEMP:
     319             :                 case ADT_REM2_TEMP:
     320           0 :                         if (data == 0x80)
     321           0 :                                 sc->sc_sensor[i].flags |= SENSOR_FINVALID;
     322             :                         else
     323           0 :                                 sc->sc_sensor[i].value =
     324           0 :                                     (int8_t)data * 1000000 + 273150000;
     325             :                         break;
     326             :                 case ADT_TACH1:
     327             :                 case ADT_TACH2:
     328             :                 case ADT_TACH3:
     329             :                 case ADT_TACH4:
     330           0 :                         cmd = worklist[i].cmd + 1; /* TACHnH follows TACHnL */
     331           0 :                         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     332           0 :                             sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) {
     333           0 :                                 sc->sc_sensor[i].flags |= SENSOR_FINVALID;
     334           0 :                                 continue;
     335             :                         }
     336             : 
     337           0 :                         fan = data + (data2 << 8);
     338           0 :                         if (fan == 0 || fan == 0xffff)
     339           0 :                                 sc->sc_sensor[i].flags |= SENSOR_FINVALID;
     340             :                         else
     341           0 :                                 sc->sc_sensor[i].value = (90000 * 60) / fan;
     342             :                         break;
     343             :                 case ADT_TACH5:
     344             :                 case ADT_TACH6:
     345           0 :                         if (sc->chip->type != 5027) {
     346           0 :                                 sc->sc_sensor[i].flags |= SENSOR_FINVALID;
     347           0 :                                 break;  /* only 5027 has these fans? */
     348             :                         }
     349           0 :                         cmd = worklist[i].cmd + 1; /* TACHnH follows TACHnL */
     350           0 :                         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     351           0 :                             sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) {
     352           0 :                                 sc->sc_sensor[i].flags |= SENSOR_FINVALID;
     353           0 :                                 continue;
     354             :                         }
     355             : 
     356           0 :                         fan = data + (data2 << 8);
     357           0 :                         if (fan == 0 || fan == 0xffff)
     358           0 :                                 sc->sc_sensor[i].flags |= SENSOR_FINVALID;
     359             :                         else
     360           0 :                                 sc->sc_sensor[i].value = fan * 60;
     361             :                         break;
     362             :                 default:
     363           0 :                         sc->sc_sensor[i].flags |= SENSOR_FINVALID;
     364           0 :                         break;
     365             :                 }
     366             :         }
     367             : 
     368           0 :         iic_release_bus(sc->sc_tag, 0);
     369           0 : }

Generated by: LCOV version 1.13