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