ddr: marvell: a38x: Add support for DDR4 from Marvell mv-ddr-marvell repository
This syncs drivers/ddr/marvell/a38x/ with the master branch of repository
https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git
up to the commit "mv_ddr: a3700: Use the right size for memset to not overflow"
d5acc10c287e40cc2feeb28710b92e45c93c702c
This patch was created by following steps:
1. Replace all a38x files in U-Boot tree by files from upstream github
Marvell mv-ddr-marvell repository.
2. Run following command to omit portions not relevant for a38x, ddr3, and ddr4:
files=drivers/ddr/marvell/a38x/*
unifdef -m -UMV_DDR -UMV_DDR_ATF -UCONFIG_APN806 \
-UCONFIG_MC_STATIC -UCONFIG_MC_STATIC_PRINT -UCONFIG_PHY_STATIC \
-UCONFIG_PHY_STATIC_PRINT -UCONFIG_CUSTOMER_BOARD_SUPPORT \
-UCONFIG_A3700 -UA3900 -UA80X0 -UA70X0 -DCONFIG_ARMADA_38X -UCONFIG_ARMADA_39X \
-UCONFIG_64BIT $files
3. Manually change license to SPDX-License-Identifier
(upstream license in upstream github repository contains long license
texts and U-Boot is using just SPDX-License-Identifier.
After applying this patch, a38x, ddr3, and ddr4 code in upstream Marvell github
repository and in U-Boot would be fully identical. So in future applying
above steps could be used to sync code again.
The only change in this patch are:
1. Some fixes with include files.
2. Some function return and basic type defines changes in
mv_ddr_plat.c (to correct Marvell bug).
3. Remove of dead code in newly copied files (as a result of the
filter script stripping out everything other than a38x, dd3, and ddr4).
Reference:
"ddr: marvell: a38x: Sync code with Marvell mv-ddr-marvell repository"
https://source.denx.de/u-boot/u-boot/-/commit/107c3391b95bcc2ba09a876da4fa0c31b6c1e460
Signed-off-by: Tony Dinh <mibodhi@gmail.com>
Reviewed-by: Pali Rohár <pali@kernel.org>
Reviewed-by: Stefan Roese <sr@denx.de>
diff --git a/drivers/ddr/marvell/a38x/ddr3_training_db.c b/drivers/ddr/marvell/a38x/ddr3_training_db.c
index 6aa7b60..47ba911 100644
--- a/drivers/ddr/marvell/a38x/ddr3_training_db.c
+++ b/drivers/ddr/marvell/a38x/ddr3_training_db.c
@@ -25,6 +25,98 @@
static inline u32 pattern_table_get_isi_word(u8 index);
static inline u32 pattern_table_get_isi_word16(u8 index);
+#if defined(CONFIG_DDR4)
+u8 pattern_killer_map[KILLER_PATTERN_LENGTH * 2] = {
+ 0x01,
+ 0x00,
+ 0x01,
+ 0xff,
+ 0xfe,
+ 0xfe,
+ 0x01,
+ 0xfe,
+ 0x01,
+ 0xfe,
+ 0x01,
+ 0x01,
+ 0xfe,
+ 0x01,
+ 0xfe,
+ 0x00,
+ 0xff,
+ 0x00,
+ 0xff,
+ 0x00,
+ 0xff,
+ 0x00,
+ 0xff,
+ 0x01,
+ 0x00,
+ 0xff,
+ 0x00,
+ 0xff,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xfe,
+ 0xfe,
+ 0xff,
+ 0x00,
+ 0x00,
+ 0xff,
+ 0xff,
+ 0x00,
+ 0xff,
+ 0x00,
+ 0xff,
+ 0xff,
+ 0x00,
+ 0x00,
+ 0xff,
+ 0x00,
+ 0xff,
+ 0xfe,
+ 0x00,
+ 0xfe,
+ 0xfe,
+ 0x00,
+ 0xff,
+ 0xff,
+ 0x01,
+ 0x01,
+ 0xff,
+ 0xff,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0xff
+};
+static inline u32 pattern_table_get_killer_word_4(u8 dqs, u8 index)
+{
+ u8 byte;
+
+ if (index >= (KILLER_PATTERN_LENGTH * 2)) {
+ printf("error: %s: invalid index [%u] found\n", __func__, index);
+ return 0;
+ }
+
+ byte = pattern_killer_map[index];
+
+ switch (byte) {
+ case 0x01:
+ byte = 1 << dqs;
+ break;
+ case 0xfe:
+ byte = 0xff & ~(1 << dqs);
+ break;
+ default:
+ break;
+ }
+
+ return byte | (byte << 8) | (byte << 16) | (byte << 24);
+}
+#else /* !CONFIG_DDR4 */
/* List of allowed frequency listed in order of enum mv_ddr_freq */
static unsigned int freq_val[MV_DDR_FREQ_LAST] = {
0, /*MV_DDR_FREQ_LOW_FREQ */
@@ -302,6 +394,7 @@
12155,
13090,
};
+#endif /* CONFIG_DDR4 */
enum {
PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR = 0,
@@ -388,6 +481,7 @@
0xfe
};
+#if !defined(CONFIG_DDR4)
static struct mv_ddr_page_element page_tbl[] = {
/* 8-bit, 16-bit page size */
{MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 512M */
@@ -521,6 +615,7 @@
return byte | (byte << 8) | (byte << 16) | (byte << 24);
}
+#endif /* !CONFIG_DDR4 */
static inline u32 pattern_table_get_killer_word16(u8 dqs, u8 index)
{
@@ -651,6 +746,7 @@
return 0xffffffff;
}
+#if !defined(CONFIG_DDR4)
static inline u32 pattern_table_get_static_pbs_word(u8 index)
{
u16 temp;
@@ -659,6 +755,7 @@
return temp | (temp << 8) | (temp << 16) | (temp << 24);
}
+#endif /* !CONFIG_DDR4 */
u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index)
{
@@ -670,26 +767,36 @@
switch (type) {
case PATTERN_PBS1:
case PATTERN_PBS2:
+#if !defined(CONFIG_DDR4)
if (index == 0 || index == 2 || index == 5 ||
index == 7)
pattern = PATTERN_55;
else
pattern = PATTERN_AA;
break;
+#endif /* !CONFIG_DDR4 */
case PATTERN_PBS3:
+#if !defined(CONFIG_DDR4)
if (0 == (index & 1))
pattern = PATTERN_55;
else
pattern = PATTERN_AA;
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_RL:
+#if !defined(CONFIG_DDR4)
if (index < 6)
pattern = PATTERN_00;
else
pattern = PATTERN_80;
+#else /* CONFIG_DDR4 */
+ pattern = PATTERN_00;
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_STATIC_PBS:
+#if !defined(CONFIG_DDR4)
pattern = pattern_table_get_static_pbs_word(index);
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_KILLER_DQ0:
case PATTERN_KILLER_DQ1:
@@ -699,14 +806,22 @@
case PATTERN_KILLER_DQ5:
case PATTERN_KILLER_DQ6:
case PATTERN_KILLER_DQ7:
+#if !defined(CONFIG_DDR4)
pattern = pattern_table_get_killer_word(
+#else /* CONFIG_DDR4 */
+ pattern = pattern_table_get_killer_word_4(
+#endif /* !CONFIG_DDR4 */
(u8)(type - PATTERN_KILLER_DQ0), index);
break;
case PATTERN_RL2:
+#if !defined(CONFIG_DDR4)
if (index < 6)
pattern = PATTERN_00;
else
pattern = PATTERN_01;
+#else /* !CONFIG_DDR4 */
+ pattern = PATTERN_FF;
+#endif /* CONFIG_DDR4 */
break;
case PATTERN_TEST:
if (index > 1 && index < 6)
@@ -749,6 +864,46 @@
case PATTERN_ISI_XTALK_FREE:
pattern = pattern_table_get_isi_word(index);
break;
+#if defined(CONFIG_DDR4)
+ case PATTERN_KILLER_DQ0_INV:
+ case PATTERN_KILLER_DQ1_INV:
+ case PATTERN_KILLER_DQ2_INV:
+ case PATTERN_KILLER_DQ3_INV:
+ case PATTERN_KILLER_DQ4_INV:
+ case PATTERN_KILLER_DQ5_INV:
+ case PATTERN_KILLER_DQ6_INV:
+ case PATTERN_KILLER_DQ7_INV:
+ pattern = ~pattern_table_get_killer_word_4(
+ (u8)(type - PATTERN_KILLER_DQ0_INV), index);
+ break;
+ case PATTERN_RESONANCE_1T:
+ case PATTERN_RESONANCE_2T:
+ case PATTERN_RESONANCE_3T:
+ case PATTERN_RESONANCE_4T:
+ case PATTERN_RESONANCE_5T:
+ case PATTERN_RESONANCE_6T:
+ case PATTERN_RESONANCE_7T:
+ case PATTERN_RESONANCE_8T:
+ case PATTERN_RESONANCE_9T:
+ {
+ u8 t_num = (u8)(type - PATTERN_RESONANCE_1T);
+ u8 t_end = (59 / t_num) * t_num;
+ if (index < t_end)
+ pattern = ((index % (t_num * 2)) >= t_num) ? 0xffffffff : 0x00000000;
+ else
+ pattern = ((index % 2) == 0) ? 0xffffffff : 0x00000000;
+ }
+ break;
+ case PATTERN_ZERO:
+ pattern = PATTERN_00;
+ break;
+ case PATTERN_ONE:
+ pattern = PATTERN_FF;
+ break;
+ case PATTERN_VREF_INV:
+ pattern = ~pattern_table_get_vref_word(index);
+ break;
+#endif /* CONFIG_DDR4 */
default:
printf("error: %s: unsupported pattern type [%d] found\n",
__func__, (int)type);
@@ -761,16 +916,24 @@
case PATTERN_PBS1:
case PATTERN_PBS2:
case PATTERN_PBS3:
+#if !defined(CONFIG_DDR4)
pattern = PATTERN_55AA;
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_RL:
+#if !defined(CONFIG_DDR4)
if (index < 3)
pattern = PATTERN_00;
else
pattern = PATTERN_80;
+#else /* CONFIG_DDR4 */
+ pattern = PATTERN_00;
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_STATIC_PBS:
+#if !defined(CONFIG_DDR4)
pattern = PATTERN_00FF;
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_KILLER_DQ0:
case PATTERN_KILLER_DQ1:
@@ -784,25 +947,40 @@
(u8)(type - PATTERN_KILLER_DQ0), index);
break;
case PATTERN_RL2:
+#if !defined(CONFIG_DDR4)
if (index < 3)
pattern = PATTERN_00;
else
pattern = PATTERN_01;
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_TEST:
+#if !defined(CONFIG_DDR4)
if ((index == 0) || (index == 3))
pattern = 0x00000000;
else
pattern = 0xFFFFFFFF;
+#else /* CONFIG_DDR4 */
+ if ((index > 1) && (index < 6))
+ pattern = PATTERN_20;
+ else
+ pattern = PATTERN_00;
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_FULL_SSO0:
+#if !defined(CONFIG_DDR4)
pattern = 0x0000ffff;
break;
+#endif /* !CONFIG_DDR4 */
case PATTERN_FULL_SSO1:
case PATTERN_FULL_SSO2:
case PATTERN_FULL_SSO3:
pattern = pattern_table_get_sso_word(
+#if !defined(CONFIG_DDR4)
(u8)(type - PATTERN_FULL_SSO1), index);
+#else /* CONFIG_DDR4 */
+ (u8)(type - PATTERN_FULL_SSO0), index);
+#endif /* !CONFIG_DDR4 */
break;
case PATTERN_VREF:
pattern = pattern_table_get_vref_word16(index);
@@ -832,6 +1010,40 @@
case PATTERN_ISI_XTALK_FREE:
pattern = pattern_table_get_isi_word16(index);
break;
+#if defined(CONFIG_DDR4)
+ case PATTERN_KILLER_DQ0_INV:
+ case PATTERN_KILLER_DQ1_INV:
+ case PATTERN_KILLER_DQ2_INV:
+ case PATTERN_KILLER_DQ3_INV:
+ case PATTERN_KILLER_DQ4_INV:
+ case PATTERN_KILLER_DQ5_INV:
+ case PATTERN_KILLER_DQ6_INV:
+ case PATTERN_KILLER_DQ7_INV:
+ pattern = ~pattern_table_get_killer_word16(
+ (u8)(type - PATTERN_KILLER_DQ0_INV), index);
+ break;
+ case PATTERN_RESONANCE_1T:
+ case PATTERN_RESONANCE_2T:
+ case PATTERN_RESONANCE_3T:
+ case PATTERN_RESONANCE_4T:
+ case PATTERN_RESONANCE_5T:
+ case PATTERN_RESONANCE_6T:
+ case PATTERN_RESONANCE_7T:
+ case PATTERN_RESONANCE_8T:
+ case PATTERN_RESONANCE_9T:
+ {
+ u8 t_num = (u8)(type - PATTERN_RESONANCE_1T);
+ u8 t_end = (59 / t_num) * t_num;
+ if (index < t_end)
+ pattern = ((index % (t_num * 2)) >= t_num) ? 0xffffffff : 0x00000000;
+ else
+ pattern = ((index % 2) == 0) ? 0xffffffff : 0x00000000;
+ }
+ break;
+ case PATTERN_VREF_INV:
+ pattern = ~pattern_table_get_vref_word16(index);
+ break;
+#endif /* CONFIG_DDR4 */
default:
if (((int)type == 29) || ((int)type == 30))
break;