aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/fam15h_power.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/fam15h_power.c')
-rw-r--r--drivers/hwmon/fam15h_power.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
index b7494af1e4a9..37a8fc92b44a 100644
--- a/drivers/hwmon/fam15h_power.c
+++ b/drivers/hwmon/fam15h_power.c
@@ -122,6 +122,38 @@ static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4)
122 return true; 122 return true;
123} 123}
124 124
125/*
126 * Newer BKDG versions have an updated recommendation on how to properly
127 * initialize the running average range (was: 0xE, now: 0x9). This avoids
128 * counter saturations resulting in bogus power readings.
129 * We correct this value ourselves to cope with older BIOSes.
130 */
131static void __devinit tweak_runavg_range(struct pci_dev *pdev)
132{
133 u32 val;
134 const struct pci_device_id affected_device = {
135 PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) };
136
137 /*
138 * let this quirk apply only to the current version of the
139 * northbridge, since future versions may change the behavior
140 */
141 if (!pci_match_id(&affected_device, pdev))
142 return;
143
144 pci_bus_read_config_dword(pdev->bus,
145 PCI_DEVFN(PCI_SLOT(pdev->devfn), 5),
146 REG_TDP_RUNNING_AVERAGE, &val);
147 if ((val & 0xf) != 0xe)
148 return;
149
150 val &= ~0xf;
151 val |= 0x9;
152 pci_bus_write_config_dword(pdev->bus,
153 PCI_DEVFN(PCI_SLOT(pdev->devfn), 5),
154 REG_TDP_RUNNING_AVERAGE, val);
155}
156
125static void __devinit fam15h_power_init_data(struct pci_dev *f4, 157static void __devinit fam15h_power_init_data(struct pci_dev *f4,
126 struct fam15h_power_data *data) 158 struct fam15h_power_data *data)
127{ 159{
@@ -155,6 +187,13 @@ static int __devinit fam15h_power_probe(struct pci_dev *pdev,
155 struct device *dev; 187 struct device *dev;
156 int err; 188 int err;
157 189
190 /*
191 * though we ignore every other northbridge, we still have to
192 * do the tweaking on _each_ node in MCM processors as the counters
193 * are working hand-in-hand
194 */
195 tweak_runavg_range(pdev);
196
158 if (!fam15h_power_is_internal_node0(pdev)) { 197 if (!fam15h_power_is_internal_node0(pdev)) {
159 err = -ENODEV; 198 err = -ENODEV;
160 goto exit; 199 goto exit;