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

          Line data    Source code
       1             : /*      $OpenBSD: adm1026.c,v 1.11 2008/06/09 16:21:33 cnst Exp $       */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2005 Theo de Raadt
       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             : /* ADM 1026 registers */
      27             : #define ADM1026_TEMP            0x1f
      28             : #define ADM1026_STATUS          0x20
      29             : #define ADM1026_Vbat            0x26
      30             : #define ADM1026_Ain8            0x27
      31             : #define ADM1026_EXT1            0x28
      32             : #define ADM1026_EXT2            0x29
      33             : #define ADM1026_V3_3stby        0x2a
      34             : #define ADM1026_V3_3main        0x2b
      35             : #define ADM1026_V5              0x2c
      36             : #define ADM1026_Vccp            0x2d
      37             : #define ADM1026_V12             0x2e
      38             : #define ADM1026_Vminus12        0x2f
      39             : #define ADM1026_FAN0            0x38
      40             : #define ADM1026_FAN1            0x39
      41             : #define ADM1026_FAN2            0x3a
      42             : #define ADM1026_FAN3            0x3b
      43             : #define ADM1026_FAN4            0x3c
      44             : #define ADM1026_FAN5            0x3d
      45             : #define ADM1026_FAN6            0x3e
      46             : #define ADM1026_FAN7            0x3f
      47             : #define ADM1026_EXT1_OFF        0x6e
      48             : #define ADM1026_EXT2_OFF        0x6f
      49             : #define ADM1026_FAN0123DIV      0x02
      50             : #define ADM1026_FAN4567DIV      0x03
      51             : #define ADM1026_CONTROL         0x00
      52             : #define  ADM1026_CONTROL_START  0x01
      53             : #define  ADM1026_CONTROL_INTCLR 0x04
      54             : 
      55             : /* Sensors */
      56             : #define ADMCTS_TEMP             0
      57             : #define ADMCTS_EXT1             1
      58             : #define ADMCTS_EXT2             2
      59             : #define ADMCTS_Vbat             3
      60             : #define ADMCTS_V3_3stby         4
      61             : #define ADMCTS_V3_3main         5
      62             : #define ADMCTS_V5               6
      63             : #define ADMCTS_Vccp             7
      64             : #define ADMCTS_V12              8
      65             : #define ADMCTS_Vminus12         9
      66             : #define ADMCTS_FAN0             10
      67             : #define ADMCTS_FAN1             11
      68             : #define ADMCTS_FAN2             12
      69             : #define ADMCTS_FAN3             13
      70             : #define ADMCTS_FAN4             14
      71             : #define ADMCTS_FAN5             15
      72             : #define ADMCTS_FAN6             16
      73             : #define ADMCTS_FAN7             17
      74             : #define ADMCTS_NUM_SENSORS      18
      75             : 
      76             : struct admcts_softc {
      77             :         struct device   sc_dev;
      78             :         i2c_tag_t       sc_tag;
      79             :         i2c_addr_t      sc_addr;
      80             : 
      81             :         struct ksensor  sc_sensor[ADMCTS_NUM_SENSORS];
      82             :         struct ksensordev sc_sensordev;
      83             :         int             sc_fanmul[8];
      84             : };
      85             : 
      86             : int     admcts_match(struct device *, void *, void *);
      87             : void    admcts_attach(struct device *, struct device *, void *);
      88             : void    admcts_refresh(void *);
      89             : 
      90             : struct cfattach admcts_ca = {
      91             :         sizeof(struct admcts_softc), admcts_match, admcts_attach
      92             : };
      93             : 
      94             : struct cfdriver admcts_cd = {
      95             :         NULL, "admcts", DV_DULL
      96             : };
      97             : 
      98             : int
      99           0 : admcts_match(struct device *parent, void *match, void *aux)
     100             : {
     101           0 :         struct i2c_attach_args *ia = aux;
     102             : 
     103           0 :         if (strcmp(ia->ia_name, "adm1026") == 0)
     104           0 :                 return (1);
     105           0 :         return (0);
     106           0 : }
     107             : 
     108             : void
     109           0 : admcts_attach(struct device *parent, struct device *self, void *aux)
     110             : {
     111           0 :         struct admcts_softc *sc = (struct admcts_softc *)self;
     112           0 :         struct i2c_attach_args *ia = aux;
     113           0 :         u_int8_t cmd, data, data2;
     114             :         int i;
     115             : 
     116           0 :         sc->sc_tag = ia->ia_tag;
     117           0 :         sc->sc_addr = ia->ia_addr;
     118             : 
     119           0 :         iic_acquire_bus(sc->sc_tag, 0);
     120           0 :         cmd = ADM1026_CONTROL;
     121           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     122           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
     123           0 :                 iic_release_bus(sc->sc_tag, 0);
     124           0 :                 printf(": cannot get control register\n");
     125           0 :                 return;
     126             :         }
     127           0 :         data2 = data | ADM1026_CONTROL_START;
     128           0 :         data2 = data2 & ~ADM1026_CONTROL_INTCLR;
     129           0 :         if (data != data2) {
     130           0 :                 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
     131           0 :                     sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) {
     132           0 :                         iic_release_bus(sc->sc_tag, 0);
     133           0 :                         printf(": cannot set control register\n");
     134           0 :                         return;
     135             :                 }
     136             :         }
     137             : 
     138           0 :         cmd = ADM1026_FAN0123DIV;
     139           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     140           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
     141           0 :                 iic_release_bus(sc->sc_tag, 0);
     142           0 :                 printf(": cannot get fan0123div register\n");
     143           0 :                 return;
     144             :         }
     145           0 :         sc->sc_fanmul[0] = (1 << ((data >> 0) & 0x3));
     146           0 :         sc->sc_fanmul[1] = (1 << ((data >> 2) & 0x3));
     147           0 :         sc->sc_fanmul[2] = (1 << ((data >> 4) & 0x3));
     148           0 :         sc->sc_fanmul[3] = (1 << ((data >> 6) & 0x3));
     149             : 
     150           0 :         cmd = ADM1026_FAN4567DIV;
     151           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     152           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
     153           0 :                 iic_release_bus(sc->sc_tag, 0);
     154           0 :                 printf(": cannot get fan0123div register\n");
     155           0 :                 return;
     156             :         }
     157           0 :         sc->sc_fanmul[4] = (1 << ((data >> 0) & 0x3));
     158           0 :         sc->sc_fanmul[5] = (1 << ((data >> 2) & 0x3));
     159           0 :         sc->sc_fanmul[6] = (1 << ((data >> 4) & 0x3));
     160           0 :         sc->sc_fanmul[7] = (1 << ((data >> 6) & 0x3));
     161             : 
     162           0 :         iic_release_bus(sc->sc_tag, 0);
     163             : 
     164             :         /* Initialize sensor data. */
     165           0 :         strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
     166             :             sizeof(sc->sc_sensordev.xname));
     167             : 
     168           0 :         sc->sc_sensor[ADMCTS_TEMP].type = SENSOR_TEMP;
     169           0 :         strlcpy(sc->sc_sensor[ADMCTS_TEMP].desc, "Internal",
     170             :             sizeof(sc->sc_sensor[ADMCTS_TEMP].desc));
     171             : 
     172           0 :         sc->sc_sensor[ADMCTS_Vbat].type = SENSOR_VOLTS_DC;
     173           0 :         strlcpy(sc->sc_sensor[ADMCTS_Vbat].desc, "Vbat",
     174             :             sizeof(sc->sc_sensor[ADMCTS_Vbat].desc));
     175             : 
     176           0 :         sc->sc_sensor[ADMCTS_EXT1].type = SENSOR_TEMP;
     177           0 :         strlcpy(sc->sc_sensor[ADMCTS_EXT1].desc, "External",
     178             :             sizeof(sc->sc_sensor[ADMCTS_EXT1].desc));
     179             : 
     180           0 :         sc->sc_sensor[ADMCTS_EXT2].type = SENSOR_TEMP;
     181           0 :         strlcpy(sc->sc_sensor[ADMCTS_EXT2].desc, "External",
     182             :             sizeof(sc->sc_sensor[ADMCTS_EXT2].desc));
     183             : 
     184           0 :         sc->sc_sensor[ADMCTS_V3_3stby].type = SENSOR_VOLTS_DC;
     185           0 :         strlcpy(sc->sc_sensor[ADMCTS_V3_3stby].desc, "3.3 V standby",
     186             :             sizeof(sc->sc_sensor[ADMCTS_V3_3stby].desc));
     187             : 
     188           0 :         sc->sc_sensor[ADMCTS_V3_3main].type = SENSOR_VOLTS_DC;
     189           0 :         strlcpy(sc->sc_sensor[ADMCTS_V3_3main].desc, "3.3 V main",
     190             :             sizeof(sc->sc_sensor[ADMCTS_V3_3main].desc));
     191             : 
     192           0 :         sc->sc_sensor[ADMCTS_V5].type = SENSOR_VOLTS_DC;
     193           0 :         strlcpy(sc->sc_sensor[ADMCTS_V5].desc, "5 V",
     194             :             sizeof(sc->sc_sensor[ADMCTS_V5].desc));
     195             : 
     196           0 :         sc->sc_sensor[ADMCTS_Vccp].type = SENSOR_VOLTS_DC;
     197           0 :         strlcpy(sc->sc_sensor[ADMCTS_Vccp].desc, "Vccp",
     198             :             sizeof(sc->sc_sensor[ADMCTS_Vccp].desc));
     199             : 
     200           0 :         sc->sc_sensor[ADMCTS_V12].type = SENSOR_VOLTS_DC;
     201           0 :         strlcpy(sc->sc_sensor[ADMCTS_V12].desc, "12 V",
     202             :             sizeof(sc->sc_sensor[ADMCTS_V12].desc));
     203             : 
     204           0 :         sc->sc_sensor[ADMCTS_Vminus12].type = SENSOR_VOLTS_DC;
     205           0 :         strlcpy(sc->sc_sensor[ADMCTS_Vminus12].desc, "-12 V",
     206             :             sizeof(sc->sc_sensor[ADMCTS_Vminus12].desc));
     207             : 
     208           0 :         sc->sc_sensor[ADMCTS_FAN1].type = SENSOR_FANRPM;
     209           0 :         sc->sc_sensor[ADMCTS_FAN2].type = SENSOR_FANRPM;
     210           0 :         sc->sc_sensor[ADMCTS_FAN3].type = SENSOR_FANRPM;
     211           0 :         sc->sc_sensor[ADMCTS_FAN4].type = SENSOR_FANRPM;
     212           0 :         sc->sc_sensor[ADMCTS_FAN5].type = SENSOR_FANRPM;
     213           0 :         sc->sc_sensor[ADMCTS_FAN6].type = SENSOR_FANRPM;
     214           0 :         sc->sc_sensor[ADMCTS_FAN7].type = SENSOR_FANRPM;
     215             : 
     216           0 :         if (sensor_task_register(sc, admcts_refresh, 5) == NULL) {
     217           0 :                 printf(", unable to register update task\n");
     218           0 :                 return;
     219             :         }
     220             : 
     221           0 :         for (i = 0; i < ADMCTS_NUM_SENSORS; i++)
     222           0 :                 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
     223           0 :         sensordev_install(&sc->sc_sensordev);
     224             : 
     225           0 :         printf("\n");
     226           0 : }
     227             : 
     228             : static void
     229           0 : fanval(struct ksensor *sens, int mul, u_int8_t data)
     230             : {
     231           0 :         int tmp = data * mul;
     232             : 
     233           0 :         if (tmp == 0)
     234           0 :                 sens->flags |= SENSOR_FINVALID;
     235             :         else
     236           0 :                 sens->value = 1630000 / tmp;
     237           0 : }
     238             : 
     239             : void
     240           0 : admcts_refresh(void *arg)
     241             : {
     242           0 :         struct admcts_softc *sc = arg;
     243           0 :         u_int8_t cmd, data;
     244           0 :         int8_t sdata;
     245             : 
     246           0 :         iic_acquire_bus(sc->sc_tag, 0);
     247             : 
     248           0 :         cmd = ADM1026_TEMP;
     249           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     250           0 :             sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
     251           0 :                 sc->sc_sensor[ADMCTS_TEMP].value = 273150000 + 1000000 * sdata;
     252             : 
     253           0 :         cmd = ADM1026_EXT1;
     254           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     255           0 :             sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
     256           0 :                 sc->sc_sensor[ADMCTS_EXT1].value = 273150000 + 1000000 * sdata;
     257             : 
     258           0 :         cmd = ADM1026_EXT2;
     259           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     260           0 :             sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
     261           0 :                 sc->sc_sensor[ADMCTS_EXT2].value = 273150000 + 1000000 * sdata;
     262             : 
     263           0 :         cmd = ADM1026_Vbat;
     264           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     265           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
     266           0 :                 sc->sc_sensor[ADMCTS_Vbat].value = 3000000 * data / 192;
     267             : 
     268           0 :         cmd = ADM1026_V3_3stby;
     269           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     270           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
     271           0 :                 sc->sc_sensor[ADMCTS_V3_3stby].value = 3300000 * data / 192;
     272             : 
     273           0 :         cmd = ADM1026_V3_3main;
     274           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     275           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
     276           0 :                 sc->sc_sensor[ADMCTS_V3_3main].value = 3300000 * data / 192;
     277             : 
     278           0 :         cmd = ADM1026_V5;
     279           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     280           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
     281           0 :                 sc->sc_sensor[ADMCTS_V5].value = 5500000 * data / 192;
     282             : 
     283           0 :         cmd = ADM1026_Vccp;
     284           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     285           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
     286           0 :                 sc->sc_sensor[ADMCTS_Vccp].value = 2250000 * data / 192;
     287             : 
     288           0 :         cmd = ADM1026_V12;
     289           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     290           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
     291           0 :                 sc->sc_sensor[ADMCTS_V12].value = 12000000 * data / 192;
     292             : 
     293           0 :         cmd = ADM1026_Vminus12;
     294           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     295           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
     296           0 :                 sc->sc_sensor[ADMCTS_Vminus12].value = -2125000 * data / 192;
     297             : 
     298           0 :         cmd = ADM1026_FAN0;
     299           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     300           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
     301           0 :                 fanval(&sc->sc_sensor[ADMCTS_FAN0], sc->sc_fanmul[0], data);
     302             : 
     303           0 :         cmd = ADM1026_FAN1;
     304           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     305           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
     306           0 :                 fanval(&sc->sc_sensor[ADMCTS_FAN1], sc->sc_fanmul[1], data);
     307             : 
     308           0 :         cmd = ADM1026_FAN2;
     309           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     310           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
     311           0 :                 fanval(&sc->sc_sensor[ADMCTS_FAN2], sc->sc_fanmul[2], data);
     312             : 
     313           0 :         cmd = ADM1026_FAN3;
     314           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     315           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
     316           0 :                 fanval(&sc->sc_sensor[ADMCTS_FAN3], sc->sc_fanmul[3], data);
     317             : 
     318           0 :         cmd = ADM1026_FAN4;
     319           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     320           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
     321           0 :                 fanval(&sc->sc_sensor[ADMCTS_FAN4], sc->sc_fanmul[4], data);
     322             : 
     323           0 :         cmd = ADM1026_FAN5;
     324           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     325           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
     326           0 :                 fanval(&sc->sc_sensor[ADMCTS_FAN5], sc->sc_fanmul[5], data);
     327             : 
     328           0 :         cmd = ADM1026_FAN6;
     329           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     330           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
     331           0 :                 fanval(&sc->sc_sensor[ADMCTS_FAN6], sc->sc_fanmul[6], data);
     332             : 
     333           0 :         cmd = ADM1026_FAN7;
     334           0 :         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
     335           0 :             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
     336           0 :                 fanval(&sc->sc_sensor[ADMCTS_FAN7], sc->sc_fanmul[7], data);
     337             : 
     338           0 :         iic_release_bus(sc->sc_tag, 0);
     339           0 : }

Generated by: LCOV version 1.13