diff -urN oldtree/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c newtree/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
--- oldtree/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c	2006-01-28 16:36:00.000000000 +0000
+++ newtree/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c	2006-01-28 17:14:59.617444096 +0000
@@ -486,6 +486,151 @@
 static inline int centrino_cpu_init_acpi(struct cpufreq_policy *policy) { return -ENODEV; }
 #endif
 
+static int centrino_target (struct cpufreq_policy *policy,
+			    unsigned int target_freq,
+			    unsigned int relation);
+
+/************************** sysfs interface for user defined voltage table ************************/
+static ssize_t show_user_voltage (struct cpufreq_policy *policy, char *buf)
+{
+	ssize_t       bytes_written = 0;
+	unsigned int  cpu          = policy->cpu;
+	unsigned int  op_index     = 0;
+	unsigned int  voltage      = 0;
+
+	//dprintk("showing user voltage table in sysfs\n");
+
+	while (centrino_model[cpu]->op_points[op_index].frequency != CPUFREQ_TABLE_END)
+	{
+		//dprintk("getting state %i \n", i);
+		voltage = centrino_model[cpu]->op_points[op_index].index;
+		voltage = 700 + ((voltage & 0xFF) << 4); 
+		//dprintk("writing voltage %i: %u mV \n", i, voltage);
+		bytes_written += snprintf (&buf[bytes_written],PAGE_SIZE, "%u",voltage);
+		op_index++;
+		if (centrino_model[cpu]->op_points[op_index].frequency != CPUFREQ_TABLE_END)
+			bytes_written += snprintf (&buf[bytes_written],PAGE_SIZE, ",");
+		else
+			bytes_written += snprintf (&buf[bytes_written],PAGE_SIZE, "\n");	
+	}
+	buf[PAGE_SIZE-1] = 0;
+	return bytes_written;
+}
+
+static ssize_t 
+store_user_voltage (struct cpufreq_policy *policy, const char *buf, size_t count) 
+{
+	unsigned int  cpu;
+	const char   *curr_buf;
+	unsigned int  curr_freq;
+	unsigned int  op_index;
+	int           i;
+	int           isok;
+	char         *next_buf;
+	unsigned int  op_point;
+	ssize_t       retval;
+	unsigned int  voltage;
+
+	static struct cpufreq_frequency_table **original_table = NULL;
+
+	if (!policy)
+	    return -ENODEV;
+	cpu = policy->cpu;
+	if (!centrino_model[cpu] || !centrino_model[cpu]->op_points)
+	    return -ENODEV;
+
+	if (!original_table) 
+	{
+		original_table = kmalloc(sizeof(struct cpufreq_frequency_table *)*NR_CPUS, GFP_KERNEL);
+		for (i=0; i < NR_CPUS; i++)
+		{
+			original_table[i] = NULL;
+		}
+	}
+
+	if (!original_table[cpu]) 
+	{
+		/* Count number of frequencies and allocate memory for a copy */
+		for (i=0; centrino_model[cpu]->op_points[i].frequency != CPUFREQ_TABLE_END; i++);
+		/* Allocate memory to store the copy */
+		original_table[cpu] = (struct cpufreq_frequency_table*) kmalloc(sizeof(struct cpufreq_frequency_table)*(i+1), GFP_KERNEL);
+		/* Make copy of frequency/voltage pairs */
+		for (i=0; centrino_model[cpu]->op_points[i].frequency != CPUFREQ_TABLE_END; i++) 
+		{
+			original_table[cpu][i].frequency = centrino_model[cpu]->op_points[i].frequency;
+			original_table[cpu][i].index = centrino_model[cpu]->op_points[i].index;
+		}
+		original_table[cpu][i].frequency = CPUFREQ_TABLE_END;
+	}
+
+	op_index = 0;
+	curr_buf = buf;
+	next_buf = NULL;
+	isok     = 1;
+	
+	while ((centrino_model[cpu]->op_points[op_index].frequency != CPUFREQ_TABLE_END) 
+		&& (isok))
+	{
+		voltage = simple_strtoul(curr_buf, &next_buf, 10);
+		if ((next_buf != curr_buf) && (next_buf != NULL))
+		{
+			if ((voltage >= 700) && (voltage<=1600))
+			{
+				voltage = ((voltage - 700) >> 4) & 0xFF;
+				op_point = (original_table[cpu])[op_index].index;
+				if (voltage <= (op_point & 0xFF))
+				{
+					//dprintk("setting control value %i to %04x\n", op_index, op_point);
+					op_point = (op_point & 0xFFFFFF00) | voltage;
+					centrino_model[cpu]->op_points[op_index].index = op_point;
+				}
+				else
+				{
+					op_point = (op_point & 0xFFFFFF00) | voltage;
+					dprintk("not setting control value %i to %04x because requested voltage is not lower than the default value\n", op_index, op_point);
+					//isok = 0;
+				}
+			}
+			else
+			{
+				dprintk("voltage value %i is out of bounds: %u mV\n", op_index, voltage);
+				isok = 0;
+			}
+			curr_buf = next_buf;
+			if (*curr_buf==',')
+				curr_buf++;
+			next_buf = NULL;
+		}
+		else
+		{
+			dprintk("failed to parse voltage value %i\n", op_index);
+			isok = 0;
+		}
+		op_index++;
+	}
+
+	if (isok)
+	{
+		retval = count;
+		curr_freq = cpufreq_get(policy->cpu);
+		centrino_target(policy, curr_freq, CPUFREQ_RELATION_L);
+	}
+	else
+	{
+		retval = -EINVAL;
+	}
+
+	return retval;
+}
+
+static struct freq_attr centrino_freq_attr_voltage_table = 
+{
+	.attr = { .name = "voltage_table", .mode = 0644, .owner = THIS_MODULE },
+	.show = show_user_voltage,
+	.store = store_user_voltage,
+};
+
+
 static int centrino_cpu_init(struct cpufreq_policy *policy)
 {
 	struct cpuinfo_x86 *cpu = &cpu_data[policy->cpu];
@@ -668,6 +813,7 @@
 
 static struct freq_attr* centrino_attr[] = {
 	&cpufreq_freq_attr_scaling_available_freqs,
+	&centrino_freq_attr_voltage_table,
 	NULL,
 };
 
