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/mtrr.h>
|
||||
#include <cpu/p6/l2_cache.h>
|
||||
#include <cpu/p5/cpuid.h>
|
||||
|
||||
/* Include debugging code and outputs */
|
||||
//#define DEBUG
|
||||
#include <printk.h>
|
||||
|
||||
static int signal_l2(unsigned int address_high,
|
||||
unsigned int address_low,
|
||||
unsigned int data_high,
|
||||
unsigned int data_low, int way, int command);
|
||||
static int signal_l2(unsigned int address_high, unsigned int address_low,
|
||||
unsigned int data_high, unsigned int data_low,
|
||||
int way, int command);
|
||||
static int read_l2(unsigned int address);
|
||||
static int write_l2(unsigned int address, int data);
|
||||
static int write_l2_2(unsigned int address,
|
||||
unsigned int data1, unsigned int data2);
|
||||
static int test_l2_address_alias(unsigned int address1,
|
||||
unsigned int address2,
|
||||
unsigned int data_high,
|
||||
unsigned int data_low);
|
||||
static int write_l2_2(unsigned int address, unsigned int data1, unsigned int data2);
|
||||
static int test_l2_address_alias(unsigned int address1, unsigned int address2,
|
||||
unsigned int data_high, unsigned int data_low);
|
||||
static int calculate_l2_latency(void);
|
||||
static int set_l2_register4(int l);
|
||||
static int calculate_l2_cache_size(void);
|
||||
|
@ -65,6 +62,7 @@ static void cache_disable(void)
|
|||
|
||||
/* Disable cache */
|
||||
printk( KERN_INFO "Disable Cache\n");
|
||||
|
||||
/* Write back the cache and flush TLB */
|
||||
asm volatile ("movl %%cr0, %0\n\t"
|
||||
"orl $0x40000000, %0\n\t"
|
||||
|
@ -82,6 +80,7 @@ static void cache_enable(void)
|
|||
"andl $0x9fffffff, %0\n\t"
|
||||
"movl %0, %%cr0\n\t"
|
||||
:"=r" (tmp) : : "memory");
|
||||
|
||||
printk( KERN_INFO "Enable Cache\n");
|
||||
}
|
||||
|
||||
|
@ -118,7 +117,7 @@ int intel_l2_configure()
|
|||
}
|
||||
|
||||
/* 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 (eax & 0x800000) {
|
||||
DBG("L2 Hardware disabled\n");
|
||||
|
@ -129,7 +128,7 @@ int intel_l2_configure()
|
|||
/* 0x630 signature setup */
|
||||
|
||||
/* Read EBL_CR_POWERON */
|
||||
rdmsr(0x2a, eax, edx);
|
||||
rdmsr(EBL_CR_POWERON, eax, edx);
|
||||
|
||||
/* Mask out [22-24] Clock frequency ratio */
|
||||
eax &= 0x1c00000;
|
||||
|
@ -141,7 +140,7 @@ int intel_l2_configure()
|
|||
|
||||
cache_disable();
|
||||
/* Read BBL_CR_CTL3 */
|
||||
rdmsr(0x11e, eax, edx);
|
||||
rdmsr(BBL_CR_CTL3, eax, edx);
|
||||
/* Mask out:
|
||||
* [0] L2 Configured
|
||||
* [5] ECC Check Enable
|
||||
|
@ -161,7 +160,7 @@ int intel_l2_configure()
|
|||
*/
|
||||
eax |= 0x44000;
|
||||
/* Write BBL_CR_CTL3 */
|
||||
wrmsr(0x11e, eax, edx);
|
||||
wrmsr(BBL_CR_CTL3, eax, edx);
|
||||
} else {
|
||||
int calc_eax;
|
||||
int v;
|
||||
|
|
|
@ -31,6 +31,7 @@ static char rcsid[] = "$Id$";
|
|||
|
||||
#include <cpu/p6/msr.h>
|
||||
#include <cpu/p6/mtrr.h>
|
||||
#define DEBUG
|
||||
#include <printk.h>
|
||||
|
||||
#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
|
||||
ToDo: 1. still need to find out how to set size and alignment correctly
|
||||
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
|
||||
void intel_set_mtrr(unsigned long rambase, unsigned long ramsizeK)
|
||||
{
|
||||
unsigned int reg = 0;
|
||||
unsigned long range;
|
||||
|
||||
#ifdef SIS630
|
||||
/* hardcoded for 128MB SDRAM, 4 MB SMA */
|
||||
// change this 10/29/00 RGM
|
||||
// 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);
|
||||
DBG("\n");
|
||||
while (ramsizeK != 0 && reg <= 3) {
|
||||
intel_post(0x60 + reg);
|
||||
|
||||
printk(KERN_INFO "setting MTRR 0 size to 0x%x\n",
|
||||
(ramsizeK + 4096) * 1024);
|
||||
intel_set_var_mtrr(0, 0, (ramsizeK + 4096) * 1024, MTRR_TYPE_WRBACK);
|
||||
intel_set_var_mtrr(1, (ramsizeK * 1024),
|
||||
4096 * 1024, MTRR_TYPE_UNCACHABLE);
|
||||
printk(KERN_INFO "MTRRs set\n");
|
||||
range = 1 << fms(ramsizeK);
|
||||
DBG("Setting variable MTRR %d, base: %dMB, range: %dMB, type: WB\n",
|
||||
reg, rambase >> 10, range >> 10);
|
||||
|
||||
#else /* SIS630 */
|
||||
printk("Setting variable MTRR 0 to %dK\n", ramsizeK);
|
||||
intel_set_var_mtrr(0, 0, ramsizeK * 1024, MTRR_TYPE_WRBACK);
|
||||
#endif /* SIS630 */
|
||||
intel_set_var_mtrr(reg, rambase * 1024, range * 1024, MTRR_TYPE_WRBACK);
|
||||
|
||||
rambase += range;
|
||||
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();
|
||||
|
||||
|
@ -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_enable_var_mtrr();
|
||||
// intel_set_fixed_mtrr();
|
||||
//intel_set_fixed_mtrr();
|
||||
}
|
||||
#endif /* ENABLE_FIXED_AND_VARIABLE_MTRRS */
|
||||
#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!
|
||||
intel_set_mtrr(base, totalram);
|
||||
#endif
|
||||
intel_post(0x62);
|
||||
intel_post(0x6A);
|
||||
}
|
||||
|
||||
void intel_interrupts_on()
|
||||
|
|
Loading…
Add table
Reference in a new issue