1 /* $NetBSD: lm87.c,v 1.4 2013/11/04 15:06:26 jdc Exp $ */ 2 /* $OpenBSD: lm87.c,v 1.20 2008/11/10 05:19:48 cnst Exp $ */ 3 4 /* 5 * Copyright (c) 2005 Mark Kettenis 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/cdefs.h> 21 __KERNEL_RCSID(0, "$NetBSD: lm87.c,v 1.4 2013/11/04 15:06:26 jdc Exp $"); 22 23 #include <sys/param.h> 24 #include <sys/systm.h> 25 #include <sys/device.h> 26 #include <dev/sysmon/sysmonvar.h> 27 28 #include <dev/i2c/i2cvar.h> 29 30 /* LM87 registers */ 31 #define LM87_2_5V 0x20 32 #define LM87_VCCP1 0x21 33 #define LM87_VCC 0x22 34 #define LM87_5V 0x23 35 #define LM87_12V 0x24 36 #define LM87_VCCP2 0x25 37 #define LM87_EXT_TEMP 0x26 38 #define LM87_INT_TEMP 0x27 39 #define LM87_FAN1 0x28 40 #define LM87_FAN2 0x29 41 #define LM87_COMPANY_ID 0x3e 42 #define LM87_REVISION 0x3f 43 #define LM87_CONFIG1 0x40 44 #define LM87_CONFIG1_START 0x01 45 #define LM87_CONFIG1_INTCLR 0x08 46 #define LM87_CHANNEL 0x16 47 #define LM87_CHANNEL_AIN1 0x01 48 #define LM87_CHANNEL_AIN2 0x02 49 #define LM87_FANDIV 0x47 50 51 struct lmenv_id { 52 u_int8_t id, family; 53 const char *name; 54 }; 55 56 static const struct lmenv_id lmenv_ids[] = { 57 { 0x01, 81, "LM81" }, 58 { 0x02, 87, "LM87" }, /* LM87 or LM87CIMT */ 59 { 0x23, 81, "ADM9240" }, 60 { 0xda, 81, "DSL780" }, 61 { 0x00, 0, NULL } 62 }; 63 64 /* Sensors */ 65 #define LMENV_2_5V 0 66 #define LMENV_VCCP1 1 67 #define LMENV_VCC 2 68 #define LMENV_5V 3 69 #define LMENV_12V 4 70 #define LMENV_VCCP2 5 71 #define LMENV_EXT_TEMP 6 72 #define LMENV_INT_TEMP 7 73 #define LMENV_FAN1 8 74 #define LMENV_FAN2 9 75 #define LMENV_NUM_SENSORS 10 76 77 struct lmenv_softc { 78 i2c_tag_t sc_tag; 79 i2c_addr_t sc_addr; 80 81 int sc_fan1_div, sc_fan2_div; 82 int sc_family; 83 84 struct sysmon_envsys *sc_sme; 85 envsys_data_t sc_sensor[LMENV_NUM_SENSORS]; 86 }; 87 88 int lmenv_match(device_t, cfdata_t, void *); 89 void lmenv_attach(device_t, device_t, void *); 90 91 void lmenv_refresh(struct sysmon_envsys *, envsys_data_t *); 92 93 CFATTACH_DECL_NEW(lmenv, sizeof(struct lmenv_softc), 94 lmenv_match, lmenv_attach, NULL, NULL); 95 96 static const char * lmenv_compats[] = { 97 "lm87", 98 "lm87cimt", 99 "adm9240", 100 "lm81", 101 "ds1780", 102 NULL 103 }; 104 105 int 106 lmenv_match(device_t parent, cfdata_t match, void *aux) 107 { 108 struct i2c_attach_args *ia = aux; 109 u_int8_t cmd, val; 110 int error, i; 111 112 if (ia->ia_name == NULL) { 113 /* 114 * Indirect config - not much we can do! 115 * Check typical addresses and read the Company ID register 116 */ 117 if ((ia->ia_addr < 0x2c) || (ia->ia_addr > 0x2f)) 118 return 0; 119 120 cmd = LM87_COMPANY_ID; 121 iic_acquire_bus(ia->ia_tag, 0); 122 error = iic_exec(ia->ia_tag, I2C_OP_READ_WITH_STOP, ia->ia_addr, 123 &cmd, 1, &val, 1, I2C_F_POLL); 124 iic_release_bus(ia->ia_tag, 0); 125 126 if (error) 127 return 0; 128 129 for (i = 0; lmenv_ids[i].id != 0; i++) 130 if (lmenv_ids[i].id == val) 131 return 1; 132 } else { 133 /* 134 * Direct config - match via the list of compatible 135 * hardware. 136 */ 137 if (iic_compat_match(ia, lmenv_compats)) 138 return 1; 139 } 140 141 return 0; 142 } 143 144 void 145 lmenv_attach(device_t parent, device_t self, void *aux) 146 { 147 struct lmenv_softc *sc = device_private(self); 148 struct i2c_attach_args *ia = aux; 149 u_int8_t cmd, data, data2, channel; 150 int i; 151 152 sc->sc_tag = ia->ia_tag; 153 sc->sc_addr = ia->ia_addr; 154 155 iic_acquire_bus(sc->sc_tag, 0); 156 157 cmd = LM87_COMPANY_ID; 158 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 159 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 160 iic_release_bus(sc->sc_tag, 0); 161 printf(": cannot read ID register\n"); 162 return; 163 } 164 for (i = 0; lmenv_ids[i].id != 0; i++) 165 if (lmenv_ids[i].id == data) 166 break; 167 168 cmd = LM87_REVISION; 169 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 170 sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data, 0)) { 171 iic_release_bus(sc->sc_tag, 0); 172 printf(": cannot read revision register\n"); 173 return; 174 } 175 printf(": %s rev %x\n", lmenv_ids[i].name, data2); 176 sc->sc_family = lmenv_ids[i].family; 177 178 cmd = LM87_FANDIV; 179 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 180 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 181 iic_release_bus(sc->sc_tag, 0); 182 printf(", cannot read Fan Divisor register\n"); 183 return; 184 } 185 sc->sc_fan1_div = 1 << ((data >> 4) & 0x03); 186 sc->sc_fan2_div = 1 << ((data >> 6) & 0x03); 187 188 if (sc->sc_family == 87) { 189 cmd = LM87_CHANNEL; 190 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 191 sc->sc_addr, &cmd, sizeof cmd, &channel, 192 sizeof channel, 0)) { 193 iic_release_bus(sc->sc_tag, 0); 194 printf(", cannot read Channel register\n"); 195 return; 196 } 197 } else 198 channel = 0; 199 200 cmd = LM87_CONFIG1; 201 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 202 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 203 iic_release_bus(sc->sc_tag, 0); 204 printf(", cannot read Configuration Register 1\n"); 205 return; 206 } 207 208 /* 209 * if chip is not running, try to start it. 210 * if it is stalled doing an interrupt, unstall it 211 */ 212 data2 = (data | LM87_CONFIG1_START); 213 data2 = data2 & ~LM87_CONFIG1_INTCLR; 214 215 if (data != data2) { 216 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 217 sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) { 218 iic_release_bus(sc->sc_tag, 0); 219 printf(", cannot write Configuration Register 1\n"); 220 return; 221 } 222 } 223 iic_release_bus(sc->sc_tag, 0); 224 225 /* Initialize sensor data. */ 226 sc->sc_sensor[LMENV_2_5V].state = ENVSYS_SINVALID; 227 sc->sc_sensor[LMENV_2_5V].units = ENVSYS_SVOLTS_DC; 228 strlcpy(sc->sc_sensor[LMENV_2_5V].desc, "+2.5Vin", 229 sizeof(sc->sc_sensor[LMENV_2_5V].desc)); 230 231 sc->sc_sensor[LMENV_VCCP1].state = ENVSYS_SINVALID; 232 sc->sc_sensor[LMENV_VCCP1].units = ENVSYS_SVOLTS_DC; 233 strlcpy(sc->sc_sensor[LMENV_VCCP1].desc, "Vccp1", 234 sizeof(sc->sc_sensor[LMENV_VCCP1].desc)); 235 236 sc->sc_sensor[LMENV_VCC].state = ENVSYS_SINVALID; 237 sc->sc_sensor[LMENV_VCC].units = ENVSYS_SVOLTS_DC; 238 strlcpy(sc->sc_sensor[LMENV_VCC].desc, "+Vcc", 239 sizeof(sc->sc_sensor[LMENV_VCC].desc)); 240 241 sc->sc_sensor[LMENV_5V].state = ENVSYS_SINVALID; 242 sc->sc_sensor[LMENV_5V].units = ENVSYS_SVOLTS_DC; 243 strlcpy(sc->sc_sensor[LMENV_5V].desc, "+5Vin/Vcc", 244 sizeof(sc->sc_sensor[LMENV_5V].desc)); 245 246 sc->sc_sensor[LMENV_12V].state = ENVSYS_SINVALID; 247 sc->sc_sensor[LMENV_12V].units = ENVSYS_SVOLTS_DC; 248 strlcpy(sc->sc_sensor[LMENV_12V].desc, "+12Vin", 249 sizeof(sc->sc_sensor[LMENV_12V].desc)); 250 251 sc->sc_sensor[LMENV_VCCP2].state = ENVSYS_SINVALID; 252 sc->sc_sensor[LMENV_VCCP2].units = ENVSYS_SVOLTS_DC; 253 strlcpy(sc->sc_sensor[LMENV_VCCP2].desc, "Vccp2", 254 sizeof(sc->sc_sensor[LMENV_VCCP2].desc)); 255 256 sc->sc_sensor[LMENV_EXT_TEMP].state = ENVSYS_SINVALID; 257 sc->sc_sensor[LMENV_EXT_TEMP].units = ENVSYS_STEMP; 258 strlcpy(sc->sc_sensor[LMENV_EXT_TEMP].desc, "External", 259 sizeof(sc->sc_sensor[LMENV_EXT_TEMP].desc)); 260 if (sc->sc_family == 81) 261 sc->sc_sensor[LMENV_EXT_TEMP].state = ENVSYS_SINVALID; 262 263 sc->sc_sensor[LMENV_INT_TEMP].state = ENVSYS_SINVALID; 264 sc->sc_sensor[LMENV_INT_TEMP].units = ENVSYS_STEMP; 265 strlcpy(sc->sc_sensor[LMENV_INT_TEMP].desc, "Internal", 266 sizeof(sc->sc_sensor[LMENV_INT_TEMP].desc)); 267 268 sc->sc_sensor[LMENV_FAN1].state = ENVSYS_SINVALID; 269 if (channel & LM87_CHANNEL_AIN1) { 270 sc->sc_sensor[LMENV_FAN1].units = ENVSYS_SVOLTS_DC; 271 strlcpy(sc->sc_sensor[LMENV_FAN1].desc, "AIN1", 272 sizeof(sc->sc_sensor[LMENV_FAN1].desc)); 273 } else { 274 sc->sc_sensor[LMENV_FAN1].units = ENVSYS_SFANRPM; 275 strlcpy(sc->sc_sensor[LMENV_FAN1].desc, "FAN1", 276 sizeof(sc->sc_sensor[LMENV_FAN1].desc)); 277 } 278 279 sc->sc_sensor[LMENV_FAN2].state = ENVSYS_SINVALID; 280 if (channel & LM87_CHANNEL_AIN2) { 281 sc->sc_sensor[LMENV_FAN2].units = ENVSYS_SVOLTS_DC; 282 strlcpy(sc->sc_sensor[LMENV_FAN2].desc, "AIN2", 283 sizeof(sc->sc_sensor[LMENV_FAN2].desc)); 284 } else { 285 sc->sc_sensor[LMENV_FAN2].units = ENVSYS_SFANRPM; 286 strlcpy(sc->sc_sensor[LMENV_FAN2].desc, "FAN2", 287 sizeof(sc->sc_sensor[LMENV_FAN2].desc)); 288 } 289 290 sc->sc_sme = sysmon_envsys_create(); 291 for (i = 0; i < LMENV_NUM_SENSORS; i++) 292 if (sysmon_envsys_sensor_attach(sc->sc_sme, 293 &sc->sc_sensor[i])) { 294 sysmon_envsys_destroy(sc->sc_sme); 295 aprint_error_dev(self, 296 "unable to attach sensor %d at sysmon\n", i); 297 return; 298 } 299 sc->sc_sme->sme_name = device_xname(self); 300 sc->sc_sme->sme_cookie = sc; 301 sc->sc_sme->sme_refresh = lmenv_refresh; 302 if (sysmon_envsys_register(sc->sc_sme)) { 303 aprint_error_dev(self, 304 "unable to register with sysmon\n"); 305 sysmon_envsys_destroy(sc->sc_sme); 306 return; 307 } 308 } 309 310 void 311 lmenv_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 312 { 313 struct lmenv_softc *sc = sme->sme_cookie; 314 u_int8_t cmd, data; 315 u_int tmp; 316 317 iic_acquire_bus(sc->sc_tag, 0); 318 319 cmd = LM87_2_5V + edata->sensor; 320 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 321 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 322 edata->state = ENVSYS_SINVALID; 323 return; 324 } 325 326 switch (edata->sensor) { 327 case LMENV_2_5V: 328 edata->value_cur = 2500000 * data / 192; 329 edata->state = ENVSYS_SVALID; 330 break; 331 case LMENV_5V: 332 edata->value_cur = 5000000 * data / 192; 333 edata->state = ENVSYS_SVALID; 334 break; 335 case LMENV_12V: 336 edata->value_cur = 12000000 * data / 192; 337 edata->state = ENVSYS_SVALID; 338 break; 339 case LMENV_VCCP1: 340 case LMENV_VCCP2: 341 edata->value_cur = 2700000 * data / 192; 342 edata->state = ENVSYS_SVALID; 343 break; 344 case LMENV_VCC: 345 edata->value_cur = 3300000 * data / 192; 346 edata->state = ENVSYS_SVALID; 347 break; 348 case LMENV_EXT_TEMP: 349 if (sc->sc_family == 81) { 350 edata->state = ENVSYS_SINVALID; 351 break; /* missing on LM81 */ 352 } 353 /* FALLTHROUGH */ 354 case LMENV_INT_TEMP: 355 if (data == 0x80) 356 edata->state = ENVSYS_SINVALID; 357 else { 358 edata->value_cur = (int8_t)data * 1000000 + 273150000; 359 edata->state = ENVSYS_SVALID; 360 } 361 break; 362 case LMENV_FAN1: 363 if (edata->units == ENVSYS_SVOLTS_DC) { 364 edata->value_cur = 1870000 * data / 192; 365 edata->state = ENVSYS_SVALID; 366 break; 367 } 368 if (data == 0xff) { 369 edata->state = ENVSYS_SINVALID; 370 break; 371 } 372 tmp = data * sc->sc_fan1_div; 373 if (tmp == 0) 374 edata->state = ENVSYS_SINVALID; 375 else { 376 edata->value_cur = 1350000 / tmp; 377 edata->state = ENVSYS_SVALID; 378 } 379 break; 380 case LMENV_FAN2: 381 if (edata->units == ENVSYS_SVOLTS_DC) { 382 edata->value_cur = 1870000 * data / 192; 383 edata->state = ENVSYS_SVALID; 384 break; 385 } 386 if (data == 0xff) { 387 edata->state = ENVSYS_SINVALID; 388 break; 389 } 390 tmp = data * sc->sc_fan2_div; 391 if (tmp == 0) 392 edata->state = ENVSYS_SINVALID; 393 else { 394 edata->value_cur = 1350000 / tmp; 395 edata->state = ENVSYS_SVALID; 396 } 397 break; 398 default: 399 edata->state = ENVSYS_SINVALID; 400 break; 401 } 402 403 iic_release_bus(sc->sc_tag, 0); 404 } 405