diff options
author | Christian Krafft <krafft@de.ibm.com> | 2006-10-24 12:31:25 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-10-25 00:20:22 -0400 |
commit | b3d7dc1967d1303d4897ff9537d29f6e077de147 (patch) | |
tree | 7717eb9fbcbc60c418233ea9773badc5fbfd8099 | |
parent | 0344c6c5387ba335bba5a66fd44714b94c98573f (diff) |
[POWERPC] cell: add temperature to SPU and CPU sysfs entries
This patch adds a module that registers sysfs attributes to CPU and SPU
containing the temperature of the CBE.
They can be found under
/sys/devices/system/spu/cpuX/thermal/temperature[0|1]
/sys/devices/system/spu/spuX/thermal/temperature
The temperature is read from the on-chip temperature sensors.
Signed-off-by: Christian Krafft <krafft@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r-- | arch/powerpc/configs/cell_defconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/Kconfig | 5 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/cell/cbe_thermal.c | 225 |
4 files changed, 233 insertions, 0 deletions
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index 892d5dd3254e..910a33193d9d 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig | |||
@@ -149,6 +149,7 @@ CONFIG_MMIO_NVRAM=y | |||
149 | CONFIG_SPU_FS=m | 149 | CONFIG_SPU_FS=m |
150 | CONFIG_SPU_BASE=y | 150 | CONFIG_SPU_BASE=y |
151 | CONFIG_CBE_RAS=y | 151 | CONFIG_CBE_RAS=y |
152 | CONFIG_CBE_THERM=m | ||
152 | 153 | ||
153 | # | 154 | # |
154 | # Kernel options | 155 | # Kernel options |
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 3e430b489bb7..77ae619c7581 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig | |||
@@ -20,4 +20,9 @@ config CBE_RAS | |||
20 | bool "RAS features for bare metal Cell BE" | 20 | bool "RAS features for bare metal Cell BE" |
21 | default y | 21 | default y |
22 | 22 | ||
23 | config CBE_THERM | ||
24 | tristate "CBE thermal support" | ||
25 | default m | ||
26 | depends on CBE_RAS | ||
27 | |||
23 | endmenu | 28 | endmenu |
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index 412649b3529c..90e131451af1 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile | |||
@@ -3,6 +3,8 @@ obj-$(CONFIG_PPC_CELL_NATIVE) += interrupt.o iommu.o setup.o \ | |||
3 | pmu.o | 3 | pmu.o |
4 | obj-$(CONFIG_CBE_RAS) += ras.o | 4 | obj-$(CONFIG_CBE_RAS) += ras.o |
5 | 5 | ||
6 | obj-$(CONFIG_CBE_THERM) += cbe_thermal.o | ||
7 | |||
6 | ifeq ($(CONFIG_SMP),y) | 8 | ifeq ($(CONFIG_SMP),y) |
7 | obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o | 9 | obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o |
8 | endif | 10 | endif |
diff --git a/arch/powerpc/platforms/cell/cbe_thermal.c b/arch/powerpc/platforms/cell/cbe_thermal.c new file mode 100644 index 000000000000..17831a92d91e --- /dev/null +++ b/arch/powerpc/platforms/cell/cbe_thermal.c | |||
@@ -0,0 +1,225 @@ | |||
1 | /* | ||
2 | * thermal support for the cell processor | ||
3 | * | ||
4 | * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 | ||
5 | * | ||
6 | * Author: Christian Krafft <krafft@de.ibm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2, or (at your option) | ||
11 | * any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/sysdev.h> | ||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/cpu.h> | ||
27 | #include <asm/spu.h> | ||
28 | #include <asm/io.h> | ||
29 | #include <asm/prom.h> | ||
30 | |||
31 | #include "cbe_regs.h" | ||
32 | |||
33 | static struct cbe_pmd_regs __iomem *get_pmd_regs(struct sys_device *sysdev) | ||
34 | { | ||
35 | struct spu *spu; | ||
36 | |||
37 | spu = container_of(sysdev, struct spu, sysdev); | ||
38 | |||
39 | return cbe_get_pmd_regs(spu->devnode); | ||
40 | } | ||
41 | |||
42 | /* returns the value for a given spu in a given register */ | ||
43 | static u8 spu_read_register_value(struct sys_device *sysdev, union spe_reg __iomem *reg) | ||
44 | { | ||
45 | unsigned int *id; | ||
46 | union spe_reg value; | ||
47 | struct spu *spu; | ||
48 | |||
49 | /* getting the id from the reg attribute will not work on future device-tree layouts | ||
50 | * in future we should store the id to the spu struct and use it here */ | ||
51 | spu = container_of(sysdev, struct spu, sysdev); | ||
52 | id = (unsigned int *)get_property(spu->devnode, "reg", NULL); | ||
53 | value.val = in_be64(®->val); | ||
54 | |||
55 | return value.spe[*id]; | ||
56 | } | ||
57 | |||
58 | static ssize_t spu_show_temp(struct sys_device *sysdev, char *buf) | ||
59 | { | ||
60 | int value; | ||
61 | struct cbe_pmd_regs __iomem *pmd_regs; | ||
62 | |||
63 | pmd_regs = get_pmd_regs(sysdev); | ||
64 | |||
65 | value = spu_read_register_value(sysdev, &pmd_regs->ts_ctsr1); | ||
66 | /* clear all other bits */ | ||
67 | value &= 0x3F; | ||
68 | /* temp is stored in steps of 2 degrees */ | ||
69 | value *= 2; | ||
70 | /* base temp is 65 degrees */ | ||
71 | value += 65; | ||
72 | |||
73 | return sprintf(buf, "%d\n", (int) value); | ||
74 | } | ||
75 | |||
76 | static ssize_t ppe_show_temp(struct sys_device *sysdev, char *buf, int pos) | ||
77 | { | ||
78 | struct cbe_pmd_regs __iomem *pmd_regs; | ||
79 | u64 value; | ||
80 | |||
81 | pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id); | ||
82 | value = in_be64(&pmd_regs->ts_ctsr2); | ||
83 | |||
84 | /* access the corresponding byte */ | ||
85 | value >>= pos; | ||
86 | /* clear all other bits */ | ||
87 | value &= 0x3F; | ||
88 | /* temp is stored in steps of 2 degrees */ | ||
89 | value *= 2; | ||
90 | /* base temp is 65 degrees */ | ||
91 | value += 65; | ||
92 | |||
93 | return sprintf(buf, "%d\n", (int) value); | ||
94 | } | ||
95 | |||
96 | |||
97 | /* shows the temperature of the DTS on the PPE, | ||
98 | * located near the linear thermal sensor */ | ||
99 | static ssize_t ppe_show_temp0(struct sys_device *sysdev, char *buf) | ||
100 | { | ||
101 | return ppe_show_temp(sysdev, buf, 32); | ||
102 | } | ||
103 | |||
104 | /* shows the temperature of the second DTS on the PPE */ | ||
105 | static ssize_t ppe_show_temp1(struct sys_device *sysdev, char *buf) | ||
106 | { | ||
107 | return ppe_show_temp(sysdev, buf, 0); | ||
108 | } | ||
109 | |||
110 | static struct sysdev_attribute attr_spu_temperature = { | ||
111 | .attr = {.name = "temperature", .mode = 0400 }, | ||
112 | .show = spu_show_temp, | ||
113 | }; | ||
114 | |||
115 | static struct attribute *spu_attributes[] = { | ||
116 | &attr_spu_temperature.attr, | ||
117 | }; | ||
118 | |||
119 | static struct attribute_group spu_attribute_group = { | ||
120 | .name = "thermal", | ||
121 | .attrs = spu_attributes, | ||
122 | }; | ||
123 | |||
124 | static struct sysdev_attribute attr_ppe_temperature0 = { | ||
125 | .attr = {.name = "temperature0", .mode = 0400 }, | ||
126 | .show = ppe_show_temp0, | ||
127 | }; | ||
128 | |||
129 | static struct sysdev_attribute attr_ppe_temperature1 = { | ||
130 | .attr = {.name = "temperature1", .mode = 0400 }, | ||
131 | .show = ppe_show_temp1, | ||
132 | }; | ||
133 | |||
134 | static struct attribute *ppe_attributes[] = { | ||
135 | &attr_ppe_temperature0.attr, | ||
136 | &attr_ppe_temperature1.attr, | ||
137 | }; | ||
138 | |||
139 | static struct attribute_group ppe_attribute_group = { | ||
140 | .name = "thermal", | ||
141 | .attrs = ppe_attributes, | ||
142 | }; | ||
143 | |||
144 | /* | ||
145 | * initialize throttling with default values | ||
146 | */ | ||
147 | static void __init init_default_values(void) | ||
148 | { | ||
149 | int cpu; | ||
150 | struct cbe_pmd_regs __iomem *pmd_regs; | ||
151 | struct sys_device *sysdev; | ||
152 | union ppe_spe_reg tpr; | ||
153 | union spe_reg str1; | ||
154 | u64 str2; | ||
155 | union spe_reg cr1; | ||
156 | u64 cr2; | ||
157 | |||
158 | /* TPR defaults */ | ||
159 | /* ppe | ||
160 | * 1F - no full stop | ||
161 | * 08 - dynamic throttling starts if over 80 degrees | ||
162 | * 03 - dynamic throttling ceases if below 70 degrees */ | ||
163 | tpr.ppe = 0x1F0803; | ||
164 | /* spe | ||
165 | * 10 - full stopped when over 96 degrees | ||
166 | * 08 - dynamic throttling starts if over 80 degrees | ||
167 | * 03 - dynamic throttling ceases if below 70 degrees | ||
168 | */ | ||
169 | tpr.spe = 0x100803; | ||
170 | |||
171 | /* STR defaults */ | ||
172 | /* str1 | ||
173 | * 10 - stop 16 of 32 cycles | ||
174 | */ | ||
175 | str1.val = 0x1010101010101010ull; | ||
176 | /* str2 | ||
177 | * 10 - stop 16 of 32 cycles | ||
178 | */ | ||
179 | str2 = 0x10; | ||
180 | |||
181 | /* CR defaults */ | ||
182 | /* cr1 | ||
183 | * 4 - normal operation | ||
184 | */ | ||
185 | cr1.val = 0x0404040404040404ull; | ||
186 | /* cr2 | ||
187 | * 4 - normal operation | ||
188 | */ | ||
189 | cr2 = 0x04; | ||
190 | |||
191 | for_each_possible_cpu (cpu) { | ||
192 | pr_debug("processing cpu %d\n", cpu); | ||
193 | sysdev = get_cpu_sysdev(cpu); | ||
194 | pmd_regs = cbe_get_cpu_pmd_regs(sysdev->id); | ||
195 | |||
196 | out_be64(&pmd_regs->tm_str2, str2); | ||
197 | out_be64(&pmd_regs->tm_str1.val, str1.val); | ||
198 | out_be64(&pmd_regs->tm_tpr.val, tpr.val); | ||
199 | out_be64(&pmd_regs->tm_cr1.val, cr1.val); | ||
200 | out_be64(&pmd_regs->tm_cr2, cr2); | ||
201 | } | ||
202 | } | ||
203 | |||
204 | |||
205 | static int __init thermal_init(void) | ||
206 | { | ||
207 | init_default_values(); | ||
208 | |||
209 | spu_add_sysdev_attr_group(&spu_attribute_group); | ||
210 | cpu_add_sysdev_attr_group(&ppe_attribute_group); | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | module_init(thermal_init); | ||
215 | |||
216 | static void __exit thermal_exit(void) | ||
217 | { | ||
218 | spu_remove_sysdev_attr_group(&spu_attribute_group); | ||
219 | cpu_remove_sysdev_attr_group(&ppe_attribute_group); | ||
220 | } | ||
221 | module_exit(thermal_exit); | ||
222 | |||
223 | MODULE_LICENSE("GPL"); | ||
224 | MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>"); | ||
225 | |||