apm821xx: WNDR4700: use upstream tc654 cooling devices

Upstream hwmon-maintainer had various comments about
the changes to the tc654 driver. These have been
addressed and the cooling device support is destined
for inclusion.

One of the comments was the change of the cooling states
scaling. No longer the driver uses the same values as the
hwmon interface, instead the states are now the 17 states
the tc654 supports.

Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
This commit is contained in:
Christian Lamparter 2022-02-12 19:53:37 +01:00
parent 2aa97ecb59
commit b0d5939b80
3 changed files with 90 additions and 83 deletions

View File

@ -0,0 +1,15 @@
#!/bin/sh /etc/rc.common
START=98
boot() {
# configuring onboard temp/fan controller to run the fan on its own
# for more information, please read https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
case $(board_name) in
netgear,wndr4700)
path_to_hwmon='/sys/devices/platform/plb/plb:opb/4ef600700.i2c/i2c-0/0-001b/hwmon/hwmon1'
echo 1 > "$path_to_hwmon/pwm1_enable"
;;
esac
}

View File

@ -105,32 +105,32 @@
map1 {
trip = <&cpu_alert1>;
cooling-device = <&fan0 1 76>;
cooling-device = <&fan0 1 1>;
};
map2 {
trip = <&cpu_alert2>;
cooling-device = <&fan0 77 101>;
cooling-device = <&fan0 2 4>;
};
map3 {
trip = <&cpu_alert3>;
cooling-device = <&fan0 102 147>;
cooling-device = <&fan0 4 8>;
};
map4 {
trip = <&cpu_alert4>;
cooling-device = <&fan0 148 207>;
cooling-device = <&fan0 9 12>;
};
map5 {
trip = <&cpu_alert5>;
cooling-device = <&fan0 208 231>;
cooling-device = <&fan0 13 15>;
};
map6 {
trip = <&cpu_alert6>;
cooling-device =<&fan0 232 THERMAL_NO_LIMIT>;
cooling-device =<&fan0 16 THERMAL_NO_LIMIT>;
};
};
};

View File

@ -1,16 +1,20 @@
From 9cb27801b5cbad2e1aaf45aac428cb2fac5e1372 Mon Sep 17 00:00:00 2001
From 4d49367c5303e3ebd17502a45b74de280f6be539 Mon Sep 17 00:00:00 2001
From: Christian Lamparter <chunkeey@gmail.com>
Date: Sun, 17 Dec 2017 17:29:13 +0100
Subject: [PATCH] hwmon: tc654: add thermal_cooling device
Date: Sun, 13 Feb 2022 01:47:33 +0100
Subject: hwmon: (tc654) Add thermal_cooling device support
This patch adds a thermaL_cooling device to the tc654 driver.
This allows the chip to be used for DT-based cooling.
Adds thermal_cooling device support to the tc654/tc655
driver. This make it possible to integrate it into a
device-tree supported thermal-zone node as a
cooling device.
I have been using this patch as part of the Netgear WNDR4700
Centria NAS Router support within OpenWrt since 2016.
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
Link: https://lore.kernel.org/r/20220213004733.2421193-1-chunkeey@gmail.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
drivers/hwmon/tc654.c | 103 +++++++++++++++++++++++++++++++++++-------
1 file changed, 86 insertions(+), 17 deletions(-)
--- a/drivers/hwmon/tc654.c
+++ b/drivers/hwmon/tc654.c
@@ -15,6 +15,7 @@
@ -21,44 +25,8 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
#include <linux/util_macros.h>
enum tc654_regs {
@@ -132,6 +133,9 @@ struct tc654_data {
* writable register used to control the duty
* cycle of the V OUT output.
*/
+
+ /* optional cooling device */
+ struct thermal_cooling_device *cdev;
};
/* helper to grab and cache data, at most one time per second */
@@ -367,36 +371,30 @@ static ssize_t pwm_mode_store(struct dev
static const int tc654_pwm_map[16] = { 77, 88, 102, 112, 124, 136, 148, 160,
172, 184, 196, 207, 219, 231, 243, 255};
+static int get_pwm(struct tc654_data *data)
+{
+ if (data->config & TC654_REG_CONFIG_SDM)
+ return 0;
+ else
+ return tc654_pwm_map[data->duty_cycle];
+}
+
static ssize_t pwm_show(struct device *dev, struct device_attribute *da,
char *buf)
{
struct tc654_data *data = tc654_update_client(dev);
- int pwm;
if (IS_ERR(data))
return PTR_ERR(data);
- if (data->config & TC654_REG_CONFIG_SDM)
- pwm = 0;
- else
- pwm = tc654_pwm_map[data->duty_cycle];
-
- return sprintf(buf, "%d\n", pwm);
+ return sprintf(buf, "%d\n", get_pwm(data));
@@ -384,28 +385,20 @@ static ssize_t pwm_show(struct device *d
return sprintf(buf, "%d\n", pwm);
}
-static ssize_t pwm_store(struct device *dev, struct device_attribute *da,
@ -77,8 +45,22 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
-
mutex_lock(&data->update_lock);
if (val == 0)
@@ -416,6 +414,22 @@ static ssize_t pwm_store(struct device *
- if (val == 0)
+ if (val == 0) {
data->config |= TC654_REG_CONFIG_SDM;
- else
+ data->duty_cycle = 0;
+ } else {
data->config &= ~TC654_REG_CONFIG_SDM;
-
- data->duty_cycle = find_closest(val, tc654_pwm_map,
- ARRAY_SIZE(tc654_pwm_map));
+ data->duty_cycle = val - 1;
+ }
ret = i2c_smbus_write_byte_data(client, TC654_REG_CONFIG, data->config);
if (ret < 0)
@@ -416,6 +409,24 @@ static ssize_t pwm_store(struct device *
out:
mutex_unlock(&data->update_lock);
@ -96,48 +78,60 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+ return -EINVAL;
+ if (val > 255)
+ return -EINVAL;
+ if (val > 0)
+ val = find_closest(val, tc654_pwm_map, ARRAY_SIZE(tc654_pwm_map)) + 1;
+
+ ret = _set_pwm(data, val);
return ret < 0 ? ret : count;
}
@@ -447,6 +461,47 @@ static struct attribute *tc654_attrs[] =
@@ -448,6 +459,58 @@ static struct attribute *tc654_attrs[] =
ATTRIBUTE_GROUPS(tc654);
+/* cooling device */
/*
+ * thermal cooling device functions
+ *
+ * Account for the "ShutDown Mode (SDM)" state by offsetting
+ * the 16 PWM duty cycle states by 1.
+ *
+ * State 0 = 0% PWM | Shutdown - Fan(s) are off
+ * State 1 = 30% PWM | duty_cycle = 0
+ * State 2 = ~35% PWM | duty_cycle = 1
+ * [...]
+ * State 15 = ~95% PWM | duty_cycle = 14
+ * State 16 = 100% PWM | duty_cycle = 15
+ */
+#define TC654_MAX_COOLING_STATE 16
+
+static int tc654_get_max_state(struct thermal_cooling_device *cdev,
+ unsigned long *state)
+static int tc654_get_max_state(struct thermal_cooling_device *cdev, unsigned long *state)
+{
+ *state = 255;
+ *state = TC654_MAX_COOLING_STATE;
+ return 0;
+}
+
+static int tc654_get_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long *state)
+static int tc654_get_cur_state(struct thermal_cooling_device *cdev, unsigned long *state)
+{
+ struct tc654_data *data = tc654_update_client(cdev->devdata);
+
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ *state = get_pwm(data);
+ if (data->config & TC654_REG_CONFIG_SDM)
+ *state = 0; /* FAN is off */
+ else
+ *state = data->duty_cycle + 1; /* offset PWM States by 1 */
+
+ return 0;
+}
+
+static int tc654_set_cur_state(struct thermal_cooling_device *cdev,
+ unsigned long state)
+static int tc654_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
+{
+ struct tc654_data *data = tc654_update_client(cdev->devdata);
+
+ if (IS_ERR(data))
+ return PTR_ERR(data);
+
+ if (state > 255)
+ return -EINVAL;
+
+ return _set_pwm(data, state);
+ return _set_pwm(data, clamp_val(state, 0, TC654_MAX_COOLING_STATE));
+}
+
+static const struct thermal_cooling_device_ops tc654_fan_cool_ops = {
@ -146,10 +140,11 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+ .set_cur_state = tc654_set_cur_state,
+};
+
/*
+/*
* device probe and removal
*/
@@ -477,7 +532,21 @@ static int tc654_probe(struct i2c_client
@@ -477,7 +540,18 @@ static int tc654_probe(struct i2c_client
hwmon_dev =
devm_hwmon_device_register_with_groups(dev, client->name, data,
tc654_groups);
@ -157,18 +152,15 @@ Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+ if (IS_ERR(hwmon_dev))
+ return PTR_ERR(hwmon_dev);
+
+#if IS_ENABLED(CONFIG_OF)
+ /* Optional cooling device register for Device tree platforms */
+ data->cdev = thermal_of_cooling_device_register(client->dev.of_node,
+ "tc654", hwmon_dev,
+ &tc654_fan_cool_ops);
+#else /* CONFIG_OF */
+ /* Optional cooling device register for non Device tree platforms */
+ data->cdev = thermal_cooling_device_register("tc654", hwmon_dev,
+ &tc654_fan_cool_ops);
+#endif /* CONFIG_OF */
+ if (IS_ENABLED(CONFIG_THERMAL)) {
+ struct thermal_cooling_device *cdev;
+
+ return PTR_ERR_OR_ZERO(data->cdev);
+ cdev = devm_thermal_of_cooling_device_register(dev, dev->of_node, client->name,
+ hwmon_dev, &tc654_fan_cool_ops);
+ return PTR_ERR_OR_ZERO(cdev);
+ }
+
+ return 0;
}
static const struct i2c_device_id tc654_id[] = {