From: "Marek Behún" <kabel@kernel.org>
To: Stefan Roese <sr@denx.de>
Cc: u-boot@lists.denx.de, "Marek Behún" <kabel@kernel.org>
Subject: [PATCH u-boot-marvell 11/16] arm: mvebu: turris_omnia: Read DDR speed from EEPROM
Date: Tue, 18 Jun 2024 17:34:34 +0200 [thread overview]
Message-ID: <20240618153439.9518-12-kabel@kernel.org> (raw)
In-Reply-To: <20240618153439.9518-1-kabel@kernel.org>
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>
---
board/CZ.NIC/turris_omnia/eeprom.c | 41 +++++++++-
board/CZ.NIC/turris_omnia/turris_omnia.c | 99 +++++++++++++++++++++++-
2 files changed, 135 insertions(+), 5 deletions(-)
diff --git a/board/CZ.NIC/turris_omnia/eeprom.c b/board/CZ.NIC/turris_omnia/eeprom.c
index ea13e95b37..32572481ce 100644
--- a/board/CZ.NIC/turris_omnia/eeprom.c
+++ b/board/CZ.NIC/turris_omnia/eeprom.c
@@ -55,12 +55,49 @@ static int eeprom_field_update_region(struct eeprom_field *field, char *value)
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 @@ static int omnia_update_field(struct eeprom_layout *layout, char *field_name,
}
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);
}
diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c
index c2f91b762f..544784e860 100644
--- a/board/CZ.NIC/turris_omnia/turris_omnia.c
+++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
@@ -431,7 +431,8 @@ struct omnia_eeprom {
u32 crc;
/* second part (only considered if crc2 is not all-ones) */
- u8 reserved[44];
+ char ddr_speed[5];
+ u8 reserved[39];
u32 crc2;
};
@@ -520,6 +521,26 @@ static int omnia_get_ram_size_gb(void)
return ram_size;
}
+static const char *omnia_get_ddr_speed(void)
+{
+ struct omnia_eeprom oep;
+ static char speed[sizeof(oep.ddr_speed) + 1];
+
+ if (!omnia_read_eeprom(&oep))
+ return NULL;
+
+ if (!is_omnia_eeprom_second_part_valid(&oep))
+ return NULL;
+
+ if (!oep.ddr_speed[0] || oep.ddr_speed[0] == 0xff)
+ return NULL;
+
+ memcpy(&speed, &oep.ddr_speed, sizeof(oep.ddr_speed));
+ speed[sizeof(speed) - 1] = '\0';
+
+ return speed;
+}
+
static const char * const omnia_get_mcu_type(void)
{
static char result[] = "xxxxxxx (with peripheral resets)";
@@ -634,12 +655,84 @@ static struct mv_ddr_topology_map board_topology_map_2g = {
{0} /* timing parameters */
};
+static const struct omnia_ddr_speed {
+ char name[5];
+ u8 speed_bin;
+ u8 freq;
+} omnia_ddr_speeds[] = {
+ { "1066F", SPEED_BIN_DDR_1066F, MV_DDR_FREQ_533 },
+ { "1333H", SPEED_BIN_DDR_1333H, MV_DDR_FREQ_667 },
+ { "1600K", SPEED_BIN_DDR_1600K, MV_DDR_FREQ_800 },
+};
+
+static const struct omnia_ddr_speed *find_ddr_speed_setting(const char *name)
+{
+ for (int i = 0; i < ARRAY_SIZE(omnia_ddr_speeds); ++i)
+ if (!strncmp(name, omnia_ddr_speeds[i].name, 5))
+ return &omnia_ddr_speeds[i];
+
+ return NULL;
+}
+
+bool omnia_valid_ddr_speed(const char *name)
+{
+ return find_ddr_speed_setting(name) != NULL;
+}
+
+void omnia_print_ddr_speeds(void)
+{
+ for (int i = 0; i < ARRAY_SIZE(omnia_ddr_speeds); ++i)
+ printf("%.5s%s", omnia_ddr_speeds[i].name,
+ i == ARRAY_SIZE(omnia_ddr_speeds) - 1 ? "\n" : ", ");
+}
+
+static void fixup_speed_in_ddr_topology(struct mv_ddr_topology_map *topology)
+{
+ typeof(topology->interface_params[0]) *params;
+ const struct omnia_ddr_speed *setting;
+ const char *speed;
+ static bool done;
+
+ if (done)
+ return;
+
+ done = true;
+
+ speed = omnia_get_ddr_speed();
+ if (!speed)
+ return;
+
+ setting = find_ddr_speed_setting(speed);
+ if (!setting) {
+ printf("Unsupported value %s for DDR3 speed in EEPROM!\n",
+ speed);
+ return;
+ }
+
+ params = &topology->interface_params[0];
+
+ /* don't inform if we are not changing the speed from the default one */
+ if (params->speed_bin_index == setting->speed_bin)
+ return;
+
+ printf("Fixing up DDR3 speed (EEPROM defines %s)\n", speed);
+
+ params->speed_bin_index = setting->speed_bin;
+ params->memory_freq = setting->freq;
+}
+
struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
{
+ struct mv_ddr_topology_map *topology;
+
if (omnia_get_ram_size_gb() == 2)
- return &board_topology_map_2g;
+ topology = &board_topology_map_2g;
else
- return &board_topology_map_1g;
+ topology = &board_topology_map_1g;
+
+ fixup_speed_in_ddr_topology(topology);
+
+ return topology;
}
static int set_regdomain(void)
--
2.44.2
next prev parent reply other threads:[~2024-06-18 15:36 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-18 15:34 [PATCH u-boot-marvell 00/16] Turris Omnia DDR training changes Marek Behún
2024-06-18 15:34 ` [PATCH u-boot-marvell 01/16] arm: mvebu: turris_omnia: Disable ext4 write support in defconfig Marek Behún
2024-06-18 15:34 ` [PATCH u-boot-marvell 02/16] ddr: marvell: a38x: debug: return from ddr3_tip_print_log() early if we won't print anything Marek Behún
2024-06-18 15:34 ` [PATCH u-boot-marvell 03/16] ddr: marvell: a38x: debug: Remove unused variables Marek Behún
2024-06-18 15:34 ` [PATCH u-boot-marvell 04/16] ddr: marvell: a38x: debug: Define DDR_VIEWER_TOOL variables only if needed, and make them static Marek Behún
2024-06-18 15:34 ` [PATCH u-boot-marvell 05/16] ddr: marvell: a38x: debug: Allow compiling with immutable debug settings to reduce binary size Marek Behún
2024-06-18 15:34 ` [PATCH u-boot-marvell 06/16] arm: mvebu: turris_omnia: Enable immutable debug settings in DDR3 training by default Marek Behún
2024-06-18 15:34 ` [PATCH u-boot-marvell 07/16] arm: mvebu: turris_omnia: Fix ethernet PHY reset gpio FDT fixup Marek Behún
2024-06-18 15:34 ` [PATCH u-boot-marvell 08/16] arm: mvebu: turris_omnia: Implement EEPROM layout for the 'eeprom' command Marek Behún
2024-06-18 15:34 ` [PATCH u-boot-marvell 09/16] arm: mvebu: turris_omnia: Enable " Marek Behún
2024-06-18 15:34 ` [PATCH u-boot-marvell 10/16] arm: mvebu: turris_omnia: Extend EEPROM info structure Marek Behún
2024-06-18 15:34 ` Marek Behún [this message]
2024-06-18 15:34 ` [PATCH u-boot-marvell 12/16] ddr: marvell: a38x: Import old DDR training code from 2017 version of U-Boot Marek Behún
2024-06-18 15:34 ` [PATCH u-boot-marvell 13/16] ddr: marvell: a38x: old: Fix some compiler warning of the old code Marek Behún
2024-06-18 15:34 ` [PATCH u-boot-marvell 14/16] ddr: marvell: a38x: old: Backport immutable debug settings Marek Behún
2024-06-18 15:34 ` [PATCH u-boot-marvell 15/16] arm: mvebu: a38x: Add optional support for using old DDR3 training code Marek Behún
2024-06-18 15:34 ` [PATCH u-boot-marvell 16/16] arm: mvebu: turris_omnia: Support old DDR3 training Marek Behún
2024-07-08 14:16 ` [PATCH u-boot-marvell 00/16] Turris Omnia DDR training changes Stefan Roese
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240618153439.9518-12-kabel@kernel.org \
--to=kabel@kernel.org \
--cc=sr@denx.de \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.