forked from jonsmirl/mpc5200
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/…
…kernel/git/jdelvare/staging * 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging: hwmon: (w83627hf) Fix for "No such device" hwmon: (sht15) Off-by-one error in array index + incorrect constants hwmon: Add driver for VIA CPU core temperature hwmon: (smsc47m1) Enable device if needed hwmon: (smsc47m1) Fail module loading on error hwmon: (smsc47m1) Only request I/O ports we really use hwmon: New driver for AMD Family 10h/11h CPUs
- Loading branch information
Showing
8 changed files
with
766 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
Kernel driver k10temp | ||
===================== | ||
|
||
Supported chips: | ||
* AMD Family 10h processors: | ||
Socket F: Quad-Core/Six-Core/Embedded Opteron | ||
Socket AM2+: Opteron, Phenom (II) X3/X4 | ||
Socket AM3: Quad-Core Opteron, Athlon/Phenom II X2/X3/X4, Sempron II | ||
Socket S1G3: Athlon II, Sempron, Turion II | ||
* AMD Family 11h processors: | ||
Socket S1G2: Athlon (X2), Sempron (X2), Turion X2 (Ultra) | ||
|
||
Prefix: 'k10temp' | ||
Addresses scanned: PCI space | ||
Datasheets: | ||
BIOS and Kernel Developer's Guide (BKDG) For AMD Family 10h Processors: | ||
http://support.amd.com/us/Processor_TechDocs/31116.pdf | ||
BIOS and Kernel Developer's Guide (BKDG) for AMD Family 11h Processors: | ||
http://support.amd.com/us/Processor_TechDocs/41256.pdf | ||
Revision Guide for AMD Family 10h Processors: | ||
http://support.amd.com/us/Processor_TechDocs/41322.pdf | ||
Revision Guide for AMD Family 11h Processors: | ||
http://support.amd.com/us/Processor_TechDocs/41788.pdf | ||
AMD Family 11h Processor Power and Thermal Data Sheet for Notebooks: | ||
http://support.amd.com/us/Processor_TechDocs/43373.pdf | ||
AMD Family 10h Server and Workstation Processor Power and Thermal Data Sheet: | ||
http://support.amd.com/us/Processor_TechDocs/43374.pdf | ||
AMD Family 10h Desktop Processor Power and Thermal Data Sheet: | ||
http://support.amd.com/us/Processor_TechDocs/43375.pdf | ||
|
||
Author: Clemens Ladisch <clemens@ladisch.de> | ||
|
||
Description | ||
----------- | ||
|
||
This driver permits reading of the internal temperature sensor of AMD | ||
Family 10h and 11h processors. | ||
|
||
All these processors have a sensor, but on older revisions of Family 10h | ||
processors, the sensor may return inconsistent values (erratum 319). The | ||
driver will refuse to load on these revisions unless you specify the | ||
"force=1" module parameter. | ||
|
||
There is one temperature measurement value, available as temp1_input in | ||
sysfs. It is measured in degrees Celsius with a resolution of 1/8th degree. | ||
Please note that it is defined as a relative value; to quote the AMD manual: | ||
|
||
Tctl is the processor temperature control value, used by the platform to | ||
control cooling systems. Tctl is a non-physical temperature on an | ||
arbitrary scale measured in degrees. It does _not_ represent an actual | ||
physical temperature like die or case temperature. Instead, it specifies | ||
the processor temperature relative to the point at which the system must | ||
supply the maximum cooling for the processor's specified maximum case | ||
temperature and maximum thermal power dissipation. | ||
|
||
The maximum value for Tctl is available in the file temp1_max. | ||
|
||
If the BIOS has enabled hardware temperature control, the threshold at | ||
which the processor will throttle itself to avoid damage is available in | ||
temp1_crit and temp1_crit_hyst. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
/* | ||
* k10temp.c - AMD Family 10h/11h processor hardware monitoring | ||
* | ||
* Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de> | ||
* | ||
* | ||
* This driver is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public License; either | ||
* version 2 of the License, or (at your option) any later version. | ||
* | ||
* This driver is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
* See the GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this driver; if not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#include <linux/err.h> | ||
#include <linux/hwmon.h> | ||
#include <linux/hwmon-sysfs.h> | ||
#include <linux/init.h> | ||
#include <linux/module.h> | ||
#include <linux/pci.h> | ||
#include <asm/processor.h> | ||
|
||
MODULE_DESCRIPTION("AMD Family 10h/11h CPU core temperature monitor"); | ||
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); | ||
MODULE_LICENSE("GPL"); | ||
|
||
static bool force; | ||
module_param(force, bool, 0444); | ||
MODULE_PARM_DESC(force, "force loading on processors with erratum 319"); | ||
|
||
#define REG_HARDWARE_THERMAL_CONTROL 0x64 | ||
#define HTC_ENABLE 0x00000001 | ||
|
||
#define REG_REPORTED_TEMPERATURE 0xa4 | ||
|
||
#define REG_NORTHBRIDGE_CAPABILITIES 0xe8 | ||
#define NB_CAP_HTC 0x00000400 | ||
|
||
static ssize_t show_temp(struct device *dev, | ||
struct device_attribute *attr, char *buf) | ||
{ | ||
u32 regval; | ||
|
||
pci_read_config_dword(to_pci_dev(dev), | ||
REG_REPORTED_TEMPERATURE, ®val); | ||
return sprintf(buf, "%u\n", (regval >> 21) * 125); | ||
} | ||
|
||
static ssize_t show_temp_max(struct device *dev, | ||
struct device_attribute *attr, char *buf) | ||
{ | ||
return sprintf(buf, "%d\n", 70 * 1000); | ||
} | ||
|
||
static ssize_t show_temp_crit(struct device *dev, | ||
struct device_attribute *devattr, char *buf) | ||
{ | ||
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
int show_hyst = attr->index; | ||
u32 regval; | ||
int value; | ||
|
||
pci_read_config_dword(to_pci_dev(dev), | ||
REG_HARDWARE_THERMAL_CONTROL, ®val); | ||
value = ((regval >> 16) & 0x7f) * 500 + 52000; | ||
if (show_hyst) | ||
value -= ((regval >> 24) & 0xf) * 500; | ||
return sprintf(buf, "%d\n", value); | ||
} | ||
|
||
static ssize_t show_name(struct device *dev, | ||
struct device_attribute *attr, char *buf) | ||
{ | ||
return sprintf(buf, "k10temp\n"); | ||
} | ||
|
||
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL); | ||
static DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL); | ||
static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0); | ||
static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1); | ||
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
|
||
static bool __devinit has_erratum_319(void) | ||
{ | ||
/* | ||
* Erratum 319: The thermal sensor of older Family 10h processors | ||
* (B steppings) may be unreliable. | ||
*/ | ||
return boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model <= 2; | ||
} | ||
|
||
static int __devinit k10temp_probe(struct pci_dev *pdev, | ||
const struct pci_device_id *id) | ||
{ | ||
struct device *hwmon_dev; | ||
u32 reg_caps, reg_htc; | ||
int err; | ||
|
||
if (has_erratum_319() && !force) { | ||
dev_err(&pdev->dev, | ||
"unreliable CPU thermal sensor; monitoring disabled\n"); | ||
err = -ENODEV; | ||
goto exit; | ||
} | ||
|
||
err = device_create_file(&pdev->dev, &dev_attr_temp1_input); | ||
if (err) | ||
goto exit; | ||
err = device_create_file(&pdev->dev, &dev_attr_temp1_max); | ||
if (err) | ||
goto exit_remove; | ||
|
||
pci_read_config_dword(pdev, REG_NORTHBRIDGE_CAPABILITIES, ®_caps); | ||
pci_read_config_dword(pdev, REG_HARDWARE_THERMAL_CONTROL, ®_htc); | ||
if ((reg_caps & NB_CAP_HTC) && (reg_htc & HTC_ENABLE)) { | ||
err = device_create_file(&pdev->dev, | ||
&sensor_dev_attr_temp1_crit.dev_attr); | ||
if (err) | ||
goto exit_remove; | ||
err = device_create_file(&pdev->dev, | ||
&sensor_dev_attr_temp1_crit_hyst.dev_attr); | ||
if (err) | ||
goto exit_remove; | ||
} | ||
|
||
err = device_create_file(&pdev->dev, &dev_attr_name); | ||
if (err) | ||
goto exit_remove; | ||
|
||
hwmon_dev = hwmon_device_register(&pdev->dev); | ||
if (IS_ERR(hwmon_dev)) { | ||
err = PTR_ERR(hwmon_dev); | ||
goto exit_remove; | ||
} | ||
dev_set_drvdata(&pdev->dev, hwmon_dev); | ||
|
||
if (has_erratum_319() && force) | ||
dev_warn(&pdev->dev, | ||
"unreliable CPU thermal sensor; check erratum 319\n"); | ||
return 0; | ||
|
||
exit_remove: | ||
device_remove_file(&pdev->dev, &dev_attr_name); | ||
device_remove_file(&pdev->dev, &dev_attr_temp1_input); | ||
device_remove_file(&pdev->dev, &dev_attr_temp1_max); | ||
device_remove_file(&pdev->dev, | ||
&sensor_dev_attr_temp1_crit.dev_attr); | ||
device_remove_file(&pdev->dev, | ||
&sensor_dev_attr_temp1_crit_hyst.dev_attr); | ||
exit: | ||
return err; | ||
} | ||
|
||
static void __devexit k10temp_remove(struct pci_dev *pdev) | ||
{ | ||
hwmon_device_unregister(dev_get_drvdata(&pdev->dev)); | ||
device_remove_file(&pdev->dev, &dev_attr_name); | ||
device_remove_file(&pdev->dev, &dev_attr_temp1_input); | ||
device_remove_file(&pdev->dev, &dev_attr_temp1_max); | ||
device_remove_file(&pdev->dev, | ||
&sensor_dev_attr_temp1_crit.dev_attr); | ||
device_remove_file(&pdev->dev, | ||
&sensor_dev_attr_temp1_crit_hyst.dev_attr); | ||
dev_set_drvdata(&pdev->dev, NULL); | ||
} | ||
|
||
static struct pci_device_id k10temp_id_table[] = { | ||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) }, | ||
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) }, | ||
{} | ||
}; | ||
MODULE_DEVICE_TABLE(pci, k10temp_id_table); | ||
|
||
static struct pci_driver k10temp_driver = { | ||
.name = "k10temp", | ||
.id_table = k10temp_id_table, | ||
.probe = k10temp_probe, | ||
.remove = __devexit_p(k10temp_remove), | ||
}; | ||
|
||
static int __init k10temp_init(void) | ||
{ | ||
return pci_register_driver(&k10temp_driver); | ||
} | ||
|
||
static void __exit k10temp_exit(void) | ||
{ | ||
pci_unregister_driver(&k10temp_driver); | ||
} | ||
|
||
module_init(k10temp_init) | ||
module_exit(k10temp_exit) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.