Module Name:    src
Committed By:   macallan
Date:           Tue Jul 27 23:38:42 UTC 2021

Modified Files:
        src/sys/arch/macppc/conf: files.macppc
        src/sys/arch/macppc/dev: fcu.c
Added Files:
        src/sys/arch/macppc/dev: fancontrol.c fancontrolvar.h

Log Message:
first step towards abstracting thermal zone management out of the fcu driver
( and eventually, the smu driver )
todo:
- add sysctl()s to set zone parameters
- handle envsys
- adapt smu


To generate a diff of this commit:
cvs rdiff -u -r1.120 -r1.121 src/sys/arch/macppc/conf/files.macppc
cvs rdiff -u -r0 -r1.1 src/sys/arch/macppc/dev/fancontrol.c \
    src/sys/arch/macppc/dev/fancontrolvar.h
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/macppc/dev/fcu.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/macppc/conf/files.macppc
diff -u src/sys/arch/macppc/conf/files.macppc:1.120 src/sys/arch/macppc/conf/files.macppc:1.121
--- src/sys/arch/macppc/conf/files.macppc:1.120	Tue Jul 27 20:23:41 2021
+++ src/sys/arch/macppc/conf/files.macppc	Tue Jul 27 23:38:42 2021
@@ -1,4 +1,4 @@
-#	$NetBSD: files.macppc,v 1.120 2021/07/27 20:23:41 macallan Exp $
+#	$NetBSD: files.macppc,v 1.121 2021/07/27 23:38:42 macallan Exp $
 #
 # macppc-specific configuration info
 
@@ -176,7 +176,11 @@ device zstty: tty
 attach zstty at zsc
 file dev/ic/z8530tty.c				zstty needs-flag
 
-device smu { }
+define fancontrol
+file arch/macppc/dev/fancontrol.c		fancontrol
+defflag	opt_fancontrol.h	FANCONTROL_DEBUG
+
+device smu { } : fancontrol
 attach smu at mainbus
 file arch/macppc/dev/smu.c			smu needs-flag
 defflag	opt_smu.h	SMU_DEBUG
@@ -328,6 +332,6 @@ file	arch/macppc/dev/lmu.c				lmu
 defflag opt_lmu.h LMU_DEBUG
 
 # Apple Fan Control Unit found in some G5
-device	fcu: sysmon_envsys
+device	fcu: sysmon_envsys, fancontrol
 attach	fcu at iic
 file	arch/macppc/dev/fcu.c				fcu	needs-flag

Index: src/sys/arch/macppc/dev/fcu.c
diff -u src/sys/arch/macppc/dev/fcu.c:1.1 src/sys/arch/macppc/dev/fcu.c:1.2
--- src/sys/arch/macppc/dev/fcu.c:1.1	Tue Jul 27 20:23:41 2021
+++ src/sys/arch/macppc/dev/fcu.c	Tue Jul 27 23:38:42 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: fcu.c,v 1.1 2021/07/27 20:23:41 macallan Exp $ */
+/* $NetBSD: fcu.c,v 1.2 2021/07/27 23:38:42 macallan Exp $ */
 
 /*-
  * Copyright (c) 2018 Michael Lorenz
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fcu.c,v 1.1 2021/07/27 20:23:41 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fcu.c,v 1.2 2021/07/27 23:38:42 macallan Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -42,6 +42,8 @@ __KERNEL_RCSID(0, "$NetBSD: fcu.c,v 1.1 
 
 #include <dev/ofw/openfirm.h>
 
+#include <macppc/dev/fancontrolvar.h>
+
 //#define FCU_DEBUG
 #ifdef FCU_DEBUG
 #define DPRINTF printf
@@ -58,14 +60,6 @@ __KERNEL_RCSID(0, "$NetBSD: fcu.c,v 1.1 
 #define FCU_PWM_ACTIVE	0x2d
 #define FCU_PWMREAD(x)	0x30 + (x)*2
 
-#define FCU_MAX_FANS 10
-
-typedef struct _fcu_zone {
-	bool (*filter)(const envsys_data_t *);
-	int nfans;
-	int fans[FCU_MAX_FANS];
-	int threshold;
-} fcu_zone_t; 
 
 typedef struct _fcu_fan {
 	int target;
@@ -86,15 +80,15 @@ struct fcu_softc {
 	i2c_addr_t	sc_addr;
 
 	struct sysmon_envsys *sc_sme;
-	envsys_data_t	sc_sensors[32];
-	int		sc_nsensors;
-	fcu_zone_t	sc_zones[FCU_ZONE_COUNT];
-	fcu_fan_t	sc_fans[FCU_MAX_FANS];
-	int		sc_nfans;
-	lwp_t		*sc_thread;
-	bool		sc_dying, sc_pwm;
-	uint8_t		sc_eeprom0[160];
-	uint8_t		sc_eeprom1[160];
+	envsys_data_t		sc_sensors[32];
+	int			sc_nsensors;
+	fancontrol_zone_t	sc_zones[FCU_ZONE_COUNT];
+	fcu_fan_t		sc_fans[FANCONTROL_MAX_FANS];
+	int			sc_nfans;
+	lwp_t			*sc_thread;
+	bool			sc_dying, sc_pwm;
+	uint8_t			sc_eeprom0[160];
+	uint8_t			sc_eeprom1[160];
 };
 
 static int	fcu_match(device_t, cfdata_t, void *);
@@ -106,8 +100,8 @@ static bool is_cpu(const envsys_data_t *
 static bool is_case(const envsys_data_t *);
 static bool is_drive(const envsys_data_t *);
 
-static void fcu_set_fan_rpm(struct fcu_softc *, fcu_fan_t *, int);
-static void fcu_adjust_zone(struct fcu_softc *, int);
+static int fcu_set_rpm(void *, int, int);
+static int fcu_get_rpm(void *, int);
 static void fcu_adjust(void *);
 
 CFATTACH_DECL_NEW(fcu, sizeof(struct fcu_softc),
@@ -160,14 +154,29 @@ fcu_attach(device_t parent, device_t sel
 		have_eeprom1 = 0;
 
 	/* init zones */
+	sc->sc_zones[FCU_ZONE_CPU].name = "CPUs";
 	sc->sc_zones[FCU_ZONE_CPU].filter = is_cpu;
-	sc->sc_zones[FCU_ZONE_CPU].threshold = 50;
+	sc->sc_zones[FCU_ZONE_CPU].cookie = sc;
+	sc->sc_zones[FCU_ZONE_CPU].get_rpm = fcu_get_rpm;
+	sc->sc_zones[FCU_ZONE_CPU].set_rpm = fcu_set_rpm;
+	sc->sc_zones[FCU_ZONE_CPU].Tmin = 50;
+	sc->sc_zones[FCU_ZONE_CPU].Tmax = 85;
 	sc->sc_zones[FCU_ZONE_CPU].nfans = 0;
+	sc->sc_zones[FCU_ZONE_CASE].name = "Slots";
 	sc->sc_zones[FCU_ZONE_CASE].filter = is_case;
-	sc->sc_zones[FCU_ZONE_CASE].threshold = 50;
+	sc->sc_zones[FCU_ZONE_CASE].Tmin = 50;
+	sc->sc_zones[FCU_ZONE_CASE].cookie = sc;
+	sc->sc_zones[FCU_ZONE_CASE].get_rpm = fcu_get_rpm;
+	sc->sc_zones[FCU_ZONE_CASE].set_rpm = fcu_set_rpm;
+	sc->sc_zones[FCU_ZONE_CASE].Tmax = 75;
 	sc->sc_zones[FCU_ZONE_CASE].nfans = 0;
+	sc->sc_zones[FCU_ZONE_DRIVEBAY].name = "Drive bays";
 	sc->sc_zones[FCU_ZONE_DRIVEBAY].filter = is_drive;
-	sc->sc_zones[FCU_ZONE_DRIVEBAY].threshold = 30;
+	sc->sc_zones[FCU_ZONE_DRIVEBAY].cookie = sc;
+	sc->sc_zones[FCU_ZONE_DRIVEBAY].get_rpm = fcu_get_rpm;
+	sc->sc_zones[FCU_ZONE_DRIVEBAY].set_rpm = fcu_set_rpm;
+	sc->sc_zones[FCU_ZONE_DRIVEBAY].Tmin = 30;
+	sc->sc_zones[FCU_ZONE_DRIVEBAY].Tmax = 60;
 	sc->sc_zones[FCU_ZONE_DRIVEBAY].nfans = 0;
 
 	sc->sc_sme = sysmon_envsys_create();
@@ -278,17 +287,26 @@ fcu_attach(device_t parent, device_t sel
 
 			/* now stuff them into zones */
 			if (strstr(descr, "CPU") != NULL) {
-				fcu_zone_t *z = &sc->sc_zones[FCU_ZONE_CPU];
-				z->fans[z->nfans] = sc->sc_nfans;
+				fancontrol_zone_t *z = &sc->sc_zones[FCU_ZONE_CPU];
+				z->fans[z->nfans].num = sc->sc_nfans;
+				z->fans[z->nfans].min_rpm = fan->base_rpm;
+				z->fans[z->nfans].max_rpm = fan->max_rpm;
+				z->fans[z->nfans].name = s->desc;
 				z->nfans++;
 			} else if ((strstr(descr, "BACKSIDE") != NULL) ||
 				   (strstr(descr, "SLOT") != NULL))  {
-				fcu_zone_t *z = &sc->sc_zones[FCU_ZONE_CASE];
-				z->fans[z->nfans] = sc->sc_nfans;
+				fancontrol_zone_t *z = &sc->sc_zones[FCU_ZONE_CASE];
+				z->fans[z->nfans].num = sc->sc_nfans;
+				z->fans[z->nfans].min_rpm = fan->base_rpm;
+				z->fans[z->nfans].max_rpm = fan->max_rpm;
+				z->fans[z->nfans].name = s->desc;
 				z->nfans++;
 			} else if (strstr(descr, "DRIVE") != NULL) {
-				fcu_zone_t *z = &sc->sc_zones[FCU_ZONE_DRIVEBAY];
-				z->fans[z->nfans] = sc->sc_nfans;
+				fancontrol_zone_t *z = &sc->sc_zones[FCU_ZONE_DRIVEBAY];
+				z->fans[z->nfans].num = sc->sc_nfans;
+				z->fans[z->nfans].min_rpm = fan->base_rpm;
+				z->fans[z->nfans].max_rpm = fan->max_rpm;
+				z->fans[z->nfans].name = s->desc;
 				z->nfans++;
 			}
 			sc->sc_nfans++;
@@ -380,10 +398,31 @@ is_drive(const envsys_data_t *edata)
 	return false;
 }
 
-static void
-fcu_set_fan_rpm(struct fcu_softc *sc, fcu_fan_t *f, int speed)
+static int
+fcu_get_rpm(void *cookie, int which)
 {
+	struct fcu_softc *sc = cookie;
+	fcu_fan_t *f = &sc->sc_fans[which];
 	int error;
+	uint16_t data;
+	uint8_t cmd;
+
+	iic_acquire_bus(sc->sc_i2c, 0);
+	cmd = f->reg + 1;
+	error = iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP,
+	    sc->sc_addr, &cmd, 1, &data, 2, 0);
+	iic_release_bus(sc->sc_i2c, 0);
+	if (error != 0) return -1;
+	data = data >> 3;
+	return data;
+}
+
+static int
+fcu_set_rpm(void *cookie, int which, int speed)
+{
+	struct fcu_softc *sc = cookie;
+	fcu_fan_t *f = &sc->sc_fans[which];
+	int error = 0;
 	uint8_t cmd;
 
 	if (speed > f->max_rpm) speed = f->max_rpm;
@@ -393,7 +432,7 @@ fcu_set_fan_rpm(struct fcu_softc *sc, fc
 		uint16_t data;
 		/* simple rpm fan, just poke the register */
 
-		if (f->target == speed) return;
+		if (f->target == speed) return 0;
 		iic_acquire_bus(sc->sc_i2c, 0);
 		cmd = f->reg;
 		data = (speed << 3);
@@ -403,16 +442,12 @@ fcu_set_fan_rpm(struct fcu_softc *sc, fc
 	} else {
 		int diff;
 		int nduty = f->duty;
-		uint16_t data;
+		int current_speed;
 		/* pwm fan, measure speed, then adjust duty cycle */
 		DPRINTF("pwm fan ");
-		iic_acquire_bus(sc->sc_i2c, 0);
-		cmd = f->reg + 1;
-		error = iic_exec(sc->sc_i2c, I2C_OP_READ_WITH_STOP,
-		    sc->sc_addr, &cmd, 1, &data, 2, 0);
-		data = data >> 3;
-		diff = data - speed;
-		DPRINTF("d %d s %d t %d diff %d ", f->duty, data, speed, diff);
+		current_speed = fcu_get_rpm(sc, which);
+		diff = current_speed - speed;
+		DPRINTF("d %d s %d t %d diff %d ", f->duty, current_speed, speed, diff);
 		if (diff > 100) {
 			nduty = uimax(20, nduty - 1);
 		}
@@ -423,51 +458,19 @@ fcu_set_fan_rpm(struct fcu_softc *sc, fc
 		DPRINTF("%s nduty %d", __func__, nduty);
 		if (nduty != f->duty) {
 			uint8_t arg = nduty;
+			iic_acquire_bus(sc->sc_i2c, 0);
 			error = iic_exec(sc->sc_i2c, I2C_OP_WRITE_WITH_STOP,
 			    sc->sc_addr, &cmd, 1, &arg, 1, 0);
+			iic_release_bus(sc->sc_i2c, 0);
 			f->duty = nduty;
 			sc->sc_pwm = TRUE;
 
 		}
-		iic_release_bus(sc->sc_i2c, 0);
 		DPRINTF("ok\n");
 	}
 	if (error) printf("boo\n");
 	f->target = speed;
-}
-
-static void
-fcu_adjust_zone(struct fcu_softc *sc, int which)
-{
-	fcu_zone_t *z = &sc->sc_zones[which];
-	fcu_fan_t *f;
-	int temp, i, speed, diff;
-	
-	if (z->nfans <= 0)
-		return;
-
-	temp = sysmon_envsys_get_max_value(z->filter, true);
-	if (temp == 0) {
-		/* no sensor data - leave fan alone */
-		DPRINTF("nodata\n");
-		return;
-	}
-
-	temp = (temp - 273150000) / 1000000;
-	diff = temp - z->threshold;
-	if (diff < 0) diff = 0;
-
-	/* now adjust each fan to the new duty cycle */
-	for (i = 0; i < z->nfans; i++) {
-		if (z->fans[i] > 8) {
-			printf("wtf?!\n");
-			continue;
-		}
-		f = &sc->sc_fans[z->fans[i]];
-		speed = f->base_rpm + diff * f->step;
-		DPRINTF("diff %d base %d sp %d\n", diff, f->base_rpm, speed);
-		fcu_set_fan_rpm(sc, f, speed);
-	}
+	return 0;
 }
 
 static void
@@ -486,7 +489,7 @@ fcu_adjust(void *cookie)
 		iic_release_bus(sc->sc_i2c, 0);
 		sc->sc_pwm = FALSE;
 		for (i = 0; i < FCU_ZONE_COUNT; i++)
-			fcu_adjust_zone(sc, i);
+			fancontrol_adjust_zone(&sc->sc_zones[i]);
 		kpause("fanctrl", true, mstohz(sc->sc_pwm ? 1000 : 5000), NULL);
 	}
 	kthread_exit(0);

Added files:

Index: src/sys/arch/macppc/dev/fancontrol.c
diff -u /dev/null src/sys/arch/macppc/dev/fancontrol.c:1.1
--- /dev/null	Tue Jul 27 23:38:42 2021
+++ src/sys/arch/macppc/dev/fancontrol.c	Tue Jul 27 23:38:42 2021
@@ -0,0 +1,77 @@
+/* $NetBSD: fancontrol.c,v 1.1 2021/07/27 23:38:42 macallan Exp $ */
+
+/*-
+ * Copyright (c) 2018 Michael Lorenz
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: fancontrol.c,v 1.1 2021/07/27 23:38:42 macallan Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/bus.h>
+#include <dev/sysmon/sysmonvar.h>
+
+#include <macppc/dev/fancontrolvar.h>
+#include "opt_fancontrol.h"
+
+#ifdef FANCONTROL_DEBUG
+#define DPRINTF printf
+#else
+#define DPRINTF while (0) printf
+#endif
+
+int 
+fancontrol_adjust_zone(fancontrol_zone_t *z)
+{
+	int temp, i, speed, diff, step;
+	
+	if (z->nfans <= 0)
+		return -1;
+
+	temp = sysmon_envsys_get_max_value(z->filter, true);
+	if (temp == 0) {
+		/* no sensor data - leave fan alone */
+		DPRINTF("nodata\n");
+		return -1;
+	}
+
+	temp = (temp - 273150000) / 1000000;
+	diff = temp - z->Tmin;
+	DPRINTF("%s %d %d\n", z->name, temp, z->Tmin);
+	if (diff < 0) diff = 0;
+	diff = (100 * diff) / (z->Tmax - z->Tmin);
+
+	/* now adjust each fan to the new duty cycle */
+	for (i = 0; i < z->nfans; i++) {
+		step = (z->fans[i].max_rpm - z->fans[i].min_rpm) / 100;
+		speed = z->fans[i].min_rpm + diff * step;
+		DPRINTF("diff %d base %d %d sp %d\n", diff, z->fans[i].min_rpm, z->fans[i].max_rpm, speed);
+		z->set_rpm(z->cookie, z->fans[i].num, speed);
+	}
+	return 0;
+}
Index: src/sys/arch/macppc/dev/fancontrolvar.h
diff -u /dev/null src/sys/arch/macppc/dev/fancontrolvar.h:1.1
--- /dev/null	Tue Jul 27 23:38:42 2021
+++ src/sys/arch/macppc/dev/fancontrolvar.h	Tue Jul 27 23:38:42 2021
@@ -0,0 +1,52 @@
+/* $NetBSD: fancontrolvar.h,v 1.1 2021/07/27 23:38:42 macallan Exp $ */
+
+/*-
+ * Copyright (c) 2021 Michael Lorenz
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FANCONTROLVAR_H
+#define FANCONTROLVAR_H
+
+#define FANCONTROL_MAX_FANS 10
+
+typedef struct _fancontrol_fan_data {
+	const char *name;
+	int num, min_rpm, max_rpm;
+} fancontrol_fan_data;
+
+typedef struct _fancontrol_zone {
+	void *cookie;
+	const char *name;
+	bool (*filter)(const envsys_data_t *);
+	int (*get_rpm)(void *, int);
+	int (*set_rpm)(void *, int, int);
+	int nfans;
+	fancontrol_fan_data fans[FANCONTROL_MAX_FANS];
+	int Tmin, Tmax;		/* temperature range in this zone */
+} fancontrol_zone_t; 
+
+int fancontrol_adjust_zone(fancontrol_zone_t *);
+
+#endif /* FANCONTROLVAR_H */

Reply via email to