root/dev/i2c/adm1026.c

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

DEFINITIONS

This source file includes following definitions.
  1. admcts_match
  2. admcts_attach
  3. fanval
  4. admcts_refresh

    1 /*      $OpenBSD: adm1026.c,v 1.10 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 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 admcts_match(struct device *parent, void *match, void *aux)
  100 {
  101         struct i2c_attach_args *ia = aux;
  102 
  103         if (strcmp(ia->ia_name, "adm1026") == 0)
  104                 return (1);
  105         return (0);
  106 }
  107 
  108 void
  109 admcts_attach(struct device *parent, struct device *self, void *aux)
  110 {
  111         struct admcts_softc *sc = (struct admcts_softc *)self;
  112         struct i2c_attach_args *ia = aux;
  113         u_int8_t cmd, data, data2;
  114         int i;
  115 
  116         sc->sc_tag = ia->ia_tag;
  117         sc->sc_addr = ia->ia_addr;
  118 
  119         iic_acquire_bus(sc->sc_tag, 0);
  120         cmd = ADM1026_CONTROL;
  121         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  122             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
  123                 iic_release_bus(sc->sc_tag, 0);
  124                 printf(": cannot get control register\n");
  125                 return;
  126         }
  127         data2 = data | ADM1026_CONTROL_START;
  128         data2 = data2 & ~ADM1026_CONTROL_INTCLR;
  129         if (data != data2) {
  130                 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
  131                     sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) {
  132                         iic_release_bus(sc->sc_tag, 0);
  133                         printf(": cannot set control register\n");
  134                         return;
  135                 }
  136         }
  137 
  138         cmd = ADM1026_FAN0123DIV;
  139         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  140             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
  141                 iic_release_bus(sc->sc_tag, 0);
  142                 printf(": cannot get fan0123div register\n");
  143                 return;
  144         }
  145         sc->sc_fanmul[0] = (1 << (data >> 0) & 0x3);
  146         sc->sc_fanmul[1] = (1 << (data >> 2) & 0x3);
  147         sc->sc_fanmul[2] = (1 << (data >> 4) & 0x3);
  148         sc->sc_fanmul[3] = (1 << (data >> 6) & 0x3);
  149 
  150         cmd = ADM1026_FAN4567DIV;
  151         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  152             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
  153                 iic_release_bus(sc->sc_tag, 0);
  154                 printf(": cannot get fan0123div register\n");
  155                 return;
  156         }
  157         sc->sc_fanmul[4] = (1 << (data >> 0) & 0x3);
  158         sc->sc_fanmul[5] = (1 << (data >> 2) & 0x3);
  159         sc->sc_fanmul[6] = (1 << (data >> 4) & 0x3);
  160         sc->sc_fanmul[7] = (1 << (data >> 6) & 0x3);
  161 
  162         iic_release_bus(sc->sc_tag, 0);
  163 
  164         /* Initialize sensor data. */
  165         strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
  166             sizeof(sc->sc_sensordev.xname));
  167 
  168         sc->sc_sensor[ADMCTS_TEMP].type = SENSOR_TEMP;
  169         strlcpy(sc->sc_sensor[ADMCTS_TEMP].desc, "Internal",
  170             sizeof(sc->sc_sensor[ADMCTS_TEMP].desc));
  171 
  172         sc->sc_sensor[ADMCTS_Vbat].type = SENSOR_VOLTS_DC;
  173         strlcpy(sc->sc_sensor[ADMCTS_Vbat].desc, "Vbat",
  174             sizeof(sc->sc_sensor[ADMCTS_Vbat].desc));
  175 
  176         sc->sc_sensor[ADMCTS_EXT1].type = SENSOR_TEMP;
  177         strlcpy(sc->sc_sensor[ADMCTS_EXT1].desc, "External",
  178             sizeof(sc->sc_sensor[ADMCTS_EXT1].desc));
  179 
  180         sc->sc_sensor[ADMCTS_EXT2].type = SENSOR_TEMP;
  181         strlcpy(sc->sc_sensor[ADMCTS_EXT2].desc, "External",
  182             sizeof(sc->sc_sensor[ADMCTS_EXT2].desc));
  183 
  184         sc->sc_sensor[ADMCTS_V3_3stby].type = SENSOR_VOLTS_DC;
  185         strlcpy(sc->sc_sensor[ADMCTS_V3_3stby].desc, "3.3 V standby",
  186             sizeof(sc->sc_sensor[ADMCTS_V3_3stby].desc));
  187 
  188         sc->sc_sensor[ADMCTS_V3_3main].type = SENSOR_VOLTS_DC;
  189         strlcpy(sc->sc_sensor[ADMCTS_V3_3main].desc, "3.3 V main",
  190             sizeof(sc->sc_sensor[ADMCTS_V3_3main].desc));
  191 
  192         sc->sc_sensor[ADMCTS_V5].type = SENSOR_VOLTS_DC;
  193         strlcpy(sc->sc_sensor[ADMCTS_V5].desc, "5 V",
  194             sizeof(sc->sc_sensor[ADMCTS_V5].desc));
  195 
  196         sc->sc_sensor[ADMCTS_Vccp].type = SENSOR_VOLTS_DC;
  197         strlcpy(sc->sc_sensor[ADMCTS_Vccp].desc, "Vccp",
  198             sizeof(sc->sc_sensor[ADMCTS_Vccp].desc));
  199 
  200         sc->sc_sensor[ADMCTS_V12].type = SENSOR_VOLTS_DC;
  201         strlcpy(sc->sc_sensor[ADMCTS_V12].desc, "12 V",
  202             sizeof(sc->sc_sensor[ADMCTS_V12].desc));
  203 
  204         sc->sc_sensor[ADMCTS_Vminus12].type = SENSOR_VOLTS_DC;
  205         strlcpy(sc->sc_sensor[ADMCTS_Vminus12].desc, "-12 V",
  206             sizeof(sc->sc_sensor[ADMCTS_Vminus12].desc));
  207 
  208         sc->sc_sensor[ADMCTS_FAN1].type = SENSOR_FANRPM;
  209         sc->sc_sensor[ADMCTS_FAN2].type = SENSOR_FANRPM;
  210         sc->sc_sensor[ADMCTS_FAN3].type = SENSOR_FANRPM;
  211         sc->sc_sensor[ADMCTS_FAN4].type = SENSOR_FANRPM;
  212         sc->sc_sensor[ADMCTS_FAN5].type = SENSOR_FANRPM;
  213         sc->sc_sensor[ADMCTS_FAN6].type = SENSOR_FANRPM;
  214         sc->sc_sensor[ADMCTS_FAN7].type = SENSOR_FANRPM;
  215 
  216         if (sensor_task_register(sc, admcts_refresh, 5) == NULL) {
  217                 printf(", unable to register update task\n");
  218                 return;
  219         }
  220 
  221         for (i = 0; i < ADMCTS_NUM_SENSORS; i++)
  222                 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
  223         sensordev_install(&sc->sc_sensordev);
  224 
  225         printf("\n");
  226 }
  227 
  228 static void
  229 fanval(struct ksensor *sens, int mul, u_int8_t data)
  230 {
  231         int tmp = data * mul;
  232 
  233         if (tmp == 0)
  234                 sens->flags |= SENSOR_FINVALID;
  235         else
  236                 sens->value = 1350000 / tmp;
  237 }
  238 
  239 void
  240 admcts_refresh(void *arg)
  241 {
  242         struct admcts_softc *sc = arg;
  243         u_int8_t cmd, data;
  244         int8_t sdata;
  245 
  246         iic_acquire_bus(sc->sc_tag, 0);
  247 
  248         cmd = ADM1026_TEMP;
  249         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  250             sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
  251                 sc->sc_sensor[ADMCTS_TEMP].value = 273150000 + 1000000 * sdata;
  252 
  253         cmd = ADM1026_EXT1;
  254         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  255             sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
  256                 sc->sc_sensor[ADMCTS_EXT1].value = 273150000 + 1000000 * sdata;
  257 
  258         cmd = ADM1026_EXT2;
  259         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  260             sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0)
  261                 sc->sc_sensor[ADMCTS_EXT2].value = 273150000 + 1000000 * sdata;
  262 
  263         cmd = ADM1026_Vbat;
  264         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  265             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  266                 sc->sc_sensor[ADMCTS_Vbat].value = 3000000 * data / 192;
  267 
  268         cmd = ADM1026_V3_3stby;
  269         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  270             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  271                 sc->sc_sensor[ADMCTS_V3_3stby].value = 3300000 * data / 192;
  272 
  273         cmd = ADM1026_V3_3main;
  274         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  275             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  276                 sc->sc_sensor[ADMCTS_V3_3main].value = 3300000 * data / 192;
  277 
  278         cmd = ADM1026_V5;
  279         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  280             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  281                 sc->sc_sensor[ADMCTS_V5].value = 5500000 * data / 192;
  282 
  283         cmd = ADM1026_Vccp;
  284         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  285             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  286                 sc->sc_sensor[ADMCTS_Vccp].value = 2250000 * data / 192;
  287 
  288         cmd = ADM1026_V12;
  289         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  290             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  291                 sc->sc_sensor[ADMCTS_V12].value = 12000000 * data / 192;
  292 
  293         cmd = ADM1026_Vminus12;
  294         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  295             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  296                 sc->sc_sensor[ADMCTS_Vminus12].value = -2125000 * data / 192;
  297 
  298         cmd = ADM1026_FAN0;
  299         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  300             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  301                 fanval(&sc->sc_sensor[ADMCTS_FAN0], sc->sc_fanmul[0], data);
  302 
  303         cmd = ADM1026_FAN1;
  304         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  305             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  306                 fanval(&sc->sc_sensor[ADMCTS_FAN1], sc->sc_fanmul[1], data);
  307 
  308         cmd = ADM1026_FAN2;
  309         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  310             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  311                 fanval(&sc->sc_sensor[ADMCTS_FAN2], sc->sc_fanmul[2], data);
  312 
  313         cmd = ADM1026_FAN3;
  314         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  315             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  316                 fanval(&sc->sc_sensor[ADMCTS_FAN3], sc->sc_fanmul[3], data);
  317 
  318         cmd = ADM1026_FAN4;
  319         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  320             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  321                 fanval(&sc->sc_sensor[ADMCTS_FAN4], sc->sc_fanmul[4], data);
  322 
  323         cmd = ADM1026_FAN5;
  324         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  325             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  326                 fanval(&sc->sc_sensor[ADMCTS_FAN5], sc->sc_fanmul[5], data);
  327 
  328         cmd = ADM1026_FAN6;
  329         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  330             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  331                 fanval(&sc->sc_sensor[ADMCTS_FAN6], sc->sc_fanmul[6], data);
  332 
  333         cmd = ADM1026_FAN7;
  334         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  335             sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0)
  336                 fanval(&sc->sc_sensor[ADMCTS_FAN7], sc->sc_fanmul[7], data);
  337 
  338         iic_release_bus(sc->sc_tag, 0);
  339 }

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