Annotation of sys/dev/i2c/fcu.c, Revision 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