soc/intel/quark: MTRR support

Add the SoC specific routines to access the MTRR registers.  These
registers exist in the host bridge and are not accessible via the
rdmsr/wrmsr instructions.

Testing on Galileo:
*  Edit the src/mainboard/intel/galileo/Makefile.inc file
   *  Add "select ADD_FSP_PDAT_FILE"
   *  Add "select ADD_FSP_RAW_BIN"
   *  Add "select ADD_RMU_FILE"
   *  Add "select DISPLAY_MTRRS"
*  Place the FSP.bin file in the location specified by CONFIG_FSP_FILE
*  Place the pdat.bin files in the location specified by
CONFIG_FSP_PDAT_FILE
*  Place the rmu.bin file in the location specified by CONFIG_RMU_FILE
*  Testing is successful if:
   *  The message "FSP TempRamInit successful" is displayed

Change-Id: I7c124145429ae1d1365a6222a68853edbef4ff69
Signed-off-by: Lee Leahy <leroy.p.leahy@intel.com>
Reviewed-on: https://review.coreboot.org/13530
Tested-by: build bot (Jenkins)
Reviewed-by: FEI WANG <wangfei.jimei@gmail.com>
This commit is contained in:
Lee Leahy 2016-02-07 14:52:22 -08:00 committed by Stefan Reinauer
parent 3968653f25
commit 43cdff6b45
5 changed files with 205 additions and 0 deletions

View File

@ -27,8 +27,10 @@ config CPU_SPECIFIC_OPTIONS
select ARCH_ROMSTAGE_X86_32
select ARCH_VERSTAGE_X86_32
select SOC_INTEL_COMMON
select SOC_SETS_MTRRS
select TSC_CONSTANT_RATE
select UDELAY_TSC
select UNCOMPRESSED_RAMSTAGE
select USE_MARCH_586
#####

View File

@ -18,6 +18,12 @@
#ifndef _QUARK_PCI_DEVS_H_
#define _QUARK_PCI_DEVS_H_
#include <device/pci.h>
#include <soc/QuarkNcSocId.h>
/* DEVICE 0 (Memroy Controller Hub) */
#define MC_BDF PCI_DEV(PCI_BUS_NUMBER_QNC, MC_DEV, MC_FUN)
/* IO Fabric 1 */
#define SIO1_DEV 0x14
# define HSUART1_DEV SIO1_DEV

View File

@ -22,8 +22,14 @@
#error "Don't include romstage.h from a ramstage compilation unit!"
#endif
#include <fsp/romstage.h>
#include <fsp/util.h>
#include <soc/QuarkNcSocId.h>
void mcr_write(uint8_t opcode, uint8_t port, uint32_t reg_address);
uint32_t mdr_read(void);
void mdr_write(uint32_t value);
void mea_write(uint32_t reg_address);
int set_base_address_and_enable_uart(u8 bus, u8 dev, u8 func, u32 mmio_base);
#endif /* _QUARK_ROMSTAGE_H_ */

View File

@ -154,6 +154,13 @@ before_romstage:
/* Call cache_as_ram_main(struct cache_as_ram_params *) */
call cache_as_ram_main
/* One will never return from cache_as_ram_main() in verstage so there's
* no such thing as after ram init. */
#if !ENV_VERSTAGE
#include "src/drivers/intel/fsp1_1/after_raminit.S"
#endif
movb $0x69, %ah
jmp .Lhlt

View File

@ -16,7 +16,12 @@
#include <arch/early_variables.h>
#include <console/console.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/mtrr.h>
#include <device/pci_def.h>
#include <fsp/car.h>
#include <fsp/util.h>
#include <soc/intel/common/util.h>
#include <soc/iomap.h>
#include <soc/pci_devs.h>
#include <soc/pm.h>
@ -39,3 +44,182 @@ struct chipset_power_state *fill_power_state(void)
printk(BIOS_DEBUG, "prev_sleep_state %d\n", ps->prev_sleep_state);
return ps;
}
void mcr_write(uint8_t opcode, uint8_t port, uint32_t reg_address)
{
pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MCR,
(opcode << QNC_MCR_OP_OFFSET)
| ((uint32_t)port << QNC_MCR_PORT_OFFSET)
| ((reg_address & QNC_MCR_MASK) << QNC_MCR_REG_OFFSET)
| QNC_MCR_BYTE_ENABLES);
}
uint32_t mdr_read(void)
{
return pci_read_config32(MC_BDF, QNC_ACCESS_PORT_MDR);
}
void mdr_write(uint32_t value)
{
pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MDR, value);
}
void mea_write(uint32_t reg_address)
{
pci_write_config32(MC_BDF, QNC_ACCESS_PORT_MEA, reg_address
& QNC_MEA_MASK);
}
static uint32_t mtrr_index_to_host_bridge_register_offset(unsigned long index)
{
uint32_t offset;
/* Convert from MTRR index to host brigde offset (Datasheet 12.7.2) */
if (index == MTRR_CAP_MSR)
offset = QUARK_NC_HOST_BRIDGE_IA32_MTRR_CAP;
else if (index == MTRR_DEF_TYPE_MSR)
offset = QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE;
else if (index == MTRR_FIX_64K_00000)
offset = QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000;
else if ((index >= MTRR_FIX_16K_80000) && (index <= MTRR_FIX_16K_A0000))
offset = ((index - MTRR_FIX_16K_80000) << 1)
+ QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_80000;
else if ((index >= MTRR_FIX_4K_C0000) && (index <= MTRR_FIX_4K_F8000))
offset = ((index - MTRR_FIX_4K_C0000) << 1)
+ QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0;
else if ((index >= MTRR_PHYS_BASE(0)) && (index <= MTRR_PHYS_MASK(7)))
offset = (index - MTRR_PHYS_BASE(0))
+ QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0;
else {
printk(BIOS_DEBUG, "index: 0x%08lx\n", index);
die("Invalid MTRR index specified!\n");
}
return offset;
}
msr_t soc_mtrr_read(unsigned long index)
{
uint32_t offset;
union {
uint64_t u64;
msr_t msr;
} value;
/* Read the low 32-bits of the register */
offset = mtrr_index_to_host_bridge_register_offset(index);
mea_write(offset);
mcr_write(QUARK_OPCODE_READ, QUARK_NC_HOST_BRIDGE_SB_PORT_ID, offset);
value.u64 = mdr_read();
/* For 64-bit registers, read the upper 32-bits */
if ((offset >= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000)
&& (offset <= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000)) {
offset += 1;
mea_write(offset);
mcr_write(QUARK_OPCODE_READ, QUARK_NC_HOST_BRIDGE_SB_PORT_ID,
offset);
value.u64 |= mdr_read();
}
return value.msr;
}
void soc_mtrr_write(unsigned long index, msr_t msr)
{
uint32_t offset;
union {
uint32_t u32[2];
msr_t msr;
} value;
/* Write the low 32-bits of the register */
value.msr = msr;
offset = mtrr_index_to_host_bridge_register_offset(index);
mea_write(offset);
mdr_write(value.u32[0]);
mcr_write(QUARK_OPCODE_WRITE, QUARK_NC_HOST_BRIDGE_SB_PORT_ID, offset);
/* For 64-bit registers, write the upper 32-bits */
if ((offset >= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000)
&& (offset <= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000)) {
offset += 1;
mea_write(offset);
mdr_write(value.u32[1]);
mcr_write(QUARK_OPCODE_WRITE, QUARK_NC_HOST_BRIDGE_SB_PORT_ID,
offset);
}
}
asmlinkage void *soc_set_mtrrs(void *top_of_stack)
{
union {
uint32_t u32[2];
uint64_t u64;
msr_t msr;
} data;
uint32_t mtrr_count;
uint32_t *mtrr_data;
uint32_t mtrr_reg;
/*
* The stack contents are initialized in src/soc/intel/common/stack.c
* to be the following:
*
* *
* *
* *
* +36: MTRR mask 1 63:32
* +32: MTRR mask 1 31:0
* +28: MTRR base 1 63:32
* +24: MTRR base 1 31:0
* +20: MTRR mask 0 63:32
* +16: MTRR mask 0 31:0
* +12: MTRR base 0 63:32
* +8: MTRR base 0 31:0
* +4: Number of MTRRs to setup (described above)
* top_of_stack --> +0: Number of variable MTRRs to clear
*
* This routine:
* * Clears all of the variable MTRRs
* * Initializes the variable MTRRs with the data passed in
* * Returns the new top of stack after removing all of the
* data passed in.
*/
/* Clear all of the variable MTRRs (base and mask). */
mtrr_reg = MTRR_PHYS_BASE(0);
mtrr_data = top_of_stack;
mtrr_count = (*mtrr_data++) * 2;
data.u64 = 0;
while (mtrr_count-- > 0)
soc_mtrr_write(mtrr_reg++, data.msr);
/* Setup the specified variable MTRRs */
mtrr_reg = MTRR_PHYS_BASE(0);
mtrr_count = *mtrr_data++;
while (mtrr_count-- > 0) {
data.u32[0] = *mtrr_data++;
data.u32[1] = *mtrr_data++;
soc_mtrr_write(mtrr_reg++, data.msr); /* Base */
data.u32[0] = *mtrr_data++;
data.u32[1] = *mtrr_data++;
soc_mtrr_write(mtrr_reg++, data.msr); /* Mask */
}
/* Remove setup_stack_and_mtrrs data and return the new top_of_stack */
top_of_stack = mtrr_data;
return top_of_stack;
}
asmlinkage void soc_enable_mtrrs(void)
{
union {
uint32_t u32[2];
uint64_t u64;
msr_t msr;
} data;
/* Enable MTRR. */
data.msr = soc_mtrr_read(MTRR_DEF_TYPE_MSR);
data.u32[0] |= MTRR_DEF_TYPE_EN;
soc_mtrr_write(MTRR_DEF_TYPE_MSR, data.msr);
}