]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
arm: mvebu: turris_omnia: Support old DDR3 training
authorMarek Behún <kabel@kernel.org>
Tue, 18 Jun 2024 15:34:39 +0000 (17:34 +0200)
committerStefan Roese <sr@denx.de>
Mon, 8 Jul 2024 06:20:58 +0000 (08:20 +0200)
Support old DDR3 training code on Turris Omnia, selectable via EEPROM
field.

Users experiencing DDR3 initialization failures or random crashes of the
operating system due to incorrect DDR3 configuration can select the old
DDR3 training implementation to fix those issues by setting the EEPROM
field "Use old DDR training":
  eeprom update "Use old DDR training" 1

Signed-off-by: Marek Behún <kabel@kernel.org>
arch/arm/mach-mvebu/Kconfig
board/CZ.NIC/turris_omnia/Makefile
board/CZ.NIC/turris_omnia/eeprom.c
board/CZ.NIC/turris_omnia/old_ddr3_training.c [new file with mode: 0644]
board/CZ.NIC/turris_omnia/turris_omnia.c

index e377e8a48a965440c034ee5a7966a61ec8015d79..4a8328760eb58e9b0d0770b5978ae4a3f1f5bb94 100644 (file)
@@ -149,6 +149,7 @@ config TARGET_TURRIS_OMNIA
        select SPL_SYS_MALLOC_SIMPLE
        select SYS_I2C_MVTWSI
        select ATSHA204A
+       select ARMADA_38X_SUPPORT_OLD_DDR3_TRAINING
 
 config TARGET_TURRIS_MOX
        bool "Support CZ.NIC's Turris Mox / RIPE Atlas Probe"
index 216e11958a74c99fb958af8d030eed05952d35b8..d1ef5cb8600001a206a57325537aebc806b1a5ee 100644 (file)
@@ -4,3 +4,4 @@
 
 obj-y  := turris_omnia.o ../turris_atsha_otp.o ../turris_common.o
 obj-$(CONFIG_CMD_EEPROM_LAYOUT)        += eeprom.o
+obj-$(CONFIG_SPL_BUILD)                += old_ddr3_training.o
index 32572481ce9cc63d929df0d409d5f5e8fcf03c01..6e2640ad2a7709a13958671c070bcf1e49aa4999 100644 (file)
@@ -91,13 +91,48 @@ static int eeprom_field_update_ddr_speed(struct eeprom_field *field,
        return 0;
 }
 
+static void eeprom_field_print_bool(const struct eeprom_field *field)
+{
+       unsigned char val = field->buf[0];
+
+       printf(PRINT_FIELD_SEGMENT, field->name);
+
+       if (val == 0xff)
+               puts("(empty, defaults to 0)\n");
+       else
+               printf("%u\n", val);
+}
+
+static int eeprom_field_update_bool(struct eeprom_field *field, char *value)
+{
+       unsigned char *val = &field->buf[0];
+
+       if (value[0] == '\0') {
+               /* setting default value */
+               *val = 0xff;
+
+               return 0;
+       }
+
+       if (value[1] != '\0')
+               return -1;
+
+       if (value[0] == '1' || value[0] == '0')
+               *val = value[0] - '0';
+       else
+               return -1;
+
+       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("DDR speed", 5, ddr_speed),
-       _DEF_FIELD("Extended reserved fields", 39, reserved),
+       _DEF_FIELD("Use old DDR training", 1, bool),
+       _DEF_FIELD("Extended reserved fields", 38, reserved),
        _DEF_FIELD("Extended CRC32 checksum", 4, bin),
 };
 
diff --git a/board/CZ.NIC/turris_omnia/old_ddr3_training.c b/board/CZ.NIC/turris_omnia/old_ddr3_training.c
new file mode 100644 (file)
index 0000000..cdb3487
--- /dev/null
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2024 Marek Behún <kabel@kernel.org>
+ */
+
+#include <asm/arch/soc.h>
+#include <asm/io.h>
+
+#include "../drivers/ddr/marvell/a38x/old/ddr3_init.h"
+
+static struct hws_topology_map board_topology_map_1g = {
+       0x1, /* active interfaces */
+       /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */
+       { { { {0x1, 0, 0, 0},
+             {0x1, 0, 0, 0},
+             {0x1, 0, 0, 0},
+             {0x1, 0, 0, 0},
+             {0x1, 0, 0, 0} },
+           SPEED_BIN_DDR_1600K,        /* speed_bin */
+           BUS_WIDTH_16,               /* memory_width */
+           MEM_4G,                     /* mem_size */
+           DDR_FREQ_800,               /* frequency */
+           0, 0,                       /* cas_l cas_wl */
+           HWS_TEMP_NORMAL,            /* temperature */
+           HWS_TIM_2T} },              /* timing (force 2t) */
+       5,                              /* Num Of Bus Per Interface*/
+       BUS_MASK_32BIT                  /* Busses mask */
+};
+
+static struct hws_topology_map board_topology_map_2g = {
+       0x1, /* active interfaces */
+       /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */
+       { { { {0x1, 0, 0, 0},
+             {0x1, 0, 0, 0},
+             {0x1, 0, 0, 0},
+             {0x1, 0, 0, 0},
+             {0x1, 0, 0, 0} },
+           SPEED_BIN_DDR_1600K,        /* speed_bin */
+           BUS_WIDTH_16,               /* memory_width */
+           MEM_8G,                     /* mem_size */
+           DDR_FREQ_800,               /* frequency */
+           0, 0,                       /* cas_l cas_wl */
+           HWS_TEMP_NORMAL,            /* temperature */
+           HWS_TIM_2T} },              /* timing (force 2t) */
+       5,                              /* Num Of Bus Per Interface*/
+       BUS_MASK_32BIT                  /* Busses mask */
+};
+
+/* defined in turris_omnia.c */
+extern int omnia_get_ram_size_gb(void);
+
+struct hws_topology_map *ddr3_get_topology_map(void)
+{
+       if (omnia_get_ram_size_gb() == 2)
+               return &board_topology_map_2g;
+       else
+               return &board_topology_map_1g;
+}
+
+__weak u32 sys_env_get_topology_update_info(struct topology_update_info *tui)
+{
+       return MV_OK;
+}
index 544784e860e1e6cba488d577648ba9e3e0631f89..2f29d26edf897e93693e55d70eaacef6373583fa 100644 (file)
@@ -432,7 +432,8 @@ struct omnia_eeprom {
 
        /* second part (only considered if crc2 is not all-ones) */
        char ddr_speed[5];
-       u8 reserved[39];
+       u8 old_ddr_training;
+       u8 reserved[38];
        u32 crc2;
 };
 
@@ -496,7 +497,7 @@ static bool omnia_read_eeprom(struct omnia_eeprom *oep)
        return true;
 }
 
-static int omnia_get_ram_size_gb(void)
+int omnia_get_ram_size_gb(void)
 {
        static int ram_size;
        struct omnia_eeprom oep;
@@ -521,6 +522,19 @@ static int omnia_get_ram_size_gb(void)
        return ram_size;
 }
 
+bool board_use_old_ddr3_training(void)
+{
+       struct omnia_eeprom oep;
+
+       if (!omnia_read_eeprom(&oep))
+               return false;
+
+       if (!is_omnia_eeprom_second_part_valid(&oep))
+               return false;
+
+       return oep.old_ddr_training == 1;
+}
+
 static const char *omnia_get_ddr_speed(void)
 {
        struct omnia_eeprom oep;