mirror of
https://github.com/fail0verflow/switch-coreboot.git
synced 2025-05-04 01:39:18 -04:00
a smarter Late MTRR implementation
This commit is contained in:
parent
9b604b8ca7
commit
7f6e048fc0
3 changed files with 56 additions and 40 deletions
|
@ -35,24 +35,21 @@ static char rcsid[] = "$Id$";
|
||||||
|
|
||||||
#include <cpu/p6/msr.h>
|
#include <cpu/p6/msr.h>
|
||||||
#include <cpu/p6/mtrr.h>
|
#include <cpu/p6/mtrr.h>
|
||||||
|
#include <cpu/p6/l2_cache.h>
|
||||||
#include <cpu/p5/cpuid.h>
|
#include <cpu/p5/cpuid.h>
|
||||||
|
|
||||||
/* Include debugging code and outputs */
|
/* Include debugging code and outputs */
|
||||||
//#define DEBUG
|
//#define DEBUG
|
||||||
#include <printk.h>
|
#include <printk.h>
|
||||||
|
|
||||||
static int signal_l2(unsigned int address_high,
|
static int signal_l2(unsigned int address_high, unsigned int address_low,
|
||||||
unsigned int address_low,
|
unsigned int data_high, unsigned int data_low,
|
||||||
unsigned int data_high,
|
int way, int command);
|
||||||
unsigned int data_low, int way, int command);
|
|
||||||
static int read_l2(unsigned int address);
|
static int read_l2(unsigned int address);
|
||||||
static int write_l2(unsigned int address, int data);
|
static int write_l2(unsigned int address, int data);
|
||||||
static int write_l2_2(unsigned int address,
|
static int write_l2_2(unsigned int address, unsigned int data1, unsigned int data2);
|
||||||
unsigned int data1, unsigned int data2);
|
static int test_l2_address_alias(unsigned int address1, unsigned int address2,
|
||||||
static int test_l2_address_alias(unsigned int address1,
|
unsigned int data_high, unsigned int data_low);
|
||||||
unsigned int address2,
|
|
||||||
unsigned int data_high,
|
|
||||||
unsigned int data_low);
|
|
||||||
static int calculate_l2_latency(void);
|
static int calculate_l2_latency(void);
|
||||||
static int set_l2_register4(int l);
|
static int set_l2_register4(int l);
|
||||||
static int calculate_l2_cache_size(void);
|
static int calculate_l2_cache_size(void);
|
||||||
|
@ -65,6 +62,7 @@ static void cache_disable(void)
|
||||||
|
|
||||||
/* Disable cache */
|
/* Disable cache */
|
||||||
printk( KERN_INFO "Disable Cache\n");
|
printk( KERN_INFO "Disable Cache\n");
|
||||||
|
|
||||||
/* Write back the cache and flush TLB */
|
/* Write back the cache and flush TLB */
|
||||||
asm volatile ("movl %%cr0, %0\n\t"
|
asm volatile ("movl %%cr0, %0\n\t"
|
||||||
"orl $0x40000000, %0\n\t"
|
"orl $0x40000000, %0\n\t"
|
||||||
|
@ -82,6 +80,7 @@ static void cache_enable(void)
|
||||||
"andl $0x9fffffff, %0\n\t"
|
"andl $0x9fffffff, %0\n\t"
|
||||||
"movl %0, %%cr0\n\t"
|
"movl %0, %%cr0\n\t"
|
||||||
:"=r" (tmp) : : "memory");
|
:"=r" (tmp) : : "memory");
|
||||||
|
|
||||||
printk( KERN_INFO "Enable Cache\n");
|
printk( KERN_INFO "Enable Cache\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +117,7 @@ int intel_l2_configure()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read BBL_CR_CTL3 */
|
/* Read BBL_CR_CTL3 */
|
||||||
rdmsr(0x11e, eax, edx);
|
rdmsr(BBL_CR_CTL3, eax, edx);
|
||||||
/* If bit 23 (L2 Hardware disable) is set then done */
|
/* If bit 23 (L2 Hardware disable) is set then done */
|
||||||
if (eax & 0x800000) {
|
if (eax & 0x800000) {
|
||||||
DBG("L2 Hardware disabled\n");
|
DBG("L2 Hardware disabled\n");
|
||||||
|
@ -129,7 +128,7 @@ int intel_l2_configure()
|
||||||
/* 0x630 signature setup */
|
/* 0x630 signature setup */
|
||||||
|
|
||||||
/* Read EBL_CR_POWERON */
|
/* Read EBL_CR_POWERON */
|
||||||
rdmsr(0x2a, eax, edx);
|
rdmsr(EBL_CR_POWERON, eax, edx);
|
||||||
|
|
||||||
/* Mask out [22-24] Clock frequency ratio */
|
/* Mask out [22-24] Clock frequency ratio */
|
||||||
eax &= 0x1c00000;
|
eax &= 0x1c00000;
|
||||||
|
@ -141,7 +140,7 @@ int intel_l2_configure()
|
||||||
|
|
||||||
cache_disable();
|
cache_disable();
|
||||||
/* Read BBL_CR_CTL3 */
|
/* Read BBL_CR_CTL3 */
|
||||||
rdmsr(0x11e, eax, edx);
|
rdmsr(BBL_CR_CTL3, eax, edx);
|
||||||
/* Mask out:
|
/* Mask out:
|
||||||
* [0] L2 Configured
|
* [0] L2 Configured
|
||||||
* [5] ECC Check Enable
|
* [5] ECC Check Enable
|
||||||
|
@ -161,7 +160,7 @@ int intel_l2_configure()
|
||||||
*/
|
*/
|
||||||
eax |= 0x44000;
|
eax |= 0x44000;
|
||||||
/* Write BBL_CR_CTL3 */
|
/* Write BBL_CR_CTL3 */
|
||||||
wrmsr(0x11e, eax, edx);
|
wrmsr(BBL_CR_CTL3, eax, edx);
|
||||||
} else {
|
} else {
|
||||||
int calc_eax;
|
int calc_eax;
|
||||||
int v;
|
int v;
|
||||||
|
|
|
@ -31,6 +31,7 @@ static char rcsid[] = "$Id$";
|
||||||
|
|
||||||
#include <cpu/p6/msr.h>
|
#include <cpu/p6/msr.h>
|
||||||
#include <cpu/p6/mtrr.h>
|
#include <cpu/p6/mtrr.h>
|
||||||
|
#define DEBUG
|
||||||
#include <printk.h>
|
#include <printk.h>
|
||||||
|
|
||||||
#define arraysize(x) (sizeof(x)/sizeof((x)[0]))
|
#define arraysize(x) (sizeof(x)/sizeof((x)[0]))
|
||||||
|
@ -155,6 +156,23 @@ void intel_set_var_mtrr(unsigned int reg, unsigned long base, unsigned long size
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fms: find most sigificant bit set.
|
||||||
|
*
|
||||||
|
* stolen from Linux Kernel Source
|
||||||
|
*/
|
||||||
|
static __inline__ int fms(int x)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
__asm__("bsrl %1,%0\n\t"
|
||||||
|
"jnz 1f\n\t"
|
||||||
|
"movl $0,%0\n"
|
||||||
|
"1:" : "=r" (r) : "g" (x));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/* setting up variable and fixed mtrr
|
/* setting up variable and fixed mtrr
|
||||||
ToDo: 1. still need to find out how to set size and alignment correctly
|
ToDo: 1. still need to find out how to set size and alignment correctly
|
||||||
2. should we invalid cache by INVLD or WBINVD ?? */
|
2. should we invalid cache by INVLD or WBINVD ?? */
|
||||||
|
@ -162,33 +180,32 @@ void intel_set_var_mtrr(unsigned int reg, unsigned long base, unsigned long size
|
||||||
#ifdef ENABLE_FIXED_AND_VARIABLE_MTRRS
|
#ifdef ENABLE_FIXED_AND_VARIABLE_MTRRS
|
||||||
void intel_set_mtrr(unsigned long rambase, unsigned long ramsizeK)
|
void intel_set_mtrr(unsigned long rambase, unsigned long ramsizeK)
|
||||||
{
|
{
|
||||||
|
unsigned int reg = 0;
|
||||||
|
unsigned long range;
|
||||||
|
|
||||||
#ifdef SIS630
|
DBG("\n");
|
||||||
/* hardcoded for 128MB SDRAM, 4 MB SMA */
|
while (ramsizeK != 0 && reg <= 3) {
|
||||||
// change this 10/29/00 RGM
|
intel_post(0x60 + reg);
|
||||||
// set WRBACk to the size of ram, and SMA to the last 4M
|
|
||||||
// This works because Ollie fixed Dram setup with SPD
|
|
||||||
// coming in, from sis sizeram, the size is size of ram -
|
|
||||||
// 256M. We should probably change the way this is done.
|
|
||||||
// For now, take ramsizeK, add 4M, that's it.
|
|
||||||
// you have to round up the ramsize because MTRRs
|
|
||||||
// have to be on a power of two boundary.
|
|
||||||
// BUT: UC and WB types are allowed to overlap.
|
|
||||||
// so there is no problem with letting MTRR 0 overlap MTRR 1
|
|
||||||
printk(KERN_INFO "set_mtrr: rambase is 0x%x, ramsizeK is 0x%x\n",
|
|
||||||
rambase, ramsizeK);
|
|
||||||
|
|
||||||
printk(KERN_INFO "setting MTRR 0 size to 0x%x\n",
|
range = 1 << fms(ramsizeK);
|
||||||
(ramsizeK + 4096) * 1024);
|
DBG("Setting variable MTRR %d, base: %dMB, range: %dMB, type: WB\n",
|
||||||
intel_set_var_mtrr(0, 0, (ramsizeK + 4096) * 1024, MTRR_TYPE_WRBACK);
|
reg, rambase >> 10, range >> 10);
|
||||||
intel_set_var_mtrr(1, (ramsizeK * 1024),
|
|
||||||
4096 * 1024, MTRR_TYPE_UNCACHABLE);
|
|
||||||
printk(KERN_INFO "MTRRs set\n");
|
|
||||||
|
|
||||||
#else /* SIS630 */
|
intel_set_var_mtrr(reg, rambase * 1024, range * 1024, MTRR_TYPE_WRBACK);
|
||||||
printk("Setting variable MTRR 0 to %dK\n", ramsizeK);
|
|
||||||
intel_set_var_mtrr(0, 0, ramsizeK * 1024, MTRR_TYPE_WRBACK);
|
rambase += range;
|
||||||
#endif /* SIS630 */
|
ramsizeK -= range;
|
||||||
|
reg++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The "remainder" of the memory ranges. FixMe: should we secrify this range or set it
|
||||||
|
as WB and trust Linux Kernel (or Intel CPU ?? ) */
|
||||||
|
if (ramsizeK != 0) {
|
||||||
|
range = 1 << (fms(ramsizeK) + 1);
|
||||||
|
DBG("Setting variable MTRR %d, base: %dMB, range: %dMB, type: UC\n",
|
||||||
|
reg, rambase >> 10, range >> 10);
|
||||||
|
intel_set_var_mtrr(reg, rambase * 1024, range * 1024, MTRR_TYPE_UNCACHABLE);
|
||||||
|
}
|
||||||
|
|
||||||
intel_set_fixed_mtrr();
|
intel_set_fixed_mtrr();
|
||||||
|
|
||||||
|
@ -201,7 +218,7 @@ void intel_set_mtrr(unsigned long rambase, unsigned long ramsizeK)
|
||||||
{
|
{
|
||||||
intel_set_var_mtrr(0, 0, ramsizeK * 1024, MTRR_TYPE_WRBACK);
|
intel_set_var_mtrr(0, 0, ramsizeK * 1024, MTRR_TYPE_WRBACK);
|
||||||
intel_enable_var_mtrr();
|
intel_enable_var_mtrr();
|
||||||
// intel_set_fixed_mtrr();
|
//intel_set_fixed_mtrr();
|
||||||
}
|
}
|
||||||
#endif /* ENABLE_FIXED_AND_VARIABLE_MTRRS */
|
#endif /* ENABLE_FIXED_AND_VARIABLE_MTRRS */
|
||||||
#endif /* INTEL_PPRO_MTRR */
|
#endif /* INTEL_PPRO_MTRR */
|
||||||
|
|
|
@ -142,7 +142,7 @@ void intel_cache_on(unsigned long base, unsigned long totalram)
|
||||||
// set_mtrr is responsible for getting it into the right units!
|
// set_mtrr is responsible for getting it into the right units!
|
||||||
intel_set_mtrr(base, totalram);
|
intel_set_mtrr(base, totalram);
|
||||||
#endif
|
#endif
|
||||||
intel_post(0x62);
|
intel_post(0x6A);
|
||||||
}
|
}
|
||||||
|
|
||||||
void intel_interrupts_on()
|
void intel_interrupts_on()
|
||||||
|
|
Loading…
Add table
Reference in a new issue