diff options
Diffstat (limited to 'drivers/hwmon/fam15h_power.c')
-rw-r--r-- | drivers/hwmon/fam15h_power.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index b7494af1e4a9..e8e18cab1fb8 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c | |||
@@ -122,6 +122,41 @@ 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 | */ | ||
131 | static DEFINE_PCI_DEVICE_TABLE(affected_device) = { | ||
132 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, | ||
133 | { 0 } | ||
134 | }; | ||
135 | |||
136 | static void __devinit tweak_runavg_range(struct pci_dev *pdev) | ||
137 | { | ||
138 | u32 val; | ||
139 | |||
140 | /* | ||
141 | * let this quirk apply only to the current version of the | ||
142 | * northbridge, since future versions may change the behavior | ||
143 | */ | ||
144 | if (!pci_match_id(affected_device, pdev)) | ||
145 | return; | ||
146 | |||
147 | pci_bus_read_config_dword(pdev->bus, | ||
148 | PCI_DEVFN(PCI_SLOT(pdev->devfn), 5), | ||
149 | REG_TDP_RUNNING_AVERAGE, &val); | ||
150 | if ((val & 0xf) != 0xe) | ||
151 | return; | ||
152 | |||
153 | val &= ~0xf; | ||
154 | val |= 0x9; | ||
155 | pci_bus_write_config_dword(pdev->bus, | ||
156 | PCI_DEVFN(PCI_SLOT(pdev->devfn), 5), | ||
157 | REG_TDP_RUNNING_AVERAGE, val); | ||
158 | } | ||
159 | |||
125 | static void __devinit fam15h_power_init_data(struct pci_dev *f4, | 160 | static void __devinit fam15h_power_init_data(struct pci_dev *f4, |
126 | struct fam15h_power_data *data) | 161 | struct fam15h_power_data *data) |
127 | { | 162 | { |
@@ -155,6 +190,13 @@ static int __devinit fam15h_power_probe(struct pci_dev *pdev, | |||
155 | struct device *dev; | 190 | struct device *dev; |
156 | int err; | 191 | int err; |
157 | 192 | ||
193 | /* | ||
194 | * though we ignore every other northbridge, we still have to | ||
195 | * do the tweaking on _each_ node in MCM processors as the counters | ||
196 | * are working hand-in-hand | ||
197 | */ | ||
198 | tweak_runavg_range(pdev); | ||
199 | |||
158 | if (!fam15h_power_is_internal_node0(pdev)) { | 200 | if (!fam15h_power_is_internal_node0(pdev)) { |
159 | err = -ENODEV; | 201 | err = -ENODEV; |
160 | goto exit; | 202 | goto exit; |