1*afa48fb4Sderaadt /* $OpenBSD: ad741x.c,v 1.1 2005/11/15 18:28:05 deraadt Exp $ */ 2*afa48fb4Sderaadt 3*afa48fb4Sderaadt /* 4*afa48fb4Sderaadt * Copyright (c) 2005 Theo de Raadt 5*afa48fb4Sderaadt * 6*afa48fb4Sderaadt * Permission to use, copy, modify, and distribute this software for any 7*afa48fb4Sderaadt * purpose with or without fee is hereby granted, provided that the above 8*afa48fb4Sderaadt * copyright notice and this permission notice appear in all copies. 9*afa48fb4Sderaadt * 10*afa48fb4Sderaadt * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11*afa48fb4Sderaadt * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12*afa48fb4Sderaadt * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13*afa48fb4Sderaadt * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14*afa48fb4Sderaadt * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15*afa48fb4Sderaadt * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16*afa48fb4Sderaadt * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17*afa48fb4Sderaadt */ 18*afa48fb4Sderaadt 19*afa48fb4Sderaadt #include <sys/param.h> 20*afa48fb4Sderaadt #include <sys/systm.h> 21*afa48fb4Sderaadt #include <sys/device.h> 22*afa48fb4Sderaadt #include <sys/sensors.h> 23*afa48fb4Sderaadt 24*afa48fb4Sderaadt #include <dev/i2c/i2cvar.h> 25*afa48fb4Sderaadt 26*afa48fb4Sderaadt /* AD741x registers */ 27*afa48fb4Sderaadt #define AD741X_TEMP 0x00 28*afa48fb4Sderaadt #define AD741X_CONFIG 0x01 29*afa48fb4Sderaadt #define AD741X_THYST 0x02 30*afa48fb4Sderaadt #define AD741X_TOTI 0x03 31*afa48fb4Sderaadt #define AD741X_ADC 0x04 32*afa48fb4Sderaadt #define AD741X_CONFIG2 0x05 33*afa48fb4Sderaadt 34*afa48fb4Sderaadt #define AD741X_CONFMASK 0xe0 35*afa48fb4Sderaadt 36*afa48fb4Sderaadt /* Sensors */ 37*afa48fb4Sderaadt #define ADC_TEMP 0 38*afa48fb4Sderaadt #define ADC_ADC0 1 39*afa48fb4Sderaadt #define ADC_ADC1 2 40*afa48fb4Sderaadt #define ADC_ADC2 3 41*afa48fb4Sderaadt #define ADC_ADC3 4 42*afa48fb4Sderaadt #define ADC_NUM_SENSORS 5 43*afa48fb4Sderaadt 44*afa48fb4Sderaadt struct adc_softc { 45*afa48fb4Sderaadt struct device sc_dev; 46*afa48fb4Sderaadt i2c_tag_t sc_tag; 47*afa48fb4Sderaadt i2c_addr_t sc_addr; 48*afa48fb4Sderaadt 49*afa48fb4Sderaadt struct sensor sc_sensor[ADC_NUM_SENSORS]; 50*afa48fb4Sderaadt }; 51*afa48fb4Sderaadt 52*afa48fb4Sderaadt int adc_match(struct device *, void *, void *); 53*afa48fb4Sderaadt void adc_attach(struct device *, struct device *, void *); 54*afa48fb4Sderaadt int adc_check(struct i2c_attach_args *, u_int8_t *, u_int8_t *); 55*afa48fb4Sderaadt void adc_refresh(void *); 56*afa48fb4Sderaadt 57*afa48fb4Sderaadt struct cfattach adc_ca = { 58*afa48fb4Sderaadt sizeof(struct adc_softc), adc_match, adc_attach 59*afa48fb4Sderaadt }; 60*afa48fb4Sderaadt 61*afa48fb4Sderaadt struct cfdriver adc_cd = { 62*afa48fb4Sderaadt NULL, "adc", DV_DULL 63*afa48fb4Sderaadt }; 64*afa48fb4Sderaadt 65*afa48fb4Sderaadt int 66*afa48fb4Sderaadt adc_match(struct device *parent, void *match, void *aux) 67*afa48fb4Sderaadt { 68*afa48fb4Sderaadt struct i2c_attach_args *ia = aux; 69*afa48fb4Sderaadt 70*afa48fb4Sderaadt if (ia->ia_compat) { 71*afa48fb4Sderaadt if (strcmp(ia->ia_compat, "ad7417") == 0) 72*afa48fb4Sderaadt return (1); 73*afa48fb4Sderaadt return (0); 74*afa48fb4Sderaadt } 75*afa48fb4Sderaadt return (1); 76*afa48fb4Sderaadt } 77*afa48fb4Sderaadt 78*afa48fb4Sderaadt void 79*afa48fb4Sderaadt adc_attach(struct device *parent, struct device *self, void *aux) 80*afa48fb4Sderaadt { 81*afa48fb4Sderaadt struct adc_softc *sc = (struct adc_softc *)self; 82*afa48fb4Sderaadt struct i2c_attach_args *ia = aux; 83*afa48fb4Sderaadt u_int8_t cmd, data; 84*afa48fb4Sderaadt int i; 85*afa48fb4Sderaadt 86*afa48fb4Sderaadt sc->sc_tag = ia->ia_tag; 87*afa48fb4Sderaadt sc->sc_addr = ia->ia_addr; 88*afa48fb4Sderaadt 89*afa48fb4Sderaadt cmd = AD741X_CONFIG; 90*afa48fb4Sderaadt data = 0; 91*afa48fb4Sderaadt if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 92*afa48fb4Sderaadt sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 93*afa48fb4Sderaadt printf(", config reset failed\n"); 94*afa48fb4Sderaadt return; 95*afa48fb4Sderaadt } 96*afa48fb4Sderaadt 97*afa48fb4Sderaadt cmd = AD741X_CONFIG2; 98*afa48fb4Sderaadt data = 0; 99*afa48fb4Sderaadt if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 100*afa48fb4Sderaadt sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 101*afa48fb4Sderaadt printf(", config2 reset failed\n"); 102*afa48fb4Sderaadt return; 103*afa48fb4Sderaadt } 104*afa48fb4Sderaadt 105*afa48fb4Sderaadt /* Initialize sensor data. */ 106*afa48fb4Sderaadt for (i = 0; i < ADC_NUM_SENSORS; i++) 107*afa48fb4Sderaadt strlcpy(sc->sc_sensor[i].device, sc->sc_dev.dv_xname, 108*afa48fb4Sderaadt sizeof(sc->sc_sensor[i].device)); 109*afa48fb4Sderaadt 110*afa48fb4Sderaadt sc->sc_sensor[ADC_TEMP].type = SENSOR_TEMP; 111*afa48fb4Sderaadt strlcpy(sc->sc_sensor[ADC_TEMP].desc, "Internal", 112*afa48fb4Sderaadt sizeof(sc->sc_sensor[ADC_TEMP].desc)); 113*afa48fb4Sderaadt 114*afa48fb4Sderaadt sc->sc_sensor[ADC_ADC0].type = SENSOR_INTEGER; 115*afa48fb4Sderaadt strlcpy(sc->sc_sensor[ADC_ADC0].desc, "adc0", 116*afa48fb4Sderaadt sizeof(sc->sc_sensor[ADC_ADC0].desc)); 117*afa48fb4Sderaadt sc->sc_sensor[ADC_ADC1].type = SENSOR_INTEGER; 118*afa48fb4Sderaadt strlcpy(sc->sc_sensor[ADC_ADC1].desc, "adc1", 119*afa48fb4Sderaadt sizeof(sc->sc_sensor[ADC_ADC1].desc)); 120*afa48fb4Sderaadt sc->sc_sensor[ADC_ADC2].type = SENSOR_INTEGER; 121*afa48fb4Sderaadt strlcpy(sc->sc_sensor[ADC_ADC2].desc, "adc2", 122*afa48fb4Sderaadt sizeof(sc->sc_sensor[ADC_ADC2].desc)); 123*afa48fb4Sderaadt sc->sc_sensor[ADC_ADC3].type = SENSOR_INTEGER; 124*afa48fb4Sderaadt strlcpy(sc->sc_sensor[ADC_ADC3].desc, "adc3", 125*afa48fb4Sderaadt sizeof(sc->sc_sensor[ADC_ADC3].desc)); 126*afa48fb4Sderaadt 127*afa48fb4Sderaadt if (sensor_task_register(sc, adc_refresh, 5)) { 128*afa48fb4Sderaadt printf(", unable to register update task\n"); 129*afa48fb4Sderaadt return; 130*afa48fb4Sderaadt } 131*afa48fb4Sderaadt 132*afa48fb4Sderaadt for (i = 0; i < ADC_NUM_SENSORS; i++) 133*afa48fb4Sderaadt SENSOR_ADD(&sc->sc_sensor[i]); 134*afa48fb4Sderaadt 135*afa48fb4Sderaadt printf("\n"); 136*afa48fb4Sderaadt } 137*afa48fb4Sderaadt 138*afa48fb4Sderaadt void adc_readport(struct adc_softc *, u_int8_t, u_int8_t, int); 139*afa48fb4Sderaadt 140*afa48fb4Sderaadt void 141*afa48fb4Sderaadt adc_refresh(void *arg) 142*afa48fb4Sderaadt { 143*afa48fb4Sderaadt struct adc_softc *sc = arg; 144*afa48fb4Sderaadt u_int8_t cmd, data[2], reg; 145*afa48fb4Sderaadt int i; 146*afa48fb4Sderaadt 147*afa48fb4Sderaadt iic_acquire_bus(sc->sc_tag, 0); 148*afa48fb4Sderaadt 149*afa48fb4Sderaadt cmd = AD741X_CONFIG; 150*afa48fb4Sderaadt if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 151*afa48fb4Sderaadt sc->sc_addr, &cmd, sizeof cmd, ®, sizeof reg, 0)) 152*afa48fb4Sderaadt goto fail; 153*afa48fb4Sderaadt reg = (reg & AD741X_CONFMASK) | (0 << 5); 154*afa48fb4Sderaadt if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 155*afa48fb4Sderaadt sc->sc_addr, &cmd, sizeof cmd, ®, sizeof reg, 0)) 156*afa48fb4Sderaadt goto fail; 157*afa48fb4Sderaadt cmd = AD741X_TEMP; 158*afa48fb4Sderaadt if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 159*afa48fb4Sderaadt sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) 160*afa48fb4Sderaadt goto fail; 161*afa48fb4Sderaadt sc->sc_sensor[ADC_TEMP].value = 273150000 + 162*afa48fb4Sderaadt ((data[0] << 8 | data[1]) >> 6) * 250000; 163*afa48fb4Sderaadt 164*afa48fb4Sderaadt for (i = 0; i < 4; i++) { 165*afa48fb4Sderaadt reg = (reg & AD741X_CONFMASK) | (i << 5); 166*afa48fb4Sderaadt if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 167*afa48fb4Sderaadt sc->sc_addr, &cmd, sizeof cmd, ®, sizeof reg, 0)) 168*afa48fb4Sderaadt goto fail; 169*afa48fb4Sderaadt cmd = AD741X_ADC; 170*afa48fb4Sderaadt if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 171*afa48fb4Sderaadt sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) 172*afa48fb4Sderaadt goto fail; 173*afa48fb4Sderaadt sc->sc_sensor[ADC_ADC0 + i].value = 174*afa48fb4Sderaadt (data[0] << 8 | data[1]) >> 6; 175*afa48fb4Sderaadt } 176*afa48fb4Sderaadt 177*afa48fb4Sderaadt fail: 178*afa48fb4Sderaadt iic_release_bus(sc->sc_tag, 0); 179*afa48fb4Sderaadt } 180