Files
system76-coreboot/src/cpu/amd/agesa/s3_resume.c
Edward O'Callaghan c814be4158 amd/agesa/s3_resume: Make compiler agnostic.
Clang does not like inline functions defined in C files with prototypes
in headers. Rather Clang expects inline function bodies to be in headers
if they are to be used out of scope. Since inline is purely advisory to
the compiler, drop its usage here.

Change-Id: I08a7a3d2cdf841ffbab10c017c75917768aac209
Signed-off-by: Edward O'Callaghan <eocallaghan@alterapraxis.com>
Reviewed-on: http://review.coreboot.org/5429
Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
Tested-by: build bot (Jenkins)
2014-04-03 10:00:52 +02:00

310 lines
7.4 KiB
C

/*
* This file is part of the coreboot project.
*
* Copyright (C) 2012 Advanced Micro Devices, Inc.
*
* 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; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "AGESA.h"
#include "amdlib.h"
#include <console/console.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/mtrr.h>
#include <cpu/amd/mtrr.h>
#include <cpu/x86/cache.h>
#include <cbmem.h>
#include <device/device.h>
#include <arch/io.h>
#include <arch/acpi.h>
#include <string.h>
#include "Porting.h"
#include "BiosCallOuts.h"
#include "s3_resume.h"
#include "agesawrapper.h"
#ifndef __PRE_RAM__
#include <spi-generic.h>
#include <spi_flash.h>
#endif
void restore_mtrr(void)
{
u32 msr;
volatile UINT32 *msrPtr = (volatile UINT32 *)S3_DATA_MTRR_POS;
msr_t msr_data;
printk(BIOS_SPEW, "%s\n", __func__);
disable_cache();
/* Enable access to AMD RdDram and WrDram extension bits */
msr_data = rdmsr(SYS_CFG);
msr_data.lo |= SYSCFG_MSR_MtrrFixDramModEn;
wrmsr(SYS_CFG, msr_data);
/* Now restore the Fixed MTRRs */
msr_data.lo = *msrPtr;
msrPtr ++;
msr_data.hi = *msrPtr;
msrPtr ++;
wrmsr(0x250, msr_data);
msr_data.lo = *msrPtr;
msrPtr ++;
msr_data.hi = *msrPtr;
msrPtr ++;
wrmsr(0x258, msr_data);
msr_data.lo = *msrPtr;
msrPtr ++;
msr_data.hi = *msrPtr;
msrPtr ++;
wrmsr(0x259, msr_data);
for (msr = 0x268; msr <= 0x26F; msr++) {
msr_data.lo = *msrPtr;
msrPtr ++;
msr_data.hi = *msrPtr;
msrPtr ++;
wrmsr(msr, msr_data);
}
/* Disable access to AMD RdDram and WrDram extension bits */
msr_data = rdmsr(SYS_CFG);
msr_data.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
wrmsr(SYS_CFG, msr_data);
/* Restore the Variable MTRRs */
for (msr = 0x200; msr <= 0x20F; msr++) {
msr_data.lo = *msrPtr;
msrPtr ++;
msr_data.hi = *msrPtr;
msrPtr ++;
wrmsr(msr, msr_data);
}
/* Restore SYSCFG MTRR */
msr_data.lo = *msrPtr;
msrPtr ++;
msr_data.hi = *msrPtr;
msrPtr ++;
wrmsr(SYS_CFG, msr_data);
}
void *backup_resume(void)
{
void *resume_backup_memory;
if (cbmem_recovery(1))
return NULL;
resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
if (((u32) resume_backup_memory == 0)
|| ((u32) resume_backup_memory == -1)) {
printk(BIOS_ERR, "Error: resume_backup_memory: %x\n",
(u32) resume_backup_memory);
for (;;) ;
}
return resume_backup_memory;
}
void move_stack_high_mem(void)
{
void *high_stack;
high_stack = cbmem_find(CBMEM_ID_RESUME_SCRATCH);
memcpy(high_stack, (void *)BSP_STACK_BASE_ADDR,
(CONFIG_HIGH_SCRATCH_MEMORY_SIZE - BIOS_HEAP_SIZE));
__asm__
volatile ("add %0, %%esp; add %0, %%ebp; invd"::"g"
(high_stack - BSP_STACK_BASE_ADDR)
:);
}
#ifndef __PRE_RAM__
void write_mtrr(struct spi_flash *flash, u32 *p_nvram_pos, unsigned idx)
{
msr_t msr_data;
msr_data = rdmsr(idx);
#if CONFIG_AMD_SB_SPI_TX_LEN >= 8
flash->write(flash, *p_nvram_pos, 8, &msr_data);
*p_nvram_pos += 8;
#else
flash->write(flash, *p_nvram_pos, 4, &msr_data.lo);
*p_nvram_pos += 4;
flash->write(flash, *p_nvram_pos, 4, &msr_data.hi);
*p_nvram_pos += 4;
#endif
}
#endif
void OemAgesaSaveMtrr(void)
{
#ifndef __PRE_RAM__
msr_t msr_data;
u32 nvram_pos = S3_DATA_MTRR_POS;
u32 i;
struct spi_flash *flash;
spi_init();
flash = spi_flash_probe(0, 0, 0, 0);
if (!flash) {
printk(BIOS_DEBUG, "Could not find SPI device\n");
return;
}
flash->spi->rw = SPI_WRITE_FLAG;
spi_claim_bus(flash->spi);
flash->erase(flash, S3_DATA_MTRR_POS, S3_DATA_MTRR_SIZE);
/* Enable access to AMD RdDram and WrDram extension bits */
msr_data = rdmsr(SYS_CFG);
msr_data.lo |= SYSCFG_MSR_MtrrFixDramModEn;
wrmsr(SYS_CFG, msr_data);
/* Fixed MTRRs */
write_mtrr(flash, &nvram_pos, 0x250);
write_mtrr(flash, &nvram_pos, 0x258);
write_mtrr(flash, &nvram_pos, 0x259);
for (i = 0x268; i < 0x270; i++)
write_mtrr(flash, &nvram_pos, i);
/* Disable access to AMD RdDram and WrDram extension bits */
msr_data = rdmsr(SYS_CFG);
msr_data.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
wrmsr(SYS_CFG, msr_data);
/* Variable MTRRs */
for (i = 0x200; i < 0x210; i++)
write_mtrr(flash, &nvram_pos, i);
/* SYS_CFG */
write_mtrr(flash, &nvram_pos, 0xC0010010);
/* TOM */
write_mtrr(flash, &nvram_pos, 0xC001001A);
/* TOM2 */
write_mtrr(flash, &nvram_pos, 0xC001001D);
flash->spi->rw = SPI_WRITE_FLAG;
spi_release_bus(flash->spi);
#endif
}
void OemAgesaGetS3Info(S3_DATA_TYPE S3DataType, u32 *DataSize, void **Data)
{
AMD_CONFIG_PARAMS StdHeader;
if (S3DataType == S3DataTypeNonVolatile) {
*Data = (void *)S3_DATA_NONVOLATILE_POS;
*DataSize = *(UINTN *) (*Data);
*Data += 4;
} else {
*DataSize = *(UINTN *) S3_DATA_VOLATILE_POS;
*Data = (void *) GetHeapBase(&StdHeader);
memcpy((void *)(*Data), (void *)(S3_DATA_VOLATILE_POS + 4), *DataSize);
}
}
#ifndef __PRE_RAM__
u32 OemAgesaSaveS3Info(S3_DATA_TYPE S3DataType, u32 DataSize, void *Data)
{
u32 pos = S3_DATA_VOLATILE_POS;
u32 data;
u32 nvram_pos;
struct spi_flash *flash;
if (S3DataType == S3DataTypeNonVolatile) {
pos = S3_DATA_NONVOLATILE_POS;
} else { /* S3DataTypeVolatile */
pos = S3_DATA_VOLATILE_POS;
}
spi_init();
flash = spi_flash_probe(0, 0, 0, 0);
if (!flash) {
printk(BIOS_DEBUG, "Could not find SPI device\n");
/* Dont make flow stop. */
return AGESA_SUCCESS;
}
flash->spi->rw = SPI_WRITE_FLAG;
spi_claim_bus(flash->spi);
if (S3DataType == S3DataTypeNonVolatile) {
flash->erase(flash, S3_DATA_NONVOLATILE_POS, S3_DATA_NONVOLATILE_SIZE);
} else {
flash->erase(flash, S3_DATA_VOLATILE_POS, S3_DATA_VOLATILE_SIZE);
}
nvram_pos = 0;
flash->write(flash, nvram_pos + pos, sizeof(DataSize), &DataSize);
for (nvram_pos = 0; nvram_pos < DataSize - CONFIG_AMD_SB_SPI_TX_LEN; nvram_pos += CONFIG_AMD_SB_SPI_TX_LEN) {
data = *(u32 *) (Data + nvram_pos);
flash->write(flash, nvram_pos + pos + 4, CONFIG_AMD_SB_SPI_TX_LEN, (u8 *)(Data + nvram_pos));
}
flash->write(flash, nvram_pos + pos + 4, DataSize % CONFIG_AMD_SB_SPI_TX_LEN, (u8 *)(Data + nvram_pos));
flash->spi->rw = SPI_WRITE_FLAG;
spi_release_bus(flash->spi);
return AGESA_SUCCESS;
}
#endif
void set_resume_cache(void)
{
msr_t msr;
/* disable fixed mtrr for now, it will be enabled by mtrr restore */
msr = rdmsr(SYSCFG_MSR);
msr.lo &= ~(SYSCFG_MSR_MtrrFixDramEn | SYSCFG_MSR_MtrrFixDramModEn);
wrmsr(SYSCFG_MSR, msr);
/* Enable caching for 0 - coreboot ram using variable mtrr */
msr.lo = 0 | MTRR_TYPE_WRBACK;
msr.hi = 0;
wrmsr(MTRRphysBase_MSR(0), msr);
msr.lo = ~(CONFIG_RAMTOP - 1) | MTRRphysMaskValid;
msr.hi = (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1;
wrmsr(MTRRphysMask_MSR(0), msr);
/* Set the default memory type and disable fixed and enable variable MTRRs */
msr.hi = 0;
msr.lo = (1 << 11);
wrmsr(MTRRdefType_MSR, msr);
enable_cache();
}
void s3_resume(void)
{
int status;
printk(BIOS_DEBUG, "agesawrapper_amds3laterestore ");
status = agesawrapper_amds3laterestore();
if (status)
printk(BIOS_DEBUG, "error level: %x \n", (u32) status);
else
printk(BIOS_DEBUG, "passed.\n");
}