From 43cdff6b453e0563414a020c2bab69a841a8f2e8 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Sun, 7 Feb 2016 14:52:22 -0800 Subject: 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 Reviewed-on: https://review.coreboot.org/13530 Tested-by: build bot (Jenkins) Reviewed-by: FEI WANG --- src/soc/intel/quark/Kconfig | 2 + src/soc/intel/quark/include/soc/pci_devs.h | 6 + src/soc/intel/quark/include/soc/romstage.h | 6 + src/soc/intel/quark/romstage/cache_as_ram.inc | 7 + src/soc/intel/quark/romstage/romstage.c | 184 ++++++++++++++++++++++++++ 5 files changed, 205 insertions(+) (limited to 'src') diff --git a/src/soc/intel/quark/Kconfig b/src/soc/intel/quark/Kconfig index d99cd54156..08272f02b9 100644 --- a/src/soc/intel/quark/Kconfig +++ b/src/soc/intel/quark/Kconfig @@ -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 ##### diff --git a/src/soc/intel/quark/include/soc/pci_devs.h b/src/soc/intel/quark/include/soc/pci_devs.h index 0543a05b53..4ab23b9745 100644 --- a/src/soc/intel/quark/include/soc/pci_devs.h +++ b/src/soc/intel/quark/include/soc/pci_devs.h @@ -18,6 +18,12 @@ #ifndef _QUARK_PCI_DEVS_H_ #define _QUARK_PCI_DEVS_H_ +#include +#include + +/* 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 diff --git a/src/soc/intel/quark/include/soc/romstage.h b/src/soc/intel/quark/include/soc/romstage.h index a35f4a6dd2..3a1320cafc 100644 --- a/src/soc/intel/quark/include/soc/romstage.h +++ b/src/soc/intel/quark/include/soc/romstage.h @@ -22,8 +22,14 @@ #error "Don't include romstage.h from a ramstage compilation unit!" #endif +#include #include +#include +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_ */ diff --git a/src/soc/intel/quark/romstage/cache_as_ram.inc b/src/soc/intel/quark/romstage/cache_as_ram.inc index 4fc60e284b..a935bdf1e0 100644 --- a/src/soc/intel/quark/romstage/cache_as_ram.inc +++ b/src/soc/intel/quark/romstage/cache_as_ram.inc @@ -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 diff --git a/src/soc/intel/quark/romstage/romstage.c b/src/soc/intel/quark/romstage/romstage.c index 19d0642e54..495e454295 100644 --- a/src/soc/intel/quark/romstage/romstage.c +++ b/src/soc/intel/quark/romstage/romstage.c @@ -16,7 +16,12 @@ #include #include +#include +#include +#include #include +#include +#include #include #include #include @@ -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); +} -- cgit v1.2.3