aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/thermal
diff options
context:
space:
mode:
authorPeter Feuerer <peter@piie.net>2014-07-22 11:37:13 -0400
committerZhang Rui <rui.zhang@intel.com>2014-08-27 03:45:58 -0400
commite4dbf98f7f169346f57296e173e883b7330076ab (patch)
tree9716c985db04ada091fbb35a9b93a9494e9b13e8 /drivers/thermal
parent52addcf9d6669fa439387610bc65c92fa0980cef (diff)
thermal: Added Bang-bang thermal governor
The bang-bang thermal governor uses a hysteresis to switch abruptly on or off a cooling device. It is intended to control fans, which can not be throttled but just switched on or off. Bang-bang cannot be set as default governor as it is intended for special devices only. For those special devices the driver needs to explicitely request it. Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Zhang Rui <rui.zhang@intel.com> Cc: Andreas Mohr <andi@lisas.de> Cc: Borislav Petkov <bp@suse.de> Cc: Javi Merino <javi.merino@arm.com> Cc: linux-pm@vger.kernel.org Signed-off-by: Peter Feuerer <peter@piie.net> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Diffstat (limited to 'drivers/thermal')
-rw-r--r--drivers/thermal/Kconfig10
-rw-r--r--drivers/thermal/Makefile1
-rw-r--r--drivers/thermal/gov_bang_bang.c131
-rw-r--r--drivers/thermal/thermal_core.c5
-rw-r--r--drivers/thermal/thermal_core.h8
5 files changed, 155 insertions, 0 deletions
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index 693208eb9047..2500ecc48260 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -84,6 +84,16 @@ config THERMAL_GOV_STEP_WISE
84 Enable this to manage platform thermals using a simple linear 84 Enable this to manage platform thermals using a simple linear
85 governor. 85 governor.
86 86
87config THERMAL_GOV_BANG_BANG
88 bool "Bang Bang thermal governor"
89 default n
90 help
91 Enable this to manage platform thermals using bang bang governor.
92
93 Say 'Y' here if you want to use two point temperature regulation
94 used for fans without throttling. Some fan drivers depend on this
95 governor to be enabled (e.g. acerhdf).
96
87config THERMAL_GOV_USER_SPACE 97config THERMAL_GOV_USER_SPACE
88 bool "User_space thermal governor" 98 bool "User_space thermal governor"
89 help 99 help
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 31e232f84b6b..b7e65423d7b6 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -11,6 +11,7 @@ thermal_sys-$(CONFIG_THERMAL_OF) += of-thermal.o
11 11
12# governors 12# governors
13thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += fair_share.o 13thermal_sys-$(CONFIG_THERMAL_GOV_FAIR_SHARE) += fair_share.o
14thermal_sys-$(CONFIG_THERMAL_GOV_BANG_BANG) += gov_bang_bang.o
14thermal_sys-$(CONFIG_THERMAL_GOV_STEP_WISE) += step_wise.o 15thermal_sys-$(CONFIG_THERMAL_GOV_STEP_WISE) += step_wise.o
15thermal_sys-$(CONFIG_THERMAL_GOV_USER_SPACE) += user_space.o 16thermal_sys-$(CONFIG_THERMAL_GOV_USER_SPACE) += user_space.o
16 17
diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c
new file mode 100644
index 000000000000..c5dd76b2ee74
--- /dev/null
+++ b/drivers/thermal/gov_bang_bang.c
@@ -0,0 +1,131 @@
1/*
2 * gov_bang_bang.c - A simple thermal throttling governor using hysteresis
3 *
4 * Copyright (C) 2014 Peter Feuerer <peter@piie.net>
5 *
6 * Based on step_wise.c with following Copyrights:
7 * Copyright (C) 2012 Intel Corp
8 * Copyright (C) 2012 Durgadoss R <durgadoss.r@intel.com>
9 *
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, version 2.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
18 * the GNU General Public License for more details.
19 *
20 */
21
22#include <linux/thermal.h>
23
24#include "thermal_core.h"
25
26static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip)
27{
28 long trip_temp;
29 unsigned long trip_hyst;
30 struct thermal_instance *instance;
31
32 tz->ops->get_trip_temp(tz, trip, &trip_temp);
33 tz->ops->get_trip_hyst(tz, trip, &trip_hyst);
34
35 dev_dbg(&tz->device, "Trip%d[temp=%ld]:temp=%d:hyst=%ld\n",
36 trip, trip_temp, tz->temperature,
37 trip_hyst);
38
39 mutex_lock(&tz->lock);
40
41 list_for_each_entry(instance, &tz->thermal_instances, tz_node) {
42 if (instance->trip != trip)
43 continue;
44
45 /* in case fan is in initial state, switch the fan off */
46 if (instance->target == THERMAL_NO_TARGET)
47 instance->target = 0;
48
49 /* in case fan is neither on nor off set the fan to active */
50 if (instance->target != 0 && instance->target != 1) {
51 pr_warn("Thermal instance %s controlled by bang-bang has unexpected state: %ld\n",
52 instance->name, instance->target);
53 instance->target = 1;
54 }
55
56 /*
57 * enable fan when temperature exceeds trip_temp and disable
58 * the fan in case it falls below trip_temp minus hysteresis
59 */
60 if (instance->target == 0 && tz->temperature >= trip_temp)
61 instance->target = 1;
62 else if (instance->target == 1 &&
63 tz->temperature < trip_temp - trip_hyst)
64 instance->target = 0;
65
66 dev_dbg(&instance->cdev->device, "target=%d\n",
67 (int)instance->target);
68
69 instance->cdev->updated = false; /* cdev needs update */
70 }
71
72 mutex_unlock(&tz->lock);
73}
74
75/**
76 * bang_bang_control - controls devices associated with the given zone
77 * @tz - thermal_zone_device
78 * @trip - the trip point
79 *
80 * Regulation Logic: a two point regulation, deliver cooling state depending
81 * on the previous state shown in this diagram:
82 *
83 * Fan: OFF ON
84 *
85 * |
86 * |
87 * trip_temp: +---->+
88 * | | ^
89 * | | |
90 * | | Temperature
91 * (trip_temp - hyst): +<----+
92 * |
93 * |
94 * |
95 *
96 * * If the fan is not running and temperature exceeds trip_temp, the fan
97 * gets turned on.
98 * * In case the fan is running, temperature must fall below
99 * (trip_temp - hyst) so that the fan gets turned off again.
100 *
101 */
102static int bang_bang_control(struct thermal_zone_device *tz, int trip)
103{
104 struct thermal_instance *instance;
105
106 thermal_zone_trip_update(tz, trip);
107
108 mutex_lock(&tz->lock);
109
110 list_for_each_entry(instance, &tz->thermal_instances, tz_node)
111 thermal_cdev_update(instance->cdev);
112
113 mutex_unlock(&tz->lock);
114
115 return 0;
116}
117
118static struct thermal_governor thermal_gov_bang_bang = {
119 .name = "bang_bang",
120 .throttle = bang_bang_control,
121};
122
123int thermal_gov_bang_bang_register(void)
124{
125 return thermal_register_governor(&thermal_gov_bang_bang);
126}
127
128void thermal_gov_bang_bang_unregister(void)
129{
130 thermal_unregister_governor(&thermal_gov_bang_bang);
131}
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 71b0ec0c370d..4c2726b55a2b 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1790,6 +1790,10 @@ static int __init thermal_register_governors(void)
1790 if (result) 1790 if (result)
1791 return result; 1791 return result;
1792 1792
1793 result = thermal_gov_bang_bang_register();
1794 if (result)
1795 return result;
1796
1793 return thermal_gov_user_space_register(); 1797 return thermal_gov_user_space_register();
1794} 1798}
1795 1799
@@ -1797,6 +1801,7 @@ static void thermal_unregister_governors(void)
1797{ 1801{
1798 thermal_gov_step_wise_unregister(); 1802 thermal_gov_step_wise_unregister();
1799 thermal_gov_fair_share_unregister(); 1803 thermal_gov_fair_share_unregister();
1804 thermal_gov_bang_bang_unregister();
1800 thermal_gov_user_space_unregister(); 1805 thermal_gov_user_space_unregister();
1801} 1806}
1802 1807
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index 3db339fb636f..d15d243de27a 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -69,6 +69,14 @@ static inline int thermal_gov_fair_share_register(void) { return 0; }
69static inline void thermal_gov_fair_share_unregister(void) {} 69static inline void thermal_gov_fair_share_unregister(void) {}
70#endif /* CONFIG_THERMAL_GOV_FAIR_SHARE */ 70#endif /* CONFIG_THERMAL_GOV_FAIR_SHARE */
71 71
72#ifdef CONFIG_THERMAL_GOV_BANG_BANG
73int thermal_gov_bang_bang_register(void);
74void thermal_gov_bang_bang_unregister(void);
75#else
76static inline int thermal_gov_bang_bang_register(void) { return 0; }
77static inline void thermal_gov_bang_bang_unregister(void) {}
78#endif /* CONFIG_THERMAL_GOV_BANG_BANG */
79
72#ifdef CONFIG_THERMAL_GOV_USER_SPACE 80#ifdef CONFIG_THERMAL_GOV_USER_SPACE
73int thermal_gov_user_space_register(void); 81int thermal_gov_user_space_register(void);
74void thermal_gov_user_space_unregister(void); 82void thermal_gov_user_space_unregister(void);