18ff9ad32Smacallan /*-
28ff9ad32Smacallan * Copyright (c) 2013 Phileas Fogg
38ff9ad32Smacallan * All rights reserved.
48ff9ad32Smacallan *
58ff9ad32Smacallan * Redistribution and use in source and binary forms, with or without
68ff9ad32Smacallan * modification, are permitted provided that the following conditions
78ff9ad32Smacallan * are met:
88ff9ad32Smacallan * 1. Redistributions of source code must retain the above copyright
98ff9ad32Smacallan * notice, this list of conditions and the following disclaimer.
108ff9ad32Smacallan * 2. Redistributions in binary form must reproduce the above copyright
118ff9ad32Smacallan * notice, this list of conditions and the following disclaimer in the
128ff9ad32Smacallan * documentation and/or other materials provided with the distribution.
138ff9ad32Smacallan *
148ff9ad32Smacallan * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
158ff9ad32Smacallan * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
168ff9ad32Smacallan * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
178ff9ad32Smacallan * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
188ff9ad32Smacallan * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
198ff9ad32Smacallan * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
208ff9ad32Smacallan * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
218ff9ad32Smacallan * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
228ff9ad32Smacallan * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
238ff9ad32Smacallan * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
248ff9ad32Smacallan * POSSIBILITY OF SUCH DAMAGE.
258ff9ad32Smacallan */
268ff9ad32Smacallan
278ff9ad32Smacallan #include <sys/param.h>
288ff9ad32Smacallan #include <sys/systm.h>
298ff9ad32Smacallan #include <sys/kernel.h>
308ff9ad32Smacallan #include <sys/device.h>
318ff9ad32Smacallan #include <sys/proc.h>
328ff9ad32Smacallan #include <sys/mutex.h>
338ff9ad32Smacallan #include <sys/time.h>
348ff9ad32Smacallan #include <sys/sysctl.h>
358ff9ad32Smacallan
368ff9ad32Smacallan #include <machine/autoconf.h>
378ff9ad32Smacallan
388ff9ad32Smacallan #include <dev/ofw/openfirm.h>
398ff9ad32Smacallan #include <dev/i2c/i2cvar.h>
408ff9ad32Smacallan #include <dev/sysmon/sysmonvar.h>
418ff9ad32Smacallan #include <dev/sysmon/sysmon_taskq.h>
428ff9ad32Smacallan
438ff9ad32Smacallan #include <macppc/dev/smuiicvar.h>
448ff9ad32Smacallan
458ff9ad32Smacallan #include "opt_smusat.h"
468ff9ad32Smacallan
473e3d2eccSmacallan extern int smu_get_datablock(int, uint8_t *, size_t);
483e3d2eccSmacallan
498ff9ad32Smacallan enum {
508ff9ad32Smacallan SMUSAT_SENSOR_TEMP,
518ff9ad32Smacallan SMUSAT_SENSOR_CURRENT,
528ff9ad32Smacallan SMUSAT_SENSOR_VOLTAGE,
538ff9ad32Smacallan SMUSAT_SENSOR_POWER,
548ff9ad32Smacallan };
558ff9ad32Smacallan
568ff9ad32Smacallan struct smusat_softc;
578ff9ad32Smacallan
588ff9ad32Smacallan struct smusat_sensor {
598ff9ad32Smacallan struct smusat_softc *sc;
608ff9ad32Smacallan
618ff9ad32Smacallan char location[32];
628ff9ad32Smacallan int type;
638ff9ad32Smacallan int reg;
648ff9ad32Smacallan int zone;
658ff9ad32Smacallan int shift;
663e3d2eccSmacallan int offset;
673e3d2eccSmacallan int scale;
688ff9ad32Smacallan int current_value;
698ff9ad32Smacallan };
708ff9ad32Smacallan
718ff9ad32Smacallan #define SMUSAT_MAX_SENSORS 16
728ff9ad32Smacallan #define SMUSAT_MAX_SME_SENSORS SMUSAT_MAX_SENSORS
738ff9ad32Smacallan
748ff9ad32Smacallan struct smusat_softc {
758ff9ad32Smacallan device_t sc_dev;
768ff9ad32Smacallan int sc_node;
778ff9ad32Smacallan i2c_addr_t sc_addr;
783e3d2eccSmacallan uint8_t sc_cache[16];
793e3d2eccSmacallan time_t sc_last_update;
808ff9ad32Smacallan struct i2c_controller *sc_i2c;
818ff9ad32Smacallan struct sysctlnode *sc_sysctl_me;
828ff9ad32Smacallan
838ff9ad32Smacallan int sc_num_sensors;
848ff9ad32Smacallan struct smusat_sensor sc_sensors[SMUSAT_MAX_SENSORS];
858ff9ad32Smacallan
868ff9ad32Smacallan struct sysmon_envsys *sc_sme;
878ff9ad32Smacallan envsys_data_t sc_sme_sensors[SMUSAT_MAX_SME_SENSORS];
888ff9ad32Smacallan };
898ff9ad32Smacallan
908ff9ad32Smacallan #ifdef SMUSAT_DEBUG
918ff9ad32Smacallan #define DPRINTF printf
928ff9ad32Smacallan #else
938ff9ad32Smacallan #define DPRINTF while (0) printf
948ff9ad32Smacallan #endif
958ff9ad32Smacallan
968ff9ad32Smacallan static int smusat_match(device_t, struct cfdata *, void *);
978ff9ad32Smacallan static void smusat_attach(device_t, device_t, void *);
988ff9ad32Smacallan static void smusat_setup_sme(struct smusat_softc *);
998ff9ad32Smacallan static void smusat_sme_refresh(struct sysmon_envsys *, envsys_data_t *);
1003e3d2eccSmacallan static int smusat_sensors_update(struct smusat_softc *);
1018ff9ad32Smacallan static int smusat_sensor_read(struct smusat_sensor *, int *);
1028ff9ad32Smacallan static int smusat_sysctl_sensor_value(SYSCTLFN_ARGS);
1038ff9ad32Smacallan
1048ff9ad32Smacallan CFATTACH_DECL_NEW(smusat, sizeof(struct smusat_softc),
1058ff9ad32Smacallan smusat_match, smusat_attach, NULL, NULL);
1068ff9ad32Smacallan
107feee3a19Sthorpej static const struct device_compatible_entry compat_data[] = {
10856caee62Sthorpej { .compat = "sat" },
10956caee62Sthorpej { .compat = "smu-sat" },
110*ec189949Sthorpej DEVICE_COMPAT_EOL
1114f9e5a44Sthorpej };
1124f9e5a44Sthorpej
1138ff9ad32Smacallan static int
smusat_match(device_t parent,struct cfdata * cf,void * aux)1148ff9ad32Smacallan smusat_match(device_t parent, struct cfdata *cf, void *aux)
1158ff9ad32Smacallan {
116aa357ed6Smacallan struct i2c_attach_args *ia = aux;
117aa41e992Sthorpej int match_result;
1188ff9ad32Smacallan
119feee3a19Sthorpej if (iic_use_direct_match(ia, cf, compat_data, &match_result))
120aa41e992Sthorpej return match_result;
121aa41e992Sthorpej
122aa357ed6Smacallan if (ia->ia_addr == 0x58)
123aa41e992Sthorpej return I2C_MATCH_ADDRESS_ONLY;
124aa41e992Sthorpej
1258ff9ad32Smacallan return 0;
1268ff9ad32Smacallan }
1278ff9ad32Smacallan
1288ff9ad32Smacallan static void
smusat_attach(device_t parent,device_t self,void * aux)1298ff9ad32Smacallan smusat_attach(device_t parent, device_t self, void *aux)
1308ff9ad32Smacallan {
131aa357ed6Smacallan struct i2c_attach_args *ia = aux;
1328ff9ad32Smacallan struct smusat_softc *sc = device_private(self);
1338ff9ad32Smacallan struct smusat_sensor *sensor;
1348ff9ad32Smacallan struct sysctlnode *sysctl_sensors, *sysctl_sensor, *sysctl_node;
1358ff9ad32Smacallan char type[32], sysctl_sensor_name[32];
1368ff9ad32Smacallan int node, i, j;
1378ff9ad32Smacallan
1388ff9ad32Smacallan sc->sc_dev = self;
139aa357ed6Smacallan sc->sc_node = ia->ia_cookie;
140aa357ed6Smacallan sc->sc_addr = ia->ia_addr;
141aa357ed6Smacallan sc->sc_i2c = ia->ia_tag;
1428ff9ad32Smacallan
1438ff9ad32Smacallan sysctl_createv(NULL, 0, NULL, (void *) &sc->sc_sysctl_me,
1448ff9ad32Smacallan CTLFLAG_READWRITE,
1458ff9ad32Smacallan CTLTYPE_NODE, device_xname(sc->sc_dev), NULL,
1468ff9ad32Smacallan NULL, 0, NULL, 0,
1478ff9ad32Smacallan CTL_MACHDEP, CTL_CREATE, CTL_EOL);
1488ff9ad32Smacallan
1498ff9ad32Smacallan for (node = OF_child(sc->sc_node);
1508ff9ad32Smacallan (node != 0) && (sc->sc_num_sensors < SMUSAT_MAX_SENSORS);
1518ff9ad32Smacallan node = OF_peer(node)) {
1528ff9ad32Smacallan sensor = &sc->sc_sensors[sc->sc_num_sensors];
1538ff9ad32Smacallan sensor->sc = sc;
1548ff9ad32Smacallan
1558ff9ad32Smacallan memset(sensor->location, 0, sizeof(sensor->location));
1568ff9ad32Smacallan OF_getprop(node, "location", sensor->location,
1578ff9ad32Smacallan sizeof(sensor->location));
1588ff9ad32Smacallan
1598ff9ad32Smacallan if (OF_getprop(node, "reg", &sensor->reg,
1608ff9ad32Smacallan sizeof(sensor->reg)) <= 0)
1618ff9ad32Smacallan continue;
1628ff9ad32Smacallan
1633e3d2eccSmacallan if ((sensor->reg < 0x30) || (sensor->reg > 0x37))
1643e3d2eccSmacallan continue;
1653e3d2eccSmacallan sensor->reg -= 0x30;
1663e3d2eccSmacallan
1678ff9ad32Smacallan if (OF_getprop(node, "zone", &sensor->zone,
1688ff9ad32Smacallan sizeof(sensor->zone)) <= 0)
1698ff9ad32Smacallan continue;
1708ff9ad32Smacallan
1718ff9ad32Smacallan memset(type, 0, sizeof(type));
1728ff9ad32Smacallan OF_getprop(node, "device_type", type, sizeof(type));
1738ff9ad32Smacallan
1748ff9ad32Smacallan if (strcmp(type, "temp-sensor") == 0) {
1758ff9ad32Smacallan sensor->type = SMUSAT_SENSOR_TEMP;
1768ff9ad32Smacallan sensor->shift = 10;
1778ff9ad32Smacallan } else if (strcmp(type, "current-sensor") == 0) {
1788ff9ad32Smacallan sensor->type = SMUSAT_SENSOR_CURRENT;
1798ff9ad32Smacallan sensor->shift = 8;
1808ff9ad32Smacallan } else if (strcmp(type, "voltage-sensor") == 0) {
1818ff9ad32Smacallan sensor->type = SMUSAT_SENSOR_VOLTAGE;
1828ff9ad32Smacallan sensor->shift = 4;
1838ff9ad32Smacallan } else if (strcmp(type, "power-sensor") == 0) {
1848ff9ad32Smacallan sensor->type = SMUSAT_SENSOR_POWER;
1858ff9ad32Smacallan sensor->shift = 0;
1868ff9ad32Smacallan }
1878ff9ad32Smacallan
1888ff9ad32Smacallan DPRINTF("sensor: location %s reg %x zone %d type %s\n",
1898ff9ad32Smacallan sensor->location, sensor->reg, sensor->zone, type);
1908ff9ad32Smacallan
1918ff9ad32Smacallan sc->sc_num_sensors++;
1928ff9ad32Smacallan }
1938ff9ad32Smacallan
1948ff9ad32Smacallan /* Create sysctl nodes for each sensor */
1958ff9ad32Smacallan
1968ff9ad32Smacallan sysctl_createv(NULL, 0, NULL, (void *) &sysctl_sensors,
1978ff9ad32Smacallan CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
1988ff9ad32Smacallan CTLTYPE_NODE, "sensors", NULL,
1998ff9ad32Smacallan NULL, 0, NULL, 0,
2008ff9ad32Smacallan CTL_MACHDEP,
2018ff9ad32Smacallan sc->sc_sysctl_me->sysctl_num,
2028ff9ad32Smacallan CTL_CREATE, CTL_EOL);
2038ff9ad32Smacallan
2048ff9ad32Smacallan for (i = 0; i < sc->sc_num_sensors; i++) {
2058ff9ad32Smacallan sensor = &sc->sc_sensors[i];
2068ff9ad32Smacallan
2078ff9ad32Smacallan for (j = 0; j < strlen(sensor->location); j++) {
2088ff9ad32Smacallan sysctl_sensor_name[j] = tolower(sensor->location[j]);
2098ff9ad32Smacallan if (sysctl_sensor_name[j] == ' ')
2108ff9ad32Smacallan sysctl_sensor_name[j] = '_';
2118ff9ad32Smacallan }
2128ff9ad32Smacallan sysctl_sensor_name[j] = '\0';
2138ff9ad32Smacallan
2148ff9ad32Smacallan sysctl_createv(NULL, 0, NULL, (void *) &sysctl_sensor,
2158ff9ad32Smacallan CTLFLAG_READWRITE | CTLFLAG_OWNDESC,
2168ff9ad32Smacallan CTLTYPE_NODE, sysctl_sensor_name, "sensor information",
2178ff9ad32Smacallan NULL, 0, NULL, 0,
2188ff9ad32Smacallan CTL_MACHDEP,
2198ff9ad32Smacallan sc->sc_sysctl_me->sysctl_num,
2208ff9ad32Smacallan sysctl_sensors->sysctl_num,
2218ff9ad32Smacallan CTL_CREATE, CTL_EOL);
2228ff9ad32Smacallan
2238ff9ad32Smacallan sysctl_createv(NULL, 0, NULL, (void *) &sysctl_node,
2248ff9ad32Smacallan CTLFLAG_READONLY | CTLFLAG_OWNDESC,
2258ff9ad32Smacallan CTLTYPE_INT, "zone", "sensor zone",
2268ff9ad32Smacallan NULL, 0, &sensor->zone, 0,
2278ff9ad32Smacallan CTL_MACHDEP,
2288ff9ad32Smacallan sc->sc_sysctl_me->sysctl_num,
2298ff9ad32Smacallan sysctl_sensors->sysctl_num,
2308ff9ad32Smacallan sysctl_sensor->sysctl_num,
2318ff9ad32Smacallan CTL_CREATE, CTL_EOL);
2328ff9ad32Smacallan
2338ff9ad32Smacallan sysctl_createv(NULL, 0, NULL, (void *) &sysctl_node,
2348ff9ad32Smacallan CTLFLAG_READONLY | CTLFLAG_OWNDESC,
2358ff9ad32Smacallan CTLTYPE_INT, "value", "sensor current value",
2368ff9ad32Smacallan smusat_sysctl_sensor_value, 0, (void *) sensor, 0,
2378ff9ad32Smacallan CTL_MACHDEP,
2388ff9ad32Smacallan sc->sc_sysctl_me->sysctl_num,
2398ff9ad32Smacallan sysctl_sensors->sysctl_num,
2408ff9ad32Smacallan sysctl_sensor->sysctl_num,
2418ff9ad32Smacallan CTL_CREATE, CTL_EOL);
2428ff9ad32Smacallan }
2438ff9ad32Smacallan
2448ff9ad32Smacallan smusat_setup_sme(sc);
2458ff9ad32Smacallan
2468ff9ad32Smacallan printf("\n");
2478ff9ad32Smacallan }
2488ff9ad32Smacallan
2498ff9ad32Smacallan static void
smusat_setup_sme(struct smusat_softc * sc)2508ff9ad32Smacallan smusat_setup_sme(struct smusat_softc *sc)
2518ff9ad32Smacallan {
2528ff9ad32Smacallan struct smusat_sensor *sensor;
2538ff9ad32Smacallan envsys_data_t *sme_sensor;
2548ff9ad32Smacallan int i;
2558ff9ad32Smacallan
2568ff9ad32Smacallan sc->sc_sme = sysmon_envsys_create();
2578ff9ad32Smacallan
2588ff9ad32Smacallan for (i = 0; i < sc->sc_num_sensors; i++) {
2598ff9ad32Smacallan sme_sensor = &sc->sc_sme_sensors[i];
2608ff9ad32Smacallan sensor = &sc->sc_sensors[i];
2618ff9ad32Smacallan
2628ff9ad32Smacallan switch (sensor->type) {
2638ff9ad32Smacallan case SMUSAT_SENSOR_TEMP:
2648ff9ad32Smacallan sme_sensor->units = ENVSYS_STEMP;
2658ff9ad32Smacallan break;
2668ff9ad32Smacallan case SMUSAT_SENSOR_CURRENT:
2678ff9ad32Smacallan sme_sensor->units = ENVSYS_SAMPS;
2688ff9ad32Smacallan break;
2698ff9ad32Smacallan case SMUSAT_SENSOR_VOLTAGE:
2708ff9ad32Smacallan sme_sensor->units = ENVSYS_SVOLTS_DC;
2718ff9ad32Smacallan break;
2728ff9ad32Smacallan case SMUSAT_SENSOR_POWER:
2738ff9ad32Smacallan sme_sensor->units = ENVSYS_SWATTS;
2748ff9ad32Smacallan break;
2758ff9ad32Smacallan default:
2768ff9ad32Smacallan sme_sensor->units = ENVSYS_INTEGER;
2778ff9ad32Smacallan }
2788ff9ad32Smacallan
2798ff9ad32Smacallan sme_sensor->state = ENVSYS_SINVALID;
2808ff9ad32Smacallan snprintf(sme_sensor->desc, sizeof(sme_sensor->desc),
2818ff9ad32Smacallan "%s", sensor->location);
2828ff9ad32Smacallan
2838ff9ad32Smacallan if (sysmon_envsys_sensor_attach(sc->sc_sme, sme_sensor)) {
2848ff9ad32Smacallan sysmon_envsys_destroy(sc->sc_sme);
2858ff9ad32Smacallan return;
2868ff9ad32Smacallan }
2878ff9ad32Smacallan }
2888ff9ad32Smacallan
2898ff9ad32Smacallan sc->sc_sme->sme_name = device_xname(sc->sc_dev);
2908ff9ad32Smacallan sc->sc_sme->sme_cookie = sc;
2918ff9ad32Smacallan sc->sc_sme->sme_refresh = smusat_sme_refresh;
2928ff9ad32Smacallan
2938ff9ad32Smacallan if (sysmon_envsys_register(sc->sc_sme)) {
2948ff9ad32Smacallan aprint_error_dev(sc->sc_dev,
2958ff9ad32Smacallan "unable to register with sysmon\n");
2968ff9ad32Smacallan sysmon_envsys_destroy(sc->sc_sme);
2978ff9ad32Smacallan }
2988ff9ad32Smacallan }
2998ff9ad32Smacallan
3008ff9ad32Smacallan static void
smusat_sme_refresh(struct sysmon_envsys * sme,envsys_data_t * edata)3018ff9ad32Smacallan smusat_sme_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
3028ff9ad32Smacallan {
3038ff9ad32Smacallan struct smusat_softc *sc = sme->sme_cookie;
3048ff9ad32Smacallan struct smusat_sensor *sensor;
3058ff9ad32Smacallan int which = edata->sensor;
3068ff9ad32Smacallan int ret;
3078ff9ad32Smacallan
3088ff9ad32Smacallan edata->state = ENVSYS_SINVALID;
3098ff9ad32Smacallan
3108ff9ad32Smacallan if (which < sc->sc_num_sensors) {
3118ff9ad32Smacallan sensor = &sc->sc_sensors[which];
3128ff9ad32Smacallan
3133e3d2eccSmacallan ret = smusat_sensor_read(sensor, NULL);
3148ff9ad32Smacallan if (ret == 0) {
3158ff9ad32Smacallan switch (sensor->type) {
3168ff9ad32Smacallan case SMUSAT_SENSOR_TEMP:
3178ff9ad32Smacallan edata->value_cur = sensor->current_value *
3188ff9ad32Smacallan 1000000 + 273150000;
3198ff9ad32Smacallan break;
3208ff9ad32Smacallan case SMUSAT_SENSOR_CURRENT:
3213e3d2eccSmacallan edata->value_cur = sensor->current_value * 1000000;
3228ff9ad32Smacallan break;
3238ff9ad32Smacallan case SMUSAT_SENSOR_VOLTAGE:
3243e3d2eccSmacallan edata->value_cur = sensor->current_value * 1000000;
3258ff9ad32Smacallan break;
3268ff9ad32Smacallan case SMUSAT_SENSOR_POWER:
3273e3d2eccSmacallan edata->value_cur = sensor->current_value * 1000000;
3288ff9ad32Smacallan break;
3298ff9ad32Smacallan default:
3308ff9ad32Smacallan edata->value_cur = sensor->current_value;
3318ff9ad32Smacallan }
3328ff9ad32Smacallan
3338ff9ad32Smacallan edata->state = ENVSYS_SVALID;
3348ff9ad32Smacallan }
3358ff9ad32Smacallan }
3368ff9ad32Smacallan }
3378ff9ad32Smacallan
3388ff9ad32Smacallan static int
smusat_sensors_update(struct smusat_softc * sc)3393e3d2eccSmacallan smusat_sensors_update(struct smusat_softc *sc)
3408ff9ad32Smacallan {
3413e3d2eccSmacallan u_char reg = 0x3f;
3428ff9ad32Smacallan int ret;
3438ff9ad32Smacallan
3448ff9ad32Smacallan iic_acquire_bus(sc->sc_i2c, 0);
3453e3d2eccSmacallan ret = iic_exec(sc->sc_i2c, I2C_OP_READ, sc->sc_addr, ®, 1, sc->sc_cache, 16, 0);
3468ff9ad32Smacallan iic_release_bus(sc->sc_i2c, 0);
3478ff9ad32Smacallan
3488ff9ad32Smacallan if (ret != 0)
3498ff9ad32Smacallan return (ret);
3508ff9ad32Smacallan
3513e3d2eccSmacallan sc->sc_last_update = time_uptime;
3528ff9ad32Smacallan
3538ff9ad32Smacallan return 0;
3548ff9ad32Smacallan }
3558ff9ad32Smacallan
3568ff9ad32Smacallan static int
smusat_sensor_read(struct smusat_sensor * sensor,int * value)3578ff9ad32Smacallan smusat_sensor_read(struct smusat_sensor *sensor, int *value)
3588ff9ad32Smacallan {
3593e3d2eccSmacallan struct smusat_softc *sc = sensor->sc;
3603e3d2eccSmacallan int ret, reg;
3618ff9ad32Smacallan
3623e3d2eccSmacallan if (time_uptime - sc->sc_last_update > 1) {
3633e3d2eccSmacallan ret = smusat_sensors_update(sc);
3648ff9ad32Smacallan if (ret != 0)
3658ff9ad32Smacallan return ret;
3668ff9ad32Smacallan }
3678ff9ad32Smacallan
3683e3d2eccSmacallan reg = sensor->reg << 1;
3693e3d2eccSmacallan sensor->current_value = (sc->sc_cache[reg] << 8) + sc->sc_cache[reg + 1];
3703e3d2eccSmacallan sensor->current_value <<= sensor->shift;
3713e3d2eccSmacallan /* Discard the .16 */
3723e3d2eccSmacallan sensor->current_value >>= 16;
3733e3d2eccSmacallan
3743e3d2eccSmacallan if (value != NULL)
3758ff9ad32Smacallan *value = sensor->current_value;
3768ff9ad32Smacallan
3778ff9ad32Smacallan return 0;
3788ff9ad32Smacallan }
3798ff9ad32Smacallan
3808ff9ad32Smacallan static int
smusat_sysctl_sensor_value(SYSCTLFN_ARGS)3818ff9ad32Smacallan smusat_sysctl_sensor_value(SYSCTLFN_ARGS)
3828ff9ad32Smacallan {
3838ff9ad32Smacallan struct sysctlnode node = *rnode;
3848ff9ad32Smacallan struct smusat_sensor *sensor = node.sysctl_data;
3858ff9ad32Smacallan int value = 0;
3868ff9ad32Smacallan int ret;
3878ff9ad32Smacallan
3888ff9ad32Smacallan node.sysctl_data = &value;
3898ff9ad32Smacallan
3908ff9ad32Smacallan ret = smusat_sensor_read(sensor, &value);
3918ff9ad32Smacallan if (ret != 0)
3928ff9ad32Smacallan return (ret);
3938ff9ad32Smacallan
3948ff9ad32Smacallan return sysctl_lookup(SYSCTLFN_CALL(&node));
3958ff9ad32Smacallan }
3968ff9ad32Smacallan
3978ff9ad32Smacallan SYSCTL_SETUP(smusat_sysctl_setup, "SMU-SAT sysctl subtree setup")
3988ff9ad32Smacallan {
3998ff9ad32Smacallan sysctl_createv(NULL, 0, NULL, NULL,
4008ff9ad32Smacallan CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
4018ff9ad32Smacallan NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL);
4028ff9ad32Smacallan }
403