From 5bf935925ba48711b1bf3e17338b6f2faf74f39d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Thu, 1 Oct 2015 00:36:03 -0700 Subject: x86: ivybridge: Remove the dead codes that programs pci bridge Remove bd82x6x_pci_bus_enable_resources() that is not called anywhere. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/ivybridge/bd82x6x.c | 32 -------------------------------- 1 file changed, 32 deletions(-) (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/ivybridge/bd82x6x.c b/arch/x86/cpu/ivybridge/bd82x6x.c index ca8cccff94..3e7a907e00 100644 --- a/arch/x86/cpu/ivybridge/bd82x6x.c +++ b/arch/x86/cpu/ivybridge/bd82x6x.c @@ -55,38 +55,6 @@ void bd82x6x_pci_init(pci_dev_t dev) x86_pci_write_config16(dev, SECSTS, reg16); } -#define PCI_BRIDGE_UPDATE_COMMAND -void bd82x6x_pci_dev_enable_resources(pci_dev_t dev) -{ - uint16_t command; - - command = x86_pci_read_config16(dev, PCI_COMMAND); - command |= PCI_COMMAND_IO; -#ifdef PCI_BRIDGE_UPDATE_COMMAND - /* - * If we write to PCI_COMMAND, on some systems this will cause the - * ROM and APICs to become invisible. - */ - debug("%x cmd <- %02x\n", dev, command); - x86_pci_write_config16(dev, PCI_COMMAND, command); -#else - printf("%s cmd <- %02x (NOT WRITTEN!)\n", dev_path(dev), command); -#endif -} - -void bd82x6x_pci_bus_enable_resources(pci_dev_t dev) -{ - uint16_t ctrl; - - ctrl = x86_pci_read_config16(dev, PCI_BRIDGE_CONTROL); - ctrl |= PCI_COMMAND_IO; - ctrl |= PCI_BRIDGE_CTL_VGA; - debug("%x bridge ctrl <- %04x\n", dev, ctrl); - x86_pci_write_config16(dev, PCI_BRIDGE_CONTROL, ctrl); - - bd82x6x_pci_dev_enable_resources(dev); -} - static int bd82x6x_probe(struct udevice *dev) { const void *blob = gd->fdt_blob; -- cgit v1.2.1 From 1f124eba11cb1619e6d575770756230484e47bf7 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Thu, 1 Oct 2015 00:36:04 -0700 Subject: x86: Allow disabling IGD on Intel Queensbay Add a Kconfig option to disable the Integrated Graphics Device (IGD) so that it does not show in the PCI configuration space as a VGA disaplay controller. This gives a chance for U-Boot to run PCI/PCIe based graphics card's VGA BIOS and use that for the graphics console. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/queensbay/Kconfig | 8 ++++++++ arch/x86/cpu/queensbay/tnc.c | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+) (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/queensbay/Kconfig b/arch/x86/cpu/queensbay/Kconfig index fbf85f233f..6136d75422 100644 --- a/arch/x86/cpu/queensbay/Kconfig +++ b/arch/x86/cpu/queensbay/Kconfig @@ -42,4 +42,12 @@ config CPU_ADDR_BITS int default 32 +config DISABLE_IGD + bool "Disable Integrated Graphics Device (IGD)" + help + Disable the Integrated Graphics Device (IGD) so that it does not + show in the PCI configuration space as a VGA disaplay controller. + This gives a chance for U-Boot to run PCI/PCIe based graphics + card's VGA BIOS and use that card for the graphics console. + endif diff --git a/arch/x86/cpu/queensbay/tnc.c b/arch/x86/cpu/queensbay/tnc.c index 9682cfff26..0c02a44f63 100644 --- a/arch/x86/cpu/queensbay/tnc.c +++ b/arch/x86/cpu/queensbay/tnc.c @@ -23,6 +23,16 @@ static void unprotect_spi_flash(void) x86_pci_write_config32(TNC_LPC, 0xd8, bc); } +static void __maybe_unused disable_igd(void) +{ + u32 gc; + + gc = x86_pci_read_config32(TNC_IGD, IGD_GC); + gc &= ~GMS_MASK; + gc |= VGA_DISABLE; + x86_pci_write_config32(TNC_IGD, IGD_GC, gc); +} + int arch_cpu_init(void) { int ret; @@ -39,6 +49,15 @@ int arch_cpu_init(void) return 0; } +int arch_early_init_r(void) +{ +#ifdef CONFIG_DISABLE_IGD + disable_igd(); +#endif + + return 0; +} + void cpu_irq_init(void) { struct tnc_rcba *rcba; -- cgit v1.2.1 From 19038e1bb629a365aaf971a65744e2f0e8866d62 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 7 Oct 2015 20:19:09 -0700 Subject: x86: Initialize GDT entry 1 to be the 32-bit CS as well Some OS (like VxWorks) requires GDT entry 1 to be the 32-bit CS. Signed-off-by: Bin Meng Acked-by: Simon Glass Tested-by: Jian Luo --- arch/x86/cpu/cpu.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 1b76ca117e..812c5e4e6b 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -142,7 +142,12 @@ void arch_setup_gd(gd_t *new_gd) gdt_addr = new_gd->arch.gdt; - /* CS: code, read/execute, 4 GB, base 0 */ + /* + * CS: code, read/execute, 4 GB, base 0 + * + * Some OS (like VxWorks) requires GDT entry 1 to be the 32-bit CS + */ + gdt_addr[X86_GDT_ENTRY_UNUSED] = GDT_ENTRY(0xc09b, 0, 0xfffff); gdt_addr[X86_GDT_ENTRY_32BIT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff); /* DS: data, read/write, 4 GB, base 0 */ -- cgit v1.2.1 From f6220f1a86109f88950fd42e3af54314de24365a Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 11 Oct 2015 21:37:36 -0700 Subject: x86: Move mrccache.[c|h] to a common place mrccache implementation can be common for all boards. Move it from ivybridge cpu directory to the common lib directory. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/ivybridge/Makefile | 1 - arch/x86/cpu/ivybridge/mrccache.c | 157 -------------------------------------- arch/x86/cpu/ivybridge/sdram.c | 2 +- 3 files changed, 1 insertion(+), 159 deletions(-) delete mode 100644 arch/x86/cpu/ivybridge/mrccache.c (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index 3576b83266..0c7efaec7c 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -14,7 +14,6 @@ obj-y += lpc.o obj-y += me_status.o obj-y += model_206ax.o obj-y += microcode_intel.o -obj-y += mrccache.o obj-y += northbridge.o obj-y += pch.o obj-y += pci.o diff --git a/arch/x86/cpu/ivybridge/mrccache.c b/arch/x86/cpu/ivybridge/mrccache.c deleted file mode 100644 index 92054948eb..0000000000 --- a/arch/x86/cpu/ivybridge/mrccache.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * From Coreboot src/southbridge/intel/bd82x6x/mrccache.c - * - * Copyright (C) 2014 Google Inc. - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static struct mrc_data_container *next_mrc_block( - struct mrc_data_container *mrc_cache) -{ - /* MRC data blocks are aligned within the region */ - u32 mrc_size = sizeof(*mrc_cache) + mrc_cache->data_size; - if (mrc_size & (MRC_DATA_ALIGN - 1UL)) { - mrc_size &= ~(MRC_DATA_ALIGN - 1UL); - mrc_size += MRC_DATA_ALIGN; - } - - u8 *region_ptr = (u8 *)mrc_cache; - region_ptr += mrc_size; - return (struct mrc_data_container *)region_ptr; -} - -static int is_mrc_cache(struct mrc_data_container *cache) -{ - return cache && (cache->signature == MRC_DATA_SIGNATURE); -} - -/* - * Find the largest index block in the MRC cache. Return NULL if none is - * found. - */ -struct mrc_data_container *mrccache_find_current(struct fmap_entry *entry) -{ - struct mrc_data_container *cache, *next; - ulong base_addr, end_addr; - uint id; - - base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset; - end_addr = base_addr + entry->length; - cache = NULL; - - /* Search for the last filled entry in the region */ - for (id = 0, next = (struct mrc_data_container *)base_addr; - is_mrc_cache(next); - id++) { - cache = next; - next = next_mrc_block(next); - if ((ulong)next >= end_addr) - break; - } - - if (id-- == 0) { - debug("%s: No valid MRC cache found.\n", __func__); - return NULL; - } - - /* Verify checksum */ - if (cache->checksum != compute_ip_checksum(cache->data, - cache->data_size)) { - printf("%s: MRC cache checksum mismatch\n", __func__); - return NULL; - } - - debug("%s: picked entry %u from cache block\n", __func__, id); - - return cache; -} - -/** - * find_next_mrc_cache() - get next cache entry - * - * @entry: MRC cache flash area - * @cache: Entry to start from - * - * @return next cache entry if found, NULL if we got to the end - */ -static struct mrc_data_container *find_next_mrc_cache(struct fmap_entry *entry, - struct mrc_data_container *cache) -{ - ulong base_addr, end_addr; - - base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset; - end_addr = base_addr + entry->length; - - cache = next_mrc_block(cache); - if ((ulong)cache >= end_addr) { - /* Crossed the boundary */ - cache = NULL; - debug("%s: no available entries found\n", __func__); - } else { - debug("%s: picked next entry from cache block at %p\n", - __func__, cache); - } - - return cache; -} - -int mrccache_update(struct udevice *sf, struct fmap_entry *entry, - struct mrc_data_container *cur) -{ - struct mrc_data_container *cache; - ulong offset; - ulong base_addr; - int ret; - - /* Find the last used block */ - base_addr = (1ULL << 32) - CONFIG_ROM_SIZE + entry->offset; - debug("Updating MRC cache data\n"); - cache = mrccache_find_current(entry); - if (cache && (cache->data_size == cur->data_size) && - (!memcmp(cache, cur, cache->data_size + sizeof(*cur)))) { - debug("MRC data in flash is up to date. No update\n"); - return -EEXIST; - } - - /* Move to the next block, which will be the first unused block */ - if (cache) - cache = find_next_mrc_cache(entry, cache); - - /* - * If we have got to the end, erase the entire mrc-cache area and start - * again at block 0. - */ - if (!cache) { - debug("Erasing the MRC cache region of %x bytes at %x\n", - entry->length, entry->offset); - - ret = spi_flash_erase_dm(sf, entry->offset, entry->length); - if (ret) { - debug("Failed to erase flash region\n"); - return ret; - } - cache = (struct mrc_data_container *)base_addr; - } - - /* Write the data out */ - offset = (ulong)cache - base_addr + entry->offset; - debug("Write MRC cache update to flash at %lx\n", offset); - ret = spi_flash_write_dm(sf, offset, cur->data_size + sizeof(*cur), - cur); - if (ret) { - debug("Failed to write to SPI flash\n"); - return ret; - } - - return 0; -} diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index 7f3b13d357..10fbe5fb36 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -21,10 +21,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include -- cgit v1.2.1 From 42913a1c7ad6efae598364f5ea1ae083279b571f Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 11 Oct 2015 21:37:40 -0700 Subject: x86: ivybridge: Use APIs provided in the mrccache lib Remove the call to custom mrc cache APIs, and use the ones provided in the mrccache lib. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/ivybridge/sdram.c | 112 ++--------------------------------------- 1 file changed, 4 insertions(+), 108 deletions(-) (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index 10fbe5fb36..20c2e68910 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -89,42 +89,6 @@ void dram_init_banksize(void) } } -static int get_mrc_entry(struct udevice **devp, struct fmap_entry *entry) -{ - const void *blob = gd->fdt_blob; - int node, spi_node, mrc_node; - int upto; - int ret; - - /* Find the flash chip within the SPI controller node */ - upto = 0; - spi_node = fdtdec_next_alias(blob, "spi", COMPAT_INTEL_ICH_SPI, &upto); - if (spi_node < 0) - return -ENOENT; - node = fdt_first_subnode(blob, spi_node); - if (node < 0) - return -ECHILD; - - /* Find the place where we put the MRC cache */ - mrc_node = fdt_subnode_offset(blob, node, "rw-mrc-cache"); - if (mrc_node < 0) - return -EPERM; - - if (fdtdec_read_fmap_entry(blob, mrc_node, "rm-mrc-cache", entry)) - return -EINVAL; - - if (devp) { - debug("getting sf\n"); - ret = uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node, - devp); - debug("ret = %d\n", ret); - if (ret) - return ret; - } - - return 0; -} - static int read_seed_from_cmos(struct pei_data *pei_data) { u16 c1, c2, checksum, seed_checksum; @@ -180,7 +144,7 @@ static int prepare_mrc_cache(struct pei_data *pei_data) ret = read_seed_from_cmos(pei_data); if (ret) return ret; - ret = get_mrc_entry(NULL, &entry); + ret = mrccache_get_region(NULL, &entry); if (ret) return ret; mrc_cache = mrccache_find_current(&entry); @@ -202,32 +166,6 @@ static int prepare_mrc_cache(struct pei_data *pei_data) return 0; } -static int build_mrc_data(struct mrc_data_container **datap) -{ - struct mrc_data_container *data; - int orig_len; - int output_len; - - orig_len = gd->arch.mrc_output_len; - output_len = ALIGN(orig_len, 16); - data = malloc(output_len + sizeof(*data)); - if (!data) - return -ENOMEM; - data->signature = MRC_DATA_SIGNATURE; - data->data_size = output_len; - data->reserved = 0; - memcpy(data->data, gd->arch.mrc_output, orig_len); - - /* Zero the unused space in aligned buffer. */ - if (output_len > orig_len) - memset(data->data + orig_len, 0, output_len - orig_len); - - data->checksum = compute_ip_checksum(data->data, output_len); - *datap = data; - - return 0; -} - static int write_seeds_to_cmos(struct pei_data *pei_data) { u16 c1, c2, checksum; @@ -262,42 +200,12 @@ static int write_seeds_to_cmos(struct pei_data *pei_data) return 0; } -static int sdram_save_mrc_data(void) -{ - struct mrc_data_container *data; - struct fmap_entry entry; - struct udevice *sf; - int ret; - - if (!gd->arch.mrc_output_len) - return 0; - debug("Saving %d bytes of MRC output data to SPI flash\n", - gd->arch.mrc_output_len); - - ret = get_mrc_entry(&sf, &entry); - if (ret) - goto err_entry; - ret = build_mrc_data(&data); - if (ret) - goto err_data; - ret = mrccache_update(sf, &entry, data); - if (!ret) - debug("Saved MRC data with checksum %04x\n", data->checksum); - - free(data); -err_data: -err_entry: - if (ret) - debug("%s: Failed: %d\n", __func__, ret); - return ret; -} - /* Use this hook to save our SDRAM parameters */ int misc_init_r(void) { int ret; - ret = sdram_save_mrc_data(); + ret = mrccache_save(); if (ret) printf("Unable to save MRC data: %d\n", ret); @@ -476,7 +384,7 @@ int sdram_initialise(struct pei_data *pei_data) if (pei_data->boot_mode != PEI_BOOT_RESUME) { /* * This will be copied to SDRAM in reserve_arch(), then written - * to SPI flash in sdram_save_mrc_data() + * 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; @@ -490,19 +398,7 @@ int sdram_initialise(struct pei_data *pei_data) int reserve_arch(void) { - u16 checksum; - - checksum = compute_ip_checksum(gd->arch.mrc_output, - gd->arch.mrc_output_len); - debug("Saving %d bytes for MRC output data, checksum %04x\n", - gd->arch.mrc_output_len, checksum); - gd->start_addr_sp -= gd->arch.mrc_output_len; - memcpy((void *)gd->start_addr_sp, gd->arch.mrc_output, - gd->arch.mrc_output_len); - gd->arch.mrc_output = (char *)gd->start_addr_sp; - gd->start_addr_sp &= ~0xf; - - return 0; + return mrccache_reserve(); } static int copy_spd(struct pei_data *peid) -- cgit v1.2.1 From 4b9f6a669ee22ac4694a3a339e94e8fe30bfad1f Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 11 Oct 2015 21:37:41 -0700 Subject: x86: Use struct mrc_region to describe a mrc region Currently struct fmap_entry is used to describe a mrc region. However this structure contains some other fields that are not related to mrc cache and causes confusion. Besides, it does not include a base address field to store SPI flash's base address. Instead in the mrccache.c it tries to use CONFIG_ROM_SIZE to calculate the SPI flash base address, which unfortunately is not 100% correct as CONFIG_ROM_SIZE may not match the whole SPI flash size. Define a new struct mrc_region and use it instead. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/ivybridge/sdram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index 20c2e68910..9121426cae 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -138,7 +138,7 @@ static int read_seed_from_cmos(struct pei_data *pei_data) static int prepare_mrc_cache(struct pei_data *pei_data) { struct mrc_data_container *mrc_cache; - struct fmap_entry entry; + struct mrc_region entry; int ret; ret = read_seed_from_cmos(pei_data); -- cgit v1.2.1 From 8b185041a9f4c30dc5edb1e04c0834e931b8633f Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 11 Oct 2015 21:37:43 -0700 Subject: x86: baytrail: Save mrc cache to spi flash Save MRC cache to SPI flash in arch_misc_init(). Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/baytrail/valleyview.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/baytrail/valleyview.c b/arch/x86/cpu/baytrail/valleyview.c index 4baaae62ff..215e0d0e2d 100644 --- a/arch/x86/cpu/baytrail/valleyview.c +++ b/arch/x86/cpu/baytrail/valleyview.c @@ -8,6 +8,7 @@ #include #include #include +#include #include static struct pci_device_id mmc_supported[] = { @@ -43,6 +44,24 @@ int arch_misc_init(void) if (!ll_boot_init()) return 0; +#ifdef CONFIG_ENABLE_MRC_CACHE + /* + * We intend not to check any return value here, as even MRC cache + * is not saved successfully, it is not a severe error that will + * prevent system from continuing to boot. + */ + mrccache_save(); +#endif + return pirq_init(); } + +int reserve_arch(void) +{ +#ifdef CONFIG_ENABLE_MRC_CACHE + return mrccache_reserve(); +#else + return 0; +#endif +} #endif -- cgit v1.2.1 From 74e56d19534f85a0f7d3c84f6d692534f2e1d9b5 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 11 Oct 2015 21:37:45 -0700 Subject: x86: baytrail: Issue full system reset in reset_cpu() With MRC cache enabled, when typing 'reset' in the U-Boot shell, BayTrail FSP initialization hangs at "Configuring Memory Start": Setting BootMode to 0 Install PPI: 1F4C6F90-B06B-48D8-A201-BAE5F1CD7D56 Register PPI Notify: F894643D-C449-42D1-8EA8-85BDD8C65BDE About to call MrcInit(); BayleyBay Platform Type CurrentMrcData.BootMode = 4 Taking Fastboot path! Configuring Memory Start... Changing reset_cpu() to do a full system reset fixes this issue. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/baytrail/valleyview.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/baytrail/valleyview.c b/arch/x86/cpu/baytrail/valleyview.c index 215e0d0e2d..a009c14bd9 100644 --- a/arch/x86/cpu/baytrail/valleyview.c +++ b/arch/x86/cpu/baytrail/valleyview.c @@ -65,3 +65,9 @@ int reserve_arch(void) #endif } #endif + +void reset_cpu(ulong addr) +{ + /* cold reset */ + x86_full_reset(); +} -- cgit v1.2.1 From c6c80d8b3e8d35a6c025abfd14606e8ac21aea30 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 11 Oct 2015 21:37:47 -0700 Subject: x86: ivybridge: Correct two typos for MRC It should be MRC, not MCR. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/ivybridge/sdram.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index 9121426cae..fc66a3c3a5 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -363,7 +363,7 @@ int sdram_initialise(struct pei_data *pei_data) debug("System Agent Version %d.%d.%d Build %d\n", version >> 24 , (version >> 16) & 0xff, (version >> 8) & 0xff, version & 0xff); - debug("MCR output data length %#x at %p\n", pei_data->mrc_output_len, + debug("MRC output data length %#x at %p\n", pei_data->mrc_output_len, pei_data->mrc_output); /* @@ -723,7 +723,7 @@ int dram_init(void) int ret; debug("Boot mode %d\n", gd->arch.pei_boot_mode); - debug("mcr_input %p\n", pei_data.mrc_input); + 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) -- cgit v1.2.1 From 2fc2b83a7da61d81eee9ceaad9b3b07174838793 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 12 Oct 2015 01:30:42 -0700 Subject: x86: quark: Implement mrc cache Using existing mrccache library to implement mrc cache support for Intel Quark. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/quark/dram.c | 52 +++++++++++++++++++++++++++++++++++++++------- arch/x86/cpu/quark/quark.c | 19 +++++++++++++++++ 2 files changed, 64 insertions(+), 7 deletions(-) (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/quark/dram.c b/arch/x86/cpu/quark/dram.c index 1b89376387..40c830af96 100644 --- a/arch/x86/cpu/quark/dram.c +++ b/arch/x86/cpu/quark/dram.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include #include @@ -15,6 +17,29 @@ DECLARE_GLOBAL_DATA_PTR; +static __maybe_unused int prepare_mrc_cache(struct mrc_params *mrc_params) +{ + struct mrc_data_container *cache; + struct mrc_region entry; + int ret; + + ret = mrccache_get_region(NULL, &entry); + if (ret) + return ret; + + cache = mrccache_find_current(&entry); + if (!cache) + return -ENOENT; + + debug("%s: mrc cache at %p, size %x checksum %04x\n", __func__, + cache->data, cache->data_size, cache->checksum); + + /* copy mrc cache to the mrc_params */ + memcpy(&mrc_params->timings, cache->data, cache->data_size); + + return 0; +} + static int mrc_configure_params(struct mrc_params *mrc_params) { const void *blob = gd->fdt_blob; @@ -27,14 +52,15 @@ static int mrc_configure_params(struct mrc_params *mrc_params) return -EINVAL; } - /* - * TODO: - * - * We need support fast boot (MRC cache) in the future. - * - * Set boot mode to cold boot for now - */ +#ifdef CONFIG_ENABLE_MRC_CACHE + mrc_params->boot_mode = prepare_mrc_cache(mrc_params); + if (mrc_params->boot_mode) + mrc_params->boot_mode = BM_COLD; + else + mrc_params->boot_mode = BM_FAST; +#else mrc_params->boot_mode = BM_COLD; +#endif /* * TODO: @@ -98,6 +124,9 @@ static int mrc_configure_params(struct mrc_params *mrc_params) int dram_init(void) { struct mrc_params mrc_params; +#ifdef CONFIG_ENABLE_MRC_CACHE + char *cache; +#endif int ret; memset(&mrc_params, 0, sizeof(struct mrc_params)); @@ -121,6 +150,15 @@ int dram_init(void) (~(gd->ram_size - 1)) | MTRR_PHYS_MASK_VALID); enable_caches(); +#ifdef CONFIG_ENABLE_MRC_CACHE + cache = malloc(sizeof(struct mrc_timings)); + if (cache) { + memcpy(cache, &mrc_params.timings, sizeof(struct mrc_timings)); + gd->arch.mrc_output = cache; + gd->arch.mrc_output_len = sizeof(struct mrc_timings); + } +#endif + return 0; } diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c index 77d644a491..f737e1921f 100644 --- a/arch/x86/cpu/quark/quark.c +++ b/arch/x86/cpu/quark/quark.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -368,6 +369,15 @@ void cpu_irq_init(void) int arch_misc_init(void) { +#ifdef CONFIG_ENABLE_MRC_CACHE + /* + * We intend not to check any return value here, as even MRC cache + * is not saved successfully, it is not a severe error that will + * prevent system from continuing to boot. + */ + mrccache_save(); +#endif + return pirq_init(); } @@ -390,3 +400,12 @@ void board_final_cleanup(void) return; } + +int reserve_arch(void) +{ +#ifdef CONFIG_ENABLE_MRC_CACHE + return mrccache_reserve(); +#else + return 0; +#endif +} -- cgit v1.2.1 From ef1683d5c36d4906eefd802863ddf4798c0f2a31 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 14 Oct 2015 02:01:21 -0700 Subject: x86: Pass correct cpu_index to ap_init() In sipi_vector.S, cpu_index (passed as %eax) is wrongly overwritten by the ap_init() function address. Correct it. Signed-off-by: Bin Meng Acked-by: Simon Glass --- arch/x86/cpu/sipi_vector.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/sipi_vector.S b/arch/x86/cpu/sipi_vector.S index bcef12c6f1..0c4a157f38 100644 --- a/arch/x86/cpu/sipi_vector.S +++ b/arch/x86/cpu/sipi_vector.S @@ -190,8 +190,8 @@ load_msr: /* c_handler(cpu_num) */ movl %esi, %eax /* cpu_num */ - mov c_handler, %eax - call *%eax + mov c_handler, %esi + call *%esi .align 4 .globl sipi_params -- cgit v1.2.1 From 60994a02a56fd7dc408b0a36ad5dead1b85959b4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 18 Oct 2015 19:51:26 -0600 Subject: x86: Init the debug UART if enabled If the debug UART is enabled, get it ready for use at the earliest possible opportunity. This is not actually very early, but until we have a stack it is difficult to make it work. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/start.S | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index d072825bcd..5b4ee79d88 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -126,14 +126,9 @@ car_init_ret: call board_init_f_mem mov %eax, %esp - /* - * Debug UART is available here although it may not be plumbed out - * to pins depending on the board. To use it: - * - * call debug_uart_init - * mov $'a', %eax - * call printch - */ +#ifdef CONFIG_DEBUG_UART + call debug_uart_init +#endif /* Get address of global_data */ mov %fs:0, %edx -- cgit v1.2.1 From 7b95252d82267143e647d5fee96c7d9d5bf74560 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 18 Oct 2015 19:51:27 -0600 Subject: x86: chromebook_link: Enable the debug UART Add support for the debug UART on link. This is useful for early debugging. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/ivybridge/cpu.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index cce5923f0b..0e6512c675 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -340,3 +340,10 @@ int print_cpuinfo(void) return 0; } + +void board_debug_uart_init(void) +{ + /* This enables the debug UART */ + pci_x86_write_config(NULL, PCH_LPC_DEV, LPC_EN, COMA_LPC_EN, + PCI_SIZE_16); +} -- cgit v1.2.1 From 53327d3e61ee9917eab9ce1657f20f17a079c130 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 18 Oct 2015 15:55:32 -0600 Subject: x86: ivybridge: Use 'ret' instead of 'rcode' For consistency, use 'ret' to handle a return value. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/ivybridge/sdram.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index fc66a3c3a5..26e2e5b6f2 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -93,11 +93,11 @@ static int read_seed_from_cmos(struct pei_data *pei_data) { u16 c1, c2, checksum, seed_checksum; struct udevice *dev; - int rcode = 0; + int ret = 0; - rcode = uclass_get_device(UCLASS_RTC, 0, &dev); - if (rcode) { - debug("Cannot find RTC: err=%d\n", rcode); + ret = uclass_get_device(UCLASS_RTC, 0, &dev); + if (ret) { + debug("Cannot find RTC: err=%d\n", ret); return -ENODEV; } @@ -170,11 +170,11 @@ static int write_seeds_to_cmos(struct pei_data *pei_data) { u16 c1, c2, checksum; struct udevice *dev; - int rcode = 0; + int ret = 0; - rcode = uclass_get_device(UCLASS_RTC, 0, &dev); - if (rcode) { - debug("Cannot find RTC: err=%d\n", rcode); + ret = uclass_get_device(UCLASS_RTC, 0, &dev); + if (ret) { + debug("Cannot find RTC: err=%d\n", ret); return -ENODEV; } -- cgit v1.2.1 From 9fbc5ccd79d1c6faacd2027ca89e54f38f365e2e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 18 Oct 2015 15:55:33 -0600 Subject: x86: ivybridge: Check the RTC return value The RTC can fail, so check the return value for reads. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/ivybridge/sdram.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index 26e2e5b6f2..e63790963c 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -107,11 +107,18 @@ static int read_seed_from_cmos(struct pei_data *pei_data) * the flash too much. So we store these in CMOS and the large MRC * data in SPI flash. */ - rtc_read32(dev, CMOS_OFFSET_MRC_SEED, &pei_data->scrambler_seed); + ret = rtc_read32(dev, CMOS_OFFSET_MRC_SEED, &pei_data->scrambler_seed); + if (!ret) { + ret = rtc_read32(dev, CMOS_OFFSET_MRC_SEED_S3, + &pei_data->scrambler_seed_s3); + } + if (ret) { + debug("Failed to read from RTC %s\n", dev->name); + return ret; + } + debug("Read scrambler seed 0x%08x from CMOS 0x%02x\n", pei_data->scrambler_seed, CMOS_OFFSET_MRC_SEED); - - rtc_read32(dev, CMOS_OFFSET_MRC_SEED_S3, &pei_data->scrambler_seed_s3); debug("Read S3 scrambler seed 0x%08x from CMOS 0x%02x\n", pei_data->scrambler_seed_s3, CMOS_OFFSET_MRC_SEED_S3); -- cgit v1.2.1 From e9b3967c0c8faefb46213d6698c4bc21bf91598a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 18 Oct 2015 15:55:35 -0600 Subject: x86: ivybridge: Fix car_uninit() to correctly set run state At present a missing $ causes this code to hang when using the MRC cache/ Fix it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/ivybridge/car.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/ivybridge/car.S b/arch/x86/cpu/ivybridge/car.S index 407e451adc..1defabf91f 100644 --- a/arch/x86/cpu/ivybridge/car.S +++ b/arch/x86/cpu/ivybridge/car.S @@ -188,7 +188,7 @@ car_uninit: wrmsr /* Disable the no-eviction run state */ - movl NOEVICTMOD_MSR, %ecx + movl $NOEVICTMOD_MSR, %ecx rdmsr andl $~2, %eax wrmsr -- cgit v1.2.1 From fd8f4729ac6520e59dd1d3f57d503d8abe345ac5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 18 Oct 2015 15:55:36 -0600 Subject: x86: ivybridge: Measure the MRC code execution time This code takes about 450ms without the MRC cache and about 27ms with the cache. Add a debug timer so that this time can be displayed. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/ivybridge/sdram.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index e63790963c..d9b3dfc12c 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -336,9 +336,11 @@ int sdram_initialise(struct pei_data *pei_data) 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); @@ -356,6 +358,7 @@ int sdram_initialise(struct pei_data *pei_data) 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; -- cgit v1.2.1 From 3e45de6ed416759f0f2699d5bb358183dbdb2063 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 18 Oct 2015 15:55:37 -0600 Subject: x86: ivybridge: Enable the MRC cache This works correctly now, so enable it. Signed-off-by: Bin Meng Dropped malloc() and adjusted commit message: Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/x86/cpu/ivybridge/sdram.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'arch/x86/cpu') diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index d9b3dfc12c..4372a5caf2 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -158,14 +158,8 @@ static int prepare_mrc_cache(struct pei_data *pei_data) if (!mrc_cache) return -ENOENT; - /* - * TODO(sjg@chromium.org): Skip this for now as it causes boot - * problems - */ - if (0) { - pei_data->mrc_input = mrc_cache->data; - pei_data->mrc_input_len = mrc_cache->data_size; - } + pei_data->mrc_input = mrc_cache->data; + pei_data->mrc_input_len = mrc_cache->data_size; debug("%s: at %p, size %x checksum %04x\n", __func__, pei_data->mrc_input, pei_data->mrc_input_len, mrc_cache->checksum); -- cgit v1.2.1