Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 28 May 2011 22:11:22 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r222431 - head/sys/powerpc/powermac
Message-ID:  <201105282211.p4SMBMHr002560@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Sat May 28 22:11:22 2011
New Revision: 222431
URL: http://svn.freebsd.org/changeset/base/222431

Log:
  Adapt smusat(4) to use powermac_thermal. This provides automatic fan
  management on dual- and quad-core Powermac G5s, and the last G5 iMacs.

Modified:
  head/sys/powerpc/powermac/smusat.c

Modified: head/sys/powerpc/powermac/smusat.c
==============================================================================
--- head/sys/powerpc/powermac/smusat.c	Sat May 28 21:54:18 2011	(r222430)
+++ head/sys/powerpc/powermac/smusat.c	Sat May 28 22:11:22 2011	(r222431)
@@ -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 
 	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 
 		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);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201105282211.p4SMBMHr002560>