⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 speedstep-centrino.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * cpufreq driver for Enhanced SpeedStep, as found in Intel's Pentium * M (part of the Centrino chipset). * * Since the original Pentium M, most new Intel CPUs support Enhanced * SpeedStep. * * Despite the "SpeedStep" in the name, this is almost entirely unlike * traditional SpeedStep. * * Modelled on speedstep.c * * Copyright (C) 2003 Jeremy Fitzhardinge <jeremy@goop.org> */#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/cpufreq.h>#include <linux/sched.h>	/* current */#include <linux/delay.h>#include <linux/compiler.h>#include <asm/msr.h>#include <asm/processor.h>#include <asm/cpufeature.h>#define PFX		"speedstep-centrino: "#define MAINTAINER	"cpufreq@lists.linux.org.uk"#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "speedstep-centrino", msg)#define INTEL_MSR_RANGE	(0xffff)struct cpu_id{	__u8	x86;            /* CPU family */	__u8	x86_model;	/* model */	__u8	x86_mask;	/* stepping */};enum {	CPU_BANIAS,	CPU_DOTHAN_A1,	CPU_DOTHAN_A2,	CPU_DOTHAN_B0,	CPU_MP4HT_D0,	CPU_MP4HT_E0,};static const struct cpu_id cpu_ids[] = {	[CPU_BANIAS]	= { 6,  9, 5 },	[CPU_DOTHAN_A1]	= { 6, 13, 1 },	[CPU_DOTHAN_A2]	= { 6, 13, 2 },	[CPU_DOTHAN_B0]	= { 6, 13, 6 },	[CPU_MP4HT_D0]	= {15,  3, 4 },	[CPU_MP4HT_E0]	= {15,  4, 1 },};#define N_IDS	ARRAY_SIZE(cpu_ids)struct cpu_model{	const struct cpu_id *cpu_id;	const char	*model_name;	unsigned	max_freq; /* max clock in kHz */	struct cpufreq_frequency_table *op_points; /* clock/voltage pairs */};static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x);/* Operating points for current CPU */static struct cpu_model *centrino_model[NR_CPUS];static const struct cpu_id *centrino_cpu[NR_CPUS];static struct cpufreq_driver centrino_driver;#ifdef CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE/* Computes the correct form for IA32_PERF_CTL MSR for a particular   frequency/voltage operating point; frequency in MHz, volts in mV.   This is stored as "index" in the structure. */#define OP(mhz, mv)							\	{								\		.frequency = (mhz) * 1000,				\		.index = (((mhz)/100) << 8) | ((mv - 700) / 16)		\	}/* * These voltage tables were derived from the Intel Pentium M * datasheet, document 25261202.pdf, Table 5.  I have verified they * are consistent with my IBM ThinkPad X31, which has a 1.3GHz Pentium * M. *//* Ultra Low Voltage Intel Pentium M processor 900MHz (Banias) */static struct cpufreq_frequency_table banias_900[] ={	OP(600,  844),	OP(800,  988),	OP(900, 1004),	{ .frequency = CPUFREQ_TABLE_END }};/* Ultra Low Voltage Intel Pentium M processor 1000MHz (Banias) */static struct cpufreq_frequency_table banias_1000[] ={	OP(600,   844),	OP(800,   972),	OP(900,   988),	OP(1000, 1004),	{ .frequency = CPUFREQ_TABLE_END }};/* Low Voltage Intel Pentium M processor 1.10GHz (Banias) */static struct cpufreq_frequency_table banias_1100[] ={	OP( 600,  956),	OP( 800, 1020),	OP( 900, 1100),	OP(1000, 1164),	OP(1100, 1180),	{ .frequency = CPUFREQ_TABLE_END }};/* Low Voltage Intel Pentium M processor 1.20GHz (Banias) */static struct cpufreq_frequency_table banias_1200[] ={	OP( 600,  956),	OP( 800, 1004),	OP( 900, 1020),	OP(1000, 1100),	OP(1100, 1164),	OP(1200, 1180),	{ .frequency = CPUFREQ_TABLE_END }};/* Intel Pentium M processor 1.30GHz (Banias) */static struct cpufreq_frequency_table banias_1300[] ={	OP( 600,  956),	OP( 800, 1260),	OP(1000, 1292),	OP(1200, 1356),	OP(1300, 1388),	{ .frequency = CPUFREQ_TABLE_END }};/* Intel Pentium M processor 1.40GHz (Banias) */static struct cpufreq_frequency_table banias_1400[] ={	OP( 600,  956),	OP( 800, 1180),	OP(1000, 1308),	OP(1200, 1436),	OP(1400, 1484),	{ .frequency = CPUFREQ_TABLE_END }};/* Intel Pentium M processor 1.50GHz (Banias) */static struct cpufreq_frequency_table banias_1500[] ={	OP( 600,  956),	OP( 800, 1116),	OP(1000, 1228),	OP(1200, 1356),	OP(1400, 1452),	OP(1500, 1484),	{ .frequency = CPUFREQ_TABLE_END }};/* Intel Pentium M processor 1.60GHz (Banias) */static struct cpufreq_frequency_table banias_1600[] ={	OP( 600,  956),	OP( 800, 1036),	OP(1000, 1164),	OP(1200, 1276),	OP(1400, 1420),	OP(1600, 1484),	{ .frequency = CPUFREQ_TABLE_END }};/* Intel Pentium M processor 1.70GHz (Banias) */static struct cpufreq_frequency_table banias_1700[] ={	OP( 600,  956),	OP( 800, 1004),	OP(1000, 1116),	OP(1200, 1228),	OP(1400, 1308),	OP(1700, 1484),	{ .frequency = CPUFREQ_TABLE_END }};#undef OP#define _BANIAS(cpuid, max, name)	\{	.cpu_id		= cpuid,	\	.model_name	= "Intel(R) Pentium(R) M processor " name "MHz", \	.max_freq	= (max)*1000,	\	.op_points	= banias_##max,	\}#define BANIAS(max)	_BANIAS(&cpu_ids[CPU_BANIAS], max, #max)/* CPU models, their operating frequency range, and freq/voltage   operating points */static struct cpu_model models[] ={	_BANIAS(&cpu_ids[CPU_BANIAS], 900, " 900"),	BANIAS(1000),	BANIAS(1100),	BANIAS(1200),	BANIAS(1300),	BANIAS(1400),	BANIAS(1500),	BANIAS(1600),	BANIAS(1700),	/* NULL model_name is a wildcard */	{ &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL },	{ &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL },	{ &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL },	{ &cpu_ids[CPU_MP4HT_D0], NULL, 0, NULL },	{ &cpu_ids[CPU_MP4HT_E0], NULL, 0, NULL },	{ NULL, }};#undef _BANIAS#undef BANIASstatic int centrino_cpu_init_table(struct cpufreq_policy *policy){	struct cpuinfo_x86 *cpu = &cpu_data(policy->cpu);	struct cpu_model *model;	for(model = models; model->cpu_id != NULL; model++)		if (centrino_verify_cpu_id(cpu, model->cpu_id) &&		    (model->model_name == NULL ||		     strcmp(cpu->x86_model_id, model->model_name) == 0))			break;	if (model->cpu_id == NULL) {		/* No match at all */		dprintk("no support for CPU model \"%s\": "		       "send /proc/cpuinfo to " MAINTAINER "\n",		       cpu->x86_model_id);		return -ENOENT;	}	if (model->op_points == NULL) {		/* Matched a non-match */		dprintk("no table support for CPU model \"%s\"\n",		       cpu->x86_model_id);		dprintk("try using the acpi-cpufreq driver\n");		return -ENOENT;	}	centrino_model[policy->cpu] = model;	dprintk("found \"%s\": max frequency: %dkHz\n",	       model->model_name, model->max_freq);	return 0;}#elsestatic inline int centrino_cpu_init_table(struct cpufreq_policy *policy) { return -ENODEV; }#endif /* CONFIG_X86_SPEEDSTEP_CENTRINO_TABLE */static int centrino_verify_cpu_id(const struct cpuinfo_x86 *c, const struct cpu_id *x){	if ((c->x86 == x->x86) &&	    (c->x86_model == x->x86_model) &&	    (c->x86_mask == x->x86_mask))		return 1;	return 0;}/* To be called only after centrino_model is initialized */static unsigned extract_clock(unsigned msr, unsigned int cpu, int failsafe){	int i;	/*	 * Extract clock in kHz from PERF_CTL value	 * for centrino, as some DSDTs are buggy.	 * Ideally, this can be done using the acpi_data structure.	 */	if ((centrino_cpu[cpu] == &cpu_ids[CPU_BANIAS]) ||	    (centrino_cpu[cpu] == &cpu_ids[CPU_DOTHAN_A1]) ||	    (centrino_cpu[cpu] == &cpu_ids[CPU_DOTHAN_B0])) {		msr = (msr >> 8) & 0xff;		return msr * 100000;	}	if ((!centrino_model[cpu]) || (!centrino_model[cpu]->op_points))		return 0;	msr &= 0xffff;	for (i=0;centrino_model[cpu]->op_points[i].frequency != CPUFREQ_TABLE_END; i++) {		if (msr == centrino_model[cpu]->op_points[i].index)			return centrino_model[cpu]->op_points[i].frequency;	}	if (failsafe)		return centrino_model[cpu]->op_points[i-1].frequency;	else		return 0;}/* Return the current CPU frequency in kHz */static unsigned int get_cur_freq(unsigned int cpu){	unsigned l, h;	unsigned clock_freq;	cpumask_t saved_mask;	saved_mask = current->cpus_allowed;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -