~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/hwmon/k10temp.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * k10temp.c - AMD Family 10h/11h/12h/14h/15h processor hardware monitoring
 
3
 *
 
4
 * Copyright (c) 2009 Clemens Ladisch <clemens@ladisch.de>
 
5
 *
 
6
 *
 
7
 * This driver is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU General Public License; either
 
9
 * version 2 of the License, or (at your option) any later version.
 
10
 *
 
11
 * This driver is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
14
 * See the GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this driver; if not, see <http://www.gnu.org/licenses/>.
 
18
 */
 
19
 
 
20
#include <linux/err.h>
 
21
#include <linux/hwmon.h>
 
22
#include <linux/hwmon-sysfs.h>
 
23
#include <linux/init.h>
 
24
#include <linux/module.h>
 
25
#include <linux/pci.h>
 
26
#include <asm/processor.h>
 
27
 
 
28
MODULE_DESCRIPTION("AMD Family 10h+ CPU core temperature monitor");
 
29
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 
30
MODULE_LICENSE("GPL");
 
31
 
 
32
static bool force;
 
33
module_param(force, bool, 0444);
 
34
MODULE_PARM_DESC(force, "force loading on processors with erratum 319");
 
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) */
 
46
#define REG_HARDWARE_THERMAL_CONTROL    0x64
 
47
#define  HTC_ENABLE                     0x00000001
 
48
 
 
49
#define REG_REPORTED_TEMPERATURE        0xa4
 
50
 
 
51
#define REG_NORTHBRIDGE_CAPABILITIES    0xe8
 
52
#define  NB_CAP_HTC                     0x00000400
 
53
 
 
54
static ssize_t show_temp(struct device *dev,
 
55
                         struct device_attribute *attr, char *buf)
 
56
{
 
57
        u32 regval;
 
58
 
 
59
        pci_read_config_dword(to_pci_dev(dev),
 
60
                              REG_REPORTED_TEMPERATURE, &regval);
 
61
        return sprintf(buf, "%u\n", (regval >> 21) * 125);
 
62
}
 
63
 
 
64
static ssize_t show_temp_max(struct device *dev,
 
65
                             struct device_attribute *attr, char *buf)
 
66
{
 
67
        return sprintf(buf, "%d\n", 70 * 1000);
 
68
}
 
69
 
 
70
static ssize_t show_temp_crit(struct device *dev,
 
71
                              struct device_attribute *devattr, char *buf)
 
72
{
 
73
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 
74
        int show_hyst = attr->index;
 
75
        u32 regval;
 
76
        int value;
 
77
 
 
78
        pci_read_config_dword(to_pci_dev(dev),
 
79
                              REG_HARDWARE_THERMAL_CONTROL, &regval);
 
80
        value = ((regval >> 16) & 0x7f) * 500 + 52000;
 
81
        if (show_hyst)
 
82
                value -= ((regval >> 24) & 0xf) * 500;
 
83
        return sprintf(buf, "%d\n", value);
 
84
}
 
85
 
 
86
static ssize_t show_name(struct device *dev,
 
87
                         struct device_attribute *attr, char *buf)
 
88
{
 
89
        return sprintf(buf, "k10temp\n");
 
90
}
 
91
 
 
92
static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
 
93
static DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL);
 
94
static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
 
95
static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1);
 
96
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
97
 
 
98
static bool __devinit has_erratum_319(struct pci_dev *pdev)
 
99
{
 
100
        u32 pkg_type, reg_dram_cfg;
 
101
 
 
102
        if (boot_cpu_data.x86 != 0x10)
 
103
                return false;
 
104
 
 
105
        /*
 
106
         * Erratum 319: The thermal sensor of Socket F/AM2+ processors
 
107
         *              may be unreliable.
 
108
         */
 
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
        /* DDR3 memory implies socket AM3, which is good */
 
116
        pci_bus_read_config_dword(pdev->bus,
 
117
                                  PCI_DEVFN(PCI_SLOT(pdev->devfn), 2),
 
118
                                  REG_DCT0_CONFIG_HIGH, &reg_dram_cfg);
 
119
        if (reg_dram_cfg & DDR3_MODE)
 
120
                return false;
 
121
 
 
122
        /*
 
123
         * Unfortunately it is possible to run a socket AM3 CPU with DDR2
 
124
         * memory. We blacklist all the cores which do exist in socket AM2+
 
125
         * format. It still isn't perfect, as RB-C2 cores exist in both AM2+
 
126
         * and AM3 formats, but that's the best we can do.
 
127
         */
 
128
        return boot_cpu_data.x86_model < 4 ||
 
129
               (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_mask <= 2);
 
130
}
 
131
 
 
132
static int __devinit k10temp_probe(struct pci_dev *pdev,
 
133
                                   const struct pci_device_id *id)
 
134
{
 
135
        struct device *hwmon_dev;
 
136
        u32 reg_caps, reg_htc;
 
137
        int unreliable = has_erratum_319(pdev);
 
138
        int err;
 
139
 
 
140
        if (unreliable && !force) {
 
141
                dev_err(&pdev->dev,
 
142
                        "unreliable CPU thermal sensor; monitoring disabled\n");
 
143
                err = -ENODEV;
 
144
                goto exit;
 
145
        }
 
146
 
 
147
        err = device_create_file(&pdev->dev, &dev_attr_temp1_input);
 
148
        if (err)
 
149
                goto exit;
 
150
        err = device_create_file(&pdev->dev, &dev_attr_temp1_max);
 
151
        if (err)
 
152
                goto exit_remove;
 
153
 
 
154
        pci_read_config_dword(pdev, REG_NORTHBRIDGE_CAPABILITIES, &reg_caps);
 
155
        pci_read_config_dword(pdev, REG_HARDWARE_THERMAL_CONTROL, &reg_htc);
 
156
        if ((reg_caps & NB_CAP_HTC) && (reg_htc & HTC_ENABLE)) {
 
157
                err = device_create_file(&pdev->dev,
 
158
                                &sensor_dev_attr_temp1_crit.dev_attr);
 
159
                if (err)
 
160
                        goto exit_remove;
 
161
                err = device_create_file(&pdev->dev,
 
162
                                &sensor_dev_attr_temp1_crit_hyst.dev_attr);
 
163
                if (err)
 
164
                        goto exit_remove;
 
165
        }
 
166
 
 
167
        err = device_create_file(&pdev->dev, &dev_attr_name);
 
168
        if (err)
 
169
                goto exit_remove;
 
170
 
 
171
        hwmon_dev = hwmon_device_register(&pdev->dev);
 
172
        if (IS_ERR(hwmon_dev)) {
 
173
                err = PTR_ERR(hwmon_dev);
 
174
                goto exit_remove;
 
175
        }
 
176
        pci_set_drvdata(pdev, hwmon_dev);
 
177
 
 
178
        if (unreliable && force)
 
179
                dev_warn(&pdev->dev,
 
180
                         "unreliable CPU thermal sensor; check erratum 319\n");
 
181
        return 0;
 
182
 
 
183
exit_remove:
 
184
        device_remove_file(&pdev->dev, &dev_attr_name);
 
185
        device_remove_file(&pdev->dev, &dev_attr_temp1_input);
 
186
        device_remove_file(&pdev->dev, &dev_attr_temp1_max);
 
187
        device_remove_file(&pdev->dev,
 
188
                           &sensor_dev_attr_temp1_crit.dev_attr);
 
189
        device_remove_file(&pdev->dev,
 
190
                           &sensor_dev_attr_temp1_crit_hyst.dev_attr);
 
191
exit:
 
192
        return err;
 
193
}
 
194
 
 
195
static void __devexit k10temp_remove(struct pci_dev *pdev)
 
196
{
 
197
        hwmon_device_unregister(pci_get_drvdata(pdev));
 
198
        device_remove_file(&pdev->dev, &dev_attr_name);
 
199
        device_remove_file(&pdev->dev, &dev_attr_temp1_input);
 
200
        device_remove_file(&pdev->dev, &dev_attr_temp1_max);
 
201
        device_remove_file(&pdev->dev,
 
202
                           &sensor_dev_attr_temp1_crit.dev_attr);
 
203
        device_remove_file(&pdev->dev,
 
204
                           &sensor_dev_attr_temp1_crit_hyst.dev_attr);
 
205
        pci_set_drvdata(pdev, NULL);
 
206
}
 
207
 
 
208
static const struct pci_device_id k10temp_id_table[] = {
 
209
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
 
210
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
 
211
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
 
212
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
 
213
        {}
 
214
};
 
215
MODULE_DEVICE_TABLE(pci, k10temp_id_table);
 
216
 
 
217
static struct pci_driver k10temp_driver = {
 
218
        .name = "k10temp",
 
219
        .id_table = k10temp_id_table,
 
220
        .probe = k10temp_probe,
 
221
        .remove = __devexit_p(k10temp_remove),
 
222
};
 
223
 
 
224
static int __init k10temp_init(void)
 
225
{
 
226
        return pci_register_driver(&k10temp_driver);
 
227
}
 
228
 
 
229
static void __exit k10temp_exit(void)
 
230
{
 
231
        pci_unregister_driver(&k10temp_driver);
 
232
}
 
233
 
 
234
module_init(k10temp_init)
 
235
module_exit(k10temp_exit)