summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/powermac/smusat.c
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2011-05-28 22:11:22 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2011-05-28 22:11:22 +0000
commit16f4172df58aff2531075ad9428e980aba6a25bd (patch)
tree87a0022a86caff6d1319db97542deeb49b4b4a8d /sys/powerpc/powermac/smusat.c
parent6182e8b704c704bf06d61942bcea7a82d283cc1d (diff)
downloadFreeBSD-src-16f4172df58aff2531075ad9428e980aba6a25bd.zip
FreeBSD-src-16f4172df58aff2531075ad9428e980aba6a25bd.tar.gz
Adapt smusat(4) to use powermac_thermal. This provides automatic fan
management on dual- and quad-core Powermac G5s, and the last G5 iMacs.
Diffstat (limited to 'sys/powerpc/powermac/smusat.c')
-rw-r--r--sys/powerpc/powermac/smusat.c50
1 files changed, 34 insertions, 16 deletions
diff --git a/sys/powerpc/powermac/smusat.c b/sys/powerpc/powermac/smusat.c
index 42f023a..886cd4f 100644
--- a/sys/powerpc/powermac/smusat.c
+++ b/sys/powerpc/powermac/smusat.c
@@ -43,9 +43,13 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/openfirm.h>
+#include <powerpc/powermac/powermac_thermal.h>
+
struct smu_sensor {
+ struct pmac_therm therm;
+ device_t dev;
+
cell_t reg;
- char location[32];
enum {
SMU_CURRENT_SENSOR,
SMU_VOLTAGE_SENSOR,
@@ -57,6 +61,7 @@ struct smu_sensor {
static int smusat_probe(device_t);
static int smusat_attach(device_t);
static int smusat_sensor_sysctl(SYSCTL_HANDLER_ARGS);
+static int smusat_sensor_read(struct smu_sensor *sens);
MALLOC_DEFINE(M_SMUSAT, "smusat", "SMU Sattelite Sensors");
@@ -135,14 +140,16 @@ smusat_attach(device_t dev)
char sysctl_name[40], sysctl_desc[40];
const char *units;
+ sens->dev = dev;
sens->reg = 0;
OF_getprop(child, "reg", &sens->reg, sizeof(sens->reg));
if (sens->reg < 0x30)
continue;
-
sens->reg -= 0x30;
- OF_getprop(child, "location", sens->location,
- sizeof(sens->location));
+
+ OF_getprop(child, "zone", &sens->therm.zone, sizeof(int));
+ OF_getprop(child, "location", sens->therm.name,
+ sizeof(sens->therm.name));
OF_getprop(child, "device_type", type, sizeof(type));
@@ -162,17 +169,27 @@ smusat_attach(device_t dev)
continue;
}
- for (i = 0; i < strlen(sens->location); i++) {
- sysctl_name[i] = tolower(sens->location[i]);
+ for (i = 0; i < strlen(sens->therm.name); i++) {
+ sysctl_name[i] = tolower(sens->therm.name[i]);
if (isspace(sysctl_name[i]))
sysctl_name[i] = '_';
}
sysctl_name[i] = 0;
- sprintf(sysctl_desc,"%s (%s)", sens->location, units);
+ sprintf(sysctl_desc,"%s (%s)", sens->therm.name, units);
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(sensroot_oid), OID_AUTO,
sysctl_name, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev,
- sc->sc_nsensors, smusat_sensor_sysctl, "I", sysctl_desc);
+ sc->sc_nsensors, smusat_sensor_sysctl,
+ (sens->type == SMU_TEMP_SENSOR) ? "IK" : "I", sysctl_desc);
+
+ if (sens->type == SMU_TEMP_SENSOR) {
+ /* Make up some numbers */
+ sens->therm.target_temp = 500 + 2732; /* 50 C */
+ sens->therm.max_temp = 900 + 2732; /* 90 C */
+ sens->therm.read =
+ (int (*)(struct pmac_therm *))smusat_sensor_read;
+ pmac_thermal_sensor_register(&sens->therm);
+ }
sens++;
sc->sc_nsensors++;
@@ -198,11 +215,13 @@ smusat_updatecache(device_t dev)
}
static int
-smusat_sensor_read(device_t dev, struct smu_sensor *sens, int *val)
+smusat_sensor_read(struct smu_sensor *sens)
{
int value;
+ device_t dev;
struct smusat_softc *sc;
+ dev = sens->dev;
sc = device_get_softc(dev);
if (time_uptime - sc->sc_last_update > 1)
@@ -215,8 +234,8 @@ smusat_sensor_read(device_t dev, struct smu_sensor *sens, int *val)
case SMU_TEMP_SENSOR:
/* 16.16 */
value <<= 10;
- /* Kill the .16 */
- value >>= 16;
+ /* From 16.16 to 0.1 C */
+ value = 10*(value >> 16) + 2732;
break;
case SMU_VOLTAGE_SENSOR:
/* 16.16 */
@@ -235,8 +254,7 @@ smusat_sensor_read(device_t dev, struct smu_sensor *sens, int *val)
break;
}
- *val = value;
- return (0);
+ return (value);
}
static int
@@ -251,9 +269,9 @@ smusat_sensor_sysctl(SYSCTL_HANDLER_ARGS)
sc = device_get_softc(dev);
sens = &sc->sc_sensors[arg2];
- error = smusat_sensor_read(dev, sens, &value);
- if (error != 0)
- return (error);
+ value = smusat_sensor_read(sens);
+ if (value < 0)
+ return (EBUSY);
error = sysctl_handle_int(oidp, &value, 0, req);
OpenPOWER on IntegriCloud