Annotation of sys/dev/i2c/ad741x.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: ad741x.c,v 1.12 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: /* AD741x registers */
! 27: #define AD741X_TEMP 0x00
! 28: #define AD741X_CONFIG 0x01
! 29: #define AD741X_THYST 0x02
! 30: #define AD741X_TOTI 0x03
! 31: #define AD741X_ADC 0x04
! 32: #define AD741X_CONFIG2 0x05
! 33:
! 34: #define AD741X_CONFMASK 0xe0
! 35:
! 36: /* Sensors */
! 37: #define ADC_TEMP 0
! 38: #define ADC_ADC0 1
! 39: #define ADC_ADC1 2
! 40: #define ADC_ADC2 3
! 41: #define ADC_ADC3 4
! 42: #define ADC_MAX_SENSORS 5
! 43:
! 44: struct adc_softc {
! 45: struct device sc_dev;
! 46: i2c_tag_t sc_tag;
! 47: i2c_addr_t sc_addr;
! 48: int sc_chip;
! 49: u_int8_t sc_config;
! 50:
! 51: struct ksensor sc_sensor[ADC_MAX_SENSORS];
! 52: struct ksensordev sc_sensordev;
! 53: };
! 54:
! 55: int adc_match(struct device *, void *, void *);
! 56: void adc_attach(struct device *, struct device *, void *);
! 57: int adc_check(struct i2c_attach_args *, u_int8_t *, u_int8_t *);
! 58: void adc_refresh(void *);
! 59:
! 60: struct cfattach adc_ca = {
! 61: sizeof(struct adc_softc), adc_match, adc_attach
! 62: };
! 63:
! 64: struct cfdriver adc_cd = {
! 65: NULL, "adc", DV_DULL
! 66: };
! 67:
! 68: int
! 69: adc_match(struct device *parent, void *match, void *aux)
! 70: {
! 71: struct i2c_attach_args *ia = aux;
! 72:
! 73: if (strcmp(ia->ia_name, "ad7417") == 0 ||
! 74: strcmp(ia->ia_name, "ad7418") == 0)
! 75: return (1);
! 76: return (0);
! 77: }
! 78:
! 79: void
! 80: adc_attach(struct device *parent, struct device *self, void *aux)
! 81: {
! 82: struct adc_softc *sc = (struct adc_softc *)self;
! 83: struct i2c_attach_args *ia = aux;
! 84: u_int8_t cmd, data;
! 85: int nsens = 0, i;
! 86:
! 87: sc->sc_tag = ia->ia_tag;
! 88: sc->sc_addr = ia->ia_addr;
! 89:
! 90: printf(": %s", ia->ia_name);
! 91:
! 92: sc->sc_chip = 0;
! 93: if (strcmp(ia->ia_name, "ad7417") == 0)
! 94: sc->sc_chip = 7417;
! 95: if (strcmp(ia->ia_name, "ad7418") == 0)
! 96: sc->sc_chip = 7418;
! 97:
! 98: if (sc->sc_chip != 0) {
! 99: cmd = AD741X_CONFIG2;
! 100: data = 0;
! 101: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
! 102: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
! 103: printf(", config2 reset failed\n");
! 104: return;
! 105: }
! 106: }
! 107:
! 108: cmd = AD741X_CONFIG;
! 109: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
! 110: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
! 111: printf(", config reset failed\n");
! 112: return;
! 113: }
! 114: data &= 0xfe;
! 115: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
! 116: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) {
! 117: printf(", config reset failed\n");
! 118: return;
! 119: }
! 120: sc->sc_config = data;
! 121:
! 122: /* Initialize sensor data. */
! 123: strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname,
! 124: sizeof(sc->sc_sensordev.xname));
! 125:
! 126: sc->sc_sensor[ADC_TEMP].type = SENSOR_TEMP;
! 127: strlcpy(sc->sc_sensor[ADC_TEMP].desc, "Internal",
! 128: sizeof(sc->sc_sensor[ADC_TEMP].desc));
! 129: nsens = 1;
! 130:
! 131: if (sc->sc_chip == 7417 || sc->sc_chip == 7418) {
! 132: sc->sc_sensor[ADC_ADC0].type = SENSOR_INTEGER;
! 133: nsens++;
! 134: }
! 135: if (sc->sc_chip == 7417 || sc->sc_chip == 7418) {
! 136: sc->sc_sensor[ADC_ADC1].type = SENSOR_INTEGER;
! 137: sc->sc_sensor[ADC_ADC2].type = SENSOR_INTEGER;
! 138: sc->sc_sensor[ADC_ADC3].type = SENSOR_INTEGER;
! 139: nsens += 3;
! 140: }
! 141:
! 142: if (sensor_task_register(sc, adc_refresh, 5) == NULL) {
! 143: printf(", unable to register update task\n");
! 144: return;
! 145: }
! 146:
! 147: sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[0]);
! 148: if (sc->sc_chip == 7417 || sc->sc_chip == 7418)
! 149: sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[1]);
! 150: if (sc->sc_chip == 7417)
! 151: for (i = 2; i < nsens; i++)
! 152: sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]);
! 153: sensordev_install(&sc->sc_sensordev);
! 154:
! 155: printf("\n");
! 156: }
! 157:
! 158: void
! 159: adc_refresh(void *arg)
! 160: {
! 161: struct adc_softc *sc = arg;
! 162: u_int8_t cmd, data[2], reg;
! 163: int i;
! 164:
! 165: iic_acquire_bus(sc->sc_tag, 0);
! 166:
! 167: reg = (sc->sc_config & AD741X_CONFMASK) | (0 << 5);
! 168: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
! 169: sc->sc_addr, &cmd, sizeof cmd, ®, sizeof reg, 0))
! 170: goto done;
! 171: delay(1000);
! 172: cmd = AD741X_TEMP;
! 173: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
! 174: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0))
! 175: goto done;
! 176: sc->sc_sensor[ADC_TEMP].value = 273150000 +
! 177: ((data[0] << 8 | data[1]) >> 6) * 250000;
! 178:
! 179: if (sc->sc_chip == 0)
! 180: goto done;
! 181:
! 182: if (sc->sc_chip == 7418) {
! 183: reg = (reg & AD741X_CONFMASK) | (4 << 5);
! 184: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
! 185: sc->sc_addr, &cmd, sizeof cmd, ®, sizeof reg, 0))
! 186: goto done;
! 187: delay(1000);
! 188: cmd = AD741X_ADC;
! 189: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
! 190: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0))
! 191: goto done;
! 192: sc->sc_sensor[ADC_ADC0].value =
! 193: (data[0] << 8 | data[1]) >> 6;
! 194: goto done;
! 195: }
! 196:
! 197: for (i = 0; i < 4; i++) {
! 198: reg = (reg & AD741X_CONFMASK) | (i << 5);
! 199: if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
! 200: sc->sc_addr, &cmd, sizeof cmd, ®, sizeof reg, 0))
! 201: goto done;
! 202: delay(1000);
! 203: cmd = AD741X_ADC;
! 204: if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
! 205: sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0))
! 206: goto done;
! 207: sc->sc_sensor[ADC_ADC0 + i].value =
! 208: (data[0] << 8 | data[1]) >> 6;
! 209: }
! 210:
! 211: done:
! 212: iic_release_bus(sc->sc_tag, 0);
! 213: }
CVSweb