diff options
| -rw-r--r-- | Documentation/hwmon/k10temp | 17 | ||||
| -rw-r--r-- | drivers/hwmon/k10temp.c | 38 |
2 files changed, 43 insertions, 12 deletions
diff --git a/Documentation/hwmon/k10temp b/Documentation/hwmon/k10temp index a7a18d453a51..6526eee525a6 100644 --- a/Documentation/hwmon/k10temp +++ b/Documentation/hwmon/k10temp | |||
| @@ -3,8 +3,8 @@ Kernel driver k10temp | |||
| 3 | 3 | ||
| 4 | Supported chips: | 4 | Supported chips: |
| 5 | * AMD Family 10h processors: | 5 | * AMD Family 10h processors: |
| 6 | Socket F: Quad-Core/Six-Core/Embedded Opteron | 6 | Socket F: Quad-Core/Six-Core/Embedded Opteron (but see below) |
| 7 | Socket AM2+: Opteron, Phenom (II) X3/X4 | 7 | Socket AM2+: Quad-Core Opteron, Phenom (II) X3/X4, Athlon X2 (but see below) |
| 8 | Socket AM3: Quad-Core Opteron, Athlon/Phenom II X2/X3/X4, Sempron II | 8 | Socket AM3: Quad-Core Opteron, Athlon/Phenom II X2/X3/X4, Sempron II |
| 9 | Socket S1G3: Athlon II, Sempron, Turion II | 9 | Socket S1G3: Athlon II, Sempron, Turion II |
| 10 | * AMD Family 11h processors: | 10 | * AMD Family 11h processors: |
| @@ -36,10 +36,15 @@ Description | |||
| 36 | This driver permits reading of the internal temperature sensor of AMD | 36 | This driver permits reading of the internal temperature sensor of AMD |
| 37 | Family 10h and 11h processors. | 37 | Family 10h and 11h processors. |
| 38 | 38 | ||
| 39 | All these processors have a sensor, but on older revisions of Family 10h | 39 | All these processors have a sensor, but on those for Socket F or AM2+, |
| 40 | processors, the sensor may return inconsistent values (erratum 319). The | 40 | the sensor may return inconsistent values (erratum 319). The driver |
| 41 | driver will refuse to load on these revisions unless you specify the | 41 | will refuse to load on these revisions unless you specify the "force=1" |
| 42 | "force=1" module parameter. | 42 | module parameter. |
| 43 | |||
| 44 | Due to technical reasons, the driver can detect only the mainboard's | ||
| 45 | socket type, not the processor's actual capabilities. Therefore, if you | ||
| 46 | are using an AM3 processor on an AM2+ mainboard, you can safely use the | ||
| 47 | "force=1" parameter. | ||
| 43 | 48 | ||
| 44 | There is one temperature measurement value, available as temp1_input in | 49 | There is one temperature measurement value, available as temp1_input in |
| 45 | sysfs. It is measured in degrees Celsius with a resolution of 1/8th degree. | 50 | sysfs. It is measured in degrees Celsius with a resolution of 1/8th degree. |
diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c index d8a26d16d948..4c9d349b3ad9 100644 --- a/drivers/hwmon/k10temp.c +++ b/drivers/hwmon/k10temp.c | |||
| @@ -33,6 +33,16 @@ static bool force; | |||
| 33 | module_param(force, bool, 0444); | 33 | module_param(force, bool, 0444); |
| 34 | MODULE_PARM_DESC(force, "force loading on processors with erratum 319"); | 34 | MODULE_PARM_DESC(force, "force loading on processors with erratum 319"); |
| 35 | 35 | ||
| 36 | /* CPUID function 0x80000001, ebx */ | ||
| 37 | #define CPUID_PKGTYPE_MASK 0xf0000000 | ||
| 38 | #define CPUID_PKGTYPE_F 0x00000000 | ||
| 39 | #define CPUID_PKGTYPE_AM2R2_AM3 0x10000000 | ||
| 40 | |||
| 41 | /* DRAM controller (PCI function 2) */ | ||
| 42 | #define REG_DCT0_CONFIG_HIGH 0x094 | ||
| 43 | #define DDR3_MODE 0x00000100 | ||
| 44 | |||
| 45 | /* miscellaneous (PCI function 3) */ | ||
| 36 | #define REG_HARDWARE_THERMAL_CONTROL 0x64 | 46 | #define REG_HARDWARE_THERMAL_CONTROL 0x64 |
| 37 | #define HTC_ENABLE 0x00000001 | 47 | #define HTC_ENABLE 0x00000001 |
| 38 | 48 | ||
| @@ -85,13 +95,28 @@ static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0); | |||
| 85 | static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1); | 95 | static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1); |
| 86 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | 96 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); |
| 87 | 97 | ||
| 88 | static bool __devinit has_erratum_319(void) | 98 | static bool __devinit has_erratum_319(struct pci_dev *pdev) |
| 89 | { | 99 | { |
| 100 | u32 pkg_type, reg_dram_cfg; | ||
| 101 | |||
| 102 | if (boot_cpu_data.x86 != 0x10) | ||
| 103 | return false; | ||
| 104 | |||
| 90 | /* | 105 | /* |
| 91 | * Erratum 319: The thermal sensor of older Family 10h processors | 106 | * Erratum 319: The thermal sensor of Socket F/AM2+ processors |
| 92 | * (B steppings) may be unreliable. | 107 | * may be unreliable. |
| 93 | */ | 108 | */ |
| 94 | return boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model <= 2; | 109 | pkg_type = cpuid_ebx(0x80000001) & CPUID_PKGTYPE_MASK; |
| 110 | if (pkg_type == CPUID_PKGTYPE_F) | ||
| 111 | return true; | ||
| 112 | if (pkg_type != CPUID_PKGTYPE_AM2R2_AM3) | ||
| 113 | return false; | ||
| 114 | |||
| 115 | /* Differentiate between AM2+ (bad) and AM3 (good) */ | ||
| 116 | pci_bus_read_config_dword(pdev->bus, | ||
| 117 | PCI_DEVFN(PCI_SLOT(pdev->devfn), 2), | ||
| 118 | REG_DCT0_CONFIG_HIGH, ®_dram_cfg); | ||
| 119 | return !(reg_dram_cfg & DDR3_MODE); | ||
| 95 | } | 120 | } |
| 96 | 121 | ||
| 97 | static int __devinit k10temp_probe(struct pci_dev *pdev, | 122 | static int __devinit k10temp_probe(struct pci_dev *pdev, |
| @@ -99,9 +124,10 @@ static int __devinit k10temp_probe(struct pci_dev *pdev, | |||
| 99 | { | 124 | { |
| 100 | struct device *hwmon_dev; | 125 | struct device *hwmon_dev; |
| 101 | u32 reg_caps, reg_htc; | 126 | u32 reg_caps, reg_htc; |
| 127 | int unreliable = has_erratum_319(pdev); | ||
| 102 | int err; | 128 | int err; |
| 103 | 129 | ||
| 104 | if (has_erratum_319() && !force) { | 130 | if (unreliable && !force) { |
| 105 | dev_err(&pdev->dev, | 131 | dev_err(&pdev->dev, |
| 106 | "unreliable CPU thermal sensor; monitoring disabled\n"); | 132 | "unreliable CPU thermal sensor; monitoring disabled\n"); |
| 107 | err = -ENODEV; | 133 | err = -ENODEV; |
| @@ -139,7 +165,7 @@ static int __devinit k10temp_probe(struct pci_dev *pdev, | |||
| 139 | } | 165 | } |
| 140 | dev_set_drvdata(&pdev->dev, hwmon_dev); | 166 | dev_set_drvdata(&pdev->dev, hwmon_dev); |
| 141 | 167 | ||
| 142 | if (has_erratum_319() && force) | 168 | if (unreliable && force) |
| 143 | dev_warn(&pdev->dev, | 169 | dev_warn(&pdev->dev, |
| 144 | "unreliable CPU thermal sensor; check erratum 319\n"); | 170 | "unreliable CPU thermal sensor; check erratum 319\n"); |
| 145 | return 0; | 171 | return 0; |
