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

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

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

CVSweb