diff options
author | Nathan Whitehorn <nwhitehorn@FreeBSD.org> | 2011-05-29 18:35:57 +0000 |
---|---|---|
committer | Nathan Whitehorn <nwhitehorn@FreeBSD.org> | 2011-05-29 18:35:57 +0000 |
commit | 815d7d92c10a1537eb9aeccf26c2777f66c1135d (patch) | |
tree | 059a5a044ae0b870bfdd97208a26b7a06d2bda2f /sys/dev/iicbus/max6690.c | |
parent | 3204c8e596216d62b212b8af312f09cc0a7a10d8 (diff) | |
download | src-815d7d92c10a1537eb9aeccf26c2777f66c1135d.tar.gz src-815d7d92c10a1537eb9aeccf26c2777f66c1135d.zip |
Update the I2C-based temperature/fan drivers to connect to the Powermac
thermal control module. This provides automatic fan management on all G5
PowerMacs and Xserves.
Notes
Notes:
svn path=/head/; revision=222458
Diffstat (limited to 'sys/dev/iicbus/max6690.c')
-rw-r--r-- | sys/dev/iicbus/max6690.c | 50 |
1 files changed, 38 insertions, 12 deletions
diff --git a/sys/dev/iicbus/max6690.c b/sys/dev/iicbus/max6690.c index cbfdc26619e3..43d6c8487385 100644 --- a/sys/dev/iicbus/max6690.c +++ b/sys/dev/iicbus/max6690.c @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include <dev/ofw/openfirm.h> #include <dev/ofw/ofw_bus.h> +#include <powerpc/powermac/powermac_thermal.h> #define FCU_ZERO_C_TO_K 2732 @@ -61,8 +62,10 @@ __FBSDID("$FreeBSD$"); #define MAX6690_TEMP_MASK 0xe0 struct max6690_sensor { + struct pmac_therm therm; + device_t dev; + int id; - char location[32]; }; /* Regular bus attachment functions */ @@ -70,6 +73,7 @@ static int max6690_probe(device_t); static int max6690_attach(device_t); /* Utility functions */ +static int max6690_sensor_read(struct max6690_sensor *sens); static int max6690_sensor_sysctl(SYSCTL_HANDLER_ARGS); static void max6690_start(void *xdev); static int max6690_read_1(device_t dev, uint32_t addr, uint8_t reg, @@ -167,7 +171,7 @@ max6690_fill_sensor_prop(device_t dev) sizeof(location)); while (len < prop_len) { if (sc->sc_sensors != NULL) - strcpy(sc->sc_sensors[i].location, location + len); + strcpy(sc->sc_sensors[i].therm.name, location + len); prev_len = strlen(location + len) + 1; len += prev_len; i++; @@ -180,6 +184,22 @@ max6690_fill_sensor_prop(device_t dev) for (j = 0; j < i; j++) sc->sc_sensors[j].id = (id[j] & 0xf); + /* Fill the sensor zone property. */ + prop_len = OF_getprop(child, "hwsensor-zone", id, sizeof(id)); + for (j = 0; j < i; j++) + sc->sc_sensors[j].therm.zone = id[j]; + + /* Set up remaining sensor properties */ + for (j = 0; j < i; j++) { + sc->sc_sensors[j].dev = dev; + + sc->sc_sensors[j].therm.target_temp = 400 + 2732; + sc->sc_sensors[j].therm.max_temp = 800 + 2732; + + sc->sc_sensors[j].therm.read = + (int (*)(struct pmac_therm *))(max6690_sensor_read); + } + return (i); } static int @@ -240,10 +260,15 @@ max6690_start(void *xdev) /* Now we can fill the properties into the allocated struct. */ sc->sc_nsensors = max6690_fill_sensor_prop(dev); + /* Register with powermac_thermal */ + for (i = 0; i < sc->sc_nsensors; i++) + pmac_thermal_sensor_register(&sc->sc_sensors[i].therm); + /* Add sysctls for the sensors. */ for (i = 0; i < sc->sc_nsensors; i++) { - for (j = 0; j < strlen(sc->sc_sensors[i].location); j++) { - sysctl_name[j] = tolower(sc->sc_sensors[i].location[j]); + for (j = 0; j < strlen(sc->sc_sensors[i].therm.name); j++) { + sysctl_name[j] = + tolower(sc->sc_sensors[i].therm.name[j]); if (isspace(sysctl_name[j])) sysctl_name[j] = '_'; } @@ -265,7 +290,7 @@ max6690_start(void *xdev) device_printf(dev, "Sensors\n"); for (i = 0; i < sc->sc_nsensors; i++) { device_printf(dev, "Location : %s ID: %d\n", - sc->sc_sensors[i].location, + sc->sc_sensors[i].therm.name, sc->sc_sensors[i].id); } } @@ -274,14 +299,15 @@ max6690_start(void *xdev) } static int -max6690_sensor_read(device_t dev, struct max6690_sensor *sens, int *temp) +max6690_sensor_read(struct max6690_sensor *sens) { uint8_t reg_int = 0, reg_ext = 0; uint8_t integer; uint8_t fraction; + int temp; struct max6690_softc *sc; - sc = device_get_softc(dev); + sc = device_get_softc(sens->dev); /* The internal sensor id's are even, the external ar odd. */ if ((sens->id % 2) == 0) { @@ -301,9 +327,9 @@ max6690_sensor_read(device_t dev, struct max6690_sensor *sens, int *temp) /* The temperature is in tenth kelvin, the fractional part resolution is 0.125. */ - *temp = (integer * 10) + (fraction >> 5) * 10 / 8; + temp = (integer * 10) + (fraction >> 5) * 10 / 8; - return (0); + return (temp); } static int @@ -320,9 +346,9 @@ max6690_sensor_sysctl(SYSCTL_HANDLER_ARGS) sc = device_get_softc(dev); sens = &sc->sc_sensors[arg2]; - error = max6690_sensor_read(dev, sens, &value); - if (error != 0) - return (error); + value = max6690_sensor_read(sens); + if (value < 0) + return (EIO); temp = value + FCU_ZERO_C_TO_K; |