[coreboot-gerrit] New patch to review for coreboot: soc/apollolake: Set BootMode based on previous sleep state

Hannah Williams (hannah.williams@intel.com) gerrit at coreboot.org
Mon Apr 11 19:09:17 CEST 2016


Hannah Williams (hannah.williams at intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14316

-gerrit

commit b57054b7210571697055a2dfa9dc7e024d7fb30c
Author: Hannah Williams <hannah.williams at intel.com>
Date:   Tue Mar 22 10:07:21 2016 -0700

    soc/apollolake: Set BootMode based on previous sleep state
    
    - fill_power_state makes a copy of the current snapshot of power management
      registers in CAR variable "power_state" for use in ramstage
    - migrate_power_state adds CAR variable "power_state" to
      CBMEM (CBMEM_ID_POWER_STATE)
    - s3_resume state is updated in romstage_handoff block
    
    Change-Id: I512d6c27a9df3449ef7f4b923e297f6d334d9ed2
    Signed-off-by: Hannah Williams <hannah.williams at intel.com>
---
 src/soc/intel/apollolake/romstage/romstage.c | 220 +++++++++++++++++++++++++++
 1 file changed, 220 insertions(+)

diff --git a/src/soc/intel/apollolake/romstage/romstage.c b/src/soc/intel/apollolake/romstage/romstage.c
new file mode 100644
index 0000000..0bae9dd
--- /dev/null
+++ b/src/soc/intel/apollolake/romstage/romstage.c
@@ -0,0 +1,220 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Intel Corp.
+ * (Written by Alexandru Gagniuc <alexandrux.gagniuc at intel.com> for Intel Corp.)
+ * (Written by Andrey Petrov <andrey.petrov at intel.com> for Intel Corp.)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <arch/io.h>
+#include <cbfs.h>
+#include <cbmem.h>
+#include <stddef.h>
+#include <string.h>
+#include <arch/early_variables.h>
+#include <console/console.h>
+#include <cpu/x86/msr.h>
+#include <device/pci_def.h>
+#include <fsp/api.h>
+#include <fsp/FspmUpd.h>
+#include <fsp/util.h>
+#include <device/resource.h>
+#include <soc/iomap.h>
+#include <soc/pm.h>
+#include <soc/romstage.h>
+#include <soc/uart.h>
+#include <soc/intel/common/mrc_cache.h>
+#include <fsp/api.h>
+#include <romstage_handoff.h>
+
+#define FIT_POINTER		(0x100000000ULL - 0x40)
+
+static struct chipset_power_state power_state CAR_GLOBAL;
+
+/*
+ * Enables several BARs and devices which are needed for memory init
+ * - MCH_BASE_ADDR is needed in order to talk to the memory controller
+ * - PMC_BAR0 and PMC_BAR1 are used by FSP (with the base address hardcoded)
+ *   Once raminit is done, we can safely let the allocator re-assign them
+ * - HPET is enabled because FSP wants to store a pointer to global data in the
+ *   HPET comparator register
+ */
+static void soc_early_romstage_init(void)
+{
+	msr_t msr;
+	device_t pmc = PCI_DEV(0, 13, 1);
+
+	/* Set MCH base address and enable bit */
+	pci_write_config32(PCI_DEV(0, 0, 0), 0x48, MCH_BASE_ADDR | 1);
+
+	/* Set PMC base address */
+	pci_write_config32(pmc, PCI_BASE_ADDRESS_0, PMC_BAR0);
+	pci_write_config32(pmc, PCI_BASE_ADDRESS_1, 0);	/* 64-bit BAR */
+	pci_write_config32(pmc, PCI_BASE_ADDRESS_2, PMC_BAR1);
+	pci_write_config32(pmc, PCI_BASE_ADDRESS_3, 0);	/* 64-bit BAR */
+
+	/* PMIO BAR4 was already set in bootblock, hence the COMMAND_IO below */
+	pci_write_config32(pmc, PCI_COMMAND,
+				PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+				PCI_COMMAND_MASTER);
+
+	/* Enable decoding for HPET */
+	pci_write_config32(PCI_DEV(0, 13, 0), 0x60, 1<<7);
+
+	/* Work around ACPI timer bug */
+	msr.hi = 0x2FBA2E25;
+	msr.lo = (1<<16) | (ACPI_PMIO_BASE + R_ACPI_PM1_TMR);
+	wrmsr(0x121, msr);
+}
+
+/*
+ * Now that FSP is done consuming large amounts of CAR, we can use a much
+ * larger portion of CAR for the stack. The larger stack is needed for
+ * decompressing ramstage. It turns out that setting the stack pointer to top
+ * of CAR gives us the largest uninterrupted stack.
+ */
+static void *realloc_stack(void)
+{
+	uintptr_t new_stack = CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE;
+	new_stack -= sizeof(size_t);
+	printk(BIOS_DEBUG, "Placing new stack at 0x%lx\n", new_stack);
+	return (void *)new_stack;
+}
+
+static void migrate_power_state(int is_recovery)
+{
+        struct chipset_power_state *ps_cbmem;
+        struct chipset_power_state *ps_car;
+
+        ps_car = car_get_var_ptr(&power_state);
+        ps_cbmem = cbmem_add(CBMEM_ID_POWER_STATE, sizeof(*ps_cbmem));
+
+        if (ps_cbmem == NULL) {
+                printk(BIOS_DEBUG, "Unable to add power state to cbmem!\n");
+                return;
+        }
+        memcpy(ps_cbmem, ps_car, sizeof(*ps_cbmem));
+}
+
+asmlinkage void* romstage_entry(void)
+{
+	void *hob_list_ptr;
+	const void *mrc_data;
+	size_t mrc_data_size;
+	struct resource fsp_mem;
+	int prev_sleep_state;
+	struct romstage_handoff *handoff;
+	struct chipset_power_state *ps = car_get_var_ptr(&power_state);
+
+	/* Be careful. Bootblock might already have initialized the console */
+	if (!IS_ENABLED(CONFIG_BOOTBLOCK_CONSOLE)) {
+		lpss_console_uart_init();
+		console_init();
+	}
+
+	printk(BIOS_DEBUG, "Starting romstage...\n");
+
+	soc_early_romstage_init();
+
+	prev_sleep_state = fill_power_state(ps);
+
+	fsp_memory_init(&hob_list_ptr);
+
+	fsp_find_reserved_memory(&fsp_mem, hob_list_ptr);
+
+	/* initialize cbmem by adding FSP reserved memory first thing */
+	cbmem_initialize_empty_id_size(CBMEM_ID_FSP_RESERVED_MEMORY,
+					fsp_mem.size);
+
+	migrate_power_state(0);
+
+	/* make sure FSP memory is reserved in cbmem */
+	if (fsp_mem.base != (uintptr_t)cbmem_find(CBMEM_ID_FSP_RESERVED_MEMORY))
+		die("Failed to accommodate FSP reserved memory request");
+
+	/* Now that CBMEM is up, save the list so ramstage can use it */
+	fsp_save_hob_list(hob_list_ptr);
+
+	/* Save MRC Data to CBMEM */
+	if (IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS) &&
+	    (prev_sleep_state != SLEEP_STATE_S3))
+	{
+		if ((mrc_data = fsp_find_nv_storage_data(&mrc_data_size)) &&
+		    mrc_cache_stash_data(mrc_data, mrc_data_size) < 0)
+			printk(BIOS_ERR, "Failed to stash MRC data\n");
+	}
+       /* Create romstage handof information */
+        handoff = romstage_handoff_find_or_add();
+        if (handoff != NULL)
+                handoff->s3_resume = (prev_sleep_state == SLEEP_STATE_S3);
+        else
+                printk(BIOS_DEBUG, "Romstage handoff structure not added!\n");
+
+	return realloc_stack();
+}
+
+asmlinkage void romstage_after_raminit(void)
+{
+	run_ramstage();
+}
+
+static void fill_console_params(struct FSPM_UPD *memupd)
+{
+	if (IS_ENABLED(CONFIG_CONSOLE_SERIAL)) {
+		memupd->FspmConfig.SerialDebugPortDevice = CONFIG_UART_FOR_CONSOLE;
+		memupd->FspmConfig.SerialDebugPortType = 2;
+		memupd->FspmConfig.SerialDebugPortStrideSize = 2;
+		memupd->FspmConfig.SerialDebugPortAddress = 0;
+	} else {
+		memupd->FspmConfig.SerialDebugPortType = 0;
+	}
+}
+
+void platform_fsp_memory_init_params_cb(struct FSPM_UPD *memupd)
+{
+	const struct mrc_saved_data *mrc_cache;
+	struct FSP_M_ARCH_UPD *arch_upd = &memupd->FspmArchUpd;
+	struct chipset_power_state *ps = car_get_var_ptr(&power_state);
+	int prev_sleep_state = chipset_prev_sleep_state(ps);
+
+	fill_console_params(memupd);
+	mainboard_memory_init_params(memupd);
+
+	/* Do NOT let FSP do any GPIO pad configuration */
+	memupd->FspmConfig.GpioPadInitTablePtr = NULL;
+	/* This is somewhere in ASSRAM */
+	memupd->FspmConfig.FitTablePtr = read32((void *)FIT_POINTER);
+
+	/* Reserve enough memory under TOLUD to save CBMEM header */
+	memupd->FspmArchUpd.BootLoaderTolumSize = cbmem_overhead_size();
+	/* TODO: This matches the policy in entry.inc, but should be unified. */
+	memupd->FspmArchUpd.StackBase = (void *)CONFIG_FSPM_STACK_BASE;
+	memupd->FspmArchUpd.StackSize = CONFIG_FSPM_STACK_SIZE;
+
+	arch_upd->Bootmode = FSP_BOOT_WITH_FULL_CONFIGURATION;
+
+	if (IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS)) {
+		if (!mrc_cache_get_current_with_version(&mrc_cache, 0)) {
+			/* MRC cache found */
+			arch_upd->NvsBufferPtr = (void *)mrc_cache->data;
+			arch_upd->Bootmode =
+				prev_sleep_state == SLEEP_STATE_S3 ?
+				FSP_BOOT_ON_S3_RESUME:
+				FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES;
+			printk(BIOS_DEBUG, "MRC cache found, size %x bootmode:%d\n", mrc_cache->size, arch_upd->Bootmode);
+		} else
+			printk(BIOS_DEBUG, "MRC cache was not found\n");
+	}
+
+}
+
+__attribute__ ((weak))
+void mainboard_memory_init_params(struct FSPM_UPD *memupd)
+{
+        printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
+}



More information about the coreboot-gerrit mailing list