mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
mips_malta: generate SPD EEPROM data at runtime
The SPD EEPROM specifies the amount of memory present in the system and thus its correct contents can only be known at runtime. Calculating parts of the data on init allows the data to accurately reflect the amount of target memory present and allow YAMON to boot with an arbitrary amount of SDRAM. Where possible the SPD data will favor indicating 2 banks of SDRAM rather than 1. For example the default 128MB of target memory will be represented as 2x64MB banks rather than 1x128MB bank. This allows versions of MIPS BIOS code (such as YAMON 2.22 and older) to boot despite a bug preventing them from handling a single bank of SDRAM with the Galileo GT64120 system controller emulated by QEMU. Signed-off-by: Paul Burton <paul.burton@imgtec.com> Signed-off-by: Leon Alrae <leon.alrae@imgtec.com> Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
parent
a427338b22
commit
02bccc7796
1 changed files with 57 additions and 3 deletions
|
@ -47,6 +47,7 @@
|
|||
#include "sysemu/blockdev.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/sysbus.h" /* SysBusDevice */
|
||||
#include "qemu/host-utils.h"
|
||||
|
||||
//#define DEBUG_BOARD_INIT
|
||||
|
||||
|
@ -150,10 +151,10 @@ typedef struct _eeprom24c0x_t eeprom24c0x_t;
|
|||
|
||||
static eeprom24c0x_t eeprom = {
|
||||
.contents = {
|
||||
/* 00000000: */ 0x80,0x08,0x04,0x0D,0x0A,0x01,0x40,0x00,
|
||||
/* 00000000: */ 0x80,0x08,0xFF,0x0D,0x0A,0xFF,0x40,0x00,
|
||||
/* 00000008: */ 0x01,0x75,0x54,0x00,0x82,0x08,0x00,0x01,
|
||||
/* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x0E,0x00,
|
||||
/* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0x40,
|
||||
/* 00000010: */ 0x8F,0x04,0x02,0x01,0x01,0x00,0x00,0x00,
|
||||
/* 00000018: */ 0x00,0x00,0x00,0x14,0x0F,0x14,0x2D,0xFF,
|
||||
/* 00000020: */ 0x15,0x08,0x15,0x08,0x00,0x00,0x00,0x00,
|
||||
/* 00000028: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
/* 00000030: */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
|
@ -169,6 +170,56 @@ static eeprom24c0x_t eeprom = {
|
|||
},
|
||||
};
|
||||
|
||||
static void eeprom_generate(eeprom24c0x_t *eeprom, ram_addr_t ram_size)
|
||||
{
|
||||
enum { SDR = 0x4, DDR2 = 0x8 } type;
|
||||
uint8_t *spd = eeprom->contents;
|
||||
uint8_t nbanks = 0;
|
||||
uint16_t density = 0;
|
||||
int i;
|
||||
|
||||
/* work in terms of MB */
|
||||
ram_size >>= 20;
|
||||
|
||||
while ((ram_size >= 4) && (nbanks <= 2)) {
|
||||
int sz_log2 = MIN(31 - clz32(ram_size), 14);
|
||||
nbanks++;
|
||||
density |= 1 << (sz_log2 - 2);
|
||||
ram_size -= 1 << sz_log2;
|
||||
}
|
||||
|
||||
/* split to 2 banks if possible */
|
||||
if ((nbanks == 1) && (density > 1)) {
|
||||
nbanks++;
|
||||
density >>= 1;
|
||||
}
|
||||
|
||||
if (density & 0xff00) {
|
||||
density = (density & 0xe0) | ((density >> 8) & 0x1f);
|
||||
type = DDR2;
|
||||
} else if (!(density & 0x1f)) {
|
||||
type = DDR2;
|
||||
} else {
|
||||
type = SDR;
|
||||
}
|
||||
|
||||
if (ram_size) {
|
||||
fprintf(stderr, "Warning: SPD cannot represent final %dMB"
|
||||
" of SDRAM\n", (int)ram_size);
|
||||
}
|
||||
|
||||
/* fill in SPD memory information */
|
||||
spd[2] = type;
|
||||
spd[5] = nbanks;
|
||||
spd[31] = density;
|
||||
|
||||
/* checksum */
|
||||
spd[63] = 0;
|
||||
for (i = 0; i < 63; i++) {
|
||||
spd[63] += spd[i];
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t eeprom24c0x_read(void)
|
||||
{
|
||||
logout("%u: scl = %u, sda = %u, data = 0x%02x\n",
|
||||
|
@ -862,6 +913,9 @@ void mips_malta_init(QEMUMachineInitArgs *args)
|
|||
vmstate_register_ram_global(ram);
|
||||
memory_region_add_subregion(system_memory, 0, ram);
|
||||
|
||||
/* generate SPD EEPROM data */
|
||||
eeprom_generate(&eeprom, ram_size);
|
||||
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
be = 1;
|
||||
#else
|
||||
|
|
Loading…
Reference in a new issue