本文主要是介绍【RK3399 Android10, 支持温控风扇】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 【RK3399 Android10, 支持温控风扇】
- 需求描述
- patch
【RK3399 Android10, 支持温控风扇】
需求描述
3399 Android10 的风扇,希望能做成温度控制的风扇,通过设置不同测温度阈值来实行不同的风速
patch
kernel
0020-feat-rochchip-system-monitor-add-temperature-notifye.patch
From 92116bdb9aa3efc280dd9c2699e8e82642860343 Mon Sep 17 00:00:00 2001
From: liangji <liangji@keenon.com>
Date: Tue, 26 Dec 2023 15:50:42 +0800
Subject: [PATCH 20/24] feat: rochchip system monitor add temperature notifyerChange-Id: I8a561b9fdcaf4d15a8ee9e827eb3a350e342f55c
Signed-off-by: liangji <liangji@keenon.com>
---drivers/soc/rockchip/rockchip_system_monitor.c | 42 ++++++++++++++++++++++++--include/soc/rockchip/rockchip_system_monitor.h | 26 ++++++++++++++++2 files changed, 65 insertions(+), 3 deletions(-)diff --git a/drivers/soc/rockchip/rockchip_system_monitor.c b/drivers/soc/rockchip/rockchip_system_monitor.c
index 8a84d02..fcd980be 100644
--- a/drivers/soc/rockchip/rockchip_system_monitor.c
+++ b/drivers/soc/rockchip/rockchip_system_monitor.c
@@ -64,6 +64,7 @@ struct system_monitor {struct thermal_zone_device *tz;struct delayed_work thermal_work;
+ int last_temp;int offline_cpus_temp;int temp_hysteresis;unsigned int delay;
@@ -84,6 +85,7 @@ static LIST_HEAD(monitor_dev_list);static struct system_monitor *system_monitor;static atomic_t monitor_in_suspend;+static BLOCKING_NOTIFIER_HEAD(system_monitor_notifier_list);static BLOCKING_NOTIFIER_HEAD(system_status_notifier_list);int rockchip_register_system_status_notifier(struct notifier_block *nb)
@@ -1167,6 +1169,31 @@ void rockchip_system_monitor_unregister(struct monitor_dev_info *info)}EXPORT_SYMBOL(rockchip_system_monitor_unregister);+int rockchip_system_monitor_register_notifier(struct notifier_block *nb)
+{
+ return blocking_notifier_chain_register(&system_monitor_notifier_list, nb);
+}
+EXPORT_SYMBOL(rockchip_system_monitor_register_notifier);
+
+void rockchip_system_monitor_unregister_notifier(struct notifier_block *nb)
+{
+ blocking_notifier_chain_unregister(&system_monitor_notifier_list, nb);
+}
+EXPORT_SYMBOL(rockchip_system_monitor_unregister_notifier);
+
+static int rockchip_system_monitor_temp_notify(int temp)
+{
+ struct system_monitor_event_data event_data;
+ int ret;
+
+ event_data.temp = temp;
+ ret = blocking_notifier_call_chain(&system_monitor_notifier_list,
+ SYSTEM_MONITOR_CHANGE_TEMP,
+ (void *)&event_data);
+
+ return notifier_to_errno(ret);
+}
+static int rockchip_system_monitor_parse_dt(struct system_monitor *monitor){struct device_node *np = monitor->dev->of_node;
@@ -1266,7 +1293,7 @@ static void rockchip_system_monitor_thermal_update(void){int temp, ret;struct monitor_dev_info *info;
- static int last_temp = INT_MAX;
+ //static int last_temp = INT_MAX;ret = thermal_zone_get_temp(system_monitor->tz, &temp);if (ret || temp == THERMAL_TEMP_INVALID)
@@ -1274,9 +1301,15 @@ static void rockchip_system_monitor_thermal_update(void)dev_dbg(system_monitor->dev, "temperature=%d\n", temp);- if (temp < last_temp && last_temp - temp <= 2000)
+ //if (temp < last_temp && last_temp - temp <= 2000)
+ if (temp < system_monitor->last_temp &&
+ system_monitor->last_temp - temp <= 2000)goto out;
- last_temp = temp;
+ //last_temp = temp;
+ system_monitor->last_temp = temp;
+
+ rockchip_system_monitor_temp_notify(temp);
+down_read(&mdev_list_sem);list_for_each_entry(info, &monitor_dev_list, node)
@@ -1379,6 +1412,8 @@ static int monitor_pm_notify(struct notifier_block *nb,if (system_monitor->tz)rockchip_system_monitor_thermal_update();atomic_set(&monitor_in_suspend, 0);
+ system_monitor->last_temp = INT_MAX;
+break;default:break;
@@ -1532,6 +1567,7 @@ static int rockchip_system_monitor_probe(struct platform_device *pdev)rockchip_system_monitor_parse_dt(system_monitor);if (system_monitor->tz) {
+ system_monitor->last_temp = INT_MAX;INIT_DELAYED_WORK(&system_monitor->thermal_work,rockchip_system_monitor_thermal_check);mod_delayed_work(system_freezable_wq,
diff --git a/include/soc/rockchip/rockchip_system_monitor.h b/include/soc/rockchip/rockchip_system_monitor.h
index 1f8bffc..bdc9a3f 100644
--- a/include/soc/rockchip/rockchip_system_monitor.h
+++ b/include/soc/rockchip/rockchip_system_monitor.h
@@ -6,11 +6,23 @@#ifndef __SOC_ROCKCHIP_SYSTEM_MONITOR_H#define __SOC_ROCKCHIP_SYSTEM_MONITOR_H+#include <linux/pm_opp.h>
+#include <linux/pm_qos.h>
+#include <linux/regulator/consumer.h>
+enum monitor_dev_type {MONITOR_TPYE_CPU = 0, /* CPU */MONITOR_TPYE_DEV, /* GPU, NPU, DMC, and so on */};+enum system_monitor_event_type {
+ SYSTEM_MONITOR_CHANGE_TEMP = 0,
+};
+
+struct system_monitor_event_data {
+ int temp;
+};
+struct volt_adjust_table {unsigned int min; /* Minimum frequency in MHz */unsigned int max; /* Maximum frequency in MHz */
@@ -127,6 +139,8 @@ int rockchip_monitor_dev_low_temp_adjust(struct monitor_dev_info *info,int rockchip_monitor_dev_high_temp_adjust(struct monitor_dev_info *info,bool is_high);int rockchip_monitor_suspend_low_temp_adjust(int cpu);
+int rockchip_system_monitor_register_notifier(struct notifier_block *nb);
+void rockchip_system_monitor_unregister_notifier(struct notifier_block *nb);introckchip_system_monitor_adjust_cdev_state(struct thermal_cooling_device *cdev,int temp, unsigned long *state);
@@ -177,6 +191,18 @@ static inline int rockchip_monitor_suspend_low_temp_adjust(int cpu)};static inline int
+rockchip_system_monitor_register_notifier(struct notifier_block *nb)
+{
+ return 0;
+};
+
+static inline void
+rockchip_system_monitor_unregister_notifier(struct notifier_block *nb)
+{
+};
+
+
+static inline introckchip_system_monitor_adjust_cdev_state(struct thermal_cooling_device *cdev,int temp, unsigned long *state){
--
2.7.4
0021-feat-rockchip-system-status-use-IS_REACHABLE.patch
From a5b79acc99fe356dba8f3a51ee7918bfb885b679 Mon Sep 17 00:00:00 2001
From: liangji <liangji@keenon.com>
Date: Tue, 26 Dec 2023 16:00:13 +0800
Subject: [PATCH 21/24] feat: rockchip system status use IS_REACHABLEChange-Id: I62e6deba1e511d14a3c11431fd04fcfcde65d5c3
Signed-off-by: liangji <liangji@keenon.com>
---include/soc/rockchip/rockchip-system-status.h | 3 ++-1 file changed, 2 insertions(+), 1 deletion(-)diff --git a/include/soc/rockchip/rockchip-system-status.h b/include/soc/rockchip/rockchip-system-status.h
index 200b1ee..de639b9 100644
--- a/include/soc/rockchip/rockchip-system-status.h
+++ b/include/soc/rockchip/rockchip-system-status.h
@@ -6,7 +6,8 @@#ifndef __SOC_ROCKCHIP_SYSTEM_STATUS_H#define __SOC_ROCKCHIP_SYSTEM_STATUS_H-#if IS_ENABLED(CONFIG_ROCKCHIP_SYSTEM_MONITOR)
+//#if IS_ENABLED(CONFIG_ROCKCHIP_SYSTEM_MONITOR)
+#if IS_REACHABLE(CONFIG_ROCKCHIP_SYSTEM_MONITOR)int rockchip_register_system_status_notifier(struct notifier_block *nb);int rockchip_unregister_system_status_notifier(struct notifier_block *nb);void rockchip_set_system_status(unsigned long status);
--
2.7.4
0022-feat-hwmon-pwm-fan-add-system-monitor-notifyer.patch
From bf6df7f1173b10fadcd56ba8f9e3a357cf6613a0 Mon Sep 17 00:00:00 2001
From: liangji <liangji@keenon.com>
Date: Tue, 26 Dec 2023 16:10:13 +0800
Subject: [PATCH 22/24] feat: hwmon pwm fan add system monitor notifyerChange-Id: Iaf0483d68ed46000d6eb43b3d41a34f7b4b55f4e
Signed-off-by: liangji <liangji@keenon.com>
---.../devicetree/bindings/hwmon/pwm-fan.txt | 5 +drivers/hwmon/pwm-fan.c | 114 ++++++++++++++++++++-2 files changed, 117 insertions(+), 2 deletions(-)diff --git a/Documentation/devicetree/bindings/hwmon/pwm-fan.txt b/Documentation/devicetree/bindings/hwmon/pwm-fan.txt
index c6d5332..282bca2 100644
--- a/Documentation/devicetree/bindings/hwmon/pwm-fan.txt
+++ b/Documentation/devicetree/bindings/hwmon/pwm-fan.txt
@@ -5,6 +5,11 @@ Required properties:- pwms : the PWM that is used to control the PWM fan- cooling-levels : PWM duty cycle values in a range from 0 to 255which correspond to thermal cooling states
+- rockchip,temp-trips : The property is an array of 2-tuples items, and
+ each item consists of temperature in millicelsius and
+ pwm cooling state. This depends on CONFIG_ROCKCHIP_SYSTEM_MONITOR.
+ If add the property the fan cooling state will be changed
+ by system monitor. Otherwise, use the default thermal governor.Example:fan0: pwm-fan {
diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c
index db0d15c..5ba1820 100644
--- a/drivers/hwmon/pwm-fan.c
+++ b/drivers/hwmon/pwm-fan.c
@@ -25,9 +25,15 @@#include <linux/pwm.h>#include <linux/sysfs.h>#include <linux/thermal.h>
+#include <soc/rockchip/rockchip_system_monitor.h>#define MAX_PWM 255+struct thermal_trips {
+ int temp;
+ int state;
+};
+struct pwm_fan_ctx {struct mutex lock;struct pwm_device *pwm;
@@ -36,6 +42,9 @@ struct pwm_fan_ctx {unsigned int pwm_fan_max_state;unsigned int *pwm_fan_cooling_levels;struct thermal_cooling_device *cdev;
+ struct notifier_block thermal_nb;
+ struct thermal_trips *thermal_trips;
+ bool thermal_notifier_is_ok;};static int __set_pwm(struct pwm_fan_ctx *ctx, unsigned long pwm)
@@ -205,6 +214,95 @@ static int pwm_fan_of_get_cooling_data(struct device *dev,return 0;}+static int pwm_fan_get_thermal_trips(struct device *dev, char *porp_name,
+ struct thermal_trips **trips)
+{
+ struct device_node *np = dev->of_node;
+ struct thermal_trips *thermal_trips;
+ const struct property *prop;
+ int count, i;
+
+ prop = of_find_property(np, porp_name, NULL);
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+ count = of_property_count_u32_elems(np, porp_name);
+ if (count < 0)
+ return -EINVAL;
+ if (count % 2)
+ return -EINVAL;
+ thermal_trips = devm_kzalloc(dev,
+ sizeof(*thermal_trips) * (count / 2 + 1),
+ GFP_KERNEL);
+ if (!thermal_trips)
+ return -ENOMEM;
+
+ for (i = 0; i < count / 2; i++) {
+ of_property_read_u32_index(np, porp_name, 2 * i,
+ &thermal_trips[i].temp);
+ of_property_read_u32_index(np, porp_name, 2 * i + 1,
+ &thermal_trips[i].state);
+ }
+ thermal_trips[i].temp = 0;
+ thermal_trips[i].state = INT_MAX;
+
+ *trips = thermal_trips;
+
+ return 0;
+}
+
+static int pwm_fan_temp_to_state(struct pwm_fan_ctx *ctx, int temp)
+{
+ struct thermal_trips *trips = ctx->thermal_trips;
+ int i, state = 0;
+
+ for (i = 0; trips[i].state != INT_MAX; i++) {
+ if (temp >= trips[i].temp)
+ state = trips[i].state;
+ }
+
+ return state;
+}
+
+static int pwm_fan_thermal_notifier_call(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct pwm_fan_ctx *ctx = container_of(nb, struct pwm_fan_ctx, thermal_nb);
+ struct system_monitor_event_data *event_data = data;
+ int state, ret;
+
+ if (event != SYSTEM_MONITOR_CHANGE_TEMP)
+ return NOTIFY_OK;
+
+ state = pwm_fan_temp_to_state(ctx, event_data->temp);
+ if (state > ctx->pwm_fan_max_state)
+ return NOTIFY_BAD;
+ if (state == ctx->pwm_fan_state)
+ return NOTIFY_OK;
+
+ ret = __set_pwm(ctx, ctx->pwm_fan_cooling_levels[state]);
+ if (ret)
+ return NOTIFY_BAD;
+
+ ctx->pwm_fan_state = state;
+
+ return NOTIFY_OK;
+}
+
+static int pwm_fan_register_thermal_notifier(struct device *dev,
+ struct pwm_fan_ctx *ctx)
+{
+ if (pwm_fan_get_thermal_trips(dev, "rockchip,temp-trips",
+ &ctx->thermal_trips))
+ return -EINVAL;
+
+ ctx->thermal_nb.notifier_call = pwm_fan_thermal_notifier_call;
+
+ return rockchip_system_monitor_register_notifier(&ctx->thermal_nb);
+}
+
+static int pwm_fan_probe(struct platform_device *pdev){struct thermal_cooling_device *cdev;
@@ -257,6 +355,16 @@ static int pwm_fan_probe(struct platform_device *pdev)goto err_pwm_disable;ctx->pwm_fan_state = ctx->pwm_fan_max_state;
+ if (IS_REACHABLE(CONFIG_ROCKCHIP_SYSTEM_MONITOR) &&
+ of_find_property(dev->of_node, "rockchip,temp-trips", NULL)) {
+ ret = pwm_fan_register_thermal_notifier(dev, ctx);
+ if (ret)
+ dev_err(dev, "Failed to register thermal notifier: %d\n", ret);
+ else
+ ctx->thermal_notifier_is_ok = true;
+ return 0;
+ }
+if (IS_ENABLED(CONFIG_THERMAL)) {cdev = thermal_of_cooling_device_register(pdev->dev.of_node,"pwm-fan", ctx,
@@ -299,7 +407,8 @@ static int pwm_fan_suspend(struct device *dev)pwm_get_args(ctx->pwm, &args);- if (ctx->pwm_value) {
+ //if (ctx->pwm_value) {
+ if (ctx->pwm_value || ctx->thermal_notifier_is_ok) {ret = pwm_config(ctx->pwm, 0, args.period);if (ret < 0)return ret;
@@ -317,7 +426,8 @@ static int pwm_fan_resume(struct device *dev)unsigned long duty;int ret;- if (ctx->pwm_value == 0)
+ //if (ctx->pwm_value == 0)
+ if (ctx->pwm_value == 0 && !ctx->thermal_notifier_is_ok)return 0;pwm_get_args(ctx->pwm, &pargs);
--
2.7.4
0023-feat-support-system-monitor-pwm-fan.patch
From 1cf46863c45c54007f1b4b9acf541781f138b215 Mon Sep 17 00:00:00 2001
From: liangji <liangji@keenon.com>
Date: Tue, 26 Dec 2023 16:59:57 +0800
Subject: [PATCH 23/24] feat: support system monitor pwm fanChange-Id: Id40a42b3f2d185a9c6c5054125e4566b91c6c784
Signed-off-by: liangji <liangji@keenon.com>
---arch/arm64/boot/dts/rockchip/rk3399-keenon-common.dtsi | 14 ++++++++++++++arch/arm64/boot/dts/rockchip/rk3399-keenon-w3s.dts | 4 ++++arch/arm64/configs/keenon_tablet_w3s_defconfig | 1 +drivers/hwmon/pwm-fan.c | 6 +++---4 files changed, 22 insertions(+), 3 deletions(-)diff --git a/arch/arm64/boot/dts/rockchip/rk3399-keenon-common.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-keenon-common.dtsi
index fae2f81..33a10a4 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-keenon-common.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-keenon-common.dtsi
@@ -254,6 +254,20 @@compatible = "fake,battery";status = "okay";};
+
+ fan: pwm-fan {
+ compatible = "pwm-fan";
+ #cooling-cells = <2>;
+ pwms = <&pwm3 0 50000 0>;
+ cooling-levels = <0 50 100 150 200 255>;
+ rockchip,temp-trips = <
+ 50000 1
+ 60000 2
+ 70000 3
+ 80000 4
+ 100000 5
+ >;
+ };};&backlight {
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-keenon-w3s.dts b/arch/arm64/boot/dts/rockchip/rk3399-keenon-w3s.dts
index 7a47c04..b8a2637 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-keenon-w3s.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-keenon-w3s.dts
@@ -18,6 +18,10 @@status = "okay";};+&pwm3{
+ status = "okay";
+};
+&backlight {enable-gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;pinctrl-names = "default";
diff --git a/arch/arm64/configs/keenon_tablet_w3s_defconfig b/arch/arm64/configs/keenon_tablet_w3s_defconfig
index 89c6e3c..db151c1 100644
--- a/arch/arm64/configs/keenon_tablet_w3s_defconfig
+++ b/arch/arm64/configs/keenon_tablet_w3s_defconfig
@@ -27,6 +27,7 @@ CONFIG_NAMESPACES=y# CONFIG_PID_NS is not setCONFIG_SCHED_TUNE=yCONFIG_BLK_DEV_INITRD=y
+CONFIG_SENSORS_PWM_FAN=y# CONFIG_RD_BZIP2 is not set# CONFIG_RD_LZMA is not set# CONFIG_RD_XZ is not set
diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c
index 5ba1820..0d3674d 100644
--- a/drivers/hwmon/pwm-fan.c
+++ b/drivers/hwmon/pwm-fan.c
@@ -356,10 +356,10 @@ static int pwm_fan_probe(struct platform_device *pdev)ctx->pwm_fan_state = ctx->pwm_fan_max_state;if (IS_REACHABLE(CONFIG_ROCKCHIP_SYSTEM_MONITOR) &&
- of_find_property(dev->of_node, "rockchip,temp-trips", NULL)) {
- ret = pwm_fan_register_thermal_notifier(dev, ctx);
+ of_find_property(pdev->dev.of_node, "rockchip,temp-trips", NULL)) {
+ ret = pwm_fan_register_thermal_notifier(&pdev->dev, ctx);if (ret)
- dev_err(dev, "Failed to register thermal notifier: %d\n", ret);
+ dev_err(&pdev->dev, "Failed to register thermal notifier: %d\n", ret);elsectx->thermal_notifier_is_ok = true;return 0;
--
2.7.4
这篇关于【RK3399 Android10, 支持温控风扇】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!