root/dev/i2c/fcu.c

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

DEFINITIONS

This source file includes following definitions.
  1. fcu_match
  2. fcu_attach
  3. fcu_refresh

    1 /*      $OpenBSD: fcu.c,v 1.7 2007/06/24 05:34:35 dlg Exp $     */
    2 
    3 /*
    4  * Copyright (c) 2005 Mark Kettenis
    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 /* FCU registers */
   27 #define FCU_FAN_FAIL    0x0b            /* fans states in bits 0<1-6>7 */
   28 #define FCU_FAN_ACTIVE  0x0d
   29 #define FCU_FANREAD(x)  0x11 + (x)*2
   30 #define FCU_FANSET(x)   0x10 + (x)*2
   31 #define FCU_PWM_FAIL    0x2b
   32 #define FCU_PWM_ACTIVE  0x2d
   33 #define FCU_PWMREAD(x)  0x30 + (x)*2
   34 
   35 /* Sensors */
   36 #define FCU_RPM1                0
   37 #define FCU_RPM2                1
   38 #define FCU_RPM3                2
   39 #define FCU_RPM4                3
   40 #define FCU_RPM5                4
   41 #define FCU_RPM6                5
   42 #define  FCU_FANS               6
   43 #define FCU_PWM1                6
   44 #define FCU_PWM2                7
   45 #define  FCU_PWMS               2
   46 #define FCU_NUM_SENSORS         8
   47 
   48 struct fcu_softc {
   49         struct device sc_dev;
   50         i2c_tag_t sc_tag;
   51         i2c_addr_t sc_addr;
   52 
   53         struct ksensor sc_sensor[FCU_NUM_SENSORS];
   54         struct ksensordev sc_sensordev;
   55 };
   56 
   57 int     fcu_match(struct device *, void *, void *);
   58 void    fcu_attach(struct device *, struct device *, void *);
   59 
   60 void    fcu_refresh(void *);
   61 
   62 struct cfattach fcu_ca = {
   63         sizeof(struct fcu_softc), fcu_match, fcu_attach
   64 };
   65 
   66 struct cfdriver fcu_cd = {
   67         NULL, "fcu", DV_DULL
   68 };
   69 
   70 int
   71 fcu_match(struct device *parent, void *match, void *aux)
   72 {
   73         struct i2c_attach_args *ia = aux;
   74 
   75         if (strcmp(ia->ia_name, "fcu") == 0)
   76                 return (1);
   77         return (0);
   78 }
   79 
   80 void
   81 fcu_attach(struct device *parent, struct device *self, void *aux)
   82 {
   83         struct fcu_softc *sc = (struct fcu_softc *)self;
   84         struct i2c_attach_args *ia = aux;
   85         int i;
   86 
   87         sc->sc_tag = ia->ia_tag;
   88         sc->sc_addr = ia->ia_addr;
   89 
   90         /* Initialize sensor data. */
   91         strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
   92             sizeof(sc->sc_sensordev.xname));
   93         for (i = 0; i < FCU_FANS; i++)
   94                 sc->sc_sensor[i].type = SENSOR_FANRPM;
   95         for (i = 0; i < FCU_PWMS; i++) {
   96                 sc->sc_sensor[FCU_PWM1 + i].type = SENSOR_PERCENT;
   97                 strlcpy(sc->sc_sensor[FCU_PWM1 + i].desc, "PWM",
   98                     sizeof(sc->sc_sensor[FCU_PWM1 + i].desc));
   99         }
  100 
  101         if (sensor_task_register(sc, fcu_refresh, 5) == NULL) {
  102                 printf(", unable to register update task\n");
  103                 return;
  104         }
  105 
  106         for (i = 0; i < FCU_NUM_SENSORS; i++)
  107                 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
  108         sensordev_install(&sc->sc_sensordev);
  109 
  110         printf("\n");
  111 }
  112 
  113 void
  114 fcu_refresh(void *arg)
  115 {
  116         struct fcu_softc *sc = arg;
  117         u_int8_t cmd, fail, fan[2], active;
  118         int i;
  119 
  120         iic_acquire_bus(sc->sc_tag, 0);
  121 
  122         cmd = FCU_FAN_FAIL;
  123         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  124             sc->sc_addr, &cmd, sizeof cmd, &fail, sizeof fail, 0))
  125                 goto abort;
  126         cmd = FCU_FAN_ACTIVE;
  127         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  128             sc->sc_addr, &cmd, sizeof cmd, &active, sizeof active, 0))
  129                 goto abort;
  130         fail &= active;
  131 
  132         for (i = 0; i < FCU_FANS; i++) {
  133                 if (fail & (1 << (i + 1)))
  134                         sc->sc_sensor[i].flags |= SENSOR_FINVALID;
  135                 else
  136                         sc->sc_sensor[i].flags &= ~SENSOR_FINVALID;
  137         }
  138 
  139         cmd = FCU_PWM_FAIL;
  140         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  141             sc->sc_addr, &cmd, sizeof cmd, &fail, sizeof fail, 0))
  142                 goto abort;
  143         cmd = FCU_PWM_ACTIVE;
  144         if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  145             sc->sc_addr, &cmd, sizeof cmd, &active, sizeof active, 0))
  146                 goto abort;
  147         fail &= active;
  148 
  149         for (i = 0; i < FCU_PWMS; i++) {
  150                 if (fail & (1 << (i + 1)))
  151                         sc->sc_sensor[FCU_PWMS + i].flags |= SENSOR_FINVALID;
  152                 else
  153                         sc->sc_sensor[FCU_PWMS + i].flags &= ~SENSOR_FINVALID;
  154         }
  155 
  156         for (i = 0; i < FCU_FANS; i++) {
  157                 cmd = FCU_FANREAD(i + 1);
  158                 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  159                     sc->sc_addr, &cmd, sizeof cmd, &fan, sizeof fan, 0)) {
  160                         sc->sc_sensor[FCU_RPM1 + i].flags |= SENSOR_FINVALID;
  161                         continue;
  162                 }
  163                 sc->sc_sensor[FCU_RPM1 + i].value = (fan[0] << 5) | (fan[1] >> 3);
  164         }
  165 
  166         for (i = 0; i < FCU_PWMS; i++) {
  167                 cmd = FCU_PWMREAD(i + 1);
  168                 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
  169                     sc->sc_addr, &cmd, sizeof cmd, &fan, sizeof fan, 0)) {
  170                         sc->sc_sensor[FCU_PWM1 + i].flags |= SENSOR_FINVALID;
  171                         continue;
  172                 }
  173                 sc->sc_sensor[FCU_PWM1 + i].value = (fan[0] * 100 * 1000) / 255;
  174         }
  175 
  176 abort:
  177         iic_release_bus(sc->sc_tag, 0);
  178 }

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