From: Rudolf Marek <r.marek@assembler.cz>
To: lm-sensors@vger.kernel.org
Subject: [lm-sensors] [PATCH 2/2] k8temp add support for family 10h and 11h
Date: Wed, 01 Oct 2008 22:20:38 +0000 [thread overview]
Message-ID: <48E3F7B6.4000901@assembler.cz> (raw)
[-- Attachment #1: Type: text/plain, Size: 1173 bytes --]
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hello all,
I finally had time to add support to k8temp for the new family 10h and family
11h of CPUs.
The patch adds support for new fam10h and fam11h CPUs (aka Phenom and new 45nm
CPUs). The patch was tested on K8 fam 0fh revE and revF CPU. I dont know if it
works at all on new CPUs. Please test. You should see the max temp (always 70C
and one temperature per CPU). Of course test is on your own risk ;)
Andreas, please is TcontrolMax also 70C for fam 11h CPUs?
The patch needs review too. I tried not to change many things in the driver,
especially the sensorsp logic, but mine test sempron has -49 at core0 place0,
which needs to be fixed by another logic which will tell driver what CPU
temperatures are usable. But maybe this is for another "cleanup" patch. I think
we really need to get this kind of change to kernel first.
What do you think?
Thanks,
Rudolf
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iD8DBQFI4/e13J9wPJqZRNURAojeAJ9OCFor1n+sDshe1gkfMOVGa1LlSwCgxEAF
b7YgrXlA2eC/aWyEsnNwLGg=
=wSE1
-----END PGP SIGNATURE-----
[-- Attachment #2: k8temp_add_fam10.patch --]
[-- Type: text/x-diff, Size: 10933 bytes --]
Index: linux-2.6.27-rc7/drivers/hwmon/k8temp.c
===================================================================
--- linux-2.6.27-rc7.orig/drivers/hwmon/k8temp.c 2008-09-28 11:13:42.000000000 +0200
+++ linux-2.6.27-rc7/drivers/hwmon/k8temp.c 2008-10-02 00:01:56.383473013 +0200
@@ -1,7 +1,7 @@
/*
* k8temp.c - Linux kernel module for hardware monitoring
*
- * Copyright (C) 2006 Rudolf Marek <r.marek@assembler.cz>
+ * Copyright (C) 2006, 2008 Rudolf Marek <r.marek@assembler.cz>
*
* Inspired from the w83785 and amd756 drivers.
*
@@ -32,11 +32,18 @@
#include <linux/err.h>
#include <linux/mutex.h>
-#define TEMP_FROM_REG(val) (((((val) >> 16) & 0xff) - 49) * 1000)
-#define REG_TEMP 0xe4
+#define FAM_F_TEMP_FROM_REG(val) (((((val) >> 16) & 0xff) - 49) * 1000)
+#define FAM_10_TEMP_FROM_REG(val) (((val) >> 21) * 125)
+
+#define FAM_F_REG_TEMP 0xe4
+#define FAM_10_REG_TEMP 0xa5
+
#define REG_CPUID 0xfc
+/* real bitpos */
#define SEL_PLACE 0x40
#define SEL_CORE 0x04
+/* program logic bitpos */
+#define SEL_TEMPMAX 0x01
struct k8temp_data {
struct device *hwmon_dev;
@@ -45,46 +52,69 @@
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
- /* registers values */
u8 sensorsp; /* sensor presence bits - SEL_CORE & SEL_PLACE */
- u32 temp[2][2]; /* core, place */
+ int temp[2][2]; /* core, place */
+ int tcontrol_max;
u8 fam;
+ u32 cpuid;
};
-static struct k8temp_data *k8temp_update_device(struct device *dev)
+static void k8temp_update_device_fam_10(struct device *dev)
{
struct k8temp_data *data = dev_get_drvdata(dev);
struct pci_dev *pdev = to_pci_dev(dev);
- u8 tmp;
+ u32 tmp;
mutex_lock(&data->update_lock);
if (!data->valid
|| time_after(jiffies, data->last_updated + HZ)) {
- pci_read_config_byte(pdev, REG_TEMP, &tmp);
+
+ pci_read_config_dword(pdev, FAM_10_REG_TEMP, &tmp);
+ data->temp[0][0] = FAM_10_TEMP_FROM_REG(tmp);
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ mutex_unlock(&data->update_lock);
+}
+
+static void k8temp_update_device_fam_f(struct device *dev)
+{
+ struct k8temp_data *data = dev_get_drvdata(dev);
+ struct pci_dev *pdev = to_pci_dev(dev);
+ u32 tmp;
+
+ mutex_lock(&data->update_lock);
+
+ if (!data->valid
+ || time_after(jiffies, data->last_updated + HZ)) {
+ pci_read_config_dword(pdev, FAM_F_REG_TEMP, &tmp);
tmp &= ~(SEL_PLACE | SEL_CORE); /* Select sensor 0, core0 */
- pci_write_config_byte(pdev, REG_TEMP, tmp);
- pci_read_config_dword(pdev, REG_TEMP, &data->temp[0][0]);
+ pci_write_config_byte(pdev, FAM_F_REG_TEMP, tmp);
+ pci_read_config_dword(pdev, FAM_F_REG_TEMP, &tmp);
+ data->temp[0][0] = FAM_F_TEMP_FROM_REG(tmp);
if (data->sensorsp & SEL_PLACE) {
tmp |= SEL_PLACE; /* Select sensor 1, core0 */
- pci_write_config_byte(pdev, REG_TEMP, tmp);
- pci_read_config_dword(pdev, REG_TEMP,
- &data->temp[0][1]);
+ pci_write_config_byte(pdev, FAM_F_REG_TEMP, tmp);
+ pci_read_config_dword(pdev, FAM_F_REG_TEMP, &tmp);
+ data->temp[0][1] = FAM_F_TEMP_FROM_REG(tmp);
}
if (data->sensorsp & SEL_CORE) {
tmp &= ~SEL_PLACE; /* Select sensor 0, core1 */
tmp |= SEL_CORE;
- pci_write_config_byte(pdev, REG_TEMP, tmp);
- pci_read_config_dword(pdev, REG_TEMP,
- &data->temp[1][0]);
+ pci_write_config_byte(pdev, FAM_F_REG_TEMP, tmp);
+ pci_read_config_dword(pdev, FAM_F_REG_TEMP, &tmp);
+ data->temp[1][0] = FAM_F_TEMP_FROM_REG(tmp);
if (data->sensorsp & SEL_PLACE) {
tmp |= SEL_PLACE; /* Select sensor 1, core1 */
- pci_write_config_byte(pdev, REG_TEMP, tmp);
- pci_read_config_dword(pdev, REG_TEMP,
- &data->temp[1][1]);
+ pci_write_config_byte(pdev, FAM_F_REG_TEMP, tmp);
+ pci_read_config_dword(pdev, FAM_F_REG_TEMP, &tmp);
+ data->temp[1][1] = FAM_F_TEMP_FROM_REG(tmp);
}
}
@@ -93,7 +123,6 @@
}
mutex_unlock(&data->update_lock);
- return data;
}
/*
@@ -116,15 +145,36 @@
to_sensor_dev_attr_2(devattr);
int core = attr->nr;
int place = attr->index;
- struct k8temp_data *data = k8temp_update_device(dev);
+ struct k8temp_data *data = dev_get_drvdata(dev);
+
+ switch (data->fam) {
+ case 0xf:
+ k8temp_update_device_fam_f(dev);
+ break;
+ case 0x10:
+ k8temp_update_device_fam_10(dev);
+ break;
+ case 0x11:
+ k8temp_update_device_fam_10(dev);
+ break;
+ }
+
+ return sprintf(buf, "%d\n", data->temp[core][place]);
+}
+
- return sprintf(buf, "%d\n",
- TEMP_FROM_REG(data->temp[core][place]));
+static ssize_t show_max(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+{
+ struct k8temp_data *data = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", data->tcontrol_max);
}
/* core, place */
static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_max, NULL, 0);
static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1);
static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 1, 0);
static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 1, 1);
@@ -132,65 +182,52 @@
static struct pci_device_id k8temp_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1203) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1303) },
{ 0 },
};
MODULE_DEVICE_TABLE(pci, k8temp_ids);
-static int __devinit k8temp_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
-{
- int err;
- u8 scfg;
- u32 temp;
-
- struct k8temp_data *data;
- u32 cpuid = cpuid_eax(1);
- /* this feature should be available since SH-C0 core */
- if ((cpuid == 0xf40) || (cpuid == 0xf50) || (cpuid == 0xf51)) {
- err = -ENODEV;
- goto exit;
- }
-
- if (!(data = kzalloc(sizeof(struct k8temp_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
+static int __devinit setup_fam_10(struct pci_dev *pdev, struct k8temp_data *data)
+{
+ /* we need max temp */
+ data->sensorsp = SEL_TEMPMAX;
+ data->tcontrol_max = 70000;
- /* get real PCI based cpuid, prior revF of fam 0Fh, this reg is 0 */
- pci_read_config_dword(pdev, REG_CPUID, &cpuid);
+ data->name = (data->fam == 0x11) ? "fam11temp" : "fam10temp";
- data->fam = (cpuid & 0x00000f00) >> 8;
- data->fam += (cpuid & 0x00f00000) >> 20;
+ return 0;
+}
- switch (data->fam) {
- case 0xf:
- dev_warn(&pdev->dev, "Temperature readouts might be wrong"
- " - check errata #141\n");
- }
+static int __devinit setup_fam_f(struct pci_dev *pdev, struct k8temp_data *data)
+{
+ u8 scfg;
+ u32 temp;
+ int err = 0;
- pci_read_config_byte(pdev, REG_TEMP, &scfg);
+ pci_read_config_byte(pdev, FAM_F_REG_TEMP, &scfg);
scfg &= ~(SEL_PLACE | SEL_CORE); /* Select sensor 0, core0 */
- pci_write_config_byte(pdev, REG_TEMP, scfg);
- pci_read_config_byte(pdev, REG_TEMP, &scfg);
+ pci_write_config_byte(pdev, FAM_F_REG_TEMP, scfg);
+ pci_read_config_byte(pdev, FAM_F_REG_TEMP, &scfg);
if (scfg & (SEL_PLACE | SEL_CORE)) {
dev_err(&pdev->dev, "Configuration bit(s) stuck at 1!\n");
err = -ENODEV;
- goto exit_free;
+ goto exit_setup;
}
scfg |= (SEL_PLACE | SEL_CORE);
- pci_write_config_byte(pdev, REG_TEMP, scfg);
+ pci_write_config_byte(pdev, FAM_F_REG_TEMP, scfg);
/* now we know if we can change core and/or sensor */
- pci_read_config_byte(pdev, REG_TEMP, &data->sensorsp);
+ pci_read_config_byte(pdev, FAM_F_REG_TEMP, &data->sensorsp);
if (data->sensorsp & SEL_PLACE) {
scfg &= ~SEL_CORE; /* Select sensor 1, core0 */
- pci_write_config_byte(pdev, REG_TEMP, scfg);
- pci_read_config_dword(pdev, REG_TEMP, &temp);
+ pci_write_config_byte(pdev, FAM_F_REG_TEMP, scfg);
+ pci_read_config_dword(pdev, FAM_F_REG_TEMP, &temp);
scfg |= SEL_CORE; /* prepare for next selection */
if (!((temp >> 16) & 0xff)) /* if temp is 0 -49C is not likely */
data->sensorsp &= ~SEL_PLACE;
@@ -198,13 +235,74 @@
if (data->sensorsp & SEL_CORE) {
scfg &= ~SEL_PLACE; /* Select sensor 0, core1 */
- pci_write_config_byte(pdev, REG_TEMP, scfg);
- pci_read_config_dword(pdev, REG_TEMP, &temp);
+ pci_write_config_byte(pdev, FAM_F_REG_TEMP, scfg);
+ pci_read_config_dword(pdev, FAM_F_REG_TEMP, &temp);
if (!((temp >> 16) & 0xff)) /* if temp is 0 -49C is not likely */
data->sensorsp &= ~SEL_CORE;
}
+ /* we use sensorsp for programm logic too */
+ data->sensorsp &= (SEL_PLACE | SEL_CORE);
data->name = "k8temp";
+
+exit_setup:
+ return err;
+}
+
+static int __devinit k8temp_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int err = 0;
+
+ struct k8temp_data *data;
+ u32 cpuid = cpuid_eax(1);
+
+ /* this feature should be available since SH-C0 core */
+ if ((cpuid == 0xf40) || (cpuid == 0xf50) || (cpuid == 0xf51)) {
+ err = -ENODEV;
+ goto exit;
+ }
+
+ if (!(data = kzalloc(sizeof(struct k8temp_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ /* get real PCI based cpuid, prior revF of fam 0Fh, this reg is 0 */
+ pci_read_config_dword(pdev, REG_CPUID, &data->cpuid);
+
+ data->fam = (data->cpuid & 0x00000f00) >> 8;
+ data->fam += (data->cpuid & 0x00f00000) >> 20;
+
+ switch (data->fam) {
+ case 0xf:
+ dev_warn(&pdev->dev, "Temperature readouts might be wrong"
+ " - check errata #141\n");
+ if ((err = setup_fam_f(pdev, data)))
+ goto exit_free;
+ break;
+ case 0x10:
+ dev_warn(&pdev->dev, "Temperature readouts might be wrong"
+ " - check errata #319\n");
+ if ((err = setup_fam_10(pdev, data)))
+ goto exit_free;
+ break;
+ case 0x11:
+ if ((err = setup_fam_10(pdev, data)))
+ goto exit_free;
+ break;
+ case 0x0:
+ /* mark revE fam 0fh as fam 0fh */
+ data->fam = 0xf;
+ if ((err = setup_fam_f(pdev, data)))
+ goto exit_free;
+ break;
+ default:
+ err = -ENODEV;
+ dev_err(&pdev->dev, "Unknown family with known PCI ID\n");
+ goto exit_free;
+ }
+
mutex_init(&data->update_lock);
dev_set_drvdata(&pdev->dev, data);
@@ -236,6 +334,13 @@
goto exit_remove;
}
+ if (data->sensorsp & SEL_TEMPMAX) {
+ err = device_create_file(&pdev->dev,
+ &sensor_dev_attr_temp1_max.dev_attr);
+ if (err)
+ goto exit_remove;
+ }
+
err = device_create_file(&pdev->dev, &dev_attr_name);
if (err)
goto exit_remove;
@@ -253,6 +358,8 @@
device_remove_file(&pdev->dev,
&sensor_dev_attr_temp1_input.dev_attr);
device_remove_file(&pdev->dev,
+ &sensor_dev_attr_temp1_max.dev_attr);
+ device_remove_file(&pdev->dev,
&sensor_dev_attr_temp2_input.dev_attr);
device_remove_file(&pdev->dev,
&sensor_dev_attr_temp3_input.dev_attr);
@@ -274,6 +381,8 @@
device_remove_file(&pdev->dev,
&sensor_dev_attr_temp1_input.dev_attr);
device_remove_file(&pdev->dev,
+ &sensor_dev_attr_temp1_max.dev_attr);
+ device_remove_file(&pdev->dev,
&sensor_dev_attr_temp2_input.dev_attr);
device_remove_file(&pdev->dev,
&sensor_dev_attr_temp3_input.dev_attr);
[-- Attachment #3: k8temp_add_fam10.patch.sig --]
[-- Type: application/octet-stream, Size: 65 bytes --]
[-- Attachment #4: Type: text/plain, Size: 153 bytes --]
_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
next reply other threads:[~2008-10-01 22:20 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-10-01 22:20 Rudolf Marek [this message]
2008-10-06 15:00 ` [lm-sensors] [PATCH 2/2] k8temp add support for family 10h and Andreas Herrmann
2008-10-06 17:37 ` Jean-Marc Spaggiari
2008-11-10 9:34 ` Jean Delvare
2008-11-18 9:34 ` [lm-sensors] [PATCH 2/2] k8temp add support for family 10h Andreas Herrmann
2008-11-18 10:50 ` [lm-sensors] [PATCH 2/2] k8temp add support for family 10h and Jean Delvare
2009-01-25 15:22 ` Michael R. Doerner
2009-02-22 18:48 ` Michael R. Doerner
2009-09-07 0:27 ` Rob Robason
2009-09-14 10:10 ` Jean Delvare
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=48E3F7B6.4000901@assembler.cz \
--to=r.marek@assembler.cz \
--cc=lm-sensors@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.