1 /* $NetBSD: lm87.c,v 1.5 2015/09/27 13:02:21 phx 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.5 2015/09/27 13:02:21 phx 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 or simply match the device name. 136 */ 137 if (ia->ia_ncompat > 0) { 138 if (iic_compat_match(ia, lmenv_compats)) 139 return 1; 140 } else { 141 if (strcmp(ia->ia_name, "lmenv") == 0) 142 return 1; 143 } 144 } 145 146 return 0; 147 } 148 149 void 150 lmenv_attach(device_t parent, device_t self, void *aux) 151 { 152 struct lmenv_softc *sc = device_private(self); 153 struct i2c_attach_args *ia = aux; 154 u_int8_t cmd, data, data2, channel; 155 int i; 156 157 sc->sc_tag = ia->ia_tag; 158 sc->sc_addr = ia->ia_addr; 159 160 iic_acquire_bus(sc->sc_tag, 0); 161 162 cmd = LM87_COMPANY_ID; 163 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 164 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 165 iic_release_bus(sc->sc_tag, 0); 166 printf(": cannot read ID register\n"); 167 return; 168 } 169 for (i = 0; lmenv_ids[i].id != 0; i++) 170 if (lmenv_ids[i].id == data) 171 break; 172 173 cmd = LM87_REVISION; 174 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 175 sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data, 0)) { 176 iic_release_bus(sc->sc_tag, 0); 177 printf(": cannot read revision register\n"); 178 return; 179 } 180 printf(": %s rev %x\n", lmenv_ids[i].name, data2); 181 sc->sc_family = lmenv_ids[i].family; 182 183 cmd = LM87_FANDIV; 184 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 185 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 186 iic_release_bus(sc->sc_tag, 0); 187 printf(", cannot read Fan Divisor register\n"); 188 return; 189 } 190 sc->sc_fan1_div = 1 << ((data >> 4) & 0x03); 191 sc->sc_fan2_div = 1 << ((data >> 6) & 0x03); 192 193 if (sc->sc_family == 87) { 194 cmd = LM87_CHANNEL; 195 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 196 sc->sc_addr, &cmd, sizeof cmd, &channel, 197 sizeof channel, 0)) { 198 iic_release_bus(sc->sc_tag, 0); 199 printf(", cannot read Channel register\n"); 200 return; 201 } 202 } else 203 channel = 0; 204 205 cmd = LM87_CONFIG1; 206 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 207 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 208 iic_release_bus(sc->sc_tag, 0); 209 printf(", cannot read Configuration Register 1\n"); 210 return; 211 } 212 213 /* 214 * if chip is not running, try to start it. 215 * if it is stalled doing an interrupt, unstall it 216 */ 217 data2 = (data | LM87_CONFIG1_START); 218 data2 = data2 & ~LM87_CONFIG1_INTCLR; 219 220 if (data != data2) { 221 if (iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 222 sc->sc_addr, &cmd, sizeof cmd, &data2, sizeof data2, 0)) { 223 iic_release_bus(sc->sc_tag, 0); 224 printf(", cannot write Configuration Register 1\n"); 225 return; 226 } 227 } 228 iic_release_bus(sc->sc_tag, 0); 229 230 /* Initialize sensor data. */ 231 sc->sc_sensor[LMENV_2_5V].state = ENVSYS_SINVALID; 232 sc->sc_sensor[LMENV_2_5V].units = ENVSYS_SVOLTS_DC; 233 strlcpy(sc->sc_sensor[LMENV_2_5V].desc, "+2.5Vin", 234 sizeof(sc->sc_sensor[LMENV_2_5V].desc)); 235 236 sc->sc_sensor[LMENV_VCCP1].state = ENVSYS_SINVALID; 237 sc->sc_sensor[LMENV_VCCP1].units = ENVSYS_SVOLTS_DC; 238 strlcpy(sc->sc_sensor[LMENV_VCCP1].desc, "Vccp1", 239 sizeof(sc->sc_sensor[LMENV_VCCP1].desc)); 240 241 sc->sc_sensor[LMENV_VCC].state = ENVSYS_SINVALID; 242 sc->sc_sensor[LMENV_VCC].units = ENVSYS_SVOLTS_DC; 243 strlcpy(sc->sc_sensor[LMENV_VCC].desc, "+Vcc", 244 sizeof(sc->sc_sensor[LMENV_VCC].desc)); 245 246 sc->sc_sensor[LMENV_5V].state = ENVSYS_SINVALID; 247 sc->sc_sensor[LMENV_5V].units = ENVSYS_SVOLTS_DC; 248 strlcpy(sc->sc_sensor[LMENV_5V].desc, "+5Vin/Vcc", 249 sizeof(sc->sc_sensor[LMENV_5V].desc)); 250 251 sc->sc_sensor[LMENV_12V].state = ENVSYS_SINVALID; 252 sc->sc_sensor[LMENV_12V].units = ENVSYS_SVOLTS_DC; 253 strlcpy(sc->sc_sensor[LMENV_12V].desc, "+12Vin", 254 sizeof(sc->sc_sensor[LMENV_12V].desc)); 255 256 sc->sc_sensor[LMENV_VCCP2].state = ENVSYS_SINVALID; 257 sc->sc_sensor[LMENV_VCCP2].units = ENVSYS_SVOLTS_DC; 258 strlcpy(sc->sc_sensor[LMENV_VCCP2].desc, "Vccp2", 259 sizeof(sc->sc_sensor[LMENV_VCCP2].desc)); 260 261 sc->sc_sensor[LMENV_EXT_TEMP].state = ENVSYS_SINVALID; 262 sc->sc_sensor[LMENV_EXT_TEMP].units = ENVSYS_STEMP; 263 strlcpy(sc->sc_sensor[LMENV_EXT_TEMP].desc, "External", 264 sizeof(sc->sc_sensor[LMENV_EXT_TEMP].desc)); 265 if (sc->sc_family == 81) 266 sc->sc_sensor[LMENV_EXT_TEMP].state = ENVSYS_SINVALID; 267 268 sc->sc_sensor[LMENV_INT_TEMP].state = ENVSYS_SINVALID; 269 sc->sc_sensor[LMENV_INT_TEMP].units = ENVSYS_STEMP; 270 strlcpy(sc->sc_sensor[LMENV_INT_TEMP].desc, "Internal", 271 sizeof(sc->sc_sensor[LMENV_INT_TEMP].desc)); 272 273 sc->sc_sensor[LMENV_FAN1].state = ENVSYS_SINVALID; 274 if (channel & LM87_CHANNEL_AIN1) { 275 sc->sc_sensor[LMENV_FAN1].units = ENVSYS_SVOLTS_DC; 276 strlcpy(sc->sc_sensor[LMENV_FAN1].desc, "AIN1", 277 sizeof(sc->sc_sensor[LMENV_FAN1].desc)); 278 } else { 279 sc->sc_sensor[LMENV_FAN1].units = ENVSYS_SFANRPM; 280 strlcpy(sc->sc_sensor[LMENV_FAN1].desc, "FAN1", 281 sizeof(sc->sc_sensor[LMENV_FAN1].desc)); 282 } 283 284 sc->sc_sensor[LMENV_FAN2].state = ENVSYS_SINVALID; 285 if (channel & LM87_CHANNEL_AIN2) { 286 sc->sc_sensor[LMENV_FAN2].units = ENVSYS_SVOLTS_DC; 287 strlcpy(sc->sc_sensor[LMENV_FAN2].desc, "AIN2", 288 sizeof(sc->sc_sensor[LMENV_FAN2].desc)); 289 } else { 290 sc->sc_sensor[LMENV_FAN2].units = ENVSYS_SFANRPM; 291 strlcpy(sc->sc_sensor[LMENV_FAN2].desc, "FAN2", 292 sizeof(sc->sc_sensor[LMENV_FAN2].desc)); 293 } 294 295 sc->sc_sme = sysmon_envsys_create(); 296 for (i = 0; i < LMENV_NUM_SENSORS; i++) 297 if (sysmon_envsys_sensor_attach(sc->sc_sme, 298 &sc->sc_sensor[i])) { 299 sysmon_envsys_destroy(sc->sc_sme); 300 aprint_error_dev(self, 301 "unable to attach sensor %d at sysmon\n", i); 302 return; 303 } 304 sc->sc_sme->sme_name = device_xname(self); 305 sc->sc_sme->sme_cookie = sc; 306 sc->sc_sme->sme_refresh = lmenv_refresh; 307 if (sysmon_envsys_register(sc->sc_sme)) { 308 aprint_error_dev(self, 309 "unable to register with sysmon\n"); 310 sysmon_envsys_destroy(sc->sc_sme); 311 return; 312 } 313 } 314 315 void 316 lmenv_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 317 { 318 struct lmenv_softc *sc = sme->sme_cookie; 319 u_int8_t cmd, data; 320 u_int tmp; 321 322 iic_acquire_bus(sc->sc_tag, 0); 323 324 cmd = LM87_2_5V + edata->sensor; 325 if (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 326 sc->sc_addr, &cmd, sizeof cmd, &data, sizeof data, 0)) { 327 edata->state = ENVSYS_SINVALID; 328 return; 329 } 330 331 switch (edata->sensor) { 332 case LMENV_2_5V: 333 edata->value_cur = 2500000 * data / 192; 334 edata->state = ENVSYS_SVALID; 335 break; 336 case LMENV_5V: 337 edata->value_cur = 5000000 * data / 192; 338 edata->state = ENVSYS_SVALID; 339 break; 340 case LMENV_12V: 341 edata->value_cur = 12000000 * data / 192; 342 edata->state = ENVSYS_SVALID; 343 break; 344 case LMENV_VCCP1: 345 case LMENV_VCCP2: 346 edata->value_cur = 2700000 * data / 192; 347 edata->state = ENVSYS_SVALID; 348 break; 349 case LMENV_VCC: 350 edata->value_cur = 3300000 * data / 192; 351 edata->state = ENVSYS_SVALID; 352 break; 353 case LMENV_EXT_TEMP: 354 if (sc->sc_family == 81) { 355 edata->state = ENVSYS_SINVALID; 356 break; /* missing on LM81 */ 357 } 358 /* FALLTHROUGH */ 359 case LMENV_INT_TEMP: 360 if (data == 0x80) 361 edata->state = ENVSYS_SINVALID; 362 else { 363 edata->value_cur = (int8_t)data * 1000000 + 273150000; 364 edata->state = ENVSYS_SVALID; 365 } 366 break; 367 case LMENV_FAN1: 368 if (edata->units == ENVSYS_SVOLTS_DC) { 369 edata->value_cur = 1870000 * data / 192; 370 edata->state = ENVSYS_SVALID; 371 break; 372 } 373 if (data == 0xff) { 374 edata->state = ENVSYS_SINVALID; 375 break; 376 } 377 tmp = data * sc->sc_fan1_div; 378 if (tmp == 0) 379 edata->state = ENVSYS_SINVALID; 380 else { 381 edata->value_cur = 1350000 / tmp; 382 edata->state = ENVSYS_SVALID; 383 } 384 break; 385 case LMENV_FAN2: 386 if (edata->units == ENVSYS_SVOLTS_DC) { 387 edata->value_cur = 1870000 * data / 192; 388 edata->state = ENVSYS_SVALID; 389 break; 390 } 391 if (data == 0xff) { 392 edata->state = ENVSYS_SINVALID; 393 break; 394 } 395 tmp = data * sc->sc_fan2_div; 396 if (tmp == 0) 397 edata->state = ENVSYS_SINVALID; 398 else { 399 edata->value_cur = 1350000 / tmp; 400 edata->state = ENVSYS_SVALID; 401 } 402 break; 403 default: 404 edata->state = ENVSYS_SINVALID; 405 break; 406 } 407 408 iic_release_bus(sc->sc_tag, 0); 409 } 410