aboutsummaryrefslogtreecommitdiff
path: root/hw/mips
diff options
context:
space:
mode:
authorPaul Burton <paul.burton@imgtec.com>2013-06-14 08:30:45 +0100
committerAurelien Jarno <aurelien@aurel32.net>2013-07-28 19:59:22 +0200
commit02bccc7796fec8b39dca9affc8bff8edebe0a867 (patch)
treef49a334715be30e48149f569071410c9b4abca79 /hw/mips
parenta427338b222b43197c2776cbc996936df0302f51 (diff)
downloadqemu-02bccc7796fec8b39dca9affc8bff8edebe0a867.zip
qemu-02bccc7796fec8b39dca9affc8bff8edebe0a867.tar.gz
qemu-02bccc7796fec8b39dca9affc8bff8edebe0a867.tar.bz2
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>
Diffstat (limited to 'hw/mips')
-rw-r--r--hw/mips/mips_malta.c60
1 files changed, 57 insertions, 3 deletions
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 2edc8e1..e06e19d 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -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