Annotation of sys/dev/i2c/maxim6690.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: maxim6690.c,v 1.15 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: /* Maxim MAX6642/90 registers */
! 27: #define MAX6690_INT_TEMP 0x00
! 28: #define MAX6690_EXT_TEMP 0x01
! 29: #define MAX6690_INT_TEMP2 0x11
! 30: #define MAX6690_EXT_TEMP2 0x10
! 31: #define MAX6690_STATUS 0x02
! 32: #define MAX6690_DEVID 0xfe
! 33: #define MAX6690_REVISION 0xff /* absent on MAX6642 */
! 34:
! 35: #define MAX6642_TEMP_INVALID 0xff /* sensor disconnected */
! 36: #define MAX6690_TEMP_INVALID 0x80 /* sensor disconnected */
! 37: #define MAX6690_TEMP_INVALID2 0x7f /* open-circuit without pull-up */
! 38: #define LM90_TEMP_INVALID 0x7f /* sensor disconnected */
! 39:
! 40: #define MAX6642_TEMP2_MASK 0xc0 /* significant bits */
! 41: #define MAX6690_TEMP2_MASK 0xe0 /* significant bits */
! 42: #define LM90_TEMP2_MASK 0xe0 /* significant bits */
! 43:
! 44: /* Sensors */
! 45: #define MAXTMP_INT 0
! 46: #define MAXTMP_EXT 1
! 47: #define MAXTMP_NUM_SENSORS 2
! 48:
! 49: struct maxtmp_softc {
! 50: struct device sc_dev;
! 51: i2c_tag_t sc_tag;
! 52: i2c_addr_t sc_addr;
! 53:
! 54: u_int8_t sc_temp_invalid[2];
! 55: u_int8_t sc_temp2_mask;
! 56:
! 57: struct ksensor sc_sensor[MAXTMP_NUM_SENSORS];
! 58: struct ksensordev sc_sensordev;
! 59: };
! 60:
! 61: int maxtmp_match(struct device *, void *, void *);
! 62: void maxtmp_attach(struct device *, struct device *, void *);
! 63: int maxtmp_check(struct i2c_attach_args *, u_int8_t *, u_int8_t *);
! 64: void maxtmp_refresh(void *);
! 65:
! 66: struct cfattach maxtmp_ca = {
! 67: sizeof(struct maxtmp_softc), maxtmp_match, maxtmp_attach
! 68: };
! 69:
! 70: struct cfdriver maxtmp_cd = {
! 71: NULL, "maxtmp", DV_DULL
! 72: };
! 73:
! 74: int
! 75: maxtmp_match(struct device *parent, void *match, void *aux)
! 76: {
! 77: struct i2c_attach_args *ia = aux;
! 78:
! 79: if (strcmp(ia->ia_name, "max6642") == 0 ||
! 80: strcmp(ia->ia_name, "max6690") == 0 ||
! 81: strcmp(ia->ia_name, "max6657") == 0 ||
! 82: strcmp(ia->ia_name, "max6658") == 0 ||
! 83: strcmp(ia->ia_name, "max6659") == 0 ||
! 84: strcmp(ia->ia_name, "lm63") == 0 ||
! 85: strcmp(ia->ia_name, "lm86") == 0 ||
! 86: strcmp(ia->ia_name, "lm89") == 0 ||
! 87: strcmp(ia->ia_name, "lm89-1") == 0 ||
! 88: strcmp(ia->ia_name, "lm90") == 0 ||
! 89: strcmp(ia->ia_name, "lm99") == 0 ||
! 90: strcmp(ia->ia_name, "lm99-1") == 0)
! 91: return (1);
! 92: return (0);
! 93: }
! 94:
! 95: void
! 96: maxtmp_attach(struct device *parent, struct device *self, void *aux)
! 97: {
! 98: struct maxtmp_softc *sc = (struct maxtmp_softc *)self;
! 99: struct i2c_attach_args *ia = aux;
! 100: int i;
! 101:
! 102: sc->sc_tag = ia->ia_tag;
! 103: sc->sc_addr = ia->ia_addr;
! 104:
! 105: if (strcmp(ia->ia_name, "max6642") == 0) {
! 106: sc->sc_temp_invalid[0] = MAX6642_TEMP_INVALID;
! 107: sc->sc_temp_invalid[1] = MAX6642_TEMP_INVALID;
! 108: sc->sc_temp2_mask = MAX6642_TEMP2_MASK;
! 109: } else if (strcmp(ia->ia_name, "max6690") == 0 ||
! 110: strcmp(ia->ia_name, "max6657") == 0 ||
! 111: strcmp(ia->ia_name, "max6658") == 0 ||
! 112: strcmp(ia->ia_name, "max6659") == 0) {
! 113: sc->sc_temp_invalid[0] = MAX6690_TEMP_INVALID;
! 114: sc->sc_temp_invalid[1] = MAX6690_TEMP_INVALID2;
! 115: sc->sc_temp2_mask = MAX6690_TEMP2_MASK;
! 116: } else {
! 117: sc->sc_temp_invalid[0] = LM90_TEMP_INVALID;
! 118: sc->sc_temp_invalid[1] = LM90_TEMP_INVALID;
! 119: sc->sc_temp2_mask = LM90_TEMP2_MASK;
! 120: }
! 121: printf(": %s", ia->ia_name);
! 122:
! 123: /* Initialize sensor data. */
! 124: strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
! 125: sizeof(sc->sc_sensordev.xname));
! 126:
! 127: sc->sc_sensor[MAXTMP_INT].type = SENSOR_TEMP;
! 128: strlcpy(sc->sc_sensor[MAXTMP_INT].desc, "Internal",
! 129: sizeof(sc->sc_sensor[MAXTMP_INT].desc));
! 130:
! 131: sc->sc_sensor[MAXTMP_EXT].type = SENSOR_TEMP;
! 132: strlcpy(sc->sc_sensor[MAXTMP_EXT].desc, "External",
! 133: sizeof(sc->sc_sensor[MAXTMP_EXT].desc));
! 134:
! 135: if (sensor_task_register(sc, maxtmp_refresh, 5) == NULL) {
! 136: printf(", unable to register update task\n");
! 137: return;
! 138: }
! 139:
! 140: for (i = 0; i < MAXTMP_NUM_SENSORS; i++)
! 141: sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
! 142: sensordev_install(&sc->sc_sensordev);
! 143:
! 144: printf("\n");
! 145: }
! 146:
! 147: void maxtmp_readport(struct maxtmp_softc *, u_int8_t, u_int8_t, int);
! 148:
! 149: void
! 150: maxtmp_readport(struct maxtmp_softc *sc, u_int8_t cmd1, u_int8_t cmd2,
! 151: int index)
! 152: {
! 153: u_int8_t data, data2;
! 154:
! 155: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
! 156: sc->sc_addr, &cmd1, sizeof cmd1, &data, sizeof data, 0))
! 157: goto invalid;
! 158: if (data == sc->sc_temp_invalid[0] || data == sc->sc_temp_invalid[1])
! 159: goto invalid;
! 160: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
! 161: sc->sc_addr, &cmd2, sizeof cmd2, &data2, sizeof data2, 0))
! 162: goto invalid;
! 163:
! 164: /* Set any meaningless bits to zero. */
! 165: data2 &= sc->sc_temp2_mask;
! 166:
! 167: sc->sc_sensor[index].value = 273150000 +
! 168: 1000000 * data + (data2 >> 5) * 1000000 / 8;
! 169: return;
! 170:
! 171: invalid:
! 172: sc->sc_sensor[index].flags |= SENSOR_FINVALID;
! 173: }
! 174:
! 175: void
! 176: maxtmp_refresh(void *arg)
! 177: {
! 178: struct maxtmp_softc *sc = arg;
! 179:
! 180: iic_acquire_bus(sc->sc_tag, 0);
! 181:
! 182: maxtmp_readport(sc, MAX6690_INT_TEMP, MAX6690_INT_TEMP2, MAXTMP_INT);
! 183: maxtmp_readport(sc, MAX6690_EXT_TEMP, MAX6690_EXT_TEMP2, MAXTMP_EXT);
! 184:
! 185: iic_release_bus(sc->sc_tag, 0);
! 186: }
CVSweb