[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     ! 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