[BACK]Return to fcu.c CVS log [TXT][DIR] Up to [local] / sys / dev / i2c

Annotation of sys/dev/i2c/fcu.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb