Longhaul - Use hardware support
PATCH 1/1 Longhaul - Use hardware support
This patch depends on "Longhaul - There are limits". Minimal change necessary for hardware support.
Changes in longhaul.c:
- most important - now C3 state is causing transition,
- code resopnsible for clearing "bus master" bit removed,
- protect bcr2 transition in the same way as longhaul.
---
arch/i386/kernel/cpu/cpufreq/longhaul.c renamed from arch/i386/kernel/cpu/cpufreq/longhaul.c.orig +107 -85
@@ -29,11 +29,13 @@#include <linux/cpufreq.h> #include <linux/slab.h> #include <linux/string.h> -#include <linux/pci.h> #include <asm/msr.h> #include <asm/timex.h> #include <asm/io.h> +#include <asm/acpi.h> +#include <linux/acpi.h> +#include <acpi/processor.h> #include "longhaul.h"
@@ -56,6 +58,8 @@ static int minvid, maxvid;static unsigned int minmult, maxmult;static int can_scale_voltage;static int vrmrev; +static struct acpi_processor *pr =NULL ; +static struct acpi_processor_cx *cx =NULL ;/* Module parameters */ static int dont_scale_voltage;
@@ -118,84 +122,64 @@ static int longhaul_get_cpu_mult(void)return eblcr_table[invalue]; } +/* For processor with BCR2 MSR */ -static void do_powersaver (union msr_longhaul *longhaul, -unsigned int clock_ratio_index) +static void do_longhaul1 (int cx_address,unsigned int clock_ratio_index) { -struct pci_dev *dev; -unsigned long flags; -unsigned int tmp_mask; -int version; -int i; -u16 pci_cmd; -u16 cmd_state[64 ]; +union msr_bcr2 bcr2; +u32 t; -switch (cpu_model) { -case CPU_EZRA_T : - version =3 ; -break ; -case CPU_NEHEMIAH : - version =0xf ; -break ; -default : -return ; - } +rdmsrl (MSR_VIA_BCR2 , bcr2.val); +/* Enable software clock multiplier */ + bcr2.bits.ESOFTBF =1 ; + bcr2.bits.CLOCKMUL = clock_ratio_index; -rdmsrl (MSR_VIA_LONGHAUL , longhaul->val); - longhaul->bits.SoftBusRatio = clock_ratio_index &0xf ; - longhaul->bits.SoftBusRatio4 = (clock_ratio_index &0x10 ) >>4 ; - longhaul->bits.EnableSoftBusRatio =1 ; - longhaul->bits.RevisionKey =0 ; +/* Sync to timer tick */ +safe_halt (); +ACPI_FLUSH_CPU_CACHE (); +/* Change frequency on next halt or sleep */ +wrmsrl (MSR_VIA_BCR2 , bcr2.val); +/* Invoke C3 */ +inb (cx_address); +/* Dummy op - must do something useless after P_LVL3 read */ + t =inl (acpi_fadt.xpm_tmr_blk.address); -preempt_disable (); -local_irq_save (flags); +/* Disable software clock multiplier */ +local_irq_disable (); +rdmsrl (MSR_VIA_BCR2 , bcr2.val); + bcr2.bits.ESOFTBF =0 ; +wrmsrl (MSR_VIA_BCR2 , bcr2.val); +} -/* -* get current pci bus master state for all devices -* and clear bus master bit -*/ - dev =NULL ; - i =0 ; -do { - dev =pci_get_device (PCI_ANY_ID ,PCI_ANY_ID , dev); -if (dev !=NULL ) { -pci_read_config_word (dev,PCI_COMMAND , &pci_cmd); - cmd_state[i++] = pci_cmd; - pci_cmd &= ~PCI_COMMAND_MASTER ; -pci_write_config_word (dev,PCI_COMMAND , pci_cmd); - } - }while (dev !=NULL ); +/* For processor with Longhaul MSR */ - tmp_mask=inb (0x21 );/* works on C3. save mask. */ -outb (0xFE ,0x21 );/* TMR0 only */ -outb (0xFF ,0x80 );/* delay */ +static void do_powersaver (int cx_address,unsigned int clock_ratio_index) +{ +union msr_longhaul longhaul; +u32 t; + +rdmsrl (MSR_VIA_LONGHAUL , longhaul.val); + longhaul.bits.RevisionKey = longhaul.bits.RevisionID; + longhaul.bits.SoftBusRatio = clock_ratio_index &0xf ; + longhaul.bits.SoftBusRatio4 = (clock_ratio_index &0x10 ) >>4 ; +/* Sync to timer tick */ safe_halt (); -wrmsrl (MSR_VIA_LONGHAUL , longhaul->val); -halt (); +ACPI_FLUSH_CPU_CACHE (); +/* Change frequency on next halt or sleep */ +wrmsrl (MSR_VIA_LONGHAUL , longhaul.val); +/* Invoke C3 */ +inb (cx_address); +/* Dummy op - must do something useless after P_LVL3 read */ + t =inl (acpi_fadt.xpm_tmr_blk.address); +/* Disable bus ratio bit */ local_irq_disable (); - -outb (tmp_mask,0x21 );/* restore mask */ - -/* restore pci bus master state for all devices */ - dev =NULL ; - i =0 ; -do { - dev =pci_get_device (PCI_ANY_ID ,PCI_ANY_ID , dev); -if (dev !=NULL ) { - pci_cmd = cmd_state[i++]; -pci_write_config_byte (dev,PCI_COMMAND , pci_cmd); - } - }while (dev !=NULL ); -local_irq_restore (flags); -preempt_enable (); - -/* disable bus ratio bit */ -rdmsrl (MSR_VIA_LONGHAUL , longhaul->val); - longhaul->bits.EnableSoftBusRatio =0 ; - longhaul->bits.RevisionKey = version; -wrmsrl (MSR_VIA_LONGHAUL , longhaul->val); + longhaul.bits.RevisionKey = longhaul.bits.RevisionID; + longhaul.bits.EnableSoftBusRatio =0 ; + longhaul.bits.EnableSoftBSEL =0 ; + longhaul.bits.EnableSoftVID =0 ; +wrmsrl (MSR_VIA_LONGHAUL , longhaul.val); }/**
@@ -209,9 +193,9 @@ static void longhaul_setstate(unsigned i {int speed, mult;struct cpufreq_freqs freqs; -union msr_longhaul longhaul; -union msr_bcr2 bcr2;static unsigned int old_ratio=-1 ; +unsigned long flags; +unsigned int pic1_mask, pic2_mask;if (old_ratio == clock_ratio_index)return ;
@@ -234,6 +218,20 @@ static void longhaul_setstate(unsigned idprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n" , fsb, mult/10 , mult%10 ,print_speed (speed/1000 )); +preempt_disable (); +local_irq_save (flags); + + pic2_mask =inb (0xA1 ); + pic1_mask =inb (0x21 );/* works on C3. save mask. */ +outb (0xFF ,0xA1 );/* Overkill */ +outb (0xFE ,0x21 );/* TMR0 only */ + +/* Disable bus master arbitration */ +if (pr->flags.bm_check) { +acpi_set_register (ACPI_BITREG_ARB_DISABLE ,1 , +ACPI_MTX_DO_NOT_LOCK ); + } +switch (longhaul_version) {/*
@@ -245,20 +243,7 @@ static void longhaul_setstate(unsigned i*/ case TYPE_LONGHAUL_V1 :case TYPE_LONGHAUL_V2 : -rdmsrl (MSR_VIA_BCR2 , bcr2.val); -/* Enable software clock multiplier */ - bcr2.bits.ESOFTBF =1 ; - bcr2.bits.CLOCKMUL = clock_ratio_index; -local_irq_disable (); -wrmsrl (MSR_VIA_BCR2 , bcr2.val); -safe_halt (); - -/* Disable software clock multiplier */ -rdmsrl (MSR_VIA_BCR2 , bcr2.val); - bcr2.bits.ESOFTBF =0 ; -local_irq_disable (); -wrmsrl (MSR_VIA_BCR2 , bcr2.val); -local_irq_enable (); +do_longhaul1 (cx->address, clock_ratio_index);break ;/*
@@ -273,10 +258,22 @@ static void longhaul_setstate(unsigned i* to work in practice. */ case TYPE_POWERSAVER : -do_powersaver (&longhaul, clock_ratio_index); +do_powersaver (cx->address, clock_ratio_index);break ; } +/* Enable bus master arbitration */ +if (pr->flags.bm_check) { +acpi_set_register (ACPI_BITREG_ARB_DISABLE ,0 , +ACPI_MTX_DO_NOT_LOCK ); + } + +outb (pic2_mask,0xA1 );/* restore mask */ +outb (pic1_mask,0x21 ); + +local_irq_restore (flags); +preempt_enable (); +cpufreq_notify_transition (&freqs,CPUFREQ_POSTCHANGE ); }
@@ -527,6 +524,18 @@ static unsigned int longhaul_get(unsignereturn calc_speed (longhaul_get_cpu_mult ()); } +acpi_status longhaul_walk_callback (acpi_handle obj_handle, +u32 nesting_level, +void *context,void **return_value) +{ +struct acpi_device *d; + +if (acpi_bus_get_device (obj_handle, &d) ) { +return 0 ; + } + *return_value = (void *)acpi_driver_data (d); +return 1 ; +}static int __init longhaul_cpu_init (struct cpufreq_policy *policy) {
@@ -534,6 +543,15 @@ static int __init longhaul_cpu_init(struchar *cpuname=NULL ;int ret; +/* Check ACPI support for C3 state */ +acpi_walk_namespace (ACPI_TYPE_PROCESSOR ,ACPI_ROOT_OBJECT ,ACPI_UINT32_MAX , + &longhaul_walk_callback,NULL , (void *)&pr); +if (pr ==NULL ) goto err_acpi; + + cx = &pr->power.states[ACPI_STATE_C3 ]; +if (cx ==NULL || cx->latency >1000 ) goto err_acpi; + +/* Now check what we have on this motherboard */ switch (c->x86_model) {case 6 : cpu_model =CPU_SAMUEL ;
@@ -634,6 +652,10 @@ static int __init longhaul_cpu_init(strucpufreq_frequency_table_get_attr (longhaul_table, policy->cpu);return 0 ; + +err_acpi: + printk(KERN_ERR PFX "No ACPI support for CPU frequency changes.\n"); +return -ENODEV ; } static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy)
----------------------------------------------------------------------
PS. Fajny portal... >>> http://link.interia.pl/f196a
Dave Jones
AppliedQuoted 9 lines · Rafał Bilski
This patch depends on "Longhaul - There are limits". Minimal change necessary for hardware support.
Changes in
longhaul.c:
- most important - now C3 state is causing transition,
- code resopnsible for clearing "bus master" bit removed,
- protect bcr2 transition in the same way as longhaul.Signed-off-by Rafał Bilski <[email protected]>
applied, thanks.
Dave
Signature · 1 line
http://www.codemonkey.org.uk