1/* 2 * processor_thermal_device.c 3 * Copyright (c) 2014, Intel Corporation. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms and conditions of the GNU General Public License, 7 * version 2, as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 */ 15#include <linux/kernel.h> 16#include <linux/module.h> 17#include <linux/init.h> 18#include <linux/pci.h> 19#include <linux/platform_device.h> 20#include <linux/acpi.h> 21#include <linux/thermal.h> 22#include "int340x_thermal_zone.h" 23 24/* Broadwell-U/HSB thermal reporting device */ 25#define PCI_DEVICE_ID_PROC_BDW_THERMAL 0x1603 26#define PCI_DEVICE_ID_PROC_HSB_THERMAL 0x0A03 27 28/* Braswell thermal reporting device */ 29#define PCI_DEVICE_ID_PROC_BSW_THERMAL 0x22DC 30 31struct power_config { 32 u32 index; 33 u32 min_uw; 34 u32 max_uw; 35 u32 tmin_us; 36 u32 tmax_us; 37 u32 step_uw; 38}; 39 40struct proc_thermal_device { 41 struct device *dev; 42 struct acpi_device *adev; 43 struct power_config power_limits[2]; 44 struct int34x_thermal_zone *int340x_zone; 45}; 46 47enum proc_thermal_emum_mode_type { 48 PROC_THERMAL_NONE, 49 PROC_THERMAL_PCI, 50 PROC_THERMAL_PLATFORM_DEV 51}; 52 53/* 54 * We can have only one type of enumeration, PCI or Platform, 55 * not both. So we don't need instance specific data. 56 */ 57static enum proc_thermal_emum_mode_type proc_thermal_emum_mode = 58 PROC_THERMAL_NONE; 59 60#define POWER_LIMIT_SHOW(index, suffix) \ 61static ssize_t power_limit_##index##_##suffix##_show(struct device *dev, \ 62 struct device_attribute *attr, \ 63 char *buf) \ 64{ \ 65 struct pci_dev *pci_dev; \ 66 struct platform_device *pdev; \ 67 struct proc_thermal_device *proc_dev; \ 68\ 69 if (proc_thermal_emum_mode == PROC_THERMAL_PLATFORM_DEV) { \ 70 pdev = to_platform_device(dev); \ 71 proc_dev = platform_get_drvdata(pdev); \ 72 } else { \ 73 pci_dev = to_pci_dev(dev); \ 74 proc_dev = pci_get_drvdata(pci_dev); \ 75 } \ 76 return sprintf(buf, "%lu\n",\ 77 (unsigned long)proc_dev->power_limits[index].suffix * 1000); \ 78} 79 80POWER_LIMIT_SHOW(0, min_uw) 81POWER_LIMIT_SHOW(0, max_uw) 82POWER_LIMIT_SHOW(0, step_uw) 83POWER_LIMIT_SHOW(0, tmin_us) 84POWER_LIMIT_SHOW(0, tmax_us) 85 86POWER_LIMIT_SHOW(1, min_uw) 87POWER_LIMIT_SHOW(1, max_uw) 88POWER_LIMIT_SHOW(1, step_uw) 89POWER_LIMIT_SHOW(1, tmin_us) 90POWER_LIMIT_SHOW(1, tmax_us) 91 92static DEVICE_ATTR_RO(power_limit_0_min_uw); 93static DEVICE_ATTR_RO(power_limit_0_max_uw); 94static DEVICE_ATTR_RO(power_limit_0_step_uw); 95static DEVICE_ATTR_RO(power_limit_0_tmin_us); 96static DEVICE_ATTR_RO(power_limit_0_tmax_us); 97 98static DEVICE_ATTR_RO(power_limit_1_min_uw); 99static DEVICE_ATTR_RO(power_limit_1_max_uw); 100static DEVICE_ATTR_RO(power_limit_1_step_uw); 101static DEVICE_ATTR_RO(power_limit_1_tmin_us); 102static DEVICE_ATTR_RO(power_limit_1_tmax_us); 103 104static struct attribute *power_limit_attrs[] = { 105 &dev_attr_power_limit_0_min_uw.attr, 106 &dev_attr_power_limit_1_min_uw.attr, 107 &dev_attr_power_limit_0_max_uw.attr, 108 &dev_attr_power_limit_1_max_uw.attr, 109 &dev_attr_power_limit_0_step_uw.attr, 110 &dev_attr_power_limit_1_step_uw.attr, 111 &dev_attr_power_limit_0_tmin_us.attr, 112 &dev_attr_power_limit_1_tmin_us.attr, 113 &dev_attr_power_limit_0_tmax_us.attr, 114 &dev_attr_power_limit_1_tmax_us.attr, 115 NULL 116}; 117 118static struct attribute_group power_limit_attribute_group = { 119 .attrs = power_limit_attrs, 120 .name = "power_limits" 121}; 122 123static int stored_tjmax; /* since it is fixed, we can have local storage */ 124 125static int get_tjmax(void) 126{ 127 u32 eax, edx; 128 u32 val; 129 int err; 130 131 err = rdmsr_safe(MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); 132 if (err) 133 return err; 134 135 val = (eax >> 16) & 0xff; 136 if (val) 137 return val; 138 139 return -EINVAL; 140} 141 142static int read_temp_msr(unsigned long *temp) 143{ 144 int cpu; 145 u32 eax, edx; 146 int err; 147 unsigned long curr_temp_off = 0; 148 149 *temp = 0; 150 151 for_each_online_cpu(cpu) { 152 err = rdmsr_safe_on_cpu(cpu, MSR_IA32_THERM_STATUS, &eax, 153 &edx); 154 if (err) 155 goto err_ret; 156 else { 157 if (eax & 0x80000000) { 158 curr_temp_off = (eax >> 16) & 0x7f; 159 if (!*temp || curr_temp_off < *temp) 160 *temp = curr_temp_off; 161 } else { 162 err = -EINVAL; 163 goto err_ret; 164 } 165 } 166 } 167 168 return 0; 169err_ret: 170 return err; 171} 172 173static int proc_thermal_get_zone_temp(struct thermal_zone_device *zone, 174 unsigned long *temp) 175{ 176 int ret; 177 178 ret = read_temp_msr(temp); 179 if (!ret) 180 *temp = (stored_tjmax - *temp) * 1000; 181 182 return ret; 183} 184 185static struct thermal_zone_device_ops proc_thermal_local_ops = { 186 .get_temp = proc_thermal_get_zone_temp, 187}; 188 189static int proc_thermal_add(struct device *dev, 190 struct proc_thermal_device **priv) 191{ 192 struct proc_thermal_device *proc_priv; 193 struct acpi_device *adev; 194 acpi_status status; 195 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; 196 union acpi_object *elements, *ppcc; 197 union acpi_object *p; 198 unsigned long long tmp; 199 struct thermal_zone_device_ops *ops = NULL; 200 int i; 201 int ret; 202 203 adev = ACPI_COMPANION(dev); 204 if (!adev) 205 return -ENODEV; 206 207 status = acpi_evaluate_object(adev->handle, "PPCC", NULL, &buf); 208 if (ACPI_FAILURE(status)) 209 return -ENODEV; 210 211 p = buf.pointer; 212 if (!p || (p->type != ACPI_TYPE_PACKAGE)) { 213 dev_err(dev, "Invalid PPCC data\n"); 214 ret = -EFAULT; 215 goto free_buffer; 216 } 217 if (!p->package.count) { 218 dev_err(dev, "Invalid PPCC package size\n"); 219 ret = -EFAULT; 220 goto free_buffer; 221 } 222 223 proc_priv = devm_kzalloc(dev, sizeof(*proc_priv), GFP_KERNEL); 224 if (!proc_priv) { 225 ret = -ENOMEM; 226 goto free_buffer; 227 } 228 229 proc_priv->dev = dev; 230 proc_priv->adev = adev; 231 232 for (i = 0; i < min((int)p->package.count - 1, 2); ++i) { 233 elements = &(p->package.elements[i+1]); 234 if (elements->type != ACPI_TYPE_PACKAGE || 235 elements->package.count != 6) { 236 ret = -EFAULT; 237 goto free_buffer; 238 } 239 ppcc = elements->package.elements; 240 proc_priv->power_limits[i].index = ppcc[0].integer.value; 241 proc_priv->power_limits[i].min_uw = ppcc[1].integer.value; 242 proc_priv->power_limits[i].max_uw = ppcc[2].integer.value; 243 proc_priv->power_limits[i].tmin_us = ppcc[3].integer.value; 244 proc_priv->power_limits[i].tmax_us = ppcc[4].integer.value; 245 proc_priv->power_limits[i].step_uw = ppcc[5].integer.value; 246 } 247 248 *priv = proc_priv; 249 250 ret = sysfs_create_group(&dev->kobj, 251 &power_limit_attribute_group); 252 if (ret) 253 goto free_buffer; 254 255 status = acpi_evaluate_integer(adev->handle, "_TMP", NULL, &tmp); 256 if (ACPI_FAILURE(status)) { 257 /* there is no _TMP method, add local method */ 258 stored_tjmax = get_tjmax(); 259 if (stored_tjmax > 0) 260 ops = &proc_thermal_local_ops; 261 } 262 263 proc_priv->int340x_zone = int340x_thermal_zone_add(adev, ops); 264 if (IS_ERR(proc_priv->int340x_zone)) { 265 sysfs_remove_group(&proc_priv->dev->kobj, 266 &power_limit_attribute_group); 267 ret = PTR_ERR(proc_priv->int340x_zone); 268 } else 269 ret = 0; 270 271free_buffer: 272 kfree(buf.pointer); 273 274 return ret; 275} 276 277static void proc_thermal_remove(struct proc_thermal_device *proc_priv) 278{ 279 int340x_thermal_zone_remove(proc_priv->int340x_zone); 280 sysfs_remove_group(&proc_priv->dev->kobj, 281 &power_limit_attribute_group); 282} 283 284static int int3401_add(struct platform_device *pdev) 285{ 286 struct proc_thermal_device *proc_priv; 287 int ret; 288 289 if (proc_thermal_emum_mode == PROC_THERMAL_PCI) { 290 dev_err(&pdev->dev, "error: enumerated as PCI dev\n"); 291 return -ENODEV; 292 } 293 294 ret = proc_thermal_add(&pdev->dev, &proc_priv); 295 if (ret) 296 return ret; 297 298 platform_set_drvdata(pdev, proc_priv); 299 proc_thermal_emum_mode = PROC_THERMAL_PLATFORM_DEV; 300 301 return 0; 302} 303 304static int int3401_remove(struct platform_device *pdev) 305{ 306 proc_thermal_remove(platform_get_drvdata(pdev)); 307 308 return 0; 309} 310 311static int proc_thermal_pci_probe(struct pci_dev *pdev, 312 const struct pci_device_id *unused) 313{ 314 struct proc_thermal_device *proc_priv; 315 int ret; 316 317 if (proc_thermal_emum_mode == PROC_THERMAL_PLATFORM_DEV) { 318 dev_err(&pdev->dev, "error: enumerated as platform dev\n"); 319 return -ENODEV; 320 } 321 322 ret = pci_enable_device(pdev); 323 if (ret < 0) { 324 dev_err(&pdev->dev, "error: could not enable device\n"); 325 return ret; 326 } 327 328 ret = proc_thermal_add(&pdev->dev, &proc_priv); 329 if (ret) { 330 pci_disable_device(pdev); 331 return ret; 332 } 333 334 pci_set_drvdata(pdev, proc_priv); 335 proc_thermal_emum_mode = PROC_THERMAL_PCI; 336 337 return 0; 338} 339 340static void proc_thermal_pci_remove(struct pci_dev *pdev) 341{ 342 proc_thermal_remove(pci_get_drvdata(pdev)); 343 pci_disable_device(pdev); 344} 345 346static const struct pci_device_id proc_thermal_pci_ids[] = { 347 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BDW_THERMAL)}, 348 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_HSB_THERMAL)}, 349 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BSW_THERMAL)}, 350 { 0, }, 351}; 352 353MODULE_DEVICE_TABLE(pci, proc_thermal_pci_ids); 354 355static struct pci_driver proc_thermal_pci_driver = { 356 .name = "proc_thermal", 357 .probe = proc_thermal_pci_probe, 358 .remove = proc_thermal_pci_remove, 359 .id_table = proc_thermal_pci_ids, 360}; 361 362static const struct acpi_device_id int3401_device_ids[] = { 363 {"INT3401", 0}, 364 {"", 0}, 365}; 366MODULE_DEVICE_TABLE(acpi, int3401_device_ids); 367 368static struct platform_driver int3401_driver = { 369 .probe = int3401_add, 370 .remove = int3401_remove, 371 .driver = { 372 .name = "int3401 thermal", 373 .acpi_match_table = int3401_device_ids, 374 }, 375}; 376 377static int __init proc_thermal_init(void) 378{ 379 int ret; 380 381 ret = platform_driver_register(&int3401_driver); 382 if (ret) 383 return ret; 384 385 ret = pci_register_driver(&proc_thermal_pci_driver); 386 387 return ret; 388} 389 390static void __exit proc_thermal_exit(void) 391{ 392 platform_driver_unregister(&int3401_driver); 393 pci_unregister_driver(&proc_thermal_pci_driver); 394} 395 396module_init(proc_thermal_init); 397module_exit(proc_thermal_exit); 398 399MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 400MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver"); 401MODULE_LICENSE("GPL v2"); 402