[PATCH] Add nForce support to amd756 driver

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

 



Hi!

I have modified the amd756 driver to support the nVidia nForce SMBus
controller.

There is of course no technical documentation (this is an nVidia product
after all :-), so this is just guesswork.

The base address is hardwired at 0x5500, because the original code does not
work, and reverse engineering the windows software shows that they have
hardcoded it as well.

It might be a good idea to change the amdsetup member in the sd struct to be
a pointer to a device specific setup function, so that it will be easier to
add new devices later on.

I have just made up a device id, I don't know the proper way to do it.

I hope that the code still works with the true amd chips.
I have only tested it on a single computer, so I have no idea whether it
will function properly for others.

Greets,
	Csaba Halasz
	hcs at ics2.ics.tvnet.hu
	jester01 at freemail.hu (use if above does not work)

diff -u -r -N lm_sensors2.orig/kernel/busses/i2c-amd756.c
lm_sensors2/kernel/busses/i2c-amd756.c
--- lm_sensors2.orig/kernel/busses/i2c-amd756.c	Sat Dec 29 01:20:47 2001
+++ lm_sensors2/kernel/busses/i2c-amd756.c	Thu Apr 25 03:23:11 2002
@@ -25,7 +25,11 @@
 */

 /*
-   Supports AMD756, AMD766, and AMD768.
+    2002-04-08: Added nForce support. (Csaba Halasz)
+*/
+
+/*
+   Supports AMD756, AMD766, AMD768 and nVidia nForce
    Note: we assume there can only be one device, with one SMBus interface.
 */

@@ -51,11 +55,31 @@
 #ifndef PCI_DEVICE_ID_AMD_766
 #define PCI_DEVICE_ID_AMD_766 0x7413
 #endif
+#ifndef PCI_DEVICE_ID_AMD_768
+#define PCI_DEVICE_ID_AMD_768 0x7443
+#endif
+#ifndef PCI_VENDOR_ID_NVIDIA
+#define PCI_VENDOR_ID_NVIDIA 0x10DE
+#endif
+#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS 0x01B4
+#endif
+
+struct sd {
+    const unsigned short vendor;
+    const unsigned short device;
+    const unsigned short function;
+    const char* name;
+    int amdsetup:1;
+};

-static int supported[] = {PCI_DEVICE_ID_AMD_756,
-                          PCI_DEVICE_ID_AMD_766,
-			  0x7443, /* AMD768 */
-                          0 };
+static struct sd supported[] = {
+    {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_756, 3, "AMD756", 1},
+    {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_766, 3, "AMD766", 1},
+    {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_768, 3, "AMD768", 1},
+    {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS, 1, "nVidia
nForce", 0},
+    {0, 0, 0}
+};

 /* AMD756 SMBus address offsets */
 #define SMB_ADDR_OFFSET        0xE0
@@ -149,7 +173,7 @@
 int amd756_setup(void)
 {
 	unsigned char temp;
-	int *num = supported;
+	struct sd *currdev;
 	struct pci_dev *AMD756_dev = NULL;

 	if (pci_present() == 0) {
@@ -157,38 +181,41 @@
 		return(-ENODEV);
 	}

-	/* Look for the AMD756, function 3 */
-	/* Note: we keep on searching until we have found 'function 3' */
-	do {
-		if((AMD756_dev = pci_find_device(PCI_VENDOR_ID_AMD,
-					      *num, AMD756_dev))) {
-			if(PCI_FUNC(AMD756_dev->devfn) != 3)
-				continue;
-			break;
+	/* Look for a supported chip */
+	for(currdev = supported; currdev->vendor; ) {
+		AMD756_dev = pci_find_device(currdev->vendor,
+						currdev->device, AMD756_dev);
+		if (AMD756_dev != NULL)	{
+			if (PCI_FUNC(AMD756_dev->devfn) == currdev->function)
+				break;
+		} else {
+		    currdev++;
 		}
-		num++;
-	} while (*num != 0);
+	}

 	if (AMD756_dev == NULL) {
 		printk
-		    ("i2c-amd756.o: Error: Can't detect AMD756, function 3!\n");
+		    ("i2c-amd756.o: Error: No AMD756 or compatible device detected!\n");
 		return(-ENODEV);
 	}
-
-
-	pci_read_config_byte(AMD756_dev, SMBGCFG, &temp);
-	if ((temp & 128) == 0) {
-		printk
-		  ("i2c-amd756.o: Error: SMBus controller I/O not enabled!\n");
+	printk(KERN_INFO "i2c-amd756.o: Found %s SMBus controller.\n",
currdev->name);
+
+	if (currdev->amdsetup)
+	{
+		pci_read_config_byte(AMD756_dev, SMBGCFG, &temp);
+		if ((temp & 128) == 0) {
+			printk("i2c-amd756.o: Error: SMBus controller I/O not enabled!\n");
+		}
 		return(-ENODEV);
-	}
-
-	/* Determine the address of the SMBus areas */
-	/* Technically it is a dword but... */
-	pci_read_config_word(AMD756_dev, SMBBA, &amd756_smba);
-	amd756_smba &= 0xff00;
-	amd756_smba += SMB_ADDR_OFFSET;

+		/* Determine the address of the SMBus areas */
+		/* Technically it is a dword but... */
+		pci_read_config_word(AMD756_dev, SMBBA, &amd756_smba);
+		amd756_smba &= 0xff00;
+		amd756_smba += SMB_ADDR_OFFSET;
+	} else {
+		amd756_smba = 0x5500;
+	}
 	if (check_region(amd756_smba, SMB_IOSIZE)) {
 		printk
 		    ("i2c-amd756.o: SMB region 0x%x already in use!\n",
diff -u -r -N lm_sensors2.orig/prog/detect/sensors-detect
lm_sensors2/prog/detect/sensors-detect
--- lm_sensors2.orig/prog/detect/sensors-detect	Tue Apr  2 04:08:56 2002
+++ lm_sensors2/prog/detect/sensors-detect	Thu Apr 25 03:23:11 2002
@@ -514,7 +514,8 @@
        devid  => 0x01b4,
        func => 1,
        procid => "nVidia nForce SMBus",
-       match => sub { $_[0] =~ /dontmatchthis/ },
+       driver => "i2c-amd756",
+       match => sub { $_[0] =~ /^SMBus AMD7X6 adapter at [0-9,a-f]{4}/ },
      } ,
      {
        vendid => 0x1166,



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

  Powered by Linux