diff options
author | Christian Krafft <krafft@de.ibm.com> | 2007-04-23 15:35:41 -0400 |
---|---|---|
committer | Arnd Bergmann <arnd@klappe.arndb.de> | 2007-04-23 15:44:39 -0400 |
commit | 5f7bdaee2aaf7dfdf18c735dee62401fd26c8d72 (patch) | |
tree | 579067e1c368bfb7888e1c51fbdfb8d77d8ba6aa | |
parent | 24d560d7b9cf90451c6ef6248c09fb4cee1c76e6 (diff) |
[POWERPC] cbe_thermal: add throttling attributes to cpu and spu nodes
This patch adds some attributes the cpu and spu nodes:
/sys/devices/system/[c|s]pu/[c|s]pu*/thermal/throttle_begin
/sys/devices/system/[c|s]pu/[c|s]pu*/thermal/throttle_end
/sys/devices/system/[c|s]pu/[c|s]pu*/thermal/throttle_full_stop
Signed-off-by: Christian Krafft <krafft@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
-rw-r--r-- | arch/powerpc/platforms/cell/cbe_thermal.c | 155 |
1 files changed, 154 insertions, 1 deletions
diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c index 0d486fd424a9..f370f0fa6f4c 100644 --- a/arch/powerpc/platforms/cell/cbe_thermal.c +++ b/arch/powerpc/platforms/cell/cbe_thermal.c | |||
@@ -1,6 +1,31 @@ | |||
1 | /* | 1 | /* |
2 | * thermal support for the cell processor | 2 | * thermal support for the cell processor |
3 | * | 3 | * |
4 | * This module adds some sysfs attributes to cpu and spu nodes. | ||
5 | * Base for measurements are the digital thermal sensors (DTS) | ||
6 | * located on the chip. | ||
7 | * The accuracy is 2 degrees, starting from 65 up to 125 degrees celsius | ||
8 | * The attributes can be found under | ||
9 | * /sys/devices/system/cpu/cpuX/thermal | ||
10 | * /sys/devices/system/spu/spuX/thermal | ||
11 | * | ||
12 | * The following attributes are added for each node: | ||
13 | * temperature: | ||
14 | * contains the current temperature measured by the DTS | ||
15 | * throttle_begin: | ||
16 | * throttling begins when temperature is greater or equal to | ||
17 | * throttle_begin. Setting this value to 125 prevents throttling. | ||
18 | * throttle_end: | ||
19 | * throttling is being ceased, if the temperature is lower than | ||
20 | * throttle_end. Due to a delay between applying throttling and | ||
21 | * a reduced temperature this value should be less than throttle_begin. | ||
22 | * A value equal to throttle_begin provides only a very little hysteresis. | ||
23 | * throttle_full_stop: | ||
24 | * If the temperatrue is greater or equal to throttle_full_stop, | ||
25 | * full throttling is applied to the cpu or spu. This value should be | ||
26 | * greater than throttle_begin and throttle_end. Setting this value to | ||
27 | * 65 prevents the unit from running code at all. | ||
28 | * | ||
4 | * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 | 29 | * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 |
5 | * | 30 | * |
6 | * Author: Christian Krafft <krafft@de.ibm.com> | 31 | * Author: Christian Krafft <krafft@de.ibm.com> |
@@ -31,9 +56,24 @@ | |||
31 | #include "cbe_regs.h" | 56 | #include "cbe_regs.h" |
32 | #include "spu_priv1_mmio.h" | 57 | #include "spu_priv1_mmio.h" |
33 | 58 | ||
59 | #define TEMP_MIN 65 | ||
60 | #define TEMP_MAX 125 | ||
61 | |||
62 | #define SYSDEV_PREFIX_ATTR(_prefix,_name,_mode) \ | ||
63 | struct sysdev_attribute attr_ ## _prefix ## _ ## _name = { \ | ||
64 | .attr = { .name = __stringify(_name), .mode = _mode }, \ | ||
65 | .show = _prefix ## _show_ ## _name, \ | ||
66 | .store = _prefix ## _store_ ## _name, \ | ||
67 | }; | ||
68 | |||
34 | static inline u8 reg_to_temp(u8 reg_value) | 69 | static inline u8 reg_to_temp(u8 reg_value) |
35 | { | 70 | { |
36 | return ((reg_value & 0x3f) << 1) + 65; | 71 | return ((reg_value & 0x3f) << 1) + TEMP_MIN; |
72 | } | ||
73 | |||
74 | static inline u8 temp_to_reg(u8 temp) | ||
75 | { | ||
76 | return ((temp - TEMP_MIN) >> 1) & 0x3f; | ||
37 | } | 77 | } |
38 | 78 | ||
39 | static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev) | 79 | static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev) |
@@ -73,6 +113,73 @@ static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf) | |||
73 | return sprintf(buf, "%d\n", reg_to_temp(value)); | 113 | return sprintf(buf, "%d\n", reg_to_temp(value)); |
74 | } | 114 | } |
75 | 115 | ||
116 | static ssize_t show_throttle(struct cbe_pmd_regs __iomem *pmd_regs, char *buf, int pos) | ||
117 | { | ||
118 | u64 value; | ||
119 | |||
120 | value = in_be64(&pmd_regs->tm_tpr.val); | ||
121 | /* access the corresponding byte */ | ||
122 | value >>= pos; | ||
123 | value &= 0x3F; | ||
124 | |||
125 | return sprintf(buf, "%d\n", reg_to_temp(value)); | ||
126 | } | ||
127 | |||
128 | static ssize_t store_throttle(struct cbe_pmd_regs __iomem *pmd_regs, const char *buf, size_t size, int pos) | ||
129 | { | ||
130 | u64 reg_value; | ||
131 | int temp; | ||
132 | u64 new_value; | ||
133 | int ret; | ||
134 | |||
135 | ret = sscanf(buf, "%u", &temp); | ||
136 | |||
137 | if (ret != 1 || temp < TEMP_MIN || temp > TEMP_MAX) | ||
138 | return -EINVAL; | ||
139 | |||
140 | new_value = temp_to_reg(temp); | ||
141 | |||
142 | reg_value = in_be64(&pmd_regs->tm_tpr.val); | ||
143 | |||
144 | /* zero out bits for new value */ | ||
145 | reg_value &= ~(0xffull << pos); | ||
146 | /* set bits to new value */ | ||
147 | reg_value |= new_value << pos; | ||
148 | |||
149 | out_be64(&pmd_regs->tm_tpr.val, reg_value); | ||
150 | return size; | ||
151 | } | ||
152 | |||
153 | static ssize_t spu_show_throttle_end(struct sys_device *sysdev, char *buf) | ||
154 | { | ||
155 | return show_throttle(get_pmd_regs(sysdev), buf, 0); | ||
156 | } | ||
157 | |||
158 | static ssize_t spu_show_throttle_begin(struct sys_device *sysdev, char *buf) | ||
159 | { | ||
160 | return show_throttle(get_pmd_regs(sysdev), buf, 8); | ||
161 | } | ||
162 | |||
163 | static ssize_t spu_show_throttle_full_stop(struct sys_device *sysdev, char *buf) | ||
164 | { | ||
165 | return show_throttle(get_pmd_regs(sysdev), buf, 16); | ||
166 | } | ||
167 | |||
168 | static ssize_t spu_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size) | ||
169 | { | ||
170 | return store_throttle(get_pmd_regs(sysdev), buf, size, 0); | ||
171 | } | ||
172 | |||
173 | static ssize_t spu_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size) | ||
174 | { | ||
175 | return store_throttle(get_pmd_regs(sysdev), buf, size, 8); | ||
176 | } | ||
177 | |||
178 | static ssize_t spu_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size) | ||
179 | { | ||
180 | return store_throttle(get_pmd_regs(sysdev), buf, size, 16); | ||
181 | } | ||
182 | |||
76 | static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos) | 183 | static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos) |
77 | { | 184 | { |
78 | struct cbe_pmd_regs __iomem *pmd_regs; | 185 | struct cbe_pmd_regs __iomem *pmd_regs; |
@@ -100,13 +207,52 @@ static ssize_t ppe_show_temp1(struct sys_device *sysdev, char *buf) | |||
100 | return ppe_show_temp(sysdev, buf, 0); | 207 | return ppe_show_temp(sysdev, buf, 0); |
101 | } | 208 | } |
102 | 209 | ||
210 | static ssize_t ppe_show_throttle_end(struct sys_device *sysdev, char *buf) | ||
211 | { | ||
212 | return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 32); | ||
213 | } | ||
214 | |||
215 | static ssize_t ppe_show_throttle_begin(struct sys_device *sysdev, char *buf) | ||
216 | { | ||
217 | return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 40); | ||
218 | } | ||
219 | |||
220 | static ssize_t ppe_show_throttle_full_stop(struct sys_device *sysdev, char *buf) | ||
221 | { | ||
222 | return show_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, 48); | ||
223 | } | ||
224 | |||
225 | static ssize_t ppe_store_throttle_end(struct sys_device *sysdev, const char *buf, size_t size) | ||
226 | { | ||
227 | return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 32); | ||
228 | } | ||
229 | |||
230 | static ssize_t ppe_store_throttle_begin(struct sys_device *sysdev, const char *buf, size_t size) | ||
231 | { | ||
232 | return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 40); | ||
233 | } | ||
234 | |||
235 | static ssize_t ppe_store_throttle_full_stop(struct sys_device *sysdev, const char *buf, size_t size) | ||
236 | { | ||
237 | return store_throttle(cbe_get_cpu_pmd_regs(sysdev->id), buf, size, 48); | ||
238 | } | ||
239 | |||
240 | |||
103 | static struct sysdev_attribute attr_spu_temperature = { | 241 | static struct sysdev_attribute attr_spu_temperature = { |
104 | .attr = {.name = "temperature", .mode = 0400 }, | 242 | .attr = {.name = "temperature", .mode = 0400 }, |
105 | .show = spu_show_temp, | 243 | .show = spu_show_temp, |
106 | }; | 244 | }; |
107 | 245 | ||
246 | static SYSDEV_PREFIX_ATTR(spu, throttle_end, 0600); | ||
247 | static SYSDEV_PREFIX_ATTR(spu, throttle_begin, 0600); | ||
248 | static SYSDEV_PREFIX_ATTR(spu, throttle_full_stop, 0600); | ||
249 | |||
250 | |||
108 | static struct attribute *spu_attributes[] = { | 251 | static struct attribute *spu_attributes[] = { |
109 | &attr_spu_temperature.attr, | 252 | &attr_spu_temperature.attr, |
253 | &attr_spu_throttle_end.attr, | ||
254 | &attr_spu_throttle_begin.attr, | ||
255 | &attr_spu_throttle_full_stop.attr, | ||
110 | NULL, | 256 | NULL, |
111 | }; | 257 | }; |
112 | 258 | ||
@@ -125,9 +271,16 @@ static struct sysdev_attribute attr_ppe_temperature1 = { | |||
125 | .show = ppe_show_temp1, | 271 | .show = ppe_show_temp1, |
126 | }; | 272 | }; |
127 | 273 | ||
274 | static SYSDEV_PREFIX_ATTR(ppe, throttle_end, 0600); | ||
275 | static SYSDEV_PREFIX_ATTR(ppe, throttle_begin, 0600); | ||
276 | static SYSDEV_PREFIX_ATTR(ppe, throttle_full_stop, 0600); | ||
277 | |||
128 | static struct attribute *ppe_attributes[] = { | 278 | static struct attribute *ppe_attributes[] = { |
129 | &attr_ppe_temperature0.attr, | 279 | &attr_ppe_temperature0.attr, |
130 | &attr_ppe_temperature1.attr, | 280 | &attr_ppe_temperature1.attr, |
281 | &attr_ppe_throttle_end.attr, | ||
282 | &attr_ppe_throttle_begin.attr, | ||
283 | &attr_ppe_throttle_full_stop.attr, | ||
131 | NULL, | 284 | NULL, |
132 | }; | 285 | }; |
133 | 286 | ||