summaryrefslogtreecommitdiffstats
path: root/via-hwmon-temp-sensor.patch
diff options
context:
space:
mode:
authorJesse Keating <jkeating@redhat.com>2010-07-29 17:18:45 -0700
committerJesse Keating <jkeating@redhat.com>2010-07-29 17:18:45 -0700
commit2f82dda4a9bf41e64e864889bf06564bdf826e25 (patch)
tree118a7b483ae5de4dbf83d20001302f1404866ef0 /via-hwmon-temp-sensor.patch
parent64ba2e5ffde5f2418eb26c700cb0ab62b04e5013 (diff)
downloaddom0-kernel-2f82dda4a9bf41e64e864889bf06564bdf826e25.tar.gz
dom0-kernel-2f82dda4a9bf41e64e864889bf06564bdf826e25.tar.xz
dom0-kernel-2f82dda4a9bf41e64e864889bf06564bdf826e25.zip
initial srpm import
Diffstat (limited to 'via-hwmon-temp-sensor.patch')
-rw-r--r--via-hwmon-temp-sensor.patch391
1 files changed, 391 insertions, 0 deletions
diff --git a/via-hwmon-temp-sensor.patch b/via-hwmon-temp-sensor.patch
new file mode 100644
index 0000000..49ced3e
--- /dev/null
+++ b/via-hwmon-temp-sensor.patch
@@ -0,0 +1,391 @@
+diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
+index 6857560..4414182 100644
+--- a/drivers/hwmon/Kconfig
++++ b/drivers/hwmon/Kconfig
+@@ -795,6 +795,14 @@ config SENSORS_TMP421
+ This driver can also be built as a module. If so, the module
+ will be called tmp421.
+
++config SENSORS_VIA_CPUTEMP
++ tristate "VIA CPU temperature sensor"
++ depends on X86
++ help
++ If you say yes here you get support for the temperature
++ sensor inside your CPU. Supported all are all known variants
++ of the VIA C7 and Nano.
++
+ config SENSORS_VIA686A
+ tristate "VIA686A"
+ depends on PCI
+diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
+index 9f46cb0..32ed56a 100644
+--- a/drivers/hwmon/Makefile
++++ b/drivers/hwmon/Makefile
+@@ -85,6 +85,7 @@ obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
+ obj-$(CONFIG_SENSORS_THMC50) += thmc50.o
+ obj-$(CONFIG_SENSORS_TMP401) += tmp401.o
+ obj-$(CONFIG_SENSORS_TMP421) += tmp421.o
++obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o
+ obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
+ obj-$(CONFIG_SENSORS_VT1211) += vt1211.o
+ obj-$(CONFIG_SENSORS_VT8231) += vt8231.o
+diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c
+new file mode 100644
+index 0000000..2abe516
+--- /dev/null
++++ b/drivers/hwmon/via-cputemp.c
+@@ -0,0 +1,354 @@
++/*
++ * 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>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; version 2 of the License.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++ * 02110-1301 USA.
++ */
++
++#include <linux/module.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/jiffies.h>
++#include <linux/hwmon.h>
++#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>
++
++#define DRVNAME "via_cputemp"
++
++typedef enum { SHOW_TEMP, SHOW_LABEL, SHOW_NAME } SHOW;
++
++/*
++ * Functions declaration
++ */
++
++struct via_cputemp_data {
++ struct device *hwmon_dev;
++ const char *name;
++ u32 id;
++ u32 msr;
++};
++
++/*
++ * Sysfs stuff
++ */
++
++static ssize_t show_name(struct device *dev, struct device_attribute
++ *devattr, char *buf)
++{
++ 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\n", data->name);
++ else /* show label */
++ ret = sprintf(buf, "Core %d\n", data->id);
++ return ret;
++}
++
++static ssize_t show_temp(struct device *dev,
++ struct device_attribute *devattr, char *buf)
++{
++ struct via_cputemp_data *data = dev_get_drvdata(dev);
++ u32 eax, edx;
++ int err;
++
++ err = rdmsr_safe_on_cpu(data->id, data->msr, &eax, &edx);
++ if (err)
++ return -EAGAIN;
++
++ err = sprintf(buf, "%d\n", (eax & 0xffffff) * 1000);
++
++ return err;
++}
++
++static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL,
++ SHOW_TEMP);
++static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL);
++static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME);
++
++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,
++};
++
++static int __devinit via_cputemp_probe(struct platform_device *pdev)
++{
++ struct via_cputemp_data *data;
++ struct cpuinfo_x86 *c = &cpu_data(pdev->id);
++ int err;
++ u32 eax, edx;
++
++ if (!(data = kzalloc(sizeof(struct via_cputemp_data), GFP_KERNEL))) {
++ err = -ENOMEM;
++ dev_err(&pdev->dev, "Out of memory\n");
++ goto exit;
++ }
++
++ data->id = pdev->id;
++ data->name = "via-cputemp";
++
++ switch (c->x86_model) {
++ case 0xA:
++ /* C7 A */
++ case 0xD:
++ /* C7 D */
++ data->msr = 0x1169;
++ break;
++ case 0xF:
++ /* Nano */
++ data->msr = 0x1423;
++ break;
++ default:
++ err = -ENODEV;
++ goto exit_free;
++ }
++
++ /* test if we can access the TEMPERATURE MSR */
++ err = rdmsr_safe_on_cpu(data->id, data->msr, &eax, &edx);
++ if (err) {
++ dev_err(&pdev->dev,
++ "Unable to access TEMPERATURE MSR, giving up\n");
++ goto exit_free;
++ }
++
++ platform_set_drvdata(pdev, data);
++
++ if ((err = sysfs_create_group(&pdev->dev.kobj, &via_cputemp_group)))
++ goto exit_free;
++
++ 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)\n",
++ err);
++ goto exit_class;
++ }
++
++ return 0;
++
++exit_class:
++ sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group);
++exit_free:
++ kfree(data);
++exit:
++ return err;
++}
++
++static int __devexit via_cputemp_remove(struct platform_device *pdev)
++{
++ struct via_cputemp_data *data = platform_get_drvdata(pdev);
++
++ hwmon_device_unregister(data->hwmon_dev);
++ sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group);
++ platform_set_drvdata(pdev, NULL);
++ kfree(data);
++ return 0;
++}
++
++static struct platform_driver via_cputemp_driver = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = DRVNAME,
++ },
++ .probe = via_cputemp_probe,
++ .remove = __devexit_p(via_cputemp_remove),
++};
++
++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);
++
++static int __cpuinit via_cputemp_device_add(unsigned int cpu)
++{
++ int err;
++ struct platform_device *pdev;
++ struct pdev_entry *pdev_entry;
++
++ pdev = platform_device_alloc(DRVNAME, cpu);
++ if (!pdev) {
++ err = -ENOMEM;
++ printk(KERN_ERR DRVNAME ": Device allocation failed\n");
++ 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) {
++ printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
++ err);
++ 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;
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++static void via_cputemp_device_remove(unsigned int cpu)
++{
++ struct pdev_entry *p, *n;
++ mutex_lock(&pdev_list_mutex);
++ list_for_each_entry_safe(p, n, &pdev_list, list) {
++ if (p->cpu == cpu) {
++ platform_device_unregister(p->pdev);
++ list_del(&p->list);
++ kfree(p);
++ }
++ }
++ mutex_unlock(&pdev_list_mutex);
++}
++
++static int __cpuinit via_cputemp_cpu_callback(struct notifier_block *nfb,
++ unsigned long action, void *hcpu)
++{
++ unsigned int cpu = (unsigned long) hcpu;
++
++ switch (action) {
++ case CPU_ONLINE:
++ case CPU_DOWN_FAILED:
++ via_cputemp_device_add(cpu);
++ break;
++ case CPU_DOWN_PREPARE:
++ via_cputemp_device_remove(cpu);
++ break;
++ }
++ return NOTIFY_OK;
++}
++
++static struct notifier_block via_cputemp_cpu_notifier __refdata = {
++ .notifier_call = via_cputemp_cpu_callback,
++};
++#endif /* !CONFIG_HOTPLUG_CPU */
++
++static int __init via_cputemp_init(void)
++{
++ int i, err = -ENODEV;
++ struct pdev_entry *p, *n;
++
++ if (cpu_data(0).x86_vendor != X86_VENDOR_CENTAUR) {
++ printk(KERN_DEBUG "not a VIA CPU\n");
++ goto exit;
++ }
++
++ err = platform_driver_register(&via_cputemp_driver);
++ if (err)
++ goto exit;
++
++ for_each_online_cpu(i) {
++ struct cpuinfo_x86 *c = &cpu_data(i);
++
++ if (c->x86 != 6)
++ continue;
++
++ if (c->x86_model < 0x0a)
++ continue;
++
++ if (c->x86_model > 0x0f) {
++ printk(KERN_WARNING DRVNAME ": Unknown CPU "
++ "model %x\n", c->x86_model);
++ continue;
++ }
++
++ err = via_cputemp_device_add(i);
++ if (err)
++ goto exit_devices_unreg;
++ }
++ if (list_empty(&pdev_list)) {
++ err = -ENODEV;
++ goto exit_driver_unreg;
++ }
++
++#ifdef CONFIG_HOTPLUG_CPU
++ register_hotcpu_notifier(&via_cputemp_cpu_notifier);
++#endif
++ return 0;
++
++exit_devices_unreg:
++ mutex_lock(&pdev_list_mutex);
++ list_for_each_entry_safe(p, n, &pdev_list, list) {
++ platform_device_unregister(p->pdev);
++ list_del(&p->list);
++ kfree(p);
++ }
++ mutex_unlock(&pdev_list_mutex);
++exit_driver_unreg:
++ platform_driver_unregister(&via_cputemp_driver);
++exit:
++ return err;
++}
++
++static void __exit via_cputemp_exit(void)
++{
++ struct pdev_entry *p, *n;
++#ifdef CONFIG_HOTPLUG_CPU
++ unregister_hotcpu_notifier(&via_cputemp_cpu_notifier);
++#endif
++ mutex_lock(&pdev_list_mutex);
++ list_for_each_entry_safe(p, n, &pdev_list, list) {
++ platform_device_unregister(p->pdev);
++ list_del(&p->list);
++ kfree(p);
++ }
++ mutex_unlock(&pdev_list_mutex);
++ 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)