On Wed, Jan 02, 2019 at 03:06:38AM +0100, BALATON Zoltan wrote:
There are several boards with SPD EEPROMs that are now using
duplicated or slightly different hard coded data. Add a helper to
generate SPD data for a memory module of given type and size that
could be used by these boards (either as is or with further changes if
needed) which should help cleaning this up and avoid further duplication.
Signed-off-by: BALATON Zoltan <address@hidden>
---
hw/i2c/smbus_eeprom.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++
include/hw/i2c/smbus.h | 3 ++
2 files changed, 131 insertions(+)
diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c
index f18aa3de35..a1f51eb921 100644
--- a/hw/i2c/smbus_eeprom.c
+++ b/hw/i2c/smbus_eeprom.c
@@ -23,6 +23,8 @@
*/
#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qemu/units.h"
#include "hw/hw.h"
#include "hw/i2c/i2c.h"
#include "hw/i2c/smbus.h"
@@ -162,3 +164,129 @@ void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom,
smbus_eeprom_init_one(smbus, 0x50 + i, eeprom_buf + (i * 256));
}
}
+
+/* Generate SDRAM SPD EEPROM data describing a module of type and size */
+uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t ram_size)
+{
+ uint8_t *spd;
+ uint8_t nbanks;
+ uint16_t density;
+ uint32_t size;
+ int min_log2, max_log2, sz_log2;
+ int i;
+
+ switch (type) {
+ case SDR:
+ min_log2 = 2;
+ max_log2 = 9;
+ break;
+ case DDR:
+ min_log2 = 5;
+ max_log2 = 12;
+ break;
+ case DDR2:
+ min_log2 = 7;
+ max_log2 = 14;
+ break;
+ default:
+ error_report("Unknown SDRAM type");
+ abort();
The error handling might work a little cleaner if you give this
function an Error ** parameter, then just pass in &error_abort from
the callers.
+ }
+ size = ram_size >> 20; /* work in terms of megabytes */
+ if (size < 4) {
+ error_report("SDRAM size is too small");
+ return NULL;
+ }
+ sz_log2 = 31 - clz32(size);
+ size = 1U << sz_log2;
+ if (ram_size > size * MiB) {
+ warn_report("SDRAM size 0x"RAM_ADDR_FMT" is not a power of 2, "
+ "truncating to %u MB", ram_size, size);
+ }
+ if (sz_log2 < min_log2) {
+ warn_report("Memory size is too small for SDRAM type, adjusting type");
+ if (size >= 32) {
+ type = DDR;
+ min_log2 = 5;
+ max_log2 = 12;
+ } else {
+ type = SDR;
+ min_log2 = 2;
+ max_log2 = 9;
+ }
What do these various fall back cases represent? Are they bugs in the
callers, or a user configuration error?