1 /* $OpenBSD: asb100.c,v 1.11 2008/04/17 19:01:48 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 2005 Damien Miller <djm@openbsd.org> 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 /* Apparently the ASB100 always lives here */ 27 #define ASB100_ADDR 0x2d 28 29 /* ASB100 registers */ 30 #define ASB100_TEMP3 0x17 31 #define ASB100_TEMP3_MAX 0x18 32 #define ASB100_TEMP3_HYST 0x19 33 #define ASB100_VIN0 0x20 34 #define ASB100_VIN1 0x21 35 #define ASB100_VIN2 0x22 36 #define ASB100_VIN3 0x23 37 #define ASB100_VIN4 0x24 38 #define ASB100_VIN5 0x25 39 #define ASB100_VIN6 0x26 40 #define ASB100_TEMP0 0x27 41 #define ASB100_FAN0 0x28 42 #define ASB100_FAN1 0x29 43 #define ASB100_FAN2 0x30 44 #define ASB100_VIN0_MIN 0x2b 45 #define ASB100_VIN0_MAX 0x2c 46 #define ASB100_VIN1_MIN 0x2d 47 #define ASB100_VIN1_MAX 0x2e 48 #define ASB100_VIN2_MIN 0x2f 49 #define ASB100_VIN2_MAX 0x30 50 #define ASB100_VIN3_MIN 0x31 51 #define ASB100_VIN3_MAX 0x32 52 #define ASB100_VIN4_MIN 0x33 53 #define ASB100_VIN4_MAX 0x34 54 #define ASB100_VIN5_MIN 0x35 55 #define ASB100_VIN5_MAX 0x36 56 #define ASB100_VIN6_MIN 0x37 57 #define ASB100_VIN6_MAX 0x38 58 #define ASB100_TEMP0_MAX 0x39 59 #define ASB100_TEMP0_HYST 0x3a 60 #define ASB100_FAN0_MIN 0x3b 61 #define ASB100_FAN1_MIN 0x3c 62 #define ASB100_FAN2_MIN 0x3d 63 #define ASB100_CONFIG 0x40 64 #define ASB100_ALARM1 0x41 65 #define ASB100_ALARM2 0x42 66 #define ASB100_SMIM1 0x43 67 #define ASB100_SMIM2 0x44 68 #define ASB100_VID_FANDIV01 0x47 /* 0-3 vid, 4-5 fan0, 6-7 fan1 */ 69 #define ASB100_I2C_ADDR 0x48 70 #define ASB100_CHIPID 0x49 71 #define ASB100_I2C_SUBADDR 0x4a 72 #define ASB100_PIN_FANDIV2 0x4b /* 6-7 fan2 */ 73 #define ASB100_IRQ 0x4c 74 #define ASB100_BANK 0x4e 75 #define ASB100_CHIPMAN 0x4f 76 #define ASB100_VID_CHIPID 0x58 /* 0 vid highbit, 1-7 chipid */ 77 #define ASB100_PWM 0x59 /* 0-3 duty cycle, 7 enable */ 78 79 /* TEMP1/2 sensors live on other chips, pointed to by the I2C_SUBADDR reg */ 80 #define ASB100_SUB1_TEMP1 0x50 /* LM75 format */ 81 #define ASB100_SUB1_TEMP1_HYST 0x53 82 #define ASB100_SUB1_TEMP1_MAX 0x55 83 #define ASB100_SUB2_TEMP2 0x50 /* LM75 format */ 84 #define ASB100_SUB2_TEMP2_HYST 0x53 85 #define ASB100_SUB2_TEMP2_MAX 0x55 86 87 /* Sensors */ 88 #define ASB100_SENSOR_VIN0 0 89 #define ASB100_SENSOR_VIN1 1 90 #define ASB100_SENSOR_VIN2 2 91 #define ASB100_SENSOR_VIN3 3 92 #define ASB100_SENSOR_VIN4 4 93 #define ASB100_SENSOR_VIN5 5 94 #define ASB100_SENSOR_VIN6 6 95 #define ASB100_SENSOR_FAN0 7 96 #define ASB100_SENSOR_FAN1 8 97 #define ASB100_SENSOR_FAN2 9 98 #define ASB100_SENSOR_TEMP0 10 99 #define ASB100_SENSOR_TEMP1 11 100 #define ASB100_SENSOR_TEMP2 12 101 #define ASB100_SENSOR_TEMP3 13 102 #define ASB100_NUM_SENSORS 14 103 104 struct asbtm_softc { 105 struct device sc_dev; 106 i2c_tag_t sc_tag; 107 i2c_addr_t sc_addr; 108 109 struct ksensor sc_sensor[ASB100_NUM_SENSORS]; 110 struct ksensordev sc_sensordev; 111 int sc_fanmul[3]; 112 int sc_satellite[2]; 113 }; 114 115 int asbtm_banksel(struct asbtm_softc *, u_int8_t, u_int8_t *); 116 int asbtm_match(struct device *, void *, void *); 117 void asbtm_attach(struct device *, struct device *, void *); 118 void asbtm_refresh(void *); 119 120 struct cfattach asbtm_ca = { 121 sizeof(struct asbtm_softc), asbtm_match, asbtm_attach 122 }; 123 124 struct cfdriver asbtm_cd = { 125 NULL, "asbtm", DV_DULL 126 }; 127 128 int 129 asbtm_match(struct device *parent, void *match, void *aux) 130 { 131 struct i2c_attach_args *ia = aux; 132 133 if (strcmp(ia->ia_name, "asb100") == 0) 134 return (1); 135 136 return (0); 137 } 138 139 int 140 asbtm_banksel(struct asbtm_softc *sc, u_int8_t new_bank, u_int8_t *orig_bank) 141 { 142 u_int8_t cmd, data; 143 144 new_bank &= 0xf; 145 146 cmd = ASB100_BANK; 147 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 148 &cmd, sizeof cmd, &data, sizeof data, 0)) 149 return (-1); 150 151 if (orig_bank != NULL) 152 *orig_bank = data & 0x0f; 153 154 if ((data & 0xf) != new_bank) { 155 cmd = ASB100_BANK; 156 data = new_bank | (data & 0xf0); 157 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, sc->sc_addr, 158 &cmd, sizeof cmd, &data, sizeof data, 0)) 159 return (-1); 160 } 161 162 return (0); 163 } 164 165 void 166 asbtm_attach(struct device *parent, struct device *self, void *aux) 167 { 168 struct asbtm_softc *sc = (struct asbtm_softc *)self; 169 struct i2c_attach_args *ia = aux; 170 u_int8_t orig_bank, cmd, data; 171 int i; 172 173 sc->sc_tag = ia->ia_tag; 174 sc->sc_addr = ia->ia_addr; 175 176 iic_acquire_bus(sc->sc_tag, 0); 177 178 if (asbtm_banksel(sc, 0, &orig_bank) == -1) { 179 printf(": cannot get/set register bank\n"); 180 iic_release_bus(sc->sc_tag, 0); 181 return; 182 } 183 184 cmd = ASB100_VID_FANDIV01; 185 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 186 &cmd, sizeof cmd, &data, sizeof data, 0)) { 187 printf(": cannot get fan01 register\n"); 188 iic_release_bus(sc->sc_tag, 0); 189 return; 190 } 191 sc->sc_fanmul[0] = (1 << (data >> 4) & 0x3); 192 sc->sc_fanmul[1] = (1 << (data >> 6) & 0x3); 193 194 cmd = ASB100_PIN_FANDIV2; 195 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 196 &cmd, sizeof cmd, &data, sizeof data, 0)) { 197 printf(": cannot get fan2 register\n"); 198 iic_release_bus(sc->sc_tag, 0); 199 return; 200 } 201 sc->sc_fanmul[0] = (1 << (data >> 6) & 0x3); 202 203 cmd = ASB100_I2C_SUBADDR; 204 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 205 &cmd, sizeof cmd, &data, sizeof data, 0)) { 206 printf(": cannot get satellite chip address register\n"); 207 iic_release_bus(sc->sc_tag, 0); 208 return; 209 } 210 /* Maybe a relative address of zero means "not present" here... */ 211 sc->sc_satellite[0] = 0x48 + (data & 0xf); 212 sc->sc_satellite[1] = 0x48 + ((data >> 4) & 0xf); 213 214 iic_ignore_addr(sc->sc_satellite[0]); 215 iic_ignore_addr(sc->sc_satellite[1]); 216 if (sc->sc_satellite[0] == sc->sc_satellite[1]) 217 sc->sc_satellite[1] = -1; 218 219 if (asbtm_banksel(sc, orig_bank, NULL) == -1) { 220 printf(": cannot restore saved bank %d\n", orig_bank); 221 iic_release_bus(sc->sc_tag, 0); 222 return; 223 } 224 225 iic_release_bus(sc->sc_tag, 0); 226 227 /* Initialize sensor data. */ 228 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 229 sizeof(sc->sc_sensordev.xname)); 230 231 sc->sc_sensor[ASB100_SENSOR_VIN0].type = SENSOR_VOLTS_DC; 232 sc->sc_sensor[ASB100_SENSOR_VIN1].type = SENSOR_VOLTS_DC; 233 sc->sc_sensor[ASB100_SENSOR_VIN2].type = SENSOR_VOLTS_DC; 234 sc->sc_sensor[ASB100_SENSOR_VIN3].type = SENSOR_VOLTS_DC; 235 sc->sc_sensor[ASB100_SENSOR_VIN4].type = SENSOR_VOLTS_DC; 236 sc->sc_sensor[ASB100_SENSOR_VIN5].type = SENSOR_VOLTS_DC; 237 sc->sc_sensor[ASB100_SENSOR_VIN6].type = SENSOR_VOLTS_DC; 238 239 sc->sc_sensor[ASB100_SENSOR_FAN0].type = SENSOR_FANRPM; 240 sc->sc_sensor[ASB100_SENSOR_FAN1].type = SENSOR_FANRPM; 241 sc->sc_sensor[ASB100_SENSOR_FAN2].type = SENSOR_FANRPM; 242 243 sc->sc_sensor[ASB100_SENSOR_TEMP0].type = SENSOR_TEMP; 244 strlcpy(sc->sc_sensor[ASB100_SENSOR_TEMP0].desc, "External", 245 sizeof(sc->sc_sensor[ASB100_SENSOR_TEMP0].desc)); 246 247 sc->sc_sensor[ASB100_SENSOR_TEMP1].type = SENSOR_TEMP; 248 strlcpy(sc->sc_sensor[ASB100_SENSOR_TEMP1].desc, "Internal", 249 sizeof(sc->sc_sensor[ASB100_SENSOR_TEMP1].desc)); 250 251 sc->sc_sensor[ASB100_SENSOR_TEMP2].type = SENSOR_TEMP; 252 strlcpy(sc->sc_sensor[ASB100_SENSOR_TEMP2].desc, "Internal", 253 sizeof(sc->sc_sensor[ASB100_SENSOR_TEMP2].desc)); 254 if (sc->sc_satellite[1] == -1) 255 sc->sc_sensor[ASB100_SENSOR_TEMP2].flags |= SENSOR_FINVALID; 256 257 sc->sc_sensor[ASB100_SENSOR_TEMP3].type = SENSOR_TEMP; 258 strlcpy(sc->sc_sensor[ASB100_SENSOR_TEMP3].desc, "External", 259 sizeof(sc->sc_sensor[ASB100_SENSOR_TEMP3].desc)); 260 261 if (sensor_task_register(sc, asbtm_refresh, 5) == NULL) { 262 printf(", unable to register update task\n"); 263 return; 264 } 265 266 for (i = 0; i < ASB100_NUM_SENSORS; i++) 267 sensor_attach(&sc->sc_sensordev, &sc->sc_sensor[i]); 268 sensordev_install(&sc->sc_sensordev); 269 270 printf("\n"); 271 } 272 273 static void 274 fanval(struct ksensor *sens, int mul, u_int8_t data) 275 { 276 int tmp = data * mul; 277 278 if (tmp == 0) 279 sens->flags |= SENSOR_FINVALID; 280 else { 281 sens->value = 1350000 / tmp; 282 sens->flags &= ~SENSOR_FINVALID; 283 } 284 } 285 286 void 287 asbtm_refresh(void *arg) 288 { 289 struct asbtm_softc *sc = arg; 290 u_int8_t orig_bank, cmd, data; 291 int8_t sdata; 292 u_int16_t sdata2; 293 294 iic_acquire_bus(sc->sc_tag, 0); 295 296 if (asbtm_banksel(sc, 0, &orig_bank) == -1) { 297 printf("%s: cannot get/set register bank\n", 298 sc->sc_dev.dv_xname); 299 iic_release_bus(sc->sc_tag, 0); 300 return; 301 } 302 303 cmd = ASB100_VIN0; 304 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 305 &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 306 sc->sc_sensor[ASB100_SENSOR_VIN0].value = (data * 1000000) / 16; 307 308 cmd = ASB100_VIN1; 309 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 310 &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 311 sc->sc_sensor[ASB100_SENSOR_VIN1].value = (data * 1000000) / 16; 312 313 cmd = ASB100_VIN2; 314 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 315 &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 316 sc->sc_sensor[ASB100_SENSOR_VIN2].value = (data * 1000000) / 16; 317 318 cmd = ASB100_VIN3; 319 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 320 &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 321 sc->sc_sensor[ASB100_SENSOR_VIN3].value = (data * 1000000) / 16; 322 323 cmd = ASB100_VIN4; 324 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 325 &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 326 sc->sc_sensor[ASB100_SENSOR_VIN4].value = (data * 1000000) / 16; 327 328 cmd = ASB100_VIN5; 329 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 330 &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 331 sc->sc_sensor[ASB100_SENSOR_VIN5].value = (data * 1000000) / 16; 332 333 cmd = ASB100_VIN6; 334 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 335 &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 336 sc->sc_sensor[ASB100_SENSOR_VIN6].value = (data * 1000000) / 16; 337 338 cmd = ASB100_FAN0; 339 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 340 &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 341 fanval(&sc->sc_sensor[ASB100_SENSOR_FAN0], 342 sc->sc_fanmul[0], data); 343 344 cmd = ASB100_FAN1; 345 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 346 &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 347 fanval(&sc->sc_sensor[ASB100_SENSOR_FAN1], 348 sc->sc_fanmul[1], data); 349 350 cmd = ASB100_FAN2; 351 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 352 &cmd, sizeof cmd, &data, sizeof data, 0) == 0) 353 fanval(&sc->sc_sensor[ASB100_SENSOR_FAN2], 354 sc->sc_fanmul[2], data); 355 356 cmd = ASB100_TEMP0; 357 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 358 &cmd, sizeof cmd, &sdata, sizeof sdata, 0) == 0) 359 sc->sc_sensor[ASB100_SENSOR_TEMP0].value = 273150000 + 360 1000000 * sdata; 361 362 cmd = ASB100_TEMP3; 363 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_addr, 364 &cmd, sizeof cmd, &data, sizeof sdata, 0) == 0) 365 sc->sc_sensor[ASB100_SENSOR_TEMP3].value = 273150000 + 366 1000000 * sdata; 367 368 /* Read satellite chips for TEMP1/TEMP2 */ 369 cmd = ASB100_SUB1_TEMP1; 370 if (sc->sc_satellite[0] != -1) { 371 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 372 sc->sc_satellite[0], &cmd, sizeof cmd, &sdata2, 373 sizeof sdata2, 0) == 0 && sdata2 != 0xffff) { 374 sc->sc_sensor[ASB100_SENSOR_TEMP1].value = 273150000 + 375 500000 * (betoh16(sdata2) / 128); 376 sc->sc_sensor[ASB100_SENSOR_TEMP2].flags &= 377 ~SENSOR_FINVALID; 378 } else { 379 sc->sc_sensor[ASB100_SENSOR_TEMP2].flags |= 380 SENSOR_FINVALID; 381 } 382 } 383 384 cmd = ASB100_SUB2_TEMP2; 385 if (sc->sc_satellite[1] != -1) { 386 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 387 sc->sc_satellite[1], &cmd, sizeof cmd, &sdata2, 388 sizeof sdata2, 0) == 0 && sdata2 != 0xffff) { 389 sc->sc_sensor[ASB100_SENSOR_TEMP2].value = 273150000 + 390 500000 * (betoh16(sdata2) / 128); 391 sc->sc_sensor[ASB100_SENSOR_TEMP2].flags &= 392 ~SENSOR_FINVALID; 393 } else { 394 sc->sc_sensor[ASB100_SENSOR_TEMP2].flags |= 395 SENSOR_FINVALID; 396 } 397 } 398 399 asbtm_banksel(sc, orig_bank, NULL); 400 401 iic_release_bus(sc->sc_tag, 0); 402 } 403