diff -Nru linux-2.6.12/Documentation/amd76x_pm.txt linux-2.6.12-jo3/Documentation/amd76x_pm.txt
--- linux-2.6.12/Documentation/amd76x_pm.txt	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.12-jo3/Documentation/amd76x_pm.txt	2005-08-12 22:37:42.000000000 +0200
@@ -0,0 +1,123 @@
+	ACPI style power management for SMP AMD-760MP(X) based systems
+	==============================================================
+
+For use until the ACPI project catches up. :-)
+
+Using this module saves about 70 - 90W of energy in the idle mode compared
+to the default idle mode. Waking up from the idle mode is fast to keep the
+system response time good. Currently no CPU load calculation is done, the
+system exits the idle mode after every C2 call.
+
+NOTE: Currently there's a bug somewhere where the reading the
+      P_LVL2 for the first time causes the system to sleep instead of 
+      idling. This means that you need to hit the power button once to
+      wake the system after loading the module for the first time after
+      reboot. After that the system idles as supposed.
+      (Only observed on Tony's system.)
+
+
+Influenced by Vcool, and LVCool. Rewrote everything from scratch to
+use the PCI features in Linux, and to support SMP systems.
+
+Currently tested amongst others on a TYAN S2460 (760MP) system (Tony), an
+ASUS A7M266-D (760MPX) system (Johnathan) and a TYAN S2466 (760MPX)
+system (Jo). Adding support for other Athlon SMP or single processor
+systems should be easy if desired.  
+
+You'll find some files in /sys/devices/pci0000:00/0000:00:00.0/
+lazy_idle (rw)	see below
+spin_idle (rw)	see below
+C2_cnt    (ro)	the number of C2 calls
+
+There are two parameters for tuning the behaviour of amd76x_pm:
+lazy_idle and spin_idle.
+* lazy_idle defines the number of idle calls into amd76x_smp_idle that are
+needed to enter C2 mode.  Higher values give better system response and
+lower values give better cooling.
+* spin_idle is the maximum number of spin cycles in an inner idle loop.
+In this inner loop one CPU waits for the remaining CPUs to become idle.
+Thus this has an large impact on cooling: lower values give less cooling
+as CPUs are less "syncronized" in their idleing.  Higher values result
+in a delayed return to the kernel's main idle loop.  (I don't know if
+this has any negative impacts.)
+
+Both values have an influence on the system clock stability: too much
+cooling may disturb the system clock.  Play around with these parameters
+and try to find values that give acceptable cooling and clock stability.
+The parameters may be set as module parameters to amd76x_pm or via the
+writable sysfs files lazy_idle and spin_idle (see above).
+
+The default value of 512 for lazy_idle is propably too high for any
+board.  I hope this default doesn't break anything :-)
+spin_idle defaults to twice of lazy_idle (if lazy_idle is given as
+module paremeter).  This parameter seems to be much less critical as
+long as it is "large enough".
+
+Some hints to tune lazy_idle and spin_idle from my experiments:
+Watch the rate of C2 calls per second.  Anything below HZ seems to be
+completely useless.  At a rate of 2*HZ you will realize a significant
+cooling and still a robust clock.  Lowering lazy_idle below this point
+will give even more cooling but less clock stability.  It's your choice
+;-)
+
+This software is licensed under GNU General Public License Version 2 
+as specified in file COPYING in the Linux kernel source tree main 
+directory.
+
+Copyright (C) 2002 - 2005	Johnathan Hicks <thetech@folkwolf.net>
+				Tony Lindgren <tony@atomide.com>
+				Joerg Sommrey <jo@sommrey.de>
+
+History:
+
+  20020702 - amd-smp-idle: Tony Lindgren <tony@atomide.com>
+Influenced by Vcool, and LVCool. Rewrote everything from scratch to
+use the PCI features in Linux, and to support SMP systems. Provides
+C2 idling on SMP AMD-760MP systems.
+
+  20020722: JH
+  	I adapted Tony's code for the AMD-765/766 southbridge and adapted it
+  	according to the AMD-768 data sheet to provide the same capability for
+  	SMP AMD-760MPX systems. Posted to acpi-devel list.
+  	
+  20020722: Alan Cox
+  	Replaces non-functional amd76x_pm code in -ac tree.
+  	
+  20020730: JH
+  	Added ability to do normal throttling (the non-thermal kind), C3 idling
+  	and Power On Suspend (S1 sleep). It would be very easy to tie swsusp
+  	into activate_amd76x_SLP(). C3 idling doesn't happen yet; see my note
+  	in amd76x_smp_idle(). I've noticed that when NTH and idling are both
+  	enabled, my hardware locks and requires a hard reset, so I have
+  	#ifndefed around the idle loop setting to prevent this. POS locks it up
+  	too, both ought to be fixable. I've also noticed that idling and NTH
+  	make some interference that is picked up by the onboard sound chip on
+  	my ASUS A7M266-D motherboard.
+
+  20030601: Pasi Savolainen
+     Simple port to 2.5
+     Added sysfs interface for making nice graphs with mrtg.
+     Look for /sys/devices/pci0/00:00.0/C2_cnt & lazy_idle (latter writable)
+
+  20050601: Joerg Sommrey (jo)
+     2.6 stuff
+     redesigned amd76x_smp_idle.  The algorithm is basically the same
+        but the implementation has changed.  This part is now independent
+        from the number of CPUs and data is locked against concurrent
+        updates from different CPUs.
+     use _smp_processor_id()
+     use cpu_idle_wait()
+     NTH and POS code not touched and not tested.
+
+  20050621: jo
+     separated C3, NTH and POS code into extra patch
+
+  20050812: jo
+     rewritten amd76x_smp_idle completely. It's much simpler now but
+     does a good job - the KISS approach.  Introduced a new tunable
+     spin_idle.
+  
+TODO: Thermal throttling (TTH).
+	 /proc interface for normal throttling level.
+	 /proc interface for POS.
+	 C3 mode for the redesigned idle loop.
diff -Nru linux-2.6.12/drivers/acpi/Kconfig linux-2.6.12-jo3/drivers/acpi/Kconfig
--- linux-2.6.12/drivers/acpi/Kconfig	2005-07-19 20:49:10.000000000 +0200
+++ linux-2.6.12-jo3/drivers/acpi/Kconfig	2005-08-12 22:38:19.000000000 +0200
@@ -352,4 +352,18 @@
 		$>modprobe acpi_memhotplug 
 endif	# ACPI
 
+config AMD76X_PM
+        tristate "AMD76x Native Power Management support"
+        default n
+        depends on X86 && PCI
+        ---help---
+          This driver enables Power Management on AMD760MP & AMD760MPX chipsets.          This is about same as ACPI C2, except that ACPI folks don't do SMP ATM.
+          See Documentation/amd76x_pm.txt for further details.
+
+          To compile this driver as a module ( = code which can be inserted in
+          and removed from the running kernel whenever you want), say M
+          here.  The module will be called amd76x_pm.
+
+          If unsure, say N.
+
 endmenu
diff -Nru linux-2.6.12/drivers/acpi/Makefile linux-2.6.12-jo3/drivers/acpi/Makefile
--- linux-2.6.12/drivers/acpi/Makefile	2005-07-19 20:49:10.000000000 +0200
+++ linux-2.6.12-jo3/drivers/acpi/Makefile	2005-08-12 22:39:10.000000000 +0200
@@ -56,3 +56,8 @@
 obj-$(CONFIG_ACPI_TOSHIBA)	+= toshiba_acpi.o
 obj-$(CONFIG_ACPI_BUS)		+= scan.o motherboard.o
 obj-$(CONFIG_ACPI_HOTPLUG_MEMORY)	+= acpi_memhotplug.o
+
+#
+# not really ACPI thing, until they handle SMP.
+#
+obj-$(CONFIG_AMD76X_PM)               += amd76x_pm.o
diff -Nru linux-2.6.12/drivers/acpi/amd76x_pm.c linux-2.6.12-jo3/drivers/acpi/amd76x_pm.c
--- linux-2.6.12/drivers/acpi/amd76x_pm.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.12-jo3/drivers/acpi/amd76x_pm.c	2005-08-12 22:35:38.000000000 +0200
@@ -0,0 +1,560 @@
+/*
+ * ACPI style PM for SMP AMD-760MP(X) based systems.
+ * For use until the ACPI project catches up. :-)
+ *
+ * Copyright (C) 2002 - 2005	Johnathan Hicks <thetech@folkwolf.net>
+ * 				Tony Lindgren <tony@atomide.com>
+ * 				Joerg Sommrey <jo@sommrey.de>
+ *
+ * History:
+ * 
+ *   20020702 - amd-smp-idle: Tony Lindgren <tony@atomide.com>
+ *	Influenced by Vcool, and LVCool. Rewrote everything from scratch to
+ *	use the PCI features in Linux, and to support SMP systems. Provides
+ *	C2 idling on SMP AMD-760MP systems.
+ *	
+ *   20020722: JH
+ *   	I adapted Tony's code for the AMD-765/766 southbridge and adapted it
+ *   	according to the AMD-768 data sheet to provide the same capability for
+ *   	SMP AMD-760MPX systems. Posted to acpi-devel list.
+ *   	
+ *   20020722: Alan Cox
+ *   	Replaces non-functional amd76x_pm code in -ac tree.
+ *   	
+ *   20020730: JH
+ *   	Added ability to do normal throttling (the non-thermal kind), C3 idling
+ *   	and Power On Suspend (S1 sleep). It would be very easy to tie swsusp
+ *   	into activate_amd76x_SLP(). C3 idling doesn't happen yet; see my note
+ *   	in amd76x_smp_idle(). I've noticed that when NTH and idling are both
+ *   	enabled, my hardware locks and requires a hard reset, so I have
+ *   	#ifndefed around the idle loop setting to prevent this. POS locks it up
+ *   	too, both ought to be fixable. I've also noticed that idling and NTH
+ *   	make some interference that is picked up by the onboard sound chip on
+ *   	my ASUS A7M266-D motherboard.
+ *
+ *   20030601: Pasi Savolainen
+ *      Simple port to 2.5
+ *      Added sysfs interface for making nice graphs with mrtg.
+ *      Look for /sys/devices/pci0/00:00.0/C2_cnt & lazy_idle (latter writable)
+ *
+ *
+ *   20050601: Joerg Sommrey (jo)
+ *        2.6 stuff
+ *        redesigned amd76x_smp_idle.  The algorithm is basically the same
+ *           but the implementation has changed.  This part is now independent
+ *           from the number of CPUs and data is locked against concurrent
+ *           updates from different CPUs.
+ *        use _smp_processor_id()
+ *        use cpu_idle_wait()
+ *        NTH and POS code not touched and not tested.
+ *   20050621: jo
+ *        separated C3, NTH and POS code into extra patch
+ *
+ *   20050812: jo
+ *        rewritten amd76x_smp_idle completely. It's much simpler now but
+ *        does a good job - the KISS approach.  Introduced a new tunable
+ *        spin_idle.
+ *
+ * TODO: Thermal throttling (TTH).
+ * 	 /proc interface for normal throttling level.
+ * 	 /proc interface for POS.
+ * 	 C3 mode for the redesigned idle loop.
+ *
+ *
+ *    <Notes from 20020722-ac revision>
+ *
+ * Processor idle mode module for AMD SMP 760MP(X) based systems
+ *
+ * Copyright (C) 2002 Tony Lindgren <tony@atomide.com>
+ *                    Johnathan Hicks (768 support)
+ *
+ * Using this module saves about 70 - 90W of energy in the idle mode compared
+ * to the default idle mode. Waking up from the idle mode is fast to keep the
+ * system response time good. Currently no CPU load calculation is done, the
+ * system exits the idle mode if the idle function runs twice on the same
+ * processor in a row. This only works on SMP systems, but maybe the idle mode
+ * enabling can be integrated to ACPI to provide C2 mode at some point.
+ *
+ * NOTE: Currently there's a bug somewhere where the reading the
+ *       P_LVL2 for the first time causes the system to sleep instead of 
+ *       idling. This means that you need to hit the power button once to
+ *       wake the system after loading the module for the first time after
+ *       reboot. After that the system idles as supposed.
+ *
+ *
+ * Influenced by Vcool, and LVCool. Rewrote everything from scratch to
+ * use the PCI features in Linux, and to support SMP systems.
+ * 
+ * Currently only tested on a TYAN S2460 (760MP) system (Tony) and an
+ * ASUS A7M266-D (760MPX) system (Johnathan). Adding support for other Athlon
+ * SMP or single processor systems should be easy if desired.
+ *
+ * This software is licensed under GNU General Public License Version 2 
+ * as specified in file COPYING in the Linux kernel source tree main 
+ * directory.
+ * 
+ *   </Notes from 20020722-ac revision>
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/version.h>
+#include <asm/atomic.h>
+
+#include <linux/amd76x_pm.h>
+
+#define VERSION	"20050812"
+
+extern void default_idle(void);
+static void amd76x_smp_idle(void);
+static int amd76x_pm_main(void);
+
+static unsigned long lazy_idle = 0;
+static unsigned long spin_idle = 0;
+module_param(lazy_idle, long, 0);
+MODULE_PARM_DESC(lazy_idle,
+		"number of idle cycles before entering power saving mode");
+
+module_param(spin_idle, long, 0);
+MODULE_PARM_DESC(spin_idle,
+		"number of spin cycles to wait for other CPUs to become idle");
+MODULE_AUTHOR("Tony Lindgren, Johnathan Hicks, Joerg Sommrey, others");
+MODULE_DESCRIPTION("ACPI style power management for SMP AMD-760MP(X) "
+		"based systems");
+
+
+static struct pci_dev *pdev_nb;
+static struct pci_dev *pdev_sb;
+
+struct PM_cfg {
+	unsigned int status_reg;
+	unsigned int C2_reg;
+	unsigned int slp_reg;
+	unsigned int resume_reg;
+	void (*orig_idle) (void);
+	void (*curr_idle) (void);
+};
+
+struct idle_stat {
+	atomic_t num_idle;
+	atomic_t num_C2;
+};
+
+static struct idle_stat amd76x_stat __cacheline_aligned_in_smp = {
+	.num_idle = ATOMIC_INIT(0),
+	.num_C2 = ATOMIC_INIT(0)
+};
+
+static struct PM_cfg amd76x_pm_cfg;
+
+struct cpu_stat {
+	int idle_count;
+	int C2_cnt;
+	int _fill[2];
+};
+
+static struct cpu_stat prs[NR_CPUS] __cacheline_aligned_in_smp;
+
+static struct pci_device_id  __devinitdata amd_nb_tbl[] = {
+	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, PCI_ANY_ID,
+		PCI_ANY_ID,},
+	{0,}
+};
+
+static struct pci_device_id  __devinitdata amd_sb_tbl[] = {
+	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, PCI_ANY_ID,
+		PCI_ANY_ID,},
+	{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7443, PCI_ANY_ID,
+		PCI_ANY_ID,},
+	{0,}
+};
+
+/*
+ * Configures the AMD-762 northbridge to support PM calls
+ */
+static int
+config_amd762(int enable)
+{
+	unsigned int regdword;
+
+	/* Enable STPGNT in BIU Status/Control for cpu0 */
+	pci_read_config_dword(pdev_nb, 0x60, &regdword);
+	regdword |= (1 << 17);
+	pci_write_config_dword(pdev_nb, 0x60, regdword);
+
+	/* Enable STPGNT in BIU Status/Control for cpu1 */
+	pci_read_config_dword(pdev_nb, 0x68, &regdword);
+	regdword |= (1 << 17);
+	pci_write_config_dword(pdev_nb, 0x68, regdword);
+
+	/* DRAM refresh enable */
+	pci_read_config_dword(pdev_nb, 0x58, &regdword);
+	regdword &= ~(1 << 19);
+	pci_write_config_dword(pdev_nb, 0x58, regdword);
+
+	/* Self refresh enable */
+	pci_read_config_dword(pdev_nb, 0x70, &regdword);
+	regdword |= (1 << 18);
+	pci_write_config_dword(pdev_nb, 0x70, regdword);
+
+	return 0;
+}
+
+
+/*
+ * Get the base PMIO address and set the pm registers in amd76x_pm_cfg.
+ */
+static void
+amd76x_get_PM(void)
+{
+	unsigned int regdword;
+
+	/* Get the address for pm status, P_LVL2, etc */
+	pci_read_config_dword(pdev_sb, 0x58, &regdword);
+	regdword &= 0xff80;
+	amd76x_pm_cfg.status_reg = (regdword + 0x00);
+	amd76x_pm_cfg.slp_reg =    (regdword + 0x04);
+	amd76x_pm_cfg.C2_reg =     (regdword + 0x14);
+	amd76x_pm_cfg.resume_reg = (regdword + 0x16); /* N/A for 768 */
+}
+
+
+/*
+ * En/Disable PMIO and configure W4SG & STPGNT.
+ */
+static int
+config_PMIO_amd76x(int is_766, int enable)
+{
+	unsigned char regbyte;
+
+	/* Clear W4SG, and set PMIOEN, if using a 765/766 set STPGNT as well.
+	 * AMD-766: C3A41; page 59 in AMD-766 doc
+	 * AMD-768: DevB:3x41C; page 94 in AMD-768 doc */
+	pci_read_config_byte(pdev_sb, 0x41, &regbyte);
+	if(enable) {
+		regbyte |= ((is_766 << 1) | (1 << 7));
+	}
+	pci_write_config_byte(pdev_sb, 0x41, regbyte);
+	return 0;
+}
+
+/*
+ * C2 idle support for AMD-766.
+ */
+static void
+config_amd766_C2(int enable)
+{
+	unsigned int regdword;
+
+	/* Set C2 options in C3A50, page 63 in AMD-766 doc */
+	pci_read_config_dword(pdev_sb, 0x50, &regdword);
+	if(enable) {
+		regdword &= ~((DCSTOP_EN | CPUSTP_EN | PCISTP_EN | SUSPND_EN |
+					CPURST_EN) << C2_REGS);
+		regdword |= (STPCLK_EN	/* ~ 20 Watt savings max */
+			 |  CPUSLP_EN)	/* Additional ~ 70 Watts max! */
+			 << C2_REGS;
+	}
+	else
+		regdword &= ~((STPCLK_EN | CPUSLP_EN) << C2_REGS);
+	pci_write_config_dword(pdev_sb, 0x50, regdword);
+}
+
+/*
+ * Configures the 765 & 766 southbridges.
+ */
+static int
+config_amd766(int enable)
+{
+	amd76x_get_PM();
+	config_PMIO_amd76x(1, 1);
+	config_amd766_C2(enable);
+
+	return 0;
+}
+
+
+/*
+ * C2 idling support for AMD-768.
+ */
+static void
+config_amd768_C2(int enable)
+{
+	unsigned char regbyte;
+
+	/* Set C2 options in DevB:3x4F, page 100 in AMD-768 doc */
+	pci_read_config_byte(pdev_sb, 0x4F, &regbyte);
+	if(enable)
+		regbyte |= C2EN;
+	else
+		regbyte ^= C2EN;
+	pci_write_config_byte(pdev_sb, 0x4F, regbyte);
+}
+
+/*
+ * Configures the 768 southbridge to support idle calls, and gets
+ * the processor idle call register location.
+ */
+static int
+config_amd768(int enable)
+{
+	amd76x_get_PM();
+
+	config_PMIO_amd76x(0, 1);
+
+	config_amd768_C2(enable);
+
+	return 0;
+}
+
+/*
+ * Idle loop for single processor systems
+ */
+void
+amd76x_up_idle(void)
+{
+	/* ACPI knows how to do C2 on SMP when cpu_count < 2
+	 * we really shouldn't end up here anyway. 
+	 */
+	amd76x_pm_cfg.orig_idle();
+}
+
+/*
+ * Idle loop for SMP systems
+ *
+ * Locking is done using atomic_t variables, no spin locks needed.
+ *
+ */
+
+static void
+amd76x_smp_idle(void)
+{
+	int cpu;
+	int i;
+	int num_online;
+
+	cpu = _smp_processor_id();
+
+	/* Spin inside (outer) idle loop until lazy_idle cycles
+	 * are reached.
+	 */
+	if (likely(++prs[cpu].idle_count <= lazy_idle))
+		return;
+
+	/* Now we are ready do go C2. */
+	local_irq_disable();
+	atomic_inc(&amd76x_stat.num_idle);
+	num_online = num_online_cpus();
+
+	/* Spin inside inner loop until either
+	 * - spin_idle cycles are reached
+	 * - there is work
+	 * - all CPUs are idle
+	 */
+	for (i = 0; i < spin_idle; i++) {
+		if (unlikely(need_resched()))
+			break;
+
+		smp_mb();
+		if (unlikely(atomic_read(&amd76x_stat.num_idle) ==
+					num_online)) {
+			prs[cpu].C2_cnt++;
+			/* Invoke C2 */
+			inb(amd76x_pm_cfg.C2_reg);
+			break;
+		}
+	}
+
+	smp_mb();
+	atomic_dec(&amd76x_stat.num_idle);
+	prs[cpu].idle_count = 0;
+	local_irq_enable();
+}
+
+/*
+ *   sysfs support, RW
+ */
+static ssize_t 
+show_lazy_idle (struct device *dev, char *buf)
+{
+	return sprintf(buf,"%lu\n", lazy_idle);  
+}
+
+static ssize_t         
+set_lazy_idle (struct device *dev, const char *buf, size_t count)
+{
+	lazy_idle = simple_strtoul(buf, NULL, 10);
+	return count;
+}
+
+static ssize_t 
+show_spin_idle (struct device *dev, char *buf)
+{
+	return sprintf(buf,"%lu\n", spin_idle);  
+}
+
+static ssize_t         
+set_spin_idle (struct device *dev, const char *buf, size_t count)
+{
+	spin_idle = simple_strtoul(buf, NULL, 10);
+	return count;
+}
+
+static ssize_t 
+show_C2_cnt (struct device *dev, char *buf)
+{
+	unsigned int C2_cnt = 0;
+	int i;
+
+	for_each_online_cpu(i)
+		C2_cnt += prs[i].C2_cnt;
+	return sprintf(buf,"%u\n", C2_cnt);  
+}
+
+static DEVICE_ATTR(lazy_idle, S_IRUGO | S_IWUSR,
+		   show_lazy_idle, set_lazy_idle);
+static DEVICE_ATTR(spin_idle, S_IRUGO | S_IWUSR,
+		   show_spin_idle, set_spin_idle);
+static DEVICE_ATTR(C2_cnt, S_IRUGO,
+		   show_C2_cnt, NULL);
+
+/*
+ * Finds and initializes the bridges, and then sets the idle function
+ */
+static int
+amd76x_pm_main(void)
+{
+	int i;
+
+	amd76x_pm_cfg.orig_idle = 0;
+	if(lazy_idle == 0)
+	    lazy_idle = LAZY_IDLE_DELAY;
+	if(spin_idle == 0)
+		spin_idle = 2 * lazy_idle;
+
+	/* Find southbridge */
+	pdev_sb = NULL;
+	while((pdev_sb = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev_sb)) != NULL) {
+		if(pci_match_device(amd_sb_tbl, pdev_sb) != NULL)
+			goto found_sb;
+	}
+	printk(KERN_ERR "amd76x_pm: Could not find southbridge\n");
+	return -ENODEV;
+
+ found_sb:
+
+	/* Find northbridge */
+	pdev_nb = NULL;
+	while((pdev_nb = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev_nb)) != NULL) {
+		if(pci_match_device(amd_nb_tbl, pdev_nb) != NULL)
+			goto found_nb;
+	}
+	printk(KERN_ERR "amd76x_pm: Could not find northbridge\n");
+	return -ENODEV;
+
+ found_nb:	
+	
+	/* Init southbridge */
+	switch (pdev_sb->device) {
+	case PCI_DEVICE_ID_AMD_VIPER_7413:	/* AMD-765 or 766 */
+		config_amd766(1);
+		break;
+	case PCI_DEVICE_ID_AMD_VIPER_7443:	/* AMD-768 */
+		config_amd768(1);
+		break;
+	default:
+		printk(KERN_ERR "amd76x_pm: No southbridge to initialize\n");		
+		break;
+	}
+
+	/* Init northbridge and queue the new idle function */
+	if(!pdev_nb) {
+		printk("amd76x_pm: No northbridge found.\n");
+		return -ENODEV;
+	}
+	switch (pdev_nb->device) {
+	case PCI_DEVICE_ID_AMD_FE_GATE_700C:	/* AMD-762 */
+		config_amd762(1);
+		amd76x_pm_cfg.curr_idle = amd76x_smp_idle;
+		break;
+	default:
+		printk(KERN_ERR "amd76x_pm: No northbridge to initialize\n");
+		break;
+	}
+
+	if(num_online_cpus() == 1) {
+		amd76x_pm_cfg.curr_idle = amd76x_up_idle;
+		printk(KERN_ERR "amd76x_pm: UP machine detected. ACPI is your friend.\n");
+	}
+	if (!amd76x_pm_cfg.curr_idle) {
+		printk(KERN_ERR "amd76x_pm: Idle function not changed\n");
+		return 1;
+	}
+
+	for (i = 0; i < NR_CPUS; i++) {
+		prs[i].idle_count = 0;
+		prs[i].C2_cnt = 0;
+	}
+
+	amd76x_pm_cfg.orig_idle = pm_idle;
+	pm_idle = amd76x_pm_cfg.curr_idle;
+
+	wmb();
+	
+	/* sysfs */
+	device_create_file(&pdev_nb->dev, &dev_attr_lazy_idle);
+	device_create_file(&pdev_nb->dev, &dev_attr_spin_idle);
+	device_create_file(&pdev_nb->dev, &dev_attr_C2_cnt);
+
+	return 0;
+}
+
+
+static int __init
+amd76x_pm_init(void)
+{
+	printk(KERN_INFO "amd76x_pm: Version %s\n", VERSION);
+	return amd76x_pm_main();
+}
+
+
+static void __exit
+amd76x_pm_cleanup(void)
+{
+	int i;
+	unsigned int C2_cnt = 0;
+	
+	pm_idle = amd76x_pm_cfg.orig_idle;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10))
+	cpu_idle_wait();
+#else
+	synchronize_kernel();
+#endif
+
+
+	/* This isn't really needed. */
+	for_each_online_cpu(i) {
+		C2_cnt += prs[i].C2_cnt;
+	}
+	printk(KERN_INFO "amd76x_pm: %u C2 calls\n", C2_cnt);
+	
+	/* remove sysfs */
+	device_remove_file(&pdev_nb->dev, &dev_attr_lazy_idle);
+	device_remove_file(&pdev_nb->dev, &dev_attr_spin_idle);
+	device_remove_file(&pdev_nb->dev, &dev_attr_C2_cnt);
+
+}
+
+
+MODULE_LICENSE("GPL");
+module_init(amd76x_pm_init);
+module_exit(amd76x_pm_cleanup);
diff -Nru linux-2.6.12/include/linux/amd76x_pm.h linux-2.6.12-jo3/include/linux/amd76x_pm.h
--- linux-2.6.12/include/linux/amd76x_pm.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.12-jo3/include/linux/amd76x_pm.h	2005-08-12 22:36:12.000000000 +0200
@@ -0,0 +1,59 @@
+/* 
+ * Begin 765/766
+ */
+/* C2/C3/POS options in C3A50, page 63 in AMD-766 doc */
+#define ZZ_CACHE_EN	1
+#define DCSTOP_EN	(1 << 1)
+#define STPCLK_EN	(1 << 2)
+#define CPUSTP_EN	(1 << 3)
+#define PCISTP_EN	(1 << 4)
+#define CPUSLP_EN	(1 << 5)
+#define SUSPND_EN	(1 << 6)
+#define CPURST_EN	(1 << 7)
+
+#define C2_REGS		0
+#define C3_REGS		8
+#define POS_REGS	16	
+/*
+ * End 765/766
+ */
+
+
+/*
+ * Begin 768
+ */
+/* C2/C3 options in DevB:3x4F, page 100 in AMD-768 doc */
+#define C2EN		1
+#define C3EN		(1 << 1)
+#define ZZ_C3EN		(1 << 2)
+#define CSLP_C3EN	(1 << 3)
+#define CSTP_C3EN	(1 << 4)
+
+/* POS options in DevB:3x50, page 101 in AMD-768 doc */
+#define POSEN	1
+#define CSTP	(1 << 2)
+#define PSTP	(1 << 3)
+#define ASTP	(1 << 4)
+#define DCSTP	(1 << 5)
+#define CSLP	(1 << 6)
+#define SUSP	(1 << 8)
+#define MSRSM	(1 << 14)
+#define PITRSM	(1 << 15)
+
+/* NTH options DevB:3x40, pg 93 of 768 doc */
+#define NTPER(x) (x << 3)
+#define THMINEN(x) (x << 4)
+
+/*
+ * End 768
+ */
+
+/* NTH activate. PM10, pg 110 of 768 doc, pg 70 of 766 doc */
+#define NTH_RATIO(x) (x << 1)
+#define NTH_EN (1 << 4)
+
+/* Sleep state. PM04, pg 109 of 768 doc, pg 69 of 766 doc */
+#define SLP_EN (1 << 13)
+#define SLP_TYP(x) (x << 10)
+
+#define LAZY_IDLE_DELAY	512	/* 0: Best savings,  3000: More responsive */
