[PATCH] hwmon: k8temp.c Add support for AMD 11h

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 2009-07-06 at 18:44 +0200, Rudolf Marek wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Hi all,
> 
> It seems mine emails are arriving multiple times. I'm sorry about that. Axel, is
> it doing mine ISP?
> 
> 
> > I totally agree with you that's why I removed the support for 10h as per
> > your suggestion.
> 
> 
> Ok fine.
> 
> > 
> >> I'm perfectly fine if you come up with a patch for fam 11h because the Errata 
> > is still waiting for your approval.
> 
> Aha sorry I forgot about this one. Please can you re-structure it so there are
> not a goto's I think kernel codingstyle allows them only for error paths.
> 

Ok, I also removed goto and here is updated patch :

[PATCH] hwmon: k8temp.c Add support for AMD 11h

Added AMD 11h support in k8temp. Thanks to Rudolf Marek for help.

Signed-off-by: Jaswinder Singh Rajput <jaswinderrajput at gmail.com>
---
 drivers/hwmon/Kconfig  |    4 +-
 drivers/hwmon/k8temp.c |   75 ++++++++++++++++++++++++++++++-----------------
 2 files changed, 50 insertions(+), 29 deletions(-)

diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 2d50166..e7b4941 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -200,11 +200,11 @@ config SENSORS_ADT7475
 	  will be called adt7475.
 
 config SENSORS_K8TEMP
-	tristate "AMD Athlon64/FX or Opteron temperature sensor"
+	tristate "AMD Athlon64/FX or Opteron or 11h temperature sensor"
 	depends on X86 && PCI && EXPERIMENTAL
 	help
 	  If you say yes here you get support for the temperature
-	  sensor(s) inside your CPU. Supported is whole AMD K8
+	  sensor(s) inside your CPU. Supported is whole AMD K8 and 11h
 	  microarchitecture. Please note that you will need at least
 	  lm-sensors 2.10.1 for proper userspace support.
 
diff --git a/drivers/hwmon/k8temp.c b/drivers/hwmon/k8temp.c
index 1fe9951..f91da26 100644
--- a/drivers/hwmon/k8temp.c
+++ b/drivers/hwmon/k8temp.c
@@ -1,5 +1,6 @@
 /*
  * k8temp.c - Linux kernel module for hardware monitoring
+ *	      for AMD K8 and 11h
  *
  * Copyright (C) 2006 Rudolf Marek <r.marek at assembler.cz>
  *
@@ -33,7 +34,7 @@
 #include <linux/mutex.h>
 #include <asm/processor.h>
 
-#define TEMP_FROM_REG(val)	(((((val) >> 16) & 0xff) - 49) * 1000)
+#define REG_TCTL	0xa4
 #define REG_TEMP	0xe4
 #define SEL_PLACE	0x40
 #define SEL_CORE	0x04
@@ -52,42 +53,61 @@ struct k8temp_data {
 	u32 temp_offset;
 };
 
-static struct k8temp_data *k8temp_update_device(struct device *dev)
+static inline unsigned long temp_from_reg(unsigned long val)
+{
+	if (boot_cpu_data.x86 > 0xf)
+		return (val >> 21) * 125;
+	else
+		return (((val >> 16) & 0xff) - 49) * 1000;
+}
+
+static void update_11h_temp(struct pci_dev *pdev, struct k8temp_data *data)
+{
+	pci_read_config_dword(pdev, REG_TCTL, &data->temp[0][0]);
+}
+
+static void update_k8_temp(struct pci_dev *pdev, struct k8temp_data *data)
 {
-	struct k8temp_data *data = dev_get_drvdata(dev);
-	struct pci_dev *pdev = to_pci_dev(dev);
 	u8 tmp;
 
-	mutex_lock(&data->update_lock);
+	pci_read_config_byte(pdev, 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]);
 
-	if (!data->valid
-	    || time_after(jiffies, data->last_updated + HZ)) {
-		pci_read_config_byte(pdev, REG_TEMP, &tmp);
-		tmp &= ~(SEL_PLACE | SEL_CORE);		/* Select sensor 0, core0 */
+	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][0]);
+		pci_read_config_dword(pdev, REG_TEMP, &data->temp[0][1]);
+	}
+
+	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]);
 
 		if (data->sensorsp & SEL_PLACE) {
-			tmp |= SEL_PLACE;	/* Select sensor 1, core0 */
+			tmp |= SEL_PLACE;	/* Select sensor 1, core1 */
 			pci_write_config_byte(pdev, REG_TEMP, tmp);
 			pci_read_config_dword(pdev, REG_TEMP,
-					      &data->temp[0][1]);
+					      &data->temp[1][1]);
 		}
+	}
+}
 
-		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]);
-
-			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]);
-			}
-		}
+static struct k8temp_data *k8temp_update_device(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct k8temp_data *data = dev_get_drvdata(dev);
+
+	mutex_lock(&data->update_lock);
+
+	if (!data->valid || time_after(jiffies, data->last_updated + HZ)) {
+		if (boot_cpu_data.x86 > 0xf)
+			update_11h_temp(pdev, data);
+		else
+			update_k8_temp(pdev, data);
 
 		data->last_updated = jiffies;
 		data->valid = 1;
@@ -123,7 +143,7 @@ static ssize_t show_temp(struct device *dev,
 	if (data->swap_core_select)
 		core = core ? 0 : 1;
 
-	temp = TEMP_FROM_REG(data->temp[core][place]) + data->temp_offset;
+	temp = temp_from_reg(data->temp[core][place]) + data->temp_offset;
 
 	return sprintf(buf, "%d\n", temp);
 }
@@ -138,6 +158,7 @@ static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
 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, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
 	{ 0 },
 };
 
-- 
1.6.0.6





[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux