diff options
Diffstat (limited to 'arch/x86/cpu/ivybridge')
-rw-r--r-- | arch/x86/cpu/ivybridge/Kconfig | 27 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/Makefile | 4 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/bd82x6x.c | 17 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/car.S | 241 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/cpu.c | 96 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/early_me.c | 31 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/gma.c | 7 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/lpc.c | 77 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/me_status.c | 195 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/microcode_intel.c | 166 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/model_206ax.c | 8 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/northbridge.c | 5 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/report_platform.c | 90 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/sata.c | 51 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/sdram.c | 404 |
15 files changed, 142 insertions, 1277 deletions
diff --git a/arch/x86/cpu/ivybridge/Kconfig b/arch/x86/cpu/ivybridge/Kconfig index 0819347b59..e23d01a08f 100644 --- a/arch/x86/cpu/ivybridge/Kconfig +++ b/arch/x86/cpu/ivybridge/Kconfig @@ -7,43 +7,18 @@ config NORTHBRIDGE_INTEL_IVYBRIDGE bool - select CACHE_MRC_BIN + select CACHE_MRC_BIN if HAVE_MRC if NORTHBRIDGE_INTEL_IVYBRIDGE -config CACHE_MRC_BIN - bool - default n - -config CACHE_MRC_SIZE_KB - int - default 512 - config DCACHE_RAM_BASE - hex default 0xff7e0000 config DCACHE_RAM_SIZE - hex default 0x20000 -config HAVE_MRC - bool "Add a System Agent binary" - help - Select this option to add a System Agent binary to - the resulting U-Boot image. MRC stands for Memory Reference Code. - It is a binary blob which U-Boot uses to set up SDRAM. - - Note: Without this binary U-Boot will not be able to set up its - SDRAM so will not boot. - config DCACHE_RAM_MRC_VAR_SIZE - hex default 0x4000 - help - This is the amount of CAR (Cache as RAM) reserved for use by the - memory reference code. This should be set to 16KB (0x4000 hex) - so that MRC has enough space to run. config CPU_SPECIFIC_OPTIONS def_bool y diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index 9203219f31..9cdb07bdf2 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -7,16 +7,12 @@ ifdef CONFIG_HAVE_FSP obj-y += fsp_configs.o ivybridge.o else -obj-y += car.o obj-y += cpu.o obj-y += early_me.o obj-y += gma.o obj-y += lpc.o -obj-y += me_status.o obj-y += model_206ax.o -obj-y += microcode_intel.o obj-y += northbridge.o -obj-y += report_platform.o obj-y += sata.o obj-y += sdram.o endif diff --git a/arch/x86/cpu/ivybridge/bd82x6x.c b/arch/x86/cpu/ivybridge/bd82x6x.c index 9972b0ae7f..4c039ac9c6 100644 --- a/arch/x86/cpu/ivybridge/bd82x6x.c +++ b/arch/x86/cpu/ivybridge/bd82x6x.c @@ -11,8 +11,10 @@ #include <pch.h> #include <syscon.h> #include <asm/cpu.h> +#include <asm/intel_regs.h> #include <asm/io.h> #include <asm/lapic.h> +#include <asm/lpc_common.h> #include <asm/pci.h> #include <asm/arch/bd82x6x.h> #include <asm/arch/model_206ax.h> @@ -187,20 +189,7 @@ static int bd82x6x_pch_get_spi_base(struct udevice *dev, ulong *sbasep) static int bd82x6x_set_spi_protect(struct udevice *dev, bool protect) { - uint8_t bios_cntl; - - /* Adjust the BIOS write protect and SMM BIOS Write Protect Disable */ - dm_pci_read_config8(dev, BIOS_CTRL, &bios_cntl); - if (protect) { - bios_cntl &= ~BIOS_CTRL_BIOSWE; - bios_cntl |= BIT(5); - } else { - bios_cntl |= BIOS_CTRL_BIOSWE; - bios_cntl &= ~BIT(5); - } - dm_pci_write_config8(dev, BIOS_CTRL, bios_cntl); - - return 0; + return lpc_set_spi_protect(dev, BIOS_CTRL, protect); } static int bd82x6x_get_gpio_base(struct udevice *dev, u32 *gbasep) diff --git a/arch/x86/cpu/ivybridge/car.S b/arch/x86/cpu/ivybridge/car.S deleted file mode 100644 index 1defabf91f..0000000000 --- a/arch/x86/cpu/ivybridge/car.S +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (c) 2014 Google, Inc - * - * From Coreboot file cpu/intel/model_206ax/cache_as_ram.inc - * - * Copyright (C) 2000,2007 Ronald G. Minnich <rminnich@gmail.com> - * Copyright (C) 2005 Tyan (written by Yinghai Lu for Tyan) - * Copyright (C) 2007-2008 coresystems GmbH - * Copyright (C) 2012 Kyösti Mälkki <kyosti.malkki@gmail.com> - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include <common.h> -#include <asm/msr-index.h> -#include <asm/mtrr.h> -#include <asm/post.h> -#include <asm/processor.h> -#include <asm/processor-flags.h> -#include <asm/arch/microcode.h> - -#define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg)) -#define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1) - -#define CACHE_AS_RAM_SIZE CONFIG_DCACHE_RAM_SIZE -#define CACHE_AS_RAM_BASE CONFIG_DCACHE_RAM_BASE - -/* Cache 4GB - MRC_SIZE_KB for MRC */ -#define CACHE_MRC_BYTES ((CONFIG_CACHE_MRC_SIZE_KB << 10) - 1) -#define CACHE_MRC_BASE (0xFFFFFFFF - CACHE_MRC_BYTES) -#define CACHE_MRC_MASK (~CACHE_MRC_BYTES) - -#define CPU_PHYSMASK_HI (1 << (CONFIG_CPU_ADDR_BITS - 32) - 1) - -#define NOEVICTMOD_MSR 0x2e0 - - /* - * Note: ebp must not be touched in this code as it holds the BIST - * value (built-in self test). We preserve this value until it can - * be written to global_data when CAR is ready for use. - */ -.globl car_init -car_init: - post_code(POST_CAR_START) - - /* Send INIT IPI to all excluding ourself */ - movl $0x000C4500, %eax - movl $0xFEE00300, %esi - movl %eax, (%esi) - - /* TODO: Load microcode later - the 'no eviction' mode breaks this */ - movl $MSR_IA32_UCODE_WRITE, %ecx - xorl %edx, %edx - movl $_dt_ucode_base_size, %eax - movl (%eax), %eax - addl $UCODE_HEADER_LEN, %eax - wrmsr - - post_code(POST_CAR_SIPI) - /* Zero out all fixed range and variable range MTRRs */ - movl $mtrr_table, %esi - movl $((mtrr_table_end - mtrr_table) / 2), %edi - xorl %eax, %eax - xorl %edx, %edx -clear_mtrrs: - movw (%esi), %bx - movzx %bx, %ecx - wrmsr - add $2, %esi - dec %edi - jnz clear_mtrrs - - post_code(POST_CAR_MTRR) - /* Configure the default memory type to uncacheable */ - movl $MTRR_DEF_TYPE_MSR, %ecx - rdmsr - andl $(~0x00000cff), %eax - wrmsr - - post_code(POST_CAR_UNCACHEABLE) - /* Set Cache-as-RAM base address */ - movl $(MTRR_PHYS_BASE_MSR(0)), %ecx - movl $(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax - xorl %edx, %edx - wrmsr - - post_code(POST_CAR_BASE_ADDRESS) - /* Set Cache-as-RAM mask */ - movl $(MTRR_PHYS_MASK_MSR(0)), %ecx - movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax - movl $CPU_PHYSMASK_HI, %edx - wrmsr - - post_code(POST_CAR_MASK) - - /* Enable MTRR */ - movl $MTRR_DEF_TYPE_MSR, %ecx - rdmsr - orl $MTRR_DEF_TYPE_EN, %eax - wrmsr - - /* Enable cache (CR0.CD = 0, CR0.NW = 0) */ - movl %cr0, %eax - andl $(~(X86_CR0_CD | X86_CR0_NW)), %eax - invd - movl %eax, %cr0 - - /* enable the 'no eviction' mode */ - movl $NOEVICTMOD_MSR, %ecx - rdmsr - orl $1, %eax - andl $~2, %eax - wrmsr - - /* Clear the cache memory region. This will also fill up the cache */ - movl $CACHE_AS_RAM_BASE, %esi - movl %esi, %edi - movl $(CACHE_AS_RAM_SIZE / 4), %ecx - xorl %eax, %eax - rep stosl - - /* enable the 'no eviction run' state */ - movl $NOEVICTMOD_MSR, %ecx - rdmsr - orl $3, %eax - wrmsr - - post_code(POST_CAR_FILL) - /* Enable Cache-as-RAM mode by disabling cache */ - movl %cr0, %eax - orl $X86_CR0_CD, %eax - movl %eax, %cr0 - - /* Enable cache for our code in Flash because we do XIP here */ - movl $MTRR_PHYS_BASE_MSR(1), %ecx - xorl %edx, %edx - movl $car_init_ret, %eax - andl $(~(CONFIG_XIP_ROM_SIZE - 1)), %eax - orl $MTRR_TYPE_WRPROT, %eax - wrmsr - - movl $MTRR_PHYS_MASK_MSR(1), %ecx - movl $CPU_PHYSMASK_HI, %edx - movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax - wrmsr - - post_code(POST_CAR_ROM_CACHE) -#ifdef CONFIG_CACHE_MRC_BIN - /* Enable caching for ram init code to run faster */ - movl $MTRR_PHYS_BASE_MSR(2), %ecx - movl $(CACHE_MRC_BASE | MTRR_TYPE_WRPROT), %eax - xorl %edx, %edx - wrmsr - movl $MTRR_PHYS_MASK_MSR(2), %ecx - movl $(CACHE_MRC_MASK | MTRR_PHYS_MASK_VALID), %eax - movl $CPU_PHYSMASK_HI, %edx - wrmsr -#endif - - post_code(POST_CAR_MRC_CACHE) - /* Enable cache */ - movl %cr0, %eax - andl $(~(X86_CR0_CD | X86_CR0_NW)), %eax - movl %eax, %cr0 - - post_code(POST_CAR_CPU_CACHE) - - /* All CPUs need to be in Wait for SIPI state */ -wait_for_sipi: - movl (%esi), %eax - bt $12, %eax - jc wait_for_sipi - - /* return */ - jmp car_init_ret - -.globl car_uninit -car_uninit: - /* Disable cache */ - movl %cr0, %eax - orl $X86_CR0_CD, %eax - movl %eax, %cr0 - - /* Disable MTRRs */ - movl $MTRR_DEF_TYPE_MSR, %ecx - rdmsr - andl $(~MTRR_DEF_TYPE_EN), %eax - wrmsr - - /* Disable the no-eviction run state */ - movl $NOEVICTMOD_MSR, %ecx - rdmsr - andl $~2, %eax - wrmsr - - invd - - /* Disable the no-eviction mode */ - rdmsr - andl $~1, %eax - wrmsr - -#ifdef CONFIG_CACHE_MRC_BIN - /* Clear the MTRR that was used to cache MRC */ - xorl %eax, %eax - xorl %edx, %edx - movl $MTRR_PHYS_BASE_MSR(2), %ecx - wrmsr - movl $MTRR_PHYS_MASK_MSR(2), %ecx - wrmsr -#endif - - /* Enable MTRRs */ - movl $MTRR_DEF_TYPE_MSR, %ecx - rdmsr - orl $MTRR_DEF_TYPE_EN, %eax - wrmsr - - invd - - ret - -mtrr_table: - /* Fixed MTRRs */ - .word 0x250, 0x258, 0x259 - .word 0x268, 0x269, 0x26A - .word 0x26B, 0x26C, 0x26D - .word 0x26E, 0x26F - /* Variable MTRRs */ - .word 0x200, 0x201, 0x202, 0x203 - .word 0x204, 0x205, 0x206, 0x207 - .word 0x208, 0x209, 0x20A, 0x20B - .word 0x20C, 0x20D, 0x20E, 0x20F - .word 0x210, 0x211, 0x212, 0x213 -mtrr_table_end: - - .align 4 -_dt_ucode_base_size: - /* These next two fields are filled in by ifdtool */ - .long 0 /* microcode base */ - .long 0 /* microcode size */ diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index 948833c028..0f9390517f 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -17,15 +17,18 @@ #include <fdtdec.h> #include <pch.h> #include <asm/cpu.h> +#include <asm/cpu_common.h> +#include <asm/intel_regs.h> #include <asm/io.h> #include <asm/lapic.h> +#include <asm/lpc_common.h> +#include <asm/microcode.h> #include <asm/msr.h> #include <asm/mtrr.h> #include <asm/pci.h> #include <asm/post.h> #include <asm/processor.h> #include <asm/arch/model_206ax.h> -#include <asm/arch/microcode.h> #include <asm/arch/pch.h> #include <asm/arch/sandybridge.h> @@ -33,51 +36,11 @@ DECLARE_GLOBAL_DATA_PTR; static int set_flex_ratio_to_tdp_nominal(void) { - msr_t flex_ratio, msr; - u8 nominal_ratio; - /* Minimum CPU revision for configurable TDP support */ if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID) return -EINVAL; - /* Check for Flex Ratio support */ - flex_ratio = msr_read(MSR_FLEX_RATIO); - if (!(flex_ratio.lo & FLEX_RATIO_EN)) - return -EINVAL; - - /* Check for >0 configurable TDPs */ - msr = msr_read(MSR_PLATFORM_INFO); - if (((msr.hi >> 1) & 3) == 0) - return -EINVAL; - - /* Use nominal TDP ratio for flex ratio */ - msr = msr_read(MSR_CONFIG_TDP_NOMINAL); - nominal_ratio = msr.lo & 0xff; - - /* See if flex ratio is already set to nominal TDP ratio */ - if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio) - return 0; - - /* Set flex ratio to nominal TDP ratio */ - flex_ratio.lo &= ~0xff00; - flex_ratio.lo |= nominal_ratio << 8; - flex_ratio.lo |= FLEX_RATIO_LOCK; - msr_write(MSR_FLEX_RATIO, flex_ratio); - - /* Set flex ratio in soft reset data register bits 11:6 */ - clrsetbits_le32(RCB_REG(SOFT_RESET_DATA), 0x3f << 6, - (nominal_ratio & 0x3f) << 6); - - /* Set soft reset control to use register value */ - setbits_le32(RCB_REG(SOFT_RESET_CTRL), 1); - - /* Issue warm reset, will be "CPU only" due to soft reset data */ - outb(0x0, PORT_RESET); - outb(SYS_RST | RST_CPU, PORT_RESET); - cpu_hlt(); - - /* Not reached */ - return -EINVAL; + return cpu_set_flex_ratio_to_tdp_nominal(); } int arch_cpu_init(void) @@ -104,9 +67,9 @@ int arch_cpu_init_dm(void) /* TODO(sjg@chromium.org): Get rid of gd->hose */ gd->hose = hose; - ret = uclass_first_device(UCLASS_LPC, &dev); - if (!dev) - return -ENODEV; + ret = uclass_first_device_err(UCLASS_LPC, &dev); + if (ret) + return ret; /* * We should do as little as possible before the serial console is @@ -162,17 +125,6 @@ static void enable_usb_bar(struct udevice *bus) pci_bus_write_config(bus, usb3, PCI_COMMAND, cmd, PCI_SIZE_32); } -static int report_bist_failure(void) -{ - if (gd->arch.bist != 0) { - post_code(POST_BIST_FAILURE); - printf("BIST failed: %08x\n", gd->arch.bist); - return -EFAULT; - } - - return 0; -} - int print_cpuinfo(void) { enum pei_boot_mode_t boot_mode = PEI_BOOT_NONE; @@ -183,20 +135,6 @@ int print_cpuinfo(void) uint16_t pm1_sts; int ret; - /* Halt if there was a built in self test failure */ - ret = report_bist_failure(); - if (ret) - return ret; - - enable_lapic(); - - ret = microcode_update_intel(); - if (ret) - return ret; - - /* Enable upper 128bytes of CMOS */ - writel(1 << 2, RCB_REG(RC)); - /* TODO: cmos_post_init() */ if (readl(MCHBAR_REG(SSKPD)) == 0xCAFE) { debug("soft reset detected\n"); @@ -207,17 +145,9 @@ int print_cpuinfo(void) reset_cpu(0); } - /* Early chipset init required before RAM init can work */ - uclass_first_device(UCLASS_NORTHBRIDGE, &dev); - - ret = uclass_first_device(UCLASS_LPC, &lpc); + ret = cpu_common_init(); if (ret) return ret; - if (!dev) - return -ENODEV; - - /* Cause the SATA device to do its early init */ - uclass_first_device(UCLASS_DISK, &dev); /* Check PM1_STS[15] to see if we are waking from Sx */ pm1_sts = inw(DEFAULT_PMBASE + PM1_STS); @@ -236,15 +166,15 @@ int print_cpuinfo(void) post_code(POST_EARLY_INIT); /* Enable SPD ROMs and DDR-III DRAM */ - ret = uclass_first_device(UCLASS_I2C, &dev); + ret = uclass_first_device_err(UCLASS_I2C, &dev); if (ret) return ret; - if (!dev) - return -ENODEV; /* Prepare USB controller early in S3 resume */ - if (boot_mode == PEI_BOOT_RESUME) + if (boot_mode == PEI_BOOT_RESUME) { + uclass_first_device(UCLASS_LPC, &lpc); enable_usb_bar(pci_get_controller(lpc->parent)); + } gd->arch.pei_boot_mode = boot_mode; diff --git a/arch/x86/cpu/ivybridge/early_me.c b/arch/x86/cpu/ivybridge/early_me.c index b1df77d571..cda96ab398 100644 --- a/arch/x86/cpu/ivybridge/early_me.c +++ b/arch/x86/cpu/ivybridge/early_me.c @@ -27,35 +27,6 @@ static const char *const me_ack_values[] = { [ME_HFS_ACK_CONTINUE] = "Continue to boot" }; -static inline void pci_read_dword_ptr(struct udevice *me_dev, void *ptr, - int offset) -{ - u32 dword; - - dm_pci_read_config32(me_dev, offset, &dword); - memcpy(ptr, &dword, sizeof(dword)); -} - -static inline void pci_write_dword_ptr(struct udevice *me_dev, void *ptr, - int offset) -{ - u32 dword = 0; - - memcpy(&dword, ptr, sizeof(dword)); - dm_pci_write_config32(me_dev, offset, dword); -} - -void intel_early_me_status(struct udevice *me_dev) -{ - struct me_hfs hfs; - struct me_gmes gmes; - - pci_read_dword_ptr(me_dev, &hfs, PCI_ME_HFS); - pci_read_dword_ptr(me_dev, &gmes, PCI_ME_GMES); - - intel_me_status(&hfs, &gmes); -} - int intel_early_me_init(struct udevice *me_dev) { int count; @@ -159,7 +130,7 @@ int intel_early_me_init_done(struct udevice *dev, struct udevice *me_dev, debug("ME: Requested BIOS Action: %s\n", me_ack_values[hfs.ack_data]); /* Check status after acknowledgement */ - intel_early_me_status(me_dev); + intel_me_status(me_dev); switch (hfs.ack_data) { case ME_HFS_ACK_CONTINUE: diff --git a/arch/x86/cpu/ivybridge/gma.c b/arch/x86/cpu/ivybridge/gma.c index 3b6291e905..37e2e6ead8 100644 --- a/arch/x86/cpu/ivybridge/gma.c +++ b/arch/x86/cpu/ivybridge/gma.c @@ -12,6 +12,7 @@ #include <errno.h> #include <fdtdec.h> #include <pci_rom.h> +#include <asm/intel_regs.h> #include <asm/io.h> #include <asm/mtrr.h> #include <asm/pci.h> @@ -812,9 +813,9 @@ int gma_func0_init(struct udevice *dev) writew(0x0010, RCB_REG(DISPBDF)); setbits_le32(RCB_REG(FD2), PCH_ENABLE_DBDF); - ret = uclass_first_device(UCLASS_NORTHBRIDGE, &nbridge); - if (!nbridge) - return -ENODEV; + ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &nbridge); + if (ret) + return ret; rev = bridge_silicon_revision(nbridge); sandybridge_setup_graphics(nbridge, dev); diff --git a/arch/x86/cpu/ivybridge/lpc.c b/arch/x86/cpu/ivybridge/lpc.c index 9ab5ed3ff9..88ab7973fd 100644 --- a/arch/x86/cpu/ivybridge/lpc.c +++ b/arch/x86/cpu/ivybridge/lpc.c @@ -13,9 +13,11 @@ #include <rtc.h> #include <pci.h> #include <asm/acpi.h> +#include <asm/intel_regs.h> #include <asm/interrupt.h> #include <asm/io.h> #include <asm/ioapic.h> +#include <asm/lpc_common.h> #include <asm/pci.h> #include <asm/arch/pch.h> @@ -404,26 +406,6 @@ static void pch_fixups(struct udevice *pch) setbits_le32(RCB_REG(0x21a8), 0x3); } -/* - * Enable Prefetching and Caching. - */ -static void enable_spi_prefetch(struct udevice *pch) -{ - u8 reg8; - - dm_pci_read_config8(pch, 0xdc, ®8); - reg8 &= ~(3 << 2); - reg8 |= (2 << 2); /* Prefetching and Caching Enabled */ - dm_pci_write_config8(pch, 0xdc, reg8); -} - -static void enable_port80_on_lpc(struct udevice *pch) -{ - /* Enable port 80 POST on LPC */ - dm_pci_write_config32(pch, PCH_RCBA_BASE, DEFAULT_RCBA | 1); - clrbits_le32(RCB_REG(GCS), 4); -} - static void set_spi_speed(void) { u32 fdod; @@ -440,54 +422,6 @@ static void set_spi_speed(void) clrsetbits_8(RCB_REG(SPI_FREQ_SWSEQ), 7, fdod); } -/** - * lpc_early_init() - set up LPC serial ports and other early things - * - * @dev: LPC device - * @return 0 if OK, -ve on error - */ -static int lpc_early_init(struct udevice *dev) -{ - struct reg_info { - u32 base; - u32 size; - } values[4], *ptr; - int count; - int i; - - count = fdtdec_get_int_array_count(gd->fdt_blob, dev->of_offset, - "intel,gen-dec", (u32 *)values, - sizeof(values) / sizeof(u32)); - if (count < 0) - return -EINVAL; - - /* Set COM1/COM2 decode range */ - dm_pci_write_config16(dev->parent, LPC_IO_DEC, 0x0010); - - /* Enable PS/2 Keyboard/Mouse, EC areas and COM1 */ - dm_pci_write_config16(dev->parent, LPC_EN, KBC_LPC_EN | MC_LPC_EN | - GAMEL_LPC_EN | COMA_LPC_EN); - - /* Write all registers but use 0 if we run out of data */ - count = count * sizeof(u32) / sizeof(values[0]); - for (i = 0, ptr = values; i < ARRAY_SIZE(values); i++, ptr++) { - u32 reg = 0; - - if (i < count) - reg = ptr->base | PCI_COMMAND_IO | (ptr->size << 16); - dm_pci_write_config32(dev->parent, LPC_GENX_DEC(i), reg); - } - - enable_spi_prefetch(dev->parent); - - /* This is already done in start.S, but let's do it in C */ - enable_port80_on_lpc(dev->parent); - - set_spi_speed(); - - return 0; -} - static int lpc_init_extra(struct udevice *dev) { struct udevice *pch = dev->parent; @@ -550,9 +484,12 @@ static int lpc_init_extra(struct udevice *dev) static int bd82x6x_lpc_early_init(struct udevice *dev) { + set_spi_speed(); + /* Setting up Southbridge. In the northbridge code. */ debug("Setting up static southbridge registers\n"); - dm_pci_write_config32(dev->parent, PCH_RCBA_BASE, DEFAULT_RCBA | 1); + dm_pci_write_config32(dev->parent, PCH_RCBA_BASE, + RCB_BASE_ADDRESS | 1); dm_pci_write_config32(dev->parent, PMBASE, DEFAULT_PMBASE | 1); /* Enable ACPI BAR */ @@ -573,7 +510,7 @@ static int bd82x6x_lpc_probe(struct udevice *dev) int ret; if (!(gd->flags & GD_FLG_RELOC)) { - ret = lpc_early_init(dev); + ret = lpc_common_early_init(dev); if (ret) { debug("%s: lpc_early_init() failed\n", __func__); return ret; diff --git a/arch/x86/cpu/ivybridge/me_status.c b/arch/x86/cpu/ivybridge/me_status.c deleted file mode 100644 index 15cf69f40e..0000000000 --- a/arch/x86/cpu/ivybridge/me_status.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * From Coreboot src/southbridge/intel/bd82x6x/me_status.c - * - * Copyright (C) 2011 The Chromium OS Authors. All rights reserved. - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include <common.h> -#include <asm/arch/me.h> - -/* HFS1[3:0] Current Working State Values */ -static const char *const me_cws_values[] = { - [ME_HFS_CWS_RESET] = "Reset", - [ME_HFS_CWS_INIT] = "Initializing", - [ME_HFS_CWS_REC] = "Recovery", - [ME_HFS_CWS_NORMAL] = "Normal", - [ME_HFS_CWS_WAIT] = "Platform Disable Wait", - [ME_HFS_CWS_TRANS] = "OP State Transition", - [ME_HFS_CWS_INVALID] = "Invalid CPU Plugged In" -}; - -/* HFS1[8:6] Current Operation State Values */ -static const char *const me_opstate_values[] = { - [ME_HFS_STATE_PREBOOT] = "Preboot", - [ME_HFS_STATE_M0_UMA] = "M0 with UMA", - [ME_HFS_STATE_M3] = "M3 without UMA", - [ME_HFS_STATE_M0] = "M0 without UMA", - [ME_HFS_STATE_BRINGUP] = "Bring up", - [ME_HFS_STATE_ERROR] = "M0 without UMA but with error" -}; - -/* HFS[19:16] Current Operation Mode Values */ -static const char *const me_opmode_values[] = { - [ME_HFS_MODE_NORMAL] = "Normal", - [ME_HFS_MODE_DEBUG] = "Debug", - [ME_HFS_MODE_DIS] = "Soft Temporary Disable", - [ME_HFS_MODE_OVER_JMPR] = "Security Override via Jumper", - [ME_HFS_MODE_OVER_MEI] = "Security Override via MEI Message" -}; - -/* HFS[15:12] Error Code Values */ -static const char *const me_error_values[] = { - [ME_HFS_ERROR_NONE] = "No Error", - [ME_HFS_ERROR_UNCAT] = "Uncategorized Failure", - [ME_HFS_ERROR_IMAGE] = "Image Failure", - [ME_HFS_ERROR_DEBUG] = "Debug Failure" -}; - -/* GMES[31:28] ME Progress Code */ -static const char *const me_progress_values[] = { - [ME_GMES_PHASE_ROM] = "ROM Phase", - [ME_GMES_PHASE_BUP] = "BUP Phase", - [ME_GMES_PHASE_UKERNEL] = "uKernel Phase", - [ME_GMES_PHASE_POLICY] = "Policy Module", - [ME_GMES_PHASE_MODULE] = "Module Loading", - [ME_GMES_PHASE_UNKNOWN] = "Unknown", - [ME_GMES_PHASE_HOST] = "Host Communication" -}; - -/* GMES[27:24] Power Management Event */ -static const char *const me_pmevent_values[] = { - [0x00] = "Clean Moff->Mx wake", - [0x01] = "Moff->Mx wake after an error", - [0x02] = "Clean global reset", - [0x03] = "Global reset after an error", - [0x04] = "Clean Intel ME reset", - [0x05] = "Intel ME reset due to exception", - [0x06] = "Pseudo-global reset", - [0x07] = "S0/M0->Sx/M3", - [0x08] = "Sx/M3->S0/M0", - [0x09] = "Non-power cycle reset", - [0x0a] = "Power cycle reset through M3", - [0x0b] = "Power cycle reset through Moff", - [0x0c] = "Sx/Mx->Sx/Moff" -}; - -/* Progress Code 0 states */ -static const char *const me_progress_rom_values[] = { - [0x00] = "BEGIN", - [0x06] = "DISABLE" -}; - -/* Progress Code 1 states */ -static const char *const me_progress_bup_values[] = { - [0x00] = "Initialization starts", - [0x01] = "Disable the host wake event", - [0x04] = "Flow determination start process", - [0x08] = "Error reading/matching the VSCC table in the descriptor", - [0x0a] = "Check to see if straps say ME DISABLED", - [0x0b] = "Timeout waiting for PWROK", - [0x0d] = "Possibly handle BUP manufacturing override strap", - [0x11] = "Bringup in M3", - [0x12] = "Bringup in M0", - [0x13] = "Flow detection error", - [0x15] = "M3 clock switching error", - [0x18] = "M3 kernel load", - [0x1c] = "T34 missing - cannot program ICC", - [0x1f] = "Waiting for DID BIOS message", - [0x20] = "Waiting for DID BIOS message failure", - [0x21] = "DID reported an error", - [0x22] = "Enabling UMA", - [0x23] = "Enabling UMA error", - [0x24] = "Sending DID Ack to BIOS", - [0x25] = "Sending DID Ack to BIOS error", - [0x26] = "Switching clocks in M0", - [0x27] = "Switching clocks in M0 error", - [0x28] = "ME in temp disable", - [0x32] = "M0 kernel load", -}; - -/* Progress Code 3 states */ -static const char *const me_progress_policy_values[] = { - [0x00] = "Entery into Policy Module", - [0x03] = "Received S3 entry", - [0x04] = "Received S4 entry", - [0x05] = "Received S5 entry", - [0x06] = "Received UPD entry", - [0x07] = "Received PCR entry", - [0x08] = "Received NPCR entry", - [0x09] = "Received host wake", - [0x0a] = "Received AC<>DC switch", - [0x0b] = "Received DRAM Init Done", - [0x0c] = "VSCC Data not found for flash device", - [0x0d] = "VSCC Table is not valid", - [0x0e] = "Flash Partition Boundary is outside address space", - [0x0f] = "ME cannot access the chipset descriptor region", - [0x10] = "Required VSCC values for flash parts do not match", -}; - -void intel_me_status(struct me_hfs *hfs, struct me_gmes *gmes) -{ - /* Check Current States */ - debug("ME: FW Partition Table : %s\n", - hfs->fpt_bad ? "BAD" : "OK"); - debug("ME: Bringup Loader Failure : %s\n", - hfs->ft_bup_ld_flr ? "YES" : "NO"); - debug("ME: Firmware Init Complete : %s\n", - hfs->fw_init_complete ? "YES" : "NO"); - debug("ME: Manufacturing Mode : %s\n", - hfs->mfg_mode ? "YES" : "NO"); - debug("ME: Boot Options Present : %s\n", - hfs->boot_options_present ? "YES" : "NO"); - debug("ME: Update In Progress : %s\n", - hfs->update_in_progress ? "YES" : "NO"); - debug("ME: Current Working State : %s\n", - me_cws_values[hfs->working_state]); - debug("ME: Current Operation State : %s\n", - me_opstate_values[hfs->operation_state]); - debug("ME: Current Operation Mode : %s\n", - me_opmode_values[hfs->operation_mode]); - debug("ME: Error Code : %s\n", - me_error_values[hfs->error_code]); - debug("ME: Progress Phase : %s\n", - me_progress_values[gmes->progress_code]); - debug("ME: Power Management Event : %s\n", - me_pmevent_values[gmes->current_pmevent]); - - debug("ME: Progress Phase State : "); - switch (gmes->progress_code) { - case ME_GMES_PHASE_ROM: /* ROM Phase */ - debug("%s", me_progress_rom_values[gmes->current_state]); - break; - - case ME_GMES_PHASE_BUP: /* Bringup Phase */ - if (gmes->current_state < ARRAY_SIZE(me_progress_bup_values) && - me_progress_bup_values[gmes->current_state]) - debug("%s", - me_progress_bup_values[gmes->current_state]); - else - debug("0x%02x", gmes->current_state); - break; - - case ME_GMES_PHASE_POLICY: /* Policy Module Phase */ - if (gmes->current_state < - ARRAY_SIZE(me_progress_policy_values) && - me_progress_policy_values[gmes->current_state]) - debug("%s", - me_progress_policy_values[gmes->current_state]); - else - debug("0x%02x", gmes->current_state); - break; - - case ME_GMES_PHASE_HOST: /* Host Communication Phase */ - if (!gmes->current_state) - debug("Host communication established"); - else - debug("0x%02x", gmes->current_state); - break; - - default: - debug("Unknown 0x%02x", gmes->current_state); - } - debug("\n"); -} diff --git a/arch/x86/cpu/ivybridge/microcode_intel.c b/arch/x86/cpu/ivybridge/microcode_intel.c deleted file mode 100644 index 2440a97c48..0000000000 --- a/arch/x86/cpu/ivybridge/microcode_intel.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2014 Google, Inc - * Copyright (C) 2000 Ronald G. Minnich - * - * Microcode update for Intel PIII and later CPUs - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include <common.h> -#include <errno.h> -#include <fdtdec.h> -#include <libfdt.h> -#include <asm/cpu.h> -#include <asm/msr.h> -#include <asm/msr-index.h> -#include <asm/processor.h> -#include <asm/arch/microcode.h> - -/** - * struct microcode_update - standard microcode header from Intel - * - * We read this information out of the device tree and use it to determine - * whether the update is applicable or not. We also use the same structure - * to read information from the CPU. - */ -struct microcode_update { - uint header_version; - uint update_revision; - uint date_code; - uint processor_signature; - uint checksum; - uint loader_revision; - uint processor_flags; - const void *data; - int size; -}; - -static int microcode_decode_node(const void *blob, int node, - struct microcode_update *update) -{ - update->data = fdt_getprop(blob, node, "data", &update->size); - if (!update->data) - return -EINVAL; - update->data += UCODE_HEADER_LEN; - update->size -= UCODE_HEADER_LEN; - - update->header_version = fdtdec_get_int(blob, node, - "intel,header-version", 0); - update->update_revision = fdtdec_get_int(blob, node, - "intel,update-revision", 0); - update->date_code = fdtdec_get_int(blob, node, - "intel,date-code", 0); - update->processor_signature = fdtdec_get_int(blob, node, - "intel,processor-signature", 0); - update->checksum = fdtdec_get_int(blob, node, "intel,checksum", 0); - update->loader_revision = fdtdec_get_int(blob, node, - "intel,loader-revision", 0); - update->processor_flags = fdtdec_get_int(blob, node, - "intel,processor-flags", 0); - - return 0; -} - -static inline uint32_t microcode_read_rev(void) -{ - /* - * Some Intel CPUs can be very finicky about the CPUID sequence used. - * So this is implemented in assembly so that it works reliably. - */ - uint32_t low, high; - - asm volatile ( - "xorl %%eax, %%eax\n" - "xorl %%edx, %%edx\n" - "movl %2, %%ecx\n" - "wrmsr\n" - "movl $0x01, %%eax\n" - "cpuid\n" - "movl %2, %%ecx\n" - "rdmsr\n" - : /* outputs */ - "=a" (low), "=d" (high) - : /* inputs */ - "i" (MSR_IA32_UCODE_REV) - : /* clobbers */ - "ebx", "ecx" - ); - - return high; -} - -static void microcode_read_cpu(struct microcode_update *cpu) -{ - /* CPUID sets MSR 0x8B iff a microcode update has been loaded. */ - unsigned int x86_model, x86_family; - struct cpuid_result result; - uint32_t low, high; - - wrmsr(MSR_IA32_UCODE_REV, 0, 0); - result = cpuid(1); - rdmsr(MSR_IA32_UCODE_REV, low, cpu->update_revision); - x86_model = (result.eax >> 4) & 0x0f; - x86_family = (result.eax >> 8) & 0x0f; - cpu->processor_signature = result.eax; - - cpu->processor_flags = 0; - if ((x86_model >= 5) || (x86_family > 6)) { - rdmsr(0x17, low, high); - cpu->processor_flags = 1 << ((high >> 18) & 7); - } - debug("microcode: sig=%#x pf=%#x revision=%#x\n", - cpu->processor_signature, cpu->processor_flags, - cpu->update_revision); -} - -/* Get a microcode update from the device tree and apply it */ -int microcode_update_intel(void) -{ - struct microcode_update cpu, update; - const void *blob = gd->fdt_blob; - int skipped; - int count; - int node; - int ret; - int rev; - - microcode_read_cpu(&cpu); - node = 0; - count = 0; - skipped = 0; - do { - node = fdtdec_next_compatible(blob, node, - COMPAT_INTEL_MICROCODE); - if (node < 0) { - debug("%s: Found %d updates\n", __func__, count); - return count ? 0 : skipped ? -EEXIST : -ENOENT; - } - - ret = microcode_decode_node(blob, node, &update); - if (ret) { - debug("%s: Unable to decode update: %d\n", __func__, - ret); - return ret; - } - if (!(update.processor_signature == cpu.processor_signature && - (update.processor_flags & cpu.processor_flags))) { - debug("%s: Skipping non-matching update, sig=%x, pf=%x\n", - __func__, update.processor_signature, - update.processor_flags); - skipped++; - continue; - } - wrmsr(MSR_IA32_UCODE_WRITE, (ulong)update.data, 0); - rev = microcode_read_rev(); - debug("microcode: updated to revision 0x%x date=%04x-%02x-%02x\n", - rev, update.date_code & 0xffff, - (update.date_code >> 24) & 0xff, - (update.date_code >> 16) & 0xff); - if (update.update_revision != rev) { - printf("Microcode update failed\n"); - return -EFAULT; - } - count++; - } while (1); -} diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c index 9654600cf1..cef425669c 100644 --- a/arch/x86/cpu/ivybridge/model_206ax.c +++ b/arch/x86/cpu/ivybridge/model_206ax.c @@ -17,6 +17,7 @@ #include <asm/cpu_x86.h> #include <asm/lapic.h> #include <asm/msr.h> +#include <asm/msr-index.h> #include <asm/mtrr.h> #include <asm/processor.h> #include <asm/speedstep.h> @@ -363,7 +364,7 @@ static void set_max_ratio(void) msr = msr_read(MSR_PLATFORM_INFO); perf_ctl.lo = msr.lo & 0xff00; } - msr_write(IA32_PERF_CTL, perf_ctl); + msr_write(MSR_IA32_PERF_CTL, perf_ctl); debug("model_x06ax: frequency set to %d\n", ((perf_ctl.lo >> 8) & 0xff) * SANDYBRIDGE_BCLK); @@ -455,9 +456,10 @@ static int model_206ax_get_info(struct udevice *dev, struct cpu_info *info) { msr_t msr; - msr = msr_read(IA32_PERF_CTL); + msr = msr_read(MSR_IA32_PERF_CTL); info->cpu_freq = ((msr.lo >> 8) & 0xff) * SANDYBRIDGE_BCLK * 1000000; - info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU; + info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU | + 1 << CPU_FEAT_UCODE; return 0; } diff --git a/arch/x86/cpu/ivybridge/northbridge.c b/arch/x86/cpu/ivybridge/northbridge.c index a066607a18..f7e0bc3f18 100644 --- a/arch/x86/cpu/ivybridge/northbridge.c +++ b/arch/x86/cpu/ivybridge/northbridge.c @@ -12,6 +12,7 @@ #include <asm/msr.h> #include <asm/acpi.h> #include <asm/cpu.h> +#include <asm/intel_regs.h> #include <asm/io.h> #include <asm/pci.h> #include <asm/processor.h> @@ -167,8 +168,8 @@ static void sandybridge_setup_northbridge_bars(struct udevice *dev) debug("Setting up static registers\n"); dm_pci_write_config32(dev, EPBAR, DEFAULT_EPBAR | 1); dm_pci_write_config32(dev, EPBAR + 4, (0LL + DEFAULT_EPBAR) >> 32); - dm_pci_write_config32(dev, MCHBAR, DEFAULT_MCHBAR | 1); - dm_pci_write_config32(dev, MCHBAR + 4, (0LL + DEFAULT_MCHBAR) >> 32); + dm_pci_write_config32(dev, MCHBAR, MCH_BASE_ADDRESS | 1); + dm_pci_write_config32(dev, MCHBAR + 4, (0LL + MCH_BASE_ADDRESS) >> 32); /* 64MB - busses 0-63 */ dm_pci_write_config32(dev, PCIEXBAR, DEFAULT_PCIEXBAR | 5); dm_pci_write_config32(dev, PCIEXBAR + 4, diff --git a/arch/x86/cpu/ivybridge/report_platform.c b/arch/x86/cpu/ivybridge/report_platform.c deleted file mode 100644 index c78322aef9..0000000000 --- a/arch/x86/cpu/ivybridge/report_platform.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * From Coreboot src/northbridge/intel/sandybridge/report_platform.c - * - * Copyright (C) 2012 Google Inc. - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include <common.h> -#include <asm/cpu.h> -#include <asm/pci.h> -#include <asm/arch/pch.h> -#include <asm/arch/sandybridge.h> - -static void report_cpu_info(void) -{ - char cpu_string[CPU_MAX_NAME_LEN], *cpu_name; - const char *mode[] = {"NOT ", ""}; - struct cpuid_result cpuidr; - int vt, txt, aes; - u32 index; - - index = 0x80000000; - cpuidr = cpuid(index); - if (cpuidr.eax < 0x80000004) { - strcpy(cpu_string, "Platform info not available"); - cpu_name = cpu_string; - } else { - cpu_name = cpu_get_name(cpu_string); - } - - cpuidr = cpuid(1); - debug("CPU id(%x): %s\n", cpuidr.eax, cpu_name); - aes = (cpuidr.ecx & (1 << 25)) ? 1 : 0; - txt = (cpuidr.ecx & (1 << 6)) ? 1 : 0; - vt = (cpuidr.ecx & (1 << 5)) ? 1 : 0; - debug("AES %ssupported, TXT %ssupported, VT %ssupported\n", - mode[aes], mode[txt], mode[vt]); -} - -/* The PCI id name match comes from Intel document 472178 */ -static struct { - u16 dev_id; - const char *dev_name; -} pch_table[] = { - {0x1E41, "Desktop Sample"}, - {0x1E42, "Mobile Sample"}, - {0x1E43, "SFF Sample"}, - {0x1E44, "Z77"}, - {0x1E45, "H71"}, - {0x1E46, "Z75"}, - {0x1E47, "Q77"}, - {0x1E48, "Q75"}, - {0x1E49, "B75"}, - {0x1E4A, "H77"}, - {0x1E53, "C216"}, - {0x1E55, "QM77"}, - {0x1E56, "QS77"}, - {0x1E58, "UM77"}, - {0x1E57, "HM77"}, - {0x1E59, "HM76"}, - {0x1E5D, "HM75"}, - {0x1E5E, "HM70"}, - {0x1E5F, "NM70"}, -}; - -static void report_pch_info(struct udevice *dev) -{ - const char *pch_type = "Unknown"; - int i; - u16 dev_id; - uint8_t rev_id; - - dm_pci_read_config16(dev, 2, &dev_id); - for (i = 0; i < ARRAY_SIZE(pch_table); i++) { - if (pch_table[i].dev_id == dev_id) { - pch_type = pch_table[i].dev_name; - break; - } - } - dm_pci_read_config8(dev, 8, &rev_id); - debug("PCH type: %s, device id: %x, rev id %x\n", pch_type, dev_id, - rev_id); -} - -void report_platform_info(struct udevice *dev) -{ - report_cpu_info(); - report_pch_info(dev); -} diff --git a/arch/x86/cpu/ivybridge/sata.c b/arch/x86/cpu/ivybridge/sata.c index a59d9edce5..c3d1057c29 100644 --- a/arch/x86/cpu/ivybridge/sata.c +++ b/arch/x86/cpu/ivybridge/sata.c @@ -9,28 +9,13 @@ #include <dm.h> #include <fdtdec.h> #include <asm/io.h> +#include <asm/pch_common.h> #include <asm/pci.h> #include <asm/arch/pch.h> #include <asm/arch/bd82x6x.h> DECLARE_GLOBAL_DATA_PTR; -static inline u32 sir_read(struct udevice *dev, int idx) -{ - u32 data; - - dm_pci_write_config32(dev, SATA_SIRI, idx); - dm_pci_read_config32(dev, SATA_SIRD, &data); - - return data; -} - -static inline void sir_write(struct udevice *dev, int idx, u32 value) -{ - dm_pci_write_config32(dev, SATA_SIRI, idx); - dm_pci_write_config32(dev, SATA_SIRD, value); -} - static void common_sata_init(struct udevice *dev, unsigned int port_map) { u32 reg32; @@ -177,27 +162,27 @@ static void bd82x6x_sata_init(struct udevice *dev, struct udevice *pch) pch_iobp_update(pch, SATA_IOBP_SP1G3IR, 0, port_tx); /* Additional Programming Requirements */ - sir_write(dev, 0x04, 0x00001600); - sir_write(dev, 0x28, 0xa0000033); - reg32 = sir_read(dev, 0x54); + pch_common_sir_write(dev, 0x04, 0x00001600); + pch_common_sir_write(dev, 0x28, 0xa0000033); + reg32 = pch_common_sir_read(dev, 0x54); reg32 &= 0xff000000; reg32 |= 0x5555aa; - sir_write(dev, 0x54, reg32); - sir_write(dev, 0x64, 0xcccc8484); - reg32 = sir_read(dev, 0x68); + pch_common_sir_write(dev, 0x54, reg32); + pch_common_sir_write(dev, 0x64, 0xcccc8484); + reg32 = pch_common_sir_read(dev, 0x68); reg32 &= 0xffff0000; reg32 |= 0xcccc; - sir_write(dev, 0x68, reg32); - reg32 = sir_read(dev, 0x78); + pch_common_sir_write(dev, 0x68, reg32); + reg32 = pch_common_sir_read(dev, 0x78); reg32 &= 0x0000ffff; reg32 |= 0x88880000; - sir_write(dev, 0x78, reg32); - sir_write(dev, 0x84, 0x001c7000); - sir_write(dev, 0x88, 0x88338822); - sir_write(dev, 0xa0, 0x001c7000); - sir_write(dev, 0xc4, 0x0c0c0c0c); - sir_write(dev, 0xc8, 0x0c0c0c0c); - sir_write(dev, 0xd4, 0x10000000); + pch_common_sir_write(dev, 0x78, reg32); + pch_common_sir_write(dev, 0x84, 0x001c7000); + pch_common_sir_write(dev, 0x88, 0x88338822); + pch_common_sir_write(dev, 0xa0, 0x001c7000); + pch_common_sir_write(dev, 0xc4, 0x0c0c0c0c); + pch_common_sir_write(dev, 0xc8, 0x0c0c0c0c); + pch_common_sir_write(dev, 0xd4, 0x10000000); pch_iobp_update(pch, 0xea004001, 0x3fffffff, 0xc0000000); pch_iobp_update(pch, 0xea00408a, 0xfffffcff, 0x00000100); @@ -229,11 +214,9 @@ static int bd82x6x_sata_probe(struct udevice *dev) struct udevice *pch; int ret; - ret = uclass_first_device(UCLASS_PCH, &pch); + ret = uclass_first_device_err(UCLASS_PCH, &pch); if (ret) return ret; - if (!pch) - return -ENODEV; if (!(gd->flags & GD_FLG_RELOC)) bd82x6x_sata_enable(dev); diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index e23c422cd0..e35e543c3e 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -23,9 +23,12 @@ #include <asm/processor.h> #include <asm/gpio.h> #include <asm/global_data.h> +#include <asm/intel_regs.h> #include <asm/mrccache.h> +#include <asm/mrc_common.h> #include <asm/mtrr.h> #include <asm/pci.h> +#include <asm/report_platform.h> #include <asm/arch/me.h> #include <asm/arch/pei_data.h> #include <asm/arch/pch.h> @@ -38,57 +41,14 @@ DECLARE_GLOBAL_DATA_PTR; #define CMOS_OFFSET_MRC_SEED_S3 156 #define CMOS_OFFSET_MRC_SEED_CHK 160 -/* - * This function looks for the highest region of memory lower than 4GB which - * has enough space for U-Boot where U-Boot is aligned on a page boundary. - * It overrides the default implementation found elsewhere which simply - * picks the end of ram, wherever that may be. The location of the stack, - * the relocation address, and how far U-Boot is moved by relocation are - * set in the global data structure. - */ ulong board_get_usable_ram_top(ulong total_size) { - struct memory_info *info = &gd->arch.meminfo; - uintptr_t dest_addr = 0; - struct memory_area *largest = NULL; - int i; - - /* Find largest area of memory below 4GB */ - - for (i = 0; i < info->num_areas; i++) { - struct memory_area *area = &info->area[i]; - - if (area->start >= 1ULL << 32) - continue; - if (!largest || area->size > largest->size) - largest = area; - } - - /* If no suitable area was found, return an error. */ - assert(largest); - if (!largest || largest->size < (2 << 20)) - panic("No available memory found for relocation"); - - dest_addr = largest->start + largest->size; - - return (ulong)dest_addr; + return mrc_common_board_get_usable_ram_top(total_size); } void dram_init_banksize(void) { - struct memory_info *info = &gd->arch.meminfo; - int num_banks; - int i; - - for (i = 0, num_banks = 0; i < info->num_areas; i++) { - struct memory_area *area = &info->area[i]; - - if (area->start >= 1ULL << 32) - continue; - gd->bd->bi_dram[num_banks].start = area->start; - gd->bd->bi_dram[num_banks].size = area->size; - num_banks++; - } + mrc_common_dram_init_banksize(); } static int read_seed_from_cmos(struct pei_data *pei_data) @@ -215,164 +175,10 @@ int misc_init_r(void) return 0; } -static const char *const ecc_decoder[] = { - "inactive", - "active on IO", - "disabled on IO", - "active" -}; - -/* - * Dump in the log memory controller configuration as read from the memory - * controller registers. - */ -static void report_memory_config(void) +static void post_system_agent_init(struct udevice *dev, struct udevice *me_dev, + struct pei_data *pei_data) { - u32 addr_decoder_common, addr_decode_ch[2]; - int i; - - addr_decoder_common = readl(MCHBAR_REG(0x5000)); - addr_decode_ch[0] = readl(MCHBAR_REG(0x5004)); - addr_decode_ch[1] = readl(MCHBAR_REG(0x5008)); - - debug("memcfg DDR3 clock %d MHz\n", - (readl(MCHBAR_REG(0x5e04)) * 13333 * 2 + 50) / 100); - debug("memcfg channel assignment: A: %d, B % d, C % d\n", - addr_decoder_common & 3, - (addr_decoder_common >> 2) & 3, - (addr_decoder_common >> 4) & 3); - - for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) { - u32 ch_conf = addr_decode_ch[i]; - debug("memcfg channel[%d] config (%8.8x):\n", i, ch_conf); - debug(" ECC %s\n", ecc_decoder[(ch_conf >> 24) & 3]); - debug(" enhanced interleave mode %s\n", - ((ch_conf >> 22) & 1) ? "on" : "off"); - debug(" rank interleave %s\n", - ((ch_conf >> 21) & 1) ? "on" : "off"); - debug(" DIMMA %d MB width x%d %s rank%s\n", - ((ch_conf >> 0) & 0xff) * 256, - ((ch_conf >> 19) & 1) ? 16 : 8, - ((ch_conf >> 17) & 1) ? "dual" : "single", - ((ch_conf >> 16) & 1) ? "" : ", selected"); - debug(" DIMMB %d MB width x%d %s rank%s\n", - ((ch_conf >> 8) & 0xff) * 256, - ((ch_conf >> 20) & 1) ? 16 : 8, - ((ch_conf >> 18) & 1) ? "dual" : "single", - ((ch_conf >> 16) & 1) ? ", selected" : ""); - } -} - -static void post_system_agent_init(struct pei_data *pei_data) -{ - /* If PCIe init is skipped, set the PEG clock gating */ - if (!pei_data->pcie_init) - setbits_le32(MCHBAR_REG(0x7010), 1); -} - -static asmlinkage void console_tx_byte(unsigned char byte) -{ -#ifdef DEBUG - putc(byte); -#endif -} - -static int recovery_mode_enabled(void) -{ - return false; -} - -/** - * Find the PEI executable in the ROM and execute it. - * - * @dev: Northbridge device - * @pei_data: configuration data for UEFI PEI reference code - */ -int sdram_initialise(struct udevice *dev, struct udevice *me_dev, - struct pei_data *pei_data) -{ - unsigned version; - const char *data; uint16_t done; - int ret; - - report_platform_info(dev); - - /* Wait for ME to be ready */ - ret = intel_early_me_init(me_dev); - if (ret) - return ret; - ret = intel_early_me_uma_size(me_dev); - if (ret < 0) - return ret; - - debug("Starting UEFI PEI System Agent\n"); - - /* - * Do not pass MRC data in for recovery mode boot, - * Always pass it in for S3 resume. - */ - if (!recovery_mode_enabled() || - pei_data->boot_mode == PEI_BOOT_RESUME) { - ret = prepare_mrc_cache(pei_data); - if (ret) - debug("prepare_mrc_cache failed: %d\n", ret); - } - - /* If MRC data is not found we cannot continue S3 resume. */ - if (pei_data->boot_mode == PEI_BOOT_RESUME && !pei_data->mrc_input) { - debug("Giving up in sdram_initialize: No MRC data\n"); - reset_cpu(0); - } - - /* Pass console handler in pei_data */ - pei_data->tx_byte = console_tx_byte; - - debug("PEI data at %p, size %x:\n", pei_data, sizeof(*pei_data)); - - data = (char *)CONFIG_X86_MRC_ADDR; - if (data) { - int rv; - int (*func)(struct pei_data *); - ulong start; - - debug("Calling MRC at %p\n", data); - post_code(POST_PRE_MRC); - start = get_timer(0); - func = (int (*)(struct pei_data *))data; - rv = func(pei_data); - post_code(POST_MRC); - if (rv) { - switch (rv) { - case -1: - printf("PEI version mismatch.\n"); - break; - case -2: - printf("Invalid memory frequency.\n"); - break; - default: - printf("MRC returned %x.\n", rv); - } - printf("Nonzero MRC return value.\n"); - return -EFAULT; - } - debug("MRC execution time %lu ms\n", get_timer(start)); - } else { - printf("UEFI PEI System Agent not found.\n"); - return -ENOSYS; - } - -#if CONFIG_USBDEBUG - /* mrc.bin reconfigures USB, so reinit it to have debug */ - early_usbdebug_init(); -#endif - - version = readl(MCHBAR_REG(0x5034)); - debug("System Agent Version %d.%d.%d Build %d\n", - version >> 24 , (version >> 16) & 0xff, - (version >> 8) & 0xff, version & 0xff); - debug("MRC output data length %#x at %p\n", pei_data->mrc_output_len, - pei_data->mrc_output); /* * Send ME init done for SandyBridge here. This is done inside the @@ -383,25 +189,16 @@ int sdram_initialise(struct udevice *dev, struct udevice *me_dev, if (BASE_REV_SNB == done) intel_early_me_init_done(dev, me_dev, ME_INIT_STATUS_SUCCESS); else - intel_early_me_status(me_dev); - - post_system_agent_init(pei_data); - report_memory_config(); + intel_me_status(me_dev); - /* S3 resume: don't save scrambler seed or MRC data */ - if (pei_data->boot_mode != PEI_BOOT_RESUME) { - /* - * This will be copied to SDRAM in reserve_arch(), then written - * to SPI flash in mrccache_save() - */ - gd->arch.mrc_output = (char *)pei_data->mrc_output; - gd->arch.mrc_output_len = pei_data->mrc_output_len; - ret = write_seeds_to_cmos(pei_data); - if (ret) - debug("Failed to write seeds to CMOS: %d\n", ret); - } + /* If PCIe init is skipped, set the PEG clock gating */ + if (!pei_data->pcie_init) + setbits_le32(MCHBAR_REG(0x7010), 1); +} - return 0; +static int recovery_mode_enabled(void) +{ + return false; } int reserve_arch(void) @@ -409,87 +206,16 @@ int reserve_arch(void) return mrccache_reserve(); } -static int copy_spd(struct pei_data *peid) +static int copy_spd(struct udevice *dev, struct pei_data *peid) { - const int gpio_vector[] = {41, 42, 43, 10, -1}; - int spd_index; - const void *blob = gd->fdt_blob; - int node, spd_node; - int ret, i; - - for (i = 0; ; i++) { - if (gpio_vector[i] == -1) - break; - ret = gpio_requestf(gpio_vector[i], "spd_id%d", i); - if (ret) { - debug("%s: Could not request gpio %d\n", __func__, - gpio_vector[i]); - return ret; - } - } - spd_index = gpio_get_values_as_int(gpio_vector); - debug("spd index %d\n", spd_index); - node = fdtdec_next_compatible(blob, 0, COMPAT_MEMORY_SPD); - if (node < 0) { - printf("SPD data not found.\n"); - return -ENOENT; - } - - for (spd_node = fdt_first_subnode(blob, node); - spd_node > 0; - spd_node = fdt_next_subnode(blob, spd_node)) { - const char *data; - int len; - - if (fdtdec_get_int(blob, spd_node, "reg", -1) != spd_index) - continue; - data = fdt_getprop(blob, spd_node, "data", &len); - if (len < sizeof(peid->spd_data[0])) { - printf("Missing SPD data\n"); - return -EINVAL; - } - - debug("Using SDRAM SPD data for '%s'\n", - fdt_get_name(blob, spd_node, NULL)); - memcpy(peid->spd_data[0], data, sizeof(peid->spd_data[0])); - break; - } - - if (spd_node < 0) { - printf("No SPD data found for index %d\n", spd_index); - return -ENOENT; - } + const void *data; + int ret; - return 0; -} + ret = mrc_locate_spd(dev, sizeof(peid->spd_data[0]), &data); + if (ret) + return ret; -/** - * add_memory_area() - Add a new usable memory area to our list - * - * Note: @start and @end must not span the first 4GB boundary - * - * @info: Place to store memory info - * @start: Start of this memory area - * @end: End of this memory area + 1 - */ -static int add_memory_area(struct memory_info *info, - uint64_t start, uint64_t end) -{ - struct memory_area *ptr; - - if (info->num_areas == CONFIG_NR_DRAM_BANKS) - return -ENOSPC; - - ptr = &info->area[info->num_areas]; - ptr->start = start; - ptr->size = end - start; - info->total_memory += ptr->size; - if (ptr->start < (1ULL << 32)) - info->total_32bit_memory += ptr->size; - debug("%d: memory %llx size %llx, total now %llx / %llx\n", - info->num_areas, ptr->start, ptr->size, - info->total_32bit_memory, info->total_memory); - info->num_areas++; + memcpy(peid->spd_data[0], data, sizeof(peid->spd_data[0])); return 0; } @@ -608,10 +334,10 @@ static int sdram_find(struct udevice *dev) debug("Available memory below 4GB: %lluM\n", tomk >> 10); /* Report the memory regions */ - add_memory_area(info, 1 << 20, 2 << 28); - add_memory_area(info, (2 << 28) + (2 << 20), 4 << 28); - add_memory_area(info, (4 << 28) + (2 << 20), tseg_base); - add_memory_area(info, 1ULL << 32, touud); + mrc_add_memory_area(info, 1 << 20, 2 << 28); + mrc_add_memory_area(info, (2 << 28) + (2 << 20), 4 << 28); + mrc_add_memory_area(info, (4 << 28) + (2 << 20), tseg_base); + mrc_add_memory_area(info, 1ULL << 32, touud); /* Add MTRRs for memory */ mtrr_add_request(MTRR_TYPE_WRBACK, 0, 2ULL << 30); @@ -680,9 +406,9 @@ static void rcba_config(void) int dram_init(void) { - struct pei_data pei_data __aligned(8) = { + struct pei_data _pei_data __aligned(8) = { .pei_version = PEI_VERSION, - .mchbar = DEFAULT_MCHBAR, + .mchbar = MCH_BASE_ADDRESS, .dmibar = DEFAULT_DMIBAR, .epbar = DEFAULT_EPBAR, .pciexbar = CONFIG_PCIE_ECAM_BASE, @@ -733,38 +459,84 @@ int dram_init(void) { 0, 4, 0x0000 }, /* P13= Empty */ }, }; + struct pei_data *pei_data = &_pei_data; struct udevice *dev, *me_dev; int ret; - ret = uclass_first_device(UCLASS_NORTHBRIDGE, &dev); + ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &dev); if (ret) return ret; - if (!dev) - return -ENODEV; ret = syscon_get_by_driver_data(X86_SYSCON_ME, &me_dev); if (ret) return ret; - debug("Boot mode %d\n", gd->arch.pei_boot_mode); - debug("mrc_input %p\n", pei_data.mrc_input); - pei_data.boot_mode = gd->arch.pei_boot_mode; - ret = copy_spd(&pei_data); - if (!ret) - ret = sdram_initialise(dev, me_dev, &pei_data); + ret = copy_spd(dev, pei_data); if (ret) return ret; + pei_data->boot_mode = gd->arch.pei_boot_mode; + debug("Boot mode %d\n", gd->arch.pei_boot_mode); + debug("mrc_input %p\n", pei_data->mrc_input); - rcba_config(); - quick_ram_check(); + /* + * Do not pass MRC data in for recovery mode boot, + * Always pass it in for S3 resume. + */ + if (!recovery_mode_enabled() || + pei_data->boot_mode == PEI_BOOT_RESUME) { + ret = prepare_mrc_cache(pei_data); + if (ret) + debug("prepare_mrc_cache failed: %d\n", ret); + } - writew(0xCAFE, MCHBAR_REG(SSKPD)); + /* If MRC data is not found we cannot continue S3 resume. */ + if (pei_data->boot_mode == PEI_BOOT_RESUME && !pei_data->mrc_input) { + debug("Giving up in sdram_initialize: No MRC data\n"); + reset_cpu(0); + } - post_code(POST_DRAM); + /* Pass console handler in pei_data */ + pei_data->tx_byte = sdram_console_tx_byte; - ret = sdram_find(dev); + /* Wait for ME to be ready */ + ret = intel_early_me_init(me_dev); if (ret) return ret; + ret = intel_early_me_uma_size(me_dev); + if (ret < 0) + return ret; + ret = mrc_common_init(dev, pei_data, false); + if (ret) + return ret; + + ret = sdram_find(dev); + if (ret) + return ret; gd->ram_size = gd->arch.meminfo.total_32bit_memory; + debug("MRC output data length %#x at %p\n", pei_data->mrc_output_len, + pei_data->mrc_output); + + post_system_agent_init(dev, me_dev, pei_data); + report_memory_config(); + + /* S3 resume: don't save scrambler seed or MRC data */ + if (pei_data->boot_mode != PEI_BOOT_RESUME) { + /* + * This will be copied to SDRAM in reserve_arch(), then written + * to SPI flash in mrccache_save() + */ + gd->arch.mrc_output = (char *)pei_data->mrc_output; + gd->arch.mrc_output_len = pei_data->mrc_output_len; + ret = write_seeds_to_cmos(pei_data); + if (ret) + debug("Failed to write seeds to CMOS: %d\n", ret); + } + + writew(0xCAFE, MCHBAR_REG(SSKPD)); + if (ret) + return ret; + + rcba_config(); + return 0; } |