arm: mvebu: turris_omnia: Read DDR speed from EEPROM
Some Turris Omnia boards experience memory issues, and by
experimentation we found that some of these issues can be solved by
slowing DDR speed.
Add a new field in the extended EEPROM information structure, ddr_speed.
Support several values in this field (for now 1066F, 1333H, and the
default, 1600K) and use it to overwrite the DDR topology parameters
used by the DDR training algorithm.
Signed-off-by: Marek BehĂșn <kabel@kernel.org>
diff --git a/board/CZ.NIC/turris_omnia/eeprom.c b/board/CZ.NIC/turris_omnia/eeprom.c
index ea13e95..3257248 100644
--- a/board/CZ.NIC/turris_omnia/eeprom.c
+++ b/board/CZ.NIC/turris_omnia/eeprom.c
@@ -55,12 +55,49 @@
return 0;
}
+static void eeprom_field_print_ddr_speed(const struct eeprom_field *field)
+{
+ printf(PRINT_FIELD_SEGMENT, field->name);
+
+ if (field->buf[0] == '\0' || field->buf[0] == 0xff)
+ puts("(empty, defaults to 1600K)\n");
+ else
+ printf("%.5s\n", field->buf);
+}
+
+bool omnia_valid_ddr_speed(const char *name);
+void omnia_print_ddr_speeds(void);
+
+static int eeprom_field_update_ddr_speed(struct eeprom_field *field,
+ char *value)
+{
+ if (value[0] == '\0') {
+ /* setting default value */
+ memset(field->buf, 0xff, field->size);
+
+ return 0;
+ }
+
+ if (!omnia_valid_ddr_speed(value)) {
+ printf("%s: invalid setting, supported values are:\n ",
+ field->name);
+ omnia_print_ddr_speeds();
+
+ return -1;
+ }
+
+ strncpy(field->buf, value, field->size);
+
+ return 0;
+}
+
static struct eeprom_field omnia_layout[] = {
_DEF_FIELD("Magic constant", 4, bin),
_DEF_FIELD("RAM size in GB", 4, ramsz),
_DEF_FIELD("Wi-Fi Region", 4, region),
_DEF_FIELD("CRC32 checksum", 4, bin),
- _DEF_FIELD("Extended reserved fields", 44, reserved),
+ _DEF_FIELD("DDR speed", 5, ddr_speed),
+ _DEF_FIELD("Extended reserved fields", 39, reserved),
_DEF_FIELD("Extended CRC32 checksum", 4, bin),
};
@@ -96,7 +133,7 @@
}
if (field < ext_crc_field) {
- u32 crc = crc32(0, layout->data, 44);
+ u32 crc = crc32(0, layout->data, 60);
put_unaligned_le32(crc, ext_crc_field->buf);
}