Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 21 Feb 2010 21:03:37 +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: r204179 - head/sys/powerpc/powermac
Message-ID:  <201002212103.o1LL3b2o037994@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Sun Feb 21 21:03:37 2010
New Revision: 204179
URL: http://svn.freebsd.org/changeset/base/204179

Log:
  Fix several mistakes in this file, in order to allow individual fan speeds
  to be read and set correctly.

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

Modified: head/sys/powerpc/powermac/smu.c
==============================================================================
--- head/sys/powerpc/powermac/smu.c	Sun Feb 21 21:03:15 2010	(r204178)
+++ head/sys/powerpc/powermac/smu.c	Sun Feb 21 21:03:37 2010	(r204179)
@@ -58,6 +58,7 @@ struct smu_fan {
 	cell_t	max_rpm;
 	cell_t	unmanaged_rpm;
 	char	location[32];
+	int	old_style;
 };
 
 struct smu_sensor {
@@ -115,6 +116,7 @@ static void	smu_cpufreq_pre_change(devic
 static void	smu_cpufreq_post_change(device_t, const struct cf_level *level);
 
 /* utility functions */
+static int	smu_run_cmd(device_t dev, struct smu_cmd *cmd);
 static int	smu_get_datablock(device_t dev, int8_t id, uint8_t *buf,
 		    size_t len);
 static void	smu_attach_fans(device_t dev, phandle_t fanroot);
@@ -148,11 +150,12 @@ MALLOC_DEFINE(M_SMU, "smu", "SMU Sensor 
 #define SMU_ADC			0xd8
 #define SMU_FAN			0x4a
 #define SMU_I2C			0x9a
-#define SMU_I2C_SIMPLE		0x00
-#define SMU_I2C_NORMAL		0x01
-#define SMU_I2C_COMBINED	0x02
+#define  SMU_I2C_SIMPLE		0x00
+#define  SMU_I2C_NORMAL		0x01
+#define  SMU_I2C_COMBINED	0x02
 #define SMU_MISC		0xee
-#define SMU_MISC_GET_DATA	0x02
+#define  SMU_MISC_GET_DATA	0x02
+#define  SMU_MISC_LED_CTRL	0x04
 #define SMU_POWER		0xaa
 
 /* Data blocks */
@@ -306,6 +309,7 @@ smu_run_cmd(device_t dev, struct smu_cmd
 	powerpc_pow_enabled = oldpow;
 
 	memcpy(cmd->data, sc->sc_cmd->data, sizeof(cmd->data));
+	cmd->len = sc->sc_cmd->len;
 
 	mtx_unlock(&sc->sc_mtx);
 
@@ -430,21 +434,43 @@ static int
 smu_fan_set_rpm(device_t smu, struct smu_fan *fan, int rpm)
 {
 	struct smu_cmd cmd;
+	int error;
 
 	cmd.cmd = SMU_FAN;
-	cmd.len = 14;
-	cmd.data[0] = 0;
-	cmd.data[1] = 1 << fan->reg;
+	error = EIO;
+
+	/* Clamp to allowed range */
+	rpm = max(fan->min_rpm, rpm);
+	rpm = min(fan->max_rpm, rpm);
 
 	/*
-	 * There are two locations used for the fan speed.
-	 * Store it in both.
+	 * Apple has two fan control mechanisms. We can't distinguish
+	 * them except by seeing if the new one fails. If the new one
+	 * fails, use the old one.
 	 */
+	
+	if (!fan->old_style) {
+		cmd.len = 4;
+		cmd.data[0] = 0x30;
+		cmd.data[1] = fan->reg;
+		cmd.data[2] = (rpm >> 8) & 0xff;
+		cmd.data[3] = rpm & 0xff;
+	
+		error = smu_run_cmd(smu, &cmd);
+		if (error)
+			fan->old_style = 1;
+	}
 
-	cmd.data[2] = cmd.data[2 + 2*fan->reg] = (rpm >> 8) & 0xff;
-	cmd.data[3] = cmd.data[3 + 2*fan->reg] = rpm & 0xff;
+	if (fan->old_style) {
+		cmd.len = 14;
+		cmd.data[0] = 0;
+		cmd.data[1] = 1 << fan->reg;
+		cmd.data[2 + 2*fan->reg] = (rpm >> 8) & 0xff;
+		cmd.data[3 + 2*fan->reg] = rpm & 0xff;
+		error = smu_run_cmd(smu, &cmd);
+	}
 
-	return (smu_run_cmd(smu, &cmd));
+	return (error);
 }
 
 static int
@@ -453,13 +479,12 @@ smu_fan_read_rpm(device_t smu, struct sm
 	struct smu_cmd cmd;
 
 	cmd.cmd = SMU_FAN;
-	cmd.len = 2;
+	cmd.len = 1;
 	cmd.data[0] = 1;
-	cmd.data[1] = 1 << fan->reg;
 
 	smu_run_cmd(smu, &cmd);
 
-	return ((cmd.data[1] << 8) | cmd.data[2]);
+	return ((cmd.data[fan->reg*2+1] << 8) | cmd.data[fan->reg*2+2]);
 }
 
 static int
@@ -522,11 +547,15 @@ smu_attach_fans(device_t dev, phandle_t 
 		if (strcmp(type, "fan-rpm-control") != 0)
 			continue;
 
+		fan->old_style = 0;
 		OF_getprop(child, "reg", &fan->reg, sizeof(cell_t));
 		OF_getprop(child, "min-value", &fan->min_rpm, sizeof(cell_t));
 		OF_getprop(child, "max-value", &fan->max_rpm, sizeof(cell_t));
-		OF_getprop(child, "unmanaged-value", &fan->unmanaged_rpm,
-		    sizeof(cell_t));
+
+		if (OF_getprop(child, "unmanaged-value", &fan->unmanaged_rpm,
+		    sizeof(cell_t)) != sizeof(cell_t))
+			fan->unmanaged_rpm = fan->max_rpm;
+
 		OF_getprop(child, "location", fan->location,
 		    sizeof(fan->location));
 
@@ -661,8 +690,8 @@ smu_attach_sensors(device_t dev, phandle
 		return;
 	}
 
-	sc->sc_fans = malloc(sc->sc_nsensors * sizeof(struct smu_sensor), M_SMU,
-	    M_WAITOK | M_ZERO);
+	sc->sc_sensors = malloc(sc->sc_nsensors * sizeof(struct smu_sensor),
+	    M_SMU, M_WAITOK | M_ZERO);
 
 	sens = sc->sc_sensors;
 	sc->sc_nsensors = 0;



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