1 /* $NetBSD: sdtemp.c,v 1.36 2019/10/01 18:00:08 chs Exp $ */ 2 3 /* 4 * Copyright (c) 2009 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Paul Goyette. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: sdtemp.c,v 1.36 2019/10/01 18:00:08 chs Exp $"); 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/kmem.h> 38 #include <sys/device.h> 39 #include <sys/kernel.h> 40 #include <sys/endian.h> 41 #include <sys/module.h> 42 43 #include <dev/sysmon/sysmonvar.h> 44 45 #include <dev/i2c/i2cvar.h> 46 #include <dev/i2c/sdtemp_reg.h> 47 48 struct sdtemp_softc { 49 device_t sc_dev; 50 i2c_tag_t sc_tag; 51 int sc_address; 52 53 struct sysmon_envsys *sc_sme; 54 envsys_data_t *sc_sensor; 55 sysmon_envsys_lim_t sc_deflims; 56 uint32_t sc_defprops; 57 int sc_resolution; 58 uint16_t sc_mfgid; 59 uint16_t sc_devid; 60 uint16_t sc_devid_masked; 61 uint16_t sc_capability; 62 }; 63 64 static int sdtemp_match(device_t, cfdata_t, void *); 65 static void sdtemp_attach(device_t, device_t, void *); 66 static int sdtemp_detach(device_t, int); 67 68 CFATTACH_DECL_NEW(sdtemp, sizeof(struct sdtemp_softc), 69 sdtemp_match, sdtemp_attach, sdtemp_detach, NULL); 70 71 static void sdtemp_refresh(struct sysmon_envsys *, envsys_data_t *); 72 static void sdtemp_get_limits(struct sysmon_envsys *, envsys_data_t *, 73 sysmon_envsys_lim_t *, uint32_t *); 74 static void sdtemp_set_limits(struct sysmon_envsys *, envsys_data_t *, 75 sysmon_envsys_lim_t *, uint32_t *); 76 #ifdef NOT_YET 77 static int sdtemp_read_8(struct sdtemp_softc *, uint8_t, uint8_t *); 78 static int sdtemp_write_8(struct sdtemp_softc *, uint8_t, uint8_t); 79 #endif /* NOT YET */ 80 static int sdtemp_read_16(struct sdtemp_softc *, uint8_t, uint16_t *); 81 static int sdtemp_write_16(struct sdtemp_softc *, uint8_t, uint16_t); 82 static uint32_t sdtemp_decode_temp(struct sdtemp_softc *, uint16_t); 83 static bool sdtemp_pmf_suspend(device_t, const pmf_qual_t *); 84 static bool sdtemp_pmf_resume(device_t, const pmf_qual_t *); 85 /* Device dependent config functions */ 86 static void sdtemp_config_mcp(struct sdtemp_softc *); 87 static void sdtemp_config_idt(struct sdtemp_softc *); 88 89 struct sdtemp_dev_entry { 90 const uint16_t sdtemp_mfg_id; 91 const uint16_t sdtemp_devrev; 92 const uint16_t sdtemp_mask; 93 void (*sdtemp_config)(struct sdtemp_softc *); 94 const char *sdtemp_desc; 95 }; 96 97 /* Convert sysmon_envsys uKelvin value to simple degC */ 98 99 #define __UK2C(uk) (((uk) - 273150000) / 1000000) 100 101 /* List of devices known to conform to JEDEC JC42.4 */ 102 103 #define CMCP sdtemp_config_mcp 104 #define CIDT sdtemp_config_idt 105 106 static const struct sdtemp_dev_entry 107 sdtemp_dev_table[] = { 108 { AT_MANUFACTURER_ID, AT_30TS00_DEVICE_ID, AT_30TS00_MASK, NULL, 109 "Atmel AT30TS00" }, 110 { AT2_MANUFACTURER_ID, AT2_30TSE004_DEVICE_ID, AT2_30TSE004_MASK, NULL, 111 "Atmel AT30TSE004" }, 112 { GT_MANUFACTURER_ID, GT_30TS00_DEVICE_ID, GT_30TS00_MASK, NULL, 113 "Giantec GT30TS00" }, 114 { GT2_MANUFACTURER_ID, GT2_34TS02_DEVICE_ID, GT2_34TS02_MASK, NULL, 115 "Giantec GT34TS02" }, 116 { MAXIM_MANUFACTURER_ID, MAX_6604_DEVICE_ID, MAX_6604_MASK, NULL, 117 "Maxim MAX6604" }, 118 { MAXIM_MANUFACTURER_ID, MAX_6604_2_DEVICE_ID, MAX_6604_MASK, NULL, 119 "Maxim MAX6604" }, 120 { MCP_MANUFACTURER_ID, MCP_9804_DEVICE_ID, MCP_9804_MASK, CMCP, 121 "Microchip Tech MCP9804" }, 122 { MCP_MANUFACTURER_ID, MCP_9805_DEVICE_ID, MCP_9805_MASK, NULL, 123 "Microchip Tech MCP9805/MCP9843" }, 124 { MCP_MANUFACTURER_ID, MCP_98242_DEVICE_ID, MCP_98242_MASK, CMCP, 125 "Microchip Tech MCP98242" }, 126 { MCP_MANUFACTURER_ID, MCP_98243_DEVICE_ID, MCP_98243_MASK, CMCP, 127 "Microchip Tech MCP98243" }, 128 { MCP_MANUFACTURER_ID, MCP_98244_DEVICE_ID, MCP_98244_MASK, CMCP, 129 "Microchip Tech MCP98244" }, 130 { MCP2_MANUFACTURER_ID, MCP2_EMC1501_DEVICE_ID, MCP2_EMC1501_MASK, NULL, 131 "Microchip Tech EMC1501" }, 132 { ADT_MANUFACTURER_ID, ADT_7408_DEVICE_ID, ADT_7408_MASK, NULL, 133 "Analog Devices ADT7408" }, 134 { NXP_MANUFACTURER_ID, NXP_SE98_DEVICE_ID, NXP_SE98_MASK, NULL, 135 "NXP Semiconductors SE97B/SE98" }, 136 { NXP_MANUFACTURER_ID, NXP_SE97_DEVICE_ID, NXP_SE97_MASK, NULL, 137 "NXP Semiconductors SE97" }, 138 { STTS_MANUFACTURER_ID, STTS_424E_DEVICE_ID, STTS_424E_MASK, NULL, 139 "STmicroelectronics STTS424E" }, 140 { STTS_MANUFACTURER_ID, STTS_424_DEVICE_ID, STTS_424_MASK, NULL, 141 "STmicroelectronics STTS424" }, 142 { STTS_MANUFACTURER_ID, STTS_2002_DEVICE_ID, STTS_2002_MASK, NULL, 143 "STmicroelectronics STTS2002" }, 144 { STTS_MANUFACTURER_ID, STTS_2004_DEVICE_ID, STTS_2004_MASK, NULL, 145 "STmicroelectronics STTS2004" }, 146 { STTS_MANUFACTURER_ID, STTS_3000_DEVICE_ID, STTS_3000_MASK, NULL, 147 "STmicroelectronics STTS3000" }, 148 { CAT_MANUFACTURER_ID, CAT_34TS02_DEVICE_ID, CAT_34TS02_MASK, NULL, 149 "Catalyst CAT34TS02/CAT6095" }, 150 { CAT_MANUFACTURER_ID, CAT_34TS02C_DEVICE_ID, CAT_34TS02C_MASK, NULL, 151 "Catalyst CAT34TS02C" }, 152 { CAT_MANUFACTURER_ID, CAT_34TS04_DEVICE_ID, CAT_34TS04_MASK, NULL, 153 "Catalyst CAT34TS04" }, 154 { IDT_MANUFACTURER_ID, IDT_TSE2004GB2_DEVICE_ID,IDT_TSE2004GB2_MASK, NULL, 155 "Integrated Device Technology TSE2004GB2" }, 156 { IDT_MANUFACTURER_ID, IDT_TS3000B3_DEVICE_ID, IDT_TS3000B3_MASK, CIDT, 157 "Integrated Device Technology TS3000B3/TSE2002B3" }, 158 { IDT_MANUFACTURER_ID, IDT_TS3000GB0_DEVICE_ID, IDT_TS3000GB0_MASK, CIDT, 159 "Integrated Device Technology TS3000GB0" }, 160 { IDT_MANUFACTURER_ID, IDT_TS3000GB2_DEVICE_ID, IDT_TS3000GB2_MASK, CIDT, 161 "Integrated Device Technology TS3000GB2" }, 162 { IDT_MANUFACTURER_ID, IDT_TS3001GB2_DEVICE_ID, IDT_TS3001GB2_MASK, CIDT, 163 "Integrated Device Technology TS3001GB2" }, 164 /* 165 * Don't change the location of the following two entries. Device specific 166 * entry must be located at above. 167 */ 168 { 0, TSE2004AV_ID, TSE2004AV_MASK, NULL, 169 "TSE2004av compliant device (generic driver)" }, 170 { 0, 0, 0, NULL, "Unknown" } 171 }; 172 173 #undef CMCP 174 #undef CIDT 175 176 static const char *temp_resl[] = { 177 "0.5C", 178 "0.25C", 179 "0.125C", 180 "0.0625C" 181 }; 182 183 static int 184 sdtemp_lookup(uint16_t mfg, uint16_t devrev) 185 { 186 int i; 187 188 for (i = 0; sdtemp_dev_table[i].sdtemp_mfg_id; i++) { 189 if (mfg != sdtemp_dev_table[i].sdtemp_mfg_id) 190 continue; 191 if ((devrev & sdtemp_dev_table[i].sdtemp_mask) == 192 sdtemp_dev_table[i].sdtemp_devrev) 193 break; 194 } 195 /* Check TSE2004av */ 196 if ((sdtemp_dev_table[i].sdtemp_mfg_id == 0) 197 && (SDTEMP_IS_TSE2004AV(devrev) == 0)) 198 i++; /* Unknown */ 199 200 return i; 201 } 202 203 static int 204 sdtemp_match(device_t parent, cfdata_t cf, void *aux) 205 { 206 struct i2c_attach_args *ia = aux; 207 uint16_t mfgid, devid, cap; 208 struct sdtemp_softc sc; 209 int i, error; 210 211 sc.sc_tag = ia->ia_tag; 212 sc.sc_address = ia->ia_addr; 213 214 if ((ia->ia_addr & SDTEMP_ADDRMASK) != SDTEMP_ADDR) 215 return 0; 216 217 /* Verify that we can read the manufacturer ID, Device ID and the capability */ 218 iic_acquire_bus(sc.sc_tag, 0); 219 error = sdtemp_read_16(&sc, SDTEMP_REG_MFG_ID, &mfgid) | 220 sdtemp_read_16(&sc, SDTEMP_REG_DEV_REV, &devid) | 221 sdtemp_read_16(&sc, SDTEMP_REG_CAPABILITY, &cap); 222 iic_release_bus(sc.sc_tag, 0); 223 224 if (error) 225 return 0; 226 227 i = sdtemp_lookup(mfgid, devid); 228 if ((sdtemp_dev_table[i].sdtemp_mfg_id == 0) && 229 (sdtemp_dev_table[i].sdtemp_devrev == 0)) { 230 aprint_debug("sdtemp: No match for mfg 0x%04x dev 0x%02x " 231 "rev 0x%02x at address 0x%02x\n", mfgid, devid >> 8, 232 devid & 0xff, sc.sc_address); 233 return 0; 234 } 235 236 /* 237 * Check by SDTEMP_IS_TSE2004AV() might not be enough, so check the alarm 238 * capability, too. 239 */ 240 if ((cap & SDTEMP_CAP_HAS_ALARM) == 0) 241 return 0; 242 243 return I2C_MATCH_ADDRESS_AND_PROBE; 244 } 245 246 static void 247 sdtemp_attach(device_t parent, device_t self, void *aux) 248 { 249 struct sdtemp_softc *sc = device_private(self); 250 struct i2c_attach_args *ia = aux; 251 uint16_t mfgid, devid; 252 int i, error; 253 254 sc->sc_tag = ia->ia_tag; 255 sc->sc_address = ia->ia_addr; 256 sc->sc_dev = self; 257 258 iic_acquire_bus(sc->sc_tag, 0); 259 if ((error = sdtemp_read_16(sc, SDTEMP_REG_MFG_ID, &mfgid)) != 0 || 260 (error = sdtemp_read_16(sc, SDTEMP_REG_DEV_REV, &devid)) != 0) { 261 iic_release_bus(sc->sc_tag, 0); 262 aprint_error(": attach error %d\n", error); 263 return; 264 } 265 sc->sc_mfgid = mfgid; 266 sc->sc_devid = devid; 267 i = sdtemp_lookup(mfgid, devid); 268 sc->sc_devid_masked = devid & sdtemp_dev_table[i].sdtemp_mask; 269 270 aprint_naive(": Temp Sensor\n"); 271 aprint_normal(": %s Temp Sensor\n", sdtemp_dev_table[i].sdtemp_desc); 272 273 if (sdtemp_dev_table[i].sdtemp_mfg_id == 0) { 274 if (SDTEMP_IS_TSE2004AV(devid)) 275 aprint_normal_dev(self, "TSE2004av compliant. " 276 "Manufacturer ID 0x%04hx, Device revision 0x%02x\n", 277 mfgid, devid & TSE2004AV_REV); 278 else { 279 aprint_error_dev(self, 280 "mfg 0x%04x dev 0x%02x rev 0x%02x at addr 0x%02x\n", 281 mfgid, devid >> 8, devid & 0xff, ia->ia_addr); 282 iic_release_bus(sc->sc_tag, 0); 283 aprint_error_dev(self, "It should no happen. " 284 "Why attach() found me?\n"); 285 return; 286 } 287 } 288 289 error = sdtemp_read_16(sc, SDTEMP_REG_CAPABILITY, &sc->sc_capability); 290 aprint_debug_dev(self, "capability reg = %04x\n", sc->sc_capability); 291 sc->sc_resolution 292 = __SHIFTOUT(sc->sc_capability, SDTEMP_CAP_RESOLUTION); 293 /* 294 * Call device dependent function here. Currently, it's used for 295 * the resolution. 296 * 297 * IDT's devices and some Microchip's devices have the resolution 298 * register in the vendor specific registers area. The devices' 299 * resolution bits in the capability register are not the maximum 300 * resolution but the current value of the setting. 301 */ 302 if (sdtemp_dev_table[i].sdtemp_config != NULL) 303 sdtemp_dev_table[i].sdtemp_config(sc); 304 305 aprint_normal_dev(self, "%s accuracy", 306 (sc->sc_capability & SDTEMP_CAP_ACCURACY_1C) ? "high" : "default"); 307 if ((sc->sc_capability & SDTEMP_CAP_WIDER_RANGE) != 0) 308 aprint_normal(", wider range"); 309 aprint_normal(", %s resolution", temp_resl[sc->sc_resolution]); 310 if ((sc->sc_capability & SDTEMP_CAP_VHV) != 0) 311 aprint_debug(", high voltage standoff"); 312 aprint_debug(", %s timeout", 313 (sc->sc_capability & SDTEMP_CAP_TMOUT) ? "25-35ms" : "10-60ms"); 314 if ((sc->sc_capability & SDTEMP_CAP_EVSD) != 0) 315 aprint_normal(", event with shutdown"); 316 aprint_normal("\n"); 317 /* 318 * Alarm capability is required; if not present, this is likely 319 * not a real sdtemp device. 320 */ 321 if (error != 0 || (sc->sc_capability & SDTEMP_CAP_HAS_ALARM) == 0) { 322 iic_release_bus(sc->sc_tag, 0); 323 aprint_error_dev(self, 324 "required alarm capability not present!\n"); 325 return; 326 } 327 /* Set the configuration to defaults. */ 328 error = sdtemp_write_16(sc, SDTEMP_REG_CONFIG, 0); 329 if (error != 0) { 330 iic_release_bus(sc->sc_tag, 0); 331 aprint_error_dev(self, "error %d writing config register\n", 332 error); 333 return; 334 } 335 iic_release_bus(sc->sc_tag, 0); 336 337 /* Hook us into the sysmon_envsys subsystem */ 338 sc->sc_sme = sysmon_envsys_create(); 339 sc->sc_sme->sme_name = device_xname(self); 340 sc->sc_sme->sme_cookie = sc; 341 sc->sc_sme->sme_refresh = sdtemp_refresh; 342 sc->sc_sme->sme_get_limits = sdtemp_get_limits; 343 sc->sc_sme->sme_set_limits = sdtemp_set_limits; 344 345 sc->sc_sensor = kmem_zalloc(sizeof(envsys_data_t), KM_SLEEP); 346 347 /* Initialize sensor data. */ 348 sc->sc_sensor->units = ENVSYS_STEMP; 349 sc->sc_sensor->state = ENVSYS_SINVALID; 350 sc->sc_sensor->flags |= ENVSYS_FMONLIMITS; 351 (void)strlcpy(sc->sc_sensor->desc, device_xname(self), 352 sizeof(sc->sc_sensor->desc)); 353 snprintf(sc->sc_sensor->desc, sizeof(sc->sc_sensor->desc), 354 "DIMM %d temperature", sc->sc_address - SDTEMP_ADDR); 355 356 /* Now attach the sensor */ 357 if (sysmon_envsys_sensor_attach(sc->sc_sme, sc->sc_sensor)) { 358 aprint_error_dev(self, "unable to attach sensor\n"); 359 goto bad; 360 } 361 362 /* Register the device */ 363 error = sysmon_envsys_register(sc->sc_sme); 364 if (error) { 365 aprint_error_dev(self, "error %d registering with sysmon\n", 366 error); 367 goto bad; 368 } 369 370 if (!pmf_device_register(self, sdtemp_pmf_suspend, sdtemp_pmf_resume)) 371 aprint_error_dev(self, "couldn't establish power handler\n"); 372 373 /* Retrieve and display hardware monitor limits */ 374 sdtemp_get_limits(sc->sc_sme, sc->sc_sensor, &sc->sc_deflims, 375 &sc->sc_defprops); 376 aprint_normal_dev(self, "Hardware limits: "); 377 i = 0; 378 if (sc->sc_defprops & PROP_WARNMIN) { 379 aprint_normal("low %dC", 380 __UK2C(sc->sc_deflims.sel_warnmin)); 381 i++; 382 } 383 if (sc->sc_defprops & PROP_WARNMAX) { 384 aprint_normal("%shigh %dC ", (i)?", ":"", 385 __UK2C(sc->sc_deflims.sel_warnmax)); 386 i++; 387 } 388 if (sc->sc_defprops & PROP_CRITMAX) { 389 aprint_normal("%scritical %dC ", (i)?", ":"", 390 __UK2C(sc->sc_deflims.sel_critmax)); 391 i++; 392 } 393 aprint_normal("%s\n", (i)?"":"none set"); 394 395 return; 396 397 bad: 398 kmem_free(sc->sc_sensor, sizeof(envsys_data_t)); 399 sysmon_envsys_destroy(sc->sc_sme); 400 } 401 402 static int 403 sdtemp_detach(device_t self, int flags) 404 { 405 struct sdtemp_softc *sc = device_private(self); 406 407 pmf_device_deregister(self); 408 409 if (sc->sc_sme) 410 sysmon_envsys_unregister(sc->sc_sme); 411 if (sc->sc_sensor) 412 kmem_free(sc->sc_sensor, sizeof(envsys_data_t)); 413 414 return 0; 415 } 416 417 /* Retrieve current limits from device, and encode in uKelvins */ 418 static void 419 sdtemp_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata, 420 sysmon_envsys_lim_t *limits, uint32_t *props) 421 { 422 struct sdtemp_softc *sc = sme->sme_cookie; 423 uint16_t lim; 424 425 *props = 0; 426 iic_acquire_bus(sc->sc_tag, 0); 427 if (sdtemp_read_16(sc, SDTEMP_REG_LOWER_LIM, &lim) == 0 && lim != 0) { 428 limits->sel_warnmin = sdtemp_decode_temp(sc, lim); 429 *props |= PROP_WARNMIN; 430 } 431 if (sdtemp_read_16(sc, SDTEMP_REG_UPPER_LIM, &lim) == 0 && lim != 0) { 432 limits->sel_warnmax = sdtemp_decode_temp(sc, lim); 433 *props |= PROP_WARNMAX; 434 } 435 if (sdtemp_read_16(sc, SDTEMP_REG_CRIT_LIM, &lim) == 0 && lim != 0) { 436 limits->sel_critmax = sdtemp_decode_temp(sc, lim); 437 *props |= PROP_CRITMAX; 438 } 439 iic_release_bus(sc->sc_tag, 0); 440 if (*props != 0) 441 *props |= PROP_DRIVER_LIMITS; 442 } 443 444 /* Send current limit values to the device */ 445 static void 446 sdtemp_set_limits(struct sysmon_envsys *sme, envsys_data_t *edata, 447 sysmon_envsys_lim_t *limits, uint32_t *props) 448 { 449 uint16_t val; 450 struct sdtemp_softc *sc = sme->sme_cookie; 451 452 if (limits == NULL) { 453 limits = &sc->sc_deflims; 454 props = &sc->sc_defprops; 455 } 456 iic_acquire_bus(sc->sc_tag, 0); 457 if (*props & PROP_WARNMIN) { 458 val = __UK2C(limits->sel_warnmin); 459 (void)sdtemp_write_16(sc, SDTEMP_REG_LOWER_LIM, 460 (val << 4) & SDTEMP_TEMP_MASK); 461 } 462 if (*props & PROP_WARNMAX) { 463 val = __UK2C(limits->sel_warnmax); 464 (void)sdtemp_write_16(sc, SDTEMP_REG_UPPER_LIM, 465 (val << 4) & SDTEMP_TEMP_MASK); 466 } 467 if (*props & PROP_CRITMAX) { 468 val = __UK2C(limits->sel_critmax); 469 (void)sdtemp_write_16(sc, SDTEMP_REG_CRIT_LIM, 470 (val << 4) & SDTEMP_TEMP_MASK); 471 } 472 iic_release_bus(sc->sc_tag, 0); 473 474 /* 475 * If at least one limit is set that we can handle, and no 476 * limits are set that we cannot handle, tell sysmon that 477 * the driver will take care of monitoring the limits! 478 */ 479 if (*props & (PROP_CRITMIN | PROP_BATTCAP | PROP_BATTWARN)) 480 *props &= ~PROP_DRIVER_LIMITS; 481 else if (*props & PROP_LIMITS) 482 *props |= PROP_DRIVER_LIMITS; 483 else 484 *props &= ~PROP_DRIVER_LIMITS; 485 } 486 487 #ifdef NOT_YET /* All registers on these sensors are 16-bits */ 488 489 /* Read a 8-bit value from a register */ 490 static int 491 sdtemp_read_8(struct sdtemp_softc *sc, uint8_t reg, uint8_t *valp) 492 { 493 int error; 494 495 error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 496 sc->sc_address, ®, 1, valp, sizeof(*valp), 0); 497 498 return error; 499 } 500 501 static int 502 sdtemp_write_8(struct sdtemp_softc *sc, uint8_t reg, uint8_t val) 503 { 504 return iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 505 sc->sc_address, ®, 1, &val, sizeof(val), 0); 506 } 507 #endif /* NOT_YET */ 508 509 /* Read a 16-bit value from a register */ 510 static int 511 sdtemp_read_16(struct sdtemp_softc *sc, uint8_t reg, uint16_t *valp) 512 { 513 int error; 514 515 error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, 516 sc->sc_address, ®, 1, valp, sizeof(*valp), 0); 517 if (error) 518 return error; 519 520 *valp = be16toh(*valp); 521 522 return 0; 523 } 524 525 static int 526 sdtemp_write_16(struct sdtemp_softc *sc, uint8_t reg, uint16_t val) 527 { 528 uint16_t temp; 529 530 temp = htobe16(val); 531 return iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP, 532 sc->sc_address, ®, 1, &temp, sizeof(temp), 0); 533 } 534 535 static uint32_t 536 sdtemp_decode_temp(struct sdtemp_softc *sc, uint16_t temp) 537 { 538 uint32_t val; 539 int32_t stemp; 540 541 /* Get only the temperature bits */ 542 temp &= SDTEMP_TEMP_MASK; 543 544 /* If necessary, extend the sign bit */ 545 if ((sc->sc_capability & SDTEMP_CAP_WIDER_RANGE) && 546 (temp & SDTEMP_TEMP_NEGATIVE)) 547 temp |= SDTEMP_TEMP_SIGN_EXT; 548 549 /* Mask off only bits valid within current resolution */ 550 temp &= ~(0x7 >> sc->sc_resolution); 551 552 /* Treat as signed and extend to 32-bits */ 553 stemp = (int16_t)temp; 554 555 /* Now convert from 0.0625 (1/16) deg C increments to microKelvins */ 556 val = (stemp * 62500) + 273150000; 557 558 return val; 559 } 560 561 static void 562 sdtemp_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 563 { 564 struct sdtemp_softc *sc = sme->sme_cookie; 565 uint16_t val; 566 int error; 567 568 iic_acquire_bus(sc->sc_tag, 0); 569 error = sdtemp_read_16(sc, SDTEMP_REG_AMBIENT_TEMP, &val); 570 iic_release_bus(sc->sc_tag, 0); 571 572 if (error) { 573 edata->state = ENVSYS_SINVALID; 574 return; 575 } 576 577 edata->value_cur = sdtemp_decode_temp(sc, val); 578 579 /* Now check for limits */ 580 if ((edata->upropset & PROP_DRIVER_LIMITS) == 0) 581 edata->state = ENVSYS_SVALID; 582 else if ((val & SDTEMP_ABOVE_CRIT) && 583 (edata->upropset & PROP_CRITMAX)) 584 edata->state = ENVSYS_SCRITOVER; 585 else if ((val & SDTEMP_ABOVE_UPPER) && 586 (edata->upropset & PROP_WARNMAX)) 587 edata->state = ENVSYS_SWARNOVER; 588 else if ((val & SDTEMP_BELOW_LOWER) && 589 (edata->upropset & PROP_WARNMIN)) 590 edata->state = ENVSYS_SWARNUNDER; 591 else 592 edata->state = ENVSYS_SVALID; 593 } 594 595 /* 596 * power management functions 597 * 598 * We go into "shutdown" mode at suspend time, and return to normal 599 * mode upon resume. This reduces power consumption by disabling 600 * the A/D converter. 601 */ 602 603 static bool 604 sdtemp_pmf_suspend(device_t dev, const pmf_qual_t *qual) 605 { 606 struct sdtemp_softc *sc = device_private(dev); 607 int error; 608 uint16_t config; 609 610 iic_acquire_bus(sc->sc_tag, 0); 611 error = sdtemp_read_16(sc, SDTEMP_REG_CONFIG, &config); 612 if (error == 0) { 613 config |= SDTEMP_CONFIG_SHUTDOWN_MODE; 614 error = sdtemp_write_16(sc, SDTEMP_REG_CONFIG, config); 615 } 616 iic_release_bus(sc->sc_tag, 0); 617 return (error == 0); 618 } 619 620 static bool 621 sdtemp_pmf_resume(device_t dev, const pmf_qual_t *qual) 622 { 623 struct sdtemp_softc *sc = device_private(dev); 624 int error; 625 uint16_t config; 626 627 iic_acquire_bus(sc->sc_tag, 0); 628 error = sdtemp_read_16(sc, SDTEMP_REG_CONFIG, &config); 629 if (error == 0) { 630 config &= ~SDTEMP_CONFIG_SHUTDOWN_MODE; 631 error = sdtemp_write_16(sc, SDTEMP_REG_CONFIG, config); 632 } 633 iic_release_bus(sc->sc_tag, 0); 634 return (error == 0); 635 } 636 637 /* Device dependent config functions */ 638 639 static void 640 sdtemp_config_mcp(struct sdtemp_softc *sc) 641 { 642 int rv; 643 uint8_t resolreg; 644 645 /* Note that MCP9805 has no resolution register */ 646 switch (sc->sc_devid_masked) { 647 case MCP_9804_DEVICE_ID: 648 case MCP_98242_DEVICE_ID: 649 case MCP_98243_DEVICE_ID: 650 resolreg = SDTEMP_REG_MCP_RESOLUTION_9804; 651 break; 652 case MCP_98244_DEVICE_ID: 653 resolreg = SDTEMP_REG_MCP_RESOLUTION_98244; 654 break; 655 default: 656 aprint_error("%s: %s: unknown device ID (%04hx)\n", 657 device_xname(sc->sc_dev), __func__, sc->sc_devid_masked); 658 return; 659 } 660 661 /* 662 * Set resolution to the max. 663 * 664 * Even if it fails, the resolution will be the default. It's not a 665 * fatal error. 666 */ 667 rv = sdtemp_write_16(sc, resolreg, SDTEMP_CAP_RESOLUTION_MAX); 668 if (rv == 0) 669 sc->sc_resolution = SDTEMP_CAP_RESOLUTION_MAX; 670 else 671 aprint_error("%s: error %d writing resolution register\n", 672 device_xname(sc->sc_dev), rv); 673 } 674 675 static void 676 sdtemp_config_idt(struct sdtemp_softc *sc) 677 { 678 int rv; 679 680 /* 681 * Set resolution to the max. 682 * 683 * Even if it fails, the resolution will be the default. It's not a 684 * fatal error. 685 */ 686 rv = sdtemp_write_16(sc, SDTEMP_REG_IDT_RESOLUTION, 687 __SHIFTIN(SDTEMP_CAP_RESOLUTION_MAX, SDTEMP_CAP_RESOLUTION)); 688 if (rv == 0) 689 sc->sc_resolution = SDTEMP_CAP_RESOLUTION_MAX; 690 else 691 aprint_error("%s: error %d writing resolution register\n", 692 device_xname(sc->sc_dev), rv); 693 } 694 695 MODULE(MODULE_CLASS_DRIVER, sdtemp, "i2cexec,sysmon_envsys"); 696 697 #ifdef _MODULE 698 #include "ioconf.c" 699 #endif 700 701 static int 702 sdtemp_modcmd(modcmd_t cmd, void *opaque) 703 { 704 int error = 0; 705 706 switch (cmd) { 707 case MODULE_CMD_INIT: 708 #ifdef _MODULE 709 error = config_init_component(cfdriver_ioconf_sdtemp, 710 cfattach_ioconf_sdtemp, cfdata_ioconf_sdtemp); 711 #endif 712 return error; 713 case MODULE_CMD_FINI: 714 #ifdef _MODULE 715 error = config_fini_component(cfdriver_ioconf_sdtemp, 716 cfattach_ioconf_sdtemp, cfdata_ioconf_sdtemp); 717 #endif 718 return error; 719 default: 720 return ENOTTY; 721 } 722 } 723