Blame view
drivers/hwmon/via-cputemp.c
7.1 KB
935912c53 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
70c38772a hwmon: Add driver... |
2 3 4 5 6 7 8 |
/* * via-cputemp.c - Driver for VIA CPU core temperature monitoring * Copyright (C) 2009 VIA Technologies, Inc. * * based on existing coretemp.c, which is * * Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz> |
70c38772a hwmon: Add driver... |
9 |
*/ |
edb8d53c6 hwmon: (via-cpute... |
10 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
70c38772a hwmon: Add driver... |
11 |
#include <linux/module.h> |
70c38772a hwmon: Add driver... |
12 13 |
#include <linux/init.h> #include <linux/slab.h> |
70c38772a hwmon: Add driver... |
14 |
#include <linux/hwmon.h> |
764e043bb hwmon: (via-cpute... |
15 |
#include <linux/hwmon-vid.h> |
70c38772a hwmon: Add driver... |
16 17 18 19 20 21 22 23 24 |
#include <linux/sysfs.h> #include <linux/hwmon-sysfs.h> #include <linux/err.h> #include <linux/mutex.h> #include <linux/list.h> #include <linux/platform_device.h> #include <linux/cpu.h> #include <asm/msr.h> #include <asm/processor.h> |
267fc9788 HWMON: Convert vi... |
25 |
#include <asm/cpu_device_id.h> |
70c38772a hwmon: Add driver... |
26 27 |
#define DRVNAME "via_cputemp" |
f27994186 hwmon: (via-cpute... |
28 |
enum { SHOW_TEMP, SHOW_LABEL, SHOW_NAME }; |
70c38772a hwmon: Add driver... |
29 30 31 32 33 34 35 36 |
/* * Functions declaration */ struct via_cputemp_data { struct device *hwmon_dev; const char *name; |
764e043bb hwmon: (via-cpute... |
37 |
u8 vrm; |
70c38772a hwmon: Add driver... |
38 |
u32 id; |
764e043bb hwmon: (via-cpute... |
39 40 |
u32 msr_temp; u32 msr_vid; |
70c38772a hwmon: Add driver... |
41 42 43 44 45 |
}; /* * Sysfs stuff */ |
f74c24f86 hwmon: (via-cpute... |
46 47 |
static ssize_t name_show(struct device *dev, struct device_attribute *devattr, char *buf) |
70c38772a hwmon: Add driver... |
48 49 50 51 52 53 54 55 56 57 58 59 60 |
{ int ret; struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct via_cputemp_data *data = dev_get_drvdata(dev); if (attr->index == SHOW_NAME) ret = sprintf(buf, "%s ", data->name); else /* show label */ ret = sprintf(buf, "Core %d ", data->id); return ret; } |
f74c24f86 hwmon: (via-cpute... |
61 62 |
static ssize_t temp_show(struct device *dev, struct device_attribute *devattr, char *buf) |
70c38772a hwmon: Add driver... |
63 64 65 66 |
{ struct via_cputemp_data *data = dev_get_drvdata(dev); u32 eax, edx; int err; |
764e043bb hwmon: (via-cpute... |
67 |
err = rdmsr_safe_on_cpu(data->id, data->msr_temp, &eax, &edx); |
70c38772a hwmon: Add driver... |
68 69 70 71 72 73 |
if (err) return -EAGAIN; return sprintf(buf, "%lu ", ((unsigned long)eax & 0xffffff) * 1000); } |
1664d7fd6 hwmon: (via-cpute... |
74 75 |
static ssize_t cpu0_vid_show(struct device *dev, struct device_attribute *devattr, char *buf) |
764e043bb hwmon: (via-cpute... |
76 77 78 79 80 81 82 83 84 85 86 87 |
{ struct via_cputemp_data *data = dev_get_drvdata(dev); u32 eax, edx; int err; err = rdmsr_safe_on_cpu(data->id, data->msr_vid, &eax, &edx); if (err) return -EAGAIN; return sprintf(buf, "%d ", vid_from_reg(~edx & 0x7f, data->vrm)); } |
f74c24f86 hwmon: (via-cpute... |
88 89 90 |
static SENSOR_DEVICE_ATTR_RO(temp1_input, temp, SHOW_TEMP); static SENSOR_DEVICE_ATTR_RO(temp1_label, name, SHOW_LABEL); static SENSOR_DEVICE_ATTR_RO(name, name, SHOW_NAME); |
70c38772a hwmon: Add driver... |
91 92 93 94 95 96 97 98 99 100 101 |
static struct attribute *via_cputemp_attributes[] = { &sensor_dev_attr_name.dev_attr.attr, &sensor_dev_attr_temp1_label.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, NULL }; static const struct attribute_group via_cputemp_group = { .attrs = via_cputemp_attributes, }; |
764e043bb hwmon: (via-cpute... |
102 |
/* Optional attributes */ |
1664d7fd6 hwmon: (via-cpute... |
103 |
static DEVICE_ATTR_RO(cpu0_vid); |
764e043bb hwmon: (via-cpute... |
104 |
|
6c931ae1c hwmon: remove use... |
105 |
static int via_cputemp_probe(struct platform_device *pdev) |
70c38772a hwmon: Add driver... |
106 107 108 109 110 |
{ struct via_cputemp_data *data; struct cpuinfo_x86 *c = &cpu_data(pdev->id); int err; u32 eax, edx; |
505dc0cc7 hwmon: (via-cpute... |
111 112 113 114 |
data = devm_kzalloc(&pdev->dev, sizeof(struct via_cputemp_data), GFP_KERNEL); if (!data) return -ENOMEM; |
70c38772a hwmon: Add driver... |
115 116 117 |
data->id = pdev->id; data->name = "via_cputemp"; |
e3a2d2be5 hwmon: (via-cpute... |
118 |
if (c->x86 == 7) { |
764e043bb hwmon: (via-cpute... |
119 |
data->msr_temp = 0x1423; |
e3a2d2be5 hwmon: (via-cpute... |
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
} else { switch (c->x86_model) { case 0xA: /* C7 A */ case 0xD: /* C7 D */ data->msr_temp = 0x1169; data->msr_vid = 0x198; break; case 0xF: /* Nano */ data->msr_temp = 0x1423; break; default: return -ENODEV; } |
70c38772a hwmon: Add driver... |
136 137 138 |
} /* test if we can access the TEMPERATURE MSR */ |
764e043bb hwmon: (via-cpute... |
139 |
err = rdmsr_safe_on_cpu(data->id, data->msr_temp, &eax, &edx); |
70c38772a hwmon: Add driver... |
140 141 142 143 |
if (err) { dev_err(&pdev->dev, "Unable to access TEMPERATURE MSR, giving up "); |
505dc0cc7 hwmon: (via-cpute... |
144 |
return err; |
70c38772a hwmon: Add driver... |
145 146 147 148 149 150 |
} platform_set_drvdata(pdev, data); err = sysfs_create_group(&pdev->dev.kobj, &via_cputemp_group); if (err) |
505dc0cc7 hwmon: (via-cpute... |
151 |
return err; |
70c38772a hwmon: Add driver... |
152 |
|
764e043bb hwmon: (via-cpute... |
153 154 155 156 157 158 159 160 |
if (data->msr_vid) data->vrm = vid_which_vrm(); if (data->vrm) { err = device_create_file(&pdev->dev, &dev_attr_cpu0_vid); if (err) goto exit_remove; } |
70c38772a hwmon: Add driver... |
161 162 163 164 165 166 167 168 169 170 171 172 |
data->hwmon_dev = hwmon_device_register(&pdev->dev); if (IS_ERR(data->hwmon_dev)) { err = PTR_ERR(data->hwmon_dev); dev_err(&pdev->dev, "Class registration failed (%d) ", err); goto exit_remove; } return 0; exit_remove: |
764e043bb hwmon: (via-cpute... |
173 174 |
if (data->vrm) device_remove_file(&pdev->dev, &dev_attr_cpu0_vid); |
70c38772a hwmon: Add driver... |
175 |
sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group); |
70c38772a hwmon: Add driver... |
176 177 |
return err; } |
281dfd0b6 hwmon: remove use... |
178 |
static int via_cputemp_remove(struct platform_device *pdev) |
70c38772a hwmon: Add driver... |
179 180 181 182 |
{ struct via_cputemp_data *data = platform_get_drvdata(pdev); hwmon_device_unregister(data->hwmon_dev); |
764e043bb hwmon: (via-cpute... |
183 184 |
if (data->vrm) device_remove_file(&pdev->dev, &dev_attr_cpu0_vid); |
70c38772a hwmon: Add driver... |
185 |
sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group); |
70c38772a hwmon: Add driver... |
186 187 188 189 190 |
return 0; } static struct platform_driver via_cputemp_driver = { .driver = { |
70c38772a hwmon: Add driver... |
191 192 193 |
.name = DRVNAME, }, .probe = via_cputemp_probe, |
9e5e9b7a9 hwmon: remove use... |
194 |
.remove = via_cputemp_remove, |
70c38772a hwmon: Add driver... |
195 196 197 198 199 200 201 202 203 204 |
}; struct pdev_entry { struct list_head list; struct platform_device *pdev; unsigned int cpu; }; static LIST_HEAD(pdev_list); static DEFINE_MUTEX(pdev_list_mutex); |
df60d7013 hwmon: (via-cpute... |
205 |
static int via_cputemp_online(unsigned int cpu) |
70c38772a hwmon: Add driver... |
206 207 208 209 210 211 212 213 |
{ int err; struct platform_device *pdev; struct pdev_entry *pdev_entry; pdev = platform_device_alloc(DRVNAME, cpu); if (!pdev) { err = -ENOMEM; |
edb8d53c6 hwmon: (via-cpute... |
214 215 |
pr_err("Device allocation failed "); |
70c38772a hwmon: Add driver... |
216 217 218 219 220 221 222 223 224 225 226 |
goto exit; } pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL); if (!pdev_entry) { err = -ENOMEM; goto exit_device_put; } err = platform_device_add(pdev); if (err) { |
edb8d53c6 hwmon: (via-cpute... |
227 228 |
pr_err("Device addition failed (%d) ", err); |
70c38772a hwmon: Add driver... |
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
goto exit_device_free; } pdev_entry->pdev = pdev; pdev_entry->cpu = cpu; mutex_lock(&pdev_list_mutex); list_add_tail(&pdev_entry->list, &pdev_list); mutex_unlock(&pdev_list_mutex); return 0; exit_device_free: kfree(pdev_entry); exit_device_put: platform_device_put(pdev); exit: return err; } |
df60d7013 hwmon: (via-cpute... |
247 |
static int via_cputemp_down_prep(unsigned int cpu) |
70c38772a hwmon: Add driver... |
248 |
{ |
ae9e0ce73 hwmon: (via-cpute... |
249 |
struct pdev_entry *p; |
70c38772a hwmon: Add driver... |
250 |
mutex_lock(&pdev_list_mutex); |
ae9e0ce73 hwmon: (via-cpute... |
251 |
list_for_each_entry(p, &pdev_list, list) { |
70c38772a hwmon: Add driver... |
252 253 254 |
if (p->cpu == cpu) { platform_device_unregister(p->pdev); list_del(&p->list); |
ae9e0ce73 hwmon: (via-cpute... |
255 |
mutex_unlock(&pdev_list_mutex); |
70c38772a hwmon: Add driver... |
256 |
kfree(p); |
df60d7013 hwmon: (via-cpute... |
257 |
return 0; |
70c38772a hwmon: Add driver... |
258 259 260 |
} } mutex_unlock(&pdev_list_mutex); |
df60d7013 hwmon: (via-cpute... |
261 |
return 0; |
70c38772a hwmon: Add driver... |
262 |
} |
e273bd98c hwmon: struct x86... |
263 |
static const struct x86_cpu_id __initconst cputemp_ids[] = { |
5cfc7ac7c hwmon: Convert to... |
264 265 266 267 |
X86_MATCH_VENDOR_FAM_MODEL(CENTAUR, 6, X86_CENTAUR_FAM6_C7_A, NULL), X86_MATCH_VENDOR_FAM_MODEL(CENTAUR, 6, X86_CENTAUR_FAM6_C7_D, NULL), X86_MATCH_VENDOR_FAM_MODEL(CENTAUR, 6, X86_CENTAUR_FAM6_NANO, NULL), X86_MATCH_VENDOR_FAM_MODEL(CENTAUR, 7, X86_MODEL_ANY, NULL), |
267fc9788 HWMON: Convert vi... |
268 269 270 |
{} }; MODULE_DEVICE_TABLE(x86cpu, cputemp_ids); |
df60d7013 hwmon: (via-cpute... |
271 |
static enum cpuhp_state via_temp_online; |
70c38772a hwmon: Add driver... |
272 273 |
static int __init via_cputemp_init(void) { |
df60d7013 hwmon: (via-cpute... |
274 |
int err; |
70c38772a hwmon: Add driver... |
275 |
|
267fc9788 HWMON: Convert vi... |
276 277 |
if (!x86_match_cpu(cputemp_ids)) return -ENODEV; |
70c38772a hwmon: Add driver... |
278 279 280 281 |
err = platform_driver_register(&via_cputemp_driver); if (err) goto exit; |
df60d7013 hwmon: (via-cpute... |
282 283 284 285 286 |
err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "hwmon/via:online", via_cputemp_online, via_cputemp_down_prep); if (err < 0) goto exit_driver_unreg; via_temp_online = err; |
ae9e0ce73 hwmon: (via-cpute... |
287 288 |
#ifndef CONFIG_HOTPLUG_CPU |
70c38772a hwmon: Add driver... |
289 290 |
if (list_empty(&pdev_list)) { err = -ENODEV; |
df60d7013 hwmon: (via-cpute... |
291 |
goto exit_hp_unreg; |
70c38772a hwmon: Add driver... |
292 |
} |
ae9e0ce73 hwmon: (via-cpute... |
293 |
#endif |
70c38772a hwmon: Add driver... |
294 |
return 0; |
ae9e0ce73 hwmon: (via-cpute... |
295 |
#ifndef CONFIG_HOTPLUG_CPU |
df60d7013 hwmon: (via-cpute... |
296 297 298 |
exit_hp_unreg: cpuhp_remove_state_nocalls(via_temp_online); #endif |
70c38772a hwmon: Add driver... |
299 300 301 302 303 304 305 306 |
exit_driver_unreg: platform_driver_unregister(&via_cputemp_driver); exit: return err; } static void __exit via_cputemp_exit(void) { |
df60d7013 hwmon: (via-cpute... |
307 |
cpuhp_remove_state(via_temp_online); |
70c38772a hwmon: Add driver... |
308 309 310 311 312 313 314 315 316 |
platform_driver_unregister(&via_cputemp_driver); } MODULE_AUTHOR("Harald Welte <HaraldWelte@viatech.com>"); MODULE_DESCRIPTION("VIA CPU temperature monitor"); MODULE_LICENSE("GPL"); module_init(via_cputemp_init) module_exit(via_cputemp_exit) |