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 */