1*7c569caaSEmmanuel Vadot /*- 2*7c569caaSEmmanuel Vadot * SPDX-License-Identifier: BSD-2-Clause 3*7c569caaSEmmanuel Vadot * 4*7c569caaSEmmanuel Vadot * Copyright (c) 2012 Andreas Tobler 5*7c569caaSEmmanuel Vadot * 6*7c569caaSEmmanuel Vadot * Redistribution and use in source and binary forms, with or without 7*7c569caaSEmmanuel Vadot * modification, are permitted provided that the following conditions 8*7c569caaSEmmanuel Vadot * are met: 9*7c569caaSEmmanuel Vadot * 1. Redistributions of source code must retain the above copyright 10*7c569caaSEmmanuel Vadot * notice, this list of conditions and the following disclaimer. 11*7c569caaSEmmanuel Vadot * 2. Redistributions in binary form must reproduce the above copyright 12*7c569caaSEmmanuel Vadot * notice, this list of conditions and the following disclaimer in the 13*7c569caaSEmmanuel Vadot * documentation and/or other materials provided with the distribution. 14*7c569caaSEmmanuel Vadot * 15*7c569caaSEmmanuel Vadot * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16*7c569caaSEmmanuel Vadot * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17*7c569caaSEmmanuel Vadot * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18*7c569caaSEmmanuel Vadot * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19*7c569caaSEmmanuel Vadot * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 20*7c569caaSEmmanuel Vadot * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21*7c569caaSEmmanuel Vadot * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22*7c569caaSEmmanuel Vadot * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23*7c569caaSEmmanuel Vadot * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24*7c569caaSEmmanuel Vadot * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25*7c569caaSEmmanuel Vadot * SUCH DAMAGE. 26*7c569caaSEmmanuel Vadot */ 27*7c569caaSEmmanuel Vadot 28*7c569caaSEmmanuel Vadot #include <sys/cdefs.h> 29*7c569caaSEmmanuel Vadot #include <sys/param.h> 30*7c569caaSEmmanuel Vadot #include <sys/bus.h> 31*7c569caaSEmmanuel Vadot #include <sys/systm.h> 32*7c569caaSEmmanuel Vadot #include <sys/module.h> 33*7c569caaSEmmanuel Vadot #include <sys/callout.h> 34*7c569caaSEmmanuel Vadot #include <sys/conf.h> 35*7c569caaSEmmanuel Vadot #include <sys/cpu.h> 36*7c569caaSEmmanuel Vadot #include <sys/ctype.h> 37*7c569caaSEmmanuel Vadot #include <sys/kernel.h> 38*7c569caaSEmmanuel Vadot #include <sys/reboot.h> 39*7c569caaSEmmanuel Vadot #include <sys/rman.h> 40*7c569caaSEmmanuel Vadot #include <sys/sysctl.h> 41*7c569caaSEmmanuel Vadot #include <sys/limits.h> 42*7c569caaSEmmanuel Vadot 43*7c569caaSEmmanuel Vadot #include <machine/bus.h> 44*7c569caaSEmmanuel Vadot #include <machine/md_var.h> 45*7c569caaSEmmanuel Vadot 46*7c569caaSEmmanuel Vadot #include <dev/iicbus/iicbus.h> 47*7c569caaSEmmanuel Vadot #include <dev/iicbus/iiconf.h> 48*7c569caaSEmmanuel Vadot 49*7c569caaSEmmanuel Vadot #include <dev/ofw/openfirm.h> 50*7c569caaSEmmanuel Vadot #include <dev/ofw/ofw_bus.h> 51*7c569caaSEmmanuel Vadot #include <powerpc/powermac/powermac_thermal.h> 52*7c569caaSEmmanuel Vadot 53*7c569caaSEmmanuel Vadot /* Sensor: Maxim DS1631 */ 54*7c569caaSEmmanuel Vadot 55*7c569caaSEmmanuel Vadot #define DS1631_STOP 0x22 56*7c569caaSEmmanuel Vadot #define DS1631_START 0x51 57*7c569caaSEmmanuel Vadot #define DS1631_RESET 0x54 58*7c569caaSEmmanuel Vadot #define DS1631_TEMP 0xAA 59*7c569caaSEmmanuel Vadot #define DS1631_CONTROL 0xAC 60*7c569caaSEmmanuel Vadot #define DS1631_CONTROL_1SHOT 0x01 61*7c569caaSEmmanuel Vadot #define DS1631_CONTROL_9BIT 0x00 62*7c569caaSEmmanuel Vadot #define DS1631_CONTROL_10BIT 0x04 63*7c569caaSEmmanuel Vadot #define DS1631_CONTROL_11BIT 0x08 64*7c569caaSEmmanuel Vadot #define DS1631_CONTROL_12BIT 0x0C 65*7c569caaSEmmanuel Vadot 66*7c569caaSEmmanuel Vadot 67*7c569caaSEmmanuel Vadot 68*7c569caaSEmmanuel Vadot /* Regular bus attachment functions */ 69*7c569caaSEmmanuel Vadot static int ds1631_probe(device_t); 70*7c569caaSEmmanuel Vadot static int ds1631_attach(device_t); 71*7c569caaSEmmanuel Vadot 72*7c569caaSEmmanuel Vadot struct ds1631_softc { 73*7c569caaSEmmanuel Vadot struct pmac_therm sc_sensor; 74*7c569caaSEmmanuel Vadot device_t sc_dev; 75*7c569caaSEmmanuel Vadot struct intr_config_hook enum_hook; 76*7c569caaSEmmanuel Vadot uint32_t sc_addr; 77*7c569caaSEmmanuel Vadot uint32_t init_done; 78*7c569caaSEmmanuel Vadot }; 79*7c569caaSEmmanuel Vadot 80*7c569caaSEmmanuel Vadot struct write_data { 81*7c569caaSEmmanuel Vadot uint8_t reg; 82*7c569caaSEmmanuel Vadot uint8_t val; 83*7c569caaSEmmanuel Vadot }; 84*7c569caaSEmmanuel Vadot 85*7c569caaSEmmanuel Vadot struct read_data { 86*7c569caaSEmmanuel Vadot uint8_t reg; 87*7c569caaSEmmanuel Vadot uint16_t val; 88*7c569caaSEmmanuel Vadot }; 89*7c569caaSEmmanuel Vadot 90*7c569caaSEmmanuel Vadot /* Utility functions */ 91*7c569caaSEmmanuel Vadot static int ds1631_sensor_read(struct ds1631_softc *sc); 92*7c569caaSEmmanuel Vadot static int ds1631_sensor_sysctl(SYSCTL_HANDLER_ARGS); 93*7c569caaSEmmanuel Vadot static void ds1631_start(void *xdev); 94*7c569caaSEmmanuel Vadot static int ds1631_read_1(device_t dev, uint32_t addr, uint8_t reg, 95*7c569caaSEmmanuel Vadot uint8_t *data); 96*7c569caaSEmmanuel Vadot static int ds1631_read_2(device_t dev, uint32_t addr, uint8_t reg, 97*7c569caaSEmmanuel Vadot uint16_t *data); 98*7c569caaSEmmanuel Vadot static int ds1631_write(device_t dev, uint32_t addr, uint8_t reg, 99*7c569caaSEmmanuel Vadot uint8_t *buff, int len); 100*7c569caaSEmmanuel Vadot 101*7c569caaSEmmanuel Vadot static device_method_t ds1631_methods[] = { 102*7c569caaSEmmanuel Vadot /* Device interface */ 103*7c569caaSEmmanuel Vadot DEVMETHOD(device_probe, ds1631_probe), 104*7c569caaSEmmanuel Vadot DEVMETHOD(device_attach, ds1631_attach), 105*7c569caaSEmmanuel Vadot { 0, 0 }, 106*7c569caaSEmmanuel Vadot }; 107*7c569caaSEmmanuel Vadot 108*7c569caaSEmmanuel Vadot static driver_t ds1631_driver = { 109*7c569caaSEmmanuel Vadot "ds1631", 110*7c569caaSEmmanuel Vadot ds1631_methods, 111*7c569caaSEmmanuel Vadot sizeof(struct ds1631_softc) 112*7c569caaSEmmanuel Vadot }; 113*7c569caaSEmmanuel Vadot 114*7c569caaSEmmanuel Vadot DRIVER_MODULE(ds1631, iicbus, ds1631_driver, 0, 0); 115*7c569caaSEmmanuel Vadot 116*7c569caaSEmmanuel Vadot static int 117*7c569caaSEmmanuel Vadot ds1631_write(device_t dev, uint32_t addr, uint8_t reg, uint8_t *buff, int len) 118*7c569caaSEmmanuel Vadot { 119*7c569caaSEmmanuel Vadot uint8_t buf[4]; 120*7c569caaSEmmanuel Vadot int try = 0; 121*7c569caaSEmmanuel Vadot 122*7c569caaSEmmanuel Vadot struct iic_msg msg[] = { 123*7c569caaSEmmanuel Vadot { addr, IIC_M_WR, 0, buf } 124*7c569caaSEmmanuel Vadot }; 125*7c569caaSEmmanuel Vadot 126*7c569caaSEmmanuel Vadot /* Prepare the write msg. */ 127*7c569caaSEmmanuel Vadot msg[0].len = len + 1; 128*7c569caaSEmmanuel Vadot buf[0] = reg; 129*7c569caaSEmmanuel Vadot memcpy(buf + 1, buff, len); 130*7c569caaSEmmanuel Vadot 131*7c569caaSEmmanuel Vadot for (;;) 132*7c569caaSEmmanuel Vadot { 133*7c569caaSEmmanuel Vadot if (iicbus_transfer(dev, msg, nitems(msg)) == 0) 134*7c569caaSEmmanuel Vadot return (0); 135*7c569caaSEmmanuel Vadot if (++try > 5) { 136*7c569caaSEmmanuel Vadot device_printf(dev, "iicbus write failed\n"); 137*7c569caaSEmmanuel Vadot return (-1); 138*7c569caaSEmmanuel Vadot } 139*7c569caaSEmmanuel Vadot pause("ds1631_write", hz); 140*7c569caaSEmmanuel Vadot } 141*7c569caaSEmmanuel Vadot } 142*7c569caaSEmmanuel Vadot 143*7c569caaSEmmanuel Vadot static int 144*7c569caaSEmmanuel Vadot ds1631_read_1(device_t dev, uint32_t addr, uint8_t reg, uint8_t *data) 145*7c569caaSEmmanuel Vadot { 146*7c569caaSEmmanuel Vadot uint8_t buf[4]; 147*7c569caaSEmmanuel Vadot int err, try = 0; 148*7c569caaSEmmanuel Vadot 149*7c569caaSEmmanuel Vadot struct iic_msg msg[2] = { 150*7c569caaSEmmanuel Vadot { addr, IIC_M_WR, 1, ® }, 151*7c569caaSEmmanuel Vadot { addr, IIC_M_RD, 1, buf }, 152*7c569caaSEmmanuel Vadot }; 153*7c569caaSEmmanuel Vadot 154*7c569caaSEmmanuel Vadot for (;;) 155*7c569caaSEmmanuel Vadot { 156*7c569caaSEmmanuel Vadot err = iicbus_transfer(dev, msg, nitems(msg)); 157*7c569caaSEmmanuel Vadot if (err != 0) 158*7c569caaSEmmanuel Vadot goto retry; 159*7c569caaSEmmanuel Vadot 160*7c569caaSEmmanuel Vadot *data = *((uint8_t*)buf); 161*7c569caaSEmmanuel Vadot return (0); 162*7c569caaSEmmanuel Vadot retry: 163*7c569caaSEmmanuel Vadot if (++try > 5) { 164*7c569caaSEmmanuel Vadot device_printf(dev, "iicbus read failed\n"); 165*7c569caaSEmmanuel Vadot return (-1); 166*7c569caaSEmmanuel Vadot } 167*7c569caaSEmmanuel Vadot pause("ds1631_read_1", hz); 168*7c569caaSEmmanuel Vadot } 169*7c569caaSEmmanuel Vadot } 170*7c569caaSEmmanuel Vadot 171*7c569caaSEmmanuel Vadot static int 172*7c569caaSEmmanuel Vadot ds1631_read_2(device_t dev, uint32_t addr, uint8_t reg, uint16_t *data) 173*7c569caaSEmmanuel Vadot { 174*7c569caaSEmmanuel Vadot uint8_t buf[4]; 175*7c569caaSEmmanuel Vadot int err, try = 0; 176*7c569caaSEmmanuel Vadot 177*7c569caaSEmmanuel Vadot struct iic_msg msg[2] = { 178*7c569caaSEmmanuel Vadot { addr, IIC_M_WR, 1, ® }, 179*7c569caaSEmmanuel Vadot { addr, IIC_M_RD, 2, buf }, 180*7c569caaSEmmanuel Vadot }; 181*7c569caaSEmmanuel Vadot 182*7c569caaSEmmanuel Vadot for (;;) 183*7c569caaSEmmanuel Vadot { 184*7c569caaSEmmanuel Vadot err = iicbus_transfer(dev, msg, nitems(msg)); 185*7c569caaSEmmanuel Vadot if (err != 0) 186*7c569caaSEmmanuel Vadot goto retry; 187*7c569caaSEmmanuel Vadot 188*7c569caaSEmmanuel Vadot *data = *((uint16_t*)buf); 189*7c569caaSEmmanuel Vadot return (0); 190*7c569caaSEmmanuel Vadot retry: 191*7c569caaSEmmanuel Vadot if (++try > 5) { 192*7c569caaSEmmanuel Vadot device_printf(dev, "iicbus read failed\n"); 193*7c569caaSEmmanuel Vadot return (-1); 194*7c569caaSEmmanuel Vadot } 195*7c569caaSEmmanuel Vadot pause("ds1631_read_2", hz); 196*7c569caaSEmmanuel Vadot } 197*7c569caaSEmmanuel Vadot } 198*7c569caaSEmmanuel Vadot 199*7c569caaSEmmanuel Vadot static int 200*7c569caaSEmmanuel Vadot ds1631_probe(device_t dev) 201*7c569caaSEmmanuel Vadot { 202*7c569caaSEmmanuel Vadot const char *name, *compatible; 203*7c569caaSEmmanuel Vadot struct ds1631_softc *sc; 204*7c569caaSEmmanuel Vadot 205*7c569caaSEmmanuel Vadot name = ofw_bus_get_name(dev); 206*7c569caaSEmmanuel Vadot compatible = ofw_bus_get_compat(dev); 207*7c569caaSEmmanuel Vadot 208*7c569caaSEmmanuel Vadot if (!name) 209*7c569caaSEmmanuel Vadot return (ENXIO); 210*7c569caaSEmmanuel Vadot 211*7c569caaSEmmanuel Vadot if (strcmp(name, "temp-monitor") != 0 || 212*7c569caaSEmmanuel Vadot strcmp(compatible, "ds1631") != 0 ) 213*7c569caaSEmmanuel Vadot return (ENXIO); 214*7c569caaSEmmanuel Vadot 215*7c569caaSEmmanuel Vadot sc = device_get_softc(dev); 216*7c569caaSEmmanuel Vadot sc->sc_dev = dev; 217*7c569caaSEmmanuel Vadot sc->sc_addr = iicbus_get_addr(dev); 218*7c569caaSEmmanuel Vadot 219*7c569caaSEmmanuel Vadot device_set_desc(dev, "Temp-Monitor DS1631"); 220*7c569caaSEmmanuel Vadot 221*7c569caaSEmmanuel Vadot return (0); 222*7c569caaSEmmanuel Vadot } 223*7c569caaSEmmanuel Vadot 224*7c569caaSEmmanuel Vadot static int 225*7c569caaSEmmanuel Vadot ds1631_attach(device_t dev) 226*7c569caaSEmmanuel Vadot { 227*7c569caaSEmmanuel Vadot struct ds1631_softc *sc; 228*7c569caaSEmmanuel Vadot 229*7c569caaSEmmanuel Vadot sc = device_get_softc(dev); 230*7c569caaSEmmanuel Vadot 231*7c569caaSEmmanuel Vadot sc->enum_hook.ich_func = ds1631_start; 232*7c569caaSEmmanuel Vadot sc->enum_hook.ich_arg = dev; 233*7c569caaSEmmanuel Vadot 234*7c569caaSEmmanuel Vadot /* 235*7c569caaSEmmanuel Vadot * We have to wait until interrupts are enabled. I2C read and write 236*7c569caaSEmmanuel Vadot * only works if the interrupts are available. 237*7c569caaSEmmanuel Vadot * The unin/i2c is controlled by the htpic on unin. But this is not 238*7c569caaSEmmanuel Vadot * the master. The openpic on mac-io is controlling the htpic. 239*7c569caaSEmmanuel Vadot * This one gets attached after the mac-io probing and then the 240*7c569caaSEmmanuel Vadot * interrupts will be available. 241*7c569caaSEmmanuel Vadot */ 242*7c569caaSEmmanuel Vadot 243*7c569caaSEmmanuel Vadot if (config_intrhook_establish(&sc->enum_hook) != 0) 244*7c569caaSEmmanuel Vadot return (ENOMEM); 245*7c569caaSEmmanuel Vadot 246*7c569caaSEmmanuel Vadot return (0); 247*7c569caaSEmmanuel Vadot } 248*7c569caaSEmmanuel Vadot static int 249*7c569caaSEmmanuel Vadot ds1631_init(device_t dev, uint32_t addr) 250*7c569caaSEmmanuel Vadot { 251*7c569caaSEmmanuel Vadot uint8_t conf; 252*7c569caaSEmmanuel Vadot int err; 253*7c569caaSEmmanuel Vadot struct ds1631_softc *sc; 254*7c569caaSEmmanuel Vadot 255*7c569caaSEmmanuel Vadot sc = device_get_softc(dev); 256*7c569caaSEmmanuel Vadot 257*7c569caaSEmmanuel Vadot err = ds1631_read_1(dev, addr, DS1631_CONTROL, &conf); 258*7c569caaSEmmanuel Vadot if (err < 0) { 259*7c569caaSEmmanuel Vadot device_printf(dev, "ds1631 read config failed: %x\n", err); 260*7c569caaSEmmanuel Vadot return (-1); 261*7c569caaSEmmanuel Vadot } 262*7c569caaSEmmanuel Vadot 263*7c569caaSEmmanuel Vadot /* Stop the conversion if not in 1SHOT mode. */ 264*7c569caaSEmmanuel Vadot if (conf & ~DS1631_CONTROL_1SHOT) 265*7c569caaSEmmanuel Vadot err = ds1631_write(dev, addr, DS1631_STOP, &conf, 0); 266*7c569caaSEmmanuel Vadot 267*7c569caaSEmmanuel Vadot /* 268*7c569caaSEmmanuel Vadot * Setup the resolution, 10-bit is enough. Each bit increase in 269*7c569caaSEmmanuel Vadot * resolution doubles the conversion time. 270*7c569caaSEmmanuel Vadot */ 271*7c569caaSEmmanuel Vadot conf = DS1631_CONTROL_10BIT; 272*7c569caaSEmmanuel Vadot 273*7c569caaSEmmanuel Vadot err = ds1631_write(dev, addr, DS1631_CONTROL, &conf, sizeof(conf)); 274*7c569caaSEmmanuel Vadot if (err < 0) { 275*7c569caaSEmmanuel Vadot device_printf(dev, "ds1631 write config failed: %x\n", err); 276*7c569caaSEmmanuel Vadot return (-1); 277*7c569caaSEmmanuel Vadot } 278*7c569caaSEmmanuel Vadot 279*7c569caaSEmmanuel Vadot /* And now start....*/ 280*7c569caaSEmmanuel Vadot err = ds1631_write(dev, addr, DS1631_START, &conf, 0); 281*7c569caaSEmmanuel Vadot 282*7c569caaSEmmanuel Vadot if (err < 0) { 283*7c569caaSEmmanuel Vadot device_printf(dev, "ds1631 write start failed: %x\n", err); 284*7c569caaSEmmanuel Vadot return (-1); 285*7c569caaSEmmanuel Vadot } 286*7c569caaSEmmanuel Vadot 287*7c569caaSEmmanuel Vadot sc->init_done = 1; 288*7c569caaSEmmanuel Vadot 289*7c569caaSEmmanuel Vadot return (0); 290*7c569caaSEmmanuel Vadot 291*7c569caaSEmmanuel Vadot } 292*7c569caaSEmmanuel Vadot static void 293*7c569caaSEmmanuel Vadot ds1631_start(void *xdev) 294*7c569caaSEmmanuel Vadot { 295*7c569caaSEmmanuel Vadot phandle_t child, node; 296*7c569caaSEmmanuel Vadot struct ds1631_softc *sc; 297*7c569caaSEmmanuel Vadot struct sysctl_oid *oid, *sensroot_oid; 298*7c569caaSEmmanuel Vadot struct sysctl_ctx_list *ctx; 299*7c569caaSEmmanuel Vadot ssize_t plen; 300*7c569caaSEmmanuel Vadot int i; 301*7c569caaSEmmanuel Vadot char sysctl_desc[40], sysctl_name[40]; 302*7c569caaSEmmanuel Vadot 303*7c569caaSEmmanuel Vadot device_t dev = (device_t)xdev; 304*7c569caaSEmmanuel Vadot 305*7c569caaSEmmanuel Vadot sc = device_get_softc(dev); 306*7c569caaSEmmanuel Vadot 307*7c569caaSEmmanuel Vadot child = ofw_bus_get_node(dev); 308*7c569caaSEmmanuel Vadot 309*7c569caaSEmmanuel Vadot ctx = device_get_sysctl_ctx(dev); 310*7c569caaSEmmanuel Vadot sensroot_oid = SYSCTL_ADD_NODE(ctx, 311*7c569caaSEmmanuel Vadot SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "sensor", 312*7c569caaSEmmanuel Vadot CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "DS1631 Sensor Information"); 313*7c569caaSEmmanuel Vadot 314*7c569caaSEmmanuel Vadot if (OF_getprop(child, "hwsensor-zone", &sc->sc_sensor.zone, 315*7c569caaSEmmanuel Vadot sizeof(int)) < 0) 316*7c569caaSEmmanuel Vadot sc->sc_sensor.zone = 0; 317*7c569caaSEmmanuel Vadot 318*7c569caaSEmmanuel Vadot plen = OF_getprop(child, "hwsensor-location", sc->sc_sensor.name, 319*7c569caaSEmmanuel Vadot sizeof(sc->sc_sensor.name)); 320*7c569caaSEmmanuel Vadot if (plen == -1) { 321*7c569caaSEmmanuel Vadot /* 322*7c569caaSEmmanuel Vadot * Ok, no hwsensor-location property, so let's look for a 323*7c569caaSEmmanuel Vadot * location property on a sub node. 324*7c569caaSEmmanuel Vadot */ 325*7c569caaSEmmanuel Vadot for (node = OF_child(child); node; node = OF_peer(node)) 326*7c569caaSEmmanuel Vadot plen = OF_getprop(node, "location", sc->sc_sensor.name, 327*7c569caaSEmmanuel Vadot sizeof(sc->sc_sensor.name)); 328*7c569caaSEmmanuel Vadot } 329*7c569caaSEmmanuel Vadot 330*7c569caaSEmmanuel Vadot if (plen == -1) { 331*7c569caaSEmmanuel Vadot strcpy(sysctl_name, "sensor"); 332*7c569caaSEmmanuel Vadot } else { 333*7c569caaSEmmanuel Vadot for (i = 0; i < strlen(sc->sc_sensor.name); i++) { 334*7c569caaSEmmanuel Vadot sysctl_name[i] = tolower(sc->sc_sensor.name[i]); 335*7c569caaSEmmanuel Vadot if (isspace(sysctl_name[i])) 336*7c569caaSEmmanuel Vadot sysctl_name[i] = '_'; 337*7c569caaSEmmanuel Vadot } 338*7c569caaSEmmanuel Vadot sysctl_name[i] = 0; 339*7c569caaSEmmanuel Vadot } 340*7c569caaSEmmanuel Vadot 341*7c569caaSEmmanuel Vadot /* Make up target temperatures. These are low, for the drive bay. */ 342*7c569caaSEmmanuel Vadot if (sc->sc_sensor.zone == 0) { 343*7c569caaSEmmanuel Vadot sc->sc_sensor.target_temp = 400 + ZERO_C_TO_K; 344*7c569caaSEmmanuel Vadot sc->sc_sensor.max_temp = 500 + ZERO_C_TO_K; 345*7c569caaSEmmanuel Vadot } else { 346*7c569caaSEmmanuel Vadot sc->sc_sensor.target_temp = 300 + ZERO_C_TO_K; 347*7c569caaSEmmanuel Vadot sc->sc_sensor.max_temp = 500 + ZERO_C_TO_K; 348*7c569caaSEmmanuel Vadot } 349*7c569caaSEmmanuel Vadot 350*7c569caaSEmmanuel Vadot sc->sc_sensor.read = 351*7c569caaSEmmanuel Vadot (int (*)(struct pmac_therm *sc))(ds1631_sensor_read); 352*7c569caaSEmmanuel Vadot pmac_thermal_sensor_register(&sc->sc_sensor); 353*7c569caaSEmmanuel Vadot 354*7c569caaSEmmanuel Vadot sprintf(sysctl_desc,"%s %s", sc->sc_sensor.name, "(C)"); 355*7c569caaSEmmanuel Vadot oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(sensroot_oid), 356*7c569caaSEmmanuel Vadot OID_AUTO, sysctl_name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 357*7c569caaSEmmanuel Vadot "Sensor Information"); 358*7c569caaSEmmanuel Vadot SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "temp", 359*7c569caaSEmmanuel Vadot CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 360*7c569caaSEmmanuel Vadot 0, ds1631_sensor_sysctl, "IK", sysctl_desc); 361*7c569caaSEmmanuel Vadot 362*7c569caaSEmmanuel Vadot config_intrhook_disestablish(&sc->enum_hook); 363*7c569caaSEmmanuel Vadot } 364*7c569caaSEmmanuel Vadot 365*7c569caaSEmmanuel Vadot static int 366*7c569caaSEmmanuel Vadot ds1631_sensor_read(struct ds1631_softc *sc) 367*7c569caaSEmmanuel Vadot { 368*7c569caaSEmmanuel Vadot uint16_t buf[2]; 369*7c569caaSEmmanuel Vadot uint16_t read; 370*7c569caaSEmmanuel Vadot int err; 371*7c569caaSEmmanuel Vadot 372*7c569caaSEmmanuel Vadot if (!sc->init_done) 373*7c569caaSEmmanuel Vadot ds1631_init(sc->sc_dev, sc->sc_addr); 374*7c569caaSEmmanuel Vadot 375*7c569caaSEmmanuel Vadot err = ds1631_read_2(sc->sc_dev, sc->sc_addr, DS1631_TEMP, buf); 376*7c569caaSEmmanuel Vadot if (err < 0) { 377*7c569caaSEmmanuel Vadot device_printf(sc->sc_dev, "ds1631 read TEMP failed: %x\n", err); 378*7c569caaSEmmanuel Vadot return (-1); 379*7c569caaSEmmanuel Vadot } 380*7c569caaSEmmanuel Vadot 381*7c569caaSEmmanuel Vadot read = *((int16_t *)buf); 382*7c569caaSEmmanuel Vadot 383*7c569caaSEmmanuel Vadot /* 384*7c569caaSEmmanuel Vadot * The default mode of the ADC is 12-bit, the resolution is 0.0625 C 385*7c569caaSEmmanuel Vadot * per bit. The temperature is in tenth kelvin. 386*7c569caaSEmmanuel Vadot * We use 10-bit resolution which seems enough, resolution is 0.25 C. 387*7c569caaSEmmanuel Vadot */ 388*7c569caaSEmmanuel Vadot 389*7c569caaSEmmanuel Vadot return (((int16_t)(read) >> 6) * 25 / 10 + ZERO_C_TO_K); 390*7c569caaSEmmanuel Vadot } 391*7c569caaSEmmanuel Vadot 392*7c569caaSEmmanuel Vadot static int 393*7c569caaSEmmanuel Vadot ds1631_sensor_sysctl(SYSCTL_HANDLER_ARGS) 394*7c569caaSEmmanuel Vadot { 395*7c569caaSEmmanuel Vadot device_t dev; 396*7c569caaSEmmanuel Vadot struct ds1631_softc *sc; 397*7c569caaSEmmanuel Vadot int error; 398*7c569caaSEmmanuel Vadot int temp; 399*7c569caaSEmmanuel Vadot 400*7c569caaSEmmanuel Vadot dev = arg1; 401*7c569caaSEmmanuel Vadot sc = device_get_softc(dev); 402*7c569caaSEmmanuel Vadot 403*7c569caaSEmmanuel Vadot temp = ds1631_sensor_read(sc); 404*7c569caaSEmmanuel Vadot if (temp < 0) 405*7c569caaSEmmanuel Vadot return (EIO); 406*7c569caaSEmmanuel Vadot 407*7c569caaSEmmanuel Vadot error = sysctl_handle_int(oidp, &temp, 0, req); 408*7c569caaSEmmanuel Vadot 409*7c569caaSEmmanuel Vadot return (error); 410*7c569caaSEmmanuel Vadot } 411