diff options
-rw-r--r-- | drivers/hwmon/Kconfig | 1 | ||||
-rw-r--r-- | drivers/hwmon/via-cputemp.c | 44 |
2 files changed, 40 insertions, 5 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 70b5704baf31..0598cd22edf2 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -1162,6 +1162,7 @@ config SENSORS_TWL4030_MADC | |||
1162 | config SENSORS_VIA_CPUTEMP | 1162 | config SENSORS_VIA_CPUTEMP |
1163 | tristate "VIA CPU temperature sensor" | 1163 | tristate "VIA CPU temperature sensor" |
1164 | depends on X86 | 1164 | depends on X86 |
1165 | select HWMON_VID | ||
1165 | help | 1166 | help |
1166 | If you say yes here you get support for the temperature | 1167 | If you say yes here you get support for the temperature |
1167 | sensor inside your CPU. Supported are all known variants of | 1168 | sensor inside your CPU. Supported are all known variants of |
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c index 0d18de424c66..8eac67d769fa 100644 --- a/drivers/hwmon/via-cputemp.c +++ b/drivers/hwmon/via-cputemp.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/hwmon.h> | 29 | #include <linux/hwmon.h> |
30 | #include <linux/hwmon-vid.h> | ||
30 | #include <linux/sysfs.h> | 31 | #include <linux/sysfs.h> |
31 | #include <linux/hwmon-sysfs.h> | 32 | #include <linux/hwmon-sysfs.h> |
32 | #include <linux/err.h> | 33 | #include <linux/err.h> |
@@ -48,8 +49,10 @@ enum { SHOW_TEMP, SHOW_LABEL, SHOW_NAME }; | |||
48 | struct via_cputemp_data { | 49 | struct via_cputemp_data { |
49 | struct device *hwmon_dev; | 50 | struct device *hwmon_dev; |
50 | const char *name; | 51 | const char *name; |
52 | u8 vrm; | ||
51 | u32 id; | 53 | u32 id; |
52 | u32 msr; | 54 | u32 msr_temp; |
55 | u32 msr_vid; | ||
53 | }; | 56 | }; |
54 | 57 | ||
55 | /* | 58 | /* |
@@ -77,13 +80,27 @@ static ssize_t show_temp(struct device *dev, | |||
77 | u32 eax, edx; | 80 | u32 eax, edx; |
78 | int err; | 81 | int err; |
79 | 82 | ||
80 | err = rdmsr_safe_on_cpu(data->id, data->msr, &eax, &edx); | 83 | err = rdmsr_safe_on_cpu(data->id, data->msr_temp, &eax, &edx); |
81 | if (err) | 84 | if (err) |
82 | return -EAGAIN; | 85 | return -EAGAIN; |
83 | 86 | ||
84 | return sprintf(buf, "%lu\n", ((unsigned long)eax & 0xffffff) * 1000); | 87 | return sprintf(buf, "%lu\n", ((unsigned long)eax & 0xffffff) * 1000); |
85 | } | 88 | } |
86 | 89 | ||
90 | static ssize_t show_cpu_vid(struct device *dev, | ||
91 | struct device_attribute *devattr, char *buf) | ||
92 | { | ||
93 | struct via_cputemp_data *data = dev_get_drvdata(dev); | ||
94 | u32 eax, edx; | ||
95 | int err; | ||
96 | |||
97 | err = rdmsr_safe_on_cpu(data->id, data->msr_vid, &eax, &edx); | ||
98 | if (err) | ||
99 | return -EAGAIN; | ||
100 | |||
101 | return sprintf(buf, "%d\n", vid_from_reg(~edx & 0x7f, data->vrm)); | ||
102 | } | ||
103 | |||
87 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, | 104 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, |
88 | SHOW_TEMP); | 105 | SHOW_TEMP); |
89 | static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL); | 106 | static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL); |
@@ -100,6 +117,9 @@ static const struct attribute_group via_cputemp_group = { | |||
100 | .attrs = via_cputemp_attributes, | 117 | .attrs = via_cputemp_attributes, |
101 | }; | 118 | }; |
102 | 119 | ||
120 | /* Optional attributes */ | ||
121 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_cpu_vid, NULL); | ||
122 | |||
103 | static int __devinit via_cputemp_probe(struct platform_device *pdev) | 123 | static int __devinit via_cputemp_probe(struct platform_device *pdev) |
104 | { | 124 | { |
105 | struct via_cputemp_data *data; | 125 | struct via_cputemp_data *data; |
@@ -122,11 +142,12 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev) | |||
122 | /* C7 A */ | 142 | /* C7 A */ |
123 | case 0xD: | 143 | case 0xD: |
124 | /* C7 D */ | 144 | /* C7 D */ |
125 | data->msr = 0x1169; | 145 | data->msr_temp = 0x1169; |
146 | data->msr_vid = 0x198; | ||
126 | break; | 147 | break; |
127 | case 0xF: | 148 | case 0xF: |
128 | /* Nano */ | 149 | /* Nano */ |
129 | data->msr = 0x1423; | 150 | data->msr_temp = 0x1423; |
130 | break; | 151 | break; |
131 | default: | 152 | default: |
132 | err = -ENODEV; | 153 | err = -ENODEV; |
@@ -134,7 +155,7 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev) | |||
134 | } | 155 | } |
135 | 156 | ||
136 | /* test if we can access the TEMPERATURE MSR */ | 157 | /* test if we can access the TEMPERATURE MSR */ |
137 | err = rdmsr_safe_on_cpu(data->id, data->msr, &eax, &edx); | 158 | err = rdmsr_safe_on_cpu(data->id, data->msr_temp, &eax, &edx); |
138 | if (err) { | 159 | if (err) { |
139 | dev_err(&pdev->dev, | 160 | dev_err(&pdev->dev, |
140 | "Unable to access TEMPERATURE MSR, giving up\n"); | 161 | "Unable to access TEMPERATURE MSR, giving up\n"); |
@@ -147,6 +168,15 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev) | |||
147 | if (err) | 168 | if (err) |
148 | goto exit_free; | 169 | goto exit_free; |
149 | 170 | ||
171 | if (data->msr_vid) | ||
172 | data->vrm = vid_which_vrm(); | ||
173 | |||
174 | if (data->vrm) { | ||
175 | err = device_create_file(&pdev->dev, &dev_attr_cpu0_vid); | ||
176 | if (err) | ||
177 | goto exit_remove; | ||
178 | } | ||
179 | |||
150 | data->hwmon_dev = hwmon_device_register(&pdev->dev); | 180 | data->hwmon_dev = hwmon_device_register(&pdev->dev); |
151 | if (IS_ERR(data->hwmon_dev)) { | 181 | if (IS_ERR(data->hwmon_dev)) { |
152 | err = PTR_ERR(data->hwmon_dev); | 182 | err = PTR_ERR(data->hwmon_dev); |
@@ -158,6 +188,8 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev) | |||
158 | return 0; | 188 | return 0; |
159 | 189 | ||
160 | exit_remove: | 190 | exit_remove: |
191 | if (data->vrm) | ||
192 | device_remove_file(&pdev->dev, &dev_attr_cpu0_vid); | ||
161 | sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group); | 193 | sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group); |
162 | exit_free: | 194 | exit_free: |
163 | platform_set_drvdata(pdev, NULL); | 195 | platform_set_drvdata(pdev, NULL); |
@@ -171,6 +203,8 @@ static int __devexit via_cputemp_remove(struct platform_device *pdev) | |||
171 | struct via_cputemp_data *data = platform_get_drvdata(pdev); | 203 | struct via_cputemp_data *data = platform_get_drvdata(pdev); |
172 | 204 | ||
173 | hwmon_device_unregister(data->hwmon_dev); | 205 | hwmon_device_unregister(data->hwmon_dev); |
206 | if (data->vrm) | ||
207 | device_remove_file(&pdev->dev, &dev_attr_cpu0_vid); | ||
174 | sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group); | 208 | sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group); |
175 | platform_set_drvdata(pdev, NULL); | 209 | platform_set_drvdata(pdev, NULL); |
176 | kfree(data); | 210 | kfree(data); |