18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * thermal support for the cell processor 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This module adds some sysfs attributes to cpu and spu nodes. 68c2ecf20Sopenharmony_ci * Base for measurements are the digital thermal sensors (DTS) 78c2ecf20Sopenharmony_ci * located on the chip. 88c2ecf20Sopenharmony_ci * The accuracy is 2 degrees, starting from 65 up to 125 degrees celsius 98c2ecf20Sopenharmony_ci * The attributes can be found under 108c2ecf20Sopenharmony_ci * /sys/devices/system/cpu/cpuX/thermal 118c2ecf20Sopenharmony_ci * /sys/devices/system/spu/spuX/thermal 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * The following attributes are added for each node: 148c2ecf20Sopenharmony_ci * temperature: 158c2ecf20Sopenharmony_ci * contains the current temperature measured by the DTS 168c2ecf20Sopenharmony_ci * throttle_begin: 178c2ecf20Sopenharmony_ci * throttling begins when temperature is greater or equal to 188c2ecf20Sopenharmony_ci * throttle_begin. Setting this value to 125 prevents throttling. 198c2ecf20Sopenharmony_ci * throttle_end: 208c2ecf20Sopenharmony_ci * throttling is being ceased, if the temperature is lower than 218c2ecf20Sopenharmony_ci * throttle_end. Due to a delay between applying throttling and 228c2ecf20Sopenharmony_ci * a reduced temperature this value should be less than throttle_begin. 238c2ecf20Sopenharmony_ci * A value equal to throttle_begin provides only a very little hysteresis. 248c2ecf20Sopenharmony_ci * throttle_full_stop: 258c2ecf20Sopenharmony_ci * If the temperatrue is greater or equal to throttle_full_stop, 268c2ecf20Sopenharmony_ci * full throttling is applied to the cpu or spu. This value should be 278c2ecf20Sopenharmony_ci * greater than throttle_begin and throttle_end. Setting this value to 288c2ecf20Sopenharmony_ci * 65 prevents the unit from running code at all. 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 318c2ecf20Sopenharmony_ci * 328c2ecf20Sopenharmony_ci * Author: Christian Krafft <krafft@de.ibm.com> 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include <linux/module.h> 368c2ecf20Sopenharmony_ci#include <linux/device.h> 378c2ecf20Sopenharmony_ci#include <linux/kernel.h> 388c2ecf20Sopenharmony_ci#include <linux/cpu.h> 398c2ecf20Sopenharmony_ci#include <linux/stringify.h> 408c2ecf20Sopenharmony_ci#include <asm/spu.h> 418c2ecf20Sopenharmony_ci#include <asm/io.h> 428c2ecf20Sopenharmony_ci#include <asm/prom.h> 438c2ecf20Sopenharmony_ci#include <asm/cell-regs.h> 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#include "spu_priv1_mmio.h" 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#define TEMP_MIN 65 488c2ecf20Sopenharmony_ci#define TEMP_MAX 125 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#define DEVICE_PREFIX_ATTR(_prefix,_name,_mode) \ 518c2ecf20Sopenharmony_cistruct device_attribute attr_ ## _prefix ## _ ## _name = { \ 528c2ecf20Sopenharmony_ci .attr = { .name = __stringify(_name), .mode = _mode }, \ 538c2ecf20Sopenharmony_ci .show = _prefix ## _show_ ## _name, \ 548c2ecf20Sopenharmony_ci .store = _prefix ## _store_ ## _name, \ 558c2ecf20Sopenharmony_ci}; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cistatic inline u8 reg_to_temp(u8 reg_value) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci return ((reg_value & 0x3f) << 1) + TEMP_MIN; 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic inline u8 temp_to_reg(u8 temp) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci return ((temp - TEMP_MIN) >> 1) & 0x3f; 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic struct cbe_pmd_regs __iomem *get_pmd_regs(struct device *dev) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci struct spu *spu; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci spu = container_of(dev, struct spu, dev); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci return cbe_get_pmd_regs(spu_devnode(spu)); 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci/* returns the value for a given spu in a given register */ 778c2ecf20Sopenharmony_cistatic u8 spu_read_register_value(struct device *dev, union spe_reg __iomem *reg) 788c2ecf20Sopenharmony_ci{ 798c2ecf20Sopenharmony_ci union spe_reg value; 808c2ecf20Sopenharmony_ci struct spu *spu; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci spu = container_of(dev, struct spu, dev); 838c2ecf20Sopenharmony_ci value.val = in_be64(®->val); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci return value.spe[spu->spe_id]; 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_cistatic ssize_t spu_show_temp(struct device *dev, struct device_attribute *attr, 898c2ecf20Sopenharmony_ci char *buf) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci u8 value; 928c2ecf20Sopenharmony_ci struct cbe_pmd_regs __iomem *pmd_regs; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci pmd_regs = get_pmd_regs(dev); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci value = spu_read_register_value(dev, &pmd_regs->ts_ctsr1); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", reg_to_temp(value)); 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistatic ssize_t show_throttle(struct cbe_pmd_regs __iomem *pmd_regs, char *buf, int pos) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci u64 value; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci value = in_be64(&pmd_regs->tm_tpr.val); 1068c2ecf20Sopenharmony_ci /* access the corresponding byte */ 1078c2ecf20Sopenharmony_ci value >>= pos; 1088c2ecf20Sopenharmony_ci value &= 0x3F; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", reg_to_temp(value)); 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistatic ssize_t store_throttle(struct cbe_pmd_regs __iomem *pmd_regs, const char *buf, size_t size, int pos) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci u64 reg_value; 1168c2ecf20Sopenharmony_ci unsigned int temp; 1178c2ecf20Sopenharmony_ci u64 new_value; 1188c2ecf20Sopenharmony_ci int ret; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci ret = sscanf(buf, "%u", &temp); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci if (ret != 1 || temp < TEMP_MIN || temp > TEMP_MAX) 1238c2ecf20Sopenharmony_ci return -EINVAL; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci new_value = temp_to_reg(temp); 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci reg_value = in_be64(&pmd_regs->tm_tpr.val); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci /* zero out bits for new value */ 1308c2ecf20Sopenharmony_ci reg_value &= ~(0xffull << pos); 1318c2ecf20Sopenharmony_ci /* set bits to new value */ 1328c2ecf20Sopenharmony_ci reg_value |= new_value << pos; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci out_be64(&pmd_regs->tm_tpr.val, reg_value); 1358c2ecf20Sopenharmony_ci return size; 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic ssize_t spu_show_throttle_end(struct device *dev, 1398c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci return show_throttle(get_pmd_regs(dev), buf, 0); 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic ssize_t spu_show_throttle_begin(struct device *dev, 1458c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci return show_throttle(get_pmd_regs(dev), buf, 8); 1488c2ecf20Sopenharmony_ci} 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_cistatic ssize_t spu_show_throttle_full_stop(struct device *dev, 1518c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci return show_throttle(get_pmd_regs(dev), buf, 16); 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistatic ssize_t spu_store_throttle_end(struct device *dev, 1578c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, size_t size) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci return store_throttle(get_pmd_regs(dev), buf, size, 0); 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistatic ssize_t spu_store_throttle_begin(struct device *dev, 1638c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, size_t size) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci return store_throttle(get_pmd_regs(dev), buf, size, 8); 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic ssize_t spu_store_throttle_full_stop(struct device *dev, 1698c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, size_t size) 1708c2ecf20Sopenharmony_ci{ 1718c2ecf20Sopenharmony_ci return store_throttle(get_pmd_regs(dev), buf, size, 16); 1728c2ecf20Sopenharmony_ci} 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic ssize_t ppe_show_temp(struct device *dev, char *buf, int pos) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci struct cbe_pmd_regs __iomem *pmd_regs; 1778c2ecf20Sopenharmony_ci u64 value; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci pmd_regs = cbe_get_cpu_pmd_regs(dev->id); 1808c2ecf20Sopenharmony_ci value = in_be64(&pmd_regs->ts_ctsr2); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci value = (value >> pos) & 0x3f; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", reg_to_temp(value)); 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci/* shows the temperature of the DTS on the PPE, 1898c2ecf20Sopenharmony_ci * located near the linear thermal sensor */ 1908c2ecf20Sopenharmony_cistatic ssize_t ppe_show_temp0(struct device *dev, 1918c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 1928c2ecf20Sopenharmony_ci{ 1938c2ecf20Sopenharmony_ci return ppe_show_temp(dev, buf, 32); 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci/* shows the temperature of the second DTS on the PPE */ 1978c2ecf20Sopenharmony_cistatic ssize_t ppe_show_temp1(struct device *dev, 1988c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci return ppe_show_temp(dev, buf, 0); 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic ssize_t ppe_show_throttle_end(struct device *dev, 2048c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 2058c2ecf20Sopenharmony_ci{ 2068c2ecf20Sopenharmony_ci return show_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, 32); 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cistatic ssize_t ppe_show_throttle_begin(struct device *dev, 2108c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 2118c2ecf20Sopenharmony_ci{ 2128c2ecf20Sopenharmony_ci return show_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, 40); 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic ssize_t ppe_show_throttle_full_stop(struct device *dev, 2168c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci return show_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, 48); 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_cistatic ssize_t ppe_store_throttle_end(struct device *dev, 2228c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, size_t size) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci return store_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, size, 32); 2258c2ecf20Sopenharmony_ci} 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistatic ssize_t ppe_store_throttle_begin(struct device *dev, 2288c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, size_t size) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci return store_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, size, 40); 2318c2ecf20Sopenharmony_ci} 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_cistatic ssize_t ppe_store_throttle_full_stop(struct device *dev, 2348c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, size_t size) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci return store_throttle(cbe_get_cpu_pmd_regs(dev->id), buf, size, 48); 2378c2ecf20Sopenharmony_ci} 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_cistatic struct device_attribute attr_spu_temperature = { 2418c2ecf20Sopenharmony_ci .attr = {.name = "temperature", .mode = 0400 }, 2428c2ecf20Sopenharmony_ci .show = spu_show_temp, 2438c2ecf20Sopenharmony_ci}; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_cistatic DEVICE_PREFIX_ATTR(spu, throttle_end, 0600); 2468c2ecf20Sopenharmony_cistatic DEVICE_PREFIX_ATTR(spu, throttle_begin, 0600); 2478c2ecf20Sopenharmony_cistatic DEVICE_PREFIX_ATTR(spu, throttle_full_stop, 0600); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_cistatic struct attribute *spu_attributes[] = { 2518c2ecf20Sopenharmony_ci &attr_spu_temperature.attr, 2528c2ecf20Sopenharmony_ci &attr_spu_throttle_end.attr, 2538c2ecf20Sopenharmony_ci &attr_spu_throttle_begin.attr, 2548c2ecf20Sopenharmony_ci &attr_spu_throttle_full_stop.attr, 2558c2ecf20Sopenharmony_ci NULL, 2568c2ecf20Sopenharmony_ci}; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_cistatic struct attribute_group spu_attribute_group = { 2598c2ecf20Sopenharmony_ci .name = "thermal", 2608c2ecf20Sopenharmony_ci .attrs = spu_attributes, 2618c2ecf20Sopenharmony_ci}; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_cistatic struct device_attribute attr_ppe_temperature0 = { 2648c2ecf20Sopenharmony_ci .attr = {.name = "temperature0", .mode = 0400 }, 2658c2ecf20Sopenharmony_ci .show = ppe_show_temp0, 2668c2ecf20Sopenharmony_ci}; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_cistatic struct device_attribute attr_ppe_temperature1 = { 2698c2ecf20Sopenharmony_ci .attr = {.name = "temperature1", .mode = 0400 }, 2708c2ecf20Sopenharmony_ci .show = ppe_show_temp1, 2718c2ecf20Sopenharmony_ci}; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_cistatic DEVICE_PREFIX_ATTR(ppe, throttle_end, 0600); 2748c2ecf20Sopenharmony_cistatic DEVICE_PREFIX_ATTR(ppe, throttle_begin, 0600); 2758c2ecf20Sopenharmony_cistatic DEVICE_PREFIX_ATTR(ppe, throttle_full_stop, 0600); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_cistatic struct attribute *ppe_attributes[] = { 2788c2ecf20Sopenharmony_ci &attr_ppe_temperature0.attr, 2798c2ecf20Sopenharmony_ci &attr_ppe_temperature1.attr, 2808c2ecf20Sopenharmony_ci &attr_ppe_throttle_end.attr, 2818c2ecf20Sopenharmony_ci &attr_ppe_throttle_begin.attr, 2828c2ecf20Sopenharmony_ci &attr_ppe_throttle_full_stop.attr, 2838c2ecf20Sopenharmony_ci NULL, 2848c2ecf20Sopenharmony_ci}; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cistatic struct attribute_group ppe_attribute_group = { 2878c2ecf20Sopenharmony_ci .name = "thermal", 2888c2ecf20Sopenharmony_ci .attrs = ppe_attributes, 2898c2ecf20Sopenharmony_ci}; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci/* 2928c2ecf20Sopenharmony_ci * initialize throttling with default values 2938c2ecf20Sopenharmony_ci */ 2948c2ecf20Sopenharmony_cistatic int __init init_default_values(void) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci int cpu; 2978c2ecf20Sopenharmony_ci struct cbe_pmd_regs __iomem *pmd_regs; 2988c2ecf20Sopenharmony_ci struct device *dev; 2998c2ecf20Sopenharmony_ci union ppe_spe_reg tpr; 3008c2ecf20Sopenharmony_ci union spe_reg str1; 3018c2ecf20Sopenharmony_ci u64 str2; 3028c2ecf20Sopenharmony_ci union spe_reg cr1; 3038c2ecf20Sopenharmony_ci u64 cr2; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci /* TPR defaults */ 3068c2ecf20Sopenharmony_ci /* ppe 3078c2ecf20Sopenharmony_ci * 1F - no full stop 3088c2ecf20Sopenharmony_ci * 08 - dynamic throttling starts if over 80 degrees 3098c2ecf20Sopenharmony_ci * 03 - dynamic throttling ceases if below 70 degrees */ 3108c2ecf20Sopenharmony_ci tpr.ppe = 0x1F0803; 3118c2ecf20Sopenharmony_ci /* spe 3128c2ecf20Sopenharmony_ci * 10 - full stopped when over 96 degrees 3138c2ecf20Sopenharmony_ci * 08 - dynamic throttling starts if over 80 degrees 3148c2ecf20Sopenharmony_ci * 03 - dynamic throttling ceases if below 70 degrees 3158c2ecf20Sopenharmony_ci */ 3168c2ecf20Sopenharmony_ci tpr.spe = 0x100803; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci /* STR defaults */ 3198c2ecf20Sopenharmony_ci /* str1 3208c2ecf20Sopenharmony_ci * 10 - stop 16 of 32 cycles 3218c2ecf20Sopenharmony_ci */ 3228c2ecf20Sopenharmony_ci str1.val = 0x1010101010101010ull; 3238c2ecf20Sopenharmony_ci /* str2 3248c2ecf20Sopenharmony_ci * 10 - stop 16 of 32 cycles 3258c2ecf20Sopenharmony_ci */ 3268c2ecf20Sopenharmony_ci str2 = 0x10; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci /* CR defaults */ 3298c2ecf20Sopenharmony_ci /* cr1 3308c2ecf20Sopenharmony_ci * 4 - normal operation 3318c2ecf20Sopenharmony_ci */ 3328c2ecf20Sopenharmony_ci cr1.val = 0x0404040404040404ull; 3338c2ecf20Sopenharmony_ci /* cr2 3348c2ecf20Sopenharmony_ci * 4 - normal operation 3358c2ecf20Sopenharmony_ci */ 3368c2ecf20Sopenharmony_ci cr2 = 0x04; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci for_each_possible_cpu (cpu) { 3398c2ecf20Sopenharmony_ci pr_debug("processing cpu %d\n", cpu); 3408c2ecf20Sopenharmony_ci dev = get_cpu_device(cpu); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci if (!dev) { 3438c2ecf20Sopenharmony_ci pr_info("invalid dev pointer for cbe_thermal\n"); 3448c2ecf20Sopenharmony_ci return -EINVAL; 3458c2ecf20Sopenharmony_ci } 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci pmd_regs = cbe_get_cpu_pmd_regs(dev->id); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci if (!pmd_regs) { 3508c2ecf20Sopenharmony_ci pr_info("invalid CBE regs pointer for cbe_thermal\n"); 3518c2ecf20Sopenharmony_ci return -EINVAL; 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci out_be64(&pmd_regs->tm_str2, str2); 3558c2ecf20Sopenharmony_ci out_be64(&pmd_regs->tm_str1.val, str1.val); 3568c2ecf20Sopenharmony_ci out_be64(&pmd_regs->tm_tpr.val, tpr.val); 3578c2ecf20Sopenharmony_ci out_be64(&pmd_regs->tm_cr1.val, cr1.val); 3588c2ecf20Sopenharmony_ci out_be64(&pmd_regs->tm_cr2, cr2); 3598c2ecf20Sopenharmony_ci } 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci return 0; 3628c2ecf20Sopenharmony_ci} 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_cistatic int __init thermal_init(void) 3668c2ecf20Sopenharmony_ci{ 3678c2ecf20Sopenharmony_ci int rc = init_default_values(); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci if (rc == 0) { 3708c2ecf20Sopenharmony_ci spu_add_dev_attr_group(&spu_attribute_group); 3718c2ecf20Sopenharmony_ci cpu_add_dev_attr_group(&ppe_attribute_group); 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci return rc; 3758c2ecf20Sopenharmony_ci} 3768c2ecf20Sopenharmony_cimodule_init(thermal_init); 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_cistatic void __exit thermal_exit(void) 3798c2ecf20Sopenharmony_ci{ 3808c2ecf20Sopenharmony_ci spu_remove_dev_attr_group(&spu_attribute_group); 3818c2ecf20Sopenharmony_ci cpu_remove_dev_attr_group(&ppe_attribute_group); 3828c2ecf20Sopenharmony_ci} 3838c2ecf20Sopenharmony_cimodule_exit(thermal_exit); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 3868c2ecf20Sopenharmony_ciMODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>"); 3878c2ecf20Sopenharmony_ci 388