1222457Sattilio/*- 2222457Sattilio * Copyright (c) 2010 Andreas Tobler 3222457Sattilio * All rights reserved. 4222457Sattilio * 5222457Sattilio * Redistribution and use in source and binary forms, with or without 6222457Sattilio * modification, are permitted provided that the following conditions 7222457Sattilio * are met: 8222457Sattilio * 1. Redistributions of source code must retain the above copyright 9222457Sattilio * notice, this list of conditions and the following disclaimer. 10222457Sattilio * 2. Redistributions in binary form must reproduce the above copyright 11222457Sattilio * notice, this list of conditions and the following disclaimer in the 12222457Sattilio * documentation and/or other materials provided with the distribution. 13222457Sattilio * 14222457Sattilio * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15222457Sattilio * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16222457Sattilio * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17222457Sattilio * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18222457Sattilio * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 19222457Sattilio * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20222457Sattilio * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 21222457Sattilio * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22222457Sattilio * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23222457Sattilio * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24222457Sattilio * SUCH DAMAGE. 25222457Sattilio */ 26222457Sattilio 27222457Sattilio#include <sys/cdefs.h> 28222457Sattilio__FBSDID("$FreeBSD$"); 29222457Sattilio 30222457Sattilio#include <sys/param.h> 31222457Sattilio#include <sys/bus.h> 32222457Sattilio#include <sys/systm.h> 33222457Sattilio#include <sys/module.h> 34222457Sattilio#include <sys/callout.h> 35222457Sattilio#include <sys/conf.h> 36222457Sattilio#include <sys/cpu.h> 37222457Sattilio#include <sys/ctype.h> 38222457Sattilio#include <sys/kernel.h> 39222457Sattilio#include <sys/reboot.h> 40222457Sattilio#include <sys/rman.h> 41222457Sattilio#include <sys/sysctl.h> 42222457Sattilio#include <sys/limits.h> 43222457Sattilio 44222457Sattilio#include <machine/bus.h> 45222457Sattilio#include <machine/md_var.h> 46222457Sattilio 47222457Sattilio#include <dev/iicbus/iicbus.h> 48222457Sattilio#include <dev/iicbus/iiconf.h> 49222457Sattilio 50222457Sattilio#include <dev/ofw/openfirm.h> 51222457Sattilio#include <dev/ofw/ofw_bus.h> 52222526Sattilio#include <powerpc/powermac/powermac_thermal.h> 53222457Sattilio 54222457Sattilio/* CPU A/B sensors, temp and adc: AD7417. */ 55222457Sattilio 56222457Sattilio#define AD7417_TEMP 0x00 57222457Sattilio#define AD7417_CONFIG 0x01 58222457Sattilio#define AD7417_ADC 0x04 59222457Sattilio#define AD7417_CONFIG2 0x05 60222457Sattilio#define AD7417_CONFMASK 0xe0 61222457Sattilio 62222457Sattiliouint8_t adc741x_config; 63222457Sattilio 64222457Sattiliostruct ad7417_sensor { 65222526Sattilio struct pmac_therm therm; 66222526Sattilio device_t dev; 67222457Sattilio int id; 68222457Sattilio enum { 69222457Sattilio ADC7417_TEMP_SENSOR, 70222457Sattilio ADC7417_ADC_SENSOR 71222457Sattilio } type; 72222457Sattilio}; 73222457Sattilio 74222860Sandreaststruct write_data { 75222860Sandreast uint8_t reg; 76222860Sandreast uint8_t val; 77222860Sandreast}; 78222860Sandreast 79222860Sandreaststruct read_data { 80222860Sandreast uint8_t reg; 81222860Sandreast uint16_t val; 82222860Sandreast}; 83222860Sandreast 84222457Sattilio/* Regular bus attachment functions */ 85222457Sattiliostatic int ad7417_probe(device_t); 86222457Sattiliostatic int ad7417_attach(device_t); 87222457Sattilio 88222457Sattilio/* Utility functions */ 89222457Sattiliostatic int ad7417_sensor_sysctl(SYSCTL_HANDLER_ARGS); 90222457Sattiliostatic int ad7417_write(device_t dev, uint32_t addr, uint8_t reg, 91222457Sattilio uint8_t *buf, int len); 92222457Sattiliostatic int ad7417_read_1(device_t dev, uint32_t addr, uint8_t reg, 93222457Sattilio uint8_t *data); 94222457Sattiliostatic int ad7417_read_2(device_t dev, uint32_t addr, uint8_t reg, 95222457Sattilio uint16_t *data); 96222860Sandreaststatic int ad7417_write_read(device_t dev, uint32_t addr, 97222860Sandreast struct write_data out, struct read_data *in); 98222526Sattiliostatic int ad7417_diode_read(struct ad7417_sensor *sens); 99222526Sattiliostatic int ad7417_adc_read(struct ad7417_sensor *sens); 100222526Sattiliostatic int ad7417_sensor_read(struct ad7417_sensor *sens); 101222457Sattilio 102222457Sattiliostruct ad7417_softc { 103222457Sattilio device_t sc_dev; 104222457Sattilio uint32_t sc_addr; 105222457Sattilio struct ad7417_sensor *sc_sensors; 106222457Sattilio int sc_nsensors; 107222457Sattilio}; 108222457Sattiliostatic device_method_t ad7417_methods[] = { 109222457Sattilio /* Device interface */ 110222457Sattilio DEVMETHOD(device_probe, ad7417_probe), 111222457Sattilio DEVMETHOD(device_attach, ad7417_attach), 112222457Sattilio { 0, 0 }, 113222457Sattilio}; 114222457Sattilio 115222457Sattiliostatic driver_t ad7417_driver = { 116222457Sattilio "ad7417", 117222457Sattilio ad7417_methods, 118222457Sattilio sizeof(struct ad7417_softc) 119222457Sattilio}; 120222457Sattilio 121222457Sattiliostatic devclass_t ad7417_devclass; 122222457Sattilio 123222457SattilioDRIVER_MODULE(ad7417, iicbus, ad7417_driver, ad7417_devclass, 0, 0); 124249132Smavstatic MALLOC_DEFINE(M_AD7417, "ad7417", "Supply-Monitor AD7417"); 125222457Sattilio 126222457Sattilio 127222457Sattiliostatic int 128222457Sattilioad7417_write(device_t dev, uint32_t addr, uint8_t reg, uint8_t *buff, int len) 129222457Sattilio{ 130222457Sattilio unsigned char buf[4]; 131222860Sandreast int try = 0; 132222860Sandreast 133222457Sattilio struct iic_msg msg[] = { 134222457Sattilio { addr, IIC_M_WR, 0, buf } 135222457Sattilio }; 136222457Sattilio 137222457Sattilio msg[0].len = len + 1; 138222457Sattilio buf[0] = reg; 139222457Sattilio memcpy(buf + 1, buff, len); 140222457Sattilio 141222860Sandreast for (;;) 142222860Sandreast { 143222860Sandreast if (iicbus_transfer(dev, msg, 1) == 0) 144222860Sandreast return (0); 145222860Sandreast 146222860Sandreast if (++try > 5) { 147222860Sandreast device_printf(dev, "iicbus write failed\n"); 148222860Sandreast return (-1); 149222860Sandreast } 150222860Sandreast pause("ad7417_write", hz); 151222457Sattilio } 152222457Sattilio} 153222457Sattilio 154222457Sattiliostatic int 155222457Sattilioad7417_read_1(device_t dev, uint32_t addr, uint8_t reg, uint8_t *data) 156222457Sattilio{ 157222457Sattilio uint8_t buf[4]; 158222860Sandreast int err, try = 0; 159222457Sattilio 160222457Sattilio struct iic_msg msg[2] = { 161222457Sattilio { addr, IIC_M_WR | IIC_M_NOSTOP, 1, ® }, 162222457Sattilio { addr, IIC_M_RD, 1, buf }, 163222457Sattilio }; 164222457Sattilio 165222860Sandreast for (;;) 166222860Sandreast { 167222860Sandreast err = iicbus_transfer(dev, msg, 2); 168222860Sandreast if (err != 0) 169222860Sandreast goto retry; 170222860Sandreast 171222860Sandreast *data = *((uint8_t*)buf); 172222860Sandreast return (0); 173222860Sandreast retry: 174222860Sandreast if (++try > 5) { 175222860Sandreast device_printf(dev, "iicbus read failed\n"); 176222860Sandreast return (-1); 177222860Sandreast } 178222860Sandreast pause("ad7417_read_1", hz); 179222457Sattilio } 180222457Sattilio} 181222457Sattilio 182222457Sattiliostatic int 183222457Sattilioad7417_read_2(device_t dev, uint32_t addr, uint8_t reg, uint16_t *data) 184222457Sattilio{ 185222457Sattilio uint8_t buf[4]; 186222860Sandreast int err, try = 0; 187222457Sattilio 188222457Sattilio struct iic_msg msg[2] = { 189222457Sattilio { addr, IIC_M_WR | IIC_M_NOSTOP, 1, ® }, 190222457Sattilio { addr, IIC_M_RD, 2, buf }, 191222457Sattilio }; 192222457Sattilio 193222860Sandreast for (;;) 194222860Sandreast { 195222860Sandreast err = iicbus_transfer(dev, msg, 2); 196222860Sandreast if (err != 0) 197222860Sandreast goto retry; 198222860Sandreast 199222860Sandreast *data = *((uint16_t*)buf); 200222860Sandreast return (0); 201222860Sandreast retry: 202222860Sandreast if (++try > 5) { 203222860Sandreast device_printf(dev, "iicbus read failed\n"); 204222860Sandreast return (-1); 205222860Sandreast } 206222860Sandreast pause("ad7417_read_2", hz); 207222457Sattilio } 208222860Sandreast} 209222457Sattilio 210222860Sandreaststatic int 211222860Sandreastad7417_write_read(device_t dev, uint32_t addr, struct write_data out, 212222860Sandreast struct read_data *in) 213222860Sandreast{ 214222860Sandreast uint8_t buf[4]; 215222860Sandreast int err, try = 0; 216222457Sattilio 217222860Sandreast /* Do a combined write/read. */ 218222860Sandreast struct iic_msg msg[3] = { 219222860Sandreast { addr, IIC_M_WR, 2, buf }, 220222860Sandreast { addr, IIC_M_WR | IIC_M_NOSTOP, 1, &in->reg }, 221222860Sandreast { addr, IIC_M_RD, 2, buf }, 222222860Sandreast }; 223222860Sandreast 224222860Sandreast /* Prepare the write msg. */ 225222860Sandreast buf[0] = out.reg; 226222860Sandreast buf[1] = out.val & 0xff; 227222860Sandreast 228222860Sandreast for (;;) 229222860Sandreast { 230222860Sandreast err = iicbus_transfer(dev, msg, 3); 231222860Sandreast if (err != 0) 232222860Sandreast goto retry; 233222860Sandreast 234222860Sandreast in->val = *((uint16_t*)buf); 235222860Sandreast return (0); 236222860Sandreast retry: 237222860Sandreast if (++try > 5) { 238222860Sandreast device_printf(dev, "iicbus write/read failed\n"); 239222860Sandreast return (-1); 240222860Sandreast } 241222860Sandreast pause("ad7417_write_read", hz); 242222860Sandreast } 243222457Sattilio} 244222457Sattilio 245222457Sattiliostatic int 246222457Sattilioad7417_init_adc(device_t dev, uint32_t addr) 247222457Sattilio{ 248222457Sattilio uint8_t buf; 249222860Sandreast int err; 250222457Sattilio 251222457Sattilio adc741x_config = 0; 252222457Sattilio /* Clear Config2 */ 253222457Sattilio buf = 0; 254222457Sattilio 255222860Sandreast err = ad7417_write(dev, addr, AD7417_CONFIG2, &buf, 1); 256222860Sandreast 257222457Sattilio /* Read & cache Config1 */ 258222457Sattilio buf = 0; 259222860Sandreast err = ad7417_write(dev, addr, AD7417_CONFIG, &buf, 1); 260222860Sandreast err = ad7417_read_1(dev, addr, AD7417_CONFIG, &buf); 261222457Sattilio adc741x_config = (uint8_t)buf; 262222457Sattilio 263222457Sattilio /* Disable shutdown mode */ 264222457Sattilio adc741x_config &= 0xfe; 265222457Sattilio buf = adc741x_config; 266222860Sandreast err = ad7417_write(dev, addr, AD7417_CONFIG, &buf, 1); 267222860Sandreast if (err < 0) 268222860Sandreast return (-1); 269222457Sattilio 270222457Sattilio return (0); 271222457Sattilio 272222457Sattilio} 273222457Sattiliostatic int 274222457Sattilioad7417_probe(device_t dev) 275222457Sattilio{ 276222457Sattilio const char *name, *compatible; 277222457Sattilio struct ad7417_softc *sc; 278222457Sattilio 279222457Sattilio name = ofw_bus_get_name(dev); 280222457Sattilio compatible = ofw_bus_get_compat(dev); 281222457Sattilio 282222457Sattilio if (!name) 283222457Sattilio return (ENXIO); 284222457Sattilio 285222457Sattilio if (strcmp(name, "supply-monitor") != 0 || 286222457Sattilio strcmp(compatible, "ad7417") != 0) 287222457Sattilio return (ENXIO); 288222457Sattilio 289222457Sattilio sc = device_get_softc(dev); 290222457Sattilio sc->sc_dev = dev; 291222457Sattilio sc->sc_addr = iicbus_get_addr(dev); 292222457Sattilio 293222457Sattilio device_set_desc(dev, "Supply-Monitor AD7417"); 294222457Sattilio 295222457Sattilio return (0); 296222457Sattilio} 297222457Sattilio 298222457Sattilio/* 299222457Sattilio * This function returns the number of sensors. If we call it the second time 300222457Sattilio * and we have allocated memory for sc->sc_sensors, we fill in the properties. 301222457Sattilio */ 302222457Sattiliostatic int 303222457Sattilioad7417_fill_sensor_prop(device_t dev) 304222457Sattilio{ 305222457Sattilio phandle_t child; 306222457Sattilio struct ad7417_softc *sc; 307222457Sattilio u_int id[10]; 308222457Sattilio char location[96]; 309222457Sattilio char type[32]; 310222457Sattilio int i = 0, j, len = 0, prop_len, prev_len = 0; 311222457Sattilio 312222457Sattilio sc = device_get_softc(dev); 313222457Sattilio 314222457Sattilio child = ofw_bus_get_node(dev); 315222457Sattilio 316222457Sattilio /* Fill the sensor location property. */ 317222457Sattilio prop_len = OF_getprop(child, "hwsensor-location", location, 318222457Sattilio sizeof(location)); 319222457Sattilio while (len < prop_len) { 320222457Sattilio if (sc->sc_sensors != NULL) 321222526Sattilio strcpy(sc->sc_sensors[i].therm.name, location + len); 322222457Sattilio prev_len = strlen(location + len) + 1; 323222457Sattilio len += prev_len; 324222457Sattilio i++; 325222457Sattilio } 326222457Sattilio if (sc->sc_sensors == NULL) 327222457Sattilio return (i); 328222457Sattilio 329222526Sattilio /* Fill the sensor type property. */ 330222457Sattilio len = 0; 331222457Sattilio i = 0; 332222457Sattilio prev_len = 0; 333222457Sattilio prop_len = OF_getprop(child, "hwsensor-type", type, sizeof(type)); 334222457Sattilio while (len < prop_len) { 335222457Sattilio if (strcmp(type + len, "temperature") == 0) 336222457Sattilio sc->sc_sensors[i].type = ADC7417_TEMP_SENSOR; 337222457Sattilio else 338222457Sattilio sc->sc_sensors[i].type = ADC7417_ADC_SENSOR; 339222457Sattilio prev_len = strlen(type + len) + 1; 340222457Sattilio len += prev_len; 341222457Sattilio i++; 342222457Sattilio } 343222457Sattilio 344222457Sattilio /* Fill the sensor id property. Taken from OF. */ 345222457Sattilio prop_len = OF_getprop(child, "hwsensor-id", id, sizeof(id)); 346222457Sattilio for (j = 0; j < i; j++) 347222457Sattilio sc->sc_sensors[j].id = id[j]; 348222457Sattilio 349222526Sattilio /* Fill the sensor zone property. Taken from OF. */ 350222526Sattilio prop_len = OF_getprop(child, "hwsensor-zone", id, sizeof(id)); 351222526Sattilio for (j = 0; j < i; j++) 352222526Sattilio sc->sc_sensors[j].therm.zone = id[j]; 353222526Sattilio 354222526Sattilio /* Finish setting up sensor properties */ 355222526Sattilio for (j = 0; j < i; j++) { 356222526Sattilio sc->sc_sensors[j].dev = dev; 357222526Sattilio 358222526Sattilio /* HACK: Apple wired a random diode to the ADC line */ 359222526Sattilio if (strstr(sc->sc_sensors[j].therm.name, "DIODE TEMP") 360222526Sattilio != NULL) { 361222526Sattilio sc->sc_sensors[j].type = ADC7417_TEMP_SENSOR; 362222526Sattilio sc->sc_sensors[j].therm.read = 363222526Sattilio (int (*)(struct pmac_therm *))(ad7417_diode_read); 364222526Sattilio } else { 365222526Sattilio sc->sc_sensors[j].therm.read = 366222526Sattilio (int (*)(struct pmac_therm *))(ad7417_sensor_read); 367222526Sattilio } 368222526Sattilio 369222526Sattilio if (sc->sc_sensors[j].type != ADC7417_TEMP_SENSOR) 370222526Sattilio continue; 371222526Sattilio 372222526Sattilio /* Make up some ranges */ 373222860Sandreast sc->sc_sensors[j].therm.target_temp = 500 + ZERO_C_TO_K; 374222860Sandreast sc->sc_sensors[j].therm.max_temp = 900 + ZERO_C_TO_K; 375222526Sattilio 376222526Sattilio pmac_thermal_sensor_register(&sc->sc_sensors[j].therm); 377222526Sattilio } 378222526Sattilio 379222457Sattilio return (i); 380222457Sattilio} 381222457Sattilio 382222457Sattiliostatic int 383222457Sattilioad7417_attach(device_t dev) 384222457Sattilio{ 385222457Sattilio struct ad7417_softc *sc; 386222457Sattilio struct sysctl_oid *oid, *sensroot_oid; 387222457Sattilio struct sysctl_ctx_list *ctx; 388222457Sattilio char sysctl_name[32]; 389222457Sattilio int i, j; 390222457Sattilio const char *unit; 391222457Sattilio const char *desc; 392222457Sattilio 393222457Sattilio sc = device_get_softc(dev); 394222457Sattilio 395222457Sattilio sc->sc_nsensors = 0; 396222457Sattilio 397222457Sattilio /* Count the actual number of sensors. */ 398222457Sattilio sc->sc_nsensors = ad7417_fill_sensor_prop(dev); 399222457Sattilio 400222457Sattilio device_printf(dev, "%d sensors detected.\n", sc->sc_nsensors); 401222457Sattilio 402222457Sattilio if (sc->sc_nsensors == 0) 403222457Sattilio device_printf(dev, "WARNING: No AD7417 sensors detected!\n"); 404222457Sattilio 405222457Sattilio sc->sc_sensors = malloc (sc->sc_nsensors * sizeof(struct ad7417_sensor), 406222457Sattilio M_AD7417, M_WAITOK | M_ZERO); 407222457Sattilio 408222457Sattilio ctx = device_get_sysctl_ctx(dev); 409222457Sattilio sensroot_oid = SYSCTL_ADD_NODE(ctx, 410222457Sattilio SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "sensor", 411222457Sattilio CTLFLAG_RD, 0, "AD7417 Sensor Information"); 412222457Sattilio 413222457Sattilio /* Now we can fill the properties into the allocated struct. */ 414222457Sattilio sc->sc_nsensors = ad7417_fill_sensor_prop(dev); 415222457Sattilio 416222457Sattilio /* Add sysctls for the sensors. */ 417222457Sattilio for (i = 0; i < sc->sc_nsensors; i++) { 418222526Sattilio for (j = 0; j < strlen(sc->sc_sensors[i].therm.name); j++) { 419222526Sattilio sysctl_name[j] = 420222526Sattilio tolower(sc->sc_sensors[i].therm.name[j]); 421222457Sattilio if (isspace(sysctl_name[j])) 422222457Sattilio sysctl_name[j] = '_'; 423222457Sattilio } 424222457Sattilio sysctl_name[j] = 0; 425222457Sattilio 426222457Sattilio oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(sensroot_oid), 427222457Sattilio OID_AUTO, 428222457Sattilio sysctl_name, CTLFLAG_RD, 0, 429222457Sattilio "Sensor Information"); 430222457Sattilio 431222457Sattilio if (sc->sc_sensors[i].type == ADC7417_TEMP_SENSOR) { 432222457Sattilio unit = "temp"; 433222457Sattilio desc = "Sensor temp in C"; 434222457Sattilio } else { 435222457Sattilio unit = "volt"; 436222457Sattilio desc = "Sensor Volt in V"; 437222457Sattilio } 438222457Sattilio /* I use i to pass the sensor id. */ 439222457Sattilio SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, 440222457Sattilio unit, CTLTYPE_INT | CTLFLAG_RD, dev, 441222457Sattilio i, ad7417_sensor_sysctl, 442222457Sattilio sc->sc_sensors[i].type == ADC7417_TEMP_SENSOR ? 443222457Sattilio "IK" : "I", desc); 444222457Sattilio } 445222457Sattilio /* Dump sensor location, ID & type. */ 446222457Sattilio if (bootverbose) { 447222457Sattilio device_printf(dev, "Sensors\n"); 448222457Sattilio for (i = 0; i < sc->sc_nsensors; i++) { 449222457Sattilio device_printf(dev, "Location: %s ID: %d type: %d\n", 450222526Sattilio sc->sc_sensors[i].therm.name, 451222457Sattilio sc->sc_sensors[i].id, 452222457Sattilio sc->sc_sensors[i].type); 453222457Sattilio } 454222457Sattilio } 455222457Sattilio 456222457Sattilio return (0); 457222457Sattilio} 458222457Sattilio 459222457Sattiliostatic int 460222457Sattilioad7417_get_temp(device_t dev, uint32_t addr, int *temp) 461222457Sattilio{ 462222457Sattilio uint16_t buf[2]; 463222457Sattilio uint16_t read; 464222860Sandreast int err; 465222457Sattilio 466222860Sandreast err = ad7417_read_2(dev, addr, AD7417_TEMP, buf); 467222860Sandreast 468222860Sandreast if (err < 0) 469222860Sandreast return (-1); 470222860Sandreast 471222457Sattilio read = *((int16_t*)buf); 472222457Sattilio 473222457Sattilio /* The ADC is 10 bit, the resolution is 0.25 C. 474222457Sattilio The temperature is in tenth kelvin. 475222457Sattilio */ 476222457Sattilio *temp = (((int16_t)(read & 0xffc0)) >> 6) * 25 / 10; 477222457Sattilio return (0); 478222457Sattilio} 479222457Sattilio 480222457Sattiliostatic int 481222457Sattilioad7417_get_adc(device_t dev, uint32_t addr, unsigned int *value, 482222457Sattilio uint8_t chan) 483222457Sattilio{ 484222860Sandreast uint8_t tmp; 485222860Sandreast int err; 486222860Sandreast struct write_data config; 487222860Sandreast struct read_data data; 488222457Sattilio 489222457Sattilio tmp = chan << 5; 490222860Sandreast config.reg = AD7417_CONFIG; 491222860Sandreast data.reg = AD7417_ADC; 492222860Sandreast data.val = 0; 493222457Sattilio 494222860Sandreast err = ad7417_read_1(dev, addr, AD7417_CONFIG, &config.val); 495222457Sattilio 496222860Sandreast config.val = (config.val & ~AD7417_CONFMASK) | (tmp & AD7417_CONFMASK); 497222457Sattilio 498222860Sandreast err = ad7417_write_read(dev, addr, config, &data); 499222860Sandreast if (err < 0) 500222860Sandreast return (-1); 501222457Sattilio 502222860Sandreast *value = ((uint32_t)data.val) >> 6; 503222457Sattilio 504222457Sattilio return (0); 505222457Sattilio} 506222457Sattilio 507222457Sattiliostatic int 508222526Sattilioad7417_diode_read(struct ad7417_sensor *sens) 509222457Sattilio{ 510222526Sattilio static int eeprom_read = 0; 511222526Sattilio static cell_t eeprom[2][40]; 512222526Sattilio phandle_t eeprom_node; 513222526Sattilio int rawval, diode_slope, diode_offset; 514222526Sattilio int temp; 515222526Sattilio 516222526Sattilio if (!eeprom_read) { 517222526Sattilio eeprom_node = OF_finddevice("/u3/i2c/cpuid@a0"); 518222526Sattilio OF_getprop(eeprom_node, "cpuid", eeprom[0], sizeof(eeprom[0])); 519222526Sattilio eeprom_node = OF_finddevice("/u3/i2c/cpuid@a2"); 520222526Sattilio OF_getprop(eeprom_node, "cpuid", eeprom[1], sizeof(eeprom[1])); 521222526Sattilio eeprom_read = 1; 522222526Sattilio } 523222526Sattilio 524222526Sattilio rawval = ad7417_adc_read(sens); 525222860Sandreast if (rawval < 0) 526222860Sandreast return (-1); 527222860Sandreast 528222526Sattilio if (strstr(sens->therm.name, "CPU B") != NULL) { 529222526Sattilio diode_slope = eeprom[1][0x11] >> 16; 530222526Sattilio diode_offset = (int16_t)(eeprom[1][0x11] & 0xffff) << 12; 531222526Sattilio } else { 532222526Sattilio diode_slope = eeprom[0][0x11] >> 16; 533222526Sattilio diode_offset = (int16_t)(eeprom[0][0x11] & 0xffff) << 12; 534222526Sattilio } 535222526Sattilio 536222526Sattilio temp = (rawval*diode_slope + diode_offset) >> 2; 537222526Sattilio temp = (10*(temp >> 16)) + ((10*(temp & 0xffff)) >> 16); 538222526Sattilio 539222860Sandreast return (temp + ZERO_C_TO_K); 540222526Sattilio} 541222526Sattilio 542222526Sattiliostatic int 543222526Sattilioad7417_adc_read(struct ad7417_sensor *sens) 544222526Sattilio{ 545222457Sattilio struct ad7417_softc *sc; 546222526Sattilio uint8_t chan; 547222526Sattilio int temp; 548222457Sattilio 549222526Sattilio sc = device_get_softc(sens->dev); 550222457Sattilio 551222526Sattilio switch (sens->id) { 552222526Sattilio case 11: 553222526Sattilio case 16: 554222526Sattilio chan = 1; 555222526Sattilio break; 556222526Sattilio case 12: 557222526Sattilio case 17: 558222526Sattilio chan = 2; 559222526Sattilio break; 560222526Sattilio case 13: 561222526Sattilio case 18: 562222526Sattilio chan = 3; 563222526Sattilio break; 564222526Sattilio case 14: 565222526Sattilio case 19: 566222526Sattilio chan = 4; 567222526Sattilio break; 568222526Sattilio default: 569222526Sattilio chan = 1; 570222526Sattilio } 571222526Sattilio 572222860Sandreast if (ad7417_get_adc(sc->sc_dev, sc->sc_addr, &temp, chan) < 0) 573222860Sandreast return (-1); 574222526Sattilio 575222526Sattilio return (temp); 576222526Sattilio} 577222526Sattilio 578222526Sattilio 579222526Sattiliostatic int 580222526Sattilioad7417_sensor_read(struct ad7417_sensor *sens) 581222526Sattilio{ 582222526Sattilio struct ad7417_softc *sc; 583222526Sattilio int temp; 584222526Sattilio 585222526Sattilio sc = device_get_softc(sens->dev); 586222526Sattilio 587222457Sattilio /* Init the ADC. */ 588222860Sandreast if (ad7417_init_adc(sc->sc_dev, sc->sc_addr) < 0) 589222860Sandreast return (-1); 590222457Sattilio 591222457Sattilio if (sens->type == ADC7417_TEMP_SENSOR) { 592222860Sandreast if (ad7417_get_temp(sc->sc_dev, sc->sc_addr, &temp) < 0) 593222860Sandreast return (-1); 594222860Sandreast temp += ZERO_C_TO_K; 595222457Sattilio } else { 596222526Sattilio temp = ad7417_adc_read(sens); 597222457Sattilio } 598222526Sattilio return (temp); 599222457Sattilio} 600222457Sattilio 601222457Sattiliostatic int 602222457Sattilioad7417_sensor_sysctl(SYSCTL_HANDLER_ARGS) 603222457Sattilio{ 604222457Sattilio device_t dev; 605222457Sattilio struct ad7417_softc *sc; 606222457Sattilio struct ad7417_sensor *sens; 607222457Sattilio int value = 0; 608222457Sattilio int error; 609222457Sattilio 610222457Sattilio dev = arg1; 611222457Sattilio sc = device_get_softc(dev); 612222457Sattilio sens = &sc->sc_sensors[arg2]; 613222457Sattilio 614222526Sattilio value = sens->therm.read(&sens->therm); 615222526Sattilio if (value < 0) 616222526Sattilio return (ENXIO); 617222457Sattilio 618222526Sattilio error = sysctl_handle_int(oidp, &value, 0, req); 619222457Sattilio 620222457Sattilio return (error); 621222457Sattilio} 622