LCOV - code coverage report
Current view: top level - dev/i2c - asc7621.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 65 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: asc7621.c,v 1.4 2007/10/31 20:46:17 cnst Exp $        */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2007 Mike Belopuhov
       5             :  * Copyright (c) 2007 Theo de Raadt
       6             :  *
       7             :  * Permission to use, copy, modify, and distribute this software for any
       8             :  * purpose with or without fee is hereby granted, provided that the above
       9             :  * copyright notice and this permission notice appear in all copies.
      10             :  *
      11             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      12             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      13             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      14             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      15             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      16             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      17             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      18             :  */
      19             : 
      20             : #include <sys/param.h>
      21             : #include <sys/systm.h>
      22             : #include <sys/device.h>
      23             : #include <sys/sensors.h>
      24             : 
      25             : #include <dev/i2c/i2cvar.h>
      26             : 
      27             : /* ASC7621 registers */
      28             : 
      29             : #define ASC7621_PECI            0x40    /* Check for PECI monitoring */
      30             : #define ASC7621_PECI_MASK       0x10    /* 00010000 */
      31             : 
      32             : #define ASC7621_LEGACY          0x36    /* Check for legacy mode */
      33             : #define ASC7621_LEGACY_MASK     0x10    /* 00010000 */
      34             : 
      35             : #define ASC7621_TEMP1H          0x25    /* Zone 1 Temperature (MS Byte) */
      36             : #define ASC7621_TEMP1L          0x10    /* Zone 1 Temperature (LS Byte) */
      37             : #define ASC7621_TEMP2H          0x26    /* Zone 2 Temperature (MS Byte) */
      38             : #define ASC7621_TEMP2L          0x15    /* Zone 2 Temperature (LS Byte) */
      39             : #define ASC7621_TEMP3H          0x27    /* Zone 3 Temperature (MS Byte) */
      40             : #define ASC7621_TEMP3L          0x16    /* Zone 3 Temperature (LS Byte) */
      41             : #define ASC7621_TEMP4H          0x33    /* Zone 4 Temperature (MS Byte) */
      42             : #define ASC7621_TEMP4L          0x17    /* Zone 4 Temperature (LS Byte) */
      43             : #define ASC7621_TEMP_NA         0x80    /* Not plugged */
      44             : 
      45             : #define ASC7621_IN1_VH          0x20    /* 2.5V (MS Byte) */
      46             : #define ASC7621_IN1_VL          0x13    /* 2.5V (LS Byte) */
      47             : #define ASC7621_IN2_VH          0x21    /* VCCP (MS Byte) */
      48             : #define ASC7621_IN2_VL          0x18    /* VCCP (LS Byte) */
      49             : #define ASC7621_IN3_VH          0x22    /* 3.3V (MS Byte) */
      50             : #define ASC7621_IN3_VL          0x11    /* 2.3V (LS Byte) */
      51             : #define ASC7621_IN4_VH          0x23    /* 5V   (MS Byte) */
      52             : #define ASC7621_IN4_VL          0x12    /* 5V   (LS Byte) */
      53             : #define ASC7621_IN5_VH          0x24    /* 12V  (MS Byte) */
      54             : #define ASC7621_IN5_VL          0x14    /* 12V  (LS Byte) */
      55             : 
      56             : #define ASC7621_TACH1H          0x29    /* Tachometer 1 (MS Byte) */
      57             : #define ASC7621_TACH1L          0x28    /* Tachometer 1 (LS Byte) */
      58             : #define ASC7621_TACH2H          0x2b    /* Tachometer 2 (MS Byte) */
      59             : #define ASC7621_TACH2L          0x2a    /* Tachometer 2 (LS Byte) */
      60             : #define ASC7621_TACH3H          0x2d    /* Tachometer 3 (MS Byte) */
      61             : #define ASC7621_TACH3L          0x2c    /* Tachometer 3 (LS Byte) */
      62             : #define ASC7621_TACH4H          0x2f    /* Tachometer 4 (MS Byte) */
      63             : #define ASC7621_TACH4L          0x2e    /* Tachometer 4 (LS Byte) */
      64             : 
      65             : /* Sensors */
      66             : #define ADL_TEMP1               0
      67             : #define ADL_TEMP2               1
      68             : #define ADL_TEMP3               2
      69             : #define ADL_TEMP4               3
      70             : #define ADL_IN1_V               4
      71             : #define ADL_IN2_V               5
      72             : #define ADL_IN3_V               6
      73             : #define ADL_IN4_V               7
      74             : #define ADL_IN5_V               8
      75             : #define ADL_TACH1               9
      76             : #define ADL_TACH2               10
      77             : #define ADL_TACH3               11
      78             : #define ADL_TACH4               12
      79             : #define ADL_NUM_SENSORS         13
      80             : 
      81             : struct {
      82             :         char            sensor;
      83             :         u_int8_t        hreg;                   /* MS-byte register */
      84             :         u_int8_t        lreg;                   /* LS-byte register */
      85             :         char            *name;
      86             :         u_short         mVscale;
      87             :         u_short         tempscale;              /* else a fan */
      88             : } adl_worklist[] = {
      89             :         { ADL_TEMP1, ASC7621_TEMP1H, ASC7621_TEMP1L, "CPU", 0, 1 },
      90             :         { ADL_TEMP2, ASC7621_TEMP2H, ASC7621_TEMP2L, "CPU", 0, 1 },
      91             :         { ADL_TEMP3, ASC7621_TEMP3H, ASC7621_TEMP3L, "Internal", 0, 1 },
      92             :         { ADL_TEMP4, ASC7621_TEMP4H, ASC7621_TEMP4L, "External", 0, 1 },
      93             : 
      94             :         { ADL_IN1_V, ASC7621_IN1_VH, ASC7621_IN1_VL, "+1.5V", 2500, 0 },
      95             :         { ADL_IN2_V, ASC7621_IN2_VH, ASC7621_IN2_VL, "Vccp",  2250, 0 },
      96             :         { ADL_IN3_V, ASC7621_IN3_VH, ASC7621_IN3_VL, "+3.3V", 3300, 0 },
      97             :         { ADL_IN4_V, ASC7621_IN4_VH, ASC7621_IN4_VL, "+5V",   5000, 0 },
      98             :         { ADL_IN5_V, ASC7621_IN5_VH, ASC7621_IN5_VL, "+12V", 12000, 0 },
      99             : 
     100             :         { ADL_TACH1, ASC7621_TACH1L, ASC7621_TACH1H, "", 0, 0 },
     101             :         { ADL_TACH2, ASC7621_TACH2L, ASC7621_TACH2H, "", 0, 0 },
     102             :         { ADL_TACH3, ASC7621_TACH3L, ASC7621_TACH3H, "", 0, 0 },
     103             :         { ADL_TACH4, ASC7621_TACH4L, ASC7621_TACH4H, "", 0, 0 }
     104             : };
     105             : 
     106             : struct adl_softc {
     107             :         struct device sc_dev;
     108             :         i2c_tag_t sc_tag;
     109             :         i2c_addr_t sc_addr;
     110             :         u_int8_t sc_conf;
     111             : 
     112             :         struct ksensor sc_sensor[ADL_NUM_SENSORS];
     113             :         struct ksensordev sc_sensordev;
     114             : };
     115             : 
     116             : #if 0
     117             : static int peci_enabled;
     118             : static int legacy_mode;
     119             : #endif
     120             : 
     121             : int     adl_match(struct device *, void *, void *);
     122             : void    adl_attach(struct device *, struct device *, void *);
     123             : 
     124             : void    adl_refresh(void *);
     125             : 
     126             : struct cfattach adl_ca = {
     127             :         sizeof(struct adl_softc), adl_match, adl_attach
     128             : };
     129             : 
     130             : struct cfdriver adl_cd = {
     131             :         NULL, "adl", DV_DULL
     132             : };
     133             : 
     134             : int
     135           0 : adl_match(struct device *parent, void *match, void *aux)
     136             : {
     137           0 :         struct i2c_attach_args *ia = aux;
     138             : 
     139           0 :         if (strcmp(ia->ia_name, "asc7621") == 0)
     140           0 :                 return (1);
     141           0 :         return (0);
     142           0 : }
     143             : 
     144             : void
     145           0 : adl_attach(struct device *parent, struct device *self, void *aux)
     146             : {
     147           0 :         struct adl_softc *sc = (struct adl_softc *)self;
     148           0 :         struct i2c_attach_args *ia = aux;
     149           0 :         u_int8_t cmd, data;
     150             :         int i;
     151             : 
     152           0 :         sc->sc_tag = ia->ia_tag;
     153           0 :         sc->sc_addr = ia->ia_addr;
     154             : 
     155           0 :         printf(": %s", ia->ia_name);
     156             : 
     157             :         /* Initialize sensor data. */
     158           0 :         strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
     159             :             sizeof(sc->sc_sensordev.xname));
     160             : 
     161             :         /* Check for PECI mode */
     162           0 :         cmd = ASC7621_PECI;
     163           0 :         (void)iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
     164             :             &cmd, sizeof(cmd), &data, sizeof(data), 0);
     165           0 :         if (data & ASC7621_PECI_MASK)
     166           0 :                 printf(", PECI enabled\n");
     167             : 
     168             : #if 0
     169             :         /* Check for legacy mode */
     170             :         cmd = ASC7621_LEGACY;
     171             :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr,
     172             :             &cmd, sizeof(cmd), &data, sizeof(data), 0)) {
     173             :                 printf(", unable to read PECI configuration register");
     174             :         }
     175             :         if (data & ASC7621_LEGACY_MASK)
     176             :                 legacy_mode = 1;
     177             : #endif
     178             : 
     179           0 :         if (sensor_task_register(sc, adl_refresh, 5) == NULL) {
     180           0 :                 printf(", unable to register update task\n");
     181           0 :                 return;
     182             :         }
     183             : 
     184           0 :         for (i = 0; i < ADL_NUM_SENSORS; i++) {
     185           0 :                 if (adl_worklist[i].tempscale)
     186           0 :                         sc->sc_sensor[i].type = SENSOR_TEMP;
     187           0 :                 else if (adl_worklist[i].mVscale)
     188           0 :                         sc->sc_sensor[i].type = SENSOR_VOLTS_DC;
     189             :                 else
     190           0 :                         sc->sc_sensor[i].type = SENSOR_FANRPM;
     191           0 :                 strlcpy(sc->sc_sensor[i].desc, adl_worklist[i].name,
     192             :                     sizeof(sc->sc_sensor[i].desc));
     193             : 
     194           0 :                 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
     195             :         }
     196           0 :         sensordev_install(&sc->sc_sensordev);
     197             : 
     198           0 :         printf("\n");
     199           0 : }
     200             : 
     201             : void
     202           0 : adl_refresh(void *arg)
     203             : {
     204           0 :         struct adl_softc *sc = arg;
     205             :         int64_t temp, volt;
     206           0 :         u_int8_t hdata, ldata, hreg, lreg;
     207             :         u_int16_t fan;
     208             :         int i;
     209             : 
     210           0 :         iic_acquire_bus(sc->sc_tag, 0);
     211             : 
     212           0 :         for (i = 0; i < sizeof adl_worklist / sizeof(adl_worklist[0]); i++) {
     213           0 :                 hreg = adl_worklist[i].hreg;
     214           0 :                 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     215           0 :                     sc->sc_addr, &hreg, sizeof hreg, &hdata, sizeof hdata, 0)) {
     216           0 :                         sc->sc_sensor[i].flags |= SENSOR_FINVALID;
     217           0 :                         continue;
     218             :                 }
     219           0 :                 lreg = adl_worklist[i].lreg;
     220           0 :                 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     221           0 :                     sc->sc_addr, &lreg, sizeof lreg, &ldata, sizeof ldata, 0)) {
     222           0 :                         sc->sc_sensor[i].flags |= SENSOR_FINVALID;
     223           0 :                         continue;
     224             :                 }
     225             : 
     226           0 :                 sc->sc_sensor[i].flags &= ~SENSOR_FINVALID;
     227           0 :                 if (adl_worklist[i].tempscale) {
     228           0 :                         if (hdata == ASC7621_TEMP_NA)
     229           0 :                                 sc->sc_sensor[i].flags |= SENSOR_FINVALID;
     230             :                         else {
     231             :                                 /*
     232             :                                  * 10-bit two's complement integer in
     233             :                                  * steps of 0.25
     234             :                                  */
     235           0 :                                 temp = ((hdata << 8 | ldata)) >> (16 - 10);
     236           0 :                                 temp = temp * 250000 + 273150000;
     237           0 :                                 sc->sc_sensor[i].value = temp;
     238             :                         }
     239           0 :                 } else if (adl_worklist[i].mVscale) {
     240           0 :                         volt = ((hdata << 8 | ldata)) >> (16 - 10);
     241           0 :                         volt = volt * adl_worklist[i].mVscale / (192 << 2);
     242           0 :                         sc->sc_sensor[i].value = volt * 1000;
     243           0 :                 } else {
     244             :                         /*
     245             :                          * Inversed to ensure that the LS byte will be read
     246             :                          * before MS byte.
     247             :                          */
     248           0 :                         fan = hdata + (ldata << 8);
     249           0 :                         if (fan == 0 || fan == 0xffff)
     250           0 :                                 sc->sc_sensor[i].flags |= SENSOR_FINVALID;
     251             :                         else
     252           0 :                                 sc->sc_sensor[i].value = (90000 * 60) / fan;
     253             :                 }
     254             :         }
     255             : 
     256           0 :         iic_release_bus(sc->sc_tag, 0);
     257           0 : }

Generated by: LCOV version 1.13