root/dev/i2c/adm1024.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. admlc_match
  2. admlc_attach
  3. fanval
  4. admlc_refresh

    1 /*      $OpenBSD: adm1024.c,v 1.14 2007/06/24 05:34:35 dlg 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 1024 registers */
   27 #define ADM1024_V2_5            0x20
   28 #define ADM1024_Vccp            0x21
   29 #define ADM1024_Vcc             0x22
   30 #define ADM1024_V5              0x23
   31 #define ADM1024_V12             0x24
   32 #define ADM1024_Vccp2           0x25
   33 #define ADM1024_EXT_TEMP        0x26
   34 #define ADM1024_INT_TEMP        0x27
   35 #define ADM1024_FAN1            0x28
   36 #define ADM1024_FAN2            0x29
   37 #define ADM1024_STATUS2         0x42
   38 #define ADM1024_FANC            0x47
   39 #define  ADM1024_STATUS2_EXT    0x40
   40 #define ADM1024_COMPANY         0x3e    /* contains 0x41 */
   41 #define ADM1024_STEPPING        0x3f    /* contains 0x2? */
   42 #define ADM1024_CONFIG1         0x40
   43 #define  ADM1024_CONFIG1_START  0x01
   44 #define  ADM1024_CONFIG1_INTCLR 0x08
   45 
   46 /* Sensors */
   47 #define ADMLC_INT               0
   48 #define ADMLC_EXT               1
   49 #define ADMLC_V2_5              2
   50 #define ADMLC_Vccp              3
   51 #define ADMLC_Vcc               4
   52 #define ADMLC_V5                5
   53 #define ADMLC_V12               6
   54 #define ADMLC_Vccp2             7
   55 #define ADMLC_FAN1              8
   56 #define ADMLC_FAN2              9
   57 #define ADMLC_NUM_SENSORS       10
   58 
   59 struct admlc_softc {
   60         struct device   sc_dev;
   61         i2c_tag_t       sc_tag;
   62         i2c_addr_t      sc_addr;
   63 
   64         struct ksensor  sc_sensor[ADMLC_NUM_SENSORS];
   65         struct ksensordev sc_sensordev;
   66         int             sc_fan1mul;
   67         int             sc_fan2mul;
   68 };
   69 
   70 int     admlc_match(struct device *, void *, void *);
   71 void    admlc_attach(struct device *, struct device *, void *);
   72 void    admlc_refresh(void *);
   73 
   74 struct cfattach admlc_ca = {
   75         sizeof(struct admlc_softc), admlc_match, admlc_attach
   76 };
   77 
   78 struct cfdriver admlc_cd = {
   79         NULL, "admlc", DV_DULL
   80 };
   81 
   82 int
   83 admlc_match(struct device *parent, void *match, void *aux)
   84 {
   85         struct i2c_attach_args *ia = aux;
   86 
   87         if (strcmp(ia->ia_name, "adm1024") == 0)
   88                 return (1);
   89         return (0);
   90 }
   91 
   92 void
   93 admlc_attach(struct device *parent, struct device *self, void *aux)
   94 {
   95         struct admlc_softc *sc = (struct admlc_softc *)self;
   96         struct i2c_attach_args *ia = aux;
   97         u_int8_t cmd, data, data2;
   98         int i;
   99 
  100         sc->sc_tag = ia->ia_tag;
  101         sc->sc_addr = ia->ia_addr;
  102 
  103         iic_acquire_bus(sc->sc_tag, 0);
  104         cmd = ADM1024_CONFIG1;
  105         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  106             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
  107                 iic_release_bus(sc->sc_tag, 0);
  108                 printf(": cannot get control register\n");
  109                 return;
  110         }
  111         data2 = data | ADM1024_CONFIG1_START;
  112         data2 = data2 & ~ADM1024_CONFIG1_INTCLR;
  113         if (data != data2) {
  114                 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
  115                     sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) {
  116                         iic_release_bus(sc->sc_tag, 0);
  117                         printf(": cannot set control register\n");
  118                         return;
  119                 }
  120         }
  121 
  122         cmd = ADM1024_FANC;
  123         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  124             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
  125                 printf(", unable to read fan setting\n");
  126                 return;
  127         }
  128         sc->sc_fan1mul = (1 << (data >> 4) & 0x3);
  129         sc->sc_fan2mul = (1 << (data >> 6) & 0x3);
  130 
  131         iic_release_bus(sc->sc_tag, 0);
  132 
  133         /* Initialize sensor data. */
  134         strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
  135             sizeof(sc->sc_sensordev.xname));
  136 
  137         sc->sc_sensor[ADMLC_INT].type = SENSOR_TEMP;
  138         strlcpy(sc->sc_sensor[ADMLC_INT].desc, "Internal",
  139             sizeof(sc->sc_sensor[ADMLC_INT].desc));
  140 
  141         sc->sc_sensor[ADMLC_EXT].type = SENSOR_TEMP;
  142         strlcpy(sc->sc_sensor[ADMLC_EXT].desc, "External",
  143             sizeof(sc->sc_sensor[ADMLC_EXT].desc));
  144 
  145         sc->sc_sensor[ADMLC_V2_5].type = SENSOR_VOLTS_DC;
  146         strlcpy(sc->sc_sensor[ADMLC_V2_5].desc, "2.5 V",
  147             sizeof(sc->sc_sensor[ADMLC_V2_5].desc));
  148 
  149         sc->sc_sensor[ADMLC_Vccp].type = SENSOR_VOLTS_DC;
  150         strlcpy(sc->sc_sensor[ADMLC_Vccp].desc, "Vccp",
  151             sizeof(sc->sc_sensor[ADMLC_Vccp].desc));
  152 
  153         sc->sc_sensor[ADMLC_Vcc].type = SENSOR_VOLTS_DC;
  154         strlcpy(sc->sc_sensor[ADMLC_Vcc].desc, "Vcc",
  155             sizeof(sc->sc_sensor[ADMLC_Vcc].desc));
  156 
  157         sc->sc_sensor[ADMLC_V5].type = SENSOR_VOLTS_DC;
  158         strlcpy(sc->sc_sensor[ADMLC_V5].desc, "5 V",
  159             sizeof(sc->sc_sensor[ADMLC_V5].desc));
  160 
  161         sc->sc_sensor[ADMLC_V12].type = SENSOR_VOLTS_DC;
  162         strlcpy(sc->sc_sensor[ADMLC_V12].desc, "12 V",
  163             sizeof(sc->sc_sensor[ADMLC_V12].desc));
  164 
  165         sc->sc_sensor[ADMLC_Vccp2].type = SENSOR_VOLTS_DC;
  166         strlcpy(sc->sc_sensor[ADMLC_Vccp2].desc, "Vccp2",
  167             sizeof(sc->sc_sensor[ADMLC_Vccp2].desc));
  168 
  169         sc->sc_sensor[ADMLC_FAN1].type = SENSOR_FANRPM;
  170 
  171         sc->sc_sensor[ADMLC_FAN2].type = SENSOR_FANRPM;
  172 
  173 
  174         if (sensor_task_register(sc, admlc_refresh, 5) == NULL) {
  175                 printf(", unable to register update task\n");
  176                 return;
  177         }
  178 
  179         for (i = 0; i < ADMLC_NUM_SENSORS; i++)
  180                 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
  181         sensordev_install(&sc->sc_sensordev);
  182 
  183         printf("\n");
  184 }
  185 
  186 static void
  187 fanval(struct ksensor *sens, int mul, u_int8_t data)
  188 {
  189         int tmp = data * mul;
  190 
  191         if (tmp == 0)
  192                 sens->flags |= SENSOR_FINVALID;
  193         else
  194                 sens->value = 1350000 / tmp;
  195 }
  196 
  197 void
  198 admlc_refresh(void *arg)
  199 {
  200         struct admlc_softc *sc = arg;
  201         u_int8_t cmd, data;
  202         int8_t sdata;
  203 
  204         iic_acquire_bus(sc->sc_tag, 0);
  205 
  206         cmd = ADM1024_INT_TEMP;
  207         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  208             sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
  209                 sc->sc_sensor[ADMLC_INT].value = 273150000 + 1000000 * sdata;
  210 
  211         cmd = ADM1024_EXT_TEMP;
  212         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  213             sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
  214                 sc->sc_sensor[ADMLC_EXT].value = 273150000 + 1000000 * sdata;
  215 
  216         cmd = ADM1024_STATUS2;
  217         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  218             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) {
  219                 if (data & ADM1024_STATUS2_EXT)
  220                         sc->sc_sensor[ADMLC_EXT].flags |= SENSOR_FINVALID;
  221                 else
  222                         sc->sc_sensor[ADMLC_EXT].flags &= ~SENSOR_FINVALID;
  223         }
  224 
  225         cmd = ADM1024_V2_5;
  226         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  227             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  228                 sc->sc_sensor[ADMLC_V2_5].value = 2500000 * data / 192;
  229 
  230         cmd = ADM1024_Vccp;
  231         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  232             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  233                 sc->sc_sensor[ADMLC_Vcc].value = 2249000 * data / 192;
  234 
  235         cmd = ADM1024_Vcc;
  236         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  237             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  238                 sc->sc_sensor[ADMLC_Vcc].value = 3300000 * data / 192;
  239 
  240         cmd = ADM1024_V5;
  241         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  242             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  243                 sc->sc_sensor[ADMLC_V5].value = 5000000 * data / 192;
  244 
  245         cmd = ADM1024_V12;
  246         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  247             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  248                 sc->sc_sensor[ADMLC_V12].value = 12000000 * data / 192;
  249 
  250         cmd = ADM1024_Vccp2;
  251         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  252             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  253                 sc->sc_sensor[ADMLC_Vccp2].value = 2700000 * data / 192;
  254 
  255         cmd = ADM1024_FAN1;
  256         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  257             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  258                 fanval(&sc->sc_sensor[ADMLC_FAN1], sc->sc_fan1mul, data);
  259 
  260         cmd = ADM1024_FAN2;
  261         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  262             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  263                 fanval(&sc->sc_sensor[ADMLC_FAN2], sc->sc_fan2mul, data);
  264         iic_release_bus(sc->sc_tag, 0);
  265 }

/* [<][>][^][v][top][bottom][index][help] */