CBMEM: Backup top_of_ram instead of cbmem_toc
AMD northbridges have a complex way to resolve top_of_ram. Once it is resolved, it is stored in NVRAM to be used on resume. TODO: Redesign these get_top_of_ram() functions from scratch. Change-Id: I3cceb7e9b8b07620dacf138e99f98dc818c65341 Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-on: http://review.coreboot.org/3557 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin <adurbin@google.com>
This commit is contained in:
parent
c04afd6433
commit
bc90e15d3f
|
@ -40,12 +40,18 @@ void get_cbmem_table(uint64_t *base, uint64_t *size)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !CONFIG_DYNAMIC_CBMEM && !defined(__PRE_RAM__)
|
#if !CONFIG_DYNAMIC_CBMEM && !defined(__PRE_RAM__)
|
||||||
|
void __attribute__((weak)) backup_top_of_ram(uint64_t ramtop)
|
||||||
|
{
|
||||||
|
/* Do nothing. Chipset may have implementation to save ramtop in NVRAM. */
|
||||||
|
}
|
||||||
|
|
||||||
/* This is for compatibility with old boards only. Any new chipset and board
|
/* This is for compatibility with old boards only. Any new chipset and board
|
||||||
* must implement get_top_of_ram() for both romstage and ramstage to support
|
* must implement get_top_of_ram() for both romstage and ramstage to support
|
||||||
* features like CAR_MIGRATION and CBMEM_CONSOLE.
|
* features like CAR_MIGRATION and CBMEM_CONSOLE.
|
||||||
*/
|
*/
|
||||||
void set_top_of_ram(uint64_t ramtop)
|
void set_top_of_ram(uint64_t ramtop)
|
||||||
{
|
{
|
||||||
|
backup_top_of_ram(ramtop);
|
||||||
cbmem_late_set_table(ramtop - HIGH_MEMORY_SIZE, HIGH_MEMORY_SIZE);
|
cbmem_late_set_table(ramtop - HIGH_MEMORY_SIZE, HIGH_MEMORY_SIZE);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -120,7 +120,8 @@ inline void *backup_resume(void)
|
||||||
* printk(BIOS_DEBUG, "CBMEM TOC 0-size:%x\n ",(u32_t)(high_ram_base + HIGH_MEMORY_SIZE + 4096));
|
* printk(BIOS_DEBUG, "CBMEM TOC 0-size:%x\n ",(u32_t)(high_ram_base + HIGH_MEMORY_SIZE + 4096));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
cbmem_reinit((u64) high_ram_base);
|
if (!cbmem_reinit((u64)high_ram_base))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
|
resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
|
||||||
if (((u32) resume_backup_memory == 0)
|
if (((u32) resume_backup_memory == 0)
|
||||||
|
|
|
@ -45,7 +45,8 @@ static inline void *backup_resume(void) {
|
||||||
print_debug_pcar("CBMEM TOC is at: ", (uint32_t)high_ram_base);
|
print_debug_pcar("CBMEM TOC is at: ", (uint32_t)high_ram_base);
|
||||||
print_debug_pcar("CBMEM TOC 0-size: ",(uint32_t)(high_ram_base + HIGH_MEMORY_SIZE + 4096));
|
print_debug_pcar("CBMEM TOC 0-size: ",(uint32_t)(high_ram_base + HIGH_MEMORY_SIZE + 4096));
|
||||||
|
|
||||||
cbmem_reinit((u64)high_ram_base);
|
if (!cbmem_reinit((u64)high_ram_base))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
|
resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
|
||||||
|
|
||||||
|
|
|
@ -132,8 +132,8 @@ u64 cbmem_entry_size(const struct cbmem_entry *entry);
|
||||||
#ifndef __PRE_RAM__
|
#ifndef __PRE_RAM__
|
||||||
extern uint64_t high_tables_base, high_tables_size;
|
extern uint64_t high_tables_base, high_tables_size;
|
||||||
void set_top_of_ram(uint64_t ramtop);
|
void set_top_of_ram(uint64_t ramtop);
|
||||||
|
void backup_top_of_ram(uint64_t ramtop);
|
||||||
void cbmem_late_set_table(uint64_t base, uint64_t size);
|
void cbmem_late_set_table(uint64_t base, uint64_t size);
|
||||||
void set_cbmem_toc(struct cbmem_entry *);
|
|
||||||
int cbmem_base_check(void);
|
int cbmem_base_check(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -45,12 +45,9 @@ struct cbmem_entry {
|
||||||
#ifndef __PRE_RAM__
|
#ifndef __PRE_RAM__
|
||||||
uint64_t high_tables_base = 0;
|
uint64_t high_tables_base = 0;
|
||||||
uint64_t high_tables_size = 0;
|
uint64_t high_tables_size = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
void __attribute__((weak)) set_cbmem_toc(struct cbmem_entry * x)
|
#if !defined(__PRE_RAM__)
|
||||||
{
|
|
||||||
/* do nothing, this should be called by chipset to save TOC in NVRAM */
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cbmem_trace_location(uint64_t base, uint64_t size, const char *s)
|
static void cbmem_trace_location(uint64_t base, uint64_t size, const char *s)
|
||||||
{
|
{
|
||||||
if (base && size && s) {
|
if (base && size && s) {
|
||||||
|
@ -113,10 +110,6 @@ void cbmem_init(u64 baseaddr, u64 size)
|
||||||
for (;;) ;
|
for (;;) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we don't need to call this in romstage, useful only from ramstage */
|
|
||||||
#ifndef __PRE_RAM__
|
|
||||||
set_cbmem_toc((struct cbmem_entry *)(unsigned long)baseaddr);
|
|
||||||
#endif
|
|
||||||
memset(cbmem_toc, 0, CBMEM_TOC_RESERVED);
|
memset(cbmem_toc, 0, CBMEM_TOC_RESERVED);
|
||||||
|
|
||||||
cbmem_toc[0] = (struct cbmem_entry) {
|
cbmem_toc[0] = (struct cbmem_entry) {
|
||||||
|
|
|
@ -95,7 +95,7 @@ int acpi_is_wakeup_early(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct cbmem_entry *get_cbmem_toc(void)
|
unsigned long get_top_of_ram(void)
|
||||||
{
|
{
|
||||||
uint32_t xdata = 0;
|
uint32_t xdata = 0;
|
||||||
int xnvram_pos = 0xf8, xi;
|
int xnvram_pos = 0xf8, xi;
|
||||||
|
@ -105,7 +105,7 @@ struct cbmem_entry *get_cbmem_toc(void)
|
||||||
xdata |= inb(BIOSRAM_DATA) << (xi *8);
|
xdata |= inb(BIOSRAM_DATA) << (xi *8);
|
||||||
xnvram_pos++;
|
xnvram_pos++;
|
||||||
}
|
}
|
||||||
return (struct cbmem_entry *) xdata;
|
return (unsigned long) xdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -40,9 +40,9 @@ int acpi_get_sleep_type(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void set_cbmem_toc(struct cbmem_entry *toc)
|
void backup_top_of_ram(uint64_t ramtop)
|
||||||
{
|
{
|
||||||
u32 dword = (u32) toc;
|
u32 dword = (u32) ramtop;
|
||||||
int nvram_pos = 0xf8, i; /* temp */
|
int nvram_pos = 0xf8, i; /* temp */
|
||||||
/* printk(BIOS_DEBUG, "dword=%x\n", dword); */
|
/* printk(BIOS_DEBUG, "dword=%x\n", dword); */
|
||||||
for (i = 0; i<4; i++) {
|
for (i = 0; i<4; i++) {
|
||||||
|
@ -132,19 +132,22 @@ void hudson_enable(device_t dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cbmem_entry *get_cbmem_toc(void)
|
#if CONFIG_HAVE_ACPI_RESUME
|
||||||
|
unsigned long get_top_of_ram(void)
|
||||||
{
|
{
|
||||||
uint32_t xdata = 0;
|
uint32_t xdata = 0;
|
||||||
int xnvram_pos = 0xf8, xi;
|
int xnvram_pos = 0xf8, xi;
|
||||||
|
if (acpi_get_sleep_type() != 3)
|
||||||
|
return 0;
|
||||||
for (xi = 0; xi<4; xi++) {
|
for (xi = 0; xi<4; xi++) {
|
||||||
outb(xnvram_pos, BIOSRAM_INDEX);
|
outb(xnvram_pos, BIOSRAM_INDEX);
|
||||||
xdata &= ~(0xff << (xi * 8));
|
xdata &= ~(0xff << (xi * 8));
|
||||||
xdata |= inb(BIOSRAM_DATA) << (xi *8);
|
xdata |= inb(BIOSRAM_DATA) << (xi *8);
|
||||||
xnvram_pos++;
|
xnvram_pos++;
|
||||||
}
|
}
|
||||||
return (struct cbmem_entry *) xdata;
|
return (unsigned long) xdata;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
struct chip_operations southbridge_amd_agesa_hudson_ops = {
|
struct chip_operations southbridge_amd_agesa_hudson_ops = {
|
||||||
CHIP_NAME("ATI HUDSON")
|
CHIP_NAME("ATI HUDSON")
|
||||||
|
|
|
@ -27,9 +27,9 @@
|
||||||
#define BIOSRAM_INDEX 0xcd4
|
#define BIOSRAM_INDEX 0xcd4
|
||||||
#define BIOSRAM_DATA 0xcd5
|
#define BIOSRAM_DATA 0xcd5
|
||||||
|
|
||||||
void set_cbmem_toc(struct cbmem_entry *toc)
|
void backup_top_of_ram(uint64_t ramtop)
|
||||||
{
|
{
|
||||||
u32 dword = (u32) toc;
|
u32 dword = (u32) ramtop;
|
||||||
int nvram_pos = 0xfc, i;
|
int nvram_pos = 0xfc, i;
|
||||||
for (i = 0; i<4; i++) {
|
for (i = 0; i<4; i++) {
|
||||||
outb(nvram_pos, BIOSRAM_INDEX);
|
outb(nvram_pos, BIOSRAM_INDEX);
|
||||||
|
|
|
@ -37,9 +37,9 @@ int acpi_get_sleep_type(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __PRE_RAM__
|
#ifndef __PRE_RAM__
|
||||||
void set_cbmem_toc(struct cbmem_entry *toc)
|
void backup_top_of_ram(uint64_t ramtop)
|
||||||
{
|
{
|
||||||
u32 dword = (u32) toc;
|
u32 dword = (u32) ramtop;
|
||||||
int nvram_pos = 0xf8, i; /* temp */
|
int nvram_pos = 0xf8, i; /* temp */
|
||||||
printk(BIOS_DEBUG, "dword=%x\n", dword);
|
printk(BIOS_DEBUG, "dword=%x\n", dword);
|
||||||
for (i = 0; i<4; i++) {
|
for (i = 0; i<4; i++) {
|
||||||
|
@ -51,18 +51,22 @@ void set_cbmem_toc(struct cbmem_entry *toc)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct cbmem_entry *get_cbmem_toc(void)
|
#if CONFIG_HAVE_ACPI_RESUME
|
||||||
|
unsigned long get_top_of_ram(void)
|
||||||
{
|
{
|
||||||
u32 xdata = 0;
|
u32 xdata = 0;
|
||||||
int xnvram_pos = 0xf8, xi;
|
int xnvram_pos = 0xf8, xi;
|
||||||
|
if (acpi_get_sleep_type() != 3)
|
||||||
|
return 0;
|
||||||
for (xi = 0; xi<4; xi++) {
|
for (xi = 0; xi<4; xi++) {
|
||||||
outb(xnvram_pos, BIOSRAM_INDEX);
|
outb(xnvram_pos, BIOSRAM_INDEX);
|
||||||
xdata &= ~(0xff << (xi * 8));
|
xdata &= ~(0xff << (xi * 8));
|
||||||
xdata |= inb(BIOSRAM_DATA) << (xi *8);
|
xdata |= inb(BIOSRAM_DATA) << (xi *8);
|
||||||
xnvram_pos++;
|
xnvram_pos++;
|
||||||
}
|
}
|
||||||
return (struct cbmem_entry *) xdata;
|
return (unsigned long) xdata;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief South Bridge CIMx configuration
|
* @brief South Bridge CIMx configuration
|
||||||
|
|
|
@ -729,19 +729,21 @@ int acpi_is_wakeup_early(void)
|
||||||
printk(BIOS_DEBUG, "IN TEST WAKEUP %x\n", tmp);
|
printk(BIOS_DEBUG, "IN TEST WAKEUP %x\n", tmp);
|
||||||
return (((tmp & (7 << 10)) >> 10) == 3);
|
return (((tmp & (7 << 10)) >> 10) == 3);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
struct cbmem_entry *get_cbmem_toc(void)
|
unsigned long get_top_of_ram(void)
|
||||||
{
|
{
|
||||||
uint32_t xdata = 0;
|
uint32_t xdata = 0;
|
||||||
int xnvram_pos = 0xfc, xi;
|
int xnvram_pos = 0xfc, xi;
|
||||||
|
if (!acpi_is_wakeup_early())
|
||||||
|
return 0;
|
||||||
for (xi = 0; xi<4; xi++) {
|
for (xi = 0; xi<4; xi++) {
|
||||||
outb(xnvram_pos, BIOSRAM_INDEX);
|
outb(xnvram_pos, BIOSRAM_INDEX);
|
||||||
xdata &= ~(0xff << (xi * 8));
|
xdata &= ~(0xff << (xi * 8));
|
||||||
xdata |= inb(BIOSRAM_DATA) << (xi *8);
|
xdata |= inb(BIOSRAM_DATA) << (xi *8);
|
||||||
xnvram_pos++;
|
xnvram_pos++;
|
||||||
}
|
}
|
||||||
return (struct cbmem_entry *) xdata;
|
return (unsigned long) xdata;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -84,9 +84,9 @@ static void lpc_init(device_t dev)
|
||||||
rtc_check_update_cmos_date(RTC_HAS_ALTCENTURY);
|
rtc_check_update_cmos_date(RTC_HAS_ALTCENTURY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_cbmem_toc(struct cbmem_entry *toc)
|
void backup_top_of_ram(uint64_t ramtop)
|
||||||
{
|
{
|
||||||
u32 dword = (u32) toc;
|
u32 dword = (u32) ramtop;
|
||||||
int nvram_pos = 0xfc, i;
|
int nvram_pos = 0xfc, i;
|
||||||
for (i = 0; i<4; i++) {
|
for (i = 0; i<4; i++) {
|
||||||
outb(nvram_pos, BIOSRAM_INDEX);
|
outb(nvram_pos, BIOSRAM_INDEX);
|
||||||
|
|
|
@ -673,19 +673,21 @@ static int acpi_is_wakeup_early(void)
|
||||||
printk(BIOS_DEBUG, "IN TEST WAKEUP %x\n", tmp);
|
printk(BIOS_DEBUG, "IN TEST WAKEUP %x\n", tmp);
|
||||||
return (((tmp & (7 << 10)) >> 10) == 3);
|
return (((tmp & (7 << 10)) >> 10) == 3);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
struct cbmem_entry *get_cbmem_toc(void)
|
unsigned long get_top_of_ram(void)
|
||||||
{
|
{
|
||||||
uint32_t xdata = 0;
|
uint32_t xdata = 0;
|
||||||
int xnvram_pos = 0xfc, xi;
|
int xnvram_pos = 0xfc, xi;
|
||||||
|
if (!acpi_is_wakeup_early())
|
||||||
|
return 0;
|
||||||
for (xi = 0; xi<4; xi++) {
|
for (xi = 0; xi<4; xi++) {
|
||||||
outb(xnvram_pos, BIOSRAM_INDEX);
|
outb(xnvram_pos, BIOSRAM_INDEX);
|
||||||
xdata &= ~(0xff << (xi * 8));
|
xdata &= ~(0xff << (xi * 8));
|
||||||
xdata |= inb(BIOSRAM_DATA) << (xi *8);
|
xdata |= inb(BIOSRAM_DATA) << (xi *8);
|
||||||
xnvram_pos++;
|
xnvram_pos++;
|
||||||
}
|
}
|
||||||
return (struct cbmem_entry *) xdata;
|
return (unsigned long) xdata;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -183,6 +183,11 @@ static inline int s3_load_nvram_early(int size, u32 *old_dword, int nvram_pos)
|
||||||
return nvram_pos;
|
return nvram_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cbmem_entry *get_cbmem_toc(void) {
|
#if CONFIG_HAVE_ACPI_RESUME
|
||||||
return (struct cbmem_entry *) inl(K8T890_NVRAM_IO_BASE+K8T890_NVRAM_CBMEM_TOC);
|
unsigned long get_top_of_ram(void)
|
||||||
|
{
|
||||||
|
if (!acpi_is_wakeup_early())
|
||||||
|
return 0;
|
||||||
|
return (unsigned long) inl(K8T890_NVRAM_IO_BASE+K8T890_NVRAM_TOP_OF_RAM);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -113,13 +113,8 @@ static void host_ctrl_enable_k8m8xx(struct device *dev) {
|
||||||
pci_write_config8(dev, 0xa6, 0x83);
|
pci_write_config8(dev, 0xa6, 0x83);
|
||||||
|
|
||||||
}
|
}
|
||||||
#if 0
|
void backup_top_of_ram(uint64_t ramtop) {
|
||||||
struct cbmem_entry *get_cbmem_toc(void) {
|
outl((u32) ramtop, K8T890_NVRAM_IO_BASE+K8T890_NVRAM_TOP_OF_RAM);
|
||||||
return (struct cbmem_entry *) inl(K8T890_NVRAM_IO_BASE+K8T890_NVRAM_CBMEM_TOC);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
void set_cbmem_toc(struct cbmem_entry *toc) {
|
|
||||||
outl((u32) toc, K8T890_NVRAM_IO_BASE+K8T890_NVRAM_CBMEM_TOC);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pci_operations lops_pci = {
|
static struct pci_operations lops_pci = {
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
/* The 256 bytes of NVRAM for S3 storage, 256B aligned */
|
/* The 256 bytes of NVRAM for S3 storage, 256B aligned */
|
||||||
#define K8T890_NVRAM_IO_BASE 0xf00
|
#define K8T890_NVRAM_IO_BASE 0xf00
|
||||||
#define K8T890_NVRAM_CBMEM_TOC 0xfc
|
#define K8T890_NVRAM_TOP_OF_RAM 0xfc
|
||||||
|
|
||||||
#define K8T890_MMCONFIG_MBAR 0x61
|
#define K8T890_MMCONFIG_MBAR 0x61
|
||||||
#define K8T890_MULTIPLE_FN_EN 0x4f
|
#define K8T890_MULTIPLE_FN_EN 0x4f
|
||||||
|
|
Loading…
Reference in New Issue