rk3568-android11-fan-pwm-temp
需求,随CPU温度控制的风扇,风扇就是普通GPIO控制;
个人建议直接开就完事了,非要PWM控制,这样搞容易坏啊,不听非要,你想我就做。
1.获取温度,输入;
2.控制模式;
3.风扇pwm输出;
=========================================================
Author: longmin <longmin@weizhouai.cn>
Date: Wed Oct 29 17:13:08 2025 +0800add fan devicediff --git a/kernel/arch/arm64/boot/dts/rockchip/pro-rk3568.dts b/kernel/arch/arm64/boot/dts/rockchip/pro-rk3568.dts
index f8a82c7413..fbefa2ca5c 100755
--- a/kernel/arch/arm64/boot/dts/rockchip/pro-rk3568.dts
+++ b/kernel/arch/arm64/boot/dts/rockchip/pro-rk3568.dts
@@ -137,10 +137,11 @@gpio_function = <0>;};*/
- fan { //fan
+ /* fan { //fangpio_num = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>;gpio_function = <0>;};
+ */usb_pwr { //usb powergpio_num = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;gpio_function = <4>;
@@ -229,6 +230,12 @@};};+ fans: fans {
+ compatible = "gpio-fan";
+ fan_0: fan-0 {
+ gpios = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>;
+ };
+ };}; //homediff --git a/kernel/arch/arm64/configs/rockchip_defconfig b/kernel/arch/arm64/configs/rockchip_defconfig
index 09ff706c89..577d03aa80 100644
--- a/kernel/arch/arm64/configs/rockchip_defconfig
+++ b/kernel/arch/arm64/configs/rockchip_defconfig
@@ -954,4 +954,5 @@ CONFIG_BEEP_GPIO=yCONFIG_BEEP_TRIGGERS=yCONFIG_BEEP_TRIGGER_TIMER=yCONFIG_BEEP_TRIGGER_BACKLIGHT=y
-CONFIG_BEEP_TRIGGER_DEFAULT_ON=y
\ No newline at end of file
+CONFIG_BEEP_TRIGGER_DEFAULT_ON=y
+CONFIG_FAN_GPIO=y
\ No newline at end of file
diff --git a/kernel/drivers/Kconfig b/kernel/drivers/Kconfig
index a3e1542c65..de2225a17a 100644
--- a/kernel/drivers/Kconfig
+++ b/kernel/drivers/Kconfig
@@ -109,6 +109,8 @@ source "drivers/leds/Kconfig"source "drivers/beep/Kconfig"+source "drivers/fan/Kconfig"
+source "drivers/accessibility/Kconfig"source "drivers/infiniband/Kconfig"
diff --git a/kernel/drivers/Makefile b/kernel/drivers/Makefile
index 95230771bb..290c594bc6 100644
--- a/kernel/drivers/Makefile
+++ b/kernel/drivers/Makefile
@@ -132,6 +132,7 @@ obj-y += mmc/obj-$(CONFIG_MEMSTICK) += memstick/obj-$(CONFIG_NEW_LEDS) += leds/obj-$(CONFIG_NEW_BEEP) += beep/
+obj-$(CONFIG_FAN_GPIO) += fan/obj-$(CONFIG_INFINIBAND) += infiniband/obj-$(CONFIG_SGI_SN) += sn/obj-y += firmware/
diff --git a/kernel/drivers/fan/Kconfig b/kernel/drivers/fan/Kconfig
new file mode 100644
index 0000000000..79c8ab5cf0
--- /dev/null
+++ b/kernel/drivers/fan/Kconfig
@@ -0,0 +1,9 @@
+menuconfig FAN_GPIO
+ bool "FAN Support"
+ help
+ This option enables support for the FAN connected to GPIO
+ outputs. To be useful the particular board must have FAN
+ and they must be connected to the GPIO lines. The FAN must be
+ defined as platform devices and/or OpenFirmware platform devices.
+ The code to use these bindings can be selected below.
+
diff --git a/kernel/drivers/fan/Makefile b/kernel/drivers/fan/Makefile
new file mode 100644
index 0000000000..3db3debe09
--- /dev/null
+++ b/kernel/drivers/fan/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+# LED Platform Drivers
+obj-$(CONFIG_FAN_GPIO) += fan-gpio.o
diff --git a/kernel/drivers/fan/fan-gpio.c b/kernel/drivers/fan/fan-gpio.c
new file mode 100644
index 0000000000..dc9fab6971
--- /dev/null
+++ b/kernel/drivers/fan/fan-gpio.c
@@ -0,0 +1,222 @@
+/*
+ * LEDs driver for GPIOs
+ *
+ * Copyright (C) 2007 8D Technologies inc.
+ * Raphael Assenat <raph@8d.com>
+ * Copyright (C) 2008 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/slab.h>
+
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/of_irq.h>
+#include <linux/of_gpio.h>
+#include <linux/input.h>
+#include <linux/of_platform.h>
+#include <linux/reboot.h>
+
+#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/wait.h>
+#include <linux/proc_fs.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/timer.h>
+#include <linux/list.h>
+
+
+static ssize_t fan_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ //int ret = get_soc_temperature();
+ //gpio_direction_input(fan_gpio);
+ if(gpio_get_value(fan_gpio))
+ return sprintf(buf,"\nfan=%d\n",1);
+ else return sprintf(buf,"\nfan=%d\n",0);
+return sprintf(buf,"\n11111 temp=%d\n",0);
+}
+
+static ssize_t fan_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+
+ unsigned long data;
+ int rc;
+ rc = kstrtoul(buf, 0, &data);
+ if (rc)
+ return rc;
+ printk("\n fan===%ld \n",data);
+ if(fan_gpio>0){
+ if(data==0)
+ {
+ gpio_direction_output(fan_gpio,0);
+ }
+ else {
+ gpio_direction_output(fan_gpio,1);
+ }
+ }
+
+return count;
+}
+
+static DEVICE_ATTR(fan, S_IWUSR | S_IRUGO, fan_show, fan_store);
+
+
+static const struct of_device_id of_gpio_fan_match[] = {
+ { .compatible = "gpio-fan", },
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, of_gpio_fan_match);
+
+
+
+static int gpio_fan_probe(struct platform_device *pdev)
+{
+
+ struct device *fan_dev = &pdev->dev;
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *child_np;
+ enum of_gpio_flags gpio_flags;
+ dev_t fan_devt = MKDEV(50,10);
+ struct class *fan_class;
+ int ret;
+ //get gpio
+ for_each_child_of_node(np, child_np)
+ {
+ fan_gpio = of_get_named_gpio_flags(child_np, "gpios", 0, &gpio_flags);
+ dev_err(&pdev->dev, "gpio_get_value(fan_gpio=%d)===\n",fan_gpio);
+ if (!gpio_is_valid(fan_gpio)){
+ return -1;
+ }
+ }
+
+ //ret = get_soc_temperature();
+ dev_err(&pdev->dev, "time=%d)===\n",ret);
+
+ fan_class = class_create(THIS_MODULE, "fan");
+
+ if (IS_ERR(fan_class))
+ return PTR_ERR(fan_class);
+
+ fan_dev = device_create(fan_class,NULL,fan_devt,NULL,"fans");
+ if (IS_ERR(fan_dev)) {
+ ret = PTR_ERR(fan_dev);
+ printk("Failed to create device.fan_dev.\n");
+ }
+
+ ret = device_create_file(fan_dev,&dev_attr_fan);
+ if (ret) {
+ printk("Failed to create device file.\\n");
+ }
+
+ gpio_direction_output(fan_gpio,1);
+
+
+ return 0;
+}
+
+static void gpio_fan_shutdown(struct platform_device *pdev)
+{
+ gpio_direction_output(fan_gpio,0);
+}
+
+static struct platform_driver gpio_fan_driver = {
+ .probe = gpio_fan_probe,
+ .shutdown = gpio_fan_shutdown,
+ .driver = {
+ .name = "fan-gpio",
+ .of_match_table = of_gpio_fan_match,
+ },
+};
+
+module_platform_driver(gpio_fan_driver);
+
+MODULE_AUTHOR("wzzn <longmin@wz.com>, fan");
+MODULE_DESCRIPTION("GPIO fan driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:fan-gpio");
第一步写了一个普通GPIO驱动;
第二步在基础上加入一个定时器,一定时间检查一下CPU温度
+extern struct thermal_zone_device *wz_zone;
+static int get_thermal_temp_via_api(void)
+{
+ struct thermal_zone_device *tz = wz_zone;
+ int temp, ret;
+
+ ret = thermal_zone_get_temp(tz, &temp);
+ if (ret) {
+ pr_err("Failed to get temperature: %d\n", ret);
+ return ret;
+ }
+
+ return temp;
+}
+static struct timer_list temp_timer;
+static void timer_callback(struct timer_list *t)
+{
+ int temp;
+ int ret;
+
+ if(i >= 5){
+ i=0;
+ //mode++;
+ //if(mode >= 10) {mode = 2;}
+ temp = get_thermal_temp_via_api();
+ if (temp < 0) {
+ pr_warn("API method failed, trying sysfs\n");
+ }
+ ret = set_fan_mode(temp);
+ //printk(KERN_INFO "mode: %d temp: %d\n", mode, temp);
+ if (ret < 0) {
+ pr_err("Failed to set_fan_mode: %d\n", ret);
+ }
+ }else {
+ i++;
+ }
+ // 2. 重新设置定时器,实现1秒后再次触发 (周期性)
+ mod_timer(&temp_timer, jiffies + msecs_to_jiffies(1000));
+}static int gpio_fan_probe(struct platform_device *pdev)
{+ timer_setup(&temp_timer, timer_callback, 0);
+ mod_timer(&temp_timer, jiffies + msecs_to_jiffies(1000)); // 1秒后启动第一次查询return 0;
}第三步:风扇输出,开了一个进程一直模拟高低电平PWM
int mode;static struct task_struct *thread_body;
struct gpio_demo_priv{int count;int gpio; struct mutex mtx;int mode;
};struct gpio_demo_priv *priv;struct temp_data_node {int some_value; // 示例数据字段,请根据实际需求修改struct list_head list; // 链表头
};
static int thread_func(void *data) { int count;while (1){count++;mutex_lock(&priv->mtx);gpio_set_value(priv->gpio, count%2 );mutex_unlock(&priv->mtx);msleep(get_soc_sleep(mode));//printk(KERN_INFO "thread count %d\n", count);}return 0;
}int set_fan_mode(int temp)
{if(temp <= 50000){mode = 3;return mode;}else if(temp <= 75000){mode = 2;return mode;}else if(temp <= 85000){mode = 1;printk(KERN_INFO "mode: %d temp: %d\n", mode, temp);return mode;}else if(temp <= 95000){mode = 0;printk(KERN_INFO "mode: %d temp: %d\n", mode, temp);return mode;}else{mode = 0;printk(KERN_INFO "mode: %d temp: %d\n", mode, temp);return mode;}return -ENODEV;
}static int gpio_fan_probe(struct platform_device *pdev)
{+ priv->count = 1;
+ mutex_init(&priv->mtx);
+ ret = devm_gpio_request_one(fan_dev, fan_gpio, GPIOF_DIR_OUT, pdev->name);
+ priv->gpio = fan_gpio;
+ if (ret < 0) {
+ dev_warn(fan_dev, "Unable to re quest GPIO %d: %d\n", fan_gpio, ret);
+ }
+ printk(KERN_INFO "success request gpio %d\n",fan_gpio);+ platform_set_drvdata(pdev,priv);
+ thread_body = kthread_create(thread_func, NULL, "thread_pwm");
+ if((thread_body))
+ {
+ wake_up_process(thread_body);
+ }
总结:就是通过以上自己写了一个驱动fan-gpio.c
/** LEDs driver for GPIOs** Copyright (C) 2007 8D Technologies inc.* Raphael Assenat <raph@8d.com>* Copyright (C) 2008 Freescale Semiconductor, Inc.** This program is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License version 2 as* published by the Free Software Foundation.**/
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/input.h>
#include <linux/of_platform.h>
#include <linux/reboot.h>
#include <linux/mutex.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/wait.h>
#include <linux/proc_fs.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/of_device.h>
//API for thread
#include <linux/kthread.h>
#include <linux/thermal.h>
#include <linux/sched.h>/*mode temp **** pwm时间间隔* 3 50°以下 1000* 2 50°-75° 500* 1 75-85° 250* 0 95°以上 50
*///static struct class *fan_class;
int i;
int fan_gpio;
int mode;static struct task_struct *thread_body;
struct gpio_demo_priv{int count;int gpio; struct mutex mtx;int mode;
};struct gpio_demo_priv *priv;struct temp_data_node {int some_value; // 示例数据字段,请根据实际需求修改struct list_head list; // 链表头
};static struct timer_list temp_timer;
int get_soc_temperature(void);int get_soc_sleep(int mode_num){int num;if(mode_num == 0){num = 50;}else if(mode_num == 1) {num = 250;}else if(mode_num == 2) {num = 500;}else if(mode_num >= 3) {num = 1000;}return num;
}static int thread_func(void *data) { int count;while (1){count++;mutex_lock(&priv->mtx);gpio_set_value(priv->gpio, count%2 );mutex_unlock(&priv->mtx);msleep(get_soc_sleep(mode));//printk(KERN_INFO "thread count %d\n", count);}return 0;
}
extern struct thermal_zone_device *wz_zone;
static int get_thermal_temp_via_api(void)
{struct thermal_zone_device *tz = wz_zone;int temp, ret;ret = thermal_zone_get_temp(tz, &temp);if (ret) {pr_err("Failed to get temperature: %d\n", ret);return ret;}return temp;
}int set_fan_mode(int temp)
{if(temp <= 50000){mode = 3;return mode;}else if(temp <= 75000){mode = 2;return mode;}else if(temp <= 85000){mode = 1;printk(KERN_INFO "mode: %d temp: %d\n", mode, temp);return mode;}else if(temp <= 95000){mode = 0;printk(KERN_INFO "mode: %d temp: %d\n", mode, temp);return mode;}else{mode = 0;printk(KERN_INFO "mode: %d temp: %d\n", mode, temp);return mode;}return -ENODEV;
}static void timer_callback(struct timer_list *t)
{int temp;int ret;if(i >= 5){i=0;//mode++;//if(mode >= 10) {mode = 2;}temp = get_thermal_temp_via_api();if (temp < 0) {pr_warn("API method failed, trying sysfs\n");}ret = set_fan_mode(temp);//printk(KERN_INFO "mode: %d temp: %d\n", mode, temp);if (ret < 0) {pr_err("Failed to set_fan_mode: %d\n", ret);}}else {i++;}// 2. 重新设置定时器,实现1秒后再次触发 (周期性)mod_timer(&temp_timer, jiffies + msecs_to_jiffies(1000));
}static ssize_t fan_show(struct device *dev,struct device_attribute *attr, char *buf)
{
return sprintf(buf,"\n mode=%d\n", mode);
}static ssize_t fan_store(struct device *dev,struct device_attribute *attr, const char *buf, size_t count)
{unsigned long data; int rc;rc = kstrtoul(buf, 0, &data);if (rc)return rc; //printk("\n fan===%ld \n",data);if(data>=0) {mode = data;}return count;
}static DEVICE_ATTR(fan, S_IWUSR | S_IRUGO, fan_show, fan_store);static const struct of_device_id of_gpio_fan_match[] = {{ .compatible = "gpio-fan", },{},
};MODULE_DEVICE_TABLE(of, of_gpio_fan_match);static int gpio_fan_probe(struct platform_device *pdev)
{struct device *fan_dev = &pdev->dev;struct device_node *np = pdev->dev.of_node;struct device_node *child_np;enum of_gpio_flags gpio_flags;dev_t fan_devt = MKDEV(50,10);struct class *fan_class;int ret;priv = devm_kzalloc(fan_dev, sizeof(*priv) + sizeof(int), GFP_KERNEL);if (!priv){return -ENOMEM;}//get gpiofor_each_child_of_node(np, child_np){fan_gpio = of_get_named_gpio_flags(child_np, "gpios", 0, &gpio_flags);dev_err(&pdev->dev, "gpio_get_value(fan_gpio=%d)===\n",fan_gpio);if (!gpio_is_valid(fan_gpio)){return -1;} }//ret = get_soc_temperature();//dev_err(&pdev->dev, "time=%d)===\n",ret);fan_class = class_create(THIS_MODULE, "fan");if (IS_ERR(fan_class))return PTR_ERR(fan_class);fan_dev = device_create(fan_class,NULL,fan_devt,NULL,"fans");if (IS_ERR(fan_dev)) {ret = PTR_ERR(fan_dev);printk("Failed to create device.fan_dev.\n");}ret = device_create_file(fan_dev,&dev_attr_fan);if (ret) {printk("Failed to create device file.\\n");}priv->count = 1;mutex_init(&priv->mtx);ret = devm_gpio_request_one(fan_dev, fan_gpio, GPIOF_DIR_OUT, pdev->name);priv->gpio = fan_gpio;if (ret < 0) {dev_warn(fan_dev, "Unable to re quest GPIO %d: %d\n", fan_gpio, ret);}printk(KERN_INFO "success request gpio %d\n",fan_gpio);gpio_direction_output(fan_gpio,1);platform_set_drvdata(pdev,priv);thread_body = kthread_create(thread_func, NULL, "thread_pwm");if((thread_body)){wake_up_process(thread_body);}timer_setup(&temp_timer, timer_callback, 0);mod_timer(&temp_timer, jiffies + msecs_to_jiffies(1000)); // 1秒后启动第一次查询return 0;
}static void gpio_fan_shutdown(struct platform_device *pdev)
{gpio_direction_output(fan_gpio,0);
}static struct platform_driver gpio_fan_driver = {.probe = gpio_fan_probe,.shutdown = gpio_fan_shutdown,.driver = {.name = "fan-gpio",.of_match_table = of_gpio_fan_match,},
};module_platform_driver(gpio_fan_driver);MODULE_AUTHOR("wzzn <longmin@wz.com>, fan");
MODULE_DESCRIPTION("GPIO fan driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:fan-gpio");
加上其他部分代码
diff --git a/kernel/arch/arm64/boot/dts/rockchip/pro-rk3568.dts b/kernel/arch/arm64/boot/dts/rockchip/pro-rk3568.dts
index f8a82c7413..fbefa2ca5c 100755
--- a/kernel/arch/arm64/boot/dts/rockchip/pro-rk3568.dts
+++ b/kernel/arch/arm64/boot/dts/rockchip/pro-rk3568.dts
@@ -229,6 +230,12 @@};};+ fans: fans {
+ compatible = "gpio-fan";
+ fan_0: fan-0 {
+ gpios = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>;
+ };
+ };}; //homediff --git a/kernel/arch/arm64/configs/rockchip_defconfig b/kernel/arch/arm64/configs/rockchip_defconfig
index 09ff706c89..577d03aa80 100644
--- a/kernel/arch/arm64/configs/rockchip_defconfig
+++ b/kernel/arch/arm64/configs/rockchip_defconfig
@@ -954,4 +954,5 @@ CONFIG_BEEP_GPIO=yCONFIG_BEEP_TRIGGERS=yCONFIG_BEEP_TRIGGER_TIMER=yCONFIG_BEEP_TRIGGER_BACKLIGHT=y
+CONFIG_FAN_GPIO=y
\ No newline at end of file
diff --git a/kernel/drivers/Kconfig b/kernel/drivers/Kconfig
index a3e1542c65..de2225a17a 100644
--- a/kernel/drivers/Kconfig
+++ b/kernel/drivers/Kconfig
@@ -109,6 +109,8 @@ source "drivers/leds/Kconfig"source "drivers/beep/Kconfig"+source "drivers/fan/Kconfig"
+source "drivers/accessibility/Kconfig"source "drivers/infiniband/Kconfig"
diff --git a/kernel/drivers/Makefile b/kernel/drivers/Makefile
index 95230771bb..290c594bc6 100644
--- a/kernel/drivers/Makefile
+++ b/kernel/drivers/Makefile
@@ -132,6 +132,7 @@ obj-y += mmc/obj-$(CONFIG_MEMSTICK) += memstick/obj-$(CONFIG_NEW_LEDS) += leds/obj-$(CONFIG_NEW_BEEP) += beep/
+obj-$(CONFIG_FAN_GPIO) += fan/obj-$(CONFIG_INFINIBAND) += infiniband/obj-$(CONFIG_SGI_SN) += sn/obj-y += firmware/
diff --git a/kernel/drivers/fan/Kconfig b/kernel/drivers/fan/Kconfig
new file mode 100644
index 0000000000..79c8ab5cf0
--- /dev/null
+++ b/kernel/drivers/fan/Kconfig
@@ -0,0 +1,9 @@
+menuconfig FAN_GPIO
+ bool "FAN Support"
+ help
+ This option enables support for the FAN connected to GPIO
+ outputs. To be useful the particular board must have FAN
+ and they must be connected to the GPIO lines. The FAN must be
+ defined as platform devices and/or OpenFirmware platform devices.
+ The code to use these bindings can be selected below.
+
diff --git a/kernel/drivers/fan/Makefile b/kernel/drivers/fan/Makefile
new file mode 100644
index 0000000000..3db3debe09
--- /dev/null
+++ b/kernel/drivers/fan/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+# LED Platform Drivers
+obj-$(CONFIG_FAN_GPIO) += fan-gpio.o
diff --git a/kernel/drivers/thermal/of-thermal.c b/kernel/drivers/thermal/of-thermal.c
index 25c3c423a8..bb9a8a6b2f 100644
--- a/kernel/drivers/thermal/of-thermal.c
+++ b/kernel/drivers/thermal/of-thermal.c
@@ -1330,6 +1330,7 @@ static inline void of_thermal_free_zone(struct __thermal_zone *tz)kfree(tz);}+struct thermal_zone_device *wz_zone;/*** of_parse_thermal_zones - parse device tree thermal data*
@@ -1421,6 +1422,7 @@ int __init of_parse_thermal_zones(void)continue;}tz->tzd = zone;
+ wz_zone = zone;}of_node_put(np);diff --git a/kernel/include/linux/thermal.h b/kernel/include/linux/thermal.h
index bb022cf792..18e47a4dca 100644
--- a/kernel/include/linux/thermal.h
+++ b/kernel/include/linux/thermal.h
@@ -634,4 +634,6 @@ static inline int thermal_generate_netlink_event(struct thermal_zone_device *tz,}#endif+extern struct thermal_zone_device *wz_zone;
+#endif /* __THERMAL_H__ */总结:就是一路GPIO模拟PWM,然后根据CPU温度去调节PWM的占空比
