1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2010 Andreas Tobler 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/bus.h> 30 #include <sys/systm.h> 31 #include <sys/module.h> 32 #include <sys/callout.h> 33 #include <sys/conf.h> 34 #include <sys/cpu.h> 35 #include <sys/ctype.h> 36 #include <sys/kernel.h> 37 #include <sys/reboot.h> 38 #include <sys/rman.h> 39 #include <sys/sysctl.h> 40 #include <sys/limits.h> 41 42 #include <machine/bus.h> 43 #include <machine/md_var.h> 44 45 #include <dev/iicbus/iicbus.h> 46 #include <dev/iicbus/iiconf.h> 47 48 #include <dev/ofw/openfirm.h> 49 #include <dev/ofw/ofw_bus.h> 50 #include <powerpc/powermac/powermac_thermal.h> 51 52 /* CPU A/B sensors, temp and adc: AD7417. */ 53 54 #define AD7417_TEMP 0x00 55 #define AD7417_CONFIG 0x01 56 #define AD7417_ADC 0x04 57 #define AD7417_CONFIG2 0x05 58 #define AD7417_CONFMASK 0xe0 59 60 uint8_t adc741x_config; 61 62 struct ad7417_sensor { 63 struct pmac_therm therm; 64 device_t dev; 65 int id; 66 enum { 67 ADC7417_TEMP_SENSOR, 68 ADC7417_ADC_SENSOR 69 } type; 70 }; 71 72 struct write_data { 73 uint8_t reg; 74 uint8_t val; 75 }; 76 77 struct read_data { 78 uint8_t reg; 79 uint16_t val; 80 }; 81 82 /* Regular bus attachment functions */ 83 static int ad7417_probe(device_t); 84 static int ad7417_attach(device_t); 85 86 /* Utility functions */ 87 static int ad7417_sensor_sysctl(SYSCTL_HANDLER_ARGS); 88 static int ad7417_write(device_t dev, uint32_t addr, uint8_t reg, 89 uint8_t *buf, int len); 90 static int ad7417_read_1(device_t dev, uint32_t addr, uint8_t reg, 91 uint8_t *data); 92 static int ad7417_read_2(device_t dev, uint32_t addr, uint8_t reg, 93 uint16_t *data); 94 static int ad7417_write_read(device_t dev, uint32_t addr, 95 struct write_data out, struct read_data *in); 96 static int ad7417_diode_read(struct ad7417_sensor *sens); 97 static int ad7417_adc_read(struct ad7417_sensor *sens); 98 static int ad7417_sensor_read(struct ad7417_sensor *sens); 99 100 struct ad7417_softc { 101 device_t sc_dev; 102 uint32_t sc_addr; 103 struct ad7417_sensor *sc_sensors; 104 int sc_nsensors; 105 int init_done; 106 }; 107 static device_method_t ad7417_methods[] = { 108 /* Device interface */ 109 DEVMETHOD(device_probe, ad7417_probe), 110 DEVMETHOD(device_attach, ad7417_attach), 111 { 0, 0 }, 112 }; 113 114 static driver_t ad7417_driver = { 115 "ad7417", 116 ad7417_methods, 117 sizeof(struct ad7417_softc) 118 }; 119 120 DRIVER_MODULE(ad7417, iicbus, ad7417_driver, 0, 0); 121 static MALLOC_DEFINE(M_AD7417, "ad7417", "Supply-Monitor AD7417"); 122 123 124 static int 125 ad7417_write(device_t dev, uint32_t addr, uint8_t reg, uint8_t *buff, int len) 126 { 127 unsigned char buf[4]; 128 int try = 0; 129 130 struct iic_msg msg[] = { 131 { addr, IIC_M_WR, 0, buf } 132 }; 133 134 msg[0].len = len + 1; 135 buf[0] = reg; 136 memcpy(buf + 1, buff, len); 137 138 for (;;) 139 { 140 if (iicbus_transfer(dev, msg, nitems(msg)) == 0) 141 return (0); 142 143 if (++try > 5) { 144 device_printf(dev, "iicbus write failed\n"); 145 return (-1); 146 } 147 pause("ad7417_write", hz); 148 } 149 } 150 151 static int 152 ad7417_read_1(device_t dev, uint32_t addr, uint8_t reg, uint8_t *data) 153 { 154 uint8_t buf[4]; 155 int err, try = 0; 156 157 struct iic_msg msg[2] = { 158 { addr, IIC_M_WR | IIC_M_NOSTOP, 1, ® }, 159 { addr, IIC_M_RD, 1, buf }, 160 }; 161 162 for (;;) 163 { 164 err = iicbus_transfer(dev, msg, nitems(msg)); 165 if (err != 0) 166 goto retry; 167 168 *data = *((uint8_t*)buf); 169 return (0); 170 retry: 171 if (++try > 5) { 172 device_printf(dev, "iicbus read failed\n"); 173 return (-1); 174 } 175 pause("ad7417_read_1", hz); 176 } 177 } 178 179 static int 180 ad7417_read_2(device_t dev, uint32_t addr, uint8_t reg, uint16_t *data) 181 { 182 uint8_t buf[4]; 183 int err, try = 0; 184 185 struct iic_msg msg[2] = { 186 { addr, IIC_M_WR | IIC_M_NOSTOP, 1, ® }, 187 { addr, IIC_M_RD, 2, buf }, 188 }; 189 190 for (;;) 191 { 192 err = iicbus_transfer(dev, msg, nitems(msg)); 193 if (err != 0) 194 goto retry; 195 196 *data = *((uint16_t*)buf); 197 return (0); 198 retry: 199 if (++try > 5) { 200 device_printf(dev, "iicbus read failed\n"); 201 return (-1); 202 } 203 pause("ad7417_read_2", hz); 204 } 205 } 206 207 static int 208 ad7417_write_read(device_t dev, uint32_t addr, struct write_data out, 209 struct read_data *in) 210 { 211 uint8_t buf[4]; 212 int err, try = 0; 213 214 /* Do a combined write/read. */ 215 struct iic_msg msg[3] = { 216 { addr, IIC_M_WR, 2, buf }, 217 { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &in->reg }, 218 { addr, IIC_M_RD, 2, buf }, 219 }; 220 221 /* Prepare the write msg. */ 222 buf[0] = out.reg; 223 buf[1] = out.val & 0xff; 224 225 for (;;) 226 { 227 err = iicbus_transfer(dev, msg, nitems(msg)); 228 if (err != 0) 229 goto retry; 230 231 in->val = *((uint16_t*)buf); 232 return (0); 233 retry: 234 if (++try > 5) { 235 device_printf(dev, "iicbus write/read failed\n"); 236 return (-1); 237 } 238 pause("ad7417_write_read", hz); 239 } 240 } 241 242 static int 243 ad7417_init_adc(device_t dev, uint32_t addr) 244 { 245 uint8_t buf; 246 int err; 247 struct ad7417_softc *sc; 248 249 sc = device_get_softc(dev); 250 251 adc741x_config = 0; 252 /* Clear Config2 */ 253 buf = 0; 254 255 err = ad7417_write(dev, addr, AD7417_CONFIG2, &buf, sizeof(buf)); 256 257 /* Read & cache Config1 */ 258 buf = 0; 259 err = ad7417_write(dev, addr, AD7417_CONFIG, &buf, sizeof(buf)); 260 err = ad7417_read_1(dev, addr, AD7417_CONFIG, &buf); 261 adc741x_config = (uint8_t)buf; 262 263 /* Disable shutdown mode */ 264 adc741x_config &= 0xfe; 265 buf = adc741x_config; 266 err = ad7417_write(dev, addr, AD7417_CONFIG, &buf, sizeof(buf)); 267 if (err < 0) 268 return (-1); 269 270 sc->init_done = 1; 271 272 return (0); 273 274 } 275 static int 276 ad7417_probe(device_t dev) 277 { 278 const char *name, *compatible; 279 struct ad7417_softc *sc; 280 281 name = ofw_bus_get_name(dev); 282 compatible = ofw_bus_get_compat(dev); 283 284 if (!name) 285 return (ENXIO); 286 287 if (strcmp(name, "supply-monitor") != 0 || 288 strcmp(compatible, "ad7417") != 0) 289 return (ENXIO); 290 291 sc = device_get_softc(dev); 292 sc->sc_dev = dev; 293 sc->sc_addr = iicbus_get_addr(dev); 294 295 device_set_desc(dev, "Supply-Monitor AD7417"); 296 297 return (0); 298 } 299 300 /* 301 * This function returns the number of sensors. If we call it the second time 302 * and we have allocated memory for sc->sc_sensors, we fill in the properties. 303 */ 304 static int 305 ad7417_fill_sensor_prop(device_t dev) 306 { 307 phandle_t child, node; 308 struct ad7417_softc *sc; 309 u_int id[10]; 310 char location[96]; 311 char type[32]; 312 int i = 0, j, len = 0, prop_len, prev_len = 0; 313 314 sc = device_get_softc(dev); 315 316 child = ofw_bus_get_node(dev); 317 318 /* Fill the sensor location property. */ 319 prop_len = OF_getprop(child, "hwsensor-location", location, 320 sizeof(location)); 321 while (len < prop_len) { 322 if (sc->sc_sensors != NULL) 323 strcpy(sc->sc_sensors[i].therm.name, location + len); 324 prev_len = strlen(location + len) + 1; 325 len += prev_len; 326 i++; 327 } 328 if (sc->sc_sensors == NULL) 329 return (i); 330 331 /* Fill the sensor type property. */ 332 len = 0; 333 i = 0; 334 prev_len = 0; 335 prop_len = OF_getprop(child, "hwsensor-type", type, sizeof(type)); 336 while (len < prop_len) { 337 if (strcmp(type + len, "temperature") == 0) 338 sc->sc_sensors[i].type = ADC7417_TEMP_SENSOR; 339 else 340 sc->sc_sensors[i].type = ADC7417_ADC_SENSOR; 341 prev_len = strlen(type + len) + 1; 342 len += prev_len; 343 i++; 344 } 345 346 /* Fill the sensor id property. Taken from OF. */ 347 prop_len = OF_getprop(child, "hwsensor-id", id, sizeof(id)); 348 for (j = 0; j < i; j++) 349 sc->sc_sensors[j].id = id[j]; 350 351 /* Fill the sensor zone property. Taken from OF. */ 352 prop_len = OF_getprop(child, "hwsensor-zone", id, sizeof(id)); 353 for (j = 0; j < i; j++) 354 sc->sc_sensors[j].therm.zone = id[j]; 355 356 /* Some PowerMac's have the real location of the sensors on 357 child nodes of the hwsensor-location node. Check for and 358 fix the name if needed. 359 This is needed to apply the below HACK with the diode. 360 */ 361 j = 0; 362 for (node = OF_child(child); node != 0; node = OF_peer(node)) { 363 364 OF_getprop(node, "location", location, sizeof(location)); 365 strcpy(sc->sc_sensors[i].therm.name, location); 366 j++; 367 } 368 369 /* Finish setting up sensor properties */ 370 for (j = 0; j < i; j++) { 371 sc->sc_sensors[j].dev = dev; 372 373 /* HACK: Apple wired a random diode to the ADC line */ 374 if ((strstr(sc->sc_sensors[j].therm.name, "DIODE TEMP") 375 != NULL) 376 || (strstr(sc->sc_sensors[j].therm.name, "AD1") != NULL)) { 377 sc->sc_sensors[j].type = ADC7417_TEMP_SENSOR; 378 sc->sc_sensors[j].therm.read = 379 (int (*)(struct pmac_therm *))(ad7417_diode_read); 380 } else { 381 sc->sc_sensors[j].therm.read = 382 (int (*)(struct pmac_therm *))(ad7417_sensor_read); 383 } 384 385 if (sc->sc_sensors[j].type != ADC7417_TEMP_SENSOR) 386 continue; 387 388 /* Make up some ranges */ 389 sc->sc_sensors[j].therm.target_temp = 500 + ZERO_C_TO_K; 390 sc->sc_sensors[j].therm.max_temp = 900 + ZERO_C_TO_K; 391 392 pmac_thermal_sensor_register(&sc->sc_sensors[j].therm); 393 } 394 395 return (i); 396 } 397 398 static int 399 ad7417_attach(device_t dev) 400 { 401 struct ad7417_softc *sc; 402 struct sysctl_oid *oid, *sensroot_oid; 403 struct sysctl_ctx_list *ctx; 404 char sysctl_name[32]; 405 int i, j; 406 const char *unit; 407 408 sc = device_get_softc(dev); 409 410 sc->sc_nsensors = 0; 411 412 /* Count the actual number of sensors. */ 413 sc->sc_nsensors = ad7417_fill_sensor_prop(dev); 414 415 device_printf(dev, "%d sensors detected.\n", sc->sc_nsensors); 416 417 if (sc->sc_nsensors == 0) 418 device_printf(dev, "WARNING: No AD7417 sensors detected!\n"); 419 420 sc->sc_sensors = malloc (sc->sc_nsensors * sizeof(struct ad7417_sensor), 421 M_AD7417, M_WAITOK | M_ZERO); 422 423 ctx = device_get_sysctl_ctx(dev); 424 sensroot_oid = SYSCTL_ADD_NODE(ctx, 425 SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "sensor", 426 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "AD7417 Sensor Information"); 427 428 /* Now we can fill the properties into the allocated struct. */ 429 sc->sc_nsensors = ad7417_fill_sensor_prop(dev); 430 431 /* Add sysctls for the sensors. */ 432 for (i = 0; i < sc->sc_nsensors; i++) { 433 for (j = 0; j < strlen(sc->sc_sensors[i].therm.name); j++) { 434 sysctl_name[j] = 435 tolower(sc->sc_sensors[i].therm.name[j]); 436 if (isspace(sysctl_name[j])) 437 sysctl_name[j] = '_'; 438 } 439 sysctl_name[j] = 0; 440 441 oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(sensroot_oid), 442 OID_AUTO, sysctl_name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 443 "Sensor Information"); 444 445 if (sc->sc_sensors[i].type == ADC7417_TEMP_SENSOR) { 446 unit = "temp"; 447 } else { 448 unit = "volt"; 449 } 450 /* I use i to pass the sensor id. */ 451 SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 452 unit, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, 453 dev, i, ad7417_sensor_sysctl, 454 sc->sc_sensors[i].type == ADC7417_TEMP_SENSOR ? 455 "IK" : "I", 456 sc->sc_sensors[i].type == ADC7417_TEMP_SENSOR ? 457 "sensor unit (C)" : "sensor unit (mV)"); 458 } 459 /* Dump sensor location, ID & type. */ 460 if (bootverbose) { 461 device_printf(dev, "Sensors\n"); 462 for (i = 0; i < sc->sc_nsensors; i++) { 463 device_printf(dev, "Location: %s ID: %d type: %d\n", 464 sc->sc_sensors[i].therm.name, 465 sc->sc_sensors[i].id, 466 sc->sc_sensors[i].type); 467 } 468 } 469 470 return (0); 471 } 472 473 static int 474 ad7417_get_temp(device_t dev, uint32_t addr, int *temp) 475 { 476 uint16_t buf[2]; 477 uint16_t read; 478 int err; 479 480 err = ad7417_read_2(dev, addr, AD7417_TEMP, buf); 481 482 if (err < 0) 483 return (-1); 484 485 read = *((int16_t*)buf); 486 487 /* The ADC is 10 bit, the resolution is 0.25 C. 488 The temperature is in tenth kelvin. 489 */ 490 *temp = (((int16_t)(read & 0xffc0)) >> 6) * 25 / 10; 491 return (0); 492 } 493 494 static int 495 ad7417_get_adc(device_t dev, uint32_t addr, unsigned int *value, 496 uint8_t chan) 497 { 498 uint8_t tmp; 499 int err; 500 struct write_data config; 501 struct read_data data; 502 503 tmp = chan << 5; 504 config.reg = AD7417_CONFIG; 505 data.reg = AD7417_ADC; 506 data.val = 0; 507 508 err = ad7417_read_1(dev, addr, AD7417_CONFIG, &config.val); 509 510 config.val = (config.val & ~AD7417_CONFMASK) | (tmp & AD7417_CONFMASK); 511 512 err = ad7417_write_read(dev, addr, config, &data); 513 if (err < 0) 514 return (-1); 515 516 *value = ((uint32_t)data.val) >> 6; 517 518 return (0); 519 } 520 521 static int 522 ad7417_diode_read(struct ad7417_sensor *sens) 523 { 524 static int eeprom_read = 0; 525 static cell_t eeprom[2][40]; 526 phandle_t eeprom_node; 527 int rawval, diode_slope, diode_offset; 528 int temp; 529 530 if (!eeprom_read) { 531 eeprom_node = OF_finddevice("/u3/i2c/cpuid@a0"); 532 OF_getprop(eeprom_node, "cpuid", eeprom[0], sizeof(eeprom[0])); 533 eeprom_node = OF_finddevice("/u3/i2c/cpuid@a2"); 534 OF_getprop(eeprom_node, "cpuid", eeprom[1], sizeof(eeprom[1])); 535 eeprom_read = 1; 536 } 537 538 rawval = ad7417_adc_read(sens); 539 if (rawval < 0) 540 return (-1); 541 542 if (strstr(sens->therm.name, "CPU B") != NULL) { 543 diode_slope = eeprom[1][0x11] >> 16; 544 diode_offset = (int16_t)(eeprom[1][0x11] & 0xffff) << 12; 545 } else { 546 diode_slope = eeprom[0][0x11] >> 16; 547 diode_offset = (int16_t)(eeprom[0][0x11] & 0xffff) << 12; 548 } 549 550 temp = (rawval*diode_slope + diode_offset) >> 2; 551 temp = (10*(temp >> 16)) + ((10*(temp & 0xffff)) >> 16); 552 553 return (temp + ZERO_C_TO_K); 554 } 555 556 static int 557 ad7417_adc_read(struct ad7417_sensor *sens) 558 { 559 struct ad7417_softc *sc; 560 uint8_t chan; 561 int temp; 562 563 sc = device_get_softc(sens->dev); 564 565 switch (sens->id) { 566 case 11: 567 case 16: 568 chan = 1; 569 break; 570 case 12: 571 case 17: 572 chan = 2; 573 break; 574 case 13: 575 case 18: 576 chan = 3; 577 break; 578 case 14: 579 case 19: 580 chan = 4; 581 break; 582 default: 583 chan = 1; 584 } 585 586 if (ad7417_get_adc(sc->sc_dev, sc->sc_addr, &temp, chan) < 0) 587 return (-1); 588 589 return (temp); 590 } 591 592 593 static int 594 ad7417_sensor_read(struct ad7417_sensor *sens) 595 { 596 struct ad7417_softc *sc; 597 int temp; 598 599 sc = device_get_softc(sens->dev); 600 601 /* Init the ADC if not already done.*/ 602 if (!sc->init_done) 603 if (ad7417_init_adc(sc->sc_dev, sc->sc_addr) < 0) 604 return (-1); 605 606 if (sens->type == ADC7417_TEMP_SENSOR) { 607 if (ad7417_get_temp(sc->sc_dev, sc->sc_addr, &temp) < 0) 608 return (-1); 609 temp += ZERO_C_TO_K; 610 } else { 611 temp = ad7417_adc_read(sens); 612 } 613 return (temp); 614 } 615 616 static int 617 ad7417_sensor_sysctl(SYSCTL_HANDLER_ARGS) 618 { 619 device_t dev; 620 struct ad7417_softc *sc; 621 struct ad7417_sensor *sens; 622 int value = 0; 623 int error; 624 625 dev = arg1; 626 sc = device_get_softc(dev); 627 sens = &sc->sc_sensors[arg2]; 628 629 value = sens->therm.read(&sens->therm); 630 if (value < 0) 631 return (ENXIO); 632 633 error = sysctl_handle_int(oidp, &value, 0, req); 634 635 return (error); 636 } 637