0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #include <linux/module.h>
0036 #include <linux/device.h>
0037 #include <linux/kernel.h>
0038 #include <linux/cpu.h>
0039 #include <linux/stringify.h>
0040 #include <asm/spu.h>
0041 #include <asm/io.h>
0042 #include <asm/cell-regs.h>
0043
0044 #include "spu_priv1_mmio.h"
0045
0046 #define TEMP_MIN 65
0047 #define TEMP_MAX 125
0048
0049 #define DEVICE_PREFIX_ATTR(_prefix,_name,_mode) \
0050 struct device_attribute attr_ ## _prefix ## _ ## _name = { \
0051 .attr = { .name = __stringify(_name), .mode = _mode }, \
0052 .show = _prefix ## _show_ ## _name, \
0053 .store = _prefix ## _store_ ## _name, \
0054 };
0055
0056 static inline u8 reg_to_temp(u8 reg_value)
0057 {
0058 return ((reg_value & 0x3f) << 1) + TEMP_MIN;
0059 }
0060
0061 static inline u8 temp_to_reg(u8 temp)
0062 {
0063 return ((temp - TEMP_MIN) >> 1) & 0x3f;
0064 }
0065
0066 static struct cbe_pmd_regs __iomem *get_pmd_regs(struct device *dev)
0067 {
0068 struct spu *spu;
0069
0070 spu = container_of(dev, struct spu, dev);
0071
0072 return cbe_get_pmd_regs(spu_devnode(spu));
0073 }
0074
0075
0076 static u8 spu_read_register_value(struct device *dev, union spe_reg __iomem *reg)
0077 {
0078 union spe_reg value;
0079 struct spu *spu;
0080
0081 spu = container_of(dev, struct spu, dev);
0082 value.val = in_be64(®->val);
0083
0084 return value.spe[spu->spe_id];
0085 }
0086
0087 static ssize_t spu_show_temp(struct device *dev, struct device_attribute *attr,
0088 char *buf)
0089 {
0090 u8 value;
0091 struct cbe_pmd_regs __iomem *pmd_regs;
0092
0093 pmd_regs = get_pmd_regs(dev);
0094
0095 value = spu_read_register_value(dev, &pmd_regs->ts_ctsr1);
0096
0097 return sprintf(buf, "%d\n", reg_to_temp(value));
0098 }
0099
0100 static ssize_t show_throttle(struct cbe_pmd_regs __iomem *pmd_regs, char *buf, int pos)
0101 {
0102 u64 value;
0103
0104 value = in_be64(&pmd_regs->tm_tpr.val);
0105
0106 value >>= pos;
0107 value &= 0x3F;
0108
0109 return sprintf(buf, "%d\n", reg_to_temp(value));
0110 }
0111
0112 static ssize_t store_throttle(struct cbe_pmd_regs __iomem *pmd_regs, const char *buf, size_t size, int pos)
0113 {
0114 u64 reg_value;
0115 unsigned int temp;
0116 u64 new_value;
0117 int ret;
0118
0119 ret = sscanf(buf, "%u", &temp);
0120
0121 if (ret != 1 || temp < TEMP_MIN || temp > TEMP_MAX)
0122 return -EINVAL;
0123
0124 new_value = temp_to_reg(temp);
0125
0126 reg_value = in_be64(&pmd_regs->tm_tpr.val);
0127
0128
0129 reg_value &= ~(0xffull << pos);
0130
0131 reg_value |= new_value << pos;
0132
0133 out_be64(&pmd_regs->tm_tpr.val, reg_value);
0134 return size;
0135 }
0136
0137 static ssize_t spu_show_throttle_end(struct device *dev,
0138 struct device_attribute *attr, char *buf)
0139 {
0140 return show_throttle(get_pmd_regs(dev), buf, 0);
0141 }
0142
0143 static ssize_t spu_show_throttle_begin(struct device *dev,
0144 struct device_attribute *attr, char *buf)
0145 {
0146 return show_throttle(get_pmd_regs(dev), buf, 8);
0147 }
0148
0149 static ssize_t spu_show_throttle_full_stop(struct device *dev,
0150 struct device_attribute *attr, char *buf)
0151 {
0152 return show_throttle(get_pmd_regs(dev), buf, 16);
0153 }
0154
0155 static ssize_t spu_store_throttle_end(struct device *dev,
0156 struct device_attribute *attr, const char *buf, size_t size)
0157 {
0158 return store_throttle(get_pmd_regs(dev), buf, size, 0);
0159 }
0160
0161 static ssize_t spu_store_throttle_begin(struct device *dev,
0162 struct device_attribute *attr, const char *buf, size_t size)
0163 {
0164 return store_throttle(get_pmd_regs(dev), buf, size, 8);
0165 }
0166
0167 static ssize_t spu_store_throttle_full_stop(struct device *dev,
0168 struct device_attribute *attr, const char *buf, size_t size)
0169 {
0170 return store_throttle(get_pmd_regs(dev), buf, size, 16);
0171 }
0172
0173 static ssize_t ppe_show_temp(struct device *dev, char *buf, int pos)
0174 {
0175 struct cbe_pmd_regs __iomem *pmd_regs;
0176 u64 value;
0177
0178 pmd_regs = cbe_get_cpu_pmd_regs(dev->id);
0179 value = in_be64(&pmd_regs->ts_ctsr2);
0180
0181 value = (value >> pos) & 0x3f;
0182
0183 return sprintf(buf, "%d\n", reg_to_temp(value));
0184 }
0185
0186
0187
0188
0189 static ssize_t ppe_show_temp0(struct device *dev,
0190 struct device_attribute *attr, char *buf)
0191 {
0192 return ppe_show_temp(dev, buf, 32);
0193 }
0194
0195
0196 static ssize_t ppe_show_temp1(struct device *dev,
0197 struct device_attribute *attr, char *buf)
0198 {
0199 return ppe_show_temp(dev, buf, 0);
0200 }
0201
0202 static ssize_t ppe_show_throttle_end(struct device *dev,
0203 struct device_attribute *attr, char *buf)
0204 {
0205 return show_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, 32);
0206 }
0207
0208 static ssize_t ppe_show_throttle_begin(struct device *dev,
0209 struct device_attribute *attr, char *buf)
0210 {
0211 return show_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, 40);
0212 }
0213
0214 static ssize_t ppe_show_throttle_full_stop(struct device *dev,
0215 struct device_attribute *attr, char *buf)
0216 {
0217 return show_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, 48);
0218 }
0219
0220 static ssize_t ppe_store_throttle_end(struct device *dev,
0221 struct device_attribute *attr, const char *buf, size_t size)
0222 {
0223 return store_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, size, 32);
0224 }
0225
0226 static ssize_t ppe_store_throttle_begin(struct device *dev,
0227 struct device_attribute *attr, const char *buf, size_t size)
0228 {
0229 return store_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, size, 40);
0230 }
0231
0232 static ssize_t ppe_store_throttle_full_stop(struct device *dev,
0233 struct device_attribute *attr, const char *buf, size_t size)
0234 {
0235 return store_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, size, 48);
0236 }
0237
0238
0239 static struct device_attribute attr_spu_temperature = {
0240 .attr = {.name = "temperature", .mode = 0400 },
0241 .show = spu_show_temp,
0242 };
0243
0244 static DEVICE_PREFIX_ATTR(spu, throttle_end, 0600);
0245 static DEVICE_PREFIX_ATTR(spu, throttle_begin, 0600);
0246 static DEVICE_PREFIX_ATTR(spu, throttle_full_stop, 0600);
0247
0248
0249 static struct attribute *spu_attributes[] = {
0250 &attr_spu_temperature.attr,
0251 &attr_spu_throttle_end.attr,
0252 &attr_spu_throttle_begin.attr,
0253 &attr_spu_throttle_full_stop.attr,
0254 NULL,
0255 };
0256
0257 static const struct attribute_group spu_attribute_group = {
0258 .name = "thermal",
0259 .attrs = spu_attributes,
0260 };
0261
0262 static struct device_attribute attr_ppe_temperature0 = {
0263 .attr = {.name = "temperature0", .mode = 0400 },
0264 .show = ppe_show_temp0,
0265 };
0266
0267 static struct device_attribute attr_ppe_temperature1 = {
0268 .attr = {.name = "temperature1", .mode = 0400 },
0269 .show = ppe_show_temp1,
0270 };
0271
0272 static DEVICE_PREFIX_ATTR(ppe, throttle_end, 0600);
0273 static DEVICE_PREFIX_ATTR(ppe, throttle_begin, 0600);
0274 static DEVICE_PREFIX_ATTR(ppe, throttle_full_stop, 0600);
0275
0276 static struct attribute *ppe_attributes[] = {
0277 &attr_ppe_temperature0.attr,
0278 &attr_ppe_temperature1.attr,
0279 &attr_ppe_throttle_end.attr,
0280 &attr_ppe_throttle_begin.attr,
0281 &attr_ppe_throttle_full_stop.attr,
0282 NULL,
0283 };
0284
0285 static struct attribute_group ppe_attribute_group = {
0286 .name = "thermal",
0287 .attrs = ppe_attributes,
0288 };
0289
0290
0291
0292
0293 static int __init init_default_values(void)
0294 {
0295 int cpu;
0296 struct cbe_pmd_regs __iomem *pmd_regs;
0297 struct device *dev;
0298 union ppe_spe_reg tpr;
0299 union spe_reg str1;
0300 u64 str2;
0301 union spe_reg cr1;
0302 u64 cr2;
0303
0304
0305
0306
0307
0308
0309 tpr.ppe = 0x1F0803;
0310
0311
0312
0313
0314
0315 tpr.spe = 0x100803;
0316
0317
0318
0319
0320
0321 str1.val = 0x1010101010101010ull;
0322
0323
0324
0325 str2 = 0x10;
0326
0327
0328
0329
0330
0331 cr1.val = 0x0404040404040404ull;
0332
0333
0334
0335 cr2 = 0x04;
0336
0337 for_each_possible_cpu (cpu) {
0338 pr_debug("processing cpu %d\n", cpu);
0339 dev = get_cpu_device(cpu);
0340
0341 if (!dev) {
0342 pr_info("invalid dev pointer for cbe_thermal\n");
0343 return -EINVAL;
0344 }
0345
0346 pmd_regs = cbe_get_cpu_pmd_regs(dev->id);
0347
0348 if (!pmd_regs) {
0349 pr_info("invalid CBE regs pointer for cbe_thermal\n");
0350 return -EINVAL;
0351 }
0352
0353 out_be64(&pmd_regs->tm_str2, str2);
0354 out_be64(&pmd_regs->tm_str1.val, str1.val);
0355 out_be64(&pmd_regs->tm_tpr.val, tpr.val);
0356 out_be64(&pmd_regs->tm_cr1.val, cr1.val);
0357 out_be64(&pmd_regs->tm_cr2, cr2);
0358 }
0359
0360 return 0;
0361 }
0362
0363
0364 static int __init thermal_init(void)
0365 {
0366 int rc = init_default_values();
0367
0368 if (rc == 0) {
0369 spu_add_dev_attr_group(&spu_attribute_group);
0370 cpu_add_dev_attr_group(&ppe_attribute_group);
0371 }
0372
0373 return rc;
0374 }
0375 module_init(thermal_init);
0376
0377 static void __exit thermal_exit(void)
0378 {
0379 spu_remove_dev_attr_group(&spu_attribute_group);
0380 cpu_remove_dev_attr_group(&ppe_attribute_group);
0381 }
0382 module_exit(thermal_exit);
0383
0384 MODULE_LICENSE("GPL");
0385 MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
0386