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