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 <[EMAIL PROTECTED]>
+ *
+ * 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__ */
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to