* [PATCH 1/5] Update drivers names to the ones invoked by i2c-powermac
2014-08-09 6:49 [PATCH][v5] therm_windtunnel does not work properly on PowerMac G4 Goffredo Baroncelli
@ 2014-08-09 6:49 ` Goffredo Baroncelli
2014-08-09 6:50 ` [PATCH 2/5] Remove attach_method because un-used Goffredo Baroncelli
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Goffredo Baroncelli @ 2014-08-09 6:49 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: LKML, Jean Delvare, Guenter Roeck, Goffredo Baroncelli
Update drivers names to the ones invoked by i2c-powermac:
- therm_ds1775 -> MAC,ds1775
- therm_adm1030 -> MAC,adm1030
The background fan control loop is started from
the devices probing methods.
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
---
drivers/macintosh/therm_windtunnel.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 3b4a157..a64a06f 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -334,6 +334,23 @@ do_attach( struct i2c_adapter *adapter )
return 0;
}
+static void
+try_start_control_loop(void)
+{
+
+ mutex_lock(&x.lock);
+ if (!x.thermostat || !x.fan || x.running) {
+ mutex_unlock(&x.lock);
+ return;
+ }
+
+ x.running = 1;
+ mutex_unlock(&x.lock);
+
+ x.poll_task = kthread_run(control_loop, NULL, "g4fand");
+
+}
+
static int
do_remove(struct i2c_client *client)
{
@@ -364,6 +381,7 @@ attach_fan( struct i2c_client *cl )
printk("ADM1030 fan controller [@%02x]\n", cl->addr );
x.fan = cl;
+ try_start_control_loop();
out:
return 0;
}
@@ -397,6 +415,7 @@ attach_thermostat( struct i2c_client *cl )
x.overheat_temp = os_temp;
x.overheat_hyst = hyst_temp;
x.thermostat = cl;
+ try_start_control_loop();
out:
return 0;
}
@@ -404,8 +423,8 @@ out:
enum chip { ds1775, adm1030 };
static const struct i2c_device_id therm_windtunnel_id[] = {
- { "therm_ds1775", ds1775 },
- { "therm_adm1030", adm1030 },
+ { "MAC,ds1775", ds1775 },
+ { "MAC,adm1030", adm1030 },
{ }
};
--
2.1.0.rc1
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 2/5] Remove attach_method because un-used
2014-08-09 6:49 [PATCH][v5] therm_windtunnel does not work properly on PowerMac G4 Goffredo Baroncelli
2014-08-09 6:49 ` [PATCH 1/5] Update drivers names to the ones invoked by i2c-powermac Goffredo Baroncelli
@ 2014-08-09 6:50 ` Goffredo Baroncelli
2014-08-09 6:50 ` [PATCH 3/5] Add the "verbose" module option Goffredo Baroncelli
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Goffredo Baroncelli @ 2014-08-09 6:50 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: LKML, Jean Delvare, Guenter Roeck, Goffredo Baroncelli
Remove attach_method because i2c-powermac is
in charge to instantiate the driver directly.
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
---
drivers/macintosh/therm_windtunnel.c | 35 -----------------------------------
1 file changed, 35 deletions(-)
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index a64a06f..1e50455 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -300,40 +300,6 @@ static int control_loop(void *dummy)
/* i2c probing and setup */
/************************************************************************/
-static int
-do_attach( struct i2c_adapter *adapter )
-{
- /* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
- static const unsigned short scan_ds1775[] = {
- 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
- I2C_CLIENT_END
- };
- static const unsigned short scan_adm1030[] = {
- 0x2c, 0x2d, 0x2e, 0x2f,
- I2C_CLIENT_END
- };
-
- if( strncmp(adapter->name, "uni-n", 5) )
- return 0;
-
- if( !x.running ) {
- struct i2c_board_info info;
-
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "therm_ds1775", I2C_NAME_SIZE);
- i2c_new_probed_device(adapter, &info, scan_ds1775, NULL);
-
- strlcpy(info.type, "therm_adm1030", I2C_NAME_SIZE);
- i2c_new_probed_device(adapter, &info, scan_adm1030, NULL);
-
- if( x.thermostat && x.fan ) {
- x.running = 1;
- x.poll_task = kthread_run(control_loop, NULL, "g4fand");
- }
- }
- return 0;
-}
-
static void
try_start_control_loop(void)
{
@@ -450,7 +416,6 @@ static struct i2c_driver g4fan_driver = {
.driver = {
.name = "therm_windtunnel",
},
- .attach_adapter = do_attach,
.probe = do_probe,
.remove = do_remove,
.id_table = therm_windtunnel_id,
--
2.1.0.rc1
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 3/5] Add the "verbose" module option.
2014-08-09 6:49 [PATCH][v5] therm_windtunnel does not work properly on PowerMac G4 Goffredo Baroncelli
2014-08-09 6:49 ` [PATCH 1/5] Update drivers names to the ones invoked by i2c-powermac Goffredo Baroncelli
2014-08-09 6:50 ` [PATCH 2/5] Remove attach_method because un-used Goffredo Baroncelli
@ 2014-08-09 6:50 ` Goffredo Baroncelli
2014-08-09 6:50 ` [PATCH 4/5] Return the fan speed via sysfs Goffredo Baroncelli
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Goffredo Baroncelli @ 2014-08-09 6:50 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: LKML, Jean Delvare, Guenter Roeck, Goffredo Baroncelli
Add a "verbose" option to control the message in the kernel log
verbose = 0 no message
verbose = 1 log only the fan speed changes
verbose = 2 log the fan speed changes and the temperature changes
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
---
drivers/macintosh/therm_windtunnel.c | 38 +++++++++++++++++++++++-------------
1 file changed, 24 insertions(+), 14 deletions(-)
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 1e50455..68f1067 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -44,7 +44,9 @@
#include <asm/sections.h>
#include <asm/macio.h>
-#define LOG_TEMP 0 /* continuously log temperature */
+static int verbose = 1;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "Verbosity level: 0=silent, 1=log the fan tuning, 2=log the temperature");
static struct {
volatile int running;
@@ -157,10 +159,6 @@ tune_fan( int fan_setting )
/* write_reg( x.fan, 0x24, val, 1 ); */
write_reg( x.fan, 0x25, val, 1 );
write_reg( x.fan, 0x20, 0, 1 );
- print_temp("CPU-temp: ", x.temp );
- if( x.casetemp )
- print_temp(", Case: ", x.casetemp );
- printk(", Fan: %d (tuned %+d)\n", 11-fan_setting, x.fan_level-fan_setting );
x.fan_level = fan_setting;
}
@@ -168,7 +166,7 @@ tune_fan( int fan_setting )
static void
poll_temp( void )
{
- int temp, i, level, casetemp;
+ int temp, i, level, casetemp, tempchanged;
temp = read_reg( x.thermostat, 0, 2 );
@@ -179,14 +177,6 @@ poll_temp( void )
casetemp = read_reg(x.fan, 0x0b, 1) << 8;
casetemp |= (read_reg(x.fan, 0x06, 1) & 0x7) << 5;
- if( LOG_TEMP && x.temp != temp ) {
- print_temp("CPU-temp: ", temp );
- print_temp(", Case: ", casetemp );
- printk(", Fan: %d\n", 11-x.fan_level );
- }
- x.temp = temp;
- x.casetemp = casetemp;
-
level = -1;
for( i=0; (temp & 0xffff) > fan_table[i].temp ; i++ )
;
@@ -200,6 +190,26 @@ poll_temp( void )
level = fan_table[i].fan_up_setting;
x.upind = i;
+ /*
+ * if verbose >=1 log each fan tuning
+ * if verbose >=2 log each cpu temperature change
+ */
+ tempchanged = x.temp != temp || x.casetemp != casetemp;
+ if ((verbose > 1 && tempchanged) ||
+ (verbose > 0 && level >= 0)) {
+ print_temp(KERN_INFO "CPU-temp: ", temp);
+ if (casetemp)
+ print_temp(", Case: ", casetemp);
+ if (level >= 0)
+ printk(", Fan: %d (tuned %+d)\n", 11-level,
+ x.fan_level-level);
+ else
+ printk(", Fan: %d\n", 11-x.fan_level);
+ }
+
+ x.temp = temp;
+ x.casetemp = casetemp;
+
if( level >= 0 )
tune_fan( level );
}
--
2.1.0.rc1
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 4/5] Return the fan speed via sysfs
2014-08-09 6:49 [PATCH][v5] therm_windtunnel does not work properly on PowerMac G4 Goffredo Baroncelli
` (2 preceding siblings ...)
2014-08-09 6:50 ` [PATCH 3/5] Add the "verbose" module option Goffredo Baroncelli
@ 2014-08-09 6:50 ` Goffredo Baroncelli
2014-08-09 6:50 ` [PATCH 5/5] Export the temperatures via hwmon Goffredo Baroncelli
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Goffredo Baroncelli @ 2014-08-09 6:50 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: LKML, Jean Delvare, Guenter Roeck, Goffredo Baroncelli
Return the fan speed via sysfs:
/sys/devices/temperature/fan_level
This patch is extracted from a Bryan Christianson's bigger one (see
debian bug #741663)
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
---
drivers/macintosh/therm_windtunnel.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 68f1067..30a6588 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -109,9 +109,15 @@ show_case_temperature( struct device *dev, struct device_attribute *attr, char *
return sprintf(buf, "%d.%d\n", x.casetemp>>8, (x.casetemp & 255)*10/256 );
}
+static ssize_t
+show_fan_level(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", 11 - x.fan_level);
+}
+
static DEVICE_ATTR(cpu_temperature, S_IRUGO, show_cpu_temperature, NULL );
static DEVICE_ATTR(case_temperature, S_IRUGO, show_case_temperature, NULL );
-
+static DEVICE_ATTR(fan_level, S_IRUGO, show_fan_level, NULL);
/************************************************************************/
@@ -264,6 +270,7 @@ setup_hardware( void )
err = device_create_file( &x.of_dev->dev, &dev_attr_cpu_temperature );
err |= device_create_file( &x.of_dev->dev, &dev_attr_case_temperature );
+ err |= device_create_file(&x.of_dev->dev, &dev_attr_fan_level);
if (err)
printk(KERN_WARNING
"Failed to create temperature attribute file(s).\n");
@@ -274,6 +281,7 @@ restore_regs( void )
{
device_remove_file( &x.of_dev->dev, &dev_attr_cpu_temperature );
device_remove_file( &x.of_dev->dev, &dev_attr_case_temperature );
+ device_remove_file(&x.of_dev->dev, &dev_attr_fan_level);
write_reg( x.fan, 0x01, x.r1, 1 );
write_reg( x.fan, 0x20, x.r20, 1 );
--
2.1.0.rc1
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 5/5] Export the temperatures via hwmon
2014-08-09 6:49 [PATCH][v5] therm_windtunnel does not work properly on PowerMac G4 Goffredo Baroncelli
` (3 preceding siblings ...)
2014-08-09 6:50 ` [PATCH 4/5] Return the fan speed via sysfs Goffredo Baroncelli
@ 2014-08-09 6:50 ` Goffredo Baroncelli
2014-08-27 8:55 ` [PATCH][v5] therm_windtunnel does not work properly on PowerMac G4 Goffredo Baroncelli
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Goffredo Baroncelli @ 2014-08-09 6:50 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: LKML, Jean Delvare, Guenter Roeck, Goffredo Baroncelli
Export the temperature via the hwmon subsystem.
See the list below for the sensors exported:
$ cd /sys/devices/temperature/hwmon/hwmon0
$ echo "name: $(cat name)"; for i in temp*; do echo "$i: $(cat $i)"; done
name: therm_windtunnel
temp1_input: 59312
temp1_label: CPU
temp2_input: 36750
temp2_label: Case
temp3_input: 37750
temp3_label: Case2
The Case2 temperature is the sensor temperature inside the adm1030.
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
---
drivers/macintosh/therm_windtunnel.c | 96 ++++++++++++++++++++++++++++++++++--
1 file changed, 92 insertions(+), 4 deletions(-)
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 30a6588..fd9061d 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -37,6 +37,8 @@
#include <linux/init.h>
#include <linux/kthread.h>
#include <linux/of_platform.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
#include <asm/prom.h>
#include <asm/machdep.h>
@@ -58,9 +60,12 @@ static struct {
struct i2c_client *thermostat;
struct i2c_client *fan;
+ struct device *hwmon;
+
int overheat_temp; /* 100% fan at this temp */
int overheat_hyst;
int temp;
+ int casetemp2;
int casetemp;
int fan_level; /* active fan_table setting */
@@ -120,6 +125,66 @@ static DEVICE_ATTR(case_temperature, S_IRUGO, show_case_temperature, NULL );
static DEVICE_ATTR(fan_level, S_IRUGO, show_fan_level, NULL);
+static ssize_t
+show_temp1(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d%03d\n", x.temp>>8,
+ (x.temp & 0xff) * 1000 / 256);
+}
+
+static ssize_t
+show_temp1_label(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "CPU\n");
+}
+
+static ssize_t
+show_temp2(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d%03d\n", x.casetemp>>8,
+ (x.casetemp & 0xff) * 1000 / 256);
+}
+
+static ssize_t
+show_temp2_label(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "Case\n");
+}
+
+
+static ssize_t
+show_temp3(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d%03d\n", x.casetemp2>>8,
+ (x.casetemp2 & 0xff) * 1000 / 256);
+}
+
+static ssize_t
+show_temp3_label(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "Case2\n");
+}
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL);
+static DEVICE_ATTR(temp1_label, S_IRUGO, show_temp1_label, NULL);
+static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp2, NULL);
+static DEVICE_ATTR(temp2_label, S_IRUGO, show_temp2_label, NULL);
+static DEVICE_ATTR(temp3_input, S_IRUGO, show_temp3, NULL);
+static DEVICE_ATTR(temp3_label, S_IRUGO, show_temp3_label, NULL);
+
+static struct attribute *therm_windtunnel_attrs[] = {
+ &dev_attr_temp1_input.attr,
+ &dev_attr_temp1_label.attr,
+ &dev_attr_temp2_input.attr,
+ &dev_attr_temp2_label.attr,
+ &dev_attr_temp3_input.attr,
+ &dev_attr_temp3_label.attr,
+
+ NULL,
+};
+
+ATTRIBUTE_GROUPS(therm_windtunnel);
+
/************************************************************************/
/* controller thread */
/************************************************************************/
@@ -172,16 +237,23 @@ tune_fan( int fan_setting )
static void
poll_temp( void )
{
- int temp, i, level, casetemp, tempchanged;
+ int temp, i, level, casetemp, tempchanged, casetemp2, reg06;
+ /* temperature read from ds1775 */
temp = read_reg( x.thermostat, 0, 2 );
/* this actually occurs when the computer is loaded */
if( temp < 0 )
return;
- casetemp = read_reg(x.fan, 0x0b, 1) << 8;
- casetemp |= (read_reg(x.fan, 0x06, 1) & 0x7) << 5;
+ /*
+ * temperatures read from the adm1030
+ * casetemp is the external temperature sensor
+ * casetemp2 is the internal temperature sensor
+ */
+ reg06 = read_reg(x.fan, 0x06, 1);
+ casetemp = (read_reg(x.fan, 0x0b, 1) << 8) | (reg06 & 0x07 << 5);
+ casetemp2 = (read_reg(x.fan, 0x0a, 1) << 8) | (reg06 & 0xc0);
level = -1;
for( i=0; (temp & 0xffff) > fan_table[i].temp ; i++ )
@@ -200,12 +272,15 @@ poll_temp( void )
* if verbose >=1 log each fan tuning
* if verbose >=2 log each cpu temperature change
*/
- tempchanged = x.temp != temp || x.casetemp != casetemp;
+ tempchanged = x.temp != temp || x.casetemp != casetemp ||
+ x.casetemp2 != casetemp2;
if ((verbose > 1 && tempchanged) ||
(verbose > 0 && level >= 0)) {
print_temp(KERN_INFO "CPU-temp: ", temp);
if (casetemp)
print_temp(", Case: ", casetemp);
+ if (casetemp2)
+ print_temp(", Case2: ", casetemp2);
if (level >= 0)
printk(", Fan: %d (tuned %+d)\n", 11-level,
x.fan_level-level);
@@ -215,6 +290,7 @@ poll_temp( void )
x.temp = temp;
x.casetemp = casetemp;
+ x.casetemp2 = casetemp2;
if( level >= 0 )
tune_fan( level );
@@ -274,11 +350,23 @@ setup_hardware( void )
if (err)
printk(KERN_WARNING
"Failed to create temperature attribute file(s).\n");
+
+ x.hwmon = hwmon_device_register_with_groups(&x.of_dev->dev,
+ "therm_windtunnel", NULL,
+ therm_windtunnel_groups);
+ if (IS_ERR(x.hwmon)) {
+ dev_warn(&x.of_dev->dev, "Failed to create the hwmon device\n");
+ x.hwmon = NULL;
+ }
}
static void
restore_regs( void )
{
+ if (x.hwmon)
+ hwmon_device_unregister(x.hwmon);
+ x.hwmon = NULL;
+
device_remove_file( &x.of_dev->dev, &dev_attr_cpu_temperature );
device_remove_file( &x.of_dev->dev, &dev_attr_case_temperature );
device_remove_file(&x.of_dev->dev, &dev_attr_fan_level);
--
2.1.0.rc1
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH][v5] therm_windtunnel does not work properly on PowerMac G4
2014-08-09 6:49 [PATCH][v5] therm_windtunnel does not work properly on PowerMac G4 Goffredo Baroncelli
` (4 preceding siblings ...)
2014-08-09 6:50 ` [PATCH 5/5] Export the temperatures via hwmon Goffredo Baroncelli
@ 2014-08-27 8:55 ` Goffredo Baroncelli
2014-11-11 13:25 ` [RESEND][PATCH 1/5] Update drivers names to the ones invoked by i2c-powermac Goffredo Baroncelli
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Goffredo Baroncelli @ 2014-08-27 8:55 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: Goffredo Baroncelli, LKML, Jean Delvare, Guenter Roeck
Hi Benjamin,
do you have any feedback about this ? Do you think that it would be possible
to include these patches in a next pull-for-linus ?
Let me know, if you want other changes.
BR
G.Baroncelli
On 08/09/2014 08:49 AM, Goffredo Baroncelli wrote:
> Hi All,
>
> On a PowerMac G4 I noticed that between the kernel v3.2 and v3.14 I lost
> the fan management.
>
> I found on internet other references to this kind of problem [2]
>
>
> **How reproduce:
> - booting with the kernel 3.2, the fan is "quite" silent.
> The module therm_windtunnel is loaded and in the log there are
> lines like:
>
> [ 1342.614956] CPU-temp: 58.7 C, Case: 33.7 C, Fan: 5 (tuned +0)
> [ 1390.637793] CPU-temp: 58.6 C, Case: 33.6 C, Fan: 5
>
> I had also access to the temperature via the sysfs files:
> /sys/devices/temperature/case_temperature
> /sys/devices/temperature/cpu_temperature
>
>
> - booting with the kernel 3.14, the fan is very loud. The module
> therm_windtunnel is not loaded. In the log there aren't any message
> related to the temperature. The sysfs entries don't exist.
>
>
> ** Analysis
> In these Apple machines the module i2c-powermac requires the
> i2c drivers provided by the module therm_windtunnel.
>
> Between the kernel v3.2 and v3.14 [1] some patches changed the
> driver name requested by the i2c-powermac module,
> so the therm_windtunnel modules is not instantiated anymore.
>
>
> ** Proposed solution
> In the following emails I sent you 5 patches to solve this
> problem (tested on my PowerMac G4). Only the first two are strictly
> related to the problem, the others three may be skipped.
>
> 1) change the driver name
> therm_ds1775 -> MAC,ds1775
> therm_adm1030 -> MAC,adm1030
> so the i2c driver are instantiated by i2c-powermac
>
> 2) remove the (unused) method do_attach from the i2c-driver
>
> 3) add a parameter to the therm_windtunnel module
> to control the kernel log message
>
> 4) export the fan speed via sysfs
>
> 5) export the temperature via the hwmon subsistem
>
> The patch 1) solve the problem. The patch 2) is a small cleanup.
> The patch 3) allow a better control of the log in dmesg.
> The patch 4) is copyied from the Bryan Christianson's patch (see
> debian bug #741663)
> The patch 5) export the temperatures via hwmon, a more standard
> interface. I also added the internal sensor of the adm1030, which
> I called "Case2", because it measure the same temperature /+/- 1C)
> of the "Case" sensor.
>
> I have to highlight that I tried to export also the fan speed,
> but I was unable to get it, without affecting the fan speed:
> when I set the bit 2 (TACH 1 En) of the register 0x1
> (Configuration 2), it seemed that the speed every 4/5s dropped,
> then it raised quickly....
> I didn't perform other test to avoid damages.
>
> Could you be so kindly to apply these patches ?
>
> PS:
> I am not LKML subscriber, so please put me in CC in case of reply.
>
> BR
> G.Baroncelli
>
> Changelog:
> v1: 2014/07/30
> - first issue
> v2: 2014/08/01
> - protect with a mutex the check before starting the fan
> daemon (to protect from parallel drivers instantation)
> - reduce the number of module parameters to 1 as suggested by
> Jean Delvare
> - export the fan speed via sysfs
> v3: 2014/08/06
> - export the temperatures via hwmon
> - export the internal temperature sensor of the adm1030
> - little cleanup due to the suggestion of checkpatch.pl (
> and Jean Delvare)
> - removed the "(tune +0)" in the log.
> v4: 2014/08/07
> - accepted some small cleanup suggestions from Jean Delvare
> - replaced SENSOR_DEVICE_ATTR with DEVICE_ATTR, and
> added ATTRIBUTE_GROUPS() use
> v5: 2014/08/09
> - hanlde the return error of
> hwmon_device_register_with_groups() with IS_ERR() "macro"
> - better explanation about the source of patch #4
>
> [1] I think that the guilty commit is
> commit 81e5d8646ff6bf323dddcf172aa3cef84468fa12
> Author: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Date: Wed Apr 18 22:16:42 2012 +0000
> i2c/powermac: Register i2c devices from device-tree
>
> This causes i2c-powermac to register i2c devices exposed in the
> device-tree, enabling new-style probing of devices.
>
> Note that we prefix the IDs with "MAC," in order to prevent the
> generic drivers from matching. This is done on purpose as we only
> want drivers specifically tested/designed to operate on powermacs
> to match.
>
> This removes the special case we had for the AMS driver, and updates
> the driver's match table instead.
>
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>
> [2] There is the debian bug #741663 which highlight the same problem. In
> the bug discussion there is a patch like the my ones.
>
> See also
> https://lists.ozlabs.org/pipermail/linuxppc-dev/2012-July/099561.html
>
--
gpg @keyserver.linux.it: Goffredo Baroncelli (kreijackATinwind.it>
Key fingerprint BBF5 1610 0B64 DAC6 5F7D 17B2 0EDA 9B37 8B82 E0B5
^ permalink raw reply [flat|nested] 12+ messages in thread* [RESEND][PATCH 1/5] Update drivers names to the ones invoked by i2c-powermac
2014-08-09 6:49 [PATCH][v5] therm_windtunnel does not work properly on PowerMac G4 Goffredo Baroncelli
` (5 preceding siblings ...)
2014-08-27 8:55 ` [PATCH][v5] therm_windtunnel does not work properly on PowerMac G4 Goffredo Baroncelli
@ 2014-11-11 13:25 ` Goffredo Baroncelli
2014-11-11 13:25 ` [RESEND][PATCH 2/5] Remove attach_method because un-used Goffredo Baroncelli
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Goffredo Baroncelli @ 2014-11-11 13:25 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: LKML, Jean Delvare, Guenter Roeck, Goffredo Baroncelli
Update drivers names to the ones invoked by i2c-powermac:
- therm_ds1775 -> MAC,ds1775
- therm_adm1030 -> MAC,adm1030
The background fan control loop is started from
the devices probing methods.
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
---
drivers/macintosh/therm_windtunnel.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 3b4a157..a64a06f 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -334,6 +334,23 @@ do_attach( struct i2c_adapter *adapter )
return 0;
}
+static void
+try_start_control_loop(void)
+{
+
+ mutex_lock(&x.lock);
+ if (!x.thermostat || !x.fan || x.running) {
+ mutex_unlock(&x.lock);
+ return;
+ }
+
+ x.running = 1;
+ mutex_unlock(&x.lock);
+
+ x.poll_task = kthread_run(control_loop, NULL, "g4fand");
+
+}
+
static int
do_remove(struct i2c_client *client)
{
@@ -364,6 +381,7 @@ attach_fan( struct i2c_client *cl )
printk("ADM1030 fan controller [@%02x]\n", cl->addr );
x.fan = cl;
+ try_start_control_loop();
out:
return 0;
}
@@ -397,6 +415,7 @@ attach_thermostat( struct i2c_client *cl )
x.overheat_temp = os_temp;
x.overheat_hyst = hyst_temp;
x.thermostat = cl;
+ try_start_control_loop();
out:
return 0;
}
@@ -404,8 +423,8 @@ out:
enum chip { ds1775, adm1030 };
static const struct i2c_device_id therm_windtunnel_id[] = {
- { "therm_ds1775", ds1775 },
- { "therm_adm1030", adm1030 },
+ { "MAC,ds1775", ds1775 },
+ { "MAC,adm1030", adm1030 },
{ }
};
--
2.1.0.rc1
^ permalink raw reply related [flat|nested] 12+ messages in thread* [RESEND][PATCH 2/5] Remove attach_method because un-used
2014-08-09 6:49 [PATCH][v5] therm_windtunnel does not work properly on PowerMac G4 Goffredo Baroncelli
` (6 preceding siblings ...)
2014-11-11 13:25 ` [RESEND][PATCH 1/5] Update drivers names to the ones invoked by i2c-powermac Goffredo Baroncelli
@ 2014-11-11 13:25 ` Goffredo Baroncelli
2014-11-11 13:25 ` [RESEND][PATCH 3/5] Add the "verbose" module option Goffredo Baroncelli
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Goffredo Baroncelli @ 2014-11-11 13:25 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: LKML, Jean Delvare, Guenter Roeck, Goffredo Baroncelli
Remove attach_method because i2c-powermac is
in charge to instantiate the driver directly.
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
---
drivers/macintosh/therm_windtunnel.c | 35 -----------------------------------
1 file changed, 35 deletions(-)
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index a64a06f..1e50455 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -300,40 +300,6 @@ static int control_loop(void *dummy)
/* i2c probing and setup */
/************************************************************************/
-static int
-do_attach( struct i2c_adapter *adapter )
-{
- /* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
- static const unsigned short scan_ds1775[] = {
- 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
- I2C_CLIENT_END
- };
- static const unsigned short scan_adm1030[] = {
- 0x2c, 0x2d, 0x2e, 0x2f,
- I2C_CLIENT_END
- };
-
- if( strncmp(adapter->name, "uni-n", 5) )
- return 0;
-
- if( !x.running ) {
- struct i2c_board_info info;
-
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "therm_ds1775", I2C_NAME_SIZE);
- i2c_new_probed_device(adapter, &info, scan_ds1775, NULL);
-
- strlcpy(info.type, "therm_adm1030", I2C_NAME_SIZE);
- i2c_new_probed_device(adapter, &info, scan_adm1030, NULL);
-
- if( x.thermostat && x.fan ) {
- x.running = 1;
- x.poll_task = kthread_run(control_loop, NULL, "g4fand");
- }
- }
- return 0;
-}
-
static void
try_start_control_loop(void)
{
@@ -450,7 +416,6 @@ static struct i2c_driver g4fan_driver = {
.driver = {
.name = "therm_windtunnel",
},
- .attach_adapter = do_attach,
.probe = do_probe,
.remove = do_remove,
.id_table = therm_windtunnel_id,
--
2.1.0.rc1
^ permalink raw reply related [flat|nested] 12+ messages in thread* [RESEND][PATCH 3/5] Add the "verbose" module option.
2014-08-09 6:49 [PATCH][v5] therm_windtunnel does not work properly on PowerMac G4 Goffredo Baroncelli
` (7 preceding siblings ...)
2014-11-11 13:25 ` [RESEND][PATCH 2/5] Remove attach_method because un-used Goffredo Baroncelli
@ 2014-11-11 13:25 ` Goffredo Baroncelli
2014-11-11 13:25 ` [RESEND][PATCH 4/5] Return the fan speed via sysfs Goffredo Baroncelli
2014-11-11 13:25 ` [RESEND][PATCH 5/5] Export the temperatures via hwmon Goffredo Baroncelli
10 siblings, 0 replies; 12+ messages in thread
From: Goffredo Baroncelli @ 2014-11-11 13:25 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: LKML, Jean Delvare, Guenter Roeck, Goffredo Baroncelli
Add a "verbose" option to control the message in the kernel log
verbose = 0 no message
verbose = 1 log only the fan speed changes
verbose = 2 log the fan speed changes and the temperature changes
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
---
drivers/macintosh/therm_windtunnel.c | 38 +++++++++++++++++++++++-------------
1 file changed, 24 insertions(+), 14 deletions(-)
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 1e50455..68f1067 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -44,7 +44,9 @@
#include <asm/sections.h>
#include <asm/macio.h>
-#define LOG_TEMP 0 /* continuously log temperature */
+static int verbose = 1;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "Verbosity level: 0=silent, 1=log the fan tuning, 2=log the temperature");
static struct {
volatile int running;
@@ -157,10 +159,6 @@ tune_fan( int fan_setting )
/* write_reg( x.fan, 0x24, val, 1 ); */
write_reg( x.fan, 0x25, val, 1 );
write_reg( x.fan, 0x20, 0, 1 );
- print_temp("CPU-temp: ", x.temp );
- if( x.casetemp )
- print_temp(", Case: ", x.casetemp );
- printk(", Fan: %d (tuned %+d)\n", 11-fan_setting, x.fan_level-fan_setting );
x.fan_level = fan_setting;
}
@@ -168,7 +166,7 @@ tune_fan( int fan_setting )
static void
poll_temp( void )
{
- int temp, i, level, casetemp;
+ int temp, i, level, casetemp, tempchanged;
temp = read_reg( x.thermostat, 0, 2 );
@@ -179,14 +177,6 @@ poll_temp( void )
casetemp = read_reg(x.fan, 0x0b, 1) << 8;
casetemp |= (read_reg(x.fan, 0x06, 1) & 0x7) << 5;
- if( LOG_TEMP && x.temp != temp ) {
- print_temp("CPU-temp: ", temp );
- print_temp(", Case: ", casetemp );
- printk(", Fan: %d\n", 11-x.fan_level );
- }
- x.temp = temp;
- x.casetemp = casetemp;
-
level = -1;
for( i=0; (temp & 0xffff) > fan_table[i].temp ; i++ )
;
@@ -200,6 +190,26 @@ poll_temp( void )
level = fan_table[i].fan_up_setting;
x.upind = i;
+ /*
+ * if verbose >=1 log each fan tuning
+ * if verbose >=2 log each cpu temperature change
+ */
+ tempchanged = x.temp != temp || x.casetemp != casetemp;
+ if ((verbose > 1 && tempchanged) ||
+ (verbose > 0 && level >= 0)) {
+ print_temp(KERN_INFO "CPU-temp: ", temp);
+ if (casetemp)
+ print_temp(", Case: ", casetemp);
+ if (level >= 0)
+ printk(", Fan: %d (tuned %+d)\n", 11-level,
+ x.fan_level-level);
+ else
+ printk(", Fan: %d\n", 11-x.fan_level);
+ }
+
+ x.temp = temp;
+ x.casetemp = casetemp;
+
if( level >= 0 )
tune_fan( level );
}
--
2.1.0.rc1
^ permalink raw reply related [flat|nested] 12+ messages in thread* [RESEND][PATCH 4/5] Return the fan speed via sysfs
2014-08-09 6:49 [PATCH][v5] therm_windtunnel does not work properly on PowerMac G4 Goffredo Baroncelli
` (8 preceding siblings ...)
2014-11-11 13:25 ` [RESEND][PATCH 3/5] Add the "verbose" module option Goffredo Baroncelli
@ 2014-11-11 13:25 ` Goffredo Baroncelli
2014-11-11 13:25 ` [RESEND][PATCH 5/5] Export the temperatures via hwmon Goffredo Baroncelli
10 siblings, 0 replies; 12+ messages in thread
From: Goffredo Baroncelli @ 2014-11-11 13:25 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: LKML, Jean Delvare, Guenter Roeck, Goffredo Baroncelli
Return the fan speed via sysfs:
/sys/devices/temperature/fan_level
This patch is extracted from a Bryan Christianson's bigger one (see
debian bug #741663)
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
---
drivers/macintosh/therm_windtunnel.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 68f1067..30a6588 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -109,9 +109,15 @@ show_case_temperature( struct device *dev, struct device_attribute *attr, char *
return sprintf(buf, "%d.%d\n", x.casetemp>>8, (x.casetemp & 255)*10/256 );
}
+static ssize_t
+show_fan_level(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", 11 - x.fan_level);
+}
+
static DEVICE_ATTR(cpu_temperature, S_IRUGO, show_cpu_temperature, NULL );
static DEVICE_ATTR(case_temperature, S_IRUGO, show_case_temperature, NULL );
-
+static DEVICE_ATTR(fan_level, S_IRUGO, show_fan_level, NULL);
/************************************************************************/
@@ -264,6 +270,7 @@ setup_hardware( void )
err = device_create_file( &x.of_dev->dev, &dev_attr_cpu_temperature );
err |= device_create_file( &x.of_dev->dev, &dev_attr_case_temperature );
+ err |= device_create_file(&x.of_dev->dev, &dev_attr_fan_level);
if (err)
printk(KERN_WARNING
"Failed to create temperature attribute file(s).\n");
@@ -274,6 +281,7 @@ restore_regs( void )
{
device_remove_file( &x.of_dev->dev, &dev_attr_cpu_temperature );
device_remove_file( &x.of_dev->dev, &dev_attr_case_temperature );
+ device_remove_file(&x.of_dev->dev, &dev_attr_fan_level);
write_reg( x.fan, 0x01, x.r1, 1 );
write_reg( x.fan, 0x20, x.r20, 1 );
--
2.1.0.rc1
^ permalink raw reply related [flat|nested] 12+ messages in thread* [RESEND][PATCH 5/5] Export the temperatures via hwmon
2014-08-09 6:49 [PATCH][v5] therm_windtunnel does not work properly on PowerMac G4 Goffredo Baroncelli
` (9 preceding siblings ...)
2014-11-11 13:25 ` [RESEND][PATCH 4/5] Return the fan speed via sysfs Goffredo Baroncelli
@ 2014-11-11 13:25 ` Goffredo Baroncelli
10 siblings, 0 replies; 12+ messages in thread
From: Goffredo Baroncelli @ 2014-11-11 13:25 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: LKML, Jean Delvare, Guenter Roeck, Goffredo Baroncelli
Export the temperature via the hwmon subsystem.
See the list below for the sensors exported:
$ cd /sys/devices/temperature/hwmon/hwmon0
$ echo "name: $(cat name)"; for i in temp*; do echo "$i: $(cat $i)"; done
name: therm_windtunnel
temp1_input: 59312
temp1_label: CPU
temp2_input: 36750
temp2_label: Case
temp3_input: 37750
temp3_label: Case2
The Case2 temperature is the sensor temperature inside the adm1030.
Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
---
drivers/macintosh/therm_windtunnel.c | 96 ++++++++++++++++++++++++++++++++++--
1 file changed, 92 insertions(+), 4 deletions(-)
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 30a6588..fd9061d 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -37,6 +37,8 @@
#include <linux/init.h>
#include <linux/kthread.h>
#include <linux/of_platform.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
#include <asm/prom.h>
#include <asm/machdep.h>
@@ -58,9 +60,12 @@ static struct {
struct i2c_client *thermostat;
struct i2c_client *fan;
+ struct device *hwmon;
+
int overheat_temp; /* 100% fan at this temp */
int overheat_hyst;
int temp;
+ int casetemp2;
int casetemp;
int fan_level; /* active fan_table setting */
@@ -120,6 +125,66 @@ static DEVICE_ATTR(case_temperature, S_IRUGO, show_case_temperature, NULL );
static DEVICE_ATTR(fan_level, S_IRUGO, show_fan_level, NULL);
+static ssize_t
+show_temp1(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d%03d\n", x.temp>>8,
+ (x.temp & 0xff) * 1000 / 256);
+}
+
+static ssize_t
+show_temp1_label(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "CPU\n");
+}
+
+static ssize_t
+show_temp2(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d%03d\n", x.casetemp>>8,
+ (x.casetemp & 0xff) * 1000 / 256);
+}
+
+static ssize_t
+show_temp2_label(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "Case\n");
+}
+
+
+static ssize_t
+show_temp3(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d%03d\n", x.casetemp2>>8,
+ (x.casetemp2 & 0xff) * 1000 / 256);
+}
+
+static ssize_t
+show_temp3_label(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "Case2\n");
+}
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL);
+static DEVICE_ATTR(temp1_label, S_IRUGO, show_temp1_label, NULL);
+static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp2, NULL);
+static DEVICE_ATTR(temp2_label, S_IRUGO, show_temp2_label, NULL);
+static DEVICE_ATTR(temp3_input, S_IRUGO, show_temp3, NULL);
+static DEVICE_ATTR(temp3_label, S_IRUGO, show_temp3_label, NULL);
+
+static struct attribute *therm_windtunnel_attrs[] = {
+ &dev_attr_temp1_input.attr,
+ &dev_attr_temp1_label.attr,
+ &dev_attr_temp2_input.attr,
+ &dev_attr_temp2_label.attr,
+ &dev_attr_temp3_input.attr,
+ &dev_attr_temp3_label.attr,
+
+ NULL,
+};
+
+ATTRIBUTE_GROUPS(therm_windtunnel);
+
/************************************************************************/
/* controller thread */
/************************************************************************/
@@ -172,16 +237,23 @@ tune_fan( int fan_setting )
static void
poll_temp( void )
{
- int temp, i, level, casetemp, tempchanged;
+ int temp, i, level, casetemp, tempchanged, casetemp2, reg06;
+ /* temperature read from ds1775 */
temp = read_reg( x.thermostat, 0, 2 );
/* this actually occurs when the computer is loaded */
if( temp < 0 )
return;
- casetemp = read_reg(x.fan, 0x0b, 1) << 8;
- casetemp |= (read_reg(x.fan, 0x06, 1) & 0x7) << 5;
+ /*
+ * temperatures read from the adm1030
+ * casetemp is the external temperature sensor
+ * casetemp2 is the internal temperature sensor
+ */
+ reg06 = read_reg(x.fan, 0x06, 1);
+ casetemp = (read_reg(x.fan, 0x0b, 1) << 8) | (reg06 & 0x07 << 5);
+ casetemp2 = (read_reg(x.fan, 0x0a, 1) << 8) | (reg06 & 0xc0);
level = -1;
for( i=0; (temp & 0xffff) > fan_table[i].temp ; i++ )
@@ -200,12 +272,15 @@ poll_temp( void )
* if verbose >=1 log each fan tuning
* if verbose >=2 log each cpu temperature change
*/
- tempchanged = x.temp != temp || x.casetemp != casetemp;
+ tempchanged = x.temp != temp || x.casetemp != casetemp ||
+ x.casetemp2 != casetemp2;
if ((verbose > 1 && tempchanged) ||
(verbose > 0 && level >= 0)) {
print_temp(KERN_INFO "CPU-temp: ", temp);
if (casetemp)
print_temp(", Case: ", casetemp);
+ if (casetemp2)
+ print_temp(", Case2: ", casetemp2);
if (level >= 0)
printk(", Fan: %d (tuned %+d)\n", 11-level,
x.fan_level-level);
@@ -215,6 +290,7 @@ poll_temp( void )
x.temp = temp;
x.casetemp = casetemp;
+ x.casetemp2 = casetemp2;
if( level >= 0 )
tune_fan( level );
@@ -274,11 +350,23 @@ setup_hardware( void )
if (err)
printk(KERN_WARNING
"Failed to create temperature attribute file(s).\n");
+
+ x.hwmon = hwmon_device_register_with_groups(&x.of_dev->dev,
+ "therm_windtunnel", NULL,
+ therm_windtunnel_groups);
+ if (IS_ERR(x.hwmon)) {
+ dev_warn(&x.of_dev->dev, "Failed to create the hwmon device\n");
+ x.hwmon = NULL;
+ }
}
static void
restore_regs( void )
{
+ if (x.hwmon)
+ hwmon_device_unregister(x.hwmon);
+ x.hwmon = NULL;
+
device_remove_file( &x.of_dev->dev, &dev_attr_cpu_temperature );
device_remove_file( &x.of_dev->dev, &dev_attr_case_temperature );
device_remove_file(&x.of_dev->dev, &dev_attr_fan_level);
--
2.1.0.rc1
^ permalink raw reply related [flat|nested] 12+ messages in thread