adm1026.c revision 1.6
1/* $OpenBSD: adm1026.c,v 1.6 2006/01/19 17:08:39 grange 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 1026 registers */ 27#define ADM1026_TEMP 0x1f 28#define ADM1026_STATUS 0x20 29#define ADM1026_Vbat 0x26 30#define ADM1026_Ain8 0x27 31#define ADM1026_EXT1 0x28 32#define ADM1026_EXT2 0x29 33#define ADM1026_V3_3stby 0x2a 34#define ADM1026_V3_3main 0x2b 35#define ADM1026_V5 0x2c 36#define ADM1026_Vccp 0x2d 37#define ADM1026_V12 0x2e 38#define ADM1026_Vminus12 0x2f 39#define ADM1026_FAN0 0x38 40#define ADM1026_FAN1 0x39 41#define ADM1026_FAN2 0x3a 42#define ADM1026_FAN3 0x3b 43#define ADM1026_FAN4 0x3c 44#define ADM1026_FAN5 0x3d 45#define ADM1026_FAN6 0x3e 46#define ADM1026_FAN7 0x3f 47#define ADM1026_EXT1_OFF 0x6e 48#define ADM1026_EXT2_OFF 0x6f 49#define ADM1026_FAN0123DIV 0x02 50#define ADM1026_FAN4567DIV 0x03 51#define ADM1026_CONTROL 0x00 52#define ADM1026_CONTROL_START 0x01 53#define ADM1026_CONTROL_INTCLR 0x04 54 55/* Sensors */ 56#define ADMCTS_TEMP 0 57#define ADMCTS_EXT1 1 58#define ADMCTS_EXT2 2 59#define ADMCTS_Vbat 3 60#define ADMCTS_V3_3stby 4 61#define ADMCTS_V3_3main 5 62#define ADMCTS_V5 6 63#define ADMCTS_Vccp 7 64#define ADMCTS_V12 8 65#define ADMCTS_Vminus12 9 66#define ADMCTS_FAN0 10 67#define ADMCTS_FAN1 11 68#define ADMCTS_FAN2 12 69#define ADMCTS_FAN3 13 70#define ADMCTS_FAN4 14 71#define ADMCTS_FAN5 15 72#define ADMCTS_FAN6 16 73#define ADMCTS_FAN7 17 74#define ADMCTS_NUM_SENSORS 18 75 76struct admcts_softc { 77 struct device sc_dev; 78 i2c_tag_t sc_tag; 79 i2c_addr_t sc_addr; 80 81 struct sensor sc_sensor[ADMCTS_NUM_SENSORS]; 82 int sc_fanmul[8]; 83}; 84 85int admcts_match(struct device *, void *, void *); 86void admcts_attach(struct device *, struct device *, void *); 87void admcts_refresh(void *); 88 89struct cfattach admcts_ca = { 90 sizeof(struct admcts_softc), admcts_match, admcts_attach 91}; 92 93struct cfdriver admcts_cd = { 94 NULL, "admcts", DV_DULL 95}; 96 97int 98admcts_match(struct device *parent, void *match, void *aux) 99{ 100 struct i2c_attach_args *ia = aux; 101 102 if (strcmp(ia->ia_name, "adm1026") == 0) 103 return (1); 104 return (0); 105} 106 107void 108admcts_attach(struct device *parent, struct device *self, void *aux) 109{ 110 struct admcts_softc *sc = (struct admcts_softc *)self; 111 struct i2c_attach_args *ia = aux; 112 u_int8_t cmd, data, data2; 113 int i; 114 115 sc->sc_tag = ia->ia_tag; 116 sc->sc_addr = ia->ia_addr; 117 118 iic_acquire_bus(sc->sc_tag, 0); 119 cmd = ADM1026_CONTROL; 120 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 121 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 122 iic_release_bus(sc->sc_tag, 0); 123 printf(": cannot get control register\n"); 124 return; 125 } 126 data2 = data | ADM1026_CONTROL_START; 127 data2 = data2 & ~ADM1026_CONTROL_INTCLR; 128 if (data != data2) { 129 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 130 sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) { 131 iic_release_bus(sc->sc_tag, 0); 132 printf(": cannot set control register\n"); 133 return; 134 } 135 } 136 137 cmd = ADM1026_FAN0123DIV; 138 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 139 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 140 iic_release_bus(sc->sc_tag, 0); 141 printf(": cannot get fan0123div register\n"); 142 return; 143 } 144 sc->sc_fanmul[0] = (1 << (data >> 0) & 0x3); 145 sc->sc_fanmul[1] = (1 << (data >> 2) & 0x3); 146 sc->sc_fanmul[2] = (1 << (data >> 4) & 0x3); 147 sc->sc_fanmul[3] = (1 << (data >> 6) & 0x3); 148 149 cmd = ADM1026_FAN4567DIV; 150 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 151 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 152 iic_release_bus(sc->sc_tag, 0); 153 printf(": cannot get fan0123div register\n"); 154 return; 155 } 156 sc->sc_fanmul[4] = (1 << (data >> 0) & 0x3); 157 sc->sc_fanmul[5] = (1 << (data >> 2) & 0x3); 158 sc->sc_fanmul[6] = (1 << (data >> 4) & 0x3); 159 sc->sc_fanmul[7] = (1 << (data >> 6) & 0x3); 160 161 iic_release_bus(sc->sc_tag, 0); 162 163 /* Initialize sensor data. */ 164 for (i = 0; i < ADMCTS_NUM_SENSORS; i++) 165 strlcpy(sc->sc_sensor[i].device, sc->sc_dev.dv_xname, 166 sizeof(sc->sc_sensor[i].device)); 167 168 sc->sc_sensor[ADMCTS_TEMP].type = SENSOR_TEMP; 169 strlcpy(sc->sc_sensor[ADMCTS_TEMP].desc, "Internal", 170 sizeof(sc->sc_sensor[ADMCTS_TEMP].desc)); 171 172 sc->sc_sensor[ADMCTS_Vbat].type = SENSOR_VOLTS_DC; 173 strlcpy(sc->sc_sensor[ADMCTS_Vbat].desc, "Vbat", 174 sizeof(sc->sc_sensor[ADMCTS_Vbat].desc)); 175 176 sc->sc_sensor[ADMCTS_EXT1].type = SENSOR_TEMP; 177 strlcpy(sc->sc_sensor[ADMCTS_EXT1].desc, "External1", 178 sizeof(sc->sc_sensor[ADMCTS_EXT1].desc)); 179 180 sc->sc_sensor[ADMCTS_EXT2].type = SENSOR_TEMP; 181 strlcpy(sc->sc_sensor[ADMCTS_EXT2].desc, "External2", 182 sizeof(sc->sc_sensor[ADMCTS_EXT2].desc)); 183 184 sc->sc_sensor[ADMCTS_V3_3stby].type = SENSOR_VOLTS_DC; 185 strlcpy(sc->sc_sensor[ADMCTS_V3_3stby].desc, "3.3 V standby", 186 sizeof(sc->sc_sensor[ADMCTS_V3_3stby].desc)); 187 188 sc->sc_sensor[ADMCTS_V3_3main].type = SENSOR_VOLTS_DC; 189 strlcpy(sc->sc_sensor[ADMCTS_V3_3main].desc, "3.3 V main", 190 sizeof(sc->sc_sensor[ADMCTS_V3_3main].desc)); 191 192 sc->sc_sensor[ADMCTS_V5].type = SENSOR_VOLTS_DC; 193 strlcpy(sc->sc_sensor[ADMCTS_V5].desc, "5 V", 194 sizeof(sc->sc_sensor[ADMCTS_V5].desc)); 195 196 sc->sc_sensor[ADMCTS_Vccp].type = SENSOR_VOLTS_DC; 197 strlcpy(sc->sc_sensor[ADMCTS_Vccp].desc, "Vccp", 198 sizeof(sc->sc_sensor[ADMCTS_Vccp].desc)); 199 200 sc->sc_sensor[ADMCTS_V12].type = SENSOR_VOLTS_DC; 201 strlcpy(sc->sc_sensor[ADMCTS_V12].desc, "12 V", 202 sizeof(sc->sc_sensor[ADMCTS_V12].desc)); 203 204 sc->sc_sensor[ADMCTS_Vminus12].type = SENSOR_VOLTS_DC; 205 strlcpy(sc->sc_sensor[ADMCTS_Vminus12].desc, "-12 V", 206 sizeof(sc->sc_sensor[ADMCTS_Vminus12].desc)); 207 208 sc->sc_sensor[ADMCTS_FAN1].type = SENSOR_FANRPM; 209 strlcpy(sc->sc_sensor[ADMCTS_FAN1].desc, "Fan1", 210 sizeof(sc->sc_sensor[ADMCTS_FAN1].desc)); 211 212 sc->sc_sensor[ADMCTS_FAN2].type = SENSOR_FANRPM; 213 strlcpy(sc->sc_sensor[ADMCTS_FAN2].desc, "Fan2", 214 sizeof(sc->sc_sensor[ADMCTS_FAN2].desc)); 215 216 sc->sc_sensor[ADMCTS_FAN2].type = SENSOR_FANRPM; 217 strlcpy(sc->sc_sensor[ADMCTS_FAN2].desc, "Fan2", 218 sizeof(sc->sc_sensor[ADMCTS_FAN2].desc)); 219 220 sc->sc_sensor[ADMCTS_FAN3].type = SENSOR_FANRPM; 221 strlcpy(sc->sc_sensor[ADMCTS_FAN3].desc, "Fan3", 222 sizeof(sc->sc_sensor[ADMCTS_FAN3].desc)); 223 224 sc->sc_sensor[ADMCTS_FAN4].type = SENSOR_FANRPM; 225 strlcpy(sc->sc_sensor[ADMCTS_FAN4].desc, "Fan4", 226 sizeof(sc->sc_sensor[ADMCTS_FAN4].desc)); 227 228 sc->sc_sensor[ADMCTS_FAN5].type = SENSOR_FANRPM; 229 strlcpy(sc->sc_sensor[ADMCTS_FAN5].desc, "Fan5", 230 sizeof(sc->sc_sensor[ADMCTS_FAN5].desc)); 231 232 sc->sc_sensor[ADMCTS_FAN6].type = SENSOR_FANRPM; 233 strlcpy(sc->sc_sensor[ADMCTS_FAN6].desc, "Fan6", 234 sizeof(sc->sc_sensor[ADMCTS_FAN6].desc)); 235 236 sc->sc_sensor[ADMCTS_FAN7].type = SENSOR_FANRPM; 237 strlcpy(sc->sc_sensor[ADMCTS_FAN7].desc, "Fan7", 238 sizeof(sc->sc_sensor[ADMCTS_FAN7].desc)); 239 240 if (sensor_task_register(sc, admcts_refresh, 5)) { 241 printf(", unable to register update task\n"); 242 return; 243 } 244 245 for (i = 0; i < ADMCTS_NUM_SENSORS; i++) 246 sensor_add(&sc->sc_sensor[i]); 247 248 printf("\n"); 249} 250 251static void 252fanval(struct sensor *sens, int mul, u_int8_t data) 253{ 254 int tmp = data * mul; 255 256 if (tmp == 0) 257 sens->flags |= SENSOR_FINVALID; 258 else 259 sens->value = 1350000 / tmp; 260} 261 262void 263admcts_refresh(void *arg) 264{ 265 struct admcts_softc *sc = arg; 266 u_int8_t cmd, data; 267 int8_t sdata; 268 269 iic_acquire_bus(sc->sc_tag, 0); 270 271 cmd = ADM1026_TEMP; 272 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 273 sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0) 274 sc->sc_sensor[ADMCTS_TEMP].value = 273150000 + 1000000 * sdata; 275 276 cmd = ADM1026_EXT1; 277 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 278 sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0) 279 sc->sc_sensor[ADMCTS_EXT1].value = 273150000 + 1000000 * sdata; 280 281 cmd = ADM1026_EXT2; 282 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 283 sc->sc_addr, &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0) 284 sc->sc_sensor[ADMCTS_EXT2].value = 273150000 + 1000000 * sdata; 285 286 cmd = ADM1026_Vbat; 287 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 288 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 289 sc->sc_sensor[ADMCTS_Vbat].value = 3000000 * data / 192; 290 291 cmd = ADM1026_V3_3stby; 292 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 293 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 294 sc->sc_sensor[ADMCTS_V3_3stby].value = 3300000 * data / 192; 295 296 cmd = ADM1026_V3_3main; 297 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 298 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 299 sc->sc_sensor[ADMCTS_V3_3main].value = 3300000 * data / 192; 300 301 cmd = ADM1026_V5; 302 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 303 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 304 sc->sc_sensor[ADMCTS_V5].value = 5500000 * data / 192; 305 306 cmd = ADM1026_Vccp; 307 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 308 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 309 sc->sc_sensor[ADMCTS_Vccp].value = 2250000 * data / 192; 310 311 cmd = ADM1026_V12; 312 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 313 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 314 sc->sc_sensor[ADMCTS_V12].value = 12000000 * data / 192; 315 316 cmd = ADM1026_Vminus12; 317 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 318 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 319 sc->sc_sensor[ADMCTS_Vminus12].value = -2125000 * data / 192; 320 321 cmd = ADM1026_FAN0; 322 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 323 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 324 fanval(&sc->sc_sensor[ADMCTS_FAN0], sc->sc_fanmul[0], data); 325 326 cmd = ADM1026_FAN1; 327 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 328 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 329 fanval(&sc->sc_sensor[ADMCTS_FAN1], sc->sc_fanmul[1], data); 330 331 cmd = ADM1026_FAN2; 332 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 333 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 334 fanval(&sc->sc_sensor[ADMCTS_FAN2], sc->sc_fanmul[2], data); 335 336 cmd = ADM1026_FAN3; 337 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 338 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 339 fanval(&sc->sc_sensor[ADMCTS_FAN3], sc->sc_fanmul[3], data); 340 341 cmd = ADM1026_FAN4; 342 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 343 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 344 fanval(&sc->sc_sensor[ADMCTS_FAN4], sc->sc_fanmul[4], data); 345 346 cmd = ADM1026_FAN5; 347 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 348 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 349 fanval(&sc->sc_sensor[ADMCTS_FAN5], sc->sc_fanmul[5], data); 350 351 cmd = ADM1026_FAN6; 352 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 353 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 354 fanval(&sc->sc_sensor[ADMCTS_FAN6], sc->sc_fanmul[6], data); 355 356 cmd = ADM1026_FAN7; 357 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 358 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 359 fanval(&sc->sc_sensor[ADMCTS_FAN7], sc->sc_fanmul[7], data); 360 361 iic_release_bus(sc->sc_tag, 0); 362} 363