[linux-pm] PowerOP 2/3: Intel Centrino support

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

 



Minimal PowerOP support for Intel Enhanced Speedstep "Centrino"
notebooks.  These systems run at an operating point comprised of a cpu
frequency and a core voltage.  The voltage could be set from the values
recommended in the datasheets if left unspecified (-1) in the operating
point, as cpufreq does.


Index: linux-2.6.12/arch/i386/Kconfig
===================================================================
--- linux-2.6.12.orig/arch/i386/Kconfig	2005-08-02 23:39:05.000000000 +0000
+++ linux-2.6.12/arch/i386/Kconfig	2005-08-03 01:11:21.000000000 +0000
@@ -1098,6 +1098,7 @@
 endmenu
 
 source "arch/i386/kernel/cpu/cpufreq/Kconfig"
+source "arch/i386/kernel/cpu/powerop/Kconfig"
 
 endmenu
 
Index: linux-2.6.12/arch/i386/kernel/cpu/Makefile
===================================================================
--- linux-2.6.12.orig/arch/i386/kernel/cpu/Makefile	2005-08-02 23:39:05.000000000 +0000
+++ linux-2.6.12/arch/i386/kernel/cpu/Makefile	2005-08-03 01:11:21.000000000 +0000
@@ -17,3 +17,4 @@
 
 obj-$(CONFIG_MTRR)	+= 	mtrr/
 obj-$(CONFIG_CPU_FREQ)	+=	cpufreq/
+obj-$(CONFIG_POWEROP)	+=	powerop/
Index: linux-2.6.12/arch/i386/kernel/cpu/powerop/Kconfig
===================================================================
--- linux-2.6.12.orig/arch/i386/kernel/cpu/powerop/Kconfig	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.12/arch/i386/kernel/cpu/powerop/Kconfig	2005-08-03 01:11:21.000000000 +0000
@@ -0,0 +1,6 @@
+source "drivers/powerop/Kconfig"
+
+config POWEROP_CENTRINO
+       tristate "PowerOP for Intel Centrino Enhanced Speedstep"
+       depends on POWEROP
+       default n
Index: linux-2.6.12/arch/i386/kernel/cpu/powerop/Makefile
===================================================================
--- linux-2.6.12.orig/arch/i386/kernel/cpu/powerop/Makefile	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.12/arch/i386/kernel/cpu/powerop/Makefile	2005-08-03 01:11:21.000000000 +0000
@@ -0,0 +1,2 @@
+obj-$(CONFIG_POWEROP_CENTRINO)	+=	powerop-centrino.o
+
Index: linux-2.6.12/arch/i386/kernel/cpu/powerop/powerop-centrino.c
===================================================================
--- linux-2.6.12.orig/arch/i386/kernel/cpu/powerop/powerop-centrino.c	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.12/arch/i386/kernel/cpu/powerop/powerop-centrino.c	2005-08-03 06:41:37.000000000 +0000
@@ -0,0 +1,160 @@
+/*
+ * PowerOP support for Intel Enhanced Speedstep "Centrino" platforms.
+ *
+ * Based heavily on speedstep-centrino.c of cpufreq Copyright (c) 2003
+ * by Jeremy Fitzhardinge <jeremy@xxxxxxxx>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/powerop.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/slab.h>
+
+#include <asm/msr.h>
+#include <asm/processor.h>
+#include <asm/cpufeature.h>
+
+static int
+powerop_centrino_get_point(struct powerop_point *point)
+{
+	unsigned l, h;
+	unsigned cpu_freq;
+
+	rdmsr(MSR_IA32_PERF_STATUS, l, h);
+	if (unlikely((cpu_freq = ((l >> 8) & 0xff) * 100) == 0)) {
+		/*
+		 * On some CPUs, we can see transient MSR values (which are
+		 * not present in _PSS), while CPU is doing some automatic
+		 * P-state transition (like TM2). Get the last freq set 
+		 * in PERF_CTL.
+		 */
+		rdmsr(MSR_IA32_PERF_CTL, l, h);
+		cpu_freq = ((l >> 8) & 0xff) * 100;
+	}
+
+	point->param[POWEROP_CPU + smp_processor_id()] = cpu_freq;
+	point->param[POWEROP_V + smp_processor_id()] = ((l & 0xff) * 16) + 700;
+	return 0;
+}
+
+static int
+powerop_centrino_set_point(struct powerop_point *point)
+{
+	unsigned int msr = 0, oldmsr, h, mask = 0;
+
+	if (point->param[POWEROP_CPU + smp_processor_id()] != -1) {
+		msr |= (point->param[POWEROP_CPU + smp_processor_id()]/100)
+			<< 8;
+		mask |= 0xff00;
+	}
+
+	if (point->param[POWEROP_V + smp_processor_id()] != -1) {
+		msr |= ((point->param[POWEROP_V + smp_processor_id()] - 700)
+			/ 16);
+		mask |= 0xff;
+	}
+
+	rdmsr(MSR_IA32_PERF_CTL, oldmsr, h);
+
+	if (msr == (oldmsr & mask))
+		return 0;
+
+	/* all but 16 LSB are "reserved", so treat them with
+	   care */
+	oldmsr &= ~mask;
+	msr &= mask;
+	oldmsr |= msr;
+	
+	wrmsr(MSR_IA32_PERF_CTL, oldmsr, h);
+	return 0;
+}
+
+#ifdef CONFIG_POWEROP_SYSFS
+static char *powerop_param_names[POWEROP_DRIVER_MAX_PARAMS];
+
+static int __init powerop_centrino_sysfs_init(void)
+{
+	int i;
+
+	for (i = 0; i < NR_CPUS; i++) {
+		if (! (powerop_param_names[POWEROP_CPU + i] = 
+		       kmalloc(5 + i / 10, GFP_KERNEL)) ||
+		    ! (powerop_param_names[POWEROP_V + i] = 
+		       kmalloc(3 + i / 10, GFP_KERNEL)))
+			goto nomem;
+
+		sprintf(powerop_param_names[POWEROP_CPU + i], "cpu%d", i);
+		sprintf(powerop_param_names[POWEROP_V + i], "v%d", i);
+	}
+
+	return 0;
+
+nomem:
+	printk(KERN_ERR "power-centrino malloc failed\n");
+
+	for (i = 0; i < NR_CPUS; i++) {
+		kfree(powerop_param_names[POWEROP_CPU + i]);
+		kfree(powerop_param_names[POWEROP_V + i]);
+	}
+
+	return -ENOMEM;
+}
+#else
+static int __init powerop_centrino_sysfs_init(void)
+{
+	return 0;
+}
+#endif
+
+static struct powerop_driver power_driver_centrino = {
+	.name		= "centrino",
+	.nr_params	= POWEROP_DRIVER_MAX_PARAMS,
+#ifdef CONFIG_POWEROP_SYSFS
+	.param_names    = powerop_param_names,
+#endif
+	.get_point	= powerop_centrino_get_point,
+	.set_point	= powerop_centrino_set_point,
+};
+
+static int __init powerop_centrino_init(void)
+{
+	struct cpuinfo_x86 *cpu = cpu_data;
+	unsigned l, h;
+
+	if (!cpu_has(cpu, X86_FEATURE_EST))
+		return -ENODEV;
+
+	/* Check to see if Enhanced SpeedStep is enabled, and try to
+	   enable it if not. */
+	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
+		
+	if (!(l & (1<<16))) {
+		l |= (1<<16);
+		wrmsr(MSR_IA32_MISC_ENABLE, l, h);
+		
+		/* check to see if it stuck */
+		rdmsr(MSR_IA32_MISC_ENABLE, l, h);
+		if (!(l & (1<<16))) {
+			printk(KERN_INFO "PowerOP: Couldn't enable Enhanced SpeedStep\n");
+			return -ENODEV;
+		}
+	}
+	
+	return powerop_centrino_sysfs_init() || 
+		powerop_driver_register(&power_driver_centrino);
+}
+
+static void __exit powerop_centrino_exit(void)
+{
+	powerop_driver_unregister(&power_driver_centrino);
+}
+
+module_init(powerop_centrino_init);
+module_exit(powerop_centrino_exit);
Index: linux-2.6.12/include/asm-i386/powerop-centrino.h
===================================================================
--- linux-2.6.12.orig/include/asm-i386/powerop-centrino.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.12/include/asm-i386/powerop-centrino.h	2005-08-03 01:24:16.000000000 +0000
@@ -0,0 +1,20 @@
+/*
+ * PowerOP support for Intel Enhanced Speedstep "Centrino" platforms.
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __ASM_POWEROP_CENTRINO_H__
+#define __ASM_POWEROP_CENTRINO_H__
+
+#include <linux/threads.h>
+
+#define POWEROP_CPU		0	/* CPU freq in MHz*/
+#define POWEROP_V		NR_CPUS /* core voltage */
+
+#define POWEROP_DRIVER_MAX_PARAMS	2*NR_CPUS	/* max # params */
+
+#endif /* __ASM_POWEROP_CENTRINO_H__ */
Index: linux-2.6.12/include/asm-i386/powerop.h
===================================================================
--- linux-2.6.12.orig/include/asm-i386/powerop.h	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.12/include/asm-i386/powerop.h	2005-08-03 01:23:03.000000000 +0000
@@ -0,0 +1,19 @@
+/*
+ * PowerOP support for i386 platforms.
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#ifndef __ASM_POWEROP_H__
+#define __ASM_POWEROP_H__
+
+#include <linux/config.h>
+
+#ifdef CONFIG_POWEROP_CENTRINO
+#include <asm/powerop-centrino.h>
+#endif
+
+#endif /* __ASM_POWEROP_H__ */

[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux