root/arch/powerpc/platforms/cell/cbe_thermal.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. reg_to_temp
  2. temp_to_reg
  3. get_pmd_regs
  4. spu_read_register_value
  5. spu_show_temp
  6. show_throttle
  7. store_throttle
  8. spu_show_throttle_end
  9. spu_show_throttle_begin
  10. spu_show_throttle_full_stop
  11. spu_store_throttle_end
  12. spu_store_throttle_begin
  13. spu_store_throttle_full_stop
  14. ppe_show_temp
  15. ppe_show_temp0
  16. ppe_show_temp1
  17. ppe_show_throttle_end
  18. ppe_show_throttle_begin
  19. ppe_show_throttle_full_stop
  20. ppe_store_throttle_end
  21. ppe_store_throttle_begin
  22. ppe_store_throttle_full_stop
  23. init_default_values
  24. thermal_init
  25. thermal_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * thermal support for the cell processor
   4  *
   5  * This module adds some sysfs attributes to cpu and spu nodes.
   6  * Base for measurements are the digital thermal sensors (DTS)
   7  * located on the chip.
   8  * The accuracy is 2 degrees, starting from 65 up to 125 degrees celsius
   9  * The attributes can be found under
  10  * /sys/devices/system/cpu/cpuX/thermal
  11  * /sys/devices/system/spu/spuX/thermal
  12  *
  13  * The following attributes are added for each node:
  14  * temperature:
  15  *      contains the current temperature measured by the DTS
  16  * throttle_begin:
  17  *      throttling begins when temperature is greater or equal to
  18  *      throttle_begin. Setting this value to 125 prevents throttling.
  19  * throttle_end:
  20  *      throttling is being ceased, if the temperature is lower than
  21  *      throttle_end. Due to a delay between applying throttling and
  22  *      a reduced temperature this value should be less than throttle_begin.
  23  *      A value equal to throttle_begin provides only a very little hysteresis.
  24  * throttle_full_stop:
  25  *      If the temperatrue is greater or equal to throttle_full_stop,
  26  *      full throttling is applied to the cpu or spu. This value should be
  27  *      greater than throttle_begin and throttle_end. Setting this value to
  28  *      65 prevents the unit from running code at all.
  29  *
  30  * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
  31  *
  32  * Author: Christian Krafft <krafft@de.ibm.com>
  33  */
  34 
  35 #include <linux/module.h>
  36 #include <linux/device.h>
  37 #include <linux/kernel.h>
  38 #include <linux/cpu.h>
  39 #include <linux/stringify.h>
  40 #include <asm/spu.h>
  41 #include <asm/io.h>
  42 #include <asm/prom.h>
  43 #include <asm/cell-regs.h>
  44 
  45 #include "spu_priv1_mmio.h"
  46 
  47 #define TEMP_MIN 65
  48 #define TEMP_MAX 125
  49 
  50 #define DEVICE_PREFIX_ATTR(_prefix,_name,_mode)                 \
  51 struct device_attribute attr_ ## _prefix ## _ ## _name = {      \
  52         .attr = { .name = __stringify(_name), .mode = _mode },  \
  53         .show   = _prefix ## _show_ ## _name,                   \
  54         .store  = _prefix ## _store_ ## _name,                  \
  55 };
  56 
  57 static inline u8 reg_to_temp(u8 reg_value)
  58 {
  59         return ((reg_value & 0x3f) << 1) + TEMP_MIN;
  60 }
  61 
  62 static inline u8 temp_to_reg(u8 temp)
  63 {
  64         return ((temp - TEMP_MIN) >> 1) & 0x3f;
  65 }
  66 
  67 static struct cbe_pmd_regs __iomem *get_pmd_regs(struct device *dev)
  68 {
  69         struct spu *spu;
  70 
  71         spu = container_of(dev, struct spu, dev);
  72 
  73         return cbe_get_pmd_regs(spu_devnode(spu));
  74 }
  75 
  76 /* returns the value for a given spu in a given register */
  77 static u8 spu_read_register_value(struct device *dev, union spe_reg __iomem *reg)
  78 {
  79         union spe_reg value;
  80         struct spu *spu;
  81 
  82         spu = container_of(dev, struct spu, dev);
  83         value.val = in_be64(&reg->val);
  84 
  85         return value.spe[spu->spe_id];
  86 }
  87 
  88 static ssize_t spu_show_temp(struct device *dev, struct device_attribute *attr,
  89                         char *buf)
  90 {
  91         u8 value;
  92         struct cbe_pmd_regs __iomem *pmd_regs;
  93 
  94         pmd_regs = get_pmd_regs(dev);
  95 
  96         value = spu_read_register_value(dev, &pmd_regs->ts_ctsr1);
  97 
  98         return sprintf(buf, "%d\n", reg_to_temp(value));
  99 }
 100 
 101 static ssize_t show_throttle(struct cbe_pmd_regs __iomem *pmd_regs, char *buf, int pos)
 102 {
 103         u64 value;
 104 
 105         value = in_be64(&pmd_regs->tm_tpr.val);
 106         /* access the corresponding byte */
 107         value >>= pos;
 108         value &= 0x3F;
 109 
 110         return sprintf(buf, "%d\n", reg_to_temp(value));
 111 }
 112 
 113 static ssize_t store_throttle(struct cbe_pmd_regs __iomem *pmd_regs, const char *buf, size_t size, int pos)
 114 {
 115         u64 reg_value;
 116         unsigned int temp;
 117         u64 new_value;
 118         int ret;
 119 
 120         ret = sscanf(buf, "%u", &temp);
 121 
 122         if (ret != 1 || temp < TEMP_MIN || temp > TEMP_MAX)
 123                 return -EINVAL;
 124 
 125         new_value = temp_to_reg(temp);
 126 
 127         reg_value = in_be64(&pmd_regs->tm_tpr.val);
 128 
 129         /* zero out bits for new value */
 130         reg_value &= ~(0xffull << pos);
 131         /* set bits to new value */
 132         reg_value |= new_value << pos;
 133 
 134         out_be64(&pmd_regs->tm_tpr.val, reg_value);
 135         return size;
 136 }
 137 
 138 static ssize_t spu_show_throttle_end(struct device *dev,
 139                         struct device_attribute *attr, char *buf)
 140 {
 141         return show_throttle(get_pmd_regs(dev), buf, 0);
 142 }
 143 
 144 static ssize_t spu_show_throttle_begin(struct device *dev,
 145                         struct device_attribute *attr, char *buf)
 146 {
 147         return show_throttle(get_pmd_regs(dev), buf, 8);
 148 }
 149 
 150 static ssize_t spu_show_throttle_full_stop(struct device *dev,
 151                         struct device_attribute *attr, char *buf)
 152 {
 153         return show_throttle(get_pmd_regs(dev), buf, 16);
 154 }
 155 
 156 static ssize_t spu_store_throttle_end(struct device *dev,
 157                         struct device_attribute *attr, const char *buf, size_t size)
 158 {
 159         return store_throttle(get_pmd_regs(dev), buf, size, 0);
 160 }
 161 
 162 static ssize_t spu_store_throttle_begin(struct device *dev,
 163                         struct device_attribute *attr, const char *buf, size_t size)
 164 {
 165         return store_throttle(get_pmd_regs(dev), buf, size, 8);
 166 }
 167 
 168 static ssize_t spu_store_throttle_full_stop(struct device *dev,
 169                         struct device_attribute *attr, const char *buf, size_t size)
 170 {
 171         return store_throttle(get_pmd_regs(dev), buf, size, 16);
 172 }
 173 
 174 static ssize_t ppe_show_temp(struct device *dev, char *buf, int pos)
 175 {
 176         struct cbe_pmd_regs __iomem *pmd_regs;
 177         u64 value;
 178 
 179         pmd_regs = cbe_get_cpu_pmd_regs(dev->id);
 180         value = in_be64(&pmd_regs->ts_ctsr2);
 181 
 182         value = (value >> pos) & 0x3f;
 183 
 184         return sprintf(buf, "%d\n", reg_to_temp(value));
 185 }
 186 
 187 
 188 /* shows the temperature of the DTS on the PPE,
 189  * located near the linear thermal sensor */
 190 static ssize_t ppe_show_temp0(struct device *dev,
 191                         struct device_attribute *attr, char *buf)
 192 {
 193         return ppe_show_temp(dev, buf, 32);
 194 }
 195 
 196 /* shows the temperature of the second DTS on the PPE */
 197 static ssize_t ppe_show_temp1(struct device *dev,
 198                         struct device_attribute *attr, char *buf)
 199 {
 200         return ppe_show_temp(dev, buf, 0);
 201 }
 202 
 203 static ssize_t ppe_show_throttle_end(struct device *dev,
 204                         struct device_attribute *attr, char *buf)
 205 {
 206         return show_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, 32);
 207 }
 208 
 209 static ssize_t ppe_show_throttle_begin(struct device *dev,
 210                         struct device_attribute *attr, char *buf)
 211 {
 212         return show_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, 40);
 213 }
 214 
 215 static ssize_t ppe_show_throttle_full_stop(struct device *dev,
 216                         struct device_attribute *attr, char *buf)
 217 {
 218         return show_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, 48);
 219 }
 220 
 221 static ssize_t ppe_store_throttle_end(struct device *dev,
 222                         struct device_attribute *attr, const char *buf, size_t size)
 223 {
 224         return store_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, size, 32);
 225 }
 226 
 227 static ssize_t ppe_store_throttle_begin(struct device *dev,
 228                         struct device_attribute *attr, const char *buf, size_t size)
 229 {
 230         return store_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, size, 40);
 231 }
 232 
 233 static ssize_t ppe_store_throttle_full_stop(struct device *dev,
 234                         struct device_attribute *attr, const char *buf, size_t size)
 235 {
 236         return store_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, size, 48);
 237 }
 238 
 239 
 240 static struct device_attribute attr_spu_temperature = {
 241         .attr = {.name = "temperature", .mode = 0400 },
 242         .show = spu_show_temp,
 243 };
 244 
 245 static DEVICE_PREFIX_ATTR(spu, throttle_end, 0600);
 246 static DEVICE_PREFIX_ATTR(spu, throttle_begin, 0600);
 247 static DEVICE_PREFIX_ATTR(spu, throttle_full_stop, 0600);
 248 
 249 
 250 static struct attribute *spu_attributes[] = {
 251         &attr_spu_temperature.attr,
 252         &attr_spu_throttle_end.attr,
 253         &attr_spu_throttle_begin.attr,
 254         &attr_spu_throttle_full_stop.attr,
 255         NULL,
 256 };
 257 
 258 static struct attribute_group spu_attribute_group = {
 259         .name   = "thermal",
 260         .attrs  = spu_attributes,
 261 };
 262 
 263 static struct device_attribute attr_ppe_temperature0 = {
 264         .attr = {.name = "temperature0", .mode = 0400 },
 265         .show = ppe_show_temp0,
 266 };
 267 
 268 static struct device_attribute attr_ppe_temperature1 = {
 269         .attr = {.name = "temperature1", .mode = 0400 },
 270         .show = ppe_show_temp1,
 271 };
 272 
 273 static DEVICE_PREFIX_ATTR(ppe, throttle_end, 0600);
 274 static DEVICE_PREFIX_ATTR(ppe, throttle_begin, 0600);
 275 static DEVICE_PREFIX_ATTR(ppe, throttle_full_stop, 0600);
 276 
 277 static struct attribute *ppe_attributes[] = {
 278         &attr_ppe_temperature0.attr,
 279         &attr_ppe_temperature1.attr,
 280         &attr_ppe_throttle_end.attr,
 281         &attr_ppe_throttle_begin.attr,
 282         &attr_ppe_throttle_full_stop.attr,
 283         NULL,
 284 };
 285 
 286 static struct attribute_group ppe_attribute_group = {
 287         .name   = "thermal",
 288         .attrs  = ppe_attributes,
 289 };
 290 
 291 /*
 292  * initialize throttling with default values
 293  */
 294 static int __init init_default_values(void)
 295 {
 296         int cpu;
 297         struct cbe_pmd_regs __iomem *pmd_regs;
 298         struct device *dev;
 299         union ppe_spe_reg tpr;
 300         union spe_reg str1;
 301         u64 str2;
 302         union spe_reg cr1;
 303         u64 cr2;
 304 
 305         /* TPR defaults */
 306         /* ppe
 307          *      1F - no full stop
 308          *      08 - dynamic throttling starts if over 80 degrees
 309          *      03 - dynamic throttling ceases if below 70 degrees */
 310         tpr.ppe = 0x1F0803;
 311         /* spe
 312          *      10 - full stopped when over 96 degrees
 313          *      08 - dynamic throttling starts if over 80 degrees
 314          *      03 - dynamic throttling ceases if below 70 degrees
 315          */
 316         tpr.spe = 0x100803;
 317 
 318         /* STR defaults */
 319         /* str1
 320          *      10 - stop 16 of 32 cycles
 321          */
 322         str1.val = 0x1010101010101010ull;
 323         /* str2
 324          *      10 - stop 16 of 32 cycles
 325          */
 326         str2 = 0x10;
 327 
 328         /* CR defaults */
 329         /* cr1
 330          *      4 - normal operation
 331          */
 332         cr1.val = 0x0404040404040404ull;
 333         /* cr2
 334          *      4 - normal operation
 335          */
 336         cr2 = 0x04;
 337 
 338         for_each_possible_cpu (cpu) {
 339                 pr_debug("processing cpu %d\n", cpu);
 340                 dev = get_cpu_device(cpu);
 341 
 342                 if (!dev) {
 343                         pr_info("invalid dev pointer for cbe_thermal\n");
 344                         return -EINVAL;
 345                 }
 346 
 347                 pmd_regs = cbe_get_cpu_pmd_regs(dev->id);
 348 
 349                 if (!pmd_regs) {
 350                         pr_info("invalid CBE regs pointer for cbe_thermal\n");
 351                         return -EINVAL;
 352                 }
 353 
 354                 out_be64(&pmd_regs->tm_str2, str2);
 355                 out_be64(&pmd_regs->tm_str1.val, str1.val);
 356                 out_be64(&pmd_regs->tm_tpr.val, tpr.val);
 357                 out_be64(&pmd_regs->tm_cr1.val, cr1.val);
 358                 out_be64(&pmd_regs->tm_cr2, cr2);
 359         }
 360 
 361         return 0;
 362 }
 363 
 364 
 365 static int __init thermal_init(void)
 366 {
 367         int rc = init_default_values();
 368 
 369         if (rc == 0) {
 370                 spu_add_dev_attr_group(&spu_attribute_group);
 371                 cpu_add_dev_attr_group(&ppe_attribute_group);
 372         }
 373 
 374         return rc;
 375 }
 376 module_init(thermal_init);
 377 
 378 static void __exit thermal_exit(void)
 379 {
 380         spu_remove_dev_attr_group(&spu_attribute_group);
 381         cpu_remove_dev_attr_group(&ppe_attribute_group);
 382 }
 383 module_exit(thermal_exit);
 384 
 385 MODULE_LICENSE("GPL");
 386 MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
 387 

/* [<][>][^][v][top][bottom][index][help] */