1 /* $OpenBSD: adm1024.c,v 1.14 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 1024 registers */ 27 #define ADM1024_V2_5 0x20 28 #define ADM1024_Vccp 0x21 29 #define ADM1024_Vcc 0x22 30 #define ADM1024_V5 0x23 31 #define ADM1024_V12 0x24 32 #define ADM1024_Vccp2 0x25 33 #define ADM1024_EXT_TEMP 0x26 34 #define ADM1024_INT_TEMP 0x27 35 #define ADM1024_FAN1 0x28 36 #define ADM1024_FAN2 0x29 37 #define ADM1024_STATUS2 0x42 38 #define ADM1024_FANC 0x47 39 #define ADM1024_STATUS2_EXT 0x40 40 #define ADM1024_COMPANY 0x3e /* contains 0x41 */ 41 #define ADM1024_STEPPING 0x3f /* contains 0x2? */ 42 #define ADM1024_CONFIG1 0x40 43 #define ADM1024_CONFIG1_START 0x01 44 #define ADM1024_CONFIG1_INTCLR 0x08 45 46 /* Sensors */ 47 #define ADMLC_INT 0 48 #define ADMLC_EXT 1 49 #define ADMLC_V2_5 2 50 #define ADMLC_Vccp 3 51 #define ADMLC_Vcc 4 52 #define ADMLC_V5 5 53 #define ADMLC_V12 6 54 #define ADMLC_Vccp2 7 55 #define ADMLC_FAN1 8 56 #define ADMLC_FAN2 9 57 #define ADMLC_NUM_SENSORS 10 58 59 struct admlc_softc { 60 struct device sc_dev; 61 i2c_tag_t sc_tag; 62 i2c_addr_t sc_addr; 63 64 struct ksensor sc_sensor[ADMLC_NUM_SENSORS]; 65 struct ksensordev sc_sensordev; 66 int sc_fan1mul; 67 int sc_fan2mul; 68 }; 69 70 int admlc_match(struct device *, void *, void *); 71 void admlc_attach(struct device *, struct device *, void *); 72 void admlc_refresh(void *); 73 74 struct cfattach admlc_ca = { 75 sizeof(struct admlc_softc), admlc_match, admlc_attach 76 }; 77 78 struct cfdriver admlc_cd = { 79 NULL, "admlc", DV_DULL 80 }; 81 82 int 83 admlc_match(struct device *parent, void *match, void *aux) 84 { 85 struct i2c_attach_args *ia = aux; 86 87 if (strcmp(ia->ia_name, "adm1024") == 0) 88 return (1); 89 return (0); 90 } 91 92 void 93 admlc_attach(struct device *parent, struct device *self, void *aux) 94 { 95 struct admlc_softc *sc = (struct admlc_softc *)self; 96 struct i2c_attach_args *ia = aux; 97 u_int8_t cmd, data, data2; 98 int i; 99 100 sc->sc_tag = ia->ia_tag; 101 sc->sc_addr = ia->ia_addr; 102 103 iic_acquire_bus(sc->sc_tag, 0); 104 cmd = ADM1024_CONFIG1; 105 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 106 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 107 iic_release_bus(sc->sc_tag, 0); 108 printf(": cannot get control register\n"); 109 return; 110 } 111 data2 = data | ADM1024_CONFIG1_START; 112 data2 = data2 & ~ADM1024_CONFIG1_INTCLR; 113 if (data != data2) { 114 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 115 sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) { 116 iic_release_bus(sc->sc_tag, 0); 117 printf(": cannot set control register\n"); 118 return; 119 } 120 } 121 122 cmd = ADM1024_FANC; 123 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 124 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 125 printf(", unable to read fan setting\n"); 126 return; 127 } 128 sc->sc_fan1mul = (1 << (data >> 4) & 0x3); 129 sc->sc_fan2mul = (1 << (data >> 6) & 0x3); 130 131 iic_release_bus(sc->sc_tag, 0); 132 133 /* Initialize sensor data. */ 134 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 135 sizeof(sc->sc_sensordev.xname)); 136 137 sc->sc_sensor[ADMLC_INT].type = SENSOR_TEMP; 138 strlcpy(sc->sc_sensor[ADMLC_INT].desc, "Internal", 139 sizeof(sc->sc_sensor[ADMLC_INT].desc)); 140 141 sc->sc_sensor[ADMLC_EXT].type = SENSOR_TEMP; 142 strlcpy(sc->sc_sensor[ADMLC_EXT].desc, "External", 143 sizeof(sc->sc_sensor[ADMLC_EXT].desc)); 144 145 sc->sc_sensor[ADMLC_V2_5].type = SENSOR_VOLTS_DC; 146 strlcpy(sc->sc_sensor[ADMLC_V2_5].desc, "2.5 V", 147 sizeof(sc->sc_sensor[ADMLC_V2_5].desc)); 148 149 sc->sc_sensor[ADMLC_Vccp].type = SENSOR_VOLTS_DC; 150 strlcpy(sc->sc_sensor[ADMLC_Vccp].desc, "Vccp", 151 sizeof(sc->sc_sensor[ADMLC_Vccp].desc)); 152 153 sc->sc_sensor[ADMLC_Vcc].type = SENSOR_VOLTS_DC; 154 strlcpy(sc->sc_sensor[ADMLC_Vcc].desc, "Vcc", 155 sizeof(sc->sc_sensor[ADMLC_Vcc].desc)); 156 157 sc->sc_sensor[ADMLC_V5].type = SENSOR_VOLTS_DC; 158 strlcpy(sc->sc_sensor[ADMLC_V5].desc, "5 V", 159 sizeof(sc->sc_sensor[ADMLC_V5].desc)); 160 161 sc->sc_sensor[ADMLC_V12].type = SENSOR_VOLTS_DC; 162 strlcpy(sc->sc_sensor[ADMLC_V12].desc, "12 V", 163 sizeof(sc->sc_sensor[ADMLC_V12].desc)); 164 165 sc->sc_sensor[ADMLC_Vccp2].type = SENSOR_VOLTS_DC; 166 strlcpy(sc->sc_sensor[ADMLC_Vccp2].desc, "Vccp2", 167 sizeof(sc->sc_sensor[ADMLC_Vccp2].desc)); 168 169 sc->sc_sensor[ADMLC_FAN1].type = SENSOR_FANRPM; 170 171 sc->sc_sensor[ADMLC_FAN2].type = SENSOR_FANRPM; 172 173 174 if (sensor_task_register(sc, admlc_refresh, 5) == NULL) { 175 printf(", unable to register update task\n"); 176 return; 177 } 178 179 for (i = 0; i < ADMLC_NUM_SENSORS; i++) 180 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]); 181 sensordev_install(&sc->sc_sensordev); 182 183 printf("\n"); 184 } 185 186 static void 187 fanval(struct ksensor *sens, int mul, u_int8_t data) 188 { 189 int tmp = data * mul; 190 191 if (tmp == 0) 192 sens->flags |= SENSOR_FINVALID; 193 else 194 sens->value = 1350000 / tmp; 195 } 196 197 void 198 admlc_refresh(void *arg) 199 { 200 struct admlc_softc *sc = arg; 201 u_int8_t cmd, data; 202 int8_t sdata; 203 204 iic_acquire_bus(sc->sc_tag, 0); 205 206 cmd = ADM1024_INT_TEMP; 207 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 208 sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0) 209 sc->sc_sensor[ADMLC_INT].value = 273150000 + 1000000 * sdata; 210 211 cmd = ADM1024_EXT_TEMP; 212 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 213 sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0) 214 sc->sc_sensor[ADMLC_EXT].value = 273150000 + 1000000 * sdata; 215 216 cmd = ADM1024_STATUS2; 217 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 218 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) { 219 if (data & ADM1024_STATUS2_EXT) 220 sc->sc_sensor[ADMLC_EXT].flags |= SENSOR_FINVALID; 221 else 222 sc->sc_sensor[ADMLC_EXT].flags &= ~SENSOR_FINVALID; 223 } 224 225 cmd = ADM1024_V2_5; 226 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 227 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 228 sc->sc_sensor[ADMLC_V2_5].value = 2500000 * data / 192; 229 230 cmd = ADM1024_Vccp; 231 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 232 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 233 sc->sc_sensor[ADMLC_Vcc].value = 2249000 * data / 192; 234 235 cmd = ADM1024_Vcc; 236 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 237 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 238 sc->sc_sensor[ADMLC_Vcc].value = 3300000 * data / 192; 239 240 cmd = ADM1024_V5; 241 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 242 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 243 sc->sc_sensor[ADMLC_V5].value = 5000000 * data / 192; 244 245 cmd = ADM1024_V12; 246 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 247 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 248 sc->sc_sensor[ADMLC_V12].value = 12000000 * data / 192; 249 250 cmd = ADM1024_Vccp2; 251 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 252 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 253 sc->sc_sensor[ADMLC_Vccp2].value = 2700000 * data / 192; 254 255 cmd = ADM1024_FAN1; 256 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 257 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 258 fanval(&sc->sc_sensor[ADMLC_FAN1], sc->sc_fan1mul, data); 259 260 cmd = ADM1024_FAN2; 261 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 262 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 263 fanval(&sc->sc_sensor[ADMLC_FAN2], sc->sc_fan2mul, data); 264 iic_release_bus(sc->sc_tag, 0); 265 } 266