diff options
Diffstat (limited to 'arch/x86/lib/mrccache.c')
-rw-r--r-- | arch/x86/lib/mrccache.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/arch/x86/lib/mrccache.c b/arch/x86/lib/mrccache.c index 1c4b5a8..0efae6d 100644 --- a/arch/x86/lib/mrccache.c +++ b/arch/x86/lib/mrccache.c @@ -2,11 +2,13 @@ * From coreboot src/southbridge/intel/bd82x6x/mrccache.c * * Copyright (C) 2014 Google Inc. + * Copyright (C) 2015 Bin Meng <bmeng.cn@gmail.com> * * SPDX-License-Identifier: GPL-2.0 */ #include <common.h> +#include <dm.h> #include <errno.h> #include <fdtdec.h> #include <net.h> @@ -14,6 +16,8 @@ #include <spi_flash.h> #include <asm/mrccache.h> +DECLARE_GLOBAL_DATA_PTR; + static struct mrc_data_container *next_mrc_block( struct mrc_data_container *cache) { @@ -155,3 +159,88 @@ int mrccache_update(struct udevice *sf, struct fmap_entry *entry, return 0; } + +int mrccache_reserve(void) +{ + struct mrc_data_container *cache; + u16 checksum; + + if (!gd->arch.mrc_output_len) + return 0; + + /* adjust stack pointer to store pure cache data plus the header */ + gd->start_addr_sp -= (gd->arch.mrc_output_len + MRC_DATA_HEADER_SIZE); + cache = (struct mrc_data_container *)gd->start_addr_sp; + + cache->signature = MRC_DATA_SIGNATURE; + cache->data_size = gd->arch.mrc_output_len; + checksum = compute_ip_checksum(gd->arch.mrc_output, cache->data_size); + debug("Saving %d bytes for MRC output data, checksum %04x\n", + cache->data_size, checksum); + cache->checksum = checksum; + cache->reserved = 0; + memcpy(cache->data, gd->arch.mrc_output, cache->data_size); + + /* gd->arch.mrc_output now points to the container */ + gd->arch.mrc_output = (char *)cache; + + gd->start_addr_sp &= ~0xf; + + return 0; +} + +int mrccache_get_region(struct udevice **devp, struct fmap_entry *entry) +{ + const void *blob = gd->fdt_blob; + int node, mrc_node; + int ret; + + /* Find the flash chip within the SPI controller node */ + node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH); + if (node < 0) + return -ENOENT; + + /* 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) { + ret = uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node, + devp); + debug("ret = %d\n", ret); + if (ret) + return ret; + } + + return 0; +} + +int mrccache_save(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 = mrccache_get_region(&sf, &entry); + if (ret) + goto err_entry; + data = (struct mrc_data_container *)gd->arch.mrc_output; + ret = mrccache_update(sf, &entry, data); + if (!ret) + debug("Saved MRC data with checksum %04x\n", data->checksum); + +err_entry: + if (ret) + debug("%s: Failed: %d\n", __func__, ret); + return ret; +} |