10SN/A/*- 2157SN/A * SPDX-License-Identifier: BSD-2-Clause 30SN/A * 40SN/A * Copyright (c) 2010 Andreas Tobler 50SN/A * 60SN/A * Redistribution and use in source and binary forms, with or without 7157SN/A * modification, are permitted provided that the following conditions 80SN/A * are met: 9157SN/A * 1. Redistributions of source code must retain the above copyright 100SN/A * notice, this list of conditions and the following disclaimer. 110SN/A * 2. Redistributions in binary form must reproduce the above copyright 120SN/A * notice, this list of conditions and the following disclaimer in the 130SN/A * documentation and/or other materials provided with the distribution. 140SN/A * 150SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 160SN/A * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 170SN/A * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 180SN/A * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 190SN/A * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 200SN/A * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21157SN/A * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22157SN/A * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23157SN/A * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 240SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 250SN/A * SUCH DAMAGE. 260SN/A */ 270SN/A 280SN/A#include <sys/param.h> 290SN/A#include <sys/bus.h> 300SN/A#include <sys/systm.h> 310SN/A#include <sys/module.h> 320SN/A#include <sys/callout.h> 330SN/A#include <sys/conf.h> 340SN/A#include <sys/cpu.h> 350SN/A#include <sys/ctype.h> 360SN/A#include <sys/kernel.h> 370SN/A#include <sys/reboot.h> 380SN/A#include <sys/rman.h> 390SN/A#include <sys/sysctl.h> 400SN/A#include <sys/limits.h> 410SN/A 420SN/A#include <machine/bus.h> 430SN/A#include <machine/md_var.h> 440SN/A 450SN/A#include <dev/iicbus/iicbus.h> 460SN/A#include <dev/iicbus/iiconf.h> 470SN/A 480SN/A#include <dev/ofw/openfirm.h> 490SN/A#include <dev/ofw/ofw_bus.h> 500SN/A#include <powerpc/powermac/powermac_thermal.h> 510SN/A 520SN/A/* Drivebay sensor: LM75/DS1775. */ 530SN/A#define DS1775_TEMP 0x0 540SN/A 550SN/A/* Regular bus attachment functions */ 560SN/Astatic int ds1775_probe(device_t); 57672Savstepanstatic int ds1775_attach(device_t); 58672Savstepan 59672Savstepanstruct ds1775_softc { 600SN/A struct pmac_therm sc_sensor; 610SN/A device_t sc_dev; 620SN/A struct intr_config_hook enum_hook; 630SN/A uint32_t sc_addr; 640SN/A}; 650SN/A 660SN/A/* Utility functions */ 670SN/Astatic int ds1775_sensor_read(struct ds1775_softc *sc); 680SN/Astatic int ds1775_sensor_sysctl(SYSCTL_HANDLER_ARGS); 690SN/Astatic void ds1775_start(void *xdev); 700SN/Astatic int ds1775_read_2(device_t dev, uint32_t addr, uint8_t reg, 710SN/A uint16_t *data); 720SN/A 730SN/Astatic device_method_t ds1775_methods[] = { 740SN/A /* Device interface */ 750SN/A DEVMETHOD(device_probe, ds1775_probe), 760SN/A DEVMETHOD(device_attach, ds1775_attach), 770SN/A { 0, 0 }, 780SN/A}; 790SN/A 800SN/Astatic driver_t ds1775_driver = { 810SN/A "ds1775", 820SN/A ds1775_methods, 830SN/A sizeof(struct ds1775_softc) 840SN/A}; 850SN/A 860SN/ADRIVER_MODULE(ds1775, iicbus, ds1775_driver, 0, 0); 870SN/A 880SN/Astatic int 890SN/Ads1775_read_2(device_t dev, uint32_t addr, uint8_t reg, uint16_t *data) 900SN/A{ 910SN/A uint8_t buf[4]; 920SN/A int err, try = 0; 930SN/A 940SN/A struct iic_msg msg[2] = { 950SN/A { addr, IIC_M_WR | IIC_M_NOSTOP, 1, ® }, 960SN/A { addr, IIC_M_RD, 2, buf }, 970SN/A }; 980SN/A 990SN/A for (;;) 1000SN/A { 1010SN/A err = iicbus_transfer(dev, msg, nitems(msg)); 1020SN/A if (err != 0) 1030SN/A goto retry; 1040SN/A 1050SN/A *data = *((uint16_t*)buf); 1060SN/A return (0); 1070SN/A retry: 1080SN/A if (++try > 5) { 1090SN/A device_printf(dev, "iicbus read failed\n"); 1100SN/A return (-1); 1110SN/A } 1120SN/A pause("ds1775_read_2", hz); 1130SN/A } 1140SN/A} 1150SN/A 1160SN/Astatic int 1170SN/Ads1775_probe(device_t dev) 1180SN/A{ 1190SN/A const char *name, *compatible; 1200SN/A struct ds1775_softc *sc; 1210SN/A 1220SN/A name = ofw_bus_get_name(dev); 1230SN/A compatible = ofw_bus_get_compat(dev); 1240SN/A 1250SN/A if (!name) 1260SN/A return (ENXIO); 1270SN/A 1280SN/A if (strcmp(name, "temp-monitor") != 0 || 1290SN/A (strcmp(compatible, "ds1775") != 0 && 1300SN/A strcmp(compatible, "lm75") != 0)) 1310SN/A return (ENXIO); 1320SN/A 1330SN/A sc = device_get_softc(dev); 1340SN/A sc->sc_dev = dev; 1350SN/A sc->sc_addr = iicbus_get_addr(dev); 1360SN/A 1370SN/A device_set_desc(dev, "Temp-Monitor DS1775"); 1380SN/A 1390SN/A return (0); 1400SN/A} 1410SN/A 1420SN/Astatic int 1430SN/Ads1775_attach(device_t dev) 1440SN/A{ 1450SN/A struct ds1775_softc *sc; 1460SN/A 1470SN/A sc = device_get_softc(dev); 1480SN/A 1490SN/A sc->enum_hook.ich_func = ds1775_start; 1500SN/A sc->enum_hook.ich_arg = dev; 1510SN/A 1520SN/A /* We have to wait until interrupts are enabled. I2C read and write 1530SN/A * only works if the interrupts are available. 1540SN/A * The unin/i2c is controlled by the htpic on unin. But this is not 1550SN/A * the master. The openpic on mac-io is controlling the htpic. 1560SN/A * This one gets attached after the mac-io probing and then the 1570SN/A * interrupts will be available. 1580SN/A */ 1590SN/A 1600SN/A if (config_intrhook_establish(&sc->enum_hook) != 0) 1610SN/A return (ENOMEM); 1620SN/A 1630SN/A return (0); 1640SN/A} 1650SN/A 1660SN/Astatic void 1670SN/Ads1775_start(void *xdev) 1680SN/A{ 1690SN/A phandle_t child; 1700SN/A struct ds1775_softc *sc; 1710SN/A struct sysctl_oid *oid, *sensroot_oid; 1720SN/A struct sysctl_ctx_list *ctx; 1730SN/A ssize_t plen; 1740SN/A int i; 1750SN/A char sysctl_name[40], sysctl_desc[40]; 1760SN/A 1770SN/A device_t dev = (device_t)xdev; 1780SN/A 1790SN/A sc = device_get_softc(dev); 1800SN/A 1810SN/A child = ofw_bus_get_node(dev); 1820SN/A 1830SN/A ctx = device_get_sysctl_ctx(dev); 1840SN/A sensroot_oid = SYSCTL_ADD_NODE(ctx, 1850SN/A SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "sensor", 1860SN/A CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "DS1775 Sensor Information"); 1870SN/A 1880SN/A if (OF_getprop(child, "hwsensor-zone", &sc->sc_sensor.zone, 1890SN/A sizeof(int)) < 0) 1900SN/A sc->sc_sensor.zone = 0; 1910SN/A 1920SN/A plen = OF_getprop(child, "hwsensor-location", sc->sc_sensor.name, 1930SN/A sizeof(sc->sc_sensor.name)); 1940SN/A 1950SN/A if (plen == -1) { 1960SN/A strcpy(sysctl_name, "sensor"); 1970SN/A } else { 1980SN/A for (i = 0; i < strlen(sc->sc_sensor.name); i++) { 1990SN/A sysctl_name[i] = tolower(sc->sc_sensor.name[i]); 2000SN/A if (isspace(sysctl_name[i])) 2010SN/A sysctl_name[i] = '_'; 2020SN/A } 2030SN/A sysctl_name[i] = 0; 2040SN/A } 2050SN/A 2060SN/A /* Make up target temperatures. These are low, for the drive bay. */ 2070SN/A if (sc->sc_sensor.zone == 0) { 2080SN/A sc->sc_sensor.target_temp = 500 + ZERO_C_TO_K; 2090SN/A sc->sc_sensor.max_temp = 600 + ZERO_C_TO_K; 2100SN/A } 2110SN/A else { 2120SN/A sc->sc_sensor.target_temp = 300 + ZERO_C_TO_K; 2130SN/A sc->sc_sensor.max_temp = 600 + ZERO_C_TO_K; 2140SN/A } 2150SN/A 2160SN/A sc->sc_sensor.read = 2170SN/A (int (*)(struct pmac_therm *sc))(ds1775_sensor_read); 2180SN/A pmac_thermal_sensor_register(&sc->sc_sensor); 2190SN/A 2200SN/A sprintf(sysctl_desc,"%s %s", sc->sc_sensor.name, "(C)"); 2210SN/A oid = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(sensroot_oid), 2220SN/A OID_AUTO, sysctl_name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 2230SN/A "Sensor Information"); 2240SN/A SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "temp", 2250SN/A CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 2260SN/A 0, ds1775_sensor_sysctl, "IK", sysctl_desc); 2270SN/A 2280SN/A config_intrhook_disestablish(&sc->enum_hook); 2290SN/A} 2300SN/A 2310SN/Astatic int 2320SN/Ads1775_sensor_read(struct ds1775_softc *sc) 2330SN/A{ 2340SN/A uint16_t buf[2]; 2350SN/A uint16_t read; 2360SN/A int err; 2370SN/A 2380SN/A err = ds1775_read_2(sc->sc_dev, sc->sc_addr, DS1775_TEMP, buf); 2390SN/A if (err < 0) 2400SN/A return (-1); 2410SN/A 2420SN/A read = *((int16_t *)buf); 2430SN/A 2440SN/A /* The default mode of the ADC is 9 bit, the resolution is 0.5 C per 2450SN/A bit. The temperature is in tenth kelvin. 2460SN/A */ 2470SN/A return (((int16_t)(read) >> 7) * 5 + ZERO_C_TO_K); 2480SN/A} 2490SN/A 2500SN/Astatic int 2510SN/Ads1775_sensor_sysctl(SYSCTL_HANDLER_ARGS) 2520SN/A{ 2530SN/A device_t dev; 2540SN/A struct ds1775_softc *sc; 2550SN/A int error; 2560SN/A int temp; 2570SN/A 2580SN/A dev = arg1; 2590SN/A sc = device_get_softc(dev); 2600SN/A 2610SN/A temp = ds1775_sensor_read(sc); 2620SN/A if (temp < 0) 2630SN/A return (EIO); 2640SN/A 2650SN/A error = sysctl_handle_int(oidp, &temp, 0, req); 2660SN/A 2670SN/A return (error); 2680SN/A} 2690SN/A