root/dev/i2c/adm1025.c

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

DEFINITIONS

This source file includes following definitions.
  1. admtm_match
  2. admtm_attach
  3. admtm_refresh

    1 /*      $OpenBSD: adm1025.c,v 1.25 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 1025 registers */
   27 #define ADM1025_V2_5            0x20
   28 #define ADM1025_Vccp            0x21
   29 #define ADM1025_V3_3            0x22
   30 #define ADM1025_V5              0x23
   31 #define ADM1025_V12             0x24
   32 #define ADM1025_Vcc             0x25
   33 #define ADM1025_EXT_TEMP        0x26
   34 #define ADM1025_INT_TEMP        0x27
   35 #define ADM1025_STATUS2         0x42
   36 #define  ADM1025_STATUS2_EXT    0x40
   37 #define ADM1025_COMPANY         0x3e    /* contains 0x41 */
   38 #define ADM1025_STEPPING        0x3f    /* contains 0x2? */
   39 #define ADM1025_CONFIG          0x40
   40 #define  ADM1025_CONFIG_START   0x01
   41 #define SMSC47M192_V1_5         0x50
   42 #define SMSC47M192_V1_8         0x51
   43 #define SMSC47M192_TEMP2        0x52
   44 
   45 /* Sensors */
   46 #define ADMTM_INT               0
   47 #define ADMTM_EXT               1
   48 #define ADMTM_V2_5              2
   49 #define ADMTM_Vccp              3
   50 #define ADMTM_V3_3              4
   51 #define ADMTM_V5                5
   52 #define ADMTM_V12               6
   53 #define ADMTM_Vcc               7
   54 #define ADMTM_NUM_SENSORS       8
   55 #define SMSC_V1_5               8
   56 #define SMSC_V1_8               9
   57 #define SMSC_TEMP2              10
   58 #define SMSC_NUM_SENSORS        3
   59 struct admtm_softc {
   60         struct device   sc_dev;
   61         i2c_tag_t       sc_tag;
   62         i2c_addr_t      sc_addr;
   63 
   64         struct ksensor  sc_sensor[ADMTM_NUM_SENSORS + SMSC_NUM_SENSORS];
   65         struct ksensordev sc_sensordev;
   66         int             sc_nsensors;
   67         int             sc_model;
   68 };
   69 
   70 int     admtm_match(struct device *, void *, void *);
   71 void    admtm_attach(struct device *, struct device *, void *);
   72 void    admtm_refresh(void *);
   73 
   74 struct cfattach admtm_ca = {
   75         sizeof(struct admtm_softc), admtm_match, admtm_attach
   76 };
   77 
   78 struct cfdriver admtm_cd = {
   79         NULL, "admtm", DV_DULL
   80 };
   81 
   82 int
   83 admtm_match(struct device *parent, void *match, void *aux)
   84 {
   85         struct i2c_attach_args *ia = aux;
   86 
   87         if (strcmp(ia->ia_name, "adm1025") == 0 ||
   88             strcmp(ia->ia_name, "47m192") == 0 ||
   89             strcmp(ia->ia_name, "ne1619") == 0)
   90                 return (1);
   91         return (0);
   92 }
   93 
   94 void
   95 admtm_attach(struct device *parent, struct device *self, void *aux)
   96 {
   97         struct admtm_softc *sc = (struct admtm_softc *)self;
   98         struct i2c_attach_args *ia = aux;
   99         u_int8_t cmd, data, data2;
  100         int i;
  101 
  102         sc->sc_tag = ia->ia_tag;
  103         sc->sc_addr = ia->ia_addr;
  104 
  105         printf(": %s", ia->ia_name);
  106 
  107         sc->sc_nsensors = ADMTM_NUM_SENSORS;
  108         sc->sc_model = 1025;
  109         if (strcmp(ia->ia_name, "47m192") == 0) {
  110                 sc->sc_nsensors += SMSC_NUM_SENSORS;
  111                 sc->sc_model = 192;
  112         }
  113 
  114         iic_acquire_bus(sc->sc_tag, 0);
  115         cmd = ADM1025_CONFIG;
  116         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  117             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
  118                 iic_release_bus(sc->sc_tag, 0);
  119                 printf(", cannot get control register\n");
  120                 return;
  121         }
  122 
  123         data2 = data | ADM1025_CONFIG_START;
  124         if (data != data2) {
  125                 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
  126                     sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) {
  127                         iic_release_bus(sc->sc_tag, 0);
  128                         printf(", cannot set control register\n");
  129                         return;
  130                 }
  131         }
  132         iic_release_bus(sc->sc_tag, 0);
  133 
  134         /* Initialize sensor data. */
  135         strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
  136             sizeof(sc->sc_sensordev.xname));
  137 
  138         sc->sc_sensor[ADMTM_INT].type = SENSOR_TEMP;
  139         strlcpy(sc->sc_sensor[ADMTM_INT].desc, "Internal",
  140             sizeof(sc->sc_sensor[ADMTM_INT].desc));
  141 
  142         sc->sc_sensor[ADMTM_EXT].type = SENSOR_TEMP;
  143         strlcpy(sc->sc_sensor[ADMTM_EXT].desc, "External",
  144             sizeof(sc->sc_sensor[ADMTM_EXT].desc));
  145 
  146         sc->sc_sensor[ADMTM_V2_5].type = SENSOR_VOLTS_DC;
  147         strlcpy(sc->sc_sensor[ADMTM_V2_5].desc, "2.5 V",
  148             sizeof(sc->sc_sensor[ADMTM_V2_5].desc));
  149 
  150         sc->sc_sensor[ADMTM_Vccp].type = SENSOR_VOLTS_DC;
  151         strlcpy(sc->sc_sensor[ADMTM_Vccp].desc, "Vccp",
  152             sizeof(sc->sc_sensor[ADMTM_Vccp].desc));
  153 
  154         sc->sc_sensor[ADMTM_V3_3].type = SENSOR_VOLTS_DC;
  155         strlcpy(sc->sc_sensor[ADMTM_V3_3].desc, "3.3 V",
  156             sizeof(sc->sc_sensor[ADMTM_V3_3].desc));
  157 
  158         sc->sc_sensor[ADMTM_V5].type = SENSOR_VOLTS_DC;
  159         strlcpy(sc->sc_sensor[ADMTM_V5].desc, "5 V",
  160             sizeof(sc->sc_sensor[ADMTM_V5].desc));
  161 
  162         sc->sc_sensor[ADMTM_V12].type = SENSOR_VOLTS_DC;
  163         strlcpy(sc->sc_sensor[ADMTM_V12].desc, "12 V",
  164             sizeof(sc->sc_sensor[ADMTM_V12].desc));
  165 
  166         sc->sc_sensor[ADMTM_Vcc].type = SENSOR_VOLTS_DC;
  167         strlcpy(sc->sc_sensor[ADMTM_Vcc].desc, "Vcc",
  168             sizeof(sc->sc_sensor[ADMTM_Vcc].desc));
  169 
  170         sc->sc_sensor[SMSC_V1_5].type = SENSOR_VOLTS_DC;
  171         strlcpy(sc->sc_sensor[SMSC_V1_5].desc, "1.5 V",
  172             sizeof(sc->sc_sensor[SMSC_V1_5].desc));
  173 
  174         sc->sc_sensor[SMSC_V1_8].type = SENSOR_VOLTS_DC;
  175         strlcpy(sc->sc_sensor[SMSC_V1_8].desc, "1.8 V",
  176             sizeof(sc->sc_sensor[SMSC_V1_8].desc));
  177 
  178         sc->sc_sensor[SMSC_TEMP2].type = SENSOR_TEMP;
  179         strlcpy(sc->sc_sensor[SMSC_TEMP2].desc, "External",
  180             sizeof(sc->sc_sensor[SMSC_TEMP2].desc));
  181 
  182         if (sensor_task_register(sc, admtm_refresh, 5) == NULL) {
  183                 printf(", unable to register update task\n");
  184                 return;
  185         }
  186 
  187         for (i = 0; i < sc->sc_nsensors; i++)
  188                 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
  189         sensordev_install(&sc->sc_sensordev);
  190 
  191         printf("\n");
  192 }
  193 
  194 void
  195 admtm_refresh(void *arg)
  196 {
  197         struct admtm_softc *sc = arg;
  198         u_int8_t cmd, data;
  199         int8_t sdata;
  200 
  201         iic_acquire_bus(sc->sc_tag, 0);
  202 
  203         cmd = ADM1025_INT_TEMP;
  204         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  205             sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
  206                 sc->sc_sensor[ADMTM_INT].value = 273150000 + 1000000 * sdata;
  207 
  208         cmd = ADM1025_EXT_TEMP;
  209         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  210             sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
  211                 sc->sc_sensor[ADMTM_EXT].value = 273150000 + 1000000 * sdata;
  212 
  213         cmd = ADM1025_STATUS2;
  214         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  215             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) {
  216                 if (data & ADM1025_STATUS2_EXT)
  217                         sc->sc_sensor[ADMTM_EXT].flags |= SENSOR_FINVALID;
  218                 else
  219                         sc->sc_sensor[ADMTM_EXT].flags &= ~SENSOR_FINVALID;
  220         }
  221 
  222         cmd = ADM1025_V2_5;
  223         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  224             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  225                 sc->sc_sensor[ADMTM_V2_5].value = 2500000 * data / 192;
  226 
  227         cmd = ADM1025_Vccp;
  228         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  229             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  230                 sc->sc_sensor[ADMTM_Vcc].value = 2249000 * data / 192;
  231 
  232         cmd = ADM1025_V3_3;
  233         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  234             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  235                 sc->sc_sensor[ADMTM_V3_3].value = 3300000 * data / 192;
  236 
  237         cmd = ADM1025_V5;
  238         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  239             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  240                 sc->sc_sensor[ADMTM_V5].value = 5000000 * data / 192;
  241 
  242         cmd = ADM1025_V12;
  243         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  244             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  245                 sc->sc_sensor[ADMTM_V12].value = 12000000 * data / 192;
  246 
  247         cmd = ADM1025_Vcc;
  248         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  249             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  250                 sc->sc_sensor[ADMTM_Vcc].value = 3300000 * data / 192;
  251 
  252         if (sc->sc_model == 192) {
  253                 cmd = SMSC47M192_V1_5;
  254                 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  255                     sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  256                         sc->sc_sensor[SMSC_V1_5].value = 1500000 * data / 192;
  257 
  258                 cmd = SMSC47M192_V1_8;
  259                 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  260                     sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  261                         sc->sc_sensor[SMSC_V1_8].value = 1800000 * data / 192;
  262 
  263                 cmd = SMSC47M192_TEMP2;
  264                 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  265                     sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata,
  266                     0) == 0)
  267                         sc->sc_sensor[SMSC_TEMP2].value = 273150000 + 1000000 * sdata;
  268 
  269         }
  270 
  271         iic_release_bus(sc->sc_tag, 0);
  272 }

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