Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 59204
b: refs/heads/master
c: 73e107d
h: refs/heads/master
v: v3
  • Loading branch information
Rafał Bilski authored and Dave Jones committed May 29, 2007
1 parent 6bc3abf commit 65f520c
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 50 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 13424f6514f6444554a103362dd9d31eabbbdc54
refs/heads/master: 73e107d4a156affeed510cf5745177fd893878f1
145 changes: 96 additions & 49 deletions trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/delay.h>

#include <asm/msr.h>
#include <asm/timex.h>
Expand Down Expand Up @@ -62,19 +63,14 @@ static unsigned int fsb;

static const struct mV_pos *vrm_mV_table;
static const unsigned char *mV_vrm_table;
struct f_msr {
u8 vrm;
u8 pos;
};
static struct f_msr f_msr_table[32];

static unsigned int highest_speed, lowest_speed; /* kHz */
static unsigned int minmult, maxmult;
static int can_scale_voltage;
static struct acpi_processor *pr = NULL;
static struct acpi_processor_cx *cx = NULL;
static u8 longhaul_flags;
static u8 longhaul_pos;
static unsigned int longhaul_index;

/* Module parameters */
static int scale_voltage;
Expand All @@ -87,7 +83,6 @@ static int clock_ratio[32];
static int eblcr_table[32];
static int longhaul_version;
static struct cpufreq_frequency_table *longhaul_table;
static unsigned int old_ratio = -1;

#ifdef CONFIG_CPU_FREQ_DEBUG
static char speedbuffer[8];
Expand Down Expand Up @@ -144,7 +139,7 @@ static void do_longhaul1(unsigned int clock_ratio_index)
rdmsrl(MSR_VIA_BCR2, bcr2.val);
/* Enable software clock multiplier */
bcr2.bits.ESOFTBF = 1;
bcr2.bits.CLOCKMUL = clock_ratio_index;
bcr2.bits.CLOCKMUL = clock_ratio_index & 0xff;

/* Sync to timer tick */
safe_halt();
Expand All @@ -163,26 +158,24 @@ static void do_longhaul1(unsigned int clock_ratio_index)

/* For processor with Longhaul MSR */

static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
static void do_powersaver(int cx_address, unsigned int clock_ratio_index,
unsigned int dir)
{
union msr_longhaul longhaul;
u8 dest_pos;
u32 t;

dest_pos = f_msr_table[clock_ratio_index].pos;

rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
/* Setup new frequency */
longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
/* Setup new voltage */
if (can_scale_voltage)
longhaul.bits.SoftVID = f_msr_table[clock_ratio_index].vrm;
longhaul.bits.SoftVID = (clock_ratio_index >> 8) & 0x1f;
/* Sync to timer tick */
safe_halt();
/* Raise voltage if necessary */
if (can_scale_voltage && longhaul_pos < dest_pos) {
if (can_scale_voltage && dir) {
longhaul.bits.EnableSoftVID = 1;
wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
/* Change voltage */
Expand All @@ -199,7 +192,6 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
}
longhaul.bits.EnableSoftVID = 0;
wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
longhaul_pos = dest_pos;
}

/* Change frequency on next halt or sleep */
Expand All @@ -220,7 +212,7 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);

/* Reduce voltage if necessary */
if (can_scale_voltage && longhaul_pos > dest_pos) {
if (can_scale_voltage && !dir) {
longhaul.bits.EnableSoftVID = 1;
wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
/* Change voltage */
Expand All @@ -237,7 +229,6 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
}
longhaul.bits.EnableSoftVID = 0;
wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
longhaul_pos = dest_pos;
}
}

Expand All @@ -248,26 +239,28 @@ static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
* Sets a new clock ratio.
*/

static void longhaul_setstate(unsigned int clock_ratio_index)
static void longhaul_setstate(unsigned int table_index)
{
unsigned int clock_ratio_index;
int speed, mult;
struct cpufreq_freqs freqs;
unsigned long flags;
unsigned int pic1_mask, pic2_mask;
u32 bm_status = 0;
u32 bm_timeout = 100000;
unsigned int dir = 0;

if (old_ratio == clock_ratio_index)
return;
old_ratio = clock_ratio_index;

mult = clock_ratio[clock_ratio_index];
clock_ratio_index = longhaul_table[table_index].index;
/* Safety precautions */
mult = clock_ratio[clock_ratio_index & 0x1f];
if (mult == -1)
return;

speed = calc_speed(mult);
if ((speed > highest_speed) || (speed < lowest_speed))
return;
/* Voltage transition before frequency transition? */
if (can_scale_voltage && longhaul_index < table_index)
dir = 1;

freqs.old = calc_speed(longhaul_get_cpu_mult());
freqs.new = speed;
Expand Down Expand Up @@ -302,7 +295,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
/* Disable AGP and PCI arbiters */
outb(3, 0x22);
} else if ((pr != NULL) && pr->flags.bm_control) {
/* Disable bus master arbitration */
/* Disable bus master arbitration */
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1);
}
switch (longhaul_version) {
Expand All @@ -327,9 +320,9 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
if (longhaul_flags & USE_ACPI_C3) {
/* Don't allow wakeup */
acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
do_powersaver(cx->address, clock_ratio_index);
do_powersaver(cx->address, clock_ratio_index, dir);
} else {
do_powersaver(0, clock_ratio_index);
do_powersaver(0, clock_ratio_index, dir);
}
break;
}
Expand Down Expand Up @@ -386,7 +379,8 @@ static int guess_fsb(int mult)

static int __init longhaul_get_ranges(void)
{
unsigned int j, k = 0;
unsigned int i, j, k = 0;
unsigned int ratio;
int mult;

/* Get current frequency */
Expand Down Expand Up @@ -440,8 +434,7 @@ static int __init longhaul_get_ranges(void)
if(!longhaul_table)
return -ENOMEM;

for (j=0; j < numscales; j++) {
unsigned int ratio;
for (j = 0; j < numscales; j++) {
ratio = clock_ratio[j];
if (ratio == -1)
continue;
Expand All @@ -451,21 +444,49 @@ static int __init longhaul_get_ranges(void)
longhaul_table[k].index = j;
k++;
}
if (k <= 1) {
kfree(longhaul_table);
return -ENODEV;
}
/* Sort */
for (j = 0; j < k - 1; j++) {
unsigned int min_f, min_i;
min_f = longhaul_table[j].frequency;
min_i = j;
for (i = j + 1; i < k; i++) {
if (longhaul_table[i].frequency < min_f) {
min_f = longhaul_table[i].frequency;
min_i = i;
}
}
if (min_i != j) {
unsigned int temp;
temp = longhaul_table[j].frequency;
longhaul_table[j].frequency = longhaul_table[min_i].frequency;
longhaul_table[min_i].frequency = temp;
temp = longhaul_table[j].index;
longhaul_table[j].index = longhaul_table[min_i].index;
longhaul_table[min_i].index = temp;
}
}

longhaul_table[k].frequency = CPUFREQ_TABLE_END;
if (!k) {
kfree (longhaul_table);
return -EINVAL;
}

/* Find index we are running on */
for (j = 0; j < k; j++) {
if (clock_ratio[longhaul_table[j].index & 0x1f] == mult) {
longhaul_index = j;
break;
}
}
return 0;
}


static void __init longhaul_setup_voltagescaling(void)
{
union msr_longhaul longhaul;
struct mV_pos minvid, maxvid;
struct mV_pos minvid, maxvid, vid;
unsigned int j, speed, pos, kHz_step, numvscales;
int min_vid_speed;

Expand All @@ -476,11 +497,11 @@ static void __init longhaul_setup_voltagescaling(void)
}

if (!longhaul.bits.VRMRev) {
printk (KERN_INFO PFX "VRM 8.5\n");
printk(KERN_INFO PFX "VRM 8.5\n");
vrm_mV_table = &vrm85_mV[0];
mV_vrm_table = &mV_vrm85[0];
} else {
printk (KERN_INFO PFX "Mobile VRM\n");
printk(KERN_INFO PFX "Mobile VRM\n");
if (cpu_model < CPU_NEHEMIAH)
return;
vrm_mV_table = &mobilevrm_mV[0];
Expand Down Expand Up @@ -540,23 +561,21 @@ static void __init longhaul_setup_voltagescaling(void)
/* Calculate kHz for one voltage step */
kHz_step = (highest_speed - min_vid_speed) / numvscales;


j = 0;
while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) {
speed = longhaul_table[j].frequency;
if (speed > min_vid_speed)
pos = (speed - min_vid_speed) / kHz_step + minvid.pos;
else
pos = minvid.pos;
f_msr_table[longhaul_table[j].index].vrm = mV_vrm_table[pos];
f_msr_table[longhaul_table[j].index].pos = pos;
longhaul_table[j].index |= mV_vrm_table[pos] << 8;
vid = vrm_mV_table[mV_vrm_table[pos]];
printk(KERN_INFO PFX "f: %d kHz, index: %d, vid: %d mV\n", speed, j, vid.mV);
j++;
}

longhaul_pos = maxvid.pos;
can_scale_voltage = 1;
printk(KERN_INFO PFX "Voltage scaling enabled. "
"Use of \"conservative\" governor is highly recommended.\n");
printk(KERN_INFO PFX "Voltage scaling enabled.\n");
}


Expand All @@ -570,15 +589,44 @@ static int longhaul_target(struct cpufreq_policy *policy,
unsigned int target_freq, unsigned int relation)
{
unsigned int table_index = 0;
unsigned int new_clock_ratio = 0;
unsigned int i;
unsigned int dir = 0;
u8 vid, current_vid;

if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, relation, &table_index))
return -EINVAL;

new_clock_ratio = longhaul_table[table_index].index & 0xFF;

longhaul_setstate(new_clock_ratio);
/* Don't set same frequency again */
if (longhaul_index == table_index)
return 0;

if (!can_scale_voltage)
longhaul_setstate(table_index);
else {
/* On test system voltage transitions exceeding single
* step up or down were turning motherboard off. Both
* "ondemand" and "userspace" are unsafe. C7 is doing
* this in hardware, C3 is old and we need to do this
* in software. */
i = longhaul_index;
current_vid = (longhaul_table[longhaul_index].index >> 8) & 0x1f;
if (table_index > longhaul_index)
dir = 1;
while (i != table_index) {
vid = (longhaul_table[i].index >> 8) & 0x1f;
if (vid != current_vid) {
longhaul_setstate(i);
current_vid = vid;
msleep(200);
}
if (dir)
i++;
else
i--;
}
longhaul_setstate(table_index);
}
longhaul_index = table_index;
return 0;
}

Expand Down Expand Up @@ -607,11 +655,10 @@ static acpi_status longhaul_walk_callback(acpi_handle obj_handle,
static int enable_arbiter_disable(void)
{
struct pci_dev *dev;
int status;
int status = 1;
int reg;
u8 pci_cmd;

status = 1;
/* Find PLE133 host bridge */
reg = 0x78;
dev = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0,
Expand Down

0 comments on commit 65f520c

Please sign in to comment.