From mboxrd@z Thu Jan 1 00:00:00 1970 From: Chris Packham Date: Mon, 9 Apr 2018 22:12:55 +1200 Subject: [U-Boot] [PATCH v2 4/6] ARM: mvebu: a38x: sync ddr training code with upstream In-Reply-To: <20180409101257.3899-1-judge.packham@gmail.com> References: <20180409101257.3899-1-judge.packham@gmail.com> Message-ID: <20180409101257.3899-5-judge.packham@gmail.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de This syncs drivers/ddr/marvell/a38x/ with the mv_ddr-armada-17.10 branch of https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git. The upstream code is incorporated omitting the ddr4 and apn806 and folding the nested a38x directory up one level. After that a semi-automated step is used to drop unused features with unifdef find drivers/ddr/marvell/a38x/ -name '*.[ch]' | \ xargs unifdef -m -UMV_DDR -UMV_DDR_ATF -UCONFIG_DDR4 \ -UCONFIG_APN806 -UCONFIG_MC_STATIC \ -UCONFIG_MC_STATIC_PRINT -UCONFIG_PHY_STATIC \ -UCONFIG_64BIT INTER_REGS_BASE is updated to be defined as SOC_REGS_PHY_BASE. Some now empty files are removed and the ternary license is replaced with a SPDX GPL-2.0+ identifier. Signed-off-by: Chris Packham --- Changes in v2: New board/CZ.NIC/turris_omnia/turris_omnia.c | 36 +- board/Marvell/db-88f6820-amc/db-88f6820-amc.c | 20 +- board/Marvell/db-88f6820-gp/db-88f6820-gp.c | 20 +- board/gdsys/a38x/controlcenterdc.c | 21 +- board/solidrun/clearfog/clearfog.c | 20 +- drivers/ddr/marvell/a38x/Makefile | 10 +- drivers/ddr/marvell/a38x/ddr3_a38x.c | 686 --------- drivers/ddr/marvell/a38x/ddr3_a38x.h | 93 -- drivers/ddr/marvell/a38x/ddr3_a38x_topology.h | 22 - drivers/ddr/marvell/a38x/ddr3_a38x_training.c | 40 - drivers/ddr/marvell/a38x/ddr3_debug.c | 733 ++++++---- drivers/ddr/marvell/a38x/ddr3_hws_hw_training.c | 148 -- drivers/ddr/marvell/a38x/ddr3_hws_hw_training.h | 49 - .../ddr/marvell/a38x/ddr3_hws_hw_training_def.h | 462 ------- drivers/ddr/marvell/a38x/ddr3_hws_sil_training.h | 17 - drivers/ddr/marvell/a38x/ddr3_init.c | 745 ++-------- drivers/ddr/marvell/a38x/ddr3_init.h | 299 +--- drivers/ddr/marvell/a38x/ddr3_logging_def.h | 10 +- drivers/ddr/marvell/a38x/ddr3_patterns_64bit.h | 1 + drivers/ddr/marvell/a38x/ddr3_topology_def.h | 6 +- drivers/ddr/marvell/a38x/ddr3_training.c | 1450 +++++++++++-------- drivers/ddr/marvell/a38x/ddr3_training_bist.c | 548 ++++++-- .../marvell/a38x/ddr3_training_centralization.c | 108 +- drivers/ddr/marvell/a38x/ddr3_training_db.c | 267 +++- drivers/ddr/marvell/a38x/ddr3_training_hw_algo.c | 98 +- drivers/ddr/marvell/a38x/ddr3_training_ip.h | 19 +- drivers/ddr/marvell/a38x/ddr3_training_ip_bist.h | 6 +- drivers/ddr/marvell/a38x/ddr3_training_ip_db.h | 71 +- drivers/ddr/marvell/a38x/ddr3_training_ip_def.h | 34 +- drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c | 1134 +++++++++------ drivers/ddr/marvell/a38x/ddr3_training_ip_engine.h | 9 +- drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h | 305 +--- drivers/ddr/marvell/a38x/ddr3_training_ip_prv_if.h | 17 +- drivers/ddr/marvell/a38x/ddr3_training_ip_static.h | 31 - drivers/ddr/marvell/a38x/ddr3_training_leveling.c | 1347 ++++++++++-------- drivers/ddr/marvell/a38x/ddr3_training_leveling.h | 2 +- drivers/ddr/marvell/a38x/ddr3_training_pbs.c | 201 +-- drivers/ddr/marvell/a38x/ddr3_training_static.c | 101 -- drivers/ddr/marvell/a38x/ddr_ml_wrapper.h | 149 ++ drivers/ddr/marvell/a38x/ddr_topology_def.h | 85 +- drivers/ddr/marvell/a38x/mv_ddr_build_message.c | 1 + drivers/ddr/marvell/a38x/mv_ddr_common.c | 48 + drivers/ddr/marvell/a38x/mv_ddr_common.h | 21 + drivers/ddr/marvell/a38x/mv_ddr_plat.c | 1456 ++++++++++++++++++++ drivers/ddr/marvell/a38x/mv_ddr_plat.h | 236 ++++ drivers/ddr/marvell/a38x/mv_ddr_regs.h | 447 ++++++ drivers/ddr/marvell/a38x/mv_ddr_spd.c | 378 +++++ drivers/ddr/marvell/a38x/mv_ddr_spd.h | 290 ++++ drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.c | 103 ++ drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.h | 118 ++ drivers/ddr/marvell/a38x/mv_ddr_topology.c | 198 +++ drivers/ddr/marvell/a38x/mv_ddr_topology.h | 124 ++ drivers/ddr/marvell/a38x/seq_exec.h | 65 + drivers/ddr/marvell/a38x/silicon_if.h | 17 - drivers/ddr/marvell/a38x/xor.c | 184 ++- drivers/ddr/marvell/a38x/xor.h | 3 +- 56 files changed, 7958 insertions(+), 5151 deletions(-) delete mode 100644 drivers/ddr/marvell/a38x/ddr3_a38x.c delete mode 100644 drivers/ddr/marvell/a38x/ddr3_a38x.h delete mode 100644 drivers/ddr/marvell/a38x/ddr3_a38x_topology.h delete mode 100644 drivers/ddr/marvell/a38x/ddr3_a38x_training.c delete mode 100644 drivers/ddr/marvell/a38x/ddr3_hws_hw_training.c delete mode 100644 drivers/ddr/marvell/a38x/ddr3_hws_hw_training.h delete mode 100644 drivers/ddr/marvell/a38x/ddr3_hws_hw_training_def.h delete mode 100644 drivers/ddr/marvell/a38x/ddr3_hws_sil_training.h delete mode 100644 drivers/ddr/marvell/a38x/ddr3_training_ip_static.h delete mode 100644 drivers/ddr/marvell/a38x/ddr3_training_static.c create mode 100644 drivers/ddr/marvell/a38x/ddr_ml_wrapper.h create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_build_message.c create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_common.c create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_common.h create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_plat.c create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_plat.h create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_regs.h create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_spd.c create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_spd.h create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.c create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.h create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_topology.c create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_topology.h create mode 100644 drivers/ddr/marvell/a38x/seq_exec.h delete mode 100644 drivers/ddr/marvell/a38x/silicon_if.h diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c index b03c0a3714b1..9477a802acde 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -27,7 +27,7 @@ # include #endif -#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h" +#include "../drivers/ddr/marvell/a38x/ddr3_init.h" #include <../serdes/a38x/high_speed_env_spec.h> DECLARE_GLOBAL_DATA_PTR; @@ -200,7 +200,8 @@ static bool omnia_read_eeprom(struct omnia_eeprom *oep) * be used by the DDR3 init code in the SPL U-Boot version to configure * the DDR3 controller. */ -static struct hws_topology_map board_topology_map_1g = { +static struct mv_ddr_topology_map board_topology_map_1g = { + DEBUG_LEVEL_ERROR, 0x1, /* active interfaces */ /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */ { { { {0x1, 0, 0, 0}, @@ -209,17 +210,19 @@ static struct hws_topology_map board_topology_map_1g = { {0x1, 0, 0, 0}, {0x1, 0, 0, 0} }, SPEED_BIN_DDR_1600K, /* speed_bin */ - BUS_WIDTH_16, /* memory_width */ - MEM_4G, /* mem_size */ + MV_DDR_DEV_WIDTH_16BIT, /* memory_width */ + MV_DDR_DIE_CAP_4GBIT, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_wl cas_l */ - HWS_TEMP_NORMAL, /* temperature */ - HWS_TIM_2T} }, /* timing (force 2t) */ - 5, /* Num Of Bus Per Interface*/ - BUS_MASK_32BIT /* Busses mask */ + MV_DDR_TEMP_NORMAL} }, /* temperature */ + BUS_MASK_32BIT, /* Busses mask */ + MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ + { {0} }, /* raw spd data */ + {0} /* timing parameters */ }; -static struct hws_topology_map board_topology_map_2g = { +static struct mv_ddr_topology_map board_topology_map_2g = { + DEBUG_LEVEL_ERROR, 0x1, /* active interfaces */ /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */ { { { {0x1, 0, 0, 0}, @@ -228,17 +231,18 @@ static struct hws_topology_map board_topology_map_2g = { {0x1, 0, 0, 0}, {0x1, 0, 0, 0} }, SPEED_BIN_DDR_1600K, /* speed_bin */ - BUS_WIDTH_16, /* memory_width */ - MEM_8G, /* mem_size */ + MV_DDR_DEV_WIDTH_16BIT, /* memory_width */ + MV_DDR_DIE_CAP_8GBIT, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_wl cas_l */ - HWS_TEMP_NORMAL, /* temperature */ - HWS_TIM_2T} }, /* timing (force 2t) */ - 5, /* Num Of Bus Per Interface*/ - BUS_MASK_32BIT /* Busses mask */ + MV_DDR_TEMP_NORMAL} }, /* temperature */ + BUS_MASK_32BIT, /* Busses mask */ + MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ + { {0} }, /* raw spd data */ + {0} /* timing parameters */ }; -struct hws_topology_map *ddr3_get_topology_map(void) +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) { static int mem = 0; struct omnia_eeprom oep; diff --git a/board/Marvell/db-88f6820-amc/db-88f6820-amc.c b/board/Marvell/db-88f6820-amc/db-88f6820-amc.c index 7db0095f75ef..2a092cb80418 100644 --- a/board/Marvell/db-88f6820-amc/db-88f6820-amc.c +++ b/board/Marvell/db-88f6820-amc/db-88f6820-amc.c @@ -12,7 +12,7 @@ #include #include -#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h" +#include "../drivers/ddr/marvell/a38x/ddr3_init.h" #include <../serdes/a38x/high_speed_env_spec.h> DECLARE_GLOBAL_DATA_PTR; @@ -56,7 +56,8 @@ int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count) * be used by the DDR3 init code in the SPL U-Boot version to configure * the DDR3 controller. */ -static struct hws_topology_map board_topology_map = { +static struct mv_ddr_topology_map board_topology_map = { + DEBUG_LEVEL_ERROR, 0x1, /* active interfaces */ /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */ { { { {0x1, 0, 0, 0}, @@ -65,17 +66,18 @@ static struct hws_topology_map board_topology_map = { {0x1, 0, 0, 0}, {0x1, 0, 0, 0} }, SPEED_BIN_DDR_1866L, /* speed_bin */ - BUS_WIDTH_8, /* memory_width */ - MEM_2G, /* mem_size */ + MV_DDR_DEV_WIDTH_8BIT, /* memory_width */ + MV_DDR_DIE_CAP_2GBIT, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_wl cas_l */ - HWS_TEMP_LOW, /* temperature */ - HWS_TIM_DEFAULT} }, /* timing */ - 5, /* Num Of Bus Per Interface*/ - BUS_MASK_32BIT /* Busses mask */ + MV_DDR_TEMP_LOW} }, /* temperature */ + BUS_MASK_32BIT, /* Busses mask */ + MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ + { {0} }, /* raw spd data */ + {0} /* timing parameters */ }; -struct hws_topology_map *ddr3_get_topology_map(void) +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) { /* Return the board topology as defined in the board code */ return &board_topology_map; diff --git a/board/Marvell/db-88f6820-gp/db-88f6820-gp.c b/board/Marvell/db-88f6820-gp/db-88f6820-gp.c index b95cd1d4aab5..e3b6f2d8a7e6 100644 --- a/board/Marvell/db-88f6820-gp/db-88f6820-gp.c +++ b/board/Marvell/db-88f6820-gp/db-88f6820-gp.c @@ -12,7 +12,7 @@ #include #include -#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h" +#include "../drivers/ddr/marvell/a38x/ddr3_init.h" #include <../serdes/a38x/high_speed_env_spec.h> DECLARE_GLOBAL_DATA_PTR; @@ -77,7 +77,8 @@ int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count) * be used by the DDR3 init code in the SPL U-Boot version to configure * the DDR3 controller. */ -static struct hws_topology_map board_topology_map = { +static struct mv_ddr_topology_map board_topology_map = { + DEBUG_LEVEL_ERROR, 0x1, /* active interfaces */ /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */ { { { {0x1, 0, 0, 0}, @@ -86,17 +87,18 @@ static struct hws_topology_map board_topology_map = { {0x1, 0, 0, 0}, {0x1, 0, 0, 0} }, SPEED_BIN_DDR_1866L, /* speed_bin */ - BUS_WIDTH_8, /* memory_width */ - MEM_4G, /* mem_size */ + MV_DDR_DEV_WIDTH_8BIT, /* memory_width */ + MV_DDR_DIE_CAP_4GBIT, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_wl cas_l */ - HWS_TEMP_LOW, /* temperature */ - HWS_TIM_DEFAULT} }, /* timing */ - 5, /* Num Of Bus Per Interface*/ - BUS_MASK_32BIT /* Busses mask */ + MV_DDR_TEMP_LOW} }, /* temperature */ + BUS_MASK_32BIT, /* Busses mask */ + MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ + { {0} }, /* raw spd data */ + {0} /* timing parameters */ }; -struct hws_topology_map *ddr3_get_topology_map(void) +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) { /* Return the board topology as defined in the board code */ return &board_topology_map; diff --git a/board/gdsys/a38x/controlcenterdc.c b/board/gdsys/a38x/controlcenterdc.c index 3d74a6dfb897..1b3b881c3996 100644 --- a/board/gdsys/a38x/controlcenterdc.c +++ b/board/gdsys/a38x/controlcenterdc.c @@ -13,7 +13,7 @@ #include #include -#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h" +#include "../drivers/ddr/marvell/a38x/ddr3_init.h" #include "../arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h" #include "keyprogram.h" @@ -40,7 +40,8 @@ DECLARE_GLOBAL_DATA_PTR; * be used by the DDR3 init code in the SPL U-Boot version to configure * the DDR3 controller. */ -static struct hws_topology_map ddr_topology_map = { +static struct mv_ddr_topology_map ddr_topology_map = { + DEBUG_LEVEL_ERROR, 0x1, /* active interfaces */ /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */ { { { {0x1, 0, 0, 0}, @@ -49,14 +50,16 @@ static struct hws_topology_map ddr_topology_map = { {0x1, 0, 0, 0}, {0x1, 0, 0, 0} }, SPEED_BIN_DDR_1600K, /* speed_bin */ - BUS_WIDTH_16, /* memory_width */ - MEM_4G, /* mem_size */ + MV_DDR_DEV_WIDTH_16BIT, /* memory_width */ + MV_DDR_DIE_CAP_4GBIT, /* mem_size */ DDR_FREQ_533, /* frequency */ 0, 0, /* cas_wl cas_l */ - HWS_TEMP_LOW, /* temperature */ - HWS_TIM_DEFAULT} }, /* timing */ - 5, /* Num Of Bus Per Interface*/ - BUS_MASK_32BIT /* Busses mask */ + MV_DDR_TEMP_LOW} }, /* temperature */ + BUS_MASK_32BIT, /* Busses mask */ + MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ + { {0} }, /* raw spd data */ + {0} /* timing parameters */ + }; static struct serdes_map serdes_topology_map[] = { @@ -122,7 +125,7 @@ void board_pex_config(void) #endif } -struct hws_topology_map *ddr3_get_topology_map(void) +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) { return &ddr_topology_map; } diff --git a/board/solidrun/clearfog/clearfog.c b/board/solidrun/clearfog/clearfog.c index 1472e9793e5f..75eb59ae3ee3 100644 --- a/board/solidrun/clearfog/clearfog.c +++ b/board/solidrun/clearfog/clearfog.c @@ -12,7 +12,7 @@ #include #include -#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h" +#include "../drivers/ddr/marvell/a38x/ddr3_init.h" #include <../serdes/a38x/high_speed_env_spec.h> DECLARE_GLOBAL_DATA_PTR; @@ -70,7 +70,8 @@ int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count) * be used by the DDR3 init code in the SPL U-Boot version to configure * the DDR3 controller. */ -static struct hws_topology_map board_topology_map = { +static struct mv_ddr_topology_map board_topology_map = { + DEBUG_LEVEL_ERROR, 0x1, /* active interfaces */ /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */ { { { {0x1, 0, 0, 0}, @@ -79,17 +80,18 @@ static struct hws_topology_map board_topology_map = { {0x1, 0, 0, 0}, {0x1, 0, 0, 0} }, SPEED_BIN_DDR_1600K, /* speed_bin */ - BUS_WIDTH_16, /* memory_width */ - MEM_4G, /* mem_size */ + MV_DDR_DEV_WIDTH_16BIT, /* memory_width */ + MV_DDR_DIE_CAP_4GBIT, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_wl cas_l */ - HWS_TEMP_LOW, /* temperature */ - HWS_TIM_DEFAULT} }, /* timing */ - 5, /* Num Of Bus Per Interface*/ - BUS_MASK_32BIT /* Busses mask */ + MV_DDR_TEMP_LOW} }, /* temperature */ + BUS_MASK_32BIT, /* Busses mask */ + MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ + { {0} }, /* raw spd data */ + {0} /* timing parameters */ }; -struct hws_topology_map *ddr3_get_topology_map(void) +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) { /* Return the board topology as defined in the board code */ return &board_topology_map; diff --git a/drivers/ddr/marvell/a38x/Makefile b/drivers/ddr/marvell/a38x/Makefile index bf6ea4945f03..aadfb767e30d 100644 --- a/drivers/ddr/marvell/a38x/Makefile +++ b/drivers/ddr/marvell/a38x/Makefile @@ -2,10 +2,9 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-$(CONFIG_SPL_BUILD) += ddr3_a38x.o -obj-$(CONFIG_SPL_BUILD) += ddr3_a38x_training.o +obj-$(CONFIG_SPL_BUILD) += mv_ddr_plat.o +obj-$(CONFIG_SPL_BUILD) += mv_ddr_sys_env_lib.o obj-$(CONFIG_SPL_BUILD) += ddr3_debug.o -obj-$(CONFIG_SPL_BUILD) += ddr3_hws_hw_training.o obj-$(CONFIG_SPL_BUILD) += ddr3_init.o obj-$(CONFIG_SPL_BUILD) += ddr3_training.o obj-$(CONFIG_SPL_BUILD) += ddr3_training_bist.o @@ -15,5 +14,8 @@ obj-$(CONFIG_SPL_BUILD) += ddr3_training_hw_algo.o obj-$(CONFIG_SPL_BUILD) += ddr3_training_ip_engine.o obj-$(CONFIG_SPL_BUILD) += ddr3_training_leveling.o obj-$(CONFIG_SPL_BUILD) += ddr3_training_pbs.o -obj-$(CONFIG_SPL_BUILD) += ddr3_training_static.o +obj-$(CONFIG_SPL_BUILD) += mv_ddr_build_message.o +obj-$(CONFIG_SPL_BUILD) += mv_ddr_common.o +obj-$(CONFIG_SPL_BUILD) += mv_ddr_spd.o +obj-$(CONFIG_SPL_BUILD) += mv_ddr_topology.o obj-$(CONFIG_SPL_BUILD) += xor.o diff --git a/drivers/ddr/marvell/a38x/ddr3_a38x.c b/drivers/ddr/marvell/a38x/ddr3_a38x.c deleted file mode 100644 index 22390325003d..000000000000 --- a/drivers/ddr/marvell/a38x/ddr3_a38x.c +++ /dev/null @@ -1,686 +0,0 @@ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include -#include -#include -#include -#include -#include - -#include "ddr3_init.h" - -#define A38X_NUMBER_OF_INTERFACES 5 - -#define SAR_DEV_ID_OFFS 27 -#define SAR_DEV_ID_MASK 0x7 - -/* Termal Sensor Registers */ -#define TSEN_STATE_REG 0xe4070 -#define TSEN_STATE_OFFSET 31 -#define TSEN_STATE_MASK (0x1 << TSEN_STATE_OFFSET) -#define TSEN_CONF_REG 0xe4074 -#define TSEN_CONF_RST_OFFSET 8 -#define TSEN_CONF_RST_MASK (0x1 << TSEN_CONF_RST_OFFSET) -#define TSEN_STATUS_REG 0xe4078 -#define TSEN_STATUS_READOUT_VALID_OFFSET 10 -#define TSEN_STATUS_READOUT_VALID_MASK (0x1 << \ - TSEN_STATUS_READOUT_VALID_OFFSET) -#define TSEN_STATUS_TEMP_OUT_OFFSET 0 -#define TSEN_STATUS_TEMP_OUT_MASK (0x3ff << TSEN_STATUS_TEMP_OUT_OFFSET) - -static struct dfx_access interface_map[] = { - /* Pipe Client */ - { 0, 17 }, - { 1, 7 }, - { 1, 11 }, - { 0, 3 }, - { 1, 25 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 } -}; - -/* This array hold the board round trip delay (DQ and CK) per */ -struct trip_delay_element a38x_board_round_trip_delay_array[] = { - /* 1st board */ - /* Interface bus DQS-delay CK-delay */ - { 3952, 5060 }, - { 3192, 4493 }, - { 4785, 6677 }, - { 3413, 7267 }, - { 4282, 6086 }, /* ECC PUP */ - { 3952, 5134 }, - { 3192, 4567 }, - { 4785, 6751 }, - { 3413, 7341 }, - { 4282, 6160 }, /* ECC PUP */ - - /* 2nd board */ - /* Interface bus DQS-delay CK-delay */ - { 3952, 5060 }, - { 3192, 4493 }, - { 4785, 6677 }, - { 3413, 7267 }, - { 4282, 6086 }, /* ECC PUP */ - { 3952, 5134 }, - { 3192, 4567 }, - { 4785, 6751 }, - { 3413, 7341 }, - { 4282, 6160 } /* ECC PUP */ -}; - - -static u8 a38x_bw_per_freq[DDR_FREQ_LIMIT] = { - 0x3, /* DDR_FREQ_100 */ - 0x4, /* DDR_FREQ_400 */ - 0x4, /* DDR_FREQ_533 */ - 0x5, /* DDR_FREQ_667 */ - 0x5, /* DDR_FREQ_800 */ - 0x5, /* DDR_FREQ_933 */ - 0x5, /* DDR_FREQ_1066 */ - 0x3, /* DDR_FREQ_311 */ - 0x3, /* DDR_FREQ_333 */ - 0x4, /* DDR_FREQ_467 */ - 0x5, /* DDR_FREQ_850 */ - 0x5, /* DDR_FREQ_600 */ - 0x3, /* DDR_FREQ_300 */ - 0x5, /* DDR_FREQ_900 */ - 0x3, /* DDR_FREQ_360 */ - 0x5 /* DDR_FREQ_1000 */ -}; - -static u8 a38x_rate_per_freq[DDR_FREQ_LIMIT] = { - /*TBD*/ 0x1, /* DDR_FREQ_100 */ - 0x2, /* DDR_FREQ_400 */ - 0x2, /* DDR_FREQ_533 */ - 0x2, /* DDR_FREQ_667 */ - 0x2, /* DDR_FREQ_800 */ - 0x3, /* DDR_FREQ_933 */ - 0x3, /* DDR_FREQ_1066 */ - 0x1, /* DDR_FREQ_311 */ - 0x1, /* DDR_FREQ_333 */ - 0x2, /* DDR_FREQ_467 */ - 0x2, /* DDR_FREQ_850 */ - 0x2, /* DDR_FREQ_600 */ - 0x1, /* DDR_FREQ_300 */ - 0x2, /* DDR_FREQ_900 */ - 0x1, /* DDR_FREQ_360 */ - 0x2 /* DDR_FREQ_1000 */ -}; - -static u16 a38x_vco_freq_per_sar[] = { - 666, /* 0 */ - 1332, - 800, - 1600, - 1066, - 2132, - 1200, - 2400, - 1332, - 1332, - 1500, - 1500, - 1600, /* 12 */ - 1600, - 1700, - 1700, - 1866, - 1866, - 1800, /* 18 */ - 2000, - 2000, - 4000, - 2132, - 2132, - 2300, - 2300, - 2400, - 2400, - 2500, - 2500, - 800 -}; - -u32 pipe_multicast_mask; - -u32 dq_bit_map_2_phy_pin[] = { - 1, 0, 2, 6, 9, 8, 3, 7, /* 0 */ - 8, 9, 1, 7, 2, 6, 3, 0, /* 1 */ - 3, 9, 7, 8, 1, 0, 2, 6, /* 2 */ - 1, 0, 6, 2, 8, 3, 7, 9, /* 3 */ - 0, 1, 2, 9, 7, 8, 3, 6, /* 4 */ -}; - -static int ddr3_tip_a38x_set_divider(u8 dev_num, u32 if_id, - enum hws_ddr_freq freq); - -/* - * Read temperature TJ value - */ -u32 ddr3_ctrl_get_junc_temp(u8 dev_num) -{ - int reg = 0; - - /* Initiates TSEN hardware reset once */ - if ((reg_read(TSEN_CONF_REG) & TSEN_CONF_RST_MASK) == 0) - reg_bit_set(TSEN_CONF_REG, TSEN_CONF_RST_MASK); - mdelay(10); - - /* Check if the readout field is valid */ - if ((reg_read(TSEN_STATUS_REG) & TSEN_STATUS_READOUT_VALID_MASK) == 0) { - printf("%s: TSEN not ready\n", __func__); - return 0; - } - - reg = reg_read(TSEN_STATUS_REG); - reg = (reg & TSEN_STATUS_TEMP_OUT_MASK) >> TSEN_STATUS_TEMP_OUT_OFFSET; - - return ((((10000 * reg) / 21445) * 1000) - 272674) / 1000; -} - -/* - * Name: ddr3_tip_a38x_get_freq_config. - * Desc: - * Args: - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -int ddr3_tip_a38x_get_freq_config(u8 dev_num, enum hws_ddr_freq freq, - struct hws_tip_freq_config_info - *freq_config_info) -{ - if (a38x_bw_per_freq[freq] == 0xff) - return MV_NOT_SUPPORTED; - - if (freq_config_info == NULL) - return MV_BAD_PARAM; - - freq_config_info->bw_per_freq = a38x_bw_per_freq[freq]; - freq_config_info->rate_per_freq = a38x_rate_per_freq[freq]; - freq_config_info->is_supported = 1; - - return MV_OK; -} - -/* - * Name: ddr3_tip_a38x_pipe_enable. - * Desc: - * Args: - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -int ddr3_tip_a38x_pipe_enable(u8 dev_num, enum hws_access_type interface_access, - u32 if_id, int enable) -{ - u32 data_value, pipe_enable_mask = 0; - - if (enable == 0) { - pipe_enable_mask = 0; - } else { - if (interface_access == ACCESS_TYPE_MULTICAST) - pipe_enable_mask = pipe_multicast_mask; - else - pipe_enable_mask = (1 << interface_map[if_id].pipe); - } - - CHECK_STATUS(ddr3_tip_reg_read - (dev_num, PIPE_ENABLE_ADDR, &data_value, MASK_ALL_BITS)); - data_value = (data_value & (~0xff)) | pipe_enable_mask; - CHECK_STATUS(ddr3_tip_reg_write(dev_num, PIPE_ENABLE_ADDR, data_value)); - - return MV_OK; -} - -/* - * Name: ddr3_tip_a38x_if_write. - * Desc: - * Args: - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -int ddr3_tip_a38x_if_write(u8 dev_num, enum hws_access_type interface_access, - u32 if_id, u32 reg_addr, u32 data_value, - u32 mask) -{ - u32 ui_data_read; - - if (mask != MASK_ALL_BITS) { - CHECK_STATUS(ddr3_tip_a38x_if_read - (dev_num, ACCESS_TYPE_UNICAST, if_id, reg_addr, - &ui_data_read, MASK_ALL_BITS)); - data_value = (ui_data_read & (~mask)) | (data_value & mask); - } - - reg_write(reg_addr, data_value); - - return MV_OK; -} - -/* - * Name: ddr3_tip_a38x_if_read. - * Desc: - * Args: - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -int ddr3_tip_a38x_if_read(u8 dev_num, enum hws_access_type interface_access, - u32 if_id, u32 reg_addr, u32 *data, u32 mask) -{ - *data = reg_read(reg_addr) & mask; - - return MV_OK; -} - -/* - * Name: ddr3_tip_a38x_select_ddr_controller. - * Desc: Enable/Disable access to Marvell's server. - * Args: dev_num - device number - * enable - whether to enable or disable the server - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -int ddr3_tip_a38x_select_ddr_controller(u8 dev_num, int enable) -{ - u32 reg; - - reg = reg_read(CS_ENABLE_REG); - - if (enable) - reg |= (1 << 6); - else - reg &= ~(1 << 6); - - reg_write(CS_ENABLE_REG, reg); - - return MV_OK; -} - -/* - * Name: ddr3_tip_init_a38x_silicon. - * Desc: init Training SW DB. - * Args: - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -static int ddr3_tip_init_a38x_silicon(u32 dev_num, u32 board_id) -{ - struct hws_tip_config_func_db config_func; - enum hws_ddr_freq ddr_freq; - int status; - struct hws_topology_map *tm = ddr3_get_topology_map(); - - /* new read leveling version */ - config_func.tip_dunit_read_func = ddr3_tip_a38x_if_read; - config_func.tip_dunit_write_func = ddr3_tip_a38x_if_write; - config_func.tip_dunit_mux_select_func = - ddr3_tip_a38x_select_ddr_controller; - config_func.tip_get_freq_config_info_func = - ddr3_tip_a38x_get_freq_config; - config_func.tip_set_freq_divider_func = ddr3_tip_a38x_set_divider; - config_func.tip_get_device_info_func = ddr3_tip_a38x_get_device_info; - config_func.tip_get_temperature = ddr3_ctrl_get_junc_temp; - - ddr3_tip_init_config_func(dev_num, &config_func); - - ddr3_tip_register_dq_table(dev_num, dq_bit_map_2_phy_pin); - - status = ddr3_tip_a38x_get_init_freq(dev_num, &ddr_freq); - if (MV_OK != status) { - DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR, - ("DDR3 silicon get target frequency - FAILED 0x%x\n", - status)); - return status; - } - - rl_version = 1; - mask_tune_func = (SET_LOW_FREQ_MASK_BIT | - LOAD_PATTERN_MASK_BIT | - SET_MEDIUM_FREQ_MASK_BIT | WRITE_LEVELING_MASK_BIT | - /* LOAD_PATTERN_2_MASK_BIT | */ - WRITE_LEVELING_SUPP_MASK_BIT | - READ_LEVELING_MASK_BIT | - PBS_RX_MASK_BIT | - PBS_TX_MASK_BIT | - SET_TARGET_FREQ_MASK_BIT | - WRITE_LEVELING_TF_MASK_BIT | - WRITE_LEVELING_SUPP_TF_MASK_BIT | - READ_LEVELING_TF_MASK_BIT | - CENTRALIZATION_RX_MASK_BIT | - CENTRALIZATION_TX_MASK_BIT); - rl_mid_freq_wa = 1; - - if ((ddr_freq == DDR_FREQ_333) || (ddr_freq == DDR_FREQ_400)) { - mask_tune_func = (WRITE_LEVELING_MASK_BIT | - LOAD_PATTERN_2_MASK_BIT | - WRITE_LEVELING_SUPP_MASK_BIT | - READ_LEVELING_MASK_BIT | - PBS_RX_MASK_BIT | - PBS_TX_MASK_BIT | - CENTRALIZATION_RX_MASK_BIT | - CENTRALIZATION_TX_MASK_BIT); - rl_mid_freq_wa = 0; /* WA not needed if 333/400 is TF */ - } - - /* Supplementary not supported for ECC modes */ - if (1 == ddr3_if_ecc_enabled()) { - mask_tune_func &= ~WRITE_LEVELING_SUPP_TF_MASK_BIT; - mask_tune_func &= ~WRITE_LEVELING_SUPP_MASK_BIT; - mask_tune_func &= ~PBS_TX_MASK_BIT; - mask_tune_func &= ~PBS_RX_MASK_BIT; - } - - if (ck_delay == -1) - ck_delay = 160; - if (ck_delay_16 == -1) - ck_delay_16 = 160; - ca_delay = 0; - delay_enable = 1; - - calibration_update_control = 1; - - init_freq = tm->interface_params[first_active_if].memory_freq; - - ddr3_tip_a38x_get_medium_freq(dev_num, &medium_freq); - - return MV_OK; -} - -int ddr3_a38x_update_topology_map(u32 dev_num, struct hws_topology_map *tm) -{ - u32 if_id = 0; - enum hws_ddr_freq freq; - - ddr3_tip_a38x_get_init_freq(dev_num, &freq); - tm->interface_params[if_id].memory_freq = freq; - - /* - * re-calc topology parameters according to topology updates - * (if needed) - */ - CHECK_STATUS(hws_ddr3_tip_load_topology_map(dev_num, tm)); - - return MV_OK; -} - -int ddr3_tip_init_a38x(u32 dev_num, u32 board_id) -{ - struct hws_topology_map *tm = ddr3_get_topology_map(); - - if (NULL == tm) - return MV_FAIL; - - ddr3_a38x_update_topology_map(dev_num, tm); - ddr3_tip_init_a38x_silicon(dev_num, board_id); - - return MV_OK; -} - -int ddr3_tip_a38x_get_init_freq(int dev_num, enum hws_ddr_freq *freq) -{ - u32 reg; - - /* Read sample at reset setting */ - reg = (reg_read(REG_DEVICE_SAR1_ADDR) >> - RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) & - RST2_CPU_DDR_CLOCK_SELECT_IN_MASK; - switch (reg) { - case 0x0: - case 0x1: - *freq = DDR_FREQ_333; - break; - case 0x2: - case 0x3: - *freq = DDR_FREQ_400; - break; - case 0x4: - case 0xd: - *freq = DDR_FREQ_533; - break; - case 0x6: - *freq = DDR_FREQ_600; - break; - case 0x8: - case 0x11: - case 0x14: - *freq = DDR_FREQ_667; - break; - case 0xc: - case 0x15: - case 0x1b: - *freq = DDR_FREQ_800; - break; - case 0x10: - *freq = DDR_FREQ_933; - break; - case 0x12: - *freq = DDR_FREQ_900; - break; - case 0x13: - *freq = DDR_FREQ_900; - break; - default: - *freq = 0; - return MV_NOT_SUPPORTED; - } - - return MV_OK; -} - -int ddr3_tip_a38x_get_medium_freq(int dev_num, enum hws_ddr_freq *freq) -{ - u32 reg; - - /* Read sample at reset setting */ - reg = (reg_read(REG_DEVICE_SAR1_ADDR) >> - RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) & - RST2_CPU_DDR_CLOCK_SELECT_IN_MASK; - switch (reg) { - case 0x0: - case 0x1: - /* Medium is same as TF to run PBS in this freq */ - *freq = DDR_FREQ_333; - break; - case 0x2: - case 0x3: - /* Medium is same as TF to run PBS in this freq */ - *freq = DDR_FREQ_400; - break; - case 0x4: - case 0xd: - *freq = DDR_FREQ_533; - break; - case 0x8: - case 0x11: - case 0x14: - *freq = DDR_FREQ_333; - break; - case 0xc: - case 0x15: - case 0x1b: - *freq = DDR_FREQ_400; - break; - case 0x6: - *freq = DDR_FREQ_300; - break; - case 0x12: - *freq = DDR_FREQ_360; - break; - case 0x13: - *freq = DDR_FREQ_400; - break; - default: - *freq = 0; - return MV_NOT_SUPPORTED; - } - - return MV_OK; -} - -u32 ddr3_tip_get_init_freq(void) -{ - enum hws_ddr_freq freq; - - ddr3_tip_a38x_get_init_freq(0, &freq); - - return freq; -} - -static int ddr3_tip_a38x_set_divider(u8 dev_num, u32 if_id, - enum hws_ddr_freq frequency) -{ - u32 divider = 0; - u32 sar_val; - - if (if_id != 0) { - DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR, - ("A38x does not support interface 0x%x\n", - if_id)); - return MV_BAD_PARAM; - } - - /* get VCO freq index */ - sar_val = (reg_read(REG_DEVICE_SAR1_ADDR) >> - RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) & - RST2_CPU_DDR_CLOCK_SELECT_IN_MASK; - divider = a38x_vco_freq_per_sar[sar_val] / freq_val[frequency]; - - /* Set Sync mode */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x20220, 0x0, - 0x1000)); - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe42f4, 0x0, - 0x200)); - - /* cpupll_clkdiv_reset_mask */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4264, 0x1f, - 0xff)); - - /* cpupll_clkdiv_reload_smooth */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4260, - (0x2 << 8), (0xff << 8))); - - /* cpupll_clkdiv_relax_en */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4260, - (0x2 << 24), (0xff << 24))); - - /* write the divider */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4268, - (divider << 8), (0x3f << 8))); - - /* set cpupll_clkdiv_reload_ratio */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4264, - (1 << 8), (1 << 8))); - - /* undet cpupll_clkdiv_reload_ratio */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4264, 0, - (1 << 8))); - - /* clear cpupll_clkdiv_reload_force */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4260, 0, - (0xff << 8))); - - /* clear cpupll_clkdiv_relax_en */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4260, 0, - (0xff << 24))); - - /* clear cpupll_clkdiv_reset_mask */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4264, 0, - 0xff)); - - /* Dunit training clock + 1:1 mode */ - if ((frequency == DDR_FREQ_LOW_FREQ) || (freq_val[frequency] <= 400)) { - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x18488, - (1 << 16), (1 << 16))); - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1524, - (0 << 15), (1 << 15))); - } else { - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x18488, - 0, (1 << 16))); - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1524, - (1 << 15), (1 << 15))); - } - - return MV_OK; -} - -/* - * external read from memory - */ -int ddr3_tip_ext_read(u32 dev_num, u32 if_id, u32 reg_addr, - u32 num_of_bursts, u32 *data) -{ - u32 burst_num; - - for (burst_num = 0; burst_num < num_of_bursts * 8; burst_num++) - data[burst_num] = readl(reg_addr + 4 * burst_num); - - return MV_OK; -} - -/* - * external write to memory - */ -int ddr3_tip_ext_write(u32 dev_num, u32 if_id, u32 reg_addr, - u32 num_of_bursts, u32 *data) { - u32 burst_num; - - for (burst_num = 0; burst_num < num_of_bursts * 8; burst_num++) - writel(data[burst_num], reg_addr + 4 * burst_num); - - return MV_OK; -} - -int ddr3_silicon_pre_init(void) -{ - return ddr3_silicon_init(); -} - -int ddr3_post_run_alg(void) -{ - return MV_OK; -} - -int ddr3_silicon_post_init(void) -{ - struct hws_topology_map *tm = ddr3_get_topology_map(); - - /* Set half bus width */ - if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask)) { - CHECK_STATUS(ddr3_tip_if_write - (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, - REG_SDRAM_CONFIG_ADDR, 0x0, 0x8000)); - } - - return MV_OK; -} - -int ddr3_tip_a38x_get_device_info(u8 dev_num, struct ddr3_device_info *info_ptr) -{ - info_ptr->device_id = 0x6800; - info_ptr->ck_delay = ck_delay; - - return MV_OK; -} diff --git a/drivers/ddr/marvell/a38x/ddr3_a38x.h b/drivers/ddr/marvell/a38x/ddr3_a38x.h deleted file mode 100644 index 1ed517446f95..000000000000 --- a/drivers/ddr/marvell/a38x/ddr3_a38x.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#ifndef _DDR3_A38X_H -#define _DDR3_A38X_H - -#define MAX_INTERFACE_NUM 1 -#define MAX_BUS_NUM 5 - -#include "ddr3_hws_hw_training_def.h" - -#define ECC_SUPPORT - -/* right now, we're not supporting this in mainline */ -#undef SUPPORT_STATIC_DUNIT_CONFIG - -/* Controler bus divider 1 for 32 bit, 2 for 64 bit */ -#define DDR_CONTROLLER_BUS_WIDTH_MULTIPLIER 1 - -/* Tune internal training params values */ -#define TUNE_TRAINING_PARAMS_CK_DELAY 160 -#define TUNE_TRAINING_PARAMS_CK_DELAY_16 160 -#define TUNE_TRAINING_PARAMS_PFINGER 41 -#define TUNE_TRAINING_PARAMS_NFINGER 43 -#define TUNE_TRAINING_PARAMS_PHYREG3VAL 0xa - -#define MARVELL_BOARD MARVELL_BOARD_ID_BASE - - -#define REG_DEVICE_SAR1_ADDR 0xe4204 -#define RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET 17 -#define RST2_CPU_DDR_CLOCK_SELECT_IN_MASK 0x1f - -/* DRAM Windows */ -#define REG_XBAR_WIN_5_CTRL_ADDR 0x20050 -#define REG_XBAR_WIN_5_BASE_ADDR 0x20054 - -/* DRAM Windows */ -#define REG_XBAR_WIN_4_CTRL_ADDR 0x20040 -#define REG_XBAR_WIN_4_BASE_ADDR 0x20044 -#define REG_XBAR_WIN_4_REMAP_ADDR 0x20048 -#define REG_XBAR_WIN_7_REMAP_ADDR 0x20078 -#define REG_XBAR_WIN_16_CTRL_ADDR 0x200d0 -#define REG_XBAR_WIN_16_BASE_ADDR 0x200d4 -#define REG_XBAR_WIN_16_REMAP_ADDR 0x200dc -#define REG_XBAR_WIN_19_CTRL_ADDR 0x200e8 - -#define REG_FASTPATH_WIN_BASE_ADDR(win) (0x20180 + (0x8 * win)) -#define REG_FASTPATH_WIN_CTRL_ADDR(win) (0x20184 + (0x8 * win)) - -/* SatR defined too change topology busWidth and ECC configuration */ -#define DDR_SATR_CONFIG_MASK_WIDTH 0x8 -#define DDR_SATR_CONFIG_MASK_ECC 0x10 -#define DDR_SATR_CONFIG_MASK_ECC_PUP 0x20 - -#define REG_SAMPLE_RESET_HIGH_ADDR 0x18600 - -#define MV_BOARD_REFCLK MV_BOARD_REFCLK_25MHZ - -/* Matrix enables DRAM modes (bus width/ECC) per boardId */ -#define TOPOLOGY_UPDATE_32BIT 0 -#define TOPOLOGY_UPDATE_32BIT_ECC 1 -#define TOPOLOGY_UPDATE_16BIT 2 -#define TOPOLOGY_UPDATE_16BIT_ECC 3 -#define TOPOLOGY_UPDATE_16BIT_ECC_PUP3 4 -#define TOPOLOGY_UPDATE { \ - /* 32Bit, 32bit ECC, 16bit, 16bit ECC PUP4, 16bit ECC PUP3 */ \ - {1, 1, 1, 1, 1}, /* RD_NAS_68XX_ID */ \ - {1, 1, 1, 1, 1}, /* DB_68XX_ID */ \ - {1, 0, 1, 0, 1}, /* RD_AP_68XX_ID */ \ - {1, 0, 1, 0, 1}, /* DB_AP_68XX_ID */ \ - {1, 0, 1, 0, 1}, /* DB_GP_68XX_ID */ \ - {0, 0, 1, 1, 0}, /* DB_BP_6821_ID */ \ - {1, 1, 1, 1, 1} /* DB_AMC_6820_ID */ \ - }; - -enum { - CPU_1066MHZ_DDR_400MHZ, - CPU_RESERVED_DDR_RESERVED0, - CPU_667MHZ_DDR_667MHZ, - CPU_800MHZ_DDR_800MHZ, - CPU_RESERVED_DDR_RESERVED1, - CPU_RESERVED_DDR_RESERVED2, - CPU_RESERVED_DDR_RESERVED3, - LAST_FREQ -}; - -#define ACTIVE_INTERFACE_MASK 0x1 - -#endif /* _DDR3_A38X_H */ diff --git a/drivers/ddr/marvell/a38x/ddr3_a38x_topology.h b/drivers/ddr/marvell/a38x/ddr3_a38x_topology.h deleted file mode 100644 index f27bbff73383..000000000000 --- a/drivers/ddr/marvell/a38x/ddr3_a38x_topology.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#ifndef _DDR3_A38X_TOPOLOGY_H -#define _DDR3_A38X_TOPOLOGY_H - -#include "ddr_topology_def.h" - -/* Bus mask variants */ -#define BUS_MASK_32BIT 0xf -#define BUS_MASK_32BIT_ECC 0x1f -#define BUS_MASK_16BIT 0x3 -#define BUS_MASK_16BIT_ECC 0x13 -#define BUS_MASK_16BIT_ECC_PUP3 0xb - -#define DYNAMIC_CS_SIZE_CONFIG -#define DISABLE_L2_FILTERING_DURING_DDR_TRAINING - -#endif /* _DDR3_A38X_TOPOLOGY_H */ diff --git a/drivers/ddr/marvell/a38x/ddr3_a38x_training.c b/drivers/ddr/marvell/a38x/ddr3_a38x_training.c deleted file mode 100644 index 52c43f75e080..000000000000 --- a/drivers/ddr/marvell/a38x/ddr3_a38x_training.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include -#include -#include -#include -#include -#include - -#include "ddr3_init.h" - -/* - * Name: ddr3_tip_init_silicon - * Desc: initiate silicon parameters - * Args: - * Notes: - * Returns: required value - */ -int ddr3_silicon_init(void) -{ - int status; - static int init_done; - - if (init_done == 1) - return MV_OK; - - status = ddr3_tip_init_a38x(0, 0); - if (MV_OK != status) { - printf("DDR3 A38x silicon init - FAILED 0x%x\n", status); - return status; - } - - init_done = 1; - - return MV_OK; -} diff --git a/drivers/ddr/marvell/a38x/ddr3_debug.c b/drivers/ddr/marvell/a38x/ddr3_debug.c index f0c8daa4b62c..589636f13372 100644 --- a/drivers/ddr/marvell/a38x/ddr3_debug.c +++ b/drivers/ddr/marvell/a38x/ddr3_debug.c @@ -4,13 +4,6 @@ * SPDX-License-Identifier: GPL-2.0 */ -#include -#include -#include -#include -#include -#include - #include "ddr3_init.h" u8 is_reg_dump = 0; @@ -19,7 +12,12 @@ u8 debug_pbs = DEBUG_LEVEL_ERROR; /* * API to change flags outside of the lib */ -#ifndef SILENT_LIB +#if defined(SILENT_LIB) +void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level) +{ + /* do nothing */ +} +#else /* SILENT_LIB */ /* Debug flags for other Training modules */ u8 debug_training_static = DEBUG_LEVEL_ERROR; u8 debug_training = DEBUG_LEVEL_ERROR; @@ -29,7 +27,14 @@ u8 debug_training_ip = DEBUG_LEVEL_ERROR; u8 debug_training_bist = DEBUG_LEVEL_ERROR; u8 debug_training_hw_alg = DEBUG_LEVEL_ERROR; u8 debug_training_access = DEBUG_LEVEL_ERROR; -u8 debug_training_a38x = DEBUG_LEVEL_ERROR; +u8 debug_training_device = DEBUG_LEVEL_ERROR; + + +void mv_ddr_user_log_level_set(enum ddr_lib_debug_block block) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + ddr3_hws_set_log_level(block, tm->debug_level); +}; void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level) { @@ -53,7 +58,7 @@ void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level) debug_training_hw_alg = level; break; case DEBUG_BLOCK_DEVICE: - debug_training_a38x = level; + debug_training_device = level; break; case DEBUG_BLOCK_ACCESS: debug_training_access = level; @@ -73,24 +78,31 @@ void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level) debug_pbs = level; debug_training_hw_alg = level; debug_training_access = level; - debug_training_a38x = level; + debug_training_device = level; } } -#else -void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level) -{ - return; -} -#endif +#endif /* SILENT_LIB */ -struct hws_tip_config_func_db config_func_info[HWS_MAX_DEVICE_NUM]; +#if defined(DDR_VIEWER_TOOL) +static char *convert_freq(enum hws_ddr_freq freq); +#if defined(EXCLUDE_SWITCH_DEBUG) +u32 ctrl_sweepres[ADLL_LENGTH][MAX_INTERFACE_NUM][MAX_BUS_NUM]; +u32 ctrl_adll[MAX_CS_NUM * MAX_INTERFACE_NUM * MAX_BUS_NUM]; +u32 ctrl_adll1[MAX_CS_NUM * MAX_INTERFACE_NUM * MAX_BUS_NUM]; +u32 ctrl_level_phase[MAX_CS_NUM * MAX_INTERFACE_NUM * MAX_BUS_NUM]; +#endif /* EXCLUDE_SWITCH_DEBUG */ +#endif /* DDR_VIEWER_TOOL */ + +struct hws_tip_config_func_db config_func_info[MAX_DEVICE_NUM]; u8 is_default_centralization = 0; u8 is_tune_result = 0; u8 is_validate_window_per_if = 0; u8 is_validate_window_per_pup = 0; u8 sweep_cnt = 1; u32 is_bist_reset_bit = 1; -static struct hws_xsb_info xsb_info[HWS_MAX_DEVICE_NUM]; +u8 is_run_leveling_sweep_tests; + +static struct hws_xsb_info xsb_info[MAX_DEVICE_NUM]; /* * Dump Dunit & Phy registers @@ -99,13 +111,14 @@ int ddr3_tip_reg_dump(u32 dev_num) { u32 if_id, reg_addr, data_value, bus_id; u32 read_data[MAX_INTERFACE_NUM]; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); printf("-- dunit registers --\n"); for (reg_addr = 0x1400; reg_addr < 0x19f0; reg_addr += 4) { printf("0x%x ", reg_addr); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, reg_addr, read_data, @@ -119,11 +132,11 @@ int ddr3_tip_reg_dump(u32 dev_num) for (reg_addr = 0; reg_addr <= 0xff; reg_addr++) { printf("0x%x ", reg_addr); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (bus_id = 0; - bus_id < tm->num_of_bus_per_interface; + bus_id < octets_per_if_num; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, @@ -132,9 +145,9 @@ int ddr3_tip_reg_dump(u32 dev_num) printf("0x%x ", data_value); } for (bus_id = 0; - bus_id < tm->num_of_bus_per_interface; + bus_id < octets_per_if_num; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, @@ -164,6 +177,23 @@ int ddr3_tip_init_config_func(u32 dev_num, return MV_OK; } +/* + * Read training result table + */ +int hws_ddr3_tip_read_training_result( + u32 dev_num, enum hws_result result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM]) +{ + if (result == NULL) + return MV_BAD_PARAM; + + memcpy(result, training_result, + sizeof(enum hws_result) * + MAX_STAGE_LIMIT * + MAX_INTERFACE_NUM); + + return MV_OK; +} + /* * Get training result info pointer */ @@ -185,7 +215,7 @@ int ddr3_tip_get_device_info(u32 dev_num, struct ddr3_device_info *info_ptr) return MV_FAIL; } -#ifndef EXCLUDE_SWITCH_DEBUG +#if defined(DDR_VIEWER_TOOL) /* * Convert freq to character string */ @@ -194,11 +224,13 @@ static char *convert_freq(enum hws_ddr_freq freq) switch (freq) { case DDR_FREQ_LOW_FREQ: return "DDR_FREQ_LOW_FREQ"; + case DDR_FREQ_400: return "400"; case DDR_FREQ_533: return "533"; + case DDR_FREQ_667: return "667"; @@ -210,6 +242,7 @@ static char *convert_freq(enum hws_ddr_freq freq) case DDR_FREQ_1066: return "1066"; + case DDR_FREQ_311: return "311"; @@ -230,6 +263,7 @@ static char *convert_freq(enum hws_ddr_freq freq) case DDR_FREQ_1000: return "DDR_FREQ_1000"; + default: return "Unknown Frequency"; } @@ -280,7 +314,7 @@ static char *convert_mem_size(u32 dev_id) int print_device_info(u8 dev_num) { struct ddr3_device_info info_ptr; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); CHECK_STATUS(ddr3_tip_get_device_info(dev_num, &info_ptr)); printf("=== DDR setup START===\n"); @@ -303,7 +337,7 @@ void hws_ddr3_tip_sweep_test(int enable) is_validate_window_per_pup = 0; } } -#endif +#endif /* DDR_VIEWER_TOOL */ char *ddr3_tip_convert_tune_result(enum hws_result tune_result) { @@ -325,9 +359,9 @@ char *ddr3_tip_convert_tune_result(enum hws_result tune_result) int ddr3_tip_print_log(u32 dev_num, u32 mem_addr) { u32 if_id = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); -#ifndef EXCLUDE_SWITCH_DEBUG +#if defined(DDR_VIEWER_TOOL) if ((is_validate_window_per_if != 0) || (is_validate_window_per_pup != 0)) { u32 is_pup_log = 0; @@ -341,16 +375,22 @@ int ddr3_tip_print_log(u32 dev_num, u32 mem_addr) /* print sweep windows */ ddr3_tip_run_sweep_test(dev_num, sweep_cnt, 1, is_pup_log); ddr3_tip_run_sweep_test(dev_num, sweep_cnt, 0, is_pup_log); +#if defined(EXCLUDE_SWITCH_DEBUG) + if (is_run_leveling_sweep_tests == 1) { + ddr3_tip_run_leveling_sweep_test(dev_num, sweep_cnt, 0, is_pup_log); + ddr3_tip_run_leveling_sweep_test(dev_num, sweep_cnt, 1, is_pup_log); + } +#endif /* EXCLUDE_SWITCH_DEBUG */ ddr3_tip_print_all_pbs_result(dev_num); ddr3_tip_print_wl_supp_result(dev_num); printf("===VALIDATE WINDOW LOG END ===\n"); CHECK_STATUS(ddr3_tip_restore_dunit_regs(dev_num)); ddr3_tip_reg_dump(dev_num); } -#endif +#endif /* DDR_VIEWER_TOOL */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("IF %d Status:\n", if_id)); @@ -480,6 +520,7 @@ int ddr3_tip_print_log(u32 dev_num, u32 mem_addr) return MV_OK; } +#if !defined(EXCLUDE_DEBUG_PRINTS) /* * Print stability log info */ @@ -488,17 +529,17 @@ int ddr3_tip_print_stability_log(u32 dev_num) u8 if_id = 0, csindex = 0, bus_id = 0, idx = 0; u32 reg_data; u32 read_data[MAX_INTERFACE_NUM]; - u32 max_cs = hws_ddr3_tip_max_cs_get(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 max_cs = ddr3_tip_max_cs_get(dev_num); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* Title print */ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); printf("Title: I/F# , Tj, Calibration_n0, Calibration_p0, Calibration_n1, Calibration_p1, Calibration_n2, Calibration_p2,"); for (csindex = 0; csindex < max_cs; csindex++) { printf("CS%d , ", csindex); printf("\n"); - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); printf("VWTx, VWRx, WL_tot, WL_ADLL, WL_PH, RL_Tot, RL_ADLL, RL_PH, RL_Smp, Cen_tx, Cen_rx, Vref, DQVref,"); printf("\t\t"); for (idx = 0; idx < 11; idx++) @@ -512,7 +553,7 @@ int ddr3_tip_print_stability_log(u32 dev_num) /* Data print */ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); printf("Data: %d,%d,", if_id, (config_func_info[dev_num].tip_get_temperature != NULL) @@ -539,11 +580,11 @@ int ddr3_tip_print_stability_log(u32 dev_num) printf("CS%d , ", csindex); for (bus_id = 0; bus_id < MAX_BUS_NUM; bus_id++) { printf("\n"); - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - RESULT_DB_PHY_REG_ADDR + + RESULT_PHY_REG + csindex, ®_data); printf("%d,%d,", (reg_data & 0x1f), ((reg_data & 0x3e0) >> 5)); @@ -551,8 +592,8 @@ int ddr3_tip_print_stability_log(u32 dev_num) ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - WL_PHY_REG + - csindex * 4, ®_data); + WL_PHY_REG(csindex), + ®_data); printf("%d,%d,%d,", (reg_data & 0x1f) + ((reg_data & 0x1c0) >> 6) * 32, @@ -562,16 +603,16 @@ int ddr3_tip_print_stability_log(u32 dev_num) CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, - READ_DATA_SAMPLE_DELAY, + RD_DATA_SMPL_DLYS_REG, read_data, MASK_ALL_BITS)); read_data[if_id] = (read_data[if_id] & - (0xf << (4 * csindex))) >> - (4 * csindex); + (0x1f << (8 * csindex))) >> + (8 * csindex); ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - RL_PHY_REG + csindex * 4, + RL_PHY_REG(csindex), ®_data); printf("%d,%d,%d,%d,", (reg_data & 0x1f) + @@ -584,36 +625,26 @@ int ddr3_tip_print_stability_log(u32 dev_num) ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG - + csindex * 4, ®_data); + CTX_PHY_REG(csindex), + ®_data); printf("%d,", (reg_data & 0x3f)); ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - READ_CENTRALIZATION_PHY_REG - + csindex * 4, ®_data); + CRX_PHY_REG(csindex), + ®_data); printf("%d,", (reg_data & 0x1f)); /* Vref */ ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - PAD_CONFIG_PHY_REG, + PAD_CFG_PHY_REG, ®_data); printf("%d,", (reg_data & 0x7)); /* DQVref */ /* Need to add the Read Function from device */ printf("%d,", 0); printf("\t\t"); - for (idx = 0; idx < 11; idx++) { - ddr3_tip_bus_read(dev_num, if_id, - ACCESS_TYPE_UNICAST, - bus_id, DDR_PHY_DATA, - 0xd0 + - 12 * csindex + - idx, ®_data); - printf("%d,", (reg_data & 0x3f)); - } - printf("\t\t"); for (idx = 0; idx < 11; idx++) { ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, @@ -640,6 +671,7 @@ int ddr3_tip_print_stability_log(u32 dev_num) return MV_OK; } +#endif /* EXCLUDE_DEBUG_PRINTS */ /* * Register XSB information @@ -653,30 +685,30 @@ int ddr3_tip_register_xsb_info(u32 dev_num, struct hws_xsb_info *xsb_info_table) /* * Read ADLL Value */ -int read_adll_value(u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], - int reg_addr, u32 mask) +int ddr3_tip_read_adll_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + u32 reg_addr, u32 mask) { u32 data_value; u32 if_id = 0, bus_id = 0; - u32 dev_num = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* * multi CS support - reg_addr is calucalated in calling function * with CS offset */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); CHECK_STATUS(ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, reg_addr, &data_value)); pup_values[if_id * - tm->num_of_bus_per_interface + bus_id] = + octets_per_if_num + bus_id] = data_value & mask; } } @@ -687,24 +719,25 @@ int read_adll_value(u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], /* * Write ADLL Value */ -int write_adll_value(u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], - int reg_addr) +int ddr3_tip_write_adll_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + u32 reg_addr) { u32 if_id = 0, bus_id = 0; - u32 dev_num = 0, data; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 data; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* * multi CS support - reg_addr is calucalated in calling function * with CS offset */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); data = pup_values[if_id * - tm->num_of_bus_per_interface + + octets_per_if_num + bus_id]; CHECK_STATUS(ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, @@ -718,23 +751,78 @@ int write_adll_value(u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], return 0; } -#ifndef EXCLUDE_SWITCH_DEBUG -u32 rl_version = 1; /* 0 - old RL machine */ -struct hws_tip_config_func_db config_func_info[HWS_MAX_DEVICE_NUM]; +/** + * Read Phase Value + */ +int read_phase_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + int reg_addr, u32 mask) +{ + u32 data_value; + u32 if_id = 0, bus_id = 0; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + /* multi CS support - reg_addr is calucalated in calling function with CS offset */ + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); + CHECK_STATUS(ddr3_tip_bus_read(dev_num, if_id, + ACCESS_TYPE_UNICAST, + bus_id, + DDR_PHY_DATA, reg_addr, + &data_value)); + pup_values[if_id * octets_per_if_num + bus_id] = data_value & mask; + } + } + + return 0; +} + +/** + * Write Leveling Value + */ +int write_leveling_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + u32 pup_ph_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], int reg_addr) +{ + u32 if_id = 0, bus_id = 0; + u32 data; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + /* multi CS support - reg_addr is calucalated in calling function with CS offset */ + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_id = 0 ; bus_id < octets_per_if_num ; bus_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); + data = pup_values[if_id * octets_per_if_num + bus_id] + + pup_ph_values[if_id * octets_per_if_num + bus_id]; + CHECK_STATUS(ddr3_tip_bus_write(dev_num, + ACCESS_TYPE_UNICAST, + if_id, + ACCESS_TYPE_UNICAST, + bus_id, + DDR_PHY_DATA, + reg_addr, + data)); + } + } + + return 0; +} + +#if !defined(EXCLUDE_SWITCH_DEBUG) +struct hws_tip_config_func_db config_func_info[MAX_DEVICE_NUM]; u32 start_xsb_offset = 0; u8 is_rl_old = 0; u8 is_freq_old = 0; u8 is_dfs_disabled = 0; u32 default_centrlization_value = 0x12; -u32 vref = 0x4; u32 activate_select_before_run_alg = 1, activate_deselect_after_run_alg = 1, rl_test = 0, reset_read_fifo = 0; int debug_acc = 0; u32 ctrl_sweepres[ADLL_LENGTH][MAX_INTERFACE_NUM][MAX_BUS_NUM]; u32 ctrl_adll[MAX_CS_NUM * MAX_INTERFACE_NUM * MAX_BUS_NUM]; -u8 cs_mask_reg[] = { - 0, 4, 8, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; u32 xsb_test_table[][8] = { {0x00000000, 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, @@ -762,13 +850,14 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr); int ddr3_tip_print_adll(void) { u32 bus_cnt = 0, if_id, data_p1, data_p2, ui_data3, dev_num = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_cnt = 0; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES(); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_cnt, @@ -816,7 +905,7 @@ int ddr3_tip_set_atr(u32 dev_num, u32 flag_id, u32 value) static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) { u32 tmp_val = 0, if_id = 0, pup_id = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); *ptr = NULL; @@ -830,21 +919,17 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) break; case 0x2: - *ptr = (u32 *)&low_freq; + low_freq = (enum hws_ddr_freq)value; break; case 0x3: - *ptr = (u32 *)&medium_freq; + medium_freq = (enum hws_ddr_freq)value; break; case 0x4: *ptr = (u32 *)&generic_init_controller; break; - case 0x5: - *ptr = (u32 *)&rl_version; - break; - case 0x8: *ptr = (u32 *)&start_xsb_offset; break; @@ -893,15 +978,14 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) break; case 0x33: - *ptr = (u32 *)&p_finger; + *ptr = (u32 *)&g_zpodt_data; break; case 0x34: - *ptr = (u32 *)&n_finger; + *ptr = (u32 *)&g_znodt_data; break; case 0x35: - *ptr = (u32 *)&init_freq; break; case 0x36: @@ -933,19 +1017,15 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) break; case 0x4e: - *ptr = (u32 *)&sweep_pattern; - break; - - case 0x50: - *ptr = (u32 *)&is_rzq6; + sweep_pattern = (enum hws_pattern)value; break; case 0x51: - *ptr = (u32 *)&znri_data_phy_val; + *ptr = (u32 *)&g_znri_data; break; case 0x52: - *ptr = (u32 *)&zpri_data_phy_val; + *ptr = (u32 *)&g_zpri_data; break; case 0x53: @@ -977,11 +1057,11 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) break; case 0x5a: - *ptr = (u32 *)&znri_ctrl_phy_val; + *ptr = (u32 *)&g_znri_ctrl; break; case 0x5b: - *ptr = (u32 *)&zpri_ctrl_phy_val; + *ptr = (u32 *)&g_zpri_ctrl; break; case 0x5c: @@ -989,11 +1069,11 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) break; case 0x5d: - *ptr = (u32 *)&vref; + *ptr = (u32 *)&vref_init_val; break; case 0x5e: - *ptr = (u32 *)&mode2_t; + *ptr = (u32 *)&mode_2t; break; case 0x5f: @@ -1021,7 +1101,7 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) break; case 0x71: - *ptr = (u32 *)&pbs_pattern; + pbs_pattern = (enum hws_pattern)value; break; case 0x72: @@ -1032,10 +1112,6 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) *ptr = (u32 *)&ck_delay; break; - case 0x74: - *ptr = (u32 *)&ck_delay_16; - break; - case 0x75: *ptr = (u32 *)&ca_delay; break; @@ -1080,6 +1156,7 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) debug_training_access = (u8)value; break; + case 0x112: *ptr = &start_pattern; break; @@ -1148,28 +1225,46 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) return MV_OK; } -#ifndef EXCLUDE_SWITCH_DEBUG +#endif /* EXCLUDE_SWITCH_DEBUG */ + +#if defined(DDR_VIEWER_TOOL) /* * Print ADLL */ int print_adll(u32 dev_num, u32 adll[MAX_INTERFACE_NUM * MAX_BUS_NUM]) { u32 i, j; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - for (j = 0; j < tm->num_of_bus_per_interface; j++) { - VALIDATE_ACTIVE(tm->bus_act_mask, j); - for (i = 0; i < MAX_INTERFACE_NUM; i++) { - printf("%d ,", - adll[i * tm->num_of_bus_per_interface + j]); - } + for (j = 0; j < octets_per_if_num; j++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, j); + for (i = 0; i < MAX_INTERFACE_NUM; i++) + printf("%d ,", adll[i * octets_per_if_num + j]); } printf("\n"); return MV_OK; } -#endif +int print_ph(u32 dev_num, u32 adll[MAX_INTERFACE_NUM * MAX_BUS_NUM]) +{ + u32 i, j; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + for (j = 0; j < octets_per_if_num; j++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, j); + for (i = 0; i < MAX_INTERFACE_NUM; i++) + printf("%d ,", adll[i * octets_per_if_num + j] >> 6); + } + printf("\n"); + + return MV_OK; +} +#endif /* DDR_VIEWER_TOOL */ + +#if !defined(EXCLUDE_SWITCH_DEBUG) /* byte_index - only byte 0, 1, 2, or 3, oxff - test all bytes */ static u32 ddr3_tip_compare(u32 if_id, u32 *p_src, u32 *p_dst, u32 byte_index) @@ -1182,7 +1277,7 @@ static u32 ddr3_tip_compare(u32 if_id, u32 *p_src, u32 *p_dst, 0xff) ? (u32) 0xffffffff : (u32) (0xff << (byte_index * 8)); for (burst_cnt = 0; burst_cnt < EXT_ACCESS_BURST_LENGTH; burst_cnt++) { if ((p_src[burst_cnt] & addr_offset) != - (p_dst[burst_cnt] & addr_offset)) + (p_dst[if_id] & addr_offset)) b_is_fail = 1; } @@ -1204,69 +1299,9 @@ static u32 ddr3_tip_compare(u32 if_id, u32 *p_src, u32 *p_dst, return b_is_fail; } +#endif /* EXCLUDE_SWITCH_DEBUG */ -/* test_type = 0-tx , 1-rx */ -int ddr3_tip_sweep_test(u32 dev_num, u32 test_type, - u32 mem_addr, u32 is_modify_adll, - u32 start_if, u32 end_if, u32 startpup, u32 endpup) -{ - u32 bus_cnt = 0, adll_val = 0, if_id, ui_prev_adll, ui_mask_bit, - end_adll, start_adll; - u32 reg_addr = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); - - if (test_type == 0) { - reg_addr = 1; - ui_mask_bit = 0x3f; - start_adll = 0; - end_adll = ui_mask_bit; - } else { - reg_addr = 3; - ui_mask_bit = 0x1f; - start_adll = 0; - end_adll = ui_mask_bit; - } - - DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, - ("==============================\n")); - DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, - ("Test type %d (0-tx, 1-rx)\n", test_type)); - - for (if_id = start_if; if_id <= end_if; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_cnt = startpup; bus_cnt < endpup; bus_cnt++) { - CHECK_STATUS(ddr3_tip_bus_read - (dev_num, if_id, ACCESS_TYPE_UNICAST, - bus_cnt, DDR_PHY_DATA, reg_addr, - &ui_prev_adll)); - - for (adll_val = start_adll; adll_val <= end_adll; - adll_val++) { - if (is_modify_adll == 1) { - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, - ACCESS_TYPE_UNICAST, - if_id, bus_cnt, - DDR_PHY_DATA, reg_addr, - adll_val, ui_mask_bit)); - } - } - if (is_modify_adll == 1) { - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_UNICAST, - if_id, ACCESS_TYPE_UNICAST, - bus_cnt, DDR_PHY_DATA, reg_addr, - ui_prev_adll)); - } - DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("\n")); - } - DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("\n")); - } - - return MV_OK; -} - -#ifndef EXCLUDE_SWITCH_DEBUG +#if defined(DDR_VIEWER_TOOL) /* * Sweep validation */ @@ -1274,21 +1309,23 @@ int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, u32 mode) { u32 pup = 0, start_pup = 0, end_pup = 0; - u32 adll = 0; + u32 adll = 0, rep = 0, pattern_idx = 0; u32 res[MAX_INTERFACE_NUM] = { 0 }; int if_id = 0; u32 adll_value = 0; - int reg = (direction == 0) ? WRITE_CENTRALIZATION_PHY_REG : - READ_CENTRALIZATION_PHY_REG; + u32 reg; enum hws_access_type pup_access; u32 cs; - u32 max_cs = hws_ddr3_tip_max_cs_get(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 max_cs = ddr3_tip_max_cs_get(dev_num); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + repeat_num = 2; if (mode == 1) { /* per pup */ start_pup = 0; - end_pup = tm->num_of_bus_per_interface - 1; + end_pup = octets_per_if_num - 1; pup_access = ACCESS_TYPE_UNICAST; } else { start_pup = 0; @@ -1297,11 +1334,12 @@ int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, } for (cs = 0; cs < max_cs; cs++) { + reg = (direction == 0) ? CTX_PHY_REG(cs) : CRX_PHY_REG(cs); for (adll = 0; adll < ADLL_LENGTH; adll++) { for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE + VALIDATE_IF_ACTIVE (tm->if_act_mask, if_id); for (pup = start_pup; pup <= end_pup; pup++) { @@ -1313,10 +1351,9 @@ int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, for (adll = 0; adll < (MAX_INTERFACE_NUM * MAX_BUS_NUM); adll++) ctrl_adll[adll] = 0; - /* Save DQS value(after algorithm run) */ - read_adll_value(ctrl_adll, - (reg + (cs * CS_REGISTER_ADDR_OFFSET)), - MASK_ALL_BITS); + /* Save DQS value(after algorithm run) */ + ddr3_tip_read_adll_value(dev_num, ctrl_adll, + reg, MASK_ALL_BITS); /* * Sweep ADLL from 0:31 on all I/F on all Pup and perform @@ -1324,38 +1361,43 @@ int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, */ for (pup = start_pup; pup <= end_pup; pup++) { for (adll = 0; adll < ADLL_LENGTH; adll++) { - adll_value = - (direction == 0) ? (adll * 2) : adll; - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, 0, - pup_access, pup, DDR_PHY_DATA, - reg + CS_REG_VALUE(cs), - adll_value)); - hws_ddr3_run_bist(dev_num, sweep_pattern, res, - cs); - /* ddr3_tip_reset_fifo_ptr(dev_num); */ - for (if_id = 0; - if_id <= MAX_INTERFACE_NUM - 1; - if_id++) { - VALIDATE_ACTIVE - (tm->if_act_mask, - if_id); - ctrl_sweepres[adll][if_id][pup] - = res[if_id]; - if (mode == 1) { - CHECK_STATUS - (ddr3_tip_bus_write - (dev_num, - ACCESS_TYPE_UNICAST, - if_id, - ACCESS_TYPE_UNICAST, - pup, - DDR_PHY_DATA, - reg + CS_REG_VALUE(cs), - ctrl_adll[if_id * - cs * - tm->num_of_bus_per_interface - + pup])); + for (rep = 0; rep < repeat_num; rep++) { + for (pattern_idx = PATTERN_KILLER_DQ0; + pattern_idx < PATTERN_LAST; + pattern_idx++) { + adll_value = + (direction == 0) ? (adll * 2) : adll; + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, 0, + pup_access, pup, DDR_PHY_DATA, + reg, adll_value)); + hws_ddr3_run_bist(dev_num, sweep_pattern, res, + cs); + /* ddr3_tip_reset_fifo_ptr(dev_num); */ + for (if_id = 0; + if_id < MAX_INTERFACE_NUM; + if_id++) { + VALIDATE_IF_ACTIVE + (tm->if_act_mask, + if_id); + ctrl_sweepres[adll][if_id][pup] + += res[if_id]; + if (mode == 1) { + CHECK_STATUS + (ddr3_tip_bus_write + (dev_num, + ACCESS_TYPE_UNICAST, + if_id, + ACCESS_TYPE_UNICAST, + pup, + DDR_PHY_DATA, + reg, + ctrl_adll[if_id * + cs * + octets_per_if_num + + pup])); + } + } } } } @@ -1363,10 +1405,10 @@ int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, printf("Final, CS %d,%s, Sweep, Result, Adll,", cs, ((direction == 0) ? "TX" : "RX")); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (mode == 1) { for (pup = start_pup; pup <= end_pup; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); printf("I/F%d-PHY%d , ", if_id, pup); } } else { @@ -1383,9 +1425,9 @@ int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (pup = start_pup; pup <= end_pup; pup++) { - printf("%d , ", + printf("%8d , ", ctrl_sweepres[adll][if_id] [pup]); } @@ -1397,11 +1439,9 @@ int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, * Write back to the phy the Rx DQS value, we store in * the beginning. */ - write_adll_value(ctrl_adll, - (reg + cs * CS_REGISTER_ADDR_OFFSET)); + ddr3_tip_write_adll_value(dev_num, ctrl_adll, reg); /* print adll results */ - read_adll_value(ctrl_adll, (reg + cs * CS_REGISTER_ADDR_OFFSET), - MASK_ALL_BITS); + ddr3_tip_read_adll_value(dev_num, ctrl_adll, reg, MASK_ALL_BITS); printf("%s, DQS, ADLL,,,", (direction == 0) ? "Tx" : "Rx"); print_adll(dev_num, ctrl_adll); } @@ -1410,16 +1450,214 @@ int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, return 0; } -void print_topology(struct hws_topology_map *topology_db) +#if defined(EXCLUDE_SWITCH_DEBUG) +int ddr3_tip_run_leveling_sweep_test(int dev_num, u32 repeat_num, + u32 direction, u32 mode) +{ + u32 pup = 0, start_pup = 0, end_pup = 0, start_adll = 0; + u32 adll = 0, rep = 0, pattern_idx = 0; + u32 read_data[MAX_INTERFACE_NUM]; + u32 res[MAX_INTERFACE_NUM] = { 0 }; + int if_id = 0, gap = 0; + u32 adll_value = 0; + u32 reg; + enum hws_access_type pup_access; + u32 cs; + u32 max_cs = ddr3_tip_max_cs_get(dev_num); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + if (mode == 1) { /* per pup */ + start_pup = 0; + end_pup = octets_per_if_num - 1; + pup_access = ACCESS_TYPE_UNICAST; + } else { + start_pup = 0; + end_pup = 0; + pup_access = ACCESS_TYPE_MULTICAST; + } + + for (cs = 0; cs < max_cs; cs++) { + reg = (direction == 0) ? WL_PHY_REG(cs) : RL_PHY_REG(cs); + for (adll = 0; adll < ADLL_LENGTH; adll++) { + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (pup = start_pup; pup <= end_pup; pup++) + ctrl_sweepres[adll][if_id][pup] = 0; + } + } + + for (adll = 0; adll < MAX_INTERFACE_NUM * MAX_BUS_NUM; adll++) { + ctrl_adll[adll] = 0; + ctrl_level_phase[adll] = 0; + ctrl_adll1[adll] = 0; + } + + /* save leveling value after running algorithm */ + ddr3_tip_read_adll_value(dev_num, ctrl_adll, reg, 0x1f); + read_phase_value(dev_num, ctrl_level_phase, reg, 0x7 << 6); + + if (direction == 0) + ddr3_tip_read_adll_value(dev_num, ctrl_adll1, + CTX_PHY_REG(cs), MASK_ALL_BITS); + + /* Sweep ADLL from 0 to 31 on all interfaces, all pups, + * and perform BIST on each stage + */ + for (pup = start_pup; pup <= end_pup; pup++) { + for (adll = 0; adll < ADLL_LENGTH; adll++) { + for (rep = 0; rep < repeat_num; rep++) { + adll_value = (direction == 0) ? (adll * 2) : (adll * 3); + for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { + start_adll = ctrl_adll[if_id * cs * octets_per_if_num + pup] + + (ctrl_level_phase[if_id * cs * + octets_per_if_num + + pup] >> 6) * 32; + + if (direction == 0) + start_adll = (start_adll > 32) ? (start_adll - 32) : 0; + else + start_adll = (start_adll > 48) ? (start_adll - 48) : 0; + + adll_value += start_adll; + + gap = ctrl_adll1[if_id * cs * octets_per_if_num + pup] - + ctrl_adll[if_id * cs * octets_per_if_num + pup]; + gap = (((adll_value % 32) + gap) % 64); + + adll_value = ((adll_value % 32) + + (((adll_value - (adll_value % 32)) / 32) << 6)); + + CHECK_STATUS(ddr3_tip_bus_write(dev_num, + ACCESS_TYPE_UNICAST, + if_id, + pup_access, + pup, + DDR_PHY_DATA, + reg, + adll_value)); + if (direction == 0) + CHECK_STATUS(ddr3_tip_bus_write(dev_num, + ACCESS_TYPE_UNICAST, + if_id, + pup_access, + pup, + DDR_PHY_DATA, + CTX_PHY_REG(cs), + gap)); + } + + for (pattern_idx = PATTERN_KILLER_DQ0; + pattern_idx < PATTERN_LAST; + pattern_idx++) { + hws_ddr3_run_bist(dev_num, sweep_pattern, res, cs); + ddr3_tip_reset_fifo_ptr(dev_num); + for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + if (pup != 4) { /* TODO: remove literal */ + ctrl_sweepres[adll][if_id][pup] += res[if_id]; + } else { + CHECK_STATUS(ddr3_tip_if_read(dev_num, + ACCESS_TYPE_UNICAST, + if_id, + 0x1458, + read_data, + MASK_ALL_BITS)); + ctrl_sweepres[adll][if_id][pup] += read_data[if_id]; + CHECK_STATUS(ddr3_tip_if_write(dev_num, + ACCESS_TYPE_UNICAST, + if_id, + 0x1458, + 0x0, + 0xFFFFFFFF)); + CHECK_STATUS(ddr3_tip_if_write(dev_num, + ACCESS_TYPE_UNICAST, + if_id, + 0x145C, + 0x0, + 0xFFFFFFFF)); + } + } + } + } + } + + for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { + start_adll = ctrl_adll[if_id * cs * octets_per_if_num + pup] + + ctrl_level_phase[if_id * cs * octets_per_if_num + pup]; + CHECK_STATUS(ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, pup_access, pup, + DDR_PHY_DATA, reg, start_adll)); + if (direction == 0) + CHECK_STATUS(ddr3_tip_bus_write(dev_num, + ACCESS_TYPE_UNICAST, + if_id, + pup_access, + pup, + DDR_PHY_DATA, + CTX_PHY_REG(cs), + ctrl_adll1[if_id * + cs * + octets_per_if_num + + pup])); + } + } + + printf("Final,CS %d,%s,Leveling,Result,Adll,", cs, ((direction == 0) ? "TX" : "RX")); + + for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + if (mode == 1) { + for (pup = start_pup; pup <= end_pup; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); + printf("I/F%d-PHY%d , ", if_id, pup); + } + } else { + printf("I/F%d , ", if_id); + } + } + printf("\n"); + + for (adll = 0; adll < ADLL_LENGTH; adll++) { + adll_value = (direction == 0) ? ((adll * 2) - 32) : ((adll * 3) - 48); + printf("Final,%s,LevelingSweep,Result, %d ,", ((direction == 0) ? "TX" : "RX"), adll_value); + + for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (pup = start_pup; pup <= end_pup; pup++) + printf("%8d , ", ctrl_sweepres[adll][if_id][pup]); + } + printf("\n"); + } + + /* write back to the phy the Rx DQS value, we store in the beginning */ + write_leveling_value(dev_num, ctrl_adll, ctrl_level_phase, reg); + if (direction == 0) + ddr3_tip_write_adll_value(dev_num, ctrl_adll1, CTX_PHY_REG(cs)); + + /* print adll results */ + ddr3_tip_read_adll_value(dev_num, ctrl_adll, reg, MASK_ALL_BITS); + printf("%s,DQS,Leveling,,,", (direction == 0) ? "Tx" : "Rx"); + print_adll(dev_num, ctrl_adll); + print_ph(dev_num, ctrl_level_phase); + } + ddr3_tip_reset_fifo_ptr(dev_num); + + return 0; +} +#endif /* EXCLUDE_SWITCH_DEBUG */ + +void print_topology(struct mv_ddr_topology_map *topology_db) { u32 ui, uj; + u32 dev_num = 0; printf("\tinterface_mask: 0x%x\n", topology_db->if_act_mask); - printf("\tNum Bus: %d\n", topology_db->num_of_bus_per_interface); + printf("\tNumber of buses: 0x%x\n", + ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE)); printf("\tbus_act_mask: 0x%x\n", topology_db->bus_act_mask); for (ui = 0; ui < MAX_INTERFACE_NUM; ui++) { - VALIDATE_ACTIVE(topology_db->if_act_mask, ui); + VALIDATE_IF_ACTIVE(topology_db->if_act_mask, ui); printf("\n\tInterface ID: %d\n", ui); printf("\t\tDDR Frequency: %s\n", convert_freq(topology_db-> @@ -1457,8 +1695,9 @@ void print_topology(struct hws_topology_map *topology_db) } } } -#endif +#endif /* DDR_VIEWER_TOOL */ +#if !defined(EXCLUDE_SWITCH_DEBUG) /* * Execute XSB Test transaction (rd/wr/both) */ @@ -1468,10 +1707,10 @@ int run_xsb_test(u32 dev_num, u32 mem_addr, u32 write_type, u32 seq = 0, if_id = 0, addr, cnt; int ret = MV_OK, ret_tmp; u32 data_read[MAX_INTERFACE_NUM]; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); addr = mem_addr; for (cnt = 0; cnt <= burst_length; cnt++) { seq = (seq + 1) % 8; @@ -1501,13 +1740,7 @@ int run_xsb_test(u32 dev_num, u32 mem_addr, u32 write_type, } #else /*EXCLUDE_SWITCH_DEBUG */ - -u32 rl_version = 1; /* 0 - old RL machine */ -u32 vref = 0x4; u32 start_xsb_offset = 0; -u8 cs_mask_reg[] = { - 0, 4, 8, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; int run_xsb_test(u32 dev_num, u32 mem_addr, u32 write_type, u32 read_type, u32 burst_length) @@ -1515,4 +1748,4 @@ int run_xsb_test(u32 dev_num, u32 mem_addr, u32 write_type, return MV_OK; } -#endif +#endif /* EXCLUDE_SWITCH_DEBUG */ diff --git a/drivers/ddr/marvell/a38x/ddr3_hws_hw_training.c b/drivers/ddr/marvell/a38x/ddr3_hws_hw_training.c deleted file mode 100644 index 560da7ee80b6..000000000000 --- a/drivers/ddr/marvell/a38x/ddr3_hws_hw_training.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include -#include -#include -#include -#include -#include - -#include "ddr3_init.h" - -#define REG_READ_DATA_SAMPLE_DELAYS_ADDR 0x1538 -#define REG_READ_DATA_SAMPLE_DELAYS_MASK 0x1f -#define REG_READ_DATA_SAMPLE_DELAYS_OFFS 8 - -#define REG_READ_DATA_READY_DELAYS_ADDR 0x153c -#define REG_READ_DATA_READY_DELAYS_MASK 0x1f -#define REG_READ_DATA_READY_DELAYS_OFFS 8 - -int ddr3_if_ecc_enabled(void) -{ - struct hws_topology_map *tm = ddr3_get_topology_map(); - - if (DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask) || - DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) - return 1; - else - return 0; -} - -int ddr3_pre_algo_config(void) -{ - struct hws_topology_map *tm = ddr3_get_topology_map(); - - /* Set Bus3 ECC training mode */ - if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) { - /* Set Bus3 ECC MUX */ - CHECK_STATUS(ddr3_tip_if_write - (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, - REG_SDRAM_PINS_MUX, 0x100, 0x100)); - } - - /* Set regular ECC training mode (bus4 and bus 3) */ - if ((DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask)) || - (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask))) { - /* Enable ECC Write MUX */ - CHECK_STATUS(ddr3_tip_if_write - (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, - TRAINING_SW_2_REG, 0x100, 0x100)); - /* General ECC enable */ - CHECK_STATUS(ddr3_tip_if_write - (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, - REG_SDRAM_CONFIG_ADDR, 0x40000, 0x40000)); - /* Disable Read Data ECC MUX */ - CHECK_STATUS(ddr3_tip_if_write - (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, - TRAINING_SW_2_REG, 0x0, 0x2)); - } - - return MV_OK; -} - -int ddr3_post_algo_config(void) -{ - struct hws_topology_map *tm = ddr3_get_topology_map(); - int status; - - status = ddr3_post_run_alg(); - if (MV_OK != status) { - printf("DDR3 Post Run Alg - FAILED 0x%x\n", status); - return status; - } - - /* Un_set ECC training mode */ - if ((DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask)) || - (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask))) { - /* Disable ECC Write MUX */ - CHECK_STATUS(ddr3_tip_if_write - (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, - TRAINING_SW_2_REG, 0x0, 0x100)); - /* General ECC and Bus3 ECC MUX remains enabled */ - } - - return MV_OK; -} - -int ddr3_hws_hw_training(void) -{ - enum hws_algo_type algo_mode = ALGO_TYPE_DYNAMIC; - int status; - struct init_cntr_param init_param; - - status = ddr3_silicon_pre_init(); - if (MV_OK != status) { - printf("DDR3 Pre silicon Config - FAILED 0x%x\n", status); - return status; - } - - init_param.do_mrs_phy = 1; -#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_39X) - init_param.is_ctrl64_bit = 0; -#else - init_param.is_ctrl64_bit = 1; -#endif -#if defined(CONFIG_ALLEYCAT3) || defined(CONFIG_ARMADA_38X) || \ - defined(CONFIG_ARMADA_39X) - init_param.init_phy = 1; -#else - init_param.init_phy = 0; -#endif - init_param.msys_init = 1; - status = hws_ddr3_tip_init_controller(0, &init_param); - if (MV_OK != status) { - printf("DDR3 init controller - FAILED 0x%x\n", status); - return status; - } - - status = ddr3_silicon_post_init(); - if (MV_OK != status) { - printf("DDR3 Post Init - FAILED 0x%x\n", status); - return status; - } - - status = ddr3_pre_algo_config(); - if (MV_OK != status) { - printf("DDR3 Pre Algo Config - FAILED 0x%x\n", status); - return status; - } - - /* run algorithm in order to configure the PHY */ - status = hws_ddr3_tip_run_alg(0, algo_mode); - if (MV_OK != status) { - printf("DDR3 run algorithm - FAILED 0x%x\n", status); - return status; - } - - status = ddr3_post_algo_config(); - if (MV_OK != status) { - printf("DDR3 Post Algo Config - FAILED 0x%x\n", status); - return status; - } - - return MV_OK; -} diff --git a/drivers/ddr/marvell/a38x/ddr3_hws_hw_training.h b/drivers/ddr/marvell/a38x/ddr3_hws_hw_training.h deleted file mode 100644 index 17a09530d703..000000000000 --- a/drivers/ddr/marvell/a38x/ddr3_hws_hw_training.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#ifndef _DDR3_HWS_HW_TRAINING_H -#define _DDR3_HWS_HW_TRAINING_H - -/* struct used for DLB configuration array */ -struct dlb_config { - u32 reg_addr; - u32 reg_data; -}; - -/* Topology update structure */ -struct topology_update_info { - int update_ecc; - u8 ecc; - int update_width; - u8 width; - int update_ecc_pup3_mode; - u8 ecc_pup_mode_offset; -}; - -/* Topology update defines */ -#define TOPOLOGY_UPDATE_WIDTH_16BIT 1 -#define TOPOLOGY_UPDATE_WIDTH_32BIT 0 -#define TOPOLOGY_UPDATE_WIDTH_32BIT_MASK 0xf -#define TOPOLOGY_UPDATE_WIDTH_16BIT_MASK 0x3 - -#define TOPOLOGY_UPDATE_ECC_ON 1 -#define TOPOLOGY_UPDATE_ECC_OFF 0 -#define TOPOLOGY_UPDATE_ECC_OFFSET_PUP4 4 -#define TOPOLOGY_UPDATE_ECC_OFFSET_PUP3 3 - -/* - * 1. L2 filter should be set at binary header to 0xd000000, - * to avoid conflict with internal register IO. - * 2. U-Boot modifies internal registers base to 0xf100000, - * and than should update L2 filter accordingly to 0xf000000 (3.75 GB) - */ -/* temporary limit l2 filter to 3GiB (LSP issue) */ -#define L2_FILTER_FOR_MAX_MEMORY_SIZE 0xc0000000 -#define ADDRESS_FILTERING_END_REGISTER 0x8c04 - -#define SUB_VERSION 0 - -#endif /* _DDR3_HWS_HW_TRAINING_H */ diff --git a/drivers/ddr/marvell/a38x/ddr3_hws_hw_training_def.h b/drivers/ddr/marvell/a38x/ddr3_hws_hw_training_def.h deleted file mode 100644 index bca0af89a72d..000000000000 --- a/drivers/ddr/marvell/a38x/ddr3_hws_hw_training_def.h +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#ifndef _DDR3_HWS_HW_TRAINING_DEF_H -#define _DDR3_HWS_HW_TRAINING_DEF_H - -#define SAR_DDR3_FREQ_MASK 0xfe00000 -#define SAR_CPU_FAB_GET(cpu, fab) (((cpu & 0x7) << 21) | \ - ((fab & 0xf) << 24)) - -#define MAX_CS 4 - -#define MIN_DIMM_ADDR 0x50 -#define FAR_END_DIMM_ADDR 0x50 -#define MAX_DIMM_ADDR 0x60 - -#define SDRAM_CS_SIZE 0xfffffff -#define SDRAM_CS_BASE 0x0 -#define SDRAM_DIMM_SIZE 0x80000000 - -#define CPU_CONFIGURATION_REG(id) (0x21800 + (id * 0x100)) -#define CPU_MRVL_ID_OFFSET 0x10 -#define SAR1_CPU_CORE_MASK 0x38000000 -#define SAR1_CPU_CORE_OFFSET 27 - -#define NEW_FABRIC_TWSI_ADDR 0x4e -#ifdef DB_784MP_GP -#define BUS_WIDTH_ECC_TWSI_ADDR 0x4e -#else -#define BUS_WIDTH_ECC_TWSI_ADDR 0x4f -#endif -#define MV_MAX_DDR3_STATIC_SIZE 50 -#define MV_DDR3_MODES_NUMBER 30 - -#define RESUME_RL_PATTERNS_ADDR 0xfe0000 -#define RESUME_RL_PATTERNS_SIZE 0x100 -#define RESUME_TRAINING_VALUES_ADDR (RESUME_RL_PATTERNS_ADDR + \ - RESUME_RL_PATTERNS_SIZE) -#define RESUME_TRAINING_VALUES_MAX 0xcd0 -#define BOOT_INFO_ADDR (RESUME_RL_PATTERNS_ADDR + 0x1000) -#define CHECKSUM_RESULT_ADDR (BOOT_INFO_ADDR + 0x1000) -#define NUM_OF_REGISTER_ADDR (CHECKSUM_RESULT_ADDR + 4) -#define SUSPEND_MAGIC_WORD 0xdeadb002 -#define REGISTER_LIST_END 0xffffffff - -/* MISC */ -#define INTER_REGS_BASE SOC_REGS_PHY_BASE - -/* DDR */ -#define REG_SDRAM_CONFIG_ADDR 0x1400 -#define REG_SDRAM_CONFIG_MASK 0x9fffffff -#define REG_SDRAM_CONFIG_RFRS_MASK 0x3fff -#define REG_SDRAM_CONFIG_WIDTH_OFFS 15 -#define REG_SDRAM_CONFIG_REGDIMM_OFFS 17 -#define REG_SDRAM_CONFIG_ECC_OFFS 18 -#define REG_SDRAM_CONFIG_IERR_OFFS 19 -#define REG_SDRAM_CONFIG_PUPRSTDIV_OFFS 28 -#define REG_SDRAM_CONFIG_RSTRD_OFFS 30 - -#define REG_SDRAM_PINS_MUX 0x19d4 - -#define REG_DUNIT_CTRL_LOW_ADDR 0x1404 -#define REG_DUNIT_CTRL_LOW_2T_OFFS 3 -#define REG_DUNIT_CTRL_LOW_2T_MASK 0x3 -#define REG_DUNIT_CTRL_LOW_DPDE_OFFS 14 - -#define REG_SDRAM_TIMING_LOW_ADDR 0x1408 -#define REG_SDRAM_TIMING_HIGH_ADDR 0x140c -#define REG_SDRAM_TIMING_H_R2R_OFFS 7 -#define REG_SDRAM_TIMING_H_R2R_MASK 0x3 -#define REG_SDRAM_TIMING_H_R2W_W2R_OFFS 9 -#define REG_SDRAM_TIMING_H_R2W_W2R_MASK 0x3 -#define REG_SDRAM_TIMING_H_W2W_OFFS 11 -#define REG_SDRAM_TIMING_H_W2W_MASK 0x1f -#define REG_SDRAM_TIMING_H_R2R_H_OFFS 19 -#define REG_SDRAM_TIMING_H_R2R_H_MASK 0x7 -#define REG_SDRAM_TIMING_H_R2W_W2R_H_OFFS 22 -#define REG_SDRAM_TIMING_H_R2W_W2R_H_MASK 0x7 - -#define REG_SDRAM_ADDRESS_CTRL_ADDR 0x1410 -#define REG_SDRAM_ADDRESS_SIZE_OFFS 2 -#define REG_SDRAM_ADDRESS_SIZE_HIGH_OFFS 18 -#define REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS 4 - -#define REG_SDRAM_OPEN_PAGES_ADDR 0x1414 -#define REG_SDRAM_OPERATION_CS_OFFS 8 - -#define REG_SDRAM_OPERATION_ADDR 0x1418 -#define REG_SDRAM_OPERATION_CWA_DELAY_SEL_OFFS 24 -#define REG_SDRAM_OPERATION_CWA_DATA_OFFS 20 -#define REG_SDRAM_OPERATION_CWA_DATA_MASK 0xf -#define REG_SDRAM_OPERATION_CWA_RC_OFFS 16 -#define REG_SDRAM_OPERATION_CWA_RC_MASK 0xf -#define REG_SDRAM_OPERATION_CMD_MR0 0xf03 -#define REG_SDRAM_OPERATION_CMD_MR1 0xf04 -#define REG_SDRAM_OPERATION_CMD_MR2 0xf08 -#define REG_SDRAM_OPERATION_CMD_MR3 0xf09 -#define REG_SDRAM_OPERATION_CMD_RFRS 0xf02 -#define REG_SDRAM_OPERATION_CMD_CWA 0xf0e -#define REG_SDRAM_OPERATION_CMD_RFRS_DONE 0xf -#define REG_SDRAM_OPERATION_CMD_MASK 0xf -#define REG_SDRAM_OPERATION_CS_OFFS 8 - -#define REG_OUDDR3_TIMING_ADDR 0x142c - -#define REG_SDRAM_MODE_ADDR 0x141c - -#define REG_SDRAM_EXT_MODE_ADDR 0x1420 - -#define REG_DDR_CONT_HIGH_ADDR 0x1424 - -#define REG_ODT_TIME_LOW_ADDR 0x1428 -#define REG_ODT_ON_CTL_RD_OFFS 12 -#define REG_ODT_OFF_CTL_RD_OFFS 16 -#define REG_SDRAM_ERROR_ADDR 0x1454 -#define REG_SDRAM_AUTO_PWR_SAVE_ADDR 0x1474 -#define REG_ODT_TIME_HIGH_ADDR 0x147c - -#define REG_SDRAM_INIT_CTRL_ADDR 0x1480 -#define REG_SDRAM_INIT_CTRL_OFFS 0 -#define REG_SDRAM_INIT_CKE_ASSERT_OFFS 2 -#define REG_SDRAM_INIT_RESET_DEASSERT_OFFS 3 -#define REG_SDRAM_INIT_RESET_MASK_OFFS 1 - -#define REG_SDRAM_ODT_CTRL_LOW_ADDR 0x1494 - -#define REG_SDRAM_ODT_CTRL_HIGH_ADDR 0x1498 -#define REG_SDRAM_ODT_CTRL_HIGH_OVRD_MASK 0x0 -#define REG_SDRAM_ODT_CTRL_HIGH_OVRD_ENA 0x3 - -#define REG_DUNIT_ODT_CTRL_ADDR 0x149c -#define REG_DUNIT_ODT_CTRL_OVRD_OFFS 8 -#define REG_DUNIT_ODT_CTRL_OVRD_VAL_OFFS 9 - -#define REG_DRAM_FIFO_CTRL_ADDR 0x14a0 - -#define REG_DRAM_AXI_CTRL_ADDR 0x14a8 -#define REG_DRAM_AXI_CTRL_AXIDATABUSWIDTH_OFFS 0 - -#define REG_METAL_MASK_ADDR 0x14b0 -#define REG_METAL_MASK_MASK 0xdfffffff -#define REG_METAL_MASK_RETRY_OFFS 0 - -#define REG_DRAM_ADDR_CTRL_DRIVE_STRENGTH_ADDR 0x14c0 - -#define REG_DRAM_DATA_DQS_DRIVE_STRENGTH_ADDR 0x14c4 -#define REG_DRAM_VER_CAL_MACHINE_CTRL_ADDR 0x14c8 -#define REG_DRAM_MAIN_PADS_CAL_ADDR 0x14cc - -#define REG_DRAM_HOR_CAL_MACHINE_CTRL_ADDR 0x17c8 - -#define REG_CS_SIZE_SCRATCH_ADDR 0x1504 -#define REG_DYNAMIC_POWER_SAVE_ADDR 0x1520 -#define REG_DDR_IO_ADDR 0x1524 -#define REG_DDR_IO_CLK_RATIO_OFFS 15 - -#define REG_DFS_ADDR 0x1528 -#define REG_DFS_DLLNEXTSTATE_OFFS 0 -#define REG_DFS_BLOCK_OFFS 1 -#define REG_DFS_SR_OFFS 2 -#define REG_DFS_ATSR_OFFS 3 -#define REG_DFS_RECONF_OFFS 4 -#define REG_DFS_CL_NEXT_STATE_OFFS 8 -#define REG_DFS_CL_NEXT_STATE_MASK 0xf -#define REG_DFS_CWL_NEXT_STATE_OFFS 12 -#define REG_DFS_CWL_NEXT_STATE_MASK 0x7 - -#define REG_READ_DATA_SAMPLE_DELAYS_ADDR 0x1538 -#define REG_READ_DATA_SAMPLE_DELAYS_MASK 0x1f -#define REG_READ_DATA_SAMPLE_DELAYS_OFFS 8 - -#define REG_READ_DATA_READY_DELAYS_ADDR 0x153c -#define REG_READ_DATA_READY_DELAYS_MASK 0x1f -#define REG_READ_DATA_READY_DELAYS_OFFS 8 - -#define START_BURST_IN_ADDR 1 - -#define REG_DRAM_TRAINING_SHADOW_ADDR 0x18488 -#define REG_DRAM_TRAINING_ADDR 0x15b0 -#define REG_DRAM_TRAINING_LOW_FREQ_OFFS 0 -#define REG_DRAM_TRAINING_PATTERNS_OFFS 4 -#define REG_DRAM_TRAINING_MED_FREQ_OFFS 2 -#define REG_DRAM_TRAINING_WL_OFFS 3 -#define REG_DRAM_TRAINING_RL_OFFS 6 -#define REG_DRAM_TRAINING_DQS_RX_OFFS 15 -#define REG_DRAM_TRAINING_DQS_TX_OFFS 16 -#define REG_DRAM_TRAINING_CS_OFFS 20 -#define REG_DRAM_TRAINING_RETEST_OFFS 24 -#define REG_DRAM_TRAINING_DFS_FREQ_OFFS 27 -#define REG_DRAM_TRAINING_DFS_REQ_OFFS 29 -#define REG_DRAM_TRAINING_ERROR_OFFS 30 -#define REG_DRAM_TRAINING_AUTO_OFFS 31 -#define REG_DRAM_TRAINING_RETEST_PAR 0x3 -#define REG_DRAM_TRAINING_RETEST_MASK 0xf8ffffff -#define REG_DRAM_TRAINING_CS_MASK 0xff0fffff -#define REG_DRAM_TRAINING_PATTERNS_MASK 0xff0f0000 - -#define REG_DRAM_TRAINING_1_ADDR 0x15b4 -#define REG_DRAM_TRAINING_1_TRNBPOINT_OFFS 16 - -#define REG_DRAM_TRAINING_2_ADDR 0x15b8 -#define REG_DRAM_TRAINING_2_OVERRUN_OFFS 17 -#define REG_DRAM_TRAINING_2_FIFO_RST_OFFS 4 -#define REG_DRAM_TRAINING_2_RL_MODE_OFFS 3 -#define REG_DRAM_TRAINING_2_WL_MODE_OFFS 2 -#define REG_DRAM_TRAINING_2_ECC_MUX_OFFS 1 -#define REG_DRAM_TRAINING_2_SW_OVRD_OFFS 0 - -#define REG_DRAM_TRAINING_PATTERN_BASE_ADDR 0x15bc -#define REG_DRAM_TRAINING_PATTERN_BASE_OFFS 3 - -#define REG_TRAINING_DEBUG_2_ADDR 0x15c4 -#define REG_TRAINING_DEBUG_2_OFFS 16 -#define REG_TRAINING_DEBUG_2_MASK 0x3 - -#define REG_TRAINING_DEBUG_3_ADDR 0x15c8 -#define REG_TRAINING_DEBUG_3_OFFS 3 -#define REG_TRAINING_DEBUG_3_MASK 0x7 - -#define MR_CS_ADDR_OFFS 4 - -#define REG_DDR3_MR0_ADDR 0x15d0 -#define REG_DDR3_MR0_CS_ADDR 0x1870 -#define REG_DDR3_MR0_CL_MASK 0x74 -#define REG_DDR3_MR0_CL_OFFS 2 -#define REG_DDR3_MR0_CL_HIGH_OFFS 3 -#define CL_MASK 0xf - -#define REG_DDR3_MR1_ADDR 0x15d4 -#define REG_DDR3_MR1_CS_ADDR 0x1874 -#define REG_DDR3_MR1_RTT_MASK 0xfffffdbb -#define REG_DDR3_MR1_DLL_ENA_OFFS 0 -#define REG_DDR3_MR1_RTT_DISABLED 0x0 -#define REG_DDR3_MR1_RTT_RZQ2 0x40 -#define REG_DDR3_MR1_RTT_RZQ4 0x2 -#define REG_DDR3_MR1_RTT_RZQ6 0x42 -#define REG_DDR3_MR1_RTT_RZQ8 0x202 -#define REG_DDR3_MR1_RTT_RZQ12 0x4 -/* WL-disabled, OB-enabled */ -#define REG_DDR3_MR1_OUTBUF_WL_MASK 0xffffef7f -/* Output Buffer Disabled */ -#define REG_DDR3_MR1_OUTBUF_DIS_OFFS 12 -#define REG_DDR3_MR1_WL_ENA_OFFS 7 -#define REG_DDR3_MR1_WL_ENA 0x80 /* WL Enabled */ -#define REG_DDR3_MR1_ODT_MASK 0xfffffdbb - -#define REG_DDR3_MR2_ADDR 0x15d8 -#define REG_DDR3_MR2_CS_ADDR 0x1878 -#define REG_DDR3_MR2_CWL_OFFS 3 -#define REG_DDR3_MR2_CWL_MASK 0x7 -#define REG_DDR3_MR2_ODT_MASK 0xfffff9ff -#define REG_DDR3_MR3_ADDR 0x15dc -#define REG_DDR3_MR3_CS_ADDR 0x187c - -#define REG_DDR3_RANK_CTRL_ADDR 0x15e0 -#define REG_DDR3_RANK_CTRL_CS_ENA_MASK 0xf -#define REG_DDR3_RANK_CTRL_MIRROR_OFFS 4 - -#define REG_ZQC_CONF_ADDR 0x15e4 - -#define REG_DRAM_PHY_CONFIG_ADDR 0x15ec -#define REG_DRAM_PHY_CONFIG_MASK 0x3fffffff - -#define REG_ODPG_CNTRL_ADDR 0x1600 -#define REG_ODPG_CNTRL_OFFS 21 - -#define REG_PHY_LOCK_MASK_ADDR 0x1670 -#define REG_PHY_LOCK_MASK_MASK 0xfffff000 - -#define REG_PHY_LOCK_STATUS_ADDR 0x1674 -#define REG_PHY_LOCK_STATUS_LOCK_OFFS 9 -#define REG_PHY_LOCK_STATUS_LOCK_MASK 0xfff -#define REG_PHY_LOCK_APLL_ADLL_STATUS_MASK 0x7ff - -#define REG_PHY_REGISTRY_FILE_ACCESS_ADDR 0x16a0 -#define REG_PHY_REGISTRY_FILE_ACCESS_OP_WR 0xc0000000 -#define REG_PHY_REGISTRY_FILE_ACCESS_OP_RD 0x80000000 -#define REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE 0x80000000 -#define REG_PHY_BC_OFFS 27 -#define REG_PHY_CNTRL_OFFS 26 -#define REG_PHY_CS_OFFS 16 -#define REG_PHY_DQS_REF_DLY_OFFS 10 -#define REG_PHY_PHASE_OFFS 8 -#define REG_PHY_PUP_OFFS 22 - -#define REG_TRAINING_WL_ADDR 0x16ac -#define REG_TRAINING_WL_CS_MASK 0xfffffffc -#define REG_TRAINING_WL_UPD_OFFS 2 -#define REG_TRAINING_WL_CS_DONE_OFFS 3 -#define REG_TRAINING_WL_RATIO_MASK 0xffffff0f -#define REG_TRAINING_WL_1TO1 0x50 -#define REG_TRAINING_WL_2TO1 0x10 -#define REG_TRAINING_WL_DELAYEXP_MASK 0x20000000 -#define REG_TRAINING_WL_RESULTS_MASK 0x000001ff -#define REG_TRAINING_WL_RESULTS_OFFS 20 - -#define REG_REGISTERED_DRAM_CTRL_ADDR 0x16d0 -#define REG_REGISTERED_DRAM_CTRL_SR_FLOAT_OFFS 15 -#define REG_REGISTERED_DRAM_CTRL_PARITY_MASK 0x3f - -/* DLB */ -#define REG_STATIC_DRAM_DLB_CONTROL 0x1700 -#define DLB_BUS_OPTIMIZATION_WEIGHTS_REG 0x1704 -#define DLB_AGING_REGISTER 0x1708 -#define DLB_EVICTION_CONTROL_REG 0x170c -#define DLB_EVICTION_TIMERS_REGISTER_REG 0x1710 -#define DLB_USER_COMMAND_REG 0x1714 -#define DLB_BUS_WEIGHTS_DIFF_CS 0x1770 -#define DLB_BUS_WEIGHTS_DIFF_BG 0x1774 -#define DLB_BUS_WEIGHTS_SAME_BG 0x1778 -#define DLB_BUS_WEIGHTS_RD_WR 0x177c -#define DLB_BUS_WEIGHTS_ATTR_SYS_PRIO 0x1780 -#define DLB_MAIN_QUEUE_MAP 0x1784 -#define DLB_LINE_SPLIT 0x1788 - -#define DLB_ENABLE 0x1 -#define DLB_WRITE_COALESING (0x1 << 2) -#define DLB_AXI_PREFETCH_EN (0x1 << 3) -#define DLB_MBUS_PREFETCH_EN (0x1 << 4) -#define PREFETCH_N_LN_SZ_TR (0x1 << 6) -#define DLB_INTERJECTION_ENABLE (0x1 << 3) - -/* CPU */ -#define REG_BOOTROM_ROUTINE_ADDR 0x182d0 -#define REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS 12 - -#define REG_DRAM_INIT_CTRL_STATUS_ADDR 0x18488 -#define REG_DRAM_INIT_CTRL_TRN_CLK_OFFS 16 -#define REG_CPU_DIV_CLK_CTRL_0_NEW_RATIO 0x000200ff -#define REG_DRAM_INIT_CTRL_STATUS_2_ADDR 0x1488 - -#define REG_CPU_DIV_CLK_CTRL_0_ADDR 0x18700 - -#define REG_CPU_DIV_CLK_CTRL_1_ADDR 0x18704 -#define REG_CPU_DIV_CLK_CTRL_2_ADDR 0x18708 - -#define REG_CPU_DIV_CLK_CTRL_3_ADDR 0x1870c -#define REG_CPU_DIV_CLK_CTRL_3_FREQ_MASK 0xffffc0ff -#define REG_CPU_DIV_CLK_CTRL_3_FREQ_OFFS 8 - -#define REG_CPU_DIV_CLK_CTRL_4_ADDR 0x18710 - -#define REG_CPU_DIV_CLK_STATUS_0_ADDR 0x18718 -#define REG_CPU_DIV_CLK_ALL_STABLE_OFFS 8 - -#define REG_CPU_PLL_CTRL_0_ADDR 0x1871c -#define REG_CPU_PLL_STATUS_0_ADDR 0x18724 -#define REG_CORE_DIV_CLK_CTRL_ADDR 0x18740 -#define REG_CORE_DIV_CLK_STATUS_ADDR 0x18744 -#define REG_DDRPHY_APLL_CTRL_ADDR 0x18780 - -#define REG_DDRPHY_APLL_CTRL_2_ADDR 0x18784 -#define REG_SFABRIC_CLK_CTRL_ADDR 0x20858 -#define REG_SFABRIC_CLK_CTRL_SMPL_OFFS 8 - -/* DRAM Windows */ -#define REG_XBAR_WIN_19_CTRL_ADDR 0x200e8 -#define REG_XBAR_WIN_4_CTRL_ADDR 0x20040 -#define REG_XBAR_WIN_4_BASE_ADDR 0x20044 -#define REG_XBAR_WIN_4_REMAP_ADDR 0x20048 -#define REG_FASTPATH_WIN_0_CTRL_ADDR 0x20184 -#define REG_XBAR_WIN_7_REMAP_ADDR 0x20078 - -/* SRAM */ -#define REG_CDI_CONFIG_ADDR 0x20220 -#define REG_SRAM_WINDOW_0_ADDR 0x20240 -#define REG_SRAM_WINDOW_0_ENA_OFFS 0 -#define REG_SRAM_WINDOW_1_ADDR 0x20244 -#define REG_SRAM_L2_ENA_ADDR 0x8500 -#define REG_SRAM_CLEAN_BY_WAY_ADDR 0x87bc - -/* Timers */ -#define REG_TIMERS_CTRL_ADDR 0x20300 -#define REG_TIMERS_EVENTS_ADDR 0x20304 -#define REG_TIMER0_VALUE_ADDR 0x20314 -#define REG_TIMER1_VALUE_ADDR 0x2031c -#define REG_TIMER0_ENABLE_MASK 0x1 - -#define MV_BOARD_REFCLK_25MHZ 25000000 -#define CNTMR_RELOAD_REG(tmr) (REG_TIMERS_CTRL_ADDR + 0x10 + (tmr * 8)) -#define CNTMR_VAL_REG(tmr) (REG_TIMERS_CTRL_ADDR + 0x14 + (tmr * 8)) -#define CNTMR_CTRL_REG(tmr) (REG_TIMERS_CTRL_ADDR) -#define CTCR_ARM_TIMER_EN_OFFS(timer) (timer * 2) -#define CTCR_ARM_TIMER_EN_MASK(timer) (1 << CTCR_ARM_TIMER_EN_OFFS(timer)) -#define CTCR_ARM_TIMER_EN(timer) (1 << CTCR_ARM_TIMER_EN_OFFS(timer)) - -#define CTCR_ARM_TIMER_AUTO_OFFS(timer) (1 + (timer * 2)) -#define CTCR_ARM_TIMER_AUTO_MASK(timer) (1 << CTCR_ARM_TIMER_EN_OFFS(timer)) -#define CTCR_ARM_TIMER_AUTO_EN(timer) (1 << CTCR_ARM_TIMER_AUTO_OFFS(timer)) - -/* PMU */ -#define REG_PMU_I_F_CTRL_ADDR 0x1c090 -#define REG_PMU_DUNIT_BLK_OFFS 16 -#define REG_PMU_DUNIT_RFRS_OFFS 20 -#define REG_PMU_DUNIT_ACK_OFFS 24 - -/* MBUS */ -#define MBUS_UNITS_PRIORITY_CONTROL_REG (MBUS_REGS_OFFSET + 0x420) -#define FABRIC_UNITS_PRIORITY_CONTROL_REG (MBUS_REGS_OFFSET + 0x424) -#define MBUS_UNITS_PREFETCH_CONTROL_REG (MBUS_REGS_OFFSET + 0x428) -#define FABRIC_UNITS_PREFETCH_CONTROL_REG (MBUS_REGS_OFFSET + 0x42c) - -#define REG_PM_STAT_MASK_ADDR 0x2210c -#define REG_PM_STAT_MASK_CPU0_IDLE_MASK_OFFS 16 - -#define REG_PM_EVENT_STAT_MASK_ADDR 0x22120 -#define REG_PM_EVENT_STAT_MASK_DFS_DONE_OFFS 17 - -#define REG_PM_CTRL_CONFIG_ADDR 0x22104 -#define REG_PM_CTRL_CONFIG_DFS_REQ_OFFS 18 - -#define REG_FABRIC_LOCAL_IRQ_MASK_ADDR 0x218c4 -#define REG_FABRIC_LOCAL_IRQ_PMU_MASK_OFFS 18 - -/* Controller revision info */ -#define PCI_CLASS_CODE_AND_REVISION_ID 0x008 -#define PCCRIR_REVID_OFFS 0 /* Revision ID */ -#define PCCRIR_REVID_MASK (0xff << PCCRIR_REVID_OFFS) - -/* Power Management Clock Gating Control Register */ -#define POWER_MNG_CTRL_REG 0x18220 -#define PMC_PEXSTOPCLOCK_OFFS(p) ((p) < 8 ? (5 + (p)) : (18 + (p))) -#define PMC_PEXSTOPCLOCK_MASK(p) (1 << PMC_PEXSTOPCLOCK_OFFS(p)) -#define PMC_PEXSTOPCLOCK_EN(p) (1 << PMC_PEXSTOPCLOCK_OFFS(p)) -#define PMC_PEXSTOPCLOCK_STOP(p) (0 << PMC_PEXSTOPCLOCK_OFFS(p)) - -/* TWSI */ -#define TWSI_DATA_ADDR_MASK 0x7 -#define TWSI_DATA_ADDR_OFFS 1 - -/* General */ -#define MAX_CS 4 - -/* Frequencies */ -#define FAB_OPT 21 -#define CLK_CPU 12 -#define CLK_VCO (2 * CLK_CPU) -#define CLK_DDR 12 - -/* CPU Frequencies: */ -#define CLK_CPU_1000 0 -#define CLK_CPU_1066 1 -#define CLK_CPU_1200 2 -#define CLK_CPU_1333 3 -#define CLK_CPU_1500 4 -#define CLK_CPU_1666 5 -#define CLK_CPU_1800 6 -#define CLK_CPU_2000 7 -#define CLK_CPU_600 8 -#define CLK_CPU_667 9 -#define CLK_CPU_800 0xa - -/* Extra Cpu Frequencies: */ -#define CLK_CPU_1600 11 -#define CLK_CPU_2133 12 -#define CLK_CPU_2200 13 -#define CLK_CPU_2400 14 - -#endif /* _DDR3_HWS_HW_TRAINING_DEF_H */ diff --git a/drivers/ddr/marvell/a38x/ddr3_hws_sil_training.h b/drivers/ddr/marvell/a38x/ddr3_hws_sil_training.h deleted file mode 100644 index 544237a27620..000000000000 --- a/drivers/ddr/marvell/a38x/ddr3_hws_sil_training.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#ifndef _DDR3_HWS_SIL_TRAINING_H -#define _DDR3_HWS_SIL_TRAINING_H - -#include "ddr3_training_ip.h" -#include "ddr3_training_ip_prv_if.h" - -int ddr3_silicon_pre_config(void); -int ddr3_silicon_init(void); -int ddr3_silicon_get_ddr_target_freq(u32 *ddr_freq); - -#endif /* _DDR3_HWS_SIL_TRAINING_H */ diff --git a/drivers/ddr/marvell/a38x/ddr3_init.c b/drivers/ddr/marvell/a38x/ddr3_init.c index 4790ec1d8174..482614b2aa24 100644 --- a/drivers/ddr/marvell/a38x/ddr3_init.c +++ b/drivers/ddr/marvell/a38x/ddr3_init.c @@ -4,239 +4,30 @@ * SPDX-License-Identifier: GPL-2.0 */ -#include -#include -#include -#include -#include -#include - #include "ddr3_init.h" +#include "mv_ddr_common.h" -#include "../../../../arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h" - -static struct dlb_config ddr3_dlb_config_table[] = { - {REG_STATIC_DRAM_DLB_CONTROL, 0x2000005c}, - {DLB_BUS_OPTIMIZATION_WEIGHTS_REG, 0x00880000}, - {DLB_AGING_REGISTER, 0x0f7f007f}, - {DLB_EVICTION_CONTROL_REG, 0x0000129f}, - {DLB_EVICTION_TIMERS_REGISTER_REG, 0x00ff0000}, - {DLB_BUS_WEIGHTS_DIFF_CS, 0x04030802}, - {DLB_BUS_WEIGHTS_DIFF_BG, 0x00000a02}, - {DLB_BUS_WEIGHTS_SAME_BG, 0x09000a01}, - {DLB_BUS_WEIGHTS_RD_WR, 0x00020005}, - {DLB_BUS_WEIGHTS_ATTR_SYS_PRIO, 0x00060f10}, - {DLB_MAIN_QUEUE_MAP, 0x00000543}, - {DLB_LINE_SPLIT, 0x00000000}, - {DLB_USER_COMMAND_REG, 0x00000000}, - {0x0, 0x0} -}; - -static struct dlb_config ddr3_dlb_config_table_a0[] = { - {REG_STATIC_DRAM_DLB_CONTROL, 0x2000005c}, - {DLB_BUS_OPTIMIZATION_WEIGHTS_REG, 0x00880000}, - {DLB_AGING_REGISTER, 0x0f7f007f}, - {DLB_EVICTION_CONTROL_REG, 0x0000129f}, - {DLB_EVICTION_TIMERS_REGISTER_REG, 0x00ff0000}, - {DLB_BUS_WEIGHTS_DIFF_CS, 0x04030802}, - {DLB_BUS_WEIGHTS_DIFF_BG, 0x00000a02}, - {DLB_BUS_WEIGHTS_SAME_BG, 0x09000a01}, - {DLB_BUS_WEIGHTS_RD_WR, 0x00020005}, - {DLB_BUS_WEIGHTS_ATTR_SYS_PRIO, 0x00060f10}, - {DLB_MAIN_QUEUE_MAP, 0x00000543}, - {DLB_LINE_SPLIT, 0x00000000}, - {DLB_USER_COMMAND_REG, 0x00000000}, - {0x0, 0x0} -}; - -#if defined(CONFIG_ARMADA_38X) -struct dram_modes { - char *mode_name; - u8 cpu_freq; - u8 fab_freq; - u8 chip_id; - u8 chip_board_rev; - struct reg_data *regs; -}; - -struct dram_modes ddr_modes[] = { -}; -#endif /* defined(CONFIG_ARMADA_38X) */ - -/* Translates topology map definitions to real memory size in bits */ +/* + * Translates topology map definitions to real memory size in bits + * (per values in ddr3_training_ip_def.h) + */ u32 mem_size[] = { - ADDR_SIZE_512MB, ADDR_SIZE_1GB, ADDR_SIZE_2GB, ADDR_SIZE_4GB, + ADDR_SIZE_512MB, + ADDR_SIZE_1GB, + ADDR_SIZE_2GB, + ADDR_SIZE_4GB, ADDR_SIZE_8GB }; static char *ddr_type = "DDR3"; /* - * Set 1 to use dynamic DUNIT configuration, - * set 0 (supported for A380 and AC3) to configure DUNIT in values set by - * ddr3_tip_init_specific_reg_config + * generic_init_controller controls D-unit configuration: + * '1' - dynamic D-unit configuration, */ u8 generic_init_controller = 1; -static int ddr3_hws_tune_training_params(u8 dev_num); - -/* device revision */ -#define DEV_VERSION_ID_REG 0x1823c -#define REVISON_ID_OFFS 8 -#define REVISON_ID_MASK 0xf00 - -/* A38x revisions */ -#define MV_88F68XX_Z1_ID 0x0 -#define MV_88F68XX_A0_ID 0x4 -/* A39x revisions */ -#define MV_88F69XX_Z1_ID 0x2 - -/* - * sys_env_dlb_config_ptr_get - * - * DESCRIPTION: defines pointer to to DLB COnfiguration table - * - * INPUT: none - * - * OUTPUT: pointer to DLB COnfiguration table - * - * RETURN: - * returns pointer to DLB COnfiguration table - */ -struct dlb_config *sys_env_dlb_config_ptr_get(void) -{ -#ifdef CONFIG_ARMADA_39X - return &ddr3_dlb_config_table_a0[0]; -#else - if (sys_env_device_rev_get() == MV_88F68XX_A0_ID) - return &ddr3_dlb_config_table_a0[0]; - else - return &ddr3_dlb_config_table[0]; -#endif -} - -/* - * sys_env_get_cs_ena_from_reg - * - * DESCRIPTION: Get bit mask of enabled CS - * - * INPUT: None - * - * OUTPUT: None - * - * RETURN: - * Bit mask of enabled CS, 1 if only CS0 enabled, - * 3 if both CS0 and CS1 enabled - */ -u32 sys_env_get_cs_ena_from_reg(void) -{ - return reg_read(REG_DDR3_RANK_CTRL_ADDR) & - REG_DDR3_RANK_CTRL_CS_ENA_MASK; -} - -static void ddr3_restore_and_set_final_windows(u32 *win) -{ - u32 win_ctrl_reg, num_of_win_regs; - u32 cs_ena = sys_env_get_cs_ena_from_reg(); - u32 ui; - - win_ctrl_reg = REG_XBAR_WIN_4_CTRL_ADDR; - num_of_win_regs = 16; - - /* Return XBAR windows 4-7 or 16-19 init configuration */ - for (ui = 0; ui < num_of_win_regs; ui++) - reg_write((win_ctrl_reg + 0x4 * ui), win[ui]); - - printf("%s Training Sequence - Switching XBAR Window to FastPath Window\n", - ddr_type); - -#if defined DYNAMIC_CS_SIZE_CONFIG - if (ddr3_fast_path_dynamic_cs_size_config(cs_ena) != MV_OK) - printf("ddr3_fast_path_dynamic_cs_size_config FAILED\n"); -#else - u32 reg, cs; - reg = 0x1fffffe1; - for (cs = 0; cs < MAX_CS; cs++) { - if (cs_ena & (1 << cs)) { - reg |= (cs << 2); - break; - } - } - /* Open fast path Window to - 0.5G */ - reg_write(REG_FASTPATH_WIN_0_CTRL_ADDR, reg); -#endif -} - -static int ddr3_save_and_set_training_windows(u32 *win) -{ - u32 cs_ena; - u32 reg, tmp_count, cs, ui; - u32 win_ctrl_reg, win_base_reg, win_remap_reg; - u32 num_of_win_regs, win_jump_index; - win_ctrl_reg = REG_XBAR_WIN_4_CTRL_ADDR; - win_base_reg = REG_XBAR_WIN_4_BASE_ADDR; - win_remap_reg = REG_XBAR_WIN_4_REMAP_ADDR; - win_jump_index = 0x10; - num_of_win_regs = 16; - struct hws_topology_map *tm = ddr3_get_topology_map(); - -#ifdef DISABLE_L2_FILTERING_DURING_DDR_TRAINING - /* - * Disable L2 filtering during DDR training - * (when Cross Bar window is open) - */ - reg_write(ADDRESS_FILTERING_END_REGISTER, 0); -#endif - - cs_ena = tm->interface_params[0].as_bus_params[0].cs_bitmask; - - /* Close XBAR Window 19 - Not needed */ - /* {0x000200e8} - Open Mbus Window - 2G */ - reg_write(REG_XBAR_WIN_19_CTRL_ADDR, 0); - - /* Save XBAR Windows 4-19 init configurations */ - for (ui = 0; ui < num_of_win_regs; ui++) - win[ui] = reg_read(win_ctrl_reg + 0x4 * ui); - - /* Open XBAR Windows 4-7 or 16-19 for other CS */ - reg = 0; - tmp_count = 0; - for (cs = 0; cs < MAX_CS; cs++) { - if (cs_ena & (1 << cs)) { - switch (cs) { - case 0: - reg = 0x0e00; - break; - case 1: - reg = 0x0d00; - break; - case 2: - reg = 0x0b00; - break; - case 3: - reg = 0x0700; - break; - } - reg |= (1 << 0); - reg |= (SDRAM_CS_SIZE & 0xffff0000); - - reg_write(win_ctrl_reg + win_jump_index * tmp_count, - reg); - reg = (((SDRAM_CS_SIZE + 1) * (tmp_count)) & - 0xffff0000); - reg_write(win_base_reg + win_jump_index * tmp_count, - reg); - - if (win_remap_reg <= REG_XBAR_WIN_7_REMAP_ADDR) - reg_write(win_remap_reg + - win_jump_index * tmp_count, 0); - - tmp_count++; - } - } - - return MV_OK; -} +static int mv_ddr_training_params_set(u8 dev_num); /* * Name: ddr3_init - Main DDR3 Init function @@ -247,464 +38,182 @@ static int ddr3_save_and_set_training_windows(u32 *win) */ int ddr3_init(void) { - u32 reg = 0; - u32 soc_num; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + u32 octets_per_if_num; int status; - u32 win[16]; - - /* SoC/Board special Initializtions */ - /* Get version from internal library */ - ddr3_print_version(); - - /*Add sub_version string */ - DEBUG_INIT_C("", SUB_VERSION, 1); - - /* Switching CPU to MRVL ID */ - soc_num = (reg_read(REG_SAMPLE_RESET_HIGH_ADDR) & SAR1_CPU_CORE_MASK) >> - SAR1_CPU_CORE_OFFSET; - switch (soc_num) { - case 0x3: - case 0x1: - reg_bit_set(CPU_CONFIGURATION_REG(1), CPU_MRVL_ID_OFFSET); - case 0x0: - reg_bit_set(CPU_CONFIGURATION_REG(0), CPU_MRVL_ID_OFFSET); - default: - break; - } + int is_manual_cal_done; - /* - * Set DRAM Reset Mask in case detected GPIO indication of wakeup from - * suspend i.e the DRAM values will not be overwritten / reset when - * waking from suspend - */ - if (sys_env_suspend_wakeup_check() == - SUSPEND_WAKEUP_ENABLED_GPIO_DETECTED) { - reg_bit_set(REG_SDRAM_INIT_CTRL_ADDR, - 1 << REG_SDRAM_INIT_RESET_MASK_OFFS); - } + /* Print mv_ddr version */ + mv_ddr_ver_print(); - /* - * Stage 0 - Set board configuration - */ + mv_ddr_pre_training_fixup(); - /* Check if DRAM is already initialized */ - if (reg_read(REG_BOOTROM_ROUTINE_ADDR) & - (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)) { - printf("%s Training Sequence - 2nd boot - Skip\n", ddr_type); - return MV_OK; - } + /* SoC/Board special initializations */ + mv_ddr_pre_training_soc_config(ddr_type); - /* - * Stage 1 - Dunit Setup - */ - - /* Fix read ready phases for all SOC in reg 0x15c8 */ - reg = reg_read(REG_TRAINING_DEBUG_3_ADDR); - reg &= ~(REG_TRAINING_DEBUG_3_MASK); - reg |= 0x4; /* Phase 0 */ - reg &= ~(REG_TRAINING_DEBUG_3_MASK << REG_TRAINING_DEBUG_3_OFFS); - reg |= (0x4 << (1 * REG_TRAINING_DEBUG_3_OFFS)); /* Phase 1 */ - reg &= ~(REG_TRAINING_DEBUG_3_MASK << (3 * REG_TRAINING_DEBUG_3_OFFS)); - reg |= (0x6 << (3 * REG_TRAINING_DEBUG_3_OFFS)); /* Phase 3 */ - reg &= ~(REG_TRAINING_DEBUG_3_MASK << (4 * REG_TRAINING_DEBUG_3_OFFS)); - reg |= (0x6 << (4 * REG_TRAINING_DEBUG_3_OFFS)); - reg &= ~(REG_TRAINING_DEBUG_3_MASK << (5 * REG_TRAINING_DEBUG_3_OFFS)); - reg |= (0x6 << (5 * REG_TRAINING_DEBUG_3_OFFS)); - reg_write(REG_TRAINING_DEBUG_3_ADDR, reg); - - /* - * Axi_bresp_mode[8] = Compliant, - * Axi_addr_decode_cntrl[11] = Internal, - * Axi_data_bus_width[0] = 128bit - * */ - /* 0x14a8 - AXI Control Register */ - reg_write(REG_DRAM_AXI_CTRL_ADDR, 0); - - /* - * Stage 2 - Training Values Setup - */ - /* Set X-BAR windows for the training sequence */ - ddr3_save_and_set_training_windows(win); - - - /* Tune training algo paramteres */ - status = ddr3_hws_tune_training_params(0); - if (MV_OK != status) - return status; + /* Set log level for training library */ + mv_ddr_user_log_level_set(DEBUG_BLOCK_ALL); - /* Set log level for training lib */ - ddr3_hws_set_log_level(DEBUG_BLOCK_ALL, DEBUG_LEVEL_ERROR); + mv_ddr_early_init(); - /* Start New Training IP */ - status = ddr3_hws_hw_training(); - if (MV_OK != status) { - printf("%s Training Sequence - FAILED\n", ddr_type); - return status; + if (mv_ddr_topology_map_update() == NULL) { + printf("mv_ddr: failed to update topology\n"); + return MV_FAIL; } - /* - * Stage 3 - Finish - */ - /* Restore and set windows */ - ddr3_restore_and_set_final_windows(win); - - /* Update DRAM init indication in bootROM register */ - reg = reg_read(REG_BOOTROM_ROUTINE_ADDR); - reg_write(REG_BOOTROM_ROUTINE_ADDR, - reg | (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)); - - /* DLB config */ - ddr3_new_tip_dlb_config(); - -#if defined(ECC_SUPPORT) - if (ddr3_if_ecc_enabled()) - ddr3_new_tip_ecc_scrub(); -#endif - - printf("%s Training Sequence - Ended Successfully\n", ddr_type); - - return MV_OK; -} + if (mv_ddr_early_init2() != MV_OK) + return MV_FAIL; -/* - * Name: ddr3_get_cpu_freq - * Desc: read S at R and return CPU frequency - * Args: - * Notes: - * Returns: required value - */ -u32 ddr3_get_cpu_freq(void) -{ - return ddr3_tip_get_init_freq(); -} + /* Set training algorithm's parameters */ + status = mv_ddr_training_params_set(0); + if (MV_OK != status) + return status; -/* - * Name: ddr3_get_fab_opt - * Desc: read S@R and return CPU frequency - * Args: - * Notes: - * Returns: required value - */ -u32 ddr3_get_fab_opt(void) -{ - return 0; /* No fabric */ -} -/* - * Name: ddr3_get_static_m_cValue - Init Memory controller with - * static parameters - * Desc: Use this routine to init the controller without the HW training - * procedure. - * User must provide compatible header file with registers data. - * Args: None. - * Notes: - * Returns: None. - */ -u32 ddr3_get_static_mc_value(u32 reg_addr, u32 offset1, u32 mask1, - u32 offset2, u32 mask2) -{ - u32 reg, temp; + mv_ddr_mc_config(); - reg = reg_read(reg_addr); + is_manual_cal_done = mv_ddr_manual_cal_do(); - temp = (reg >> offset1) & mask1; - if (mask2) - temp |= (reg >> offset2) & mask2; + mv_ddr_mc_init(); - return temp; -} + if (!is_manual_cal_done) { + } -/* - * Name: ddr3_get_static_ddr_mode - Init Memory controller with - * static parameters - * Desc: Use this routine to init the controller without the HW training - * procedure. - * User must provide compatible header file with registers data. - * Args: None. - * Notes: - * Returns: None. - */ -u32 ddr3_get_static_ddr_mode(void) -{ - u32 chip_board_rev, i; - u32 size; - - /* Valid only for A380 only, MSYS using dynamic controller config */ -#ifdef CONFIG_CUSTOMER_BOARD_SUPPORT - /* - * Customer boards select DDR mode according to - * board ID & Sample at Reset - */ - chip_board_rev = mv_board_id_get(); -#else - /* Marvell boards select DDR mode according to Sample at Reset only */ - chip_board_rev = MARVELL_BOARD; -#endif - size = ARRAY_SIZE(ddr_modes); - for (i = 0; i < size; i++) { - if ((ddr3_get_cpu_freq() == ddr_modes[i].cpu_freq) && - (ddr3_get_fab_opt() == ddr_modes[i].fab_freq) && - (chip_board_rev == ddr_modes[i].chip_board_rev)) - return i; + status = ddr3_silicon_post_init(); + if (MV_OK != status) { + printf("DDR3 Post Init - FAILED 0x%x\n", status); + return status; } - DEBUG_INIT_S("\n*** Error: ddr3_get_static_ddr_mode: No match for requested DDR mode. ***\n\n"); - - return 0; -} + /* PHY initialization (Training) */ + status = hws_ddr3_tip_run_alg(0, ALGO_TYPE_DYNAMIC); + if (MV_OK != status) { + printf("%s Training Sequence - FAILED\n", ddr_type); + return status; + } -/****************************************************************************** - * Name: ddr3_get_cs_num_from_reg - * Desc: - * Args: - * Notes: - * Returns: - */ -u32 ddr3_get_cs_num_from_reg(void) -{ - u32 cs_ena = sys_env_get_cs_ena_from_reg(); - u32 cs_count = 0; - u32 cs; +#if defined(CONFIG_PHY_STATIC_PRINT) + mv_ddr_phy_static_print(); +#endif - for (cs = 0; cs < MAX_CS; cs++) { - if (cs_ena & (1 << cs)) - cs_count++; - } + /* Post MC/PHY initializations */ + mv_ddr_post_training_soc_config(ddr_type); - return cs_count; -} + mv_ddr_post_training_fixup(); -void get_target_freq(u32 freq_mode, u32 *ddr_freq, u32 *hclk_ps) -{ - u32 tmp, hclk = 200; - - switch (freq_mode) { - case 4: - tmp = 1; /* DDR_400; */ - hclk = 200; - break; - case 0x8: - tmp = 1; /* DDR_666; */ - hclk = 333; - break; - case 0xc: - tmp = 1; /* DDR_800; */ - hclk = 400; - break; - default: - *ddr_freq = 0; - *hclk_ps = 0; - break; + octets_per_if_num = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE); + if (ddr3_if_ecc_enabled()) { + if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask) || + MV_DDR_IS_32BIT_IN_64BIT_DRAM_MODE(tm->bus_act_mask, octets_per_if_num)) + mv_ddr_mem_scrubbing(); + else + ddr3_new_tip_ecc_scrub(); } - *ddr_freq = tmp; /* DDR freq define */ - *hclk_ps = 1000000 / hclk; /* values are 1/HCLK in ps */ + printf("mv_ddr: completed successfully\n"); - return; + return MV_OK; } -void ddr3_new_tip_dlb_config(void) +uint64_t mv_ddr_get_memory_size_per_cs_in_bits(void) { - u32 reg, i = 0; - struct dlb_config *config_table_ptr = sys_env_dlb_config_ptr_get(); - - /* Write the configuration */ - while (config_table_ptr[i].reg_addr != 0) { - reg_write(config_table_ptr[i].reg_addr, - config_table_ptr[i].reg_data); - i++; - } + uint64_t memory_size_per_cs; - /* Enable DLB */ - reg = reg_read(REG_STATIC_DRAM_DLB_CONTROL); - reg |= DLB_ENABLE | DLB_WRITE_COALESING | DLB_AXI_PREFETCH_EN | - DLB_MBUS_PREFETCH_EN | PREFETCH_N_LN_SZ_TR; - reg_write(REG_STATIC_DRAM_DLB_CONTROL, reg); -} + u32 bus_cnt, num_of_active_bus = 0; + u32 num_of_sub_phys_per_ddr_unit = 0; -int ddr3_fast_path_dynamic_cs_size_config(u32 cs_ena) -{ - u32 reg, cs; - u32 mem_total_size = 0; - u32 cs_mem_size = 0; - u32 mem_total_size_c, cs_mem_size_c; - -#ifdef DEVICE_MAX_DRAM_ADDRESS_SIZE - u32 physical_mem_size; - u32 max_mem_size = DEVICE_MAX_DRAM_ADDRESS_SIZE; - struct hws_topology_map *tm = ddr3_get_topology_map(); -#endif + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - /* Open fast path windows */ - for (cs = 0; cs < MAX_CS; cs++) { - if (cs_ena & (1 << cs)) { - /* get CS size */ - if (ddr3_calc_mem_cs_size(cs, &cs_mem_size) != MV_OK) - return MV_FAIL; - -#ifdef DEVICE_MAX_DRAM_ADDRESS_SIZE - /* - * if number of address pins doesn't allow to use max - * mem size that is defined in topology - * mem size is defined by DEVICE_MAX_DRAM_ADDRESS_SIZE - */ - physical_mem_size = mem_size - [tm->interface_params[0].memory_size]; - - if (ddr3_get_device_width(cs) == 16) { - /* - * 16bit mem device can be twice more - no need - * in less significant pin - */ - max_mem_size = DEVICE_MAX_DRAM_ADDRESS_SIZE * 2; - } - - if (physical_mem_size > max_mem_size) { - cs_mem_size = max_mem_size * - (ddr3_get_bus_width() / - ddr3_get_device_width(cs)); - printf("Updated Physical Mem size is from 0x%x to %x\n", - physical_mem_size, - DEVICE_MAX_DRAM_ADDRESS_SIZE); - } -#endif + u32 octets_per_if_num = ddr3_tip_dev_attr_get(DEV_NUM_0, MV_ATTR_OCTET_PER_INTERFACE); - /* set fast path window control for the cs */ - reg = 0xffffe1; - reg |= (cs << 2); - reg |= (cs_mem_size - 1) & 0xffff0000; - /*Open fast path Window */ - reg_write(REG_FASTPATH_WIN_CTRL_ADDR(cs), reg); - - /* Set fast path window base address for the cs */ - reg = ((cs_mem_size) * cs) & 0xffff0000; - /* Set base address */ - reg_write(REG_FASTPATH_WIN_BASE_ADDR(cs), reg); - - /* - * Since memory size may be bigger than 4G the summ may - * be more than 32 bit word, - * so to estimate the result divide mem_total_size and - * cs_mem_size by 0x10000 (it is equal to >> 16) - */ - mem_total_size_c = mem_total_size >> 16; - cs_mem_size_c = cs_mem_size >> 16; - /* if the sum less than 2 G - calculate the value */ - if (mem_total_size_c + cs_mem_size_c < 0x10000) - mem_total_size += cs_mem_size; - else /* put max possible size */ - mem_total_size = L2_FILTER_FOR_MAX_MEMORY_SIZE; - } + /* count the number of active bus */ + for (bus_cnt = 0; bus_cnt < octets_per_if_num - 1/* ignore ecc octet */; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); + num_of_active_bus++; } - /* Set L2 filtering to Max Memory size */ - reg_write(ADDRESS_FILTERING_END_REGISTER, mem_total_size); + /* calculate number of sub-phys per ddr unit */ + if (tm->interface_params[0].bus_width/* supports only single interface */ == MV_DDR_DEV_WIDTH_16BIT) + num_of_sub_phys_per_ddr_unit = TWO_SUB_PHYS; + if (tm->interface_params[0].bus_width/* supports only single interface */ == MV_DDR_DEV_WIDTH_8BIT) + num_of_sub_phys_per_ddr_unit = SINGLE_SUB_PHY; - return MV_OK; -} - -u32 ddr3_get_bus_width(void) -{ - u32 bus_width; + /* calculate dram size per cs */ + memory_size_per_cs = (uint64_t)mem_size[tm->interface_params[0].memory_size] * (uint64_t)num_of_active_bus + / (uint64_t)num_of_sub_phys_per_ddr_unit * (uint64_t)MV_DDR_NUM_BITS_IN_BYTE; - bus_width = (reg_read(REG_SDRAM_CONFIG_ADDR) & 0x8000) >> - REG_SDRAM_CONFIG_WIDTH_OFFS; - - return (bus_width == 0) ? 16 : 32; + return memory_size_per_cs; } -u32 ddr3_get_device_width(u32 cs) +uint64_t mv_ddr_get_total_memory_size_in_bits(void) { - u32 device_width; + uint64_t total_memory_size = 0; + uint64_t memory_size_per_cs = 0; - device_width = (reg_read(REG_SDRAM_ADDRESS_CTRL_ADDR) & - (0x3 << (REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS * cs))) >> - (REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS * cs); + /* get the number of cs */ + u32 max_cs = ddr3_tip_max_cs_get(DEV_NUM_0); - return (device_width == 0) ? 8 : 16; -} + memory_size_per_cs = mv_ddr_get_memory_size_per_cs_in_bits(); + total_memory_size = (uint64_t)max_cs * memory_size_per_cs; -static int ddr3_get_device_size(u32 cs) -{ - u32 device_size_low, device_size_high, device_size; - u32 data, cs_low_offset, cs_high_offset; - - cs_low_offset = REG_SDRAM_ADDRESS_SIZE_OFFS + cs * 4; - cs_high_offset = REG_SDRAM_ADDRESS_SIZE_OFFS + - REG_SDRAM_ADDRESS_SIZE_HIGH_OFFS + cs; - - data = reg_read(REG_SDRAM_ADDRESS_CTRL_ADDR); - device_size_low = (data >> cs_low_offset) & 0x3; - device_size_high = (data >> cs_high_offset) & 0x1; - - device_size = device_size_low | (device_size_high << 2); - - switch (device_size) { - case 0: - return 2048; - case 2: - return 512; - case 3: - return 1024; - case 4: - return 4096; - case 5: - return 8192; - case 1: - default: - DEBUG_INIT_C("Error: Wrong device size of Cs: ", cs, 1); - /* - * Small value will give wrong emem size in - * ddr3_calc_mem_cs_size - */ - return 0; - } + return total_memory_size; } -int ddr3_calc_mem_cs_size(u32 cs, u32 *cs_size) +int ddr3_if_ecc_enabled(void) { - int cs_mem_size; - - /* Calculate in GiB */ - cs_mem_size = ((ddr3_get_bus_width() / ddr3_get_device_width(cs)) * - ddr3_get_device_size(cs)) / 8; - - /* - * Multiple controller bus width, 2x for 64 bit - * (SoC controller may be 32 or 64 bit, - * so bit 15 in 0x1400, that means if whole bus used or only half, - * have a differnt meaning - */ - cs_mem_size *= DDR_CONTROLLER_BUS_WIDTH_MULTIPLIER; - - if (!cs_mem_size || (cs_mem_size == 64) || (cs_mem_size == 4096)) { - DEBUG_INIT_C("Error: Wrong Memory size of Cs: ", cs, 1); - return MV_BAD_VALUE; - } + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - *cs_size = cs_mem_size << 20; - return MV_OK; + if (DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask) || + DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask) || + DDR3_IS_ECC_PUP8_MODE(tm->bus_act_mask)) + return 1; + else + return 0; } /* - * Name: ddr3_hws_tune_training_params + * Name: mv_ddr_training_params_set * Desc: * Args: - * Notes: Tune internal training params + * Notes: sets internal training params * Returns: */ -static int ddr3_hws_tune_training_params(u8 dev_num) +static int mv_ddr_training_params_set(u8 dev_num) { struct tune_train_params params; int status; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + u32 if_id; + u32 cs_num; + + CHECK_STATUS(ddr3_tip_get_first_active_if + (dev_num, tm->if_act_mask, + &if_id)); + + CHECK_STATUS(calc_cs_num(dev_num, if_id, &cs_num)); /* NOTE: do not remove any field initilization */ params.ck_delay = TUNE_TRAINING_PARAMS_CK_DELAY; - params.ck_delay_16 = TUNE_TRAINING_PARAMS_CK_DELAY_16; - params.p_finger = TUNE_TRAINING_PARAMS_PFINGER; - params.n_finger = TUNE_TRAINING_PARAMS_NFINGER; params.phy_reg3_val = TUNE_TRAINING_PARAMS_PHYREG3VAL; + params.g_zpri_data = TUNE_TRAINING_PARAMS_PRI_DATA; + params.g_znri_data = TUNE_TRAINING_PARAMS_NRI_DATA; + params.g_zpri_ctrl = TUNE_TRAINING_PARAMS_PRI_CTRL; + params.g_znri_ctrl = TUNE_TRAINING_PARAMS_NRI_CTRL; + params.g_znodt_data = TUNE_TRAINING_PARAMS_N_ODT_DATA; + params.g_zpodt_ctrl = TUNE_TRAINING_PARAMS_P_ODT_CTRL; + params.g_znodt_ctrl = TUNE_TRAINING_PARAMS_N_ODT_CTRL; + + params.g_zpodt_data = TUNE_TRAINING_PARAMS_P_ODT_DATA; + params.g_dic = TUNE_TRAINING_PARAMS_DIC; + params.g_rtt_nom = TUNE_TRAINING_PARAMS_RTT_NOM; + if (cs_num == 1) { + params.g_rtt_wr = TUNE_TRAINING_PARAMS_RTT_WR_1CS; + params.g_odt_config = TUNE_TRAINING_PARAMS_ODT_CONFIG_1CS; + } else { + params.g_rtt_wr = TUNE_TRAINING_PARAMS_RTT_WR_2CS; + params.g_odt_config = TUNE_TRAINING_PARAMS_ODT_CONFIG_2CS; + } status = ddr3_tip_tune_training_params(dev_num, ¶ms); if (MV_OK != status) { diff --git a/drivers/ddr/marvell/a38x/ddr3_init.h b/drivers/ddr/marvell/a38x/ddr3_init.h index cbf072cdef6f..70f5657f8893 100644 --- a/drivers/ddr/marvell/a38x/ddr3_init.h +++ b/drivers/ddr/marvell/a38x/ddr3_init.h @@ -7,12 +7,12 @@ #ifndef _DDR3_INIT_H #define _DDR3_INIT_H -#if defined(CONFIG_ARMADA_38X) -#include "ddr3_a38x.h" -#include "ddr3_a38x_topology.h" +#include "ddr_ml_wrapper.h" +#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_39X) +#include "mv_ddr_plat.h" #endif -#include "ddr3_hws_hw_training.h" -#include "ddr3_hws_sil_training.h" + +#include "seq_exec.h" #include "ddr3_logging_def.h" #include "ddr3_training_hw_algo.h" #include "ddr3_training_ip.h" @@ -21,119 +21,9 @@ #include "ddr3_training_ip_flow.h" #include "ddr3_training_ip_pbs.h" #include "ddr3_training_ip_prv_if.h" -#include "ddr3_training_ip_static.h" #include "ddr3_training_leveling.h" #include "xor.h" -/* - * MV_DEBUG_INIT need to be defines, otherwise the output of the - * DDR2 training code is not complete and misleading - */ -#define MV_DEBUG_INIT - -#ifdef MV_DEBUG_INIT -#define DEBUG_INIT_S(s) puts(s) -#define DEBUG_INIT_D(d, l) printf("%x", d) -#define DEBUG_INIT_D_10(d, l) printf("%d", d) -#else -#define DEBUG_INIT_S(s) -#define DEBUG_INIT_D(d, l) -#define DEBUG_INIT_D_10(d, l) -#endif - -#ifdef MV_DEBUG_INIT_FULL -#define DEBUG_INIT_FULL_S(s) puts(s) -#define DEBUG_INIT_FULL_D(d, l) printf("%x", d) -#define DEBUG_INIT_FULL_D_10(d, l) printf("%d", d) -#define DEBUG_WR_REG(reg, val) \ - { DEBUG_INIT_S("Write Reg: 0x"); DEBUG_INIT_D((reg), 8); \ - DEBUG_INIT_S("= "); DEBUG_INIT_D((val), 8); DEBUG_INIT_S("\n"); } -#define DEBUG_RD_REG(reg, val) \ - { DEBUG_INIT_S("Read Reg: 0x"); DEBUG_INIT_D((reg), 8); \ - DEBUG_INIT_S("= "); DEBUG_INIT_D((val), 8); DEBUG_INIT_S("\n"); } -#else -#define DEBUG_INIT_FULL_S(s) -#define DEBUG_INIT_FULL_D(d, l) -#define DEBUG_INIT_FULL_D_10(d, l) -#define DEBUG_WR_REG(reg, val) -#define DEBUG_RD_REG(reg, val) -#endif - -#define DEBUG_INIT_FULL_C(s, d, l) \ - { DEBUG_INIT_FULL_S(s); \ - DEBUG_INIT_FULL_D(d, l); \ - DEBUG_INIT_FULL_S("\n"); } -#define DEBUG_INIT_C(s, d, l) \ - { DEBUG_INIT_S(s); DEBUG_INIT_D(d, l); DEBUG_INIT_S("\n"); } - -/* - * Debug (Enable/Disable modules) and Error report - */ - -#ifdef BASIC_DEBUG -#define MV_DEBUG_WL -#define MV_DEBUG_RL -#define MV_DEBUG_DQS_RESULTS -#endif - -#ifdef FULL_DEBUG -#define MV_DEBUG_WL -#define MV_DEBUG_RL -#define MV_DEBUG_DQS - -#define MV_DEBUG_PBS -#define MV_DEBUG_DFS -#define MV_DEBUG_MAIN_FULL -#define MV_DEBUG_DFS_FULL -#define MV_DEBUG_DQS_FULL -#define MV_DEBUG_RL_FULL -#define MV_DEBUG_WL_FULL -#endif - -#if defined(CONFIG_ARMADA_38X) -#include "ddr3_a38x.h" -#include "ddr3_a38x_topology.h" -#endif - -/* The following is a list of Marvell status */ -#define MV_ERROR (-1) -#define MV_OK (0x00) /* Operation succeeded */ -#define MV_FAIL (0x01) /* Operation failed */ -#define MV_BAD_VALUE (0x02) /* Illegal value (general) */ -#define MV_OUT_OF_RANGE (0x03) /* The value is out of range */ -#define MV_BAD_PARAM (0x04) /* Illegal parameter in function called */ -#define MV_BAD_PTR (0x05) /* Illegal pointer value */ -#define MV_BAD_SIZE (0x06) /* Illegal size */ -#define MV_BAD_STATE (0x07) /* Illegal state of state machine */ -#define MV_SET_ERROR (0x08) /* Set operation failed */ -#define MV_GET_ERROR (0x09) /* Get operation failed */ -#define MV_CREATE_ERROR (0x0a) /* Fail while creating an item */ -#define MV_NOT_FOUND (0x0b) /* Item not found */ -#define MV_NO_MORE (0x0c) /* No more items found */ -#define MV_NO_SUCH (0x0d) /* No such item */ -#define MV_TIMEOUT (0x0e) /* Time Out */ -#define MV_NO_CHANGE (0x0f) /* Parameter(s) is already in this value */ -#define MV_NOT_SUPPORTED (0x10) /* This request is not support */ -#define MV_NOT_IMPLEMENTED (0x11) /* Request supported but not implemented*/ -#define MV_NOT_INITIALIZED (0x12) /* The item is not initialized */ -#define MV_NO_RESOURCE (0x13) /* Resource not available (memory ...) */ -#define MV_FULL (0x14) /* Item is full (Queue or table etc...) */ -#define MV_EMPTY (0x15) /* Item is empty (Queue or table etc...) */ -#define MV_INIT_ERROR (0x16) /* Error occurred while INIT process */ -#define MV_HW_ERROR (0x17) /* Hardware error */ -#define MV_TX_ERROR (0x18) /* Transmit operation not succeeded */ -#define MV_RX_ERROR (0x19) /* Recieve operation not succeeded */ -#define MV_NOT_READY (0x1a) /* The other side is not ready yet */ -#define MV_ALREADY_EXIST (0x1b) /* Tried to create existing item */ -#define MV_OUT_OF_CPU_MEM (0x1c) /* Cpu memory allocation failed. */ -#define MV_NOT_STARTED (0x1d) /* Not started yet */ -#define MV_BUSY (0x1e) /* Item is busy. */ -#define MV_TERMINATE (0x1f) /* Item terminates it's work. */ -#define MV_NOT_ALIGNED (0x20) /* Wrong alignment */ -#define MV_NOT_ALLOWED (0x21) /* Operation NOT allowed */ -#define MV_WRITE_PROTECT (0x22) /* Write protected */ -#define MV_INVALID (int)(-1) - /* For checking function return values */ #define CHECK_STATUS(orig_func) \ { \ @@ -143,6 +33,14 @@ return status; \ } +#define GET_MAX_VALUE(x, y) \ + ((x) > (y)) ? (x) : (y) + +#define SUB_VERSION 0 + +/* max number of devices supported by driver */ +#define MAX_DEVICE_NUM 1 + enum log_level { MV_LOG_LEVEL_0, MV_LOG_LEVEL_1, @@ -151,28 +49,27 @@ enum log_level { }; /* Globals */ -extern u8 debug_training; +extern u8 debug_training, debug_calibration, debug_ddr4_centralization, + debug_tap_tuning, debug_dm_tuning; extern u8 is_reg_dump; extern u8 generic_init_controller; -extern u32 freq_val[]; +/* list of allowed frequency listed in order of enum hws_ddr_freq */ +extern u32 freq_val[DDR_FREQ_LAST]; extern u32 is_pll_old; extern struct cl_val_per_freq cas_latency_table[]; extern struct pattern_info pattern_table[]; extern struct cl_val_per_freq cas_write_latency_table[]; -extern u8 debug_training; extern u8 debug_centralization, debug_training_ip, debug_training_bist, debug_pbs, debug_training_static, debug_leveling; -extern u32 pipe_multicast_mask; extern struct hws_tip_config_func_db config_func_info[]; -extern u8 cs_mask_reg[]; extern u8 twr_mask_table[]; extern u8 cl_mask_table[]; extern u8 cwl_mask_table[]; extern u16 rfc_table[]; extern u32 speed_bin_table_t_rc[]; extern u32 speed_bin_table_t_rcd_t_rp[]; -extern u32 ck_delay, ck_delay_16; +extern u32 vref_init_val; extern u32 g_zpri_data; extern u32 g_znri_data; extern u32 g_zpri_ctrl; @@ -182,39 +79,28 @@ extern u32 g_znodt_data; extern u32 g_zpodt_ctrl; extern u32 g_znodt_ctrl; extern u32 g_dic; -extern u32 g_odt_config_2cs; -extern u32 g_odt_config_1cs; +extern u32 g_odt_config; extern u32 g_rtt_nom; +extern u32 g_rtt_wr; +extern u32 g_rtt_park; extern u8 debug_training_access; -extern u8 debug_training_a38x; extern u32 first_active_if; -extern enum hws_ddr_freq init_freq; -extern u32 delay_enable, ck_delay, ck_delay_16, ca_delay; +extern u32 delay_enable, ck_delay, ca_delay; extern u32 mask_tune_func; extern u32 rl_version; extern int rl_mid_freq_wa; extern u8 calibration_update_control; /* 2 external only, 1 is internal only */ extern enum hws_ddr_freq medium_freq; -extern u32 ck_delay, ck_delay_16; extern enum hws_result training_result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM]; -extern u32 first_active_if; -extern u32 mask_tune_func; -extern u32 freq_val[]; -extern enum hws_ddr_freq init_freq; extern enum hws_ddr_freq low_freq; -extern enum hws_ddr_freq medium_freq; -extern u8 generic_init_controller; extern enum auto_tune_stage training_stage; extern u32 is_pll_before_init; extern u32 is_adll_calib_before_init; extern u32 is_dfs_in_init; extern int wl_debug_delay; -extern u32 silicon_delay[HWS_MAX_DEVICE_NUM]; -extern u32 p_finger; -extern u32 n_finger; -extern u32 freq_val[DDR_FREQ_LIMIT]; +extern u32 silicon_delay[MAX_DEVICE_NUM]; extern u32 start_pattern, end_pattern; extern u32 phy_reg0_val; extern u32 phy_reg1_val; @@ -222,172 +108,93 @@ extern u32 phy_reg2_val; extern u32 phy_reg3_val; extern enum hws_pattern sweep_pattern; extern enum hws_pattern pbs_pattern; -extern u8 is_rzq6; -extern u32 znri_data_phy_val; -extern u32 zpri_data_phy_val; -extern u32 znri_ctrl_phy_val; -extern u32 zpri_ctrl_phy_val; -extern u8 debug_training_access; +extern u32 g_znri_data; +extern u32 g_zpri_data; +extern u32 g_znri_ctrl; +extern u32 g_zpri_ctrl; extern u32 finger_test, p_finger_start, p_finger_end, n_finger_start, n_finger_end, p_finger_step, n_finger_step; -extern u32 mode2_t; +extern u32 mode_2t; extern u32 xsb_validate_type; extern u32 xsb_validation_base_address; extern u32 odt_additional; extern u32 debug_mode; -extern u32 delay_enable; -extern u32 ca_delay; extern u32 debug_dunit; extern u32 clamp_tbl[]; -extern u32 freq_mask[HWS_MAX_DEVICE_NUM][DDR_FREQ_LIMIT]; -extern u32 start_pattern, end_pattern; +extern u32 freq_mask[MAX_DEVICE_NUM][DDR_FREQ_LAST]; extern u32 maxt_poll_tries; extern u32 is_bist_reset_bit; -extern u8 debug_training_bist; extern u8 vref_window_size[MAX_INTERFACE_NUM][MAX_BUS_NUM]; -extern u32 debug_mode; extern u32 effective_cs; extern int ddr3_tip_centr_skip_min_win_check; extern u32 *dq_map_table; -extern enum auto_tune_stage training_stage; -extern u8 debug_centralization; -extern u32 delay_enable; -extern u32 start_pattern, end_pattern; -extern u32 freq_val[DDR_FREQ_LIMIT]; extern u8 debug_training_hw_alg; -extern enum auto_tune_stage training_stage; -extern u8 debug_training_ip; -extern enum hws_result training_result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM]; -extern enum auto_tune_stage training_stage; -extern u32 effective_cs; - -extern u8 debug_leveling; -extern enum hws_result training_result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM]; -extern enum auto_tune_stage training_stage; -extern u32 rl_version; -extern struct cl_val_per_freq cas_latency_table[]; extern u32 start_xsb_offset; -extern u32 debug_mode; extern u32 odt_config; -extern u32 effective_cs; -extern u32 phy_reg1_val; -extern u8 debug_pbs; -extern u32 effective_cs; extern u16 mask_results_dq_reg_map[]; -extern enum hws_ddr_freq medium_freq; -extern u32 freq_val[]; -extern enum hws_result training_result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM]; -extern enum auto_tune_stage training_stage; -extern u32 debug_mode; -extern u32 *dq_map_table; -extern u32 vref; -extern struct cl_val_per_freq cas_latency_table[]; extern u32 target_freq; -extern struct hws_tip_config_func_db config_func_info[HWS_MAX_DEVICE_NUM]; -extern u32 clamp_tbl[]; -extern u32 init_freq; -/* list of allowed frequency listed in order of enum hws_ddr_freq */ -extern u32 freq_val[]; -extern u8 debug_training_static; -extern u32 first_active_if; +extern u32 dfs_low_freq; +extern u32 mem_size[]; + +extern u32 nominal_avs; +extern u32 extension_avs; + /* Prototypes */ +int ddr3_init(void); int ddr3_tip_enable_init_sequence(u32 dev_num); -int ddr3_tip_init_a38x(u32 dev_num, u32 board_id); - -int ddr3_hws_hw_training(void); -int ddr3_silicon_pre_init(void); +int ddr3_hws_hw_training(enum hws_algo_type algo_mode); +int mv_ddr_early_init(void); +int mv_ddr_early_init2(void); int ddr3_silicon_post_init(void); int ddr3_post_run_alg(void); int ddr3_if_ecc_enabled(void); void ddr3_new_tip_ecc_scrub(void); -void ddr3_print_version(void); -void ddr3_new_tip_dlb_config(void); -struct hws_topology_map *ddr3_get_topology_map(void); +void mv_ddr_ver_print(void); +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void); int ddr3_if_ecc_enabled(void); int ddr3_tip_reg_write(u32 dev_num, u32 reg_addr, u32 data); int ddr3_tip_reg_read(u32 dev_num, u32 reg_addr, u32 *data, u32 reg_mask); int ddr3_silicon_get_ddr_target_freq(u32 *ddr_freq); -int ddr3_tip_a38x_get_freq_config(u8 dev_num, enum hws_ddr_freq freq, - struct hws_tip_freq_config_info - *freq_config_info); -int ddr3_a38x_update_topology_map(u32 dev_num, - struct hws_topology_map *topology_map); -int ddr3_tip_a38x_get_init_freq(int dev_num, enum hws_ddr_freq *freq); -int ddr3_tip_a38x_get_medium_freq(int dev_num, enum hws_ddr_freq *freq); -int ddr3_tip_a38x_if_read(u8 dev_num, enum hws_access_type interface_access, - u32 if_id, u32 reg_addr, u32 *data, u32 mask); -int ddr3_tip_a38x_if_write(u8 dev_num, enum hws_access_type interface_access, - u32 if_id, u32 reg_addr, u32 data, u32 mask); -int ddr3_tip_a38x_get_device_info(u8 dev_num, - struct ddr3_device_info *info_ptr); - -int ddr3_tip_init_a38x(u32 dev_num, u32 board_id); int print_adll(u32 dev_num, u32 adll[MAX_INTERFACE_NUM * MAX_BUS_NUM]); +int print_ph(u32 dev_num, u32 adll[MAX_INTERFACE_NUM * MAX_BUS_NUM]); +int read_phase_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + int reg_addr, u32 mask); +int write_leveling_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + u32 pup_ph_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], int reg_addr); int ddr3_tip_restore_dunit_regs(u32 dev_num); -void print_topology(struct hws_topology_map *topology_db); +void print_topology(struct mv_ddr_topology_map *tm); u32 mv_board_id_get(void); int ddr3_load_topology_map(void); -int ddr3_tip_init_specific_reg_config(u32 dev_num, - struct reg_data *reg_config_arr); -u32 ddr3_tip_get_init_freq(void); void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level); +void mv_ddr_user_log_level_set(enum ddr_lib_debug_block block); int ddr3_tip_tune_training_params(u32 dev_num, struct tune_train_params *params); void get_target_freq(u32 freq_mode, u32 *ddr_freq, u32 *hclk_ps); -int ddr3_fast_path_dynamic_cs_size_config(u32 cs_ena); void ddr3_fast_path_static_cs_size_config(u32 cs_ena); -u32 ddr3_get_device_width(u32 cs); u32 mv_board_id_index_get(u32 board_id); -u32 mv_board_id_get(void); -u32 ddr3_get_bus_width(void); void ddr3_set_log_level(u32 n_log_level); -int ddr3_calc_mem_cs_size(u32 cs, u32 *cs_size); +int calc_cs_num(u32 dev_num, u32 if_id, u32 *cs_num); int hws_ddr3_cs_base_adr_calc(u32 if_id, u32 cs, u32 *cs_base_addr); int ddr3_tip_print_pbs_result(u32 dev_num, u32 cs_num, enum pbs_dir pbs_mode); int ddr3_tip_clean_pbs_result(u32 dev_num, enum pbs_dir pbs_mode); -int ddr3_tip_static_round_trip_arr_build(u32 dev_num, - struct trip_delay_element *table_ptr, - int is_wl, u32 *round_trip_delay_arr); - -u32 hws_ddr3_tip_max_cs_get(void); - -/* - * Accessor functions for the registers - */ -static inline void reg_write(u32 addr, u32 val) -{ - writel(val, INTER_REGS_BASE + addr); -} - -static inline u32 reg_read(u32 addr) -{ - return readl(INTER_REGS_BASE + addr); -} - -static inline void reg_bit_set(u32 addr, u32 mask) -{ - setbits_le32(INTER_REGS_BASE + addr, mask); -} - -static inline void reg_bit_clr(u32 addr, u32 mask) -{ - clrbits_le32(INTER_REGS_BASE + addr, mask); -} - +u32 mv_ddr_init_freq_get(void); +void mv_ddr_mc_config(void); +int mv_ddr_mc_init(void); +void mv_ddr_set_calib_controller(void); #endif /* _DDR3_INIT_H */ diff --git a/drivers/ddr/marvell/a38x/ddr3_logging_def.h b/drivers/ddr/marvell/a38x/ddr3_logging_def.h index 2de7c4fa312b..7c90ba5ea38b 100644 --- a/drivers/ddr/marvell/a38x/ddr3_logging_def.h +++ b/drivers/ddr/marvell/a38x/ddr3_logging_def.h @@ -74,10 +74,14 @@ #endif #endif + /* Logging defines */ -#define DEBUG_LEVEL_TRACE 1 -#define DEBUG_LEVEL_INFO 2 -#define DEBUG_LEVEL_ERROR 3 +enum mv_ddr_debug_level { + DEBUG_LEVEL_TRACE = 1, + DEBUG_LEVEL_INFO = 2, + DEBUG_LEVEL_ERROR = 3, + DEBUG_LEVEL_LAST +}; enum ddr_lib_debug_block { DEBUG_BLOCK_STATIC, diff --git a/drivers/ddr/marvell/a38x/ddr3_patterns_64bit.h b/drivers/ddr/marvell/a38x/ddr3_patterns_64bit.h index 0ce0479a3ab6..257470113559 100644 --- a/drivers/ddr/marvell/a38x/ddr3_patterns_64bit.h +++ b/drivers/ddr/marvell/a38x/ddr3_patterns_64bit.h @@ -7,6 +7,7 @@ #ifndef __DDR3_PATTERNS_64_H #define __DDR3_PATTERNS_64_H +#define FAB_OPT 21 /* * Patterns Declerations */ diff --git a/drivers/ddr/marvell/a38x/ddr3_topology_def.h b/drivers/ddr/marvell/a38x/ddr3_topology_def.h index a17eca041878..87f6c88ade16 100644 --- a/drivers/ddr/marvell/a38x/ddr3_topology_def.h +++ b/drivers/ddr/marvell/a38x/ddr3_topology_def.h @@ -7,8 +7,9 @@ #ifndef _DDR3_TOPOLOGY_DEF_H #define _DDR3_TOPOLOGY_DEF_H -/* TOPOLOGY */ +#define DEV_NUM_0 0 +/* TOPOLOGY */ enum hws_speed_bin { SPEED_BIN_DDR_800D, SPEED_BIN_DDR_800E, @@ -54,7 +55,8 @@ enum hws_ddr_freq { DDR_FREQ_900, DDR_FREQ_360, DDR_FREQ_1000, - DDR_FREQ_LIMIT + DDR_FREQ_LAST, + DDR_FREQ_SAR }; enum speed_bin_table_elements { diff --git a/drivers/ddr/marvell/a38x/ddr3_training.c b/drivers/ddr/marvell/a38x/ddr3_training.c index f9e11591d992..0b414aba1fda 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training.c +++ b/drivers/ddr/marvell/a38x/ddr3_training.c @@ -4,48 +4,35 @@ * SPDX-License-Identifier: GPL-2.0 */ -#include -#include -#include -#include -#include - #include "ddr3_init.h" - -#define GET_MAX_VALUE(x, y) \ - ((x) > (y)) ? (x) : (y) -#define CEIL_DIVIDE(x, y) \ - ((x - (x / y) * y) == 0) ? ((x / y) - 1) : (x / y) - -#define TIME_2_CLOCK_CYCLES CEIL_DIVIDE +#include "mv_ddr_common.h" #define GET_CS_FROM_MASK(mask) (cs_mask2_num[mask]) #define CS_CBE_VALUE(cs_num) (cs_cbe_reg[cs_num]) -#define TIMES_9_TREFI_CYCLES 0x8 - u32 window_mem_addr = 0; u32 phy_reg0_val = 0; u32 phy_reg1_val = 8; u32 phy_reg2_val = 0; -u32 phy_reg3_val = 0xa; -enum hws_ddr_freq init_freq = DDR_FREQ_667; +u32 phy_reg3_val = PARAM_UNDEFINED; enum hws_ddr_freq low_freq = DDR_FREQ_LOW_FREQ; enum hws_ddr_freq medium_freq; u32 debug_dunit = 0; u32 odt_additional = 1; u32 *dq_map_table = NULL; + +/* in case of ddr4 do not run ddr3_tip_write_additional_odt_setting function - mc odt always 'on' + * in ddr4 case the terminations are rttWR and rttPARK and the odt must be always 'on' 0x1498 = 0xf + */ u32 odt_config = 1; -#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ALLEYCAT3) || \ - defined(CONFIG_ARMADA_39X) -u32 is_pll_before_init = 0, is_adll_calib_before_init = 0, is_dfs_in_init = 0; -u32 dfs_low_freq = 130; -#else +u32 nominal_avs; +u32 extension_avs; + u32 is_pll_before_init = 0, is_adll_calib_before_init = 1, is_dfs_in_init = 0; -u32 dfs_low_freq = 100; -#endif -u32 g_rtt_nom_c_s0, g_rtt_nom_c_s1; +u32 dfs_low_freq; + +u32 g_rtt_nom_cs0, g_rtt_nom_cs1; u8 calibration_update_control; /* 2 external only, 1 is internal only */ enum hws_result training_result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM]; @@ -56,7 +43,7 @@ u32 finger_test = 0, p_finger_start = 11, p_finger_end = 64, u32 clamp_tbl[] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; /* Initiate to 0xff, this variable is define by user in debug mode */ -u32 mode2_t = 0xff; +u32 mode_2t = 0xff; u32 xsb_validate_type = 0; u32 xsb_validation_base_address = 0xf000; u32 first_active_if = 0; @@ -71,25 +58,41 @@ int rl_mid_freq_wa = 0; u32 effective_cs = 0; +u32 vref_init_val = 0x4; +u32 ck_delay = PARAM_UNDEFINED; + +/* Design guidelines parameters */ +u32 g_zpri_data = PARAM_UNDEFINED; /* controller data - P drive strength */ +u32 g_znri_data = PARAM_UNDEFINED; /* controller data - N drive strength */ +u32 g_zpri_ctrl = PARAM_UNDEFINED; /* controller C/A - P drive strength */ +u32 g_znri_ctrl = PARAM_UNDEFINED; /* controller C/A - N drive strength */ + +u32 g_zpodt_data = PARAM_UNDEFINED; /* controller data - P ODT */ +u32 g_znodt_data = PARAM_UNDEFINED; /* controller data - N ODT */ +u32 g_zpodt_ctrl = PARAM_UNDEFINED; /* controller data - P ODT */ +u32 g_znodt_ctrl = PARAM_UNDEFINED; /* controller data - N ODT */ + +u32 g_odt_config = PARAM_UNDEFINED; +u32 g_rtt_nom = PARAM_UNDEFINED; +u32 g_rtt_wr = PARAM_UNDEFINED; +u32 g_dic = PARAM_UNDEFINED; +u32 g_rtt_park = PARAM_UNDEFINED; + u32 mask_tune_func = (SET_MEDIUM_FREQ_MASK_BIT | WRITE_LEVELING_MASK_BIT | LOAD_PATTERN_2_MASK_BIT | READ_LEVELING_MASK_BIT | - SET_TARGET_FREQ_MASK_BIT | WRITE_LEVELING_TF_MASK_BIT | + SET_TARGET_FREQ_MASK_BIT | + WRITE_LEVELING_TF_MASK_BIT | READ_LEVELING_TF_MASK_BIT | - CENTRALIZATION_RX_MASK_BIT | CENTRALIZATION_TX_MASK_BIT); - -void ddr3_print_version(void) -{ - printf(DDR3_TIP_VERSION_STRING); -} + CENTRALIZATION_RX_MASK_BIT | + CENTRALIZATION_TX_MASK_BIT); static int ddr3_tip_ddr3_training_main_flow(u32 dev_num); static int ddr3_tip_write_odt(u32 dev_num, enum hws_access_type access_type, u32 if_id, u32 cl_value, u32 cwl_value); static int ddr3_tip_ddr3_auto_tune(u32 dev_num); -static int is_bus_access_done(u32 dev_num, u32 if_id, - u32 dunit_reg_adrr, u32 bit); + #ifdef ODT_TEST_SUPPORT static int odt_test(u32 dev_num, enum hws_algo_type algo_type); #endif @@ -99,7 +102,7 @@ int adll_calibration(u32 dev_num, enum hws_access_type access_type, static int ddr3_tip_set_timing(u32 dev_num, enum hws_access_type access_type, u32 if_id, enum hws_ddr_freq frequency); -static struct page_element page_param[] = { +static struct page_element page_tbl[] = { /* * 8bits 16 bits * page-size(K) page-size(K) mask @@ -112,16 +115,30 @@ static struct page_element page_param[] = { /* 2G */ { 1, 2, 4}, /* 4G */ - { 2, 2, 5} + { 2, 2, 5}, /* 8G */ + {0, 0, 0}, /* TODO: placeholder for 16-Mbit die capacity */ + {0, 0, 0}, /* TODO: placeholder for 32-Mbit die capacity */ + {0, 0, 0}, /* TODO: placeholder for 12-Mbit die capacity */ + {0, 0, 0} /* TODO: placeholder for 24-Mbit die capacity */ + }; -static u8 mem_size_config[MEM_SIZE_LAST] = { +struct page_element *mv_ddr_page_tbl_get(void) +{ + return &page_tbl[0]; +} + +static u8 mem_size_config[MV_DDR_DIE_CAP_LAST] = { 0x2, /* 512Mbit */ 0x3, /* 1Gbit */ 0x0, /* 2Gbit */ 0x4, /* 4Gbit */ - 0x5 /* 8Gbit */ + 0x5, /* 8Gbit */ + 0x0, /* TODO: placeholder for 16-Mbit die capacity */ + 0x0, /* TODO: placeholder for 32-Mbit die capacity */ + 0x0, /* TODO: placeholder for 12-Mbit die capacity */ + 0x0 /* TODO: placeholder for 24-Mbit die capacity */ }; static u8 cs_mask2_num[] = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 }; @@ -180,10 +197,14 @@ static struct reg_data odpg_default_value[] = { {0x16fc, 0x0, MASK_ALL_BITS} }; -static int ddr3_tip_bus_access(u32 dev_num, enum hws_access_type interface_access, - u32 if_id, enum hws_access_type phy_access, - u32 phy_id, enum hws_ddr_phy phy_type, u32 reg_addr, - u32 data_value, enum hws_operation oper_type); +/* MR cmd and addr definitions */ +struct mv_ddr_mr_data mr_data[] = { + {MRS0_CMD, MR0_REG}, + {MRS1_CMD, MR1_REG}, + {MRS2_CMD, MR2_REG}, + {MRS3_CMD, MR3_REG} +}; + static int ddr3_tip_pad_inv(u32 dev_num, u32 if_id); static int ddr3_tip_rank_control(u32 dev_num, u32 if_id); @@ -193,12 +214,41 @@ static int ddr3_tip_rank_control(u32 dev_num, u32 if_id); int ddr3_tip_tune_training_params(u32 dev_num, struct tune_train_params *params) { - if (params->ck_delay != -1) + if (params->ck_delay != PARAM_UNDEFINED) ck_delay = params->ck_delay; - if (params->ck_delay_16 != -1) - ck_delay_16 = params->ck_delay_16; - if (params->phy_reg3_val != -1) + if (params->phy_reg3_val != PARAM_UNDEFINED) phy_reg3_val = params->phy_reg3_val; + if (params->g_rtt_nom != PARAM_UNDEFINED) + g_rtt_nom = params->g_rtt_nom; + if (params->g_rtt_wr != PARAM_UNDEFINED) + g_rtt_wr = params->g_rtt_wr; + if (params->g_dic != PARAM_UNDEFINED) + g_dic = params->g_dic; + if (params->g_odt_config != PARAM_UNDEFINED) + g_odt_config = params->g_odt_config; + if (params->g_zpri_data != PARAM_UNDEFINED) + g_zpri_data = params->g_zpri_data; + if (params->g_znri_data != PARAM_UNDEFINED) + g_znri_data = params->g_znri_data; + if (params->g_zpri_ctrl != PARAM_UNDEFINED) + g_zpri_ctrl = params->g_zpri_ctrl; + if (params->g_znri_ctrl != PARAM_UNDEFINED) + g_znri_ctrl = params->g_znri_ctrl; + if (params->g_zpodt_data != PARAM_UNDEFINED) + g_zpodt_data = params->g_zpodt_data; + if (params->g_znodt_data != PARAM_UNDEFINED) + g_znodt_data = params->g_znodt_data; + if (params->g_zpodt_ctrl != PARAM_UNDEFINED) + g_zpodt_ctrl = params->g_zpodt_ctrl; + if (params->g_znodt_ctrl != PARAM_UNDEFINED) + g_znodt_ctrl = params->g_znodt_ctrl; + if (params->g_rtt_park != PARAM_UNDEFINED) + g_rtt_park = params->g_rtt_park; + + DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, + ("DGL parameters: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n", + g_zpri_data, g_znri_data, g_zpri_ctrl, g_znri_ctrl, g_zpodt_data, g_znodt_data, + g_zpodt_ctrl, g_znodt_ctrl, g_rtt_nom, g_dic, g_odt_config, g_rtt_wr)); return MV_OK; } @@ -210,34 +260,34 @@ int ddr3_tip_configure_cs(u32 dev_num, u32 if_id, u32 cs_num, u32 enable) { u32 data, addr_hi, data_high; u32 mem_index; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (enable == 1) { data = (tm->interface_params[if_id].bus_width == - BUS_WIDTH_8) ? 0 : 1; + MV_DDR_DEV_WIDTH_8BIT) ? 0 : 1; CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - SDRAM_ACCESS_CONTROL_REG, (data << (cs_num * 4)), + SDRAM_ADDR_CTRL_REG, (data << (cs_num * 4)), 0x3 << (cs_num * 4))); mem_index = tm->interface_params[if_id].memory_size; addr_hi = mem_size_config[mem_index] & 0x3; CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - SDRAM_ACCESS_CONTROL_REG, + SDRAM_ADDR_CTRL_REG, (addr_hi << (2 + cs_num * 4)), 0x3 << (2 + cs_num * 4))); data_high = (mem_size_config[mem_index] & 0x4) >> 2; CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - SDRAM_ACCESS_CONTROL_REG, + SDRAM_ADDR_CTRL_REG, data_high << (20 + cs_num), 1 << (20 + cs_num))); /* Enable Address Select Mode */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - SDRAM_ACCESS_CONTROL_REG, 1 << (16 + cs_num), + SDRAM_ADDR_CTRL_REG, 1 << (16 + cs_num), 1 << (16 + cs_num))); } switch (cs_num) { @@ -246,13 +296,13 @@ int ddr3_tip_configure_cs(u32 dev_num, u32 if_id, u32 cs_num, u32 enable) case 2: CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - DDR_CONTROL_LOW_REG, (enable << (cs_num + 11)), + DUNIT_CTRL_LOW_REG, (enable << (cs_num + 11)), 1 << (cs_num + 11))); break; case 3: CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - DDR_CONTROL_LOW_REG, (enable << 15), 1 << 15)); + DUNIT_CTRL_LOW_REG, (enable << 15), 1 << 15)); break; } @@ -262,17 +312,18 @@ int ddr3_tip_configure_cs(u32 dev_num, u32 if_id, u32 cs_num, u32 enable) /* * Calculate number of CS */ -static int calc_cs_num(u32 dev_num, u32 if_id, u32 *cs_num) +int calc_cs_num(u32 dev_num, u32 if_id, u32 *cs_num) { u32 cs; u32 bus_cnt; u32 cs_count; u32 cs_bitmask; u32 curr_cs_num = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - for (bus_cnt = 0; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES(); bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); cs_count = 0; cs_bitmask = tm->interface_params[if_id]. as_bus_params[bus_cnt].cs_bitmask; @@ -303,21 +354,18 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ { u32 if_id; u32 cs_num; - u32 t_refi = 0, t_hclk = 0, t_ckclk = 0, t_faw = 0, t_pd = 0, - t_wr = 0, t2t = 0, txpdll = 0; - u32 data_value = 0, bus_width = 0, page_size = 0, cs_cnt = 0, + u32 t_ckclk = 0, t_wr = 0, t2t = 0; + u32 data_value = 0, cs_cnt = 0, mem_mask = 0, bus_index = 0; enum hws_speed_bin speed_bin_index = SPEED_BIN_DDR_2133N; - enum hws_mem_size memory_size = MEM_2G; - enum hws_ddr_freq freq = init_freq; - enum hws_timing timing; u32 cs_mask = 0; u32 cl_value = 0, cwl_val = 0; - u32 refresh_interval_cnt = 0, bus_cnt = 0, adll_tap = 0; + u32 bus_cnt = 0, adll_tap = 0; enum hws_access_type access_type = ACCESS_TYPE_UNICAST; u32 data_read[MAX_INTERFACE_NUM]; - struct hws_topology_map *tm = ddr3_get_topology_map(); - u32 odt_config = g_odt_config_2cs; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + enum hws_ddr_freq freq = tm->interface_params[0].memory_freq; DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, ("Init_controller, do_mrs_phy=%d, is_ctrl64_bit=%d\n", @@ -330,14 +378,14 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ if (generic_init_controller == 1) { for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, ("active IF %d\n", if_id)); mem_mask = 0; for (bus_index = 0; - bus_index < GET_TOPOLOGY_NUM_OF_BUSES(); + bus_index < octets_per_if_num; bus_index++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_index); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_index); mem_mask |= tm->interface_params[if_id]. as_bus_params[bus_index].mirror_enable_bitmask; @@ -346,57 +394,46 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ if (mem_mask != 0) { CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, - if_id, CS_ENABLE_REG, 0, + if_id, DUAL_DUNIT_CFG_REG, 0, 0x8)); } - memory_size = - tm->interface_params[if_id]. - memory_size; speed_bin_index = tm->interface_params[if_id]. speed_bin_index; - freq = init_freq; - t_refi = - (tm->interface_params[if_id]. - interface_temp == - HWS_TEMP_HIGH) ? TREFI_HIGH : TREFI_LOW; - t_refi *= 1000; /* psec */ - DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, - ("memy_size %d speed_bin_ind %d freq %d t_refi %d\n", - memory_size, speed_bin_index, freq, - t_refi)); - /* HCLK & CK CLK in 2:1[ps] */ + /* t_ckclk is external clock */ t_ckclk = (MEGA / freq_val[freq]); - /* t_hclk is internal clock */ - t_hclk = 2 * t_ckclk; - refresh_interval_cnt = t_refi / t_hclk; /* no units */ - bus_width = - (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) - == 1) ? (16) : (32); - - if (init_cntr_prm->is_ctrl64_bit) - bus_width = 64; - data_value = - (refresh_interval_cnt | 0x4000 | - ((bus_width == - 32) ? 0x8000 : 0) | 0x1000000) & ~(1 << 26); + if (MV_DDR_IS_HALF_BUS_DRAM_MODE(tm->bus_act_mask, octets_per_if_num)) + data_value = (0x4000 | 0 | 0x1000000) & ~(1 << 26); + else + data_value = (0x4000 | 0x8000 | 0x1000000) & ~(1 << 26); /* Interface Bus Width */ /* SRMode */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - SDRAM_CONFIGURATION_REG, data_value, - 0x100ffff)); + SDRAM_CFG_REG, data_value, + 0x100c000)); /* Interleave first command pre-charge enable (TBD) */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - SDRAM_OPEN_PAGE_CONTROL_REG, (1 << 10), + SDRAM_OPEN_PAGES_CTRL_REG, (1 << 10), (1 << 10))); + /* Reset divider_b assert -> de-assert */ + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, + SDRAM_CFG_REG, + 0x0 << PUP_RST_DIVIDER_OFFS, + PUP_RST_DIVIDER_MASK << PUP_RST_DIVIDER_OFFS)); + + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, + SDRAM_CFG_REG, + 0x1 << PUP_RST_DIVIDER_OFFS, + PUP_RST_DIVIDER_MASK << PUP_RST_DIVIDER_OFFS)); + /* PHY configuration */ /* * Postamble Length = 1.5cc, Addresscntl to clk skew @@ -404,12 +441,12 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - DRAM_PHY_CONFIGURATION, 0x28, 0x3e)); + DRAM_PHY_CFG_REG, 0x28, 0x3e)); if (init_cntr_prm->is_ctrl64_bit) { /* positive edge */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - DRAM_PHY_CONFIGURATION, 0x0, + DRAM_PHY_CFG_REG, 0x0, 0xff80)); } @@ -417,17 +454,24 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ /* Xbar Read buffer select (for Internal access) */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - CALIB_MACHINE_CTRL_REG, 0x1200c, + MAIN_PADS_CAL_MACH_CTRL_REG, 0x1200c, 0x7dffe01c)); CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - CALIB_MACHINE_CTRL_REG, + MAIN_PADS_CAL_MACH_CTRL_REG, calibration_update_control << 3, 0x3 << 3)); /* Pad calibration control - enable */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - CALIB_MACHINE_CTRL_REG, 0x1, 0x1)); + MAIN_PADS_CAL_MACH_CTRL_REG, 0x1, 0x1)); + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) < MV_TIP_REV_3) { + /* DDR3 rank ctrl \96 part of the generic code */ + /* CS1 mirroring enable + w/a for JIRA DUNIT-14581 */ + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + DDR3_RANK_CTRL_REG, 0x27, MASK_ALL_BITS)); + } cs_mask = 0; data_value = 0x7; @@ -438,40 +482,19 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ * 2) Bus_width * 3) CS# * 4) Page Number - * 5) t_faw * Per Dunit get from the Map_topology the parameters: * Bus_width - * t_faw is per Dunit not per CS */ - page_size = - (tm->interface_params[if_id]. - bus_width == - BUS_WIDTH_8) ? page_param[memory_size]. - page_size_8bit : page_param[memory_size]. - page_size_16bit; - - t_faw = - (page_size == 1) ? speed_bin_table(speed_bin_index, - SPEED_BIN_TFAW1K) - : speed_bin_table(speed_bin_index, - SPEED_BIN_TFAW2K); - - data_value = TIME_2_CLOCK_CYCLES(t_faw, t_ckclk); - data_value = data_value << 24; - CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, - SDRAM_ACCESS_CONTROL_REG, data_value, - 0x7f000000)); data_value = (tm->interface_params[if_id]. - bus_width == BUS_WIDTH_8) ? 0 : 1; + bus_width == MV_DDR_DEV_WIDTH_8BIT) ? 0 : 1; /* create merge cs mask for all cs available in dunit */ for (bus_cnt = 0; - bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES(); + bus_cnt < octets_per_if_num; bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); cs_mask |= tm->interface_params[if_id]. as_bus_params[bus_cnt].cs_bitmask; @@ -510,9 +533,11 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, ("cl_value 0x%x cwl_val 0x%x\n", cl_value, cwl_val)); - t_wr = TIME_2_CLOCK_CYCLES(speed_bin_table(speed_bin_index, - SPEED_BIN_TWR), - t_ckclk); + + t_wr = time_to_nclk(speed_bin_table + (speed_bin_index, + SPEED_BIN_TWR), t_ckclk); + data_value = ((cl_mask_table[cl_value] & 0x1) << 2) | ((cl_mask_table[cl_value] & 0xe) << 3); @@ -522,9 +547,8 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ (0x7 << 4) | (1 << 2))); CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - MR0_REG, twr_mask_table[t_wr + 1] << 9, - (0x7 << 9))); - + MR0_REG, twr_mask_table[t_wr] << 9, + 0x7 << 9)); /* * MR1: Set RTT and DIC Design GL values @@ -545,7 +569,8 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ data_value |= ((tm->interface_params[if_id]. interface_temp == - HWS_TEMP_HIGH) ? (1 << 7) : 0); + MV_DDR_TEMP_HIGH) ? (1 << 7) : 0); + data_value |= g_rtt_wr; CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, MR2_REG, data_value, @@ -557,53 +582,41 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ cl_value, cwl_val); ddr3_tip_set_timing(dev_num, access_type, if_id, freq); - CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, - DUNIT_CONTROL_HIGH_REG, 0x177, - 0x1000177)); - - if (init_cntr_prm->is_ctrl64_bit) { - /* disable 0.25 cc delay */ + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) < MV_TIP_REV_3) { + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + DUNIT_CTRL_HIGH_REG, 0x1000119, + 0x100017F)); + } else { CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - DUNIT_CONTROL_HIGH_REG, 0x0, - 0x800)); + DUNIT_CTRL_HIGH_REG, 0x600177 | + (init_cntr_prm->is_ctrl64_bit ? + CPU_INTERJECTION_ENA_SPLIT_ENA << CPU_INTERJECTION_ENA_OFFS : + CPU_INTERJECTION_ENA_SPLIT_DIS << CPU_INTERJECTION_ENA_OFFS), + 0x1600177 | CPU_INTERJECTION_ENA_MASK << + CPU_INTERJECTION_ENA_OFFS)); } /* reset bit 7 */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - DUNIT_CONTROL_HIGH_REG, + DUNIT_CTRL_HIGH_REG, (init_cntr_prm->msys_init << 7), (1 << 7))); - /* calculate number of CS (per interface) */ - CHECK_STATUS(calc_cs_num - (dev_num, if_id, &cs_num)); - timing = tm->interface_params[if_id].timing; - - if (mode2_t != 0xff) { - t2t = mode2_t; - } else if (timing != HWS_TIM_DEFAULT) { - /* Board topology map is forcing timing */ - t2t = (timing == HWS_TIM_2T) ? 1 : 0; + if (mode_2t != 0xff) { + t2t = mode_2t; } else { + /* calculate number of CS (per interface) */ + CHECK_STATUS(calc_cs_num + (dev_num, if_id, &cs_num)); t2t = (cs_num == 1) ? 0 : 1; } CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - DDR_CONTROL_LOW_REG, t2t << 3, + DUNIT_CTRL_LOW_REG, t2t << 3, 0x3 << 3)); - /* move the block to ddr3_tip_set_timing - start */ - t_pd = TIMES_9_TREFI_CYCLES; - txpdll = GET_MAX_VALUE(t_ckclk * 10, - speed_bin_table(speed_bin_index, - SPEED_BIN_TXPDLL)); - txpdll = CEIL_DIVIDE((txpdll - 1), t_ckclk); - CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, - DDR_TIMING_REG, txpdll << 4 | t_pd, - 0x1f << 4 | 0xf)); CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, DDR_TIMING_REG, 0x28 << 9, 0x3f << 9)); @@ -615,31 +628,38 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ /* AUTO_ZQC_TIMING */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - TIMING_REG, (AUTO_ZQC_TIMING | (2 << 20)), + ZQC_CFG_REG, (AUTO_ZQC_TIMING | (2 << 20)), 0x3fffff)); CHECK_STATUS(ddr3_tip_if_read (dev_num, access_type, if_id, - DRAM_PHY_CONFIGURATION, data_read, 0x30)); + DRAM_PHY_CFG_REG, data_read, 0x30)); data_value = (data_read[if_id] == 0) ? (1 << 11) : 0; CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - DUNIT_CONTROL_HIGH_REG, data_value, + DUNIT_CTRL_HIGH_REG, data_value, (1 << 11))); /* Set Active control for ODT write transactions */ - if (cs_num == 1) - odt_config = g_odt_config_1cs; CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, 0x1494, odt_config, + PARAM_NOT_CARE, 0x1494, g_odt_config, MASK_ALL_BITS)); + + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) == MV_TIP_REV_3) { + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + 0x14a8, 0x900, 0x900)); + /* wa: controls control sub-phy outputs floating during self-refresh */ + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + 0x16d0, 0, 0x8000)); + } } - } else { } for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); CHECK_STATUS(ddr3_tip_rank_control(dev_num, if_id)); if (init_cntr_prm->do_mrs_phy) { @@ -649,14 +669,13 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ /* Pad calibration control - disable */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - CALIB_MACHINE_CTRL_REG, 0x0, 0x1)); + MAIN_PADS_CAL_MACH_CTRL_REG, 0x0, 0x1)); CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - CALIB_MACHINE_CTRL_REG, + MAIN_PADS_CAL_MACH_CTRL_REG, calibration_update_control << 3, 0x3 << 3)); } - CHECK_STATUS(ddr3_tip_enable_init_sequence(dev_num)); if (delay_enable != 0) { adll_tap = MEGA / (freq_val[freq] * 64); @@ -667,67 +686,70 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ } /* - * Load Topology map + * Rank Control Flow */ -int hws_ddr3_tip_load_topology_map(u32 dev_num, struct hws_topology_map *tm) +static int ddr3_tip_rev2_rank_control(u32 dev_num, u32 if_id) { - enum hws_speed_bin speed_bin_index; - enum hws_ddr_freq freq = DDR_FREQ_LIMIT; - u32 if_id; + u32 data_value = 0, bus_cnt = 0; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - freq_val[DDR_FREQ_LOW_FREQ] = dfs_low_freq; - tm = ddr3_get_topology_map(); - CHECK_STATUS(ddr3_tip_get_first_active_if - ((u8)dev_num, tm->if_act_mask, - &first_active_if)); - DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, - ("board IF_Mask=0x%x num_of_bus_per_interface=0x%x\n", - tm->if_act_mask, - tm->num_of_bus_per_interface)); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); + data_value |= tm->interface_params[if_id].as_bus_params[bus_cnt]. + cs_bitmask; - /* - * if CL, CWL values are missing in topology map, then fill them - * according to speedbin tables - */ - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - speed_bin_index = - tm->interface_params[if_id].speed_bin_index; - /* TBD memory frequency of interface 0 only is used ! */ - freq = tm->interface_params[first_active_if].memory_freq; + if (tm->interface_params[if_id].as_bus_params[bus_cnt]. + mirror_enable_bitmask == 1) { + /* + * Check mirror_enable_bitmask + * If it is enabled, CS + 4 bit in a word to be '1' + */ + if ((tm->interface_params[if_id].as_bus_params[bus_cnt]. + cs_bitmask & 0x1) != 0) { + data_value |= tm->interface_params[if_id]. + as_bus_params[bus_cnt]. + mirror_enable_bitmask << 4; + } - DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, - ("speed_bin_index =%d freq=%d cl=%d cwl=%d\n", - speed_bin_index, freq_val[freq], - tm->interface_params[if_id]. - cas_l, - tm->interface_params[if_id]. - cas_wl)); + if ((tm->interface_params[if_id].as_bus_params[bus_cnt]. + cs_bitmask & 0x2) != 0) { + data_value |= tm->interface_params[if_id]. + as_bus_params[bus_cnt]. + mirror_enable_bitmask << 5; + } - if (tm->interface_params[if_id].cas_l == 0) { - tm->interface_params[if_id].cas_l = - cas_latency_table[speed_bin_index].cl_val[freq]; - } + if ((tm->interface_params[if_id].as_bus_params[bus_cnt]. + cs_bitmask & 0x4) != 0) { + data_value |= tm->interface_params[if_id]. + as_bus_params[bus_cnt]. + mirror_enable_bitmask << 6; + } - if (tm->interface_params[if_id].cas_wl == 0) { - tm->interface_params[if_id].cas_wl = - cas_write_latency_table[speed_bin_index].cl_val[freq]; + if ((tm->interface_params[if_id].as_bus_params[bus_cnt]. + cs_bitmask & 0x8) != 0) { + data_value |= tm->interface_params[if_id]. + as_bus_params[bus_cnt]. + mirror_enable_bitmask << 7; + } } } + CHECK_STATUS(ddr3_tip_if_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, DDR3_RANK_CTRL_REG, + data_value, 0xff)); + return MV_OK; } -/* - * RANK Control Flow - */ -static int ddr3_tip_rank_control(u32 dev_num, u32 if_id) +static int ddr3_tip_rev3_rank_control(u32 dev_num, u32 if_id) { u32 data_value = 0, bus_cnt; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - for (bus_cnt = 1; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES(); bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + for (bus_cnt = 1; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); if ((tm->interface_params[if_id]. as_bus_params[0].cs_bitmask != tm->interface_params[if_id]. @@ -747,29 +769,38 @@ static int ddr3_tip_rank_control(u32 dev_num, u32 if_id) as_bus_params[0].mirror_enable_bitmask << 4; CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, RANK_CTRL_REG, + (dev_num, ACCESS_TYPE_UNICAST, if_id, DDR3_RANK_CTRL_REG, data_value, 0xff)); return MV_OK; } +static int ddr3_tip_rank_control(u32 dev_num, u32 if_id) +{ + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) == MV_TIP_REV_2) + return ddr3_tip_rev2_rank_control(dev_num, if_id); + else + return ddr3_tip_rev3_rank_control(dev_num, if_id); +} + /* * PAD Inverse Flow */ static int ddr3_tip_pad_inv(u32 dev_num, u32 if_id) { u32 bus_cnt, data_value, ck_swap_pup_ctrl; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - for (bus_cnt = 0; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES(); bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); if (tm->interface_params[if_id]. as_bus_params[bus_cnt].is_dqs_swap == 1) { /* dqs swap */ ddr3_tip_bus_read_modify_write(dev_num, ACCESS_TYPE_UNICAST, if_id, bus_cnt, DDR_PHY_DATA, - PHY_CONTROL_PHY_REG, 0xc0, + PHY_CTRL_PHY_REG, 0xc0, 0xc0); } @@ -786,7 +817,7 @@ static int ddr3_tip_pad_inv(u32 dev_num, u32 if_id) ddr3_tip_bus_read_modify_write(dev_num, ACCESS_TYPE_UNICAST, if_id, ck_swap_pup_ctrl, DDR_PHY_CONTROL, - PHY_CONTROL_PHY_REG, + PHY_CTRL_PHY_REG, data_value, data_value); } } @@ -794,12 +825,147 @@ static int ddr3_tip_pad_inv(u32 dev_num, u32 if_id) return MV_OK; } +/* + * Algorithm Parameters Validation + */ +int ddr3_tip_validate_algo_var(u32 value, u32 fail_value, char *var_name) +{ + if (value == fail_value) { + DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, + ("Error: %s is not initialized (Algo Components Validation)\n", + var_name)); + return 0; + } + + return 1; +} + +int ddr3_tip_validate_algo_ptr(void *ptr, void *fail_value, char *ptr_name) +{ + if (ptr == fail_value) { + DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, + ("Error: %s is not initialized (Algo Components Validation)\n", + ptr_name)); + return 0; + } + + return 1; +} + +int ddr3_tip_validate_algo_components(u8 dev_num) +{ + int status = 1; + + /* Check DGL parameters*/ + status &= ddr3_tip_validate_algo_var(ck_delay, PARAM_UNDEFINED, "ck_delay"); + status &= ddr3_tip_validate_algo_var(phy_reg3_val, PARAM_UNDEFINED, "phy_reg3_val"); + status &= ddr3_tip_validate_algo_var(g_rtt_nom, PARAM_UNDEFINED, "g_rtt_nom"); + status &= ddr3_tip_validate_algo_var(g_dic, PARAM_UNDEFINED, "g_dic"); + status &= ddr3_tip_validate_algo_var(odt_config, PARAM_UNDEFINED, "odt_config"); + status &= ddr3_tip_validate_algo_var(g_zpri_data, PARAM_UNDEFINED, "g_zpri_data"); + status &= ddr3_tip_validate_algo_var(g_znri_data, PARAM_UNDEFINED, "g_znri_data"); + status &= ddr3_tip_validate_algo_var(g_zpri_ctrl, PARAM_UNDEFINED, "g_zpri_ctrl"); + status &= ddr3_tip_validate_algo_var(g_znri_ctrl, PARAM_UNDEFINED, "g_znri_ctrl"); + status &= ddr3_tip_validate_algo_var(g_zpodt_data, PARAM_UNDEFINED, "g_zpodt_data"); + status &= ddr3_tip_validate_algo_var(g_znodt_data, PARAM_UNDEFINED, "g_znodt_data"); + status &= ddr3_tip_validate_algo_var(g_zpodt_ctrl, PARAM_UNDEFINED, "g_zpodt_ctrl"); + status &= ddr3_tip_validate_algo_var(g_znodt_ctrl, PARAM_UNDEFINED, "g_znodt_ctrl"); + + /* Check functions pointers */ + status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].tip_dunit_mux_select_func, + NULL, "tip_dunit_mux_select_func"); + status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].mv_ddr_dunit_write, + NULL, "mv_ddr_dunit_write"); + status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].mv_ddr_dunit_read, + NULL, "mv_ddr_dunit_read"); + status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].mv_ddr_phy_write, + NULL, "mv_ddr_phy_write"); + status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].mv_ddr_phy_read, + NULL, "mv_ddr_phy_read"); + status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].tip_get_freq_config_info_func, + NULL, "tip_get_freq_config_info_func"); + status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].tip_set_freq_divider_func, + NULL, "tip_set_freq_divider_func"); + status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].tip_get_clock_ratio, + NULL, "tip_get_clock_ratio"); + + status &= ddr3_tip_validate_algo_ptr(dq_map_table, NULL, "dq_map_table"); + status &= ddr3_tip_validate_algo_var(dfs_low_freq, 0, "dfs_low_freq"); + + return (status == 1) ? MV_OK : MV_NOT_INITIALIZED; +} + + +int ddr3_pre_algo_config(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + /* Set Bus3 ECC training mode */ + if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) { + /* Set Bus3 ECC MUX */ + CHECK_STATUS(ddr3_tip_if_write + (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, + DRAM_PINS_MUX_REG, 0x100, 0x100)); + } + + /* Set regular ECC training mode (bus4 and bus 3) */ + if ((DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask)) || + (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) || + (DDR3_IS_ECC_PUP8_MODE(tm->bus_act_mask))) { + /* Enable ECC Write MUX */ + CHECK_STATUS(ddr3_tip_if_write + (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, + TRAINING_SW_2_REG, 0x100, 0x100)); + /* General ECC enable */ + CHECK_STATUS(ddr3_tip_if_write + (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, + SDRAM_CFG_REG, 0x40000, 0x40000)); + /* Disable Read Data ECC MUX */ + CHECK_STATUS(ddr3_tip_if_write + (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, + TRAINING_SW_2_REG, 0x0, 0x2)); + } + + return MV_OK; +} + +int ddr3_post_algo_config(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + int status; + + status = ddr3_post_run_alg(); + if (MV_OK != status) { + printf("DDR3 Post Run Alg - FAILED 0x%x\n", status); + return status; + } + + /* Un_set ECC training mode */ + if ((DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask)) || + (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) || + (DDR3_IS_ECC_PUP8_MODE(tm->bus_act_mask))) { + /* Disable ECC Write MUX */ + CHECK_STATUS(ddr3_tip_if_write + (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, + TRAINING_SW_2_REG, 0x0, 0x100)); + /* General ECC and Bus3 ECC MUX remains enabled */ + } + + return MV_OK; +} + /* * Run Training Flow */ int hws_ddr3_tip_run_alg(u32 dev_num, enum hws_algo_type algo_type) { - int ret = MV_OK, ret_tune = MV_OK; + int status = MV_OK; + + status = ddr3_pre_algo_config(); + if (MV_OK != status) { + printf("DDR3 Pre Algo Config - FAILED 0x%x\n", status); + return status; + } #ifdef ODT_TEST_SUPPORT if (finger_test == 1) @@ -807,16 +973,23 @@ int hws_ddr3_tip_run_alg(u32 dev_num, enum hws_algo_type algo_type) #endif if (algo_type == ALGO_TYPE_DYNAMIC) { - ret = ddr3_tip_ddr3_auto_tune(dev_num); - } else { + status = ddr3_tip_ddr3_auto_tune(dev_num); } - if (ret != MV_OK) { + if (status != MV_OK) { DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, - ("Run_alg: tuning failed %d\n", ret_tune)); + ("******** DRAM initialization Failed (res 0x%x) ********\n", + status)); + return status; } - return ret; + status = ddr3_post_algo_config(); + if (MV_OK != status) { + printf("DDR3 Post Algo Config - FAILED 0x%x\n", status); + return status; + } + + return status; } #ifdef ODT_TEST_SUPPORT @@ -836,19 +1009,16 @@ static int odt_test(u32 dev_num, enum hws_algo_type algo_type) DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("pfinger_val %d nfinger_val %d\n", pfinger_val, nfinger_val)); - p_finger = pfinger_val; - n_finger = nfinger_val; + /* + * TODO: need to check the correctness + * of the following two lines. + */ + g_zpodt_data = pfinger_val; + g_znodt_data = nfinger_val; } if (algo_type == ALGO_TYPE_DYNAMIC) { ret = ddr3_tip_ddr3_auto_tune(dev_num); - } else { - /* - * Frequency per interface is not relevant, - * only interface 0 - */ - ret = ddr3_tip_run_static_alg(dev_num, - init_freq); } } } @@ -868,12 +1038,8 @@ static int odt_test(u32 dev_num, enum hws_algo_type algo_type) */ int hws_ddr3_tip_select_ddr_controller(u32 dev_num, int enable) { - if (config_func_info[dev_num].tip_dunit_mux_select_func != NULL) { - return config_func_info[dev_num]. - tip_dunit_mux_select_func((u8)dev_num, enable); - } - - return MV_FAIL; + return config_func_info[dev_num]. + tip_dunit_mux_select_func((u8)dev_num, enable); } /* @@ -882,14 +1048,9 @@ int hws_ddr3_tip_select_ddr_controller(u32 dev_num, int enable) int ddr3_tip_if_write(u32 dev_num, enum hws_access_type interface_access, u32 if_id, u32 reg_addr, u32 data_value, u32 mask) { - if (config_func_info[dev_num].tip_dunit_write_func != NULL) { - return config_func_info[dev_num]. - tip_dunit_write_func((u8)dev_num, interface_access, - if_id, reg_addr, - data_value, mask); - } + config_func_info[dev_num].mv_ddr_dunit_write(reg_addr, mask, data_value); - return MV_FAIL; + return MV_OK; } /* @@ -898,14 +1059,9 @@ int ddr3_tip_if_write(u32 dev_num, enum hws_access_type interface_access, int ddr3_tip_if_read(u32 dev_num, enum hws_access_type interface_access, u32 if_id, u32 reg_addr, u32 *data, u32 mask) { - if (config_func_info[dev_num].tip_dunit_read_func != NULL) { - return config_func_info[dev_num]. - tip_dunit_read_func((u8)dev_num, interface_access, - if_id, reg_addr, - data, mask); - } + config_func_info[dev_num].mv_ddr_dunit_read(reg_addr, mask, data); - return MV_FAIL; + return MV_OK; } /* @@ -919,7 +1075,7 @@ int ddr3_tip_if_polling(u32 dev_num, enum hws_access_type access_type, u32 read_data[MAX_INTERFACE_NUM]; int ret; int is_fail = 0, is_if_fail; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (access_type == ACCESS_TYPE_MULTICAST) { start_if = 0; @@ -931,7 +1087,7 @@ int ddr3_tip_if_polling(u32 dev_num, enum hws_access_type access_type, for (interface_num = start_if; interface_num <= end_if; interface_num++) { /* polling bit 3 for n times */ - VALIDATE_ACTIVE(tm->if_act_mask, interface_num); + VALIDATE_IF_ACTIVE(tm->if_act_mask, interface_num); is_if_fail = 0; for (poll_cnt = 0; poll_cnt < poll_tries; poll_cnt++) { @@ -967,42 +1123,8 @@ int ddr3_tip_bus_read(u32 dev_num, u32 if_id, enum hws_access_type phy_access, u32 phy_id, enum hws_ddr_phy phy_type, u32 reg_addr, u32 *data) { - u32 bus_index = 0; - u32 data_read[MAX_INTERFACE_NUM]; - struct hws_topology_map *tm = ddr3_get_topology_map(); - - if (phy_access == ACCESS_TYPE_MULTICAST) { - for (bus_index = 0; bus_index < GET_TOPOLOGY_NUM_OF_BUSES(); - bus_index++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_index); - CHECK_STATUS(ddr3_tip_bus_access - (dev_num, ACCESS_TYPE_UNICAST, - if_id, ACCESS_TYPE_UNICAST, - bus_index, phy_type, reg_addr, 0, - OPERATION_READ)); - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, if_id, - PHY_REG_FILE_ACCESS, data_read, - MASK_ALL_BITS)); - data[bus_index] = (data_read[if_id] & 0xffff); - } - } else { - CHECK_STATUS(ddr3_tip_bus_access - (dev_num, ACCESS_TYPE_UNICAST, if_id, - phy_access, phy_id, phy_type, reg_addr, 0, - OPERATION_READ)); - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, if_id, - PHY_REG_FILE_ACCESS, data_read, MASK_ALL_BITS)); - - /* - * only 16 lsb bit are valid in Phy (each register is different, - * some can actually be less than 16 bits) - */ - *data = (data_read[if_id] & 0xffff); - } - - return MV_OK; + return config_func_info[dev_num]. + mv_ddr_phy_read(phy_access, phy_id, phy_type, reg_addr, data); } /* @@ -1013,88 +1135,10 @@ int ddr3_tip_bus_write(u32 dev_num, enum hws_access_type interface_access, u32 phy_id, enum hws_ddr_phy phy_type, u32 reg_addr, u32 data_value) { - CHECK_STATUS(ddr3_tip_bus_access - (dev_num, interface_access, if_id, phy_access, - phy_id, phy_type, reg_addr, data_value, OPERATION_WRITE)); - - return MV_OK; -} - -/* - * Bus access routine (relevant for both read & write) - */ -static int ddr3_tip_bus_access(u32 dev_num, enum hws_access_type interface_access, - u32 if_id, enum hws_access_type phy_access, - u32 phy_id, enum hws_ddr_phy phy_type, u32 reg_addr, - u32 data_value, enum hws_operation oper_type) -{ - u32 addr_low = 0x3f & reg_addr; - u32 addr_hi = ((0xc0 & reg_addr) >> 6); - u32 data_p1 = - (oper_type << 30) + (addr_hi << 28) + (phy_access << 27) + - (phy_type << 26) + (phy_id << 22) + (addr_low << 16) + - (data_value & 0xffff); - u32 data_p2 = data_p1 + (1 << 31); - u32 start_if, end_if; - struct hws_topology_map *tm = ddr3_get_topology_map(); - - CHECK_STATUS(ddr3_tip_if_write - (dev_num, interface_access, if_id, PHY_REG_FILE_ACCESS, - data_p1, MASK_ALL_BITS)); - CHECK_STATUS(ddr3_tip_if_write - (dev_num, interface_access, if_id, PHY_REG_FILE_ACCESS, - data_p2, MASK_ALL_BITS)); - - if (interface_access == ACCESS_TYPE_UNICAST) { - start_if = if_id; - end_if = if_id; - } else { - start_if = 0; - end_if = MAX_INTERFACE_NUM - 1; - } - - /* polling for read/write execution done */ - for (if_id = start_if; if_id <= end_if; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - CHECK_STATUS(is_bus_access_done - (dev_num, if_id, PHY_REG_FILE_ACCESS, 31)); - } - - return MV_OK; + return config_func_info[dev_num]. + mv_ddr_phy_write(phy_access, phy_id, phy_type, reg_addr, data_value, OPERATION_WRITE); } -/* - * Check bus access done - */ -static int is_bus_access_done(u32 dev_num, u32 if_id, u32 dunit_reg_adrr, - u32 bit) -{ - u32 rd_data = 1; - u32 cnt = 0; - u32 data_read[MAX_INTERFACE_NUM]; - - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, if_id, dunit_reg_adrr, - data_read, MASK_ALL_BITS)); - rd_data = data_read[if_id]; - rd_data &= (1 << bit); - - while (rd_data != 0) { - if (cnt++ >= MAX_POLLING_ITERATIONS) - break; - - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, if_id, - dunit_reg_adrr, data_read, MASK_ALL_BITS)); - rd_data = data_read[if_id]; - rd_data &= (1 << bit); - } - - if (cnt < MAX_POLLING_ITERATIONS) - return MV_OK; - else - return MV_FAIL; -} /* * Phy read-modify-write @@ -1105,7 +1149,7 @@ int ddr3_tip_bus_read_modify_write(u32 dev_num, enum hws_access_type access_type u32 data_value, u32 reg_mask) { u32 data_val = 0, if_id, start_if, end_if; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (access_type == ACCESS_TYPE_MULTICAST) { start_if = 0; @@ -1116,7 +1160,7 @@ int ddr3_tip_bus_read_modify_write(u32 dev_num, enum hws_access_type access_type } for (if_id = start_if; if_id <= end_if; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, phy_id, phy_type, reg_addr, &data_val)); @@ -1138,46 +1182,52 @@ int adll_calibration(u32 dev_num, enum hws_access_type access_type, { struct hws_tip_freq_config_info freq_config_info; u32 bus_cnt = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* Reset Diver_b assert -> de-assert */ CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, SDRAM_CONFIGURATION_REG, + (dev_num, access_type, if_id, SDRAM_CFG_REG, 0, 0x10000000)); mdelay(10); CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, SDRAM_CONFIGURATION_REG, + (dev_num, access_type, if_id, SDRAM_CFG_REG, 0x10000000, 0x10000000)); - if (config_func_info[dev_num].tip_get_freq_config_info_func != NULL) { - CHECK_STATUS(config_func_info[dev_num]. - tip_get_freq_config_info_func((u8)dev_num, frequency, - &freq_config_info)); - } else { - DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, - ("tip_get_freq_config_info_func is NULL")); - return MV_NOT_INITIALIZED; - } + CHECK_STATUS(config_func_info[dev_num]. + tip_get_freq_config_info_func((u8)dev_num, frequency, + &freq_config_info)); - for (bus_cnt = 0; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES(); bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); CHECK_STATUS(ddr3_tip_bus_read_modify_write (dev_num, access_type, if_id, bus_cnt, - DDR_PHY_DATA, BW_PHY_REG, + DDR_PHY_DATA, ADLL_CFG0_PHY_REG, freq_config_info.bw_per_freq << 8, 0x700)); CHECK_STATUS(ddr3_tip_bus_read_modify_write (dev_num, access_type, if_id, bus_cnt, - DDR_PHY_DATA, RATE_PHY_REG, + DDR_PHY_DATA, ADLL_CFG2_PHY_REG, + freq_config_info.rate_per_freq, 0x7)); + } + + for (bus_cnt = 0; bus_cnt < DDR_IF_CTRL_SUBPHYS_NUM; bus_cnt++) { + CHECK_STATUS(ddr3_tip_bus_read_modify_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, bus_cnt, + DDR_PHY_CONTROL, ADLL_CFG0_PHY_REG, + freq_config_info.bw_per_freq << 8, 0x700)); + CHECK_STATUS(ddr3_tip_bus_read_modify_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, bus_cnt, + DDR_PHY_CONTROL, ADLL_CFG2_PHY_REG, freq_config_info.rate_per_freq, 0x7)); } /* DUnit to Phy drive post edge, ADLL reset assert de-assert */ CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, DRAM_PHY_CONFIGURATION, + (dev_num, access_type, if_id, DRAM_PHY_CFG_REG, 0, (0x80000000 | 0x40000000))); mdelay(100 / (freq_val[frequency] / freq_val[DDR_FREQ_LOW_FREQ])); CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, DRAM_PHY_CONFIGURATION, + (dev_num, access_type, if_id, DRAM_PHY_CFG_REG, (0x80000000 | 0x40000000), (0x80000000 | 0x40000000))); /* polling for ADLL Done */ @@ -1190,11 +1240,11 @@ int adll_calibration(u32 dev_num, enum hws_access_type access_type, /* pup data_pup reset assert-> deassert */ CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, SDRAM_CONFIGURATION_REG, + (dev_num, access_type, if_id, SDRAM_CFG_REG, 0, 0x60000000)); mdelay(10); CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, SDRAM_CONFIGURATION_REG, + (dev_num, access_type, if_id, SDRAM_CFG_REG, 0x60000000, 0x60000000)); return MV_OK; @@ -1204,18 +1254,21 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, u32 if_id, enum hws_ddr_freq frequency) { u32 cl_value = 0, cwl_value = 0, mem_mask = 0, val = 0, - bus_cnt = 0, t_hclk = 0, t_wr = 0, - refresh_interval_cnt = 0, cnt_id; - u32 t_ckclk; - u32 t_refi = 0, end_if, start_if; + bus_cnt = 0, t_wr = 0, t_ckclk = 0, + cnt_id; + u32 end_if, start_if; u32 bus_index = 0; int is_dll_off = 0; enum hws_speed_bin speed_bin_index = 0; struct hws_tip_freq_config_info freq_config_info; enum hws_result *flow_result = training_result[training_stage]; u32 adll_tap = 0; + u32 cs_num; + u32 t2t; u32 cs_mask[MAX_INTERFACE_NUM]; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + unsigned int tclk; DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, ("dev %d access %d IF %d freq %d\n", dev_num, @@ -1235,7 +1288,7 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, /* speed bin can be different for each interface */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { /* cs enable is active low */ - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); cs_mask[if_id] = CS_BIT_MASK; training_result[training_stage][if_id] = TEST_SUCCESS; ddr3_tip_calc_cs_mask(dev_num, if_id, effective_cs, @@ -1248,8 +1301,7 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, * and loop the unicast access functions */ for (if_id = start_if; if_id <= end_if; if_id++) { - if (IS_ACTIVE(tm->if_act_mask, if_id) == 0) - continue; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); flow_result[if_id] = TEST_SUCCESS; speed_bin_index = @@ -1260,6 +1312,18 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, tm->interface_params[if_id].cas_l; cwl_value = tm->interface_params[if_id].cas_wl; + } else if (tm->cfg_src == MV_DDR_CFG_SPD) { + tclk = 1000000 / freq_val[frequency]; + cl_value = mv_ddr_cl_calc(tm->timing_data[MV_DDR_TAA_MIN], tclk); + if (cl_value == 0) { + printf("mv_ddr: unsupported cas latency value found\n"); + return MV_FAIL; + } + cwl_value = mv_ddr_cwl_calc(tclk); + if (cwl_value == 0) { + printf("mv_ddr: unsupported cas write latency value found\n"); + return MV_FAIL; + } } else { cl_value = cas_latency_table[speed_bin_index].cl_val[frequency]; @@ -1273,7 +1337,7 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, dev_num, access_type, if_id, frequency, speed_bin_index)); - for (cnt_id = 0; cnt_id < DDR_FREQ_LIMIT; cnt_id++) { + for (cnt_id = 0; cnt_id < DDR_FREQ_LAST; cnt_id++) { DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, ("%d ", cas_latency_table[speed_bin_index]. @@ -1282,19 +1346,19 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, ("\n")); mem_mask = 0; - for (bus_index = 0; bus_index < GET_TOPOLOGY_NUM_OF_BUSES(); + for (bus_index = 0; bus_index < octets_per_if_num; bus_index++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_index); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_index); mem_mask |= tm->interface_params[if_id]. as_bus_params[bus_index].mirror_enable_bitmask; } if (mem_mask != 0) { - /* motib redundant in KW28 */ + /* motib redundent in KW28 */ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - CS_ENABLE_REG, 0, 0x8)); + DUAL_DUNIT_CFG_REG, 0, 0x8)); } /* dll state after exiting SR */ @@ -1344,27 +1408,37 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, ("Freq_set: DDR3 poll failed on SR entry\n")); } - /* PLL configuration */ - if (config_func_info[dev_num].tip_set_freq_divider_func != NULL) { - config_func_info[dev_num]. - tip_set_freq_divider_func(dev_num, if_id, - frequency); + /* Calculate 2T mode */ + if (mode_2t != 0xff) { + t2t = mode_2t; + } else { + /* Calculate number of CS per interface */ + CHECK_STATUS(calc_cs_num(dev_num, if_id, &cs_num)); + t2t = (cs_num == 1) ? 0 : 1; } - /* PLL configuration End */ - /* adjust t_refi to new frequency */ - t_refi = (tm->interface_params[if_id].interface_temp == - HWS_TEMP_HIGH) ? TREFI_HIGH : TREFI_LOW; - t_refi *= 1000; /*psec */ + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_INTERLEAVE_WA) == 1) { + /* Use 1T mode if 1:1 ratio configured */ + if (config_func_info[dev_num].tip_get_clock_ratio(frequency) == 1) { + /* Low freq*/ + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + SDRAM_OPEN_PAGES_CTRL_REG, 0x0, 0x3C0)); + t2t = 0; + } else { + /* Middle or target freq */ + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + SDRAM_OPEN_PAGES_CTRL_REG, 0x3C0, 0x3C0)); + } + } + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, + DUNIT_CTRL_LOW_REG, t2t << 3, 0x3 << 3)); - /* HCLK in[ps] */ - t_hclk = MEGA / (freq_val[frequency] / 2); - refresh_interval_cnt = t_refi / t_hclk; /* no units */ - val = 0x4000 | refresh_interval_cnt; - CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, - SDRAM_CONFIGURATION_REG, val, 0x7fff)); + /* PLL configuration */ + config_func_info[dev_num].tip_set_freq_divider_func(dev_num, if_id, + frequency); /* DFS - CL/CWL/WR parameters after exiting SR */ CHECK_STATUS(ddr3_tip_if_write @@ -1374,14 +1448,14 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, (dev_num, access_type, if_id, DFS_REG, (cwl_mask_table[cwl_value] << 12), 0x7000)); - t_ckclk = MEGA / freq_val[frequency]; - t_wr = TIME_2_CLOCK_CYCLES(speed_bin_table(speed_bin_index, - SPEED_BIN_TWR), - t_ckclk); + t_ckclk = (MEGA / freq_val[frequency]); + t_wr = time_to_nclk(speed_bin_table + (speed_bin_index, + SPEED_BIN_TWR), t_ckclk); CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, DFS_REG, - (twr_mask_table[t_wr + 1] << 16), 0x70000)); + (twr_mask_table[t_wr] << 16), 0x70000)); /* Restore original RTT values if returning from DLL OFF mode */ if (is_dll_off == 1) { @@ -1399,25 +1473,24 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, g_dic | g_rtt_nom, 0x266)); } - /* Reset Diver_b assert -> de-assert */ + /* Reset divider_b assert -> de-assert */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - SDRAM_CONFIGURATION_REG, 0, 0x10000000)); + SDRAM_CFG_REG, 0, 0x10000000)); mdelay(10); CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - SDRAM_CONFIGURATION_REG, 0x10000000, 0x10000000)); + SDRAM_CFG_REG, 0x10000000, 0x10000000)); + + /* ADLL configuration function of process and frequency */ + CHECK_STATUS(config_func_info[dev_num]. + tip_get_freq_config_info_func(dev_num, frequency, + &freq_config_info)); - /* Adll configuration function of process and Frequency */ - if (config_func_info[dev_num].tip_get_freq_config_info_func != NULL) { - CHECK_STATUS(config_func_info[dev_num]. - tip_get_freq_config_info_func(dev_num, frequency, - &freq_config_info)); - } /* TBD check milo5 using device ID ? */ - for (bus_cnt = 0; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES(); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); CHECK_STATUS(ddr3_tip_bus_read_modify_write (dev_num, ACCESS_TYPE_UNICAST, if_id, bus_cnt, DDR_PHY_DATA, @@ -1432,15 +1505,15 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, freq_config_info.rate_per_freq, 0x7)); } - /* DUnit to Phy drive post edge, ADLL reset assert de-assert */ + /* Dunit to PHY drive post edge, ADLL reset assert -> de-assert */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - DRAM_PHY_CONFIGURATION, 0, + DRAM_PHY_CFG_REG, 0, (0x80000000 | 0x40000000))); mdelay(100 / (freq_val[frequency] / freq_val[DDR_FREQ_LOW_FREQ])); CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - DRAM_PHY_CONFIGURATION, (0x80000000 | 0x40000000), + DRAM_PHY_CFG_REG, (0x80000000 | 0x40000000), (0x80000000 | 0x40000000))); /* polling for ADLL Done */ @@ -1455,16 +1528,16 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, /* pup data_pup reset assert-> deassert */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - SDRAM_CONFIGURATION_REG, 0, 0x60000000)); + SDRAM_CFG_REG, 0, 0x60000000)); mdelay(10); CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - SDRAM_CONFIGURATION_REG, 0x60000000, 0x60000000)); + SDRAM_CFG_REG, 0x60000000, 0x60000000)); /* Set proper timing params before existing Self-Refresh */ ddr3_tip_set_timing(dev_num, access_type, if_id, frequency); if (delay_enable != 0) { - adll_tap = MEGA / (freq_val[frequency] * 64); + adll_tap = (is_dll_off == 1) ? 1000 : (MEGA / (freq_val[frequency] * 64)); ddr3_tip_cmd_addr_init_delay(dev_num, adll_tap); } @@ -1482,10 +1555,10 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, /* Refresh Command */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - SDRAM_OPERATION_REG, 0x2, 0xf1f)); + SDRAM_OP_REG, 0x2, 0xf1f)); if (ddr3_tip_if_polling (dev_num, ACCESS_TYPE_UNICAST, if_id, 0, 0x1f, - SDRAM_OPERATION_REG, MAX_POLLING_ITERATIONS) != MV_OK) { + SDRAM_OP_REG, MAX_POLLING_ITERATIONS) != MV_OK) { DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("Freq_set: DDR3 poll failed(3)")); } @@ -1507,54 +1580,57 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, (dev_num, access_type, if_id, MR0_REG, val, (0x7 << 4) | (1 << 2))); /* MR2: CWL = 10 , Auto Self-Refresh - disable */ - val = (cwl_mask_table[cwl_value] << 3); + val = (cwl_mask_table[cwl_value] << 3) | g_rtt_wr; /* * nklein 24.10.13 - should not be here - leave value as set in * the init configuration val |= (1 << 9); * val |= ((tm->interface_params[if_id]. - * interface_temp == HWS_TEMP_HIGH) ? (1 << 7) : 0); + * interface_temp == MV_DDR_TEMP_HIGH) ? (1 << 7) : 0); */ /* nklein 24.10.13 - see above comment */ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, MR2_REG, - val, (0x7 << 3))); + val, (0x7 << 3) | (0x3 << 9))); /* ODT TIMING */ val = ((cl_value - cwl_value + 1) << 4) | ((cl_value - cwl_value + 6) << 8) | ((cl_value - 1) << 12) | ((cl_value + 6) << 16); CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, - if_id, ODT_TIMING_LOW, + if_id, DDR_ODT_TIMING_LOW_REG, val, 0xffff0)); val = 0x91 | ((cwl_value - 1) << 8) | ((cwl_value + 5) << 12); CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, - if_id, ODT_TIMING_HI_REG, + if_id, DDR_ODT_TIMING_HIGH_REG, val, 0xffff)); - /* ODT Active */ - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, - if_id, - DUNIT_ODT_CONTROL_REG, - 0xf, 0xf)); + /* in case of ddr4 need to set the receiver to odt always 'on' (odt_config = '0') + * in case of ddr3 configure the odt through the timing + */ + if (odt_config != 0) { + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, DUNIT_ODT_CTRL_REG, 0xf, 0xf)); + } + else { + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, DUNIT_ODT_CTRL_REG, + 0x30f, 0x30f)); + } /* re-write CL */ val = ((cl_mask_table[cl_value] & 0x1) << 2) | ((cl_mask_table[cl_value] & 0xe) << 3); - CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, - 0, MR0_REG, val, - (0x7 << 4) | (1 << 2))); + + CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask, MR_CMD0, + val, (0x7 << 4) | (0x1 << 2))); /* re-write CWL */ - val = (cwl_mask_table[cwl_value] << 3); - CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask, MRS2_CMD, - val, (0x7 << 3))); - CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, - 0, MR2_REG, val, (0x7 << 3))); + val = (cwl_mask_table[cwl_value] << 3) | g_rtt_wr; + CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask, MR_CMD2, + val, (0x7 << 3) | (0x3 << 9))); if (mem_mask != 0) { CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - CS_ENABLE_REG, + DUAL_DUNIT_CFG_REG, 1 << 3, 0x8)); } } @@ -1577,20 +1653,20 @@ static int ddr3_tip_write_odt(u32 dev_num, enum hws_access_type access_type, val |= (((cl_value - 1) >> 4) << 22) | (((cl_value + 6) >> 4) << 23); CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - ODT_TIMING_LOW, val, 0xffff0)); + DDR_ODT_TIMING_LOW_REG, val, 0xffff0)); val = 0x91 | ((cwl_value - 1) << 8) | ((cwl_value + 5) << 12); CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - ODT_TIMING_HI_REG, val, 0xffff)); + DDR_ODT_TIMING_HIGH_REG, val, 0xffff)); if (odt_additional == 1) { CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_ODT_CONTROL_HIGH_REG, + SDRAM_ODT_CTRL_HIGH_REG, 0xf, 0xf)); } /* ODT Active */ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - DUNIT_ODT_CONTROL_REG, 0xf, 0xf)); + DUNIT_ODT_CTRL_REG, 0xf, 0xf)); return MV_OK; } @@ -1603,88 +1679,146 @@ static int ddr3_tip_set_timing(u32 dev_num, enum hws_access_type access_type, { u32 t_ckclk = 0, t_ras = 0; u32 t_rcd = 0, t_rp = 0, t_wr = 0, t_wtr = 0, t_rrd = 0, t_rtp = 0, - t_rfc = 0, t_mod = 0; - u32 val = 0, page_size = 0; + t_rfc = 0, t_mod = 0, t_r2r = 0x3, t_r2r_high = 0, + t_r2w_w2r = 0x3, t_r2w_w2r_high = 0x1, t_w2w = 0x3; + u32 refresh_interval_cnt, t_hclk, t_refi, t_faw, t_pd, t_xpdll; + u32 val = 0, page_size = 0, mask = 0; enum hws_speed_bin speed_bin_index; - enum hws_mem_size memory_size = MEM_2G; - struct hws_topology_map *tm = ddr3_get_topology_map(); + enum mv_ddr_die_capacity memory_size = MV_DDR_DIE_CAP_2GBIT; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + struct page_element *page_param = mv_ddr_page_tbl_get(); speed_bin_index = tm->interface_params[if_id].speed_bin_index; memory_size = tm->interface_params[if_id].memory_size; page_size = (tm->interface_params[if_id].bus_width == - BUS_WIDTH_8) ? page_param[memory_size]. + MV_DDR_DEV_WIDTH_8BIT) ? page_param[memory_size]. page_size_8bit : page_param[memory_size].page_size_16bit; t_ckclk = (MEGA / freq_val[frequency]); + /* HCLK in[ps] */ + t_hclk = MEGA / (freq_val[frequency] / config_func_info[dev_num].tip_get_clock_ratio(frequency)); + + t_refi = (tm->interface_params[if_id].interface_temp == MV_DDR_TEMP_HIGH) ? TREFI_HIGH : TREFI_LOW; + t_refi *= 1000; /* psec */ + refresh_interval_cnt = t_refi / t_hclk; /* no units */ + + if (page_size == 1) { + t_faw = speed_bin_table(speed_bin_index, SPEED_BIN_TFAW1K); + t_faw = time_to_nclk(t_faw, t_ckclk); + t_faw = GET_MAX_VALUE(20, t_faw); + } else { /* page size =2, we do not support page size 0.5k */ + t_faw = speed_bin_table(speed_bin_index, SPEED_BIN_TFAW2K); + t_faw = time_to_nclk(t_faw, t_ckclk); + t_faw = GET_MAX_VALUE(28, t_faw); + } + + t_pd = GET_MAX_VALUE(t_ckclk * 3, speed_bin_table(speed_bin_index, SPEED_BIN_TPD)); + t_pd = time_to_nclk(t_pd, t_ckclk); + + t_xpdll = GET_MAX_VALUE(t_ckclk * 10, speed_bin_table(speed_bin_index, SPEED_BIN_TXPDLL)); + t_xpdll = time_to_nclk(t_xpdll, t_ckclk); + t_rrd = (page_size == 1) ? speed_bin_table(speed_bin_index, SPEED_BIN_TRRD1K) : speed_bin_table(speed_bin_index, SPEED_BIN_TRRD2K); t_rrd = GET_MAX_VALUE(t_ckclk * 4, t_rrd); t_rtp = GET_MAX_VALUE(t_ckclk * 4, speed_bin_table(speed_bin_index, SPEED_BIN_TRTP)); + t_mod = GET_MAX_VALUE(t_ckclk * 12, 15000); t_wtr = GET_MAX_VALUE(t_ckclk * 4, speed_bin_table(speed_bin_index, SPEED_BIN_TWTR)); - t_ras = TIME_2_CLOCK_CYCLES(speed_bin_table(speed_bin_index, + t_ras = time_to_nclk(speed_bin_table(speed_bin_index, SPEED_BIN_TRAS), t_ckclk); - t_rcd = TIME_2_CLOCK_CYCLES(speed_bin_table(speed_bin_index, + t_rcd = time_to_nclk(speed_bin_table(speed_bin_index, SPEED_BIN_TRCD), t_ckclk); - t_rp = TIME_2_CLOCK_CYCLES(speed_bin_table(speed_bin_index, + t_rp = time_to_nclk(speed_bin_table(speed_bin_index, SPEED_BIN_TRP), t_ckclk); - t_wr = TIME_2_CLOCK_CYCLES(speed_bin_table(speed_bin_index, + t_wr = time_to_nclk(speed_bin_table(speed_bin_index, SPEED_BIN_TWR), t_ckclk); - t_wtr = TIME_2_CLOCK_CYCLES(t_wtr, t_ckclk); - t_rrd = TIME_2_CLOCK_CYCLES(t_rrd, t_ckclk); - t_rtp = TIME_2_CLOCK_CYCLES(t_rtp, t_ckclk); - t_rfc = TIME_2_CLOCK_CYCLES(rfc_table[memory_size] * 1000, t_ckclk); - t_mod = GET_MAX_VALUE(t_ckclk * 24, 15000); - t_mod = TIME_2_CLOCK_CYCLES(t_mod, t_ckclk); + t_wtr = time_to_nclk(t_wtr, t_ckclk); + t_rrd = time_to_nclk(t_rrd, t_ckclk); + t_rtp = time_to_nclk(t_rtp, t_ckclk); + t_rfc = time_to_nclk(rfc_table[memory_size] * 1000, t_ckclk); + t_mod = time_to_nclk(t_mod, t_ckclk); /* SDRAM Timing Low */ - val = (t_ras & 0xf) | (t_rcd << 4) | (t_rp << 8) | (t_wr << 12) | - (t_wtr << 16) | (((t_ras & 0x30) >> 4) << 20) | (t_rrd << 24) | - (t_rtp << 28); + val = (((t_ras - 1) & SDRAM_TIMING_LOW_TRAS_MASK) << SDRAM_TIMING_LOW_TRAS_OFFS) | + (((t_rcd - 1) & SDRAM_TIMING_LOW_TRCD_MASK) << SDRAM_TIMING_LOW_TRCD_OFFS) | + (((t_rcd - 1) >> SDRAM_TIMING_LOW_TRCD_OFFS & SDRAM_TIMING_HIGH_TRCD_MASK) + << SDRAM_TIMING_HIGH_TRCD_OFFS) | + (((t_rp - 1) & SDRAM_TIMING_LOW_TRP_MASK) << SDRAM_TIMING_LOW_TRP_OFFS) | + (((t_rp - 1) >> SDRAM_TIMING_LOW_TRP_MASK & SDRAM_TIMING_HIGH_TRP_MASK) + << SDRAM_TIMING_HIGH_TRP_OFFS) | + (((t_wr - 1) & SDRAM_TIMING_LOW_TWR_MASK) << SDRAM_TIMING_LOW_TWR_OFFS) | + (((t_wtr - 1) & SDRAM_TIMING_LOW_TWTR_MASK) << SDRAM_TIMING_LOW_TWTR_OFFS) | + ((((t_ras - 1) >> 4) & SDRAM_TIMING_LOW_TRAS_HIGH_MASK) << SDRAM_TIMING_LOW_TRAS_HIGH_OFFS) | + (((t_rrd - 1) & SDRAM_TIMING_LOW_TRRD_MASK) << SDRAM_TIMING_LOW_TRRD_OFFS) | + (((t_rtp - 1) & SDRAM_TIMING_LOW_TRTP_MASK) << SDRAM_TIMING_LOW_TRTP_OFFS); + + mask = (SDRAM_TIMING_LOW_TRAS_MASK << SDRAM_TIMING_LOW_TRAS_OFFS) | + (SDRAM_TIMING_LOW_TRCD_MASK << SDRAM_TIMING_LOW_TRCD_OFFS) | + (SDRAM_TIMING_HIGH_TRCD_MASK << SDRAM_TIMING_HIGH_TRCD_OFFS) | + (SDRAM_TIMING_LOW_TRP_MASK << SDRAM_TIMING_LOW_TRP_OFFS) | + (SDRAM_TIMING_HIGH_TRP_MASK << SDRAM_TIMING_HIGH_TRP_OFFS) | + (SDRAM_TIMING_LOW_TWR_MASK << SDRAM_TIMING_LOW_TWR_OFFS) | + (SDRAM_TIMING_LOW_TWTR_MASK << SDRAM_TIMING_LOW_TWTR_OFFS) | + (SDRAM_TIMING_LOW_TRAS_HIGH_MASK << SDRAM_TIMING_LOW_TRAS_HIGH_OFFS) | + (SDRAM_TIMING_LOW_TRRD_MASK << SDRAM_TIMING_LOW_TRRD_OFFS) | + (SDRAM_TIMING_LOW_TRTP_MASK << SDRAM_TIMING_LOW_TRTP_OFFS); + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_LOW_REG, val, 0xff3fffff)); + SDRAM_TIMING_LOW_REG, val, mask)); /* SDRAM Timing High */ + val = 0; + mask = 0; + + val = (((t_rfc - 1) & SDRAM_TIMING_HIGH_TRFC_MASK) << SDRAM_TIMING_HIGH_TRFC_OFFS) | + ((t_r2r & SDRAM_TIMING_HIGH_TR2R_MASK) << SDRAM_TIMING_HIGH_TR2R_OFFS) | + ((t_r2w_w2r & SDRAM_TIMING_HIGH_TR2W_W2R_MASK) << SDRAM_TIMING_HIGH_TR2W_W2R_OFFS) | + ((t_w2w & SDRAM_TIMING_HIGH_TW2W_MASK) << SDRAM_TIMING_HIGH_TW2W_OFFS) | + ((((t_rfc - 1) >> 7) & SDRAM_TIMING_HIGH_TRFC_HIGH_MASK) << SDRAM_TIMING_HIGH_TRFC_HIGH_OFFS) | + ((t_r2r_high & SDRAM_TIMING_HIGH_TR2R_HIGH_MASK) << SDRAM_TIMING_HIGH_TR2R_HIGH_OFFS) | + ((t_r2w_w2r_high & SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_MASK) << SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_OFFS) | + (((t_mod - 1) & SDRAM_TIMING_HIGH_TMOD_MASK) << SDRAM_TIMING_HIGH_TMOD_OFFS) | + ((((t_mod - 1) >> 4) & SDRAM_TIMING_HIGH_TMOD_HIGH_MASK) << SDRAM_TIMING_HIGH_TMOD_HIGH_OFFS); + + mask = (SDRAM_TIMING_HIGH_TRFC_MASK << SDRAM_TIMING_HIGH_TRFC_OFFS) | + (SDRAM_TIMING_HIGH_TR2R_MASK << SDRAM_TIMING_HIGH_TR2R_OFFS) | + (SDRAM_TIMING_HIGH_TR2W_W2R_MASK << SDRAM_TIMING_HIGH_TR2W_W2R_OFFS) | + (SDRAM_TIMING_HIGH_TW2W_MASK << SDRAM_TIMING_HIGH_TW2W_OFFS) | + (SDRAM_TIMING_HIGH_TRFC_HIGH_MASK << SDRAM_TIMING_HIGH_TRFC_HIGH_OFFS) | + (SDRAM_TIMING_HIGH_TR2R_HIGH_MASK << SDRAM_TIMING_HIGH_TR2R_HIGH_OFFS) | + (SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_MASK << SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_OFFS) | + (SDRAM_TIMING_HIGH_TMOD_MASK << SDRAM_TIMING_HIGH_TMOD_OFFS) | + (SDRAM_TIMING_HIGH_TMOD_HIGH_MASK << SDRAM_TIMING_HIGH_TMOD_HIGH_OFFS); + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - t_rfc & 0x7f, 0x7f)); - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - 0x180, 0x180)); - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - 0x600, 0x600)); - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - 0x1800, 0xf800)); - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - ((t_rfc & 0x380) >> 7) << 16, 0x70000)); - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, 0, - 0x380000)); - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - (t_mod & 0xf) << 25, 0x1e00000)); - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - (t_mod >> 4) << 30, 0xc0000000)); + SDRAM_TIMING_HIGH_REG, val, mask)); + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - 0x16000000, 0x1e000000)); + SDRAM_CFG_REG, + refresh_interval_cnt << REFRESH_OFFS, + REFRESH_MASK << REFRESH_OFFS)); CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - 0x40000000, 0xc0000000)); + SDRAM_ADDR_CTRL_REG, (t_faw - 1) << T_FAW_OFFS, + T_FAW_MASK << T_FAW_OFFS)); + + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, DDR_TIMING_REG, + (t_pd - 1) << DDR_TIMING_TPD_OFFS | + (t_xpdll - 1) << DDR_TIMING_TXPDLL_OFFS, + DDR_TIMING_TPD_MASK << DDR_TIMING_TPD_OFFS | + DDR_TIMING_TXPDLL_MASK << DDR_TIMING_TXPDLL_OFFS)); + return MV_OK; } + /* * Mode Read */ @@ -1713,13 +1847,13 @@ int hws_ddr3_tip_mode_read(u32 dev_num, struct mode_info *mode_info) return ret; ret = ddr3_tip_if_read(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - READ_DATA_SAMPLE_DELAY, mode_info->read_data_sample, + RD_DATA_SMPL_DLYS_REG, mode_info->read_data_sample, MASK_ALL_BITS); if (ret != MV_OK) return ret; ret = ddr3_tip_if_read(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - READ_DATA_READY_DELAY, mode_info->read_data_ready, + RD_DATA_RDY_DLYS_REG, mode_info->read_data_ready, MASK_ALL_BITS); if (ret != MV_OK) return ret; @@ -1734,10 +1868,10 @@ int ddr3_tip_get_first_active_if(u8 dev_num, u32 interface_mask, u32 *interface_id) { u32 if_id; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (interface_mask & (1 << if_id)) { *interface_id = if_id; break; @@ -1753,13 +1887,14 @@ int ddr3_tip_get_first_active_if(u8 dev_num, u32 interface_mask, int ddr3_tip_write_cs_result(u32 dev_num, u32 offset) { u32 if_id, bus_num, cs_bitmask, data_val, cs_num; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_num = 0; bus_num < tm->num_of_bus_per_interface; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_num = 0; bus_num < octets_per_if_num; bus_num++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_num); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num); cs_bitmask = tm->interface_params[if_id]. as_bus_params[bus_num].cs_bitmask; @@ -1769,7 +1904,7 @@ int ddr3_tip_write_cs_result(u32 dev_num, u32 offset) ACCESS_TYPE_UNICAST, bus_num, DDR_PHY_DATA, offset + - CS_REG_VALUE(effective_cs), + (effective_cs * 0x4), &data_val); ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, @@ -1777,7 +1912,7 @@ int ddr3_tip_write_cs_result(u32 dev_num, u32 offset) ACCESS_TYPE_UNICAST, bus_num, DDR_PHY_DATA, offset + - CS_REG_VALUE(cs_num), + (cs_num * 0x4), data_val); } } @@ -1789,27 +1924,25 @@ int ddr3_tip_write_cs_result(u32 dev_num, u32 offset) /* * Write MRS */ -int ddr3_tip_write_mrs_cmd(u32 dev_num, u32 *cs_mask_arr, u32 cmd, - u32 data, u32 mask) +int ddr3_tip_write_mrs_cmd(u32 dev_num, u32 *cs_mask_arr, enum mr_number mr_num, u32 data, u32 mask) { - u32 if_id, reg; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 if_id; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - reg = (cmd == MRS1_CMD) ? MR1_REG : MR2_REG; CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, reg, data, mask)); + PARAM_NOT_CARE, mr_data[mr_num].reg_addr, data, mask)); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - SDRAM_OPERATION_REG, - (cs_mask_arr[if_id] << 8) | cmd, 0xf1f)); + SDRAM_OP_REG, + (cs_mask_arr[if_id] << 8) | mr_data[mr_num].cmd, 0xf1f)); } for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id, 0, - 0x1f, SDRAM_OPERATION_REG, + 0x1f, SDRAM_OP_REG, MAX_POLLING_ITERATIONS) != MV_OK) { DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("write_mrs_cmd: Poll cmd fail")); @@ -1864,35 +1997,57 @@ int ddr3_tip_reset_fifo_ptr(u32 dev_num) int ddr3_tip_ddr3_reset_phy_regs(u32 dev_num) { u32 if_id, phy_id, cs; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (phy_id = 0; phy_id < tm->num_of_bus_per_interface; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (phy_id = 0; phy_id < octets_per_if_num; phy_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, phy_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, phy_id); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, - WL_PHY_REG + - CS_REG_VALUE(effective_cs), + WL_PHY_REG(effective_cs), phy_reg0_val)); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, - RL_PHY_REG + CS_REG_VALUE(effective_cs), + RL_PHY_REG(effective_cs), phy_reg2_val)); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, - READ_CENTRALIZATION_PHY_REG + - CS_REG_VALUE(effective_cs), phy_reg3_val)); + CRX_PHY_REG(effective_cs), phy_reg3_val)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, + CTX_PHY_REG(effective_cs), phy_reg1_val)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, + PBS_TX_BCAST_PHY_REG(effective_cs), 0x0)); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - CS_REG_VALUE(effective_cs), phy_reg3_val)); + PBS_RX_BCAST_PHY_REG(effective_cs), 0)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, + PBS_TX_PHY_REG(effective_cs, DQSP_PAD), 0)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, + PBS_RX_PHY_REG(effective_cs, DQSP_PAD), 0)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, + PBS_TX_PHY_REG(effective_cs, DQSN_PAD), 0)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, + PBS_RX_PHY_REG(effective_cs, DQSN_PAD), 0)); } } @@ -1902,7 +2057,7 @@ int ddr3_tip_ddr3_reset_phy_regs(u32 dev_num) CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - DDR_PHY_DATA, CSN_IOB_VREF_REG(cs), 63)); + DDR_PHY_DATA, VREF_BCAST_PHY_REG(cs), 63)); } return MV_OK; @@ -1915,16 +2070,18 @@ int ddr3_tip_restore_dunit_regs(u32 dev_num) { u32 index_cnt; + mv_ddr_set_calib_controller(); + CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, CALIB_MACHINE_CTRL_REG, + PARAM_NOT_CARE, MAIN_PADS_CAL_MACH_CTRL_REG, 0x1, 0x1)); CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, CALIB_MACHINE_CTRL_REG, + PARAM_NOT_CARE, MAIN_PADS_CAL_MACH_CTRL_REG, calibration_update_control << 3, 0x3 << 3)); CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_WRITE_READ_MODE_ENABLE_REG, + ODPG_WR_RD_MODE_ENA_REG, 0xffff, MASK_ALL_BITS)); for (index_cnt = 0; index_cnt < ARRAY_SIZE(odpg_default_value); @@ -1939,39 +2096,72 @@ int ddr3_tip_restore_dunit_regs(u32 dev_num) return MV_OK; } +int ddr3_tip_adll_regs_bypass(u32 dev_num, u32 reg_val1, u32 reg_val2) +{ + u32 if_id, phy_id; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (phy_id = 0; phy_id < octets_per_if_num; phy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, phy_id); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, + CTX_PHY_REG(effective_cs), reg_val1)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, + PBS_TX_BCAST_PHY_REG(effective_cs), reg_val2)); + } + } + + return MV_OK; +} + /* * Auto tune main flow */ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) { - enum hws_ddr_freq freq = init_freq; +/* TODO: enable this functionality for other platforms */ +#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_39X) struct init_cntr_param init_cntr_prm; +#endif int ret = MV_OK; + int adll_bypass_flag = 0; u32 if_id; - u32 max_cs = hws_ddr3_tip_max_cs_get(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 max_cs = ddr3_tip_max_cs_get(dev_num); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + enum hws_ddr_freq freq = tm->interface_params[0].memory_freq; -#ifndef EXCLUDE_SWITCH_DEBUG +#ifdef DDR_VIEWER_TOOL if (debug_training == DEBUG_LEVEL_TRACE) { CHECK_STATUS(print_device_info((u8)dev_num)); } #endif + ddr3_tip_validate_algo_components(dev_num); + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { CHECK_STATUS(ddr3_tip_ddr3_reset_phy_regs(dev_num)); } /* Set to 0 after each loop to avoid illegal value may be used */ effective_cs = 0; - freq = init_freq; + freq_val[DDR_FREQ_LOW_FREQ] = dfs_low_freq; + if (is_pll_before_init != 0) { for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); config_func_info[dev_num].tip_set_freq_divider_func( (u8)dev_num, if_id, freq); } } +/* TODO: enable this functionality for other platforms */ +#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_39X) if (is_adll_calib_before_init != 0) { DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("with adll calib before init\n")); @@ -2002,10 +2192,25 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) return MV_FAIL; } } +#endif + ret = adll_calibration(dev_num, ACCESS_TYPE_MULTICAST, 0, freq); + if (ret != MV_OK) { + DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, + ("adll_calibration failure\n")); + if (debug_mode == 0) + return MV_FAIL; + } if (mask_tune_func & SET_LOW_FREQ_MASK_BIT) { training_stage = SET_LOW_FREQ; + + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { + ddr3_tip_adll_regs_bypass(dev_num, 0, 0x1f); + adll_bypass_flag = 1; + } + effective_cs = 0; + DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("SET_LOW_FREQ_MASK_BIT %d\n", freq_val[low_freq])); @@ -2021,6 +2226,21 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) } } + if (mask_tune_func & WRITE_LEVELING_LF_MASK_BIT) { + training_stage = WRITE_LEVELING_LF; + DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, + ("WRITE_LEVELING_LF_MASK_BIT\n")); + ret = ddr3_tip_dynamic_write_leveling(dev_num, 1); + if (is_reg_dump != 0) + ddr3_tip_reg_dump(dev_num); + if (ret != MV_OK) { + DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, + ("ddr3_tip_dynamic_write_leveling LF failure\n")); + if (debug_mode == 0) + return MV_FAIL; + } + } + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { if (mask_tune_func & LOAD_PATTERN_MASK_BIT) { training_stage = LOAD_PATTERN; @@ -2039,6 +2259,14 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) } } } + + if (adll_bypass_flag == 1) { + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { + ddr3_tip_adll_regs_bypass(dev_num, phy_reg1_val, 0); + adll_bypass_flag = 0; + } + } + /* Set to 0 after each loop to avoid illegal value may be used */ effective_cs = 0; @@ -2065,7 +2293,7 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("WRITE_LEVELING_MASK_BIT\n")); if ((rl_mid_freq_wa == 0) || (freq_val[medium_freq] == 533)) { - ret = ddr3_tip_dynamic_write_leveling(dev_num); + ret = ddr3_tip_dynamic_write_leveling(dev_num, 0); } else { /* Use old WL */ ret = ddr3_tip_legacy_dynamic_write_leveling(dev_num); @@ -2189,6 +2417,12 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) PARAM_NOT_CARE, tm->interface_params[first_active_if]. memory_freq); +#if defined(A70X0) || defined(A80X0) + if (apn806_rev_id_get() == APN806_REV_ID_A0) { + reg_write(0x6f812c, extension_avs); + reg_write(0x6f8130, nominal_avs); + } +#endif /* #if defined(A70X0) || defined(A80X0) */ if (is_reg_dump != 0) ddr3_tip_reg_dump(dev_num); if (ret != MV_OK) { @@ -2203,7 +2437,7 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) training_stage = WRITE_LEVELING_TF; DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("WRITE_LEVELING_TF_MASK_BIT\n")); - ret = ddr3_tip_dynamic_write_leveling(dev_num); + ret = ddr3_tip_dynamic_write_leveling(dev_num, 0); if (is_reg_dump != 0) ddr3_tip_reg_dump(dev_num); if (ret != MV_OK) { @@ -2245,6 +2479,21 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) } } + if (mask_tune_func & RL_DQS_BURST_MASK_BIT) { + training_stage = READ_LEVELING_TF; + DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, + ("RL_DQS_BURST_MASK_BIT\n")); + ret = mv_ddr_rl_dqs_burst(0, 0, tm->interface_params[0].memory_freq); + if (is_reg_dump != 0) + ddr3_tip_reg_dump(dev_num); + if (ret != MV_OK) { + DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, + ("mv_ddr_rl_dqs_burst TF failure\n")); + if (debug_mode == 0) + return MV_FAIL; + } + } + if (mask_tune_func & DM_PBS_TX_MASK_BIT) { DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("DM_PBS_TX_MASK_BIT\n")); } @@ -2312,6 +2561,7 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) /* Set to 0 after each loop to avoid illegal value may be used */ effective_cs = 0; + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { if (mask_tune_func & CENTRALIZATION_TX_MASK_BIT) { training_stage = CENTRALIZATION_TX; @@ -2348,7 +2598,8 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) */ static int ddr3_tip_ddr3_auto_tune(u32 dev_num) { - u32 if_id, stage, ret; + int status; + u32 if_id, stage; int is_if_fail = 0, is_auto_tune_fail = 0; training_stage = INIT_CONTROLLER; @@ -2358,7 +2609,7 @@ static int ddr3_tip_ddr3_auto_tune(u32 dev_num) training_result[stage][if_id] = NO_TEST_DONE; } - ret = ddr3_tip_ddr3_training_main_flow(dev_num); + status = ddr3_tip_ddr3_training_main_flow(dev_num); /* activate XSB test */ if (xsb_validate_type != 0) { @@ -2372,9 +2623,11 @@ static int ddr3_tip_ddr3_auto_tune(u32 dev_num) /* print log */ CHECK_STATUS(ddr3_tip_print_log(dev_num, window_mem_addr)); - if (ret != MV_OK) { +#ifndef EXCLUDE_DEBUG_PRINTS + if (status != MV_OK) { CHECK_STATUS(ddr3_tip_print_stability_log(dev_num)); } +#endif /* EXCLUDE_DEBUG_PRINTS */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { is_if_fail = 0; @@ -2390,7 +2643,20 @@ static int ddr3_tip_ddr3_auto_tune(u32 dev_num) } } - if ((ret == MV_FAIL) || (is_auto_tune_fail == 1)) + if (((status == MV_FAIL) && (is_auto_tune_fail == 0)) || + ((status == MV_OK) && (is_auto_tune_fail == 1))) { + /* + * If MainFlow result and trainingResult DB not in sync, + * issue warning (caused by no update of trainingResult DB + * when failed) + */ + DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, + ("Warning: Algorithm return value and Result DB" + "are not synced (status 0x%x result DB %d)\n", + status, is_auto_tune_fail)); + } + + if ((status != MV_OK) || (is_auto_tune_fail == 1)) return MV_FAIL; else return MV_OK; @@ -2403,18 +2669,19 @@ int ddr3_tip_enable_init_sequence(u32 dev_num) { int is_fail = 0; u32 if_id = 0, mem_mask = 0, bus_index = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* Enable init sequence */ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, 0, - SDRAM_INIT_CONTROL_REG, 0x1, 0x1)); + SDRAM_INIT_CTRL_REG, 0x1, 0x1)); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (ddr3_tip_if_polling (dev_num, ACCESS_TYPE_UNICAST, if_id, 0, 0x1, - SDRAM_INIT_CONTROL_REG, + SDRAM_INIT_CTRL_REG, MAX_POLLING_ITERATIONS) != MV_OK) { DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("polling failed IF %d\n", @@ -2424,9 +2691,9 @@ int ddr3_tip_enable_init_sequence(u32 dev_num) } mem_mask = 0; - for (bus_index = 0; bus_index < GET_TOPOLOGY_NUM_OF_BUSES(); + for (bus_index = 0; bus_index < octets_per_if_num; bus_index++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_index); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_index); mem_mask |= tm->interface_params[if_id]. as_bus_params[bus_index].mirror_enable_bitmask; @@ -2436,7 +2703,7 @@ int ddr3_tip_enable_init_sequence(u32 dev_num) /* Disable Multi CS */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, - if_id, CS_ENABLE_REG, 1 << 3, + if_id, DUAL_DUNIT_CFG_REG, 1 << 3, 1 << 3)); } } @@ -2513,7 +2780,7 @@ u8 ddr3_tip_get_buf_max(u8 *buf_ptr) u32 hws_ddr3_get_bus_width(void) { - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); return (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 1) ? 16 : 32; @@ -2521,18 +2788,18 @@ u32 hws_ddr3_get_bus_width(void) u32 hws_ddr3_get_device_width(u32 if_id) { - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); return (tm->interface_params[if_id].bus_width == - BUS_WIDTH_8) ? 8 : 16; + MV_DDR_DEV_WIDTH_8BIT) ? 8 : 16; } u32 hws_ddr3_get_device_size(u32 if_id) { - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (tm->interface_params[if_id].memory_size >= - MEM_SIZE_LAST) { + MV_DDR_DIE_CAP_LAST) { DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("Error: Wrong device size of Cs: %d", tm->interface_params[if_id].memory_size)); @@ -2586,14 +2853,13 @@ int hws_ddr3_cs_base_adr_calc(u32 if_id, u32 cs, u32 *cs_base_addr) return MV_FAIL; #ifdef DEVICE_MAX_DRAM_ADDRESS_SIZE - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* * if number of address pins doesn't allow to use max mem size that * is defined in topology mem size is defined by * DEVICE_MAX_DRAM_ADDRESS_SIZE */ - physical_mem_size = - mv_hwsmem_size[tm->interface_params[0].memory_size]; + physical_mem_size = mem_size[tm->interface_params[0].memory_size]; if (hws_ddr3_get_device_width(cs) == 16) { /* diff --git a/drivers/ddr/marvell/a38x/ddr3_training_bist.c b/drivers/ddr/marvell/a38x/ddr3_training_bist.c index bd0e26068e39..2bab1c7c3226 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_bist.c +++ b/drivers/ddr/marvell/a38x/ddr3_training_bist.c @@ -4,12 +4,6 @@ * SPDX-License-Identifier: GPL-2.0 */ -#include -#include -#include -#include -#include - #include "ddr3_init.h" static u32 bist_offset = 32; @@ -25,7 +19,7 @@ static int ddr3_tip_bist_operation(u32 dev_num, */ int ddr3_tip_bist_activate(u32 dev_num, enum hws_pattern pattern, enum hws_access_type access_type, u32 if_num, - enum hws_dir direction, + enum hws_dir dir, enum hws_stress_jump addr_stress_jump, enum hws_pattern_duration duration, enum hws_bist_operation oper_type, @@ -33,103 +27,43 @@ int ddr3_tip_bist_activate(u32 dev_num, enum hws_pattern pattern, { u32 tx_burst_size; u32 delay_between_burst; - u32 rd_mode, val; - u32 poll_cnt = 0, max_poll = 1000, i, start_if, end_if; + u32 rd_mode; struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); - u32 read_data[MAX_INTERFACE_NUM]; - struct hws_topology_map *tm = ddr3_get_topology_map(); - - /* ODPG Write enable from BIST */ - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_num, - ODPG_DATA_CONTROL_REG, 0x1, 0x1)); - /* ODPG Read enable/disable from BIST */ - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_num, - ODPG_DATA_CONTROL_REG, - (direction == OPER_READ) ? - 0x2 : 0, 0x2)); - CHECK_STATUS(ddr3_tip_load_pattern_to_odpg(dev_num, access_type, if_num, - pattern, offset)); - - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_num, - ODPG_DATA_BUF_SIZE_REG, - pattern_addr_length, MASK_ALL_BITS)); - tx_burst_size = (direction == OPER_WRITE) ? + + /* odpg bist write enable */ + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG, + (ODPG_WRBUF_WR_CTRL_ENA << ODPG_WRBUF_WR_CTRL_OFFS), + (ODPG_WRBUF_WR_CTRL_MASK << ODPG_WRBUF_WR_CTRL_OFFS)); + + /* odpg bist read enable/disable */ + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG, + (dir == OPER_READ) ? (ODPG_WRBUF_RD_CTRL_ENA << ODPG_WRBUF_RD_CTRL_OFFS) : + (ODPG_WRBUF_RD_CTRL_DIS << ODPG_WRBUF_RD_CTRL_OFFS), + (ODPG_WRBUF_RD_CTRL_MASK << ODPG_WRBUF_RD_CTRL_OFFS)); + + ddr3_tip_load_pattern_to_odpg(0, access_type, 0, pattern, offset); + + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_BUFFER_SIZE_REG, pattern_addr_length, MASK_ALL_BITS); + tx_burst_size = (dir == OPER_WRITE) ? pattern_table[pattern].tx_burst_size : 0; - delay_between_burst = (direction == OPER_WRITE) ? 2 : 0; - rd_mode = (direction == OPER_WRITE) ? 1 : 0; - CHECK_STATUS(ddr3_tip_configure_odpg - (dev_num, access_type, if_num, direction, + delay_between_burst = (dir == OPER_WRITE) ? 2 : 0; + rd_mode = (dir == OPER_WRITE) ? 1 : 0; + ddr3_tip_configure_odpg(0, access_type, 0, dir, pattern_table[pattern].num_of_phases_tx, tx_burst_size, pattern_table[pattern].num_of_phases_rx, delay_between_burst, - rd_mode, cs_num, addr_stress_jump, duration)); - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_num, - ODPG_PATTERN_ADDR_OFFSET_REG, - offset, MASK_ALL_BITS)); + rd_mode, cs_num, addr_stress_jump, duration); + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_BUFFER_OFFS_REG, offset, MASK_ALL_BITS); + if (oper_type == BIST_STOP) { - CHECK_STATUS(ddr3_tip_bist_operation(dev_num, access_type, - if_num, BIST_STOP)); + ddr3_tip_bist_operation(0, access_type, 0, BIST_STOP); } else { - CHECK_STATUS(ddr3_tip_bist_operation(dev_num, access_type, - if_num, BIST_START)); - if (duration != DURATION_CONT) { - /* - * This pdelay is a WA, becuase polling fives "done" - * also the odpg did nmot finish its task - */ - if (access_type == ACCESS_TYPE_MULTICAST) { - start_if = 0; - end_if = MAX_INTERFACE_NUM - 1; - } else { - start_if = if_num; - end_if = if_num; - } - - for (i = start_if; i <= end_if; i++) { - VALIDATE_ACTIVE(tm-> - if_act_mask, i); - - for (poll_cnt = 0; poll_cnt < max_poll; - poll_cnt++) { - CHECK_STATUS(ddr3_tip_if_read - (dev_num, - ACCESS_TYPE_UNICAST, - if_num, ODPG_BIST_DONE, - read_data, - MASK_ALL_BITS)); - val = read_data[i]; - if ((val & 0x1) == 0x0) { - /* - * In SOC type devices this bit - * is self clear so, if it was - * cleared all good - */ - break; - } - } - - if (poll_cnt >= max_poll) { - DEBUG_TRAINING_BIST_ENGINE - (DEBUG_LEVEL_ERROR, - ("Bist poll failure 2\n")); - CHECK_STATUS(ddr3_tip_if_write - (dev_num, - ACCESS_TYPE_UNICAST, - if_num, - ODPG_DATA_CONTROL_REG, 0, - MASK_ALL_BITS)); - return MV_FAIL; - } - } - - CHECK_STATUS(ddr3_tip_bist_operation - (dev_num, access_type, if_num, BIST_STOP)); - } + ddr3_tip_bist_operation(0, access_type, 0, BIST_START); + if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK) + return MV_FAIL; + ddr3_tip_bist_operation(0, access_type, 0, BIST_STOP); } - - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_num, - ODPG_DATA_CONTROL_REG, 0, - MASK_ALL_BITS)); + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS); return MV_OK; } @@ -142,34 +76,34 @@ int ddr3_tip_bist_read_result(u32 dev_num, u32 if_id, { int ret; u32 read_data[MAX_INTERFACE_NUM]; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - if (IS_ACTIVE(tm->if_act_mask, if_id) == 0) + if (IS_IF_ACTIVE(tm->if_act_mask, if_id) == 0) return MV_NOT_SUPPORTED; DEBUG_TRAINING_BIST_ENGINE(DEBUG_LEVEL_TRACE, ("ddr3_tip_bist_read_result if_id %d\n", if_id)); ret = ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_BIST_FAILED_DATA_HI_REG, read_data, + ODPG_DATA_RX_WORD_ERR_DATA_HIGH_REG, read_data, MASK_ALL_BITS); if (ret != MV_OK) return ret; pst_bist_result->bist_fail_high = read_data[if_id]; ret = ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_BIST_FAILED_DATA_LOW_REG, read_data, + ODPG_DATA_RX_WORD_ERR_DATA_LOW_REG, read_data, MASK_ALL_BITS); if (ret != MV_OK) return ret; pst_bist_result->bist_fail_low = read_data[if_id]; ret = ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_BIST_LAST_FAIL_ADDR_REG, read_data, + ODPG_DATA_RX_WORD_ERR_ADDR_REG, read_data, MASK_ALL_BITS); if (ret != MV_OK) return ret; pst_bist_result->bist_last_fail_addr = read_data[if_id]; ret = ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_BIST_DATA_ERROR_COUNTER_REG, read_data, + ODPG_DATA_RX_WORD_ERR_CNTR_REG, read_data, MASK_ALL_BITS); if (ret != MV_OK) return ret; @@ -188,10 +122,10 @@ int hws_ddr3_run_bist(u32 dev_num, enum hws_pattern pattern, u32 *result, u32 i = 0; u32 win_base; struct bist_result st_bist_result; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (i = 0; i < MAX_INTERFACE_NUM; i++) { - VALIDATE_ACTIVE(tm->if_act_mask, i); + VALIDATE_IF_ACTIVE(tm->if_act_mask, i); hws_ddr3_cs_base_adr_calc(i, cs_num, &win_base); ret = ddr3_tip_bist_activate(dev_num, pattern, ACCESS_TYPE_UNICAST, @@ -234,13 +168,10 @@ static int ddr3_tip_bist_operation(u32 dev_num, enum hws_access_type access_type, u32 if_id, enum hws_bist_operation oper_type) { - if (oper_type == BIST_STOP) { - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - ODPG_BIST_DONE, 1 << 8, 1 << 8)); - } else { - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - ODPG_BIST_DONE, 1, 1)); - } + if (oper_type == BIST_STOP) + mv_ddr_odpg_disable(); + else + mv_ddr_odpg_enable(); return MV_OK; } @@ -254,11 +185,10 @@ void ddr3_tip_print_bist_res(void) u32 i; struct bist_result st_bist_result[MAX_INTERFACE_NUM]; int res; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (i = 0; i < MAX_INTERFACE_NUM; i++) { - if (IS_ACTIVE(tm->if_act_mask, i) == 0) - continue; + VALIDATE_IF_ACTIVE(tm->if_act_mask, i); res = ddr3_tip_bist_read_result(dev_num, i, &st_bist_result[i]); if (res != MV_OK) { @@ -274,9 +204,7 @@ void ddr3_tip_print_bist_res(void) ("interface | error_cnt | fail_low | fail_high | fail_addr\n")); for (i = 0; i < MAX_INTERFACE_NUM; i++) { - if (IS_ACTIVE(tm->if_act_mask, i) == - 0) - continue; + VALIDATE_IF_ACTIVE(tm->if_act_mask, i); DEBUG_TRAINING_BIST_ENGINE( DEBUG_LEVEL_INFO, @@ -287,3 +215,389 @@ void ddr3_tip_print_bist_res(void) st_bist_result[i].bist_last_fail_addr)); } } + +enum { + PASS, + FAIL +}; +#define TIP_ITERATION_NUM 31 +static int mv_ddr_tip_bist(enum hws_dir dir, u32 val, enum hws_pattern pattern, u32 cs, u32 *result) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + enum hws_training_ip_stat training_result; + u16 *reg_map = ddr3_tip_get_mask_results_pup_reg_map(); + u32 max_subphy = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE); + u32 subphy, read_data; + + ddr3_tip_ip_training(0, ACCESS_TYPE_MULTICAST, 0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + RESULT_PER_BYTE, HWS_CONTROL_ELEMENT_ADLL, HWS_LOW2HIGH, dir, tm->if_act_mask, val, + TIP_ITERATION_NUM, pattern, EDGE_FP, CS_SINGLE, cs, &training_result); + + for (subphy = 0; subphy < max_subphy; subphy++) { + ddr3_tip_if_read(0, ACCESS_TYPE_UNICAST, 0, reg_map[subphy], &read_data, MASK_ALL_BITS); + if (((read_data >> BLOCK_STATUS_OFFS) & BLOCK_STATUS_MASK) == BLOCK_STATUS_NOT_LOCKED) + *result |= (FAIL << subphy); + } + + return MV_OK; +} + +struct interval { + u8 *vector; + u8 lendpnt; /* interval's left endpoint */ + u8 rendpnt; /* interval's right endpoint */ + u8 size; /* interval's size */ + u8 lmarker; /* left marker */ + u8 rmarker; /* right marker */ + u8 pass_lendpnt; /* left endpoint of internal pass interval */ + u8 pass_rendpnt; /* right endpoint of internal pass interval */ +}; + +static int interval_init(u8 *vector, u8 lendpnt, u8 rendpnt, + u8 lmarker, u8 rmarker, struct interval *intrvl) +{ + if (intrvl == NULL) { + printf("%s: NULL intrvl pointer found\n", __func__); + return MV_FAIL; + } + + if (vector == NULL) { + printf("%s: NULL vector pointer found\n", __func__); + return MV_FAIL; + } + intrvl->vector = vector; + + if (lendpnt >= rendpnt) { + printf("%s: incorrect lendpnt and/or rendpnt parameters found\n", __func__); + return MV_FAIL; + } + intrvl->lendpnt = lendpnt; + intrvl->rendpnt = rendpnt; + intrvl->size = rendpnt - lendpnt + 1; + + if ((lmarker < lendpnt) || (lmarker > rendpnt)) { + printf("%s: incorrect lmarker parameter found\n", __func__); + return MV_FAIL; + } + intrvl->lmarker = lmarker; + + if ((rmarker < lmarker) || (rmarker > (intrvl->rendpnt + intrvl->size))) { + printf("%s: incorrect rmarker parameter found\n", __func__); + return MV_FAIL; + } + intrvl->rmarker = rmarker; + + return MV_OK; +} +static int interval_set(u8 pass_lendpnt, u8 pass_rendpnt, struct interval *intrvl) +{ + if (intrvl == NULL) { + printf("%s: NULL intrvl pointer found\n", __func__); + return MV_FAIL; + } + + intrvl->pass_lendpnt = pass_lendpnt; + intrvl->pass_rendpnt = pass_rendpnt; + + return MV_OK; +} + +static int interval_proc(struct interval *intrvl) +{ + int curr; + int pass_lendpnt, pass_rendpnt; + int lmt; + int fcnt = 0, pcnt = 0; + + if (intrvl == NULL) { + printf("%s: NULL intrvl pointer found\n", __func__); + return MV_FAIL; + } + + /* count fails and passes */ + curr = intrvl->lendpnt; + while (curr <= intrvl->rendpnt) { + if (intrvl->vector[curr] == PASS) + pcnt++; + else + fcnt++; + curr++; + } + + /* check for all fail */ + if (fcnt == intrvl->size) { + printf("%s: no pass found\n", __func__); + return MV_FAIL; + } + + /* check for all pass */ + if (pcnt == intrvl->size) { + if (interval_set(intrvl->lendpnt, intrvl->rendpnt, intrvl) != MV_OK) + return MV_FAIL; + return MV_OK; + } + + /* proceed with rmarker */ + curr = intrvl->rmarker; + if (intrvl->vector[curr % intrvl->size] == PASS) { /* pass at rmarker */ + /* search for fail on right */ + if (intrvl->rmarker > intrvl->rendpnt) + lmt = intrvl->rendpnt + intrvl->size; + else + lmt = intrvl->rmarker + intrvl->size - 1; + while ((curr <= lmt) && + (intrvl->vector[curr % intrvl->size] == PASS)) + curr++; + if (curr > lmt) { /* fail not found */ + printf("%s: rmarker: fail following pass not found\n", __func__); + return MV_FAIL; + } + /* fail found */ + pass_rendpnt = curr - 1; + } else { /* fail at rmarker */ + /* search for pass on left */ + if (intrvl->rmarker > intrvl->rendpnt) + lmt = intrvl->rmarker - intrvl->size + 1; + else + lmt = intrvl->lendpnt; + while ((curr >= lmt) && + (intrvl->vector[curr % intrvl->size] == FAIL)) + curr--; + if (curr < lmt) { /* pass not found */ + printf("%s: rmarker: pass preceding fail not found\n", __func__); + return MV_FAIL; + } + /* pass found */ + pass_rendpnt = curr; + } + + /* search for fail on left */ + curr = pass_rendpnt; + if (pass_rendpnt > intrvl->rendpnt) + lmt = pass_rendpnt - intrvl->size + 1; + else + lmt = intrvl->lendpnt; + while ((curr >= lmt) && + (intrvl->vector[curr % intrvl->size] == PASS)) + curr--; + if (curr < lmt) { /* fail not found */ + printf("%s: rmarker: fail preceding pass not found\n", __func__); + return MV_FAIL; + } + /* fail found */ + pass_lendpnt = curr + 1; + if (interval_set(pass_lendpnt, pass_rendpnt, intrvl) != MV_OK) + return MV_FAIL; + + return MV_OK; +} + +#define ADLL_TAPS_PER_PERIOD 64 +int mv_ddr_dm_to_dq_diff_get(u8 vw_sphy_hi_lmt, u8 vw_sphy_lo_lmt, u8 *vw_vector, + int *vw_sphy_hi_diff, int *vw_sphy_lo_diff) +{ + struct interval intrvl; + + /* init interval structure */ + if (interval_init(vw_vector, 0, ADLL_TAPS_PER_PERIOD - 1, + vw_sphy_lo_lmt, vw_sphy_hi_lmt, &intrvl) != MV_OK) + return MV_FAIL; + + /* find pass sub-interval */ + if (interval_proc(&intrvl) != MV_OK) + return MV_FAIL; + + /* check for all pass */ + if ((intrvl.pass_rendpnt == intrvl.rendpnt) && + (intrvl.pass_lendpnt == intrvl.lendpnt)) { + printf("%s: no fail found\n", __func__); + return MV_FAIL; + } + + *vw_sphy_hi_diff = intrvl.pass_rendpnt - vw_sphy_hi_lmt; + *vw_sphy_lo_diff = vw_sphy_lo_lmt - intrvl.pass_lendpnt; + + return MV_OK; +} + +static int mv_ddr_bist_tx(enum hws_access_type access_type) +{ + mv_ddr_odpg_done_clr(); + + ddr3_tip_bist_operation(0, access_type, 0, BIST_START); + + if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK) + return MV_FAIL; + + ddr3_tip_bist_operation(0, access_type, 0, BIST_STOP); + + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS); + + return MV_OK; +} + +/* prepare odpg for bist operation */ +#define WR_OP_ODPG_DATA_CMD_BURST_DLY 2 +static int mv_ddr_odpg_bist_prepare(enum hws_pattern pattern, enum hws_access_type access_type, + enum hws_dir dir, enum hws_stress_jump stress_jump_addr, + enum hws_pattern_duration duration, u32 offset, u32 cs, + u32 pattern_addr_len, enum dm_direction dm_dir) +{ + struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); + u32 tx_burst_size; + u32 burst_delay; + u32 rd_mode; + + /* odpg bist write enable */ + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG, + (ODPG_WRBUF_WR_CTRL_ENA << ODPG_WRBUF_WR_CTRL_OFFS), + (ODPG_WRBUF_WR_CTRL_MASK << ODPG_WRBUF_WR_CTRL_OFFS)); + + /* odpg bist read enable/disable */ + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG, + (dir == OPER_READ) ? (ODPG_WRBUF_RD_CTRL_ENA << ODPG_WRBUF_RD_CTRL_OFFS) : + (ODPG_WRBUF_RD_CTRL_DIS << ODPG_WRBUF_RD_CTRL_OFFS), + (ODPG_WRBUF_RD_CTRL_MASK << ODPG_WRBUF_RD_CTRL_OFFS)); + + if (pattern == PATTERN_00 || pattern == PATTERN_FF) + ddr3_tip_load_pattern_to_odpg(0, access_type, 0, pattern, offset); + else + mv_ddr_load_dm_pattern_to_odpg(access_type, pattern, dm_dir); + + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_BUFFER_SIZE_REG, pattern_addr_len, MASK_ALL_BITS); + if (dir == OPER_WRITE) { + tx_burst_size = pattern_table[pattern].tx_burst_size; + burst_delay = WR_OP_ODPG_DATA_CMD_BURST_DLY; + rd_mode = ODPG_MODE_TX; + } else { + tx_burst_size = 0; + burst_delay = 0; + rd_mode = ODPG_MODE_RX; + } + ddr3_tip_configure_odpg(0, access_type, 0, dir, pattern_table[pattern].num_of_phases_tx, + tx_burst_size, pattern_table[pattern].num_of_phases_rx, burst_delay, + rd_mode, cs, stress_jump_addr, duration); + + return MV_OK; +} + +#define BYTES_PER_BURST_64BIT 0x20 +#define BYTES_PER_BURST_32BIT 0x10 +int mv_ddr_dm_vw_get(enum hws_pattern pattern, u32 cs, u8 *vw_vector) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); + u32 adll_tap; + u32 wr_ctrl_adll[MAX_BUS_NUM] = {0}; + u32 rd_ctrl_adll[MAX_BUS_NUM] = {0}; + u32 subphy; + u32 subphy_max = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE); + u32 odpg_addr = 0x0; + u32 result; + u32 idx; + /* burst length in bytes */ + u32 burst_len = (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask) ? + BYTES_PER_BURST_64BIT : BYTES_PER_BURST_32BIT); + + /* save dqs values to restore after algorithm's run */ + ddr3_tip_read_adll_value(0, wr_ctrl_adll, CTX_PHY_REG(cs), MASK_ALL_BITS); + ddr3_tip_read_adll_value(0, rd_ctrl_adll, CRX_PHY_REG(cs), MASK_ALL_BITS); + + /* fill memory with base pattern */ + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS); + mv_ddr_odpg_bist_prepare(pattern, ACCESS_TYPE_UNICAST, OPER_WRITE, STRESS_NONE, DURATION_SINGLE, + bist_offset, cs, pattern_table[pattern].num_of_phases_tx, + (pattern == PATTERN_00) ? DM_DIR_DIRECT : DM_DIR_INVERSE); + + for (adll_tap = 0; adll_tap < ADLL_TAPS_PER_PERIOD; adll_tap++) { + /* change target odpg address */ + odpg_addr = adll_tap * burst_len; + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_BUFFER_OFFS_REG, + odpg_addr, MASK_ALL_BITS); + + ddr3_tip_configure_odpg(0, ACCESS_TYPE_UNICAST, 0, OPER_WRITE, + pattern_table[pattern].num_of_phases_tx, + pattern_table[pattern].tx_burst_size, + pattern_table[pattern].num_of_phases_rx, + WR_OP_ODPG_DATA_CMD_BURST_DLY, + ODPG_MODE_TX, cs, STRESS_NONE, DURATION_SINGLE); + + /* odpg bist write enable */ + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG, + (ODPG_WRBUF_WR_CTRL_ENA << ODPG_WRBUF_WR_CTRL_OFFS), + (ODPG_WRBUF_WR_CTRL_MASK << ODPG_WRBUF_WR_CTRL_OFFS)); + + /* odpg bist read disable */ + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG, + (ODPG_WRBUF_RD_CTRL_DIS << ODPG_WRBUF_RD_CTRL_OFFS), + (ODPG_WRBUF_RD_CTRL_MASK << ODPG_WRBUF_RD_CTRL_OFFS)); + + /* trigger odpg */ + mv_ddr_bist_tx(ACCESS_TYPE_MULTICAST); + } + + /* fill memory with vref pattern to increment addr using odpg bist */ + mv_ddr_odpg_bist_prepare(PATTERN_VREF, ACCESS_TYPE_UNICAST, OPER_WRITE, STRESS_NONE, DURATION_SINGLE, + bist_offset, cs, pattern_table[pattern].num_of_phases_tx, + (pattern == PATTERN_00) ? DM_DIR_DIRECT : DM_DIR_INVERSE); + + for (adll_tap = 0; adll_tap < ADLL_TAPS_PER_PERIOD; adll_tap++) { + ddr3_tip_bus_write(0, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_MULTICAST, 0, + DDR_PHY_DATA, CTX_PHY_REG(cs), adll_tap); + /* change target odpg address */ + odpg_addr = adll_tap * burst_len; + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_BUFFER_OFFS_REG, + odpg_addr, MASK_ALL_BITS); + ddr3_tip_configure_odpg(0, ACCESS_TYPE_UNICAST, 0, OPER_WRITE, + pattern_table[pattern].num_of_phases_tx, + pattern_table[pattern].tx_burst_size, + pattern_table[pattern].num_of_phases_rx, + WR_OP_ODPG_DATA_CMD_BURST_DLY, + ODPG_MODE_TX, cs, STRESS_NONE, DURATION_SINGLE); + + /* odpg bist write enable */ + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG, + (ODPG_WRBUF_WR_CTRL_ENA << ODPG_WRBUF_WR_CTRL_OFFS), + (ODPG_WRBUF_WR_CTRL_MASK << ODPG_WRBUF_WR_CTRL_OFFS)); + + /* odpg bist read disable */ + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG, + (ODPG_WRBUF_RD_CTRL_DIS << ODPG_WRBUF_RD_CTRL_OFFS), + (ODPG_WRBUF_RD_CTRL_MASK << ODPG_WRBUF_RD_CTRL_OFFS)); + + /* trigger odpg */ + mv_ddr_bist_tx(ACCESS_TYPE_MULTICAST); + } + + /* restore subphy's tx adll_tap to its position */ + for (subphy = 0; subphy < subphy_max; subphy++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy); + ddr3_tip_bus_write(0, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_UNICAST, + subphy, DDR_PHY_DATA, CTX_PHY_REG(cs), + wr_ctrl_adll[subphy]); + } + + /* read and validate bist (comparing with the base pattern) */ + for (adll_tap = 0; adll_tap < ADLL_TAPS_PER_PERIOD; adll_tap++) { + result = 0; + odpg_addr = adll_tap * burst_len; + /* change addr to fit write */ + mv_ddr_pattern_start_addr_set(pattern_table, pattern, odpg_addr); + mv_ddr_tip_bist(OPER_READ, 0, pattern, 0, &result); + for (subphy = 0; subphy < subphy_max; subphy++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy); + idx = ADLL_TAPS_PER_PERIOD * subphy + adll_tap; + vw_vector[idx] |= ((result >> subphy) & 0x1); + } + } + + /* restore subphy's rx adll_tap to its position */ + for (subphy = 0; subphy < subphy_max; subphy++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy); + ddr3_tip_bus_write(0, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_UNICAST, + subphy, DDR_PHY_DATA, CRX_PHY_REG(cs), + rd_ctrl_adll[subphy]); + } + + return MV_OK; +} diff --git a/drivers/ddr/marvell/a38x/ddr3_training_centralization.c b/drivers/ddr/marvell/a38x/ddr3_training_centralization.c index 2909ae3c6f9a..e2b6534cf910 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_centralization.c +++ b/drivers/ddr/marvell/a38x/ddr3_training_centralization.c @@ -4,12 +4,6 @@ * SPDX-License-Identifier: GPL-2.0 */ -#include -#include -#include -#include -#include - #include "ddr3_init.h" #define VALIDATE_WIN_LENGTH(e1, e2, maxsize) \ @@ -23,6 +17,7 @@ #define NUM_OF_CENTRAL_TYPES 2 u32 start_pattern = PATTERN_KILLER_DQ0, end_pattern = PATTERN_KILLER_DQ7; + u32 start_if = 0, end_if = (MAX_INTERFACE_NUM - 1); u8 bus_end_window[NUM_OF_CENTRAL_TYPES][MAX_INTERFACE_NUM][MAX_BUS_NUM]; u8 bus_start_window[NUM_OF_CENTRAL_TYPES][MAX_INTERFACE_NUM][MAX_BUS_NUM]; @@ -66,7 +61,8 @@ static int ddr3_tip_centralization(u32 dev_num, u32 mode) u8 current_window[BUS_WIDTH_IN_BITS]; u8 opt_window, waste_window, start_window_skew, end_window_skew; u8 final_pup_window[MAX_INTERFACE_NUM][BUS_WIDTH_IN_BITS]; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); enum hws_training_result result_type = RESULT_PER_BIT; enum hws_dir direction; u32 *result[HWS_SEARCH_DIR_LIMIT]; @@ -82,33 +78,33 @@ static int ddr3_tip_centralization(u32 dev_num, u32 mode) u8 cons_tap = (mode == CENTRAL_TX) ? (64) : (0); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* save current cs enable reg val */ CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, cs_enable_reg_val, MASK_ALL_BITS)); + DUAL_DUNIT_CFG_REG, cs_enable_reg_val, MASK_ALL_BITS)); /* enable single cs */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, (1 << 3), (1 << 3))); + DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3))); } if (mode == CENTRAL_TX) { max_win_size = MAX_WINDOW_SIZE_TX; - reg_phy_off = WRITE_CENTRALIZATION_PHY_REG + (effective_cs * 4); + reg_phy_off = CTX_PHY_REG(effective_cs); direction = OPER_WRITE; } else { max_win_size = MAX_WINDOW_SIZE_RX; - reg_phy_off = READ_CENTRALIZATION_PHY_REG + (effective_cs * 4); + reg_phy_off = CRX_PHY_REG(effective_cs); direction = OPER_READ; } /* DB initialization */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (bus_id = 0; - bus_id < tm->num_of_bus_per_interface; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + bus_id < octets_per_if_num; bus_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); centralization_state[if_id][bus_id] = 0; bus_end_window[mode][if_id][bus_id] = (max_win_size - 1) + cons_tap; @@ -134,11 +130,11 @@ static int ddr3_tip_centralization(u32 dev_num, u32 mode) PARAM_NOT_CARE, training_result); for (if_id = start_if; if_id <= end_if; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (bus_id = 0; - bus_id <= tm->num_of_bus_per_interface - 1; + bus_id <= octets_per_if_num - 1; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); for (search_dir_id = HWS_LOW2HIGH; search_dir_id <= HWS_HIGH2LOW; @@ -337,8 +333,10 @@ static int ddr3_tip_centralization(u32 dev_num, u32 mode) [if_id][bus_id])); centralization_state[if_id] [bus_id] = 1; - if (debug_mode == 0) + if (debug_mode == 0) { + flow_result[if_id] = TEST_FAILED; return MV_FAIL; + } } } /* ddr3_tip_centr_skip_min_win_check */ } /* pup */ @@ -346,15 +344,14 @@ static int ddr3_tip_centralization(u32 dev_num, u32 mode) } /* pattern */ for (if_id = start_if; if_id <= end_if; if_id++) { - if (IS_ACTIVE(tm->if_act_mask, if_id) == 0) - continue; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); is_if_fail = 0; flow_result[if_id] = TEST_SUCCESS; for (bus_id = 0; - bus_id <= (tm->num_of_bus_per_interface - 1); bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + bus_id <= (octets_per_if_num - 1); bus_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); /* continue only if lock */ if (centralization_state[if_id][bus_id] != 1) { @@ -441,21 +438,21 @@ static int ddr3_tip_centralization(u32 dev_num, u32 mode) ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - RESULT_DB_PHY_REG_ADDR + + RESULT_PHY_REG + effective_cs, ®); reg = (reg & (~0x1f << ((mode == CENTRAL_TX) ? - (RESULT_DB_PHY_REG_TX_OFFSET) : - (RESULT_DB_PHY_REG_RX_OFFSET)))) + (RESULT_PHY_TX_OFFS) : + (RESULT_PHY_RX_OFFS)))) | pup_win_length << ((mode == CENTRAL_TX) ? - (RESULT_DB_PHY_REG_TX_OFFSET) : - (RESULT_DB_PHY_REG_RX_OFFSET)); + (RESULT_PHY_TX_OFFS) : + (RESULT_PHY_RX_OFFS)); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - RESULT_DB_PHY_REG_ADDR + + RESULT_PHY_REG + effective_cs, reg)); /* offset per CS is calculated earlier */ @@ -481,9 +478,9 @@ static int ddr3_tip_centralization(u32 dev_num, u32 mode) for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { /* restore cs enable value */ - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, - if_id, CS_ENABLE_REG, + if_id, DUAL_DUNIT_CFG_REG, cs_enable_reg_val[if_id], MASK_ALL_BITS)); } @@ -509,29 +506,30 @@ int ddr3_tip_special_rx(u32 dev_num) u32 cs_enable_reg_val[MAX_INTERFACE_NUM]; u32 temp = 0; int pad_num = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - if (ddr3_tip_special_rx_run_once_flag != 0) + if ((ddr3_tip_special_rx_run_once_flag & (1 << effective_cs)) == (1 << effective_cs)) return MV_OK; - ddr3_tip_special_rx_run_once_flag = 1; + ddr3_tip_special_rx_run_once_flag |= (1 << effective_cs); for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* save current cs enable reg val */ CHECK_STATUS(ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, - if_id, CS_ENABLE_REG, + if_id, DUAL_DUNIT_CFG_REG, cs_enable_reg_val, MASK_ALL_BITS)); /* enable single cs */ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, - if_id, CS_ENABLE_REG, + if_id, DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3))); } max_win_size = MAX_WINDOW_SIZE_RX; direction = OPER_READ; - pattern_id = PATTERN_VREF; + pattern_id = PATTERN_FULL_SSO1; /* start flow */ ddr3_tip_ip_training_wrapper(dev_num, ACCESS_TYPE_MULTICAST, @@ -545,10 +543,10 @@ int ddr3_tip_special_rx(u32 dev_num) PARAM_NOT_CARE, training_result); for (if_id = start_if; if_id <= end_if; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (pup_id = 0; - pup_id <= tm->num_of_bus_per_interface; pup_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup_id); + pup_id <= octets_per_if_num; pup_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup_id); for (search_dir_id = HWS_LOW2HIGH; search_dir_id <= HWS_HIGH2LOW; @@ -621,13 +619,12 @@ int ddr3_tip_special_rx(u32 dev_num) BUS_WIDTH_IN_BITS + if_id * BUS_WIDTH_IN_BITS * - tm-> - num_of_bus_per_interface]; + MAX_BUS_NUM]; CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, pup_id, DDR_PHY_DATA, - PBS_RX_PHY_REG + pad_num, + PBS_RX_PHY_REG(effective_cs, pad_num), &temp)); temp = (temp + 0xa > 31) ? (31) : (temp + 0xa); @@ -637,7 +634,7 @@ int ddr3_tip_special_rx(u32 dev_num) if_id, ACCESS_TYPE_UNICAST, pup_id, DDR_PHY_DATA, - PBS_RX_PHY_REG + pad_num, + PBS_RX_PHY_REG(effective_cs, pad_num), temp)); } DEBUG_CENTRALIZATION_ENGINE( @@ -650,25 +647,29 @@ int ddr3_tip_special_rx(u32 dev_num) CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, pup_id, - DDR_PHY_DATA, PBS_RX_PHY_REG + 4, + DDR_PHY_DATA, + PBS_RX_PHY_REG(effective_cs, 4), &temp)); temp += 0xa; CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, pup_id, DDR_PHY_DATA, - PBS_RX_PHY_REG + 4, temp)); + PBS_RX_PHY_REG(effective_cs, 4), + temp)); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, pup_id, - DDR_PHY_DATA, PBS_RX_PHY_REG + 5, + DDR_PHY_DATA, + PBS_RX_PHY_REG(effective_cs, 5), &temp)); temp += 0xa; CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, pup_id, DDR_PHY_DATA, - PBS_RX_PHY_REG + 5, temp)); + PBS_RX_PHY_REG(effective_cs, 5), + temp)); DEBUG_CENTRALIZATION_ENGINE( DEBUG_LEVEL_INFO, ("Special: PBS:: I/F# %d , Bus# %d fix align to the right\n", @@ -695,15 +696,16 @@ int ddr3_tip_special_rx(u32 dev_num) int ddr3_tip_print_centralization_result(u32 dev_num) { u32 if_id = 0, bus_id = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); printf("Centralization Results\n"); printf("I/F0 Result[0 - success 1-fail 2 - state_2 3 - state_3] ...\n"); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); printf("%d ,\n", centralization_state[if_id][bus_id]); } } diff --git a/drivers/ddr/marvell/a38x/ddr3_training_db.c b/drivers/ddr/marvell/a38x/ddr3_training_db.c index 0e11b434ab67..0681eabc9992 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_db.c +++ b/drivers/ddr/marvell/a38x/ddr3_training_db.c @@ -4,16 +4,25 @@ * SPDX-License-Identifier: GPL-2.0 */ -#include -#include -#include -#include -#include - #include "ddr3_init.h" +/* Device attributes structures */ +enum mv_ddr_dev_attribute ddr_dev_attributes[MAX_DEVICE_NUM][MV_ATTR_LAST]; +int ddr_dev_attr_init_done[MAX_DEVICE_NUM] = { 0 }; + +static inline u32 pattern_table_get_killer_word16(u8 dqs, u8 index); +static inline u32 pattern_table_get_sso_word(u8 sso, u8 index); +static inline u32 pattern_table_get_vref_word(u8 index); +static inline u32 pattern_table_get_vref_word16(u8 index); +static inline u32 pattern_table_get_sso_full_xtalk_word(u8 bit, u8 index); +static inline u32 pattern_table_get_sso_full_xtalk_word16(u8 bit, u8 index); +static inline u32 pattern_table_get_sso_xtalk_free_word(u8 bit, u8 index); +static inline u32 pattern_table_get_sso_xtalk_free_word16(u8 bit, u8 index); +static inline u32 pattern_table_get_isi_word(u8 index); +static inline u32 pattern_table_get_isi_word16(u8 index); + /* List of allowed frequency listed in order of enum hws_ddr_freq */ -u32 freq_val[DDR_FREQ_LIMIT] = { +u32 freq_val[DDR_FREQ_LAST] = { 0, /*DDR_FREQ_LOW_FREQ */ 400, /*DDR_FREQ_400, */ 533, /*DDR_FREQ_533, */ @@ -152,18 +161,18 @@ u8 twr_mask_table[] = { 10, 10, 10, - 1, /*5*/ - 2, /*6*/ - 3, /*7*/ - 4, /*8*/ + 1, /* 5 */ + 2, /* 6 */ + 3, /* 7 */ + 4, /* 8 */ 10, - 5, /*10*/ + 5, /* 10 */ 10, - 6, /*12*/ + 6, /* 12 */ 10, - 7, /*14*/ + 7, /* 14 */ 10, - 0 /*16*/ + 0 /* 16 */ }; u8 cl_mask_table[] = { @@ -210,7 +219,11 @@ u16 rfc_table[] = { 110, /* 1G */ 160, /* 2G */ 260, /* 4G */ - 350 /* 8G */ + 350, /* 8G */ + 0, /* TODO: placeholder for 16-Mbit dev width */ + 0, /* TODO: placeholder for 32-Mbit dev width */ + 0, /* TODO: placeholder for 12-Mbit dev width */ + 0 /* TODO: placeholder for 24-Mbit dev width */ }; u32 speed_bin_table_t_rc[] = { @@ -234,7 +247,7 @@ u32 speed_bin_table_t_rc[] = { 43285, 44220, 45155, - 46900 + 46090 }; u32 speed_bin_table_t_rcd_t_rp[] = { @@ -256,7 +269,7 @@ u32 speed_bin_table_t_rcd_t_rp[] = { 12840, 13910, 10285, - 11022, + 11220, 12155, 13090, }; @@ -357,13 +370,13 @@ u32 speed_bin_table(u8 index, enum speed_bin_table_elements element) result = speed_bin_table_t_rcd_t_rp[index]; break; case SPEED_BIN_TRAS: - if (index < 6) + if (index < SPEED_BIN_DDR_1066G) result = 37500; - else if (index < 10) + else if (index < SPEED_BIN_DDR_1333J) result = 36000; - else if (index < 14) + else if (index < SPEED_BIN_DDR_1600K) result = 35000; - else if (index < 18) + else if (index < SPEED_BIN_DDR_1866M) result = 34000; else result = 33000; @@ -372,49 +385,49 @@ u32 speed_bin_table(u8 index, enum speed_bin_table_elements element) result = speed_bin_table_t_rc[index]; break; case SPEED_BIN_TRRD1K: - if (index < 3) + if (index < SPEED_BIN_DDR_800E) result = 10000; - else if (index < 6) - result = 7005; - else if (index < 14) + else if (index < SPEED_BIN_DDR_1066G) + result = 7500; + else if (index < SPEED_BIN_DDR_1600K) result = 6000; else result = 5000; break; case SPEED_BIN_TRRD2K: - if (index < 6) + if (index < SPEED_BIN_DDR_1066G) result = 10000; - else if (index < 14) - result = 7005; + else if (index < SPEED_BIN_DDR_1600K) + result = 7500; else result = 6000; break; case SPEED_BIN_TPD: - if (index < 3) + if (index < SPEED_BIN_DDR_800E) result = 7500; - else if (index < 10) + else if (index < SPEED_BIN_DDR_1333J) result = 5625; else result = 5000; break; case SPEED_BIN_TFAW1K: - if (index < 3) + if (index < SPEED_BIN_DDR_800E) result = 40000; - else if (index < 6) + else if (index < SPEED_BIN_DDR_1066G) result = 37500; - else if (index < 14) + else if (index < SPEED_BIN_DDR_1600K) result = 30000; - else if (index < 18) + else if (index < SPEED_BIN_DDR_1866M) result = 27000; else result = 25000; break; case SPEED_BIN_TFAW2K: - if (index < 6) + if (index < SPEED_BIN_DDR_1066G) result = 50000; - else if (index < 10) + else if (index < SPEED_BIN_DDR_1333J) result = 45000; - else if (index < 14) + else if (index < SPEED_BIN_DDR_1600K) result = 40000; else result = 35000; @@ -466,14 +479,7 @@ static inline u32 pattern_table_get_killer_word16(u8 dqs, u8 index) (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) : (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM); byte0 |= pattern_killer_pattern_table_map[index * 2][role] << i; - } - - for (i = 0; i < 8; i++) { - role = (i == dqs) ? - (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) : - (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM); - byte1 |= pattern_killer_pattern_table_map - [index * 2 + 1][role] << i; + byte1 |= pattern_killer_pattern_table_map[index * 2 + 1][role] << i; } return byte0 | (byte0 << 8) | (byte1 << 16) | (byte1 << 24); @@ -489,6 +495,79 @@ static inline u32 pattern_table_get_sso_word(u8 sso, u8 index) return 0xffffffff; } +static inline u32 pattern_table_get_sso_full_xtalk_word(u8 bit, u8 index) +{ + u8 byte = (1 << bit); + + if ((index & 1) == 1) + byte = ~byte; + + return byte | (byte << 8) | (byte << 16) | (byte << 24); + +} + +static inline u32 pattern_table_get_sso_xtalk_free_word(u8 bit, u8 index) +{ + u8 byte = (1 << bit); + + if ((index & 1) == 1) + byte = 0; + + return byte | (byte << 8) | (byte << 16) | (byte << 24); +} + +static inline u32 pattern_table_get_isi_word(u8 index) +{ + u8 i0 = index % 32; + u8 i1 = index % 8; + u32 word; + + if (i0 > 15) + word = ((i1 == 5) | (i1 == 7)) ? 0xffffffff : 0x0; + else + word = (i1 == 6) ? 0xffffffff : 0x0; + + word = ((i0 % 16) > 7) ? ~word : word; + + return word; +} + +static inline u32 pattern_table_get_sso_full_xtalk_word16(u8 bit, u8 index) +{ + u8 byte = (1 << bit); + + if ((index & 1) == 1) + byte = ~byte; + + return byte | (byte << 8) | ((~byte) << 16) | ((~byte) << 24); +} + +static inline u32 pattern_table_get_sso_xtalk_free_word16(u8 bit, u8 index) +{ + u8 byte = (1 << bit); + + if ((index & 1) == 0) + return (byte << 16) | (byte << 24); + else + return byte | (byte << 8); +} + +static inline u32 pattern_table_get_isi_word16(u8 index) +{ + u8 i0 = index % 16; + u8 i1 = index % 4; + u32 word; + + if (i0 > 7) + word = (i1 > 1) ? 0x0000ffff : 0x0; + else + word = (i1 == 3) ? 0xffff0000 : 0x0; + + word = ((i0 % 8) > 3) ? ~word : word; + + return word; +} + static inline u32 pattern_table_get_vref_word(u8 index) { if (0 == ((pattern_vref_pattern_table_map[index / 8] >> @@ -528,13 +607,13 @@ static inline u32 pattern_table_get_static_pbs_word(u8 index) return temp | (temp << 8) | (temp << 16) | (temp << 24); } -inline u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index) +u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index) { u32 pattern; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0) { - /* 32bit patterns */ + /* 32/64-bit patterns */ switch (type) { case PATTERN_PBS1: case PATTERN_PBS2: @@ -578,9 +657,9 @@ inline u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index) break; case PATTERN_TEST: if (index > 1 && index < 6) - pattern = PATTERN_20; - else pattern = PATTERN_00; + else + pattern = PATTERN_FF; break; case PATTERN_FULL_SSO0: case PATTERN_FULL_SSO1: @@ -592,7 +671,34 @@ inline u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index) case PATTERN_VREF: pattern = pattern_table_get_vref_word(index); break; + case PATTERN_SSO_FULL_XTALK_DQ0: + case PATTERN_SSO_FULL_XTALK_DQ1: + case PATTERN_SSO_FULL_XTALK_DQ2: + case PATTERN_SSO_FULL_XTALK_DQ3: + case PATTERN_SSO_FULL_XTALK_DQ4: + case PATTERN_SSO_FULL_XTALK_DQ5: + case PATTERN_SSO_FULL_XTALK_DQ6: + case PATTERN_SSO_FULL_XTALK_DQ7: + pattern = pattern_table_get_sso_full_xtalk_word( + (u8)(type - PATTERN_SSO_FULL_XTALK_DQ0), index); + break; + case PATTERN_SSO_XTALK_FREE_DQ0: + case PATTERN_SSO_XTALK_FREE_DQ1: + case PATTERN_SSO_XTALK_FREE_DQ2: + case PATTERN_SSO_XTALK_FREE_DQ3: + case PATTERN_SSO_XTALK_FREE_DQ4: + case PATTERN_SSO_XTALK_FREE_DQ5: + case PATTERN_SSO_XTALK_FREE_DQ6: + case PATTERN_SSO_XTALK_FREE_DQ7: + pattern = pattern_table_get_sso_xtalk_free_word( + (u8)(type - PATTERN_SSO_XTALK_FREE_DQ0), index); + break; + case PATTERN_ISI_XTALK_FREE: + pattern = pattern_table_get_isi_word(index); + break; default: + DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("Error: %s: pattern type [%d] not supported\n", + __func__, (int)type)); pattern = 0; break; } @@ -631,7 +737,10 @@ inline u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index) pattern = PATTERN_01; break; case PATTERN_TEST: - pattern = PATTERN_0080; + if ((index == 0) || (index == 3)) + pattern = 0x00000000; + else + pattern = 0xFFFFFFFF; break; case PATTERN_FULL_SSO0: pattern = 0x0000ffff; @@ -645,7 +754,34 @@ inline u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index) case PATTERN_VREF: pattern = pattern_table_get_vref_word16(index); break; + case PATTERN_SSO_FULL_XTALK_DQ0: + case PATTERN_SSO_FULL_XTALK_DQ1: + case PATTERN_SSO_FULL_XTALK_DQ2: + case PATTERN_SSO_FULL_XTALK_DQ3: + case PATTERN_SSO_FULL_XTALK_DQ4: + case PATTERN_SSO_FULL_XTALK_DQ5: + case PATTERN_SSO_FULL_XTALK_DQ6: + case PATTERN_SSO_FULL_XTALK_DQ7: + pattern = pattern_table_get_sso_full_xtalk_word16( + (u8)(type - PATTERN_SSO_FULL_XTALK_DQ0), index); + break; + case PATTERN_SSO_XTALK_FREE_DQ0: + case PATTERN_SSO_XTALK_FREE_DQ1: + case PATTERN_SSO_XTALK_FREE_DQ2: + case PATTERN_SSO_XTALK_FREE_DQ3: + case PATTERN_SSO_XTALK_FREE_DQ4: + case PATTERN_SSO_XTALK_FREE_DQ5: + case PATTERN_SSO_XTALK_FREE_DQ6: + case PATTERN_SSO_XTALK_FREE_DQ7: + pattern = pattern_table_get_sso_xtalk_free_word16( + (u8)(type - PATTERN_SSO_XTALK_FREE_DQ0), index); + break; + case PATTERN_ISI_XTALK_FREE: + pattern = pattern_table_get_isi_word16(index); + break; default: + DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("Error: %s: pattern type [%d] not supported\n", + __func__, (int)type)); pattern = 0; break; } @@ -653,3 +789,30 @@ inline u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index) return pattern; } + +/* Device attribute functions */ +void ddr3_tip_dev_attr_init(u32 dev_num) +{ + u32 attr_id; + + for (attr_id = 0; attr_id < MV_ATTR_LAST; attr_id++) + ddr_dev_attributes[dev_num][attr_id] = 0xFF; + + ddr_dev_attr_init_done[dev_num] = 1; +} + +u32 ddr3_tip_dev_attr_get(u32 dev_num, enum mv_ddr_dev_attribute attr_id) +{ + if (ddr_dev_attr_init_done[dev_num] == 0) + ddr3_tip_dev_attr_init(dev_num); + + return ddr_dev_attributes[dev_num][attr_id]; +} + +void ddr3_tip_dev_attr_set(u32 dev_num, enum mv_ddr_dev_attribute attr_id, u32 value) +{ + if (ddr_dev_attr_init_done[dev_num] == 0) + ddr3_tip_dev_attr_init(dev_num); + + ddr_dev_attributes[dev_num][attr_id] = value; +} diff --git a/drivers/ddr/marvell/a38x/ddr3_training_hw_algo.c b/drivers/ddr/marvell/a38x/ddr3_training_hw_algo.c index 1fc173b60020..01da98399ae3 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_hw_algo.c +++ b/drivers/ddr/marvell/a38x/ddr3_training_hw_algo.c @@ -4,12 +4,6 @@ * SPDX-License-Identifier: GPL-2.0 */ -#include -#include -#include -#include -#include - #include "ddr3_init.h" #define VREF_INITIAL_STEP 3 @@ -17,9 +11,8 @@ #define VREF_MAX_INDEX 7 #define MAX_VALUE (1024 - 1) #define MIN_VALUE (-MAX_VALUE) -#define GET_RD_SAMPLE_DELAY(data, cs) ((data >> rd_sample_mask[cs]) & 0x1f) +#define GET_RD_SAMPLE_DELAY(data, cs) ((data >> rd_sample_mask[cs]) & 0xf) -u32 ck_delay = (u32)-1, ck_delay_16 = (u32)-1; u32 ca_delay; int ddr3_tip_centr_skip_min_win_check = 0; u8 current_vref[MAX_BUS_NUM][MAX_INTERFACE_NUM]; @@ -49,45 +42,41 @@ static u32 rd_sample_mask[] = { */ int ddr3_tip_write_additional_odt_setting(u32 dev_num, u32 if_id) { - u32 cs_num = 0, max_cs = 0, max_read_sample = 0, min_read_sample = 0x1f; + u32 cs_num = 0, max_read_sample = 0, min_read_sample = 0x1f; u32 data_read[MAX_INTERFACE_NUM] = { 0 }; u32 read_sample[MAX_CS_NUM]; u32 val; u32 pup_index; int max_phase = MIN_VALUE, current_phase; enum hws_access_type access_type = ACCESS_TYPE_UNICAST; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - DUNIT_ODT_CONTROL_REG, + DUNIT_ODT_CTRL_REG, 0 << 8, 0x3 << 8)); CHECK_STATUS(ddr3_tip_if_read(dev_num, access_type, if_id, - READ_DATA_SAMPLE_DELAY, + RD_DATA_SMPL_DLYS_REG, data_read, MASK_ALL_BITS)); val = data_read[if_id]; - max_cs = hws_ddr3_tip_max_cs_get(); - - for (cs_num = 0; cs_num < max_cs; cs_num++) { + for (cs_num = 0; cs_num < MAX_CS_NUM; cs_num++) { read_sample[cs_num] = GET_RD_SAMPLE_DELAY(val, cs_num); /* find maximum of read_samples */ if (read_sample[cs_num] >= max_read_sample) { - if (read_sample[cs_num] == max_read_sample) { - /* search for max phase */; - } else { - max_read_sample = read_sample[cs_num]; + if (read_sample[cs_num] == max_read_sample) max_phase = MIN_VALUE; - } + else + max_read_sample = read_sample[cs_num]; for (pup_index = 0; - pup_index < tm->num_of_bus_per_interface; + pup_index < octets_per_if_num; pup_index++) { CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, pup_index, DDR_PHY_DATA, - RL_PHY_REG + CS_REG_VALUE(cs_num), + RL_PHY_REG(cs_num), &val)); current_phase = ((int)val & 0xe0) >> 6; @@ -101,21 +90,19 @@ int ddr3_tip_write_additional_odt_setting(u32 dev_num, u32 if_id) min_read_sample = read_sample[cs_num]; } - if (min_read_sample <= tm->interface_params[if_id].cas_l) { - min_read_sample = (int)tm->interface_params[if_id].cas_l; - } - min_read_sample = min_read_sample - 1; max_read_sample = max_read_sample + 4 + (max_phase + 1) / 2 + 1; + if (min_read_sample >= 0xf) + min_read_sample = 0xf; if (max_read_sample >= 0x1f) max_read_sample = 0x1f; CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - ODT_TIMING_LOW, + DDR_ODT_TIMING_LOW_REG, ((min_read_sample - 1) << 12), 0xf << 12)); CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - ODT_TIMING_LOW, + DDR_ODT_TIMING_LOW_REG, (max_read_sample << 16), 0x1f << 16)); @@ -124,7 +111,7 @@ int ddr3_tip_write_additional_odt_setting(u32 dev_num, u32 if_id) int get_valid_win_rx(u32 dev_num, u32 if_id, u8 res[4]) { - u32 reg_pup = RESULT_DB_PHY_REG_ADDR; + u32 reg_pup = RESULT_PHY_REG; u32 reg_data; u32 cs_num; int i; @@ -139,7 +126,7 @@ int get_valid_win_rx(u32 dev_num, u32 if_id, u8 res[4]) ACCESS_TYPE_UNICAST, i, DDR_PHY_DATA, reg_pup, ®_data)); - res[i] = (reg_data >> RESULT_DB_PHY_REG_RX_OFFSET) & 0x1f; + res[i] = (reg_data >> RESULT_PHY_RX_OFFS) & 0x1f; } return 0; @@ -177,7 +164,8 @@ int ddr3_tip_vref(u32 dev_num) u32 copy_start_pattern, copy_end_pattern; enum hws_result *flow_result = ddr3_tip_get_result_ptr(training_stage); u8 res[4]; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); CHECK_STATUS(ddr3_tip_special_rx(dev_num)); @@ -191,9 +179,9 @@ int ddr3_tip_vref(u32 dev_num) /* init params */ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (pup = 0; - pup < tm->num_of_bus_per_interface; pup++) { + pup < octets_per_if_num; pup++) { current_vref[pup][if_id] = 0; last_vref[pup][if_id] = 0; lim_vref[pup][if_id] = 0; @@ -229,7 +217,7 @@ int ddr3_tip_vref(u32 dev_num) } /* TODO: Set number of active interfaces */ - num_pup = tm->num_of_bus_per_interface * MAX_INTERFACE_NUM; + num_pup = octets_per_if_num * MAX_INTERFACE_NUM; while ((algo_run_flag <= num_pup) & (while_count < 10)) { while_count++; @@ -240,13 +228,13 @@ int ddr3_tip_vref(u32 dev_num) /* Read Valid window results only for non converge pups */ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (interface_state[if_id] != 4) { get_valid_win_rx(dev_num, if_id, res); for (pup = 0; - pup < tm->num_of_bus_per_interface; + pup < octets_per_if_num; pup++) { - VALIDATE_ACTIVE + VALIDATE_BUS_ACTIVE (tm->bus_act_mask, pup); if (pup_st[pup] [if_id] == @@ -264,14 +252,14 @@ int ddr3_tip_vref(u32 dev_num) } for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); DEBUG_TRAINING_HW_ALG( DEBUG_LEVEL_TRACE, ("current_valid_window: IF[ %d ] - ", if_id)); for (pup = 0; - pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE, ("%d ", current_valid_window @@ -282,10 +270,10 @@ int ddr3_tip_vref(u32 dev_num) /* Compare results and respond as function of state */ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (pup = 0; - pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE, ("I/F[ %d ], pup[ %d ] STATE #%d (%d)\n", if_id, pup, @@ -610,10 +598,10 @@ int ddr3_tip_vref(u32 dev_num) } for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (pup = 0; - pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, pup, @@ -641,7 +629,7 @@ int ddr3_tip_cmd_addr_init_delay(u32 dev_num, u32 adll_tap) { u32 if_id = 0; u32 ck_num_adll_tap = 0, ca_num_adll_tap = 0, data = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* * ck_delay_table is delaying the of the clock signal only. @@ -654,22 +642,18 @@ int ddr3_tip_cmd_addr_init_delay(u32 dev_num, u32 adll_tap) */ /* Calc ADLL Tap */ - if ((ck_delay == -1) || (ck_delay_16 == -1)) { + if (ck_delay == PARAM_UNDEFINED) DEBUG_TRAINING_HW_ALG( DEBUG_LEVEL_ERROR, - ("ERROR: One of ck_delay values not initialized!!!\n")); - } + ("ERROR: ck_delay is not initialized!\n")); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - /* Calc delay ps in ADLL tap */ - if (tm->interface_params[if_id].bus_width == - BUS_WIDTH_16) - ck_num_adll_tap = ck_delay_16 / adll_tap; - else - ck_num_adll_tap = ck_delay / adll_tap; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + /* Calc delay ps in ADLL tap */ + ck_num_adll_tap = ck_delay / adll_tap; ca_num_adll_tap = ca_delay / adll_tap; + data = (ck_num_adll_tap & 0x3f) + ((ca_num_adll_tap & 0x3f) << 10); diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip.h b/drivers/ddr/marvell/a38x/ddr3_training_ip.h index ed92873697e3..a14ce63eef32 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip.h +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip.h @@ -11,11 +11,10 @@ #include "ddr_topology_def.h" #include "ddr_training_ip_db.h" -#define DDR3_TIP_VERSION_STRING "DDR3 Training Sequence - Ver TIP-1.29." - #define MAX_CS_NUM 4 #define MAX_TOTAL_BUS_NUM (MAX_INTERFACE_NUM * MAX_BUS_NUM) -#define MAX_DQ_NUM 40 +#define TIP_ENG_LOCK 0x02000000 +#define TIP_TX_DLL_RANGE_MAX 64 #define GET_MIN(arg1, arg2) ((arg1) < (arg2)) ? (arg1) : (arg2) #define GET_MAX(arg1, arg2) ((arg1) < (arg2)) ? (arg2) : (arg1) @@ -39,11 +38,15 @@ #define READ_LEVELING_TF_MASK_BIT 0x00010000 #define WRITE_LEVELING_SUPP_TF_MASK_BIT 0x00020000 #define DM_PBS_TX_MASK_BIT 0x00040000 +#define RL_DQS_BURST_MASK_BIT 0x00080000 #define CENTRALIZATION_RX_MASK_BIT 0x00100000 #define CENTRALIZATION_TX_MASK_BIT 0x00200000 #define TX_EMPHASIS_MASK_BIT 0x00400000 #define PER_BIT_READ_LEVELING_TF_MASK_BIT 0x00800000 #define VREF_CALIBRATION_MASK_BIT 0x01000000 +#define WRITE_LEVELING_LF_MASK_BIT 0x02000000 + +/* DDR4 Specific Training Mask bits */ enum hws_result { TEST_FAILED = 0, @@ -80,6 +83,7 @@ enum auto_tune_stage { TX_EMPHASIS, LOAD_PATTERN_HIGH, PER_BIT_READ_LEVELING_TF, + WRITE_LEVELING_LF, MAX_STAGE_LIMIT }; @@ -111,7 +115,7 @@ struct pattern_info { /* CL value for each frequency */ struct cl_val_per_freq { - u8 cl_val[DDR_FREQ_LIMIT]; + u8 cl_val[DDR_FREQ_LAST]; }; struct cs_element { @@ -168,11 +172,14 @@ int hws_ddr3_tip_select_ddr_controller(u32 dev_num, int enable); int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_prm); int hws_ddr3_tip_load_topology_map(u32 dev_num, - struct hws_topology_map *topology); + struct mv_ddr_topology_map *topology); int hws_ddr3_tip_run_alg(u32 dev_num, enum hws_algo_type algo_type); int hws_ddr3_tip_mode_read(u32 dev_num, struct mode_info *mode_info); +int hws_ddr3_tip_read_training_result(u32 dev_num, + enum hws_result result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM]); int ddr3_tip_is_pup_lock(u32 *pup_buf, enum hws_training_result read_mode); u8 ddr3_tip_get_buf_min(u8 *buf_ptr); u8 ddr3_tip_get_buf_max(u8 *buf_ptr); - +uint64_t mv_ddr_get_memory_size_per_cs_in_bits(void); +uint64_t mv_ddr_get_total_memory_size_in_bits(void); #endif /* _DDR3_TRAINING_IP_H_ */ diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_bist.h b/drivers/ddr/marvell/a38x/ddr3_training_ip_bist.h index 5c9bfe98a096..856b49839465 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip_bist.h +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_bist.h @@ -46,9 +46,13 @@ int hws_ddr3_run_bist(u32 dev_num, enum hws_pattern pattern, u32 *result, u32 cs_num); int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, u32 mode); +int ddr3_tip_run_leveling_sweep_test(int dev_num, u32 repeat_num, + u32 direction, u32 mode); int ddr3_tip_print_regs(u32 dev_num); int ddr3_tip_reg_dump(u32 dev_num); int run_xsb_test(u32 dev_num, u32 mem_addr, u32 write_type, u32 read_type, u32 burst_length); - +int mv_ddr_dm_to_dq_diff_get(u8 adll_byte_high, u8 adll_byte_low, u8 *vw_vector, + int *delta_h_adll, int *delta_l_adll); +int mv_ddr_dm_vw_get(enum hws_pattern pattern, u32 cs, u8 *vw_vector); #endif /* _DDR3_TRAINING_IP_BIST_H_ */ diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_db.h b/drivers/ddr/marvell/a38x/ddr3_training_ip_db.h index c0afa7742e94..55ae907ecb78 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip_db.h +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_db.h @@ -10,7 +10,10 @@ enum hws_pattern { PATTERN_PBS1, PATTERN_PBS2, + PATTERN_PBS3, + PATTERN_TEST, PATTERN_RL, + PATTERN_RL2, PATTERN_STATIC_PBS, PATTERN_KILLER_DQ0, PATTERN_KILLER_DQ1, @@ -20,15 +23,73 @@ enum hws_pattern { PATTERN_KILLER_DQ5, PATTERN_KILLER_DQ6, PATTERN_KILLER_DQ7, - PATTERN_PBS3, - PATTERN_RL2, - PATTERN_TEST, + PATTERN_VREF, PATTERN_FULL_SSO0, PATTERN_FULL_SSO1, PATTERN_FULL_SSO2, PATTERN_FULL_SSO3, - PATTERN_VREF, - PATTERN_LIMIT + PATTERN_LAST, + PATTERN_SSO_FULL_XTALK_DQ0, + PATTERN_SSO_FULL_XTALK_DQ1, + PATTERN_SSO_FULL_XTALK_DQ2, + PATTERN_SSO_FULL_XTALK_DQ3, + PATTERN_SSO_FULL_XTALK_DQ4, + PATTERN_SSO_FULL_XTALK_DQ5, + PATTERN_SSO_FULL_XTALK_DQ6, + PATTERN_SSO_FULL_XTALK_DQ7, + PATTERN_SSO_XTALK_FREE_DQ0, + PATTERN_SSO_XTALK_FREE_DQ1, + PATTERN_SSO_XTALK_FREE_DQ2, + PATTERN_SSO_XTALK_FREE_DQ3, + PATTERN_SSO_XTALK_FREE_DQ4, + PATTERN_SSO_XTALK_FREE_DQ5, + PATTERN_SSO_XTALK_FREE_DQ6, + PATTERN_SSO_XTALK_FREE_DQ7, + PATTERN_ISI_XTALK_FREE }; +enum mv_wl_supp_mode { + WRITE_LEVELING_SUPP_REG_MODE, + WRITE_LEVELING_SUPP_ECC_MODE_DATA_PUPS, + WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP4, + WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP3, + WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP8 +}; + +enum mv_ddr_dev_attribute { + MV_ATTR_TIP_REV, + MV_ATTR_PHY_EDGE, + MV_ATTR_OCTET_PER_INTERFACE, + MV_ATTR_PLL_BEFORE_INIT, + MV_ATTR_TUNE_MASK, + MV_ATTR_INIT_FREQ, + MV_ATTR_MID_FREQ, + MV_ATTR_DFS_LOW_FREQ, + MV_ATTR_DFS_LOW_PHY, + MV_ATTR_DELAY_ENABLE, + MV_ATTR_CK_DELAY, + MV_ATTR_CA_DELAY, + MV_ATTR_INTERLEAVE_WA, + MV_ATTR_LAST +}; + +enum mv_ddr_tip_revison { + MV_TIP_REV_NA, + MV_TIP_REV_1, /* NP5 */ + MV_TIP_REV_2, /* BC2 */ + MV_TIP_REV_3, /* AC3 */ + MV_TIP_REV_4, /* A-380/A-390 */ + MV_TIP_REV_LAST +}; + +enum mv_ddr_phy_edge { + MV_DDR_PHY_EDGE_POSITIVE, + MV_DDR_PHY_EDGE_NEGATIVE +}; + +/* Device attribute functions */ +void ddr3_tip_dev_attr_init(u32 dev_num); +u32 ddr3_tip_dev_attr_get(u32 dev_num, enum mv_ddr_dev_attribute attr_id); +void ddr3_tip_dev_attr_set(u32 dev_num, enum mv_ddr_dev_attribute attr_id, u32 value); + #endif /* _DDR3_TRAINING_IP_DB_H_ */ diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_def.h b/drivers/ddr/marvell/a38x/ddr3_training_ip_def.h index 51a66d8491a2..731d1e896bd4 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip_def.h +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_def.h @@ -7,8 +7,6 @@ #ifndef _DDR3_TRAINING_IP_DEF_H #define _DDR3_TRAINING_IP_DEF_H -#include "silicon_if.h" - #define PATTERN_55 0x55555555 #define PATTERN_AA 0xaaaaaaaa #define PATTERN_80 0x80808080 @@ -36,6 +34,7 @@ #define ADLL_RX_LENGTH 32 #define PARAM_NOT_CARE 0 +#define PARAM_UNDEFINED 0xffffffff #define READ_LEVELING_PHY_OFFSET 2 #define WRITE_LEVELING_PHY_OFFSET 0 @@ -100,6 +99,8 @@ #define _1G 0x40000000 #define _2G 0x80000000 +#define _4G 0x100000000 +#define _8G 0x200000000 #define ADDR_SIZE_512MB 0x04000000 #define ADDR_SIZE_1GB 0x08000000 @@ -164,10 +165,33 @@ enum hws_wl_supp { ALIGN_SHIFT }; +enum mv_ddr_tip_bit_state { + BIT_LOW_UI, + BIT_HIGH_UI, + BIT_SPLIT_IN, + BIT_SPLIT_OUT, + BIT_STATE_LAST +}; + +enum mv_ddr_tip_byte_state{ + BYTE_NOT_DEFINED, + BYTE_HOMOGENEOUS_LOW = 0x1, + BYTE_HOMOGENEOUS_HIGH = 0x2, + BYTE_HOMOGENEOUS_SPLIT_IN = 0x4, + BYTE_HOMOGENEOUS_SPLIT_OUT = 0x8, + BYTE_SPLIT_OUT_MIX = 0x10, + BYTE_STATE_LAST +}; + struct reg_data { - u32 reg_addr; - u32 reg_data; - u32 reg_mask; + unsigned int reg_addr; + unsigned int reg_data; + unsigned int reg_mask; +}; + +enum dm_direction { + DM_DIR_INVERSE, + DM_DIR_DIRECT }; #endif /* _DDR3_TRAINING_IP_DEF_H */ diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c b/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c index 011824ab42a1..855025953f4e 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c @@ -4,12 +4,6 @@ * SPDX-License-Identifier: GPL-2.0 */ -#include -#include -#include -#include -#include - #include "ddr3_init.h" #define PATTERN_1 0x55555555 @@ -22,6 +16,7 @@ u32 phy_reg_bk[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS]; u32 training_res[MAX_INTERFACE_NUM * MAX_BUS_NUM * BUS_WIDTH_IN_BITS * HWS_SEARCH_DIR_LIMIT]; +u8 byte_status[MAX_INTERFACE_NUM][MAX_BUS_NUM]; /* holds the bit status in the byte in wrapper function*/ u16 mask_results_dq_reg_map[] = { RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG, @@ -44,14 +39,39 @@ u16 mask_results_dq_reg_map[] = { RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG, RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG, RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG, +#if MAX_BUS_NUM == 9 + RESULT_CONTROL_PUP_5_BIT_0_REG, RESULT_CONTROL_PUP_5_BIT_1_REG, + RESULT_CONTROL_PUP_5_BIT_2_REG, RESULT_CONTROL_PUP_5_BIT_3_REG, + RESULT_CONTROL_PUP_5_BIT_4_REG, RESULT_CONTROL_PUP_5_BIT_5_REG, + RESULT_CONTROL_PUP_5_BIT_6_REG, RESULT_CONTROL_PUP_5_BIT_7_REG, + RESULT_CONTROL_PUP_6_BIT_0_REG, RESULT_CONTROL_PUP_6_BIT_1_REG, + RESULT_CONTROL_PUP_6_BIT_2_REG, RESULT_CONTROL_PUP_6_BIT_3_REG, + RESULT_CONTROL_PUP_6_BIT_4_REG, RESULT_CONTROL_PUP_6_BIT_5_REG, + RESULT_CONTROL_PUP_6_BIT_6_REG, RESULT_CONTROL_PUP_6_BIT_7_REG, + RESULT_CONTROL_PUP_7_BIT_0_REG, RESULT_CONTROL_PUP_7_BIT_1_REG, + RESULT_CONTROL_PUP_7_BIT_2_REG, RESULT_CONTROL_PUP_7_BIT_3_REG, + RESULT_CONTROL_PUP_7_BIT_4_REG, RESULT_CONTROL_PUP_7_BIT_5_REG, + RESULT_CONTROL_PUP_7_BIT_6_REG, RESULT_CONTROL_PUP_7_BIT_7_REG, + RESULT_CONTROL_PUP_8_BIT_0_REG, RESULT_CONTROL_PUP_8_BIT_1_REG, + RESULT_CONTROL_PUP_8_BIT_2_REG, RESULT_CONTROL_PUP_8_BIT_3_REG, + RESULT_CONTROL_PUP_8_BIT_4_REG, RESULT_CONTROL_PUP_8_BIT_5_REG, + RESULT_CONTROL_PUP_8_BIT_6_REG, RESULT_CONTROL_PUP_8_BIT_7_REG, +#endif + 0xffff }; u16 mask_results_pup_reg_map[] = { RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG, RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_3_REG, - RESULT_CONTROL_BYTE_PUP_4_REG + RESULT_CONTROL_BYTE_PUP_4_REG, +#if MAX_BUS_NUM == 9 + RESULT_CONTROL_BYTE_PUP_5_REG, RESULT_CONTROL_BYTE_PUP_6_REG, + RESULT_CONTROL_BYTE_PUP_7_REG, RESULT_CONTROL_BYTE_PUP_8_REG, +#endif + 0xffff }; +#if MAX_BUS_NUM == 5 u16 mask_results_dq_reg_map_pup3_ecc[] = { RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG, RESULT_CONTROL_PUP_0_BIT_2_REG, RESULT_CONTROL_PUP_0_BIT_3_REG, @@ -69,17 +89,120 @@ u16 mask_results_dq_reg_map_pup3_ecc[] = { RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG, RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG, RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG, - RESULT_CONTROL_PUP_4_BIT_0_REG, RESULT_CONTROL_PUP_4_BIT_1_REG, - RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG, - RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG, - RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG, + RESULT_CONTROL_PUP_3_BIT_0_REG, RESULT_CONTROL_PUP_3_BIT_1_REG, + RESULT_CONTROL_PUP_3_BIT_2_REG, RESULT_CONTROL_PUP_3_BIT_3_REG, + RESULT_CONTROL_PUP_3_BIT_4_REG, RESULT_CONTROL_PUP_3_BIT_5_REG, + RESULT_CONTROL_PUP_3_BIT_6_REG, RESULT_CONTROL_PUP_3_BIT_7_REG }; +#endif +#if MAX_BUS_NUM == 5 u16 mask_results_pup_reg_map_pup3_ecc[] = { RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG, RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_4_REG, RESULT_CONTROL_BYTE_PUP_4_REG }; +#endif + +struct pattern_info pattern_table_64[] = { + /* + * num_of_phases_tx, tx_burst_size; + * delay_between_bursts, num_of_phases_rx, + * start_addr, pattern_len + */ + {0x7, 0x7, 2, 0x7, 0x00000, 8}, /* PATTERN_PBS1 */ + {0x7, 0x7, 2, 0x7, 0x00080, 8}, /* PATTERN_PBS2 */ + {0x7, 0x7, 2, 0x7, 0x00100, 8}, /* PATTERN_PBS3 */ + {0x7, 0x7, 2, 0x7, 0x00030, 8}, /* PATTERN_TEST */ + {0x7, 0x7, 2, 0x7, 0x00100, 8}, /* PATTERN_RL */ + {0x7, 0x7, 2, 0x7, 0x00100, 8}, /* PATTERN_RL2 */ + {0x1f, 0xf, 2, 0xf, 0x00680, 32}, /* PATTERN_STATIC_PBS */ + {0x1f, 0xf, 2, 0xf, 0x00a80, 32}, /* PATTERN_KILLER_DQ0 */ + {0x1f, 0xf, 2, 0xf, 0x01280, 32}, /* PATTERN_KILLER_DQ1 */ + {0x1f, 0xf, 2, 0xf, 0x01a80, 32}, /* PATTERN_KILLER_DQ2 */ + {0x1f, 0xf, 2, 0xf, 0x02280, 32}, /* PATTERN_KILLER_DQ3 */ + {0x1f, 0xf, 2, 0xf, 0x02a80, 32}, /* PATTERN_KILLER_DQ4 */ + {0x1f, 0xf, 2, 0xf, 0x03280, 32}, /* PATTERN_KILLER_DQ5 */ + {0x1f, 0xf, 2, 0xf, 0x03a80, 32}, /* PATTERN_KILLER_DQ6 */ + {0x1f, 0xf, 2, 0xf, 0x04280, 32}, /* PATTERN_KILLER_DQ7 */ + {0x1f, 0xf, 2, 0xf, 0x00e80, 32}, /* PATTERN_KILLER_DQ0_64 */ + {0x1f, 0xf, 2, 0xf, 0x01680, 32}, /* PATTERN_KILLER_DQ1_64 */ + {0x1f, 0xf, 2, 0xf, 0x01e80, 32}, /* PATTERN_KILLER_DQ2_64 */ + {0x1f, 0xf, 2, 0xf, 0x02680, 32}, /* PATTERN_KILLER_DQ3_64 */ + {0x1f, 0xf, 2, 0xf, 0x02e80, 32}, /* PATTERN_KILLER_DQ4_64 */ + {0x1f, 0xf, 2, 0xf, 0x03680, 32}, /* PATTERN_KILLER_DQ5_64 */ + {0x1f, 0xf, 2, 0xf, 0x03e80, 32}, /* PATTERN_KILLER_DQ6_64 */ + {0x1f, 0xf, 2, 0xf, 0x04680, 32}, /* PATTERN_KILLER_DQ7_64 */ + {0x1f, 0xf, 2, 0xf, 0x04a80, 32}, /* PATTERN_KILLER_DQ0_INV */ + {0x1f, 0xf, 2, 0xf, 0x05280, 32}, /* PATTERN_KILLER_DQ1_INV */ + {0x1f, 0xf, 2, 0xf, 0x05a80, 32}, /* PATTERN_KILLER_DQ2_INV */ + {0x1f, 0xf, 2, 0xf, 0x06280, 32}, /* PATTERN_KILLER_DQ3_INV */ + {0x1f, 0xf, 2, 0xf, 0x06a80, 32}, /* PATTERN_KILLER_DQ4_INV */ + {0x1f, 0xf, 2, 0xf, 0x07280, 32}, /* PATTERN_KILLER_DQ5_INV */ + {0x1f, 0xf, 2, 0xf, 0x07a80, 32}, /* PATTERN_KILLER_DQ6_INV */ + {0x1f, 0xf, 2, 0xf, 0x08280, 32}, /* PATTERN_KILLER_DQ7_INV */ + {0x1f, 0xf, 2, 0xf, 0x04e80, 32}, /* PATTERN_KILLER_DQ0_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x05680, 32}, /* PATTERN_KILLER_DQ1_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x05e80, 32}, /* PATTERN_KILLER_DQ2_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x06680, 32}, /* PATTERN_KILLER_DQ3_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x06e80, 32}, /* PATTERN_KILLER_DQ4_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x07680, 32}, /* PATTERN_KILLER_DQ5_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x07e80, 32}, /* PATTERN_KILLER_DQ6_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x08680, 32}, /* PATTERN_KILLER_DQ7_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x08a80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ0 */ + {0x1f, 0xf, 2, 0xf, 0x09280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ1 */ + {0x1f, 0xf, 2, 0xf, 0x09a80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ2 */ + {0x1f, 0xf, 2, 0xf, 0x0a280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ3 */ + {0x1f, 0xf, 2, 0xf, 0x0aa80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ4 */ + {0x1f, 0xf, 2, 0xf, 0x0b280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ5 */ + {0x1f, 0xf, 2, 0xf, 0x0ba80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ6 */ + {0x1f, 0xf, 2, 0xf, 0x0c280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ7 */ + {0x1f, 0xf, 2, 0xf, 0x08e80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ0_64 */ + {0x1f, 0xf, 2, 0xf, 0x09680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ1_64 */ + {0x1f, 0xf, 2, 0xf, 0x09e80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ2_64 */ + {0x1f, 0xf, 2, 0xf, 0x0a680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ3_64 */ + {0x1f, 0xf, 2, 0xf, 0x0ae80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ4_64 */ + {0x1f, 0xf, 2, 0xf, 0x0b680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ5_64 */ + {0x1f, 0xf, 2, 0xf, 0x0be80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ6_64 */ + {0x1f, 0xf, 2, 0xf, 0x0c680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ7_64 */ + {0x1f, 0xf, 2, 0xf, 0x0ca80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ0 */ + {0x1f, 0xf, 2, 0xf, 0x0d280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ1 */ + {0x1f, 0xf, 2, 0xf, 0x0da80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ2 */ + {0x1f, 0xf, 2, 0xf, 0x0e280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ3 */ + {0x1f, 0xf, 2, 0xf, 0x0ea80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ4 */ + {0x1f, 0xf, 2, 0xf, 0x0f280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ5 */ + {0x1f, 0xf, 2, 0xf, 0x0fa80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ6 */ + {0x1f, 0xf, 2, 0xf, 0x10280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ7 */ + {0x1f, 0xf, 2, 0xf, 0x0ce80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ0_64 */ + {0x1f, 0xf, 2, 0xf, 0x0d680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ1_64 */ + {0x1f, 0xf, 2, 0xf, 0x0de80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ2_64 */ + {0x1f, 0xf, 2, 0xf, 0x0e680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ3_64 */ + {0x1f, 0xf, 2, 0xf, 0x0ee80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ4_64 */ + {0x1f, 0xf, 2, 0xf, 0x0f680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ5_64 */ + {0x1f, 0xf, 2, 0xf, 0x0fe80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ6_64 */ + {0x1f, 0xf, 2, 0xf, 0x10680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ7_64 */ + {0x1f, 0xf, 2, 0xf, 0x10a80, 32}, /* PATTERN_ISI_XTALK_FREE */ + {0x1f, 0xf, 2, 0xf, 0x10e80, 32}, /* PATTERN_ISI_XTALK_FREE_64 */ + {0x1f, 0xf, 2, 0xf, 0x11280, 32}, /* PATTERN_VREF */ + {0x1f, 0xf, 2, 0xf, 0x11680, 32}, /* PATTERN_VREF_64 */ + {0x1f, 0xf, 2, 0xf, 0x11a80, 32}, /* PATTERN_VREF_INV */ + {0x1f, 0xf, 2, 0xf, 0x11e80, 32}, /* PATTERN_FULL_SSO_0T */ + {0x1f, 0xf, 2, 0xf, 0x12280, 32}, /* PATTERN_FULL_SSO_1T */ + {0x1f, 0xf, 2, 0xf, 0x12680, 32}, /* PATTERN_FULL_SSO_2T */ + {0x1f, 0xf, 2, 0xf, 0x12a80, 32}, /* PATTERN_FULL_SSO_3T */ + {0x1f, 0xf, 2, 0xf, 0x12e80, 32}, /* PATTERN_RESONANCE_1T */ + {0x1f, 0xf, 2, 0xf, 0x13280, 32}, /* PATTERN_RESONANCE_2T */ + {0x1f, 0xf, 2, 0xf, 0x13680, 32}, /* PATTERN_RESONANCE_3T */ + {0x1f, 0xf, 2, 0xf, 0x13a80, 32}, /* PATTERN_RESONANCE_4T */ + {0x1f, 0xf, 2, 0xf, 0x13e80, 32}, /* PATTERN_RESONANCE_5T */ + {0x1f, 0xf, 2, 0xf, 0x14280, 32}, /* PATTERN_RESONANCE_6T */ + {0x1f, 0xf, 2, 0xf, 0x14680, 32}, /* PATTERN_RESONANCE_7T */ + {0x1f, 0xf, 2, 0xf, 0x14a80, 32}, /* PATTERN_RESONANCE_8T */ + {0x1f, 0xf, 2, 0xf, 0x14e80, 32}, /* PATTERN_RESONANCE_9T */ + {0x1f, 0xf, 2, 0xf, 0x15280, 32}, /* PATTERN_ZERO */ + {0x1f, 0xf, 2, 0xf, 0x15680, 32} /* PATTERN_ONE */ + /* Note: actual start_address is "<< 3" of defined address */ +}; struct pattern_info pattern_table_16[] = { /* @@ -88,7 +211,10 @@ struct pattern_info pattern_table_16[] = { */ {1, 1, 2, 1, 0x0080, 2}, /* PATTERN_PBS1 */ {1, 1, 2, 1, 0x00c0, 2}, /* PATTERN_PBS2 */ + {1, 1, 2, 1, 0x0380, 2}, /* PATTERN_PBS3 */ + {1, 1, 2, 1, 0x0040, 2}, /* PATTERN_TEST */ {1, 1, 2, 1, 0x0100, 2}, /* PATTERN_RL */ + {1, 1, 2, 1, 0x0000, 2}, /* PATTERN_RL2 */ {0xf, 0x7, 2, 0x7, 0x0140, 16}, /* PATTERN_STATIC_PBS */ {0xf, 0x7, 2, 0x7, 0x0190, 16}, /* PATTERN_KILLER_DQ0 */ {0xf, 0x7, 2, 0x7, 0x01d0, 16}, /* PATTERN_KILLER_DQ1 */ @@ -98,15 +224,29 @@ struct pattern_info pattern_table_16[] = { {0xf, 0x7, 2, 0x7, 0x02d0, 16}, /* PATTERN_KILLER_DQ5 */ {0xf, 0x7, 2, 0x7, 0x0310, 16}, /* PATTERN_KILLER_DQ6 */ {0xf, 0x7, 2, 0x7, 0x0350, 16}, /* PATTERN_KILLER_DQ7 */ - {1, 1, 2, 1, 0x0380, 2}, /* PATTERN_PBS3 */ - {1, 1, 2, 1, 0x0000, 2}, /* PATTERN_RL2 */ - {1, 1, 2, 1, 0x0040, 2}, /* PATTERN_TEST */ + {0xf, 0x7, 2, 0x7, 0x04c0, 16}, /* PATTERN_VREF */ {0xf, 0x7, 2, 0x7, 0x03c0, 16}, /* PATTERN_FULL_SSO_1T */ {0xf, 0x7, 2, 0x7, 0x0400, 16}, /* PATTERN_FULL_SSO_2T */ {0xf, 0x7, 2, 0x7, 0x0440, 16}, /* PATTERN_FULL_SSO_3T */ {0xf, 0x7, 2, 0x7, 0x0480, 16}, /* PATTERN_FULL_SSO_4T */ - {0xf, 0x7, 2, 0x7, 0x04c0, 16} /* PATTERN_VREF */ - /*Note: actual start_address is <<3 of defined addess */ + {0xf, 7, 2, 7, 0x6280, 16}, /* PATTERN_SSO_FULL_XTALK_DQ1 */ + {0xf, 7, 2, 7, 0x6680, 16}, /* PATTERN_SSO_FULL_XTALK_DQ1 */ + {0xf, 7, 2, 7, 0x6A80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ2 */ + {0xf, 7, 2, 7, 0x6E80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ3 */ + {0xf, 7, 2, 7, 0x7280, 16}, /* PATTERN_SSO_FULL_XTALK_DQ4 */ + {0xf, 7, 2, 7, 0x7680, 16}, /* PATTERN_SSO_FULL_XTALK_DQ5 */ + {0xf, 7, 2, 7, 0x7A80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ6 */ + {0xf, 7, 2, 7, 0x7E80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ7 */ + {0xf, 7, 2, 7, 0x8280, 16}, /* PATTERN_SSO_XTALK_FREE_DQ0 */ + {0xf, 7, 2, 7, 0x8680, 16}, /* PATTERN_SSO_XTALK_FREE_DQ1 */ + {0xf, 7, 2, 7, 0x8A80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ2 */ + {0xf, 7, 2, 7, 0x8E80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ3 */ + {0xf, 7, 2, 7, 0x9280, 16}, /* PATTERN_SSO_XTALK_FREE_DQ4 */ + {0xf, 7, 2, 7, 0x9680, 16}, /* PATTERN_SSO_XTALK_FREE_DQ5 */ + {0xf, 7, 2, 7, 0x9A80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ6 */ + {0xf, 7, 2, 7, 0x9E80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ7 */ + {0xf, 7, 2, 7, 0xA280, 16} /* PATTERN_ISI_XTALK_FREE */ + /* Note: actual start_address is "<< 3" of defined address */ }; struct pattern_info pattern_table_32[] = { @@ -116,7 +256,10 @@ struct pattern_info pattern_table_32[] = { */ {3, 3, 2, 3, 0x0080, 4}, /* PATTERN_PBS1 */ {3, 3, 2, 3, 0x00c0, 4}, /* PATTERN_PBS2 */ + {3, 3, 2, 3, 0x0380, 4}, /* PATTERN_PBS3 */ + {3, 3, 2, 3, 0x0040, 4}, /* PATTERN_TEST */ {3, 3, 2, 3, 0x0100, 4}, /* PATTERN_RL */ + {3, 3, 2, 3, 0x0000, 4}, /* PATTERN_RL2 */ {0x1f, 0xf, 2, 0xf, 0x0140, 32}, /* PATTERN_STATIC_PBS */ {0x1f, 0xf, 2, 0xf, 0x0190, 32}, /* PATTERN_KILLER_DQ0 */ {0x1f, 0xf, 2, 0xf, 0x01d0, 32}, /* PATTERN_KILLER_DQ1 */ @@ -126,15 +269,29 @@ struct pattern_info pattern_table_32[] = { {0x1f, 0xf, 2, 0xf, 0x02d0, 32}, /* PATTERN_KILLER_DQ5 */ {0x1f, 0xf, 2, 0xf, 0x0310, 32}, /* PATTERN_KILLER_DQ6 */ {0x1f, 0xf, 2, 0xf, 0x0350, 32}, /* PATTERN_KILLER_DQ7 */ - {3, 3, 2, 3, 0x0380, 4}, /* PATTERN_PBS3 */ - {3, 3, 2, 3, 0x0000, 4}, /* PATTERN_RL2 */ - {3, 3, 2, 3, 0x0040, 4}, /* PATTERN_TEST */ + {0x1f, 0xf, 2, 0xf, 0x04c0, 32}, /* PATTERN_VREF */ {0x1f, 0xf, 2, 0xf, 0x03c0, 32}, /* PATTERN_FULL_SSO_1T */ {0x1f, 0xf, 2, 0xf, 0x0400, 32}, /* PATTERN_FULL_SSO_2T */ {0x1f, 0xf, 2, 0xf, 0x0440, 32}, /* PATTERN_FULL_SSO_3T */ {0x1f, 0xf, 2, 0xf, 0x0480, 32}, /* PATTERN_FULL_SSO_4T */ - {0x1f, 0xf, 2, 0xf, 0x04c0, 32} /* PATTERN_VREF */ - /*Note: actual start_address is <<3 of defined addess */ + {0x1f, 0xF, 2, 0xf, 0x6280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ0 */ + {0x1f, 0xF, 2, 0xf, 0x6680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ1 */ + {0x1f, 0xF, 2, 0xf, 0x6A80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ2 */ + {0x1f, 0xF, 2, 0xf, 0x6E80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ3 */ + {0x1f, 0xF, 2, 0xf, 0x7280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ4 */ + {0x1f, 0xF, 2, 0xf, 0x7680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ5 */ + {0x1f, 0xF, 2, 0xf, 0x7A80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ6 */ + {0x1f, 0xF, 2, 0xf, 0x7E80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ7 */ + {0x1f, 0xF, 2, 0xf, 0x8280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ0 */ + {0x1f, 0xF, 2, 0xf, 0x8680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ1 */ + {0x1f, 0xF, 2, 0xf, 0x8A80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ2 */ + {0x1f, 0xF, 2, 0xf, 0x8E80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ3 */ + {0x1f, 0xF, 2, 0xf, 0x9280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ4 */ + {0x1f, 0xF, 2, 0xf, 0x9680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ5 */ + {0x1f, 0xF, 2, 0xf, 0x9A80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ6 */ + {0x1f, 0xF, 2, 0xf, 0x9E80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ7 */ + {0x1f, 0xF, 2, 0xf, 0xA280, 32} /* PATTERN_ISI_XTALK_FREE */ + /* Note: actual start_address is "<< 3" of defined address */ }; u32 train_dev_num; @@ -166,6 +323,10 @@ u32 *ddr3_tip_get_buf_ptr(u32 dev_num, enum hws_search_dir search, return buf_ptr; } +enum { + PASS, + FAIL +}; /* * IP Training search * Note: for one edge search only from fail to pass, else jitter can @@ -183,18 +344,19 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, enum hws_ddr_cs cs_type, u32 cs_num, enum hws_training_ip_stat *train_status) { - u32 mask_dq_num_of_regs, mask_pup_num_of_regs, index_cnt, poll_cnt, + u32 mask_dq_num_of_regs, mask_pup_num_of_regs, index_cnt, reg_data, pup_id; u32 tx_burst_size; u32 delay_between_burst; u32 rd_mode; - u32 read_data[MAX_INTERFACE_NUM]; + u32 data; struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - if (pup_num >= tm->num_of_bus_per_interface) { + if (pup_num >= octets_per_if_num) { DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, ("pup_num %d not valid\n", pup_num)); } @@ -214,20 +376,20 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, /* All CSs to CS0 */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - CS_ENABLE_REG, 1 << 3, 1 << 3)); + DUAL_DUNIT_CFG_REG, 1 << 3, 1 << 3)); /* All CSs to CS0 */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - ODPG_DATA_CONTROL_REG, + ODPG_DATA_CTRL_REG, (0x3 | (effective_cs << 26)), 0xc000003)); } else { CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - CS_ENABLE_REG, 0, 1 << 3)); + DUAL_DUNIT_CFG_REG, 0, 1 << 3)); /* CS select */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - ODPG_DATA_CONTROL_REG, 0x3 | cs_num << 26, + ODPG_DATA_CTRL_REG, 0x3 | cs_num << 26, 0x3 | 3 << 26)); } @@ -249,7 +411,7 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, reg_data |= (direction == OPER_READ) ? 0x60 : 0xfa; CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - ODPG_WRITE_READ_MODE_ENABLE_REG, reg_data, + ODPG_WR_RD_MODE_ENA_REG, reg_data, MASK_ALL_BITS)); reg_data = (edge_comp == EDGE_PF || edge_comp == EDGE_FP) ? 0 : 1 << 6; reg_data |= (edge_comp == EDGE_PF || edge_comp == EDGE_PFP) ? @@ -272,13 +434,13 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - ODPG_TRAINING_CONTROL_REG, + GENERAL_TRAINING_OPCODE_REG, reg_data | (0x7 << 8) | (0x7 << 11), (0x3 | (0x3 << 2) | (0x3 << 6) | (1 << 5) | (0x7 << 8) | (0x7 << 11) | (0xf << 14) | (0x3 << 18) | (3 << 20)))); reg_data = (search_dir == HWS_LOW2HIGH) ? 0 : (1 << 8); CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, interface_num, ODPG_OBJ1_OPCODE_REG, + (dev_num, access_type, interface_num, OPCODE_REG0_REG(1), 1 | reg_data | init_value << 9 | (1 << 25) | (1 << 26), 0xff | (1 << 8) | (0xffff << 9) | (1 << 25) | (1 << 26))); @@ -287,7 +449,7 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, * Max number of iterations */ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, interface_num, - ODPG_OBJ1_ITER_CNT_REG, num_iter, + OPCODE_REG1_REG(1), num_iter, 0xffff)); if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW && direction == OPER_READ) { @@ -295,12 +457,10 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, * Write2_dunit(0x10c0, 0x5f , [7:0]) * MC PBS Reg Address at DDR PHY */ - reg_data = 0x5f + - effective_cs * CALIBRATED_OBJECTS_REG_ADDR_OFFSET; + reg_data = PBS_RX_BCAST_PHY_REG(effective_cs); } else if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW && direction == OPER_WRITE) { - reg_data = 0x1f + - effective_cs * CALIBRATED_OBJECTS_REG_ADDR_OFFSET; + reg_data = PBS_TX_BCAST_PHY_REG(effective_cs); } else if (control_element == HWS_CONTROL_ELEMENT_ADLL && direction == OPER_WRITE) { /* @@ -311,11 +471,11 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, * Write2_dunit(0x10c0, 0x1 , [7:0]) * ADLL WR Reg Address at DDR PHY */ - reg_data = 1 + effective_cs * CS_REGISTER_ADDR_OFFSET; + reg_data = CTX_PHY_REG(effective_cs); } else if (control_element == HWS_CONTROL_ELEMENT_ADLL && direction == OPER_READ) { /* ADLL RD Reg Address@DDR PHY */ - reg_data = 3 + effective_cs * CS_REGISTER_ADDR_OFFSET; + reg_data = CRX_PHY_REG(effective_cs); } else if (control_element == HWS_CONTROL_ELEMENT_DQS_SKEW && direction == OPER_WRITE) { /* TBD not defined in 0.5.0 requirement */ @@ -326,12 +486,12 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, reg_data |= (0x6 << 28); CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, interface_num, CALIB_OBJ_PRFA_REG, + (dev_num, access_type, interface_num, CAL_PHY_REG(1), reg_data | (init_value << 8), 0xff | (0xffff << 8) | (0xf << 24) | (u32) (0xf << 28))); - mask_dq_num_of_regs = tm->num_of_bus_per_interface * BUS_WIDTH_IN_BITS; - mask_pup_num_of_regs = tm->num_of_bus_per_interface; + mask_dq_num_of_regs = octets_per_if_num * BUS_WIDTH_IN_BITS; + mask_pup_num_of_regs = octets_per_if_num; if (result_type == RESULT_PER_BIT) { for (index_cnt = 0; index_cnt < mask_dq_num_of_regs; @@ -343,15 +503,12 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, } /* Mask disabled buses */ - for (pup_id = 0; pup_id < tm->num_of_bus_per_interface; + for (pup_id = 0; pup_id < octets_per_if_num; pup_id++) { - if (IS_ACTIVE(tm->bus_act_mask, pup_id) == 1) + if (IS_BUS_ACTIVE(tm->bus_act_mask, pup_id) == 1) continue; - for (index_cnt = (mask_dq_num_of_regs - pup_id * 8); - index_cnt < - (mask_dq_num_of_regs - (pup_id + 1) * 8); - index_cnt++) { + for (index_cnt = (pup_id * 8); index_cnt < (pup_id + 1) * 8; index_cnt++) { CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, @@ -385,89 +542,24 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, } } - /* Start Training Trigger */ - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, interface_num, - ODPG_TRAINING_TRIGGER_REG, 1, 1)); - /* wait for all RFU tests to finish (or timeout) */ - /* WA for 16 bit mode, more investigation needed */ - mdelay(1); - - /* Training "Done ?" */ - for (index_cnt = 0; index_cnt < MAX_INTERFACE_NUM; index_cnt++) { - if (IS_ACTIVE(tm->if_act_mask, index_cnt) == 0) - continue; - - if (interface_mask & (1 << index_cnt)) { - /* need to check results for this Dunit */ - for (poll_cnt = 0; poll_cnt < max_polling_for_done; - poll_cnt++) { - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, - index_cnt, - ODPG_TRAINING_STATUS_REG, - ®_data, MASK_ALL_BITS)); - if ((reg_data & 0x2) != 0) { - /*done */ - train_status[index_cnt] = - HWS_TRAINING_IP_STATUS_SUCCESS; - break; - } - } - - if (poll_cnt == max_polling_for_done) { - train_status[index_cnt] = - HWS_TRAINING_IP_STATUS_TIMEOUT; - } - } - /* Be sure that ODPG done */ - CHECK_STATUS(is_odpg_access_done(dev_num, index_cnt)); - } - - /* Write ODPG done in Dunit */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_STATUS_DONE_REG, 0, 0x1)); + /* trigger training */ + mv_ddr_training_enable(); - /* wait for all Dunit tests to finish (or timeout) */ - /* Training "Done ?" */ - /* Training "Pass ?" */ - for (index_cnt = 0; index_cnt < MAX_INTERFACE_NUM; index_cnt++) { - if (IS_ACTIVE(tm->if_act_mask, index_cnt) == 0) - continue; - - if (interface_mask & (1 << index_cnt)) { - /* need to check results for this Dunit */ - for (poll_cnt = 0; poll_cnt < max_polling_for_done; - poll_cnt++) { - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, - index_cnt, - ODPG_TRAINING_TRIGGER_REG, - read_data, MASK_ALL_BITS)); - reg_data = read_data[index_cnt]; - if ((reg_data & 0x2) != 0) { - /* done */ - if ((reg_data & 0x4) == 0) { - train_status[index_cnt] = - HWS_TRAINING_IP_STATUS_SUCCESS; - } else { - train_status[index_cnt] = - HWS_TRAINING_IP_STATUS_FAIL; - } - break; - } - } + /* wa for 16-bit mode: wait for all rfu tests to finish or timeout */ + mdelay(1); - if (poll_cnt == max_polling_for_done) { - train_status[index_cnt] = - HWS_TRAINING_IP_STATUS_TIMEOUT; - } - } + /* check for training done */ + if (mv_ddr_is_training_done(MAX_POLLING_ITERATIONS, &data) != MV_OK) { + train_status[0] = HWS_TRAINING_IP_STATUS_TIMEOUT; + } else { /* training done; check for pass */ + if (data == PASS) + train_status[0] = HWS_TRAINING_IP_STATUS_SUCCESS; + else + train_status[0] = HWS_TRAINING_IP_STATUS_FAIL; } - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0, MASK_ALL_BITS)); + ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS); return MV_OK; } @@ -481,32 +573,47 @@ int ddr3_tip_load_pattern_to_odpg(u32 dev_num, enum hws_access_type access_type, { u32 pattern_length_cnt = 0; struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (pattern_length_cnt = 0; pattern_length_cnt < pattern_table[pattern].pattern_len; - pattern_length_cnt++) { - CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, - ODPG_PATTERN_DATA_LOW_REG, - pattern_table_get_word(dev_num, pattern, - (u8) (pattern_length_cnt * - 2)), MASK_ALL_BITS)); - CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, - ODPG_PATTERN_DATA_HI_REG, - pattern_table_get_word(dev_num, pattern, - (u8) (pattern_length_cnt * - 2 + 1)), - MASK_ALL_BITS)); + pattern_length_cnt++) { /* FIXME: the ecc patch below is only for a7040 A0 */ + if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)/* || tm->bus_act_mask == MV_DDR_32BIT_ECC_PUP8_BUS_MASK*/) { + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + ODPG_DATA_WR_DATA_LOW_REG, + pattern_table_get_word(dev_num, pattern, + (u8) (pattern_length_cnt)), + MASK_ALL_BITS)); + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + ODPG_DATA_WR_DATA_HIGH_REG, + pattern_table_get_word(dev_num, pattern, + (u8) (pattern_length_cnt)), + MASK_ALL_BITS)); + } else { + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + ODPG_DATA_WR_DATA_LOW_REG, + pattern_table_get_word(dev_num, pattern, + (u8) (pattern_length_cnt * 2)), + MASK_ALL_BITS)); + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + ODPG_DATA_WR_DATA_HIGH_REG, + pattern_table_get_word(dev_num, pattern, + (u8) (pattern_length_cnt * 2 + 1)), + MASK_ALL_BITS)); + } CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - ODPG_PATTERN_ADDR_REG, pattern_length_cnt, + ODPG_DATA_WR_ADDR_REG, pattern_length_cnt, MASK_ALL_BITS)); } CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - ODPG_PATTERN_ADDR_OFFSET_REG, load_addr, MASK_ALL_BITS)); + ODPG_DATA_BUFFER_OFFS_REG, load_addr, MASK_ALL_BITS)); return MV_OK; } @@ -528,7 +635,7 @@ int ddr3_tip_configure_odpg(u32 dev_num, enum hws_access_type access_type, (rx_phases << 21) | (rd_mode << 25) | (cs_num << 26) | (addr_stress_jump << 29)); ret = ddr3_tip_if_write(dev_num, access_type, if_id, - ODPG_DATA_CONTROL_REG, data_value, 0xaffffffc); + ODPG_DATA_CTRL_REG, data_value, 0xaffffffc); if (ret != MV_OK) return ret; @@ -598,7 +705,8 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, u32 read_data[MAX_INTERFACE_NUM]; u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* * Agreed assumption: all CS mask contain same number of bits, @@ -606,11 +714,11 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, * all pups */ CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, CS_ENABLE_REG, + (dev_num, ACCESS_TYPE_UNICAST, if_id, DUAL_DUNIT_CFG_REG, (cs_num_type == 0) ? 1 << 3 : 0, (1 << 3))); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_DATA_CONTROL_REG, (cs_num_type << 26), (3 << 26))); + ODPG_DATA_CTRL_REG, (cs_num_type << 26), (3 << 26))); DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_TRACE, ("Read_from_d_b %d cs_type %d oper %d result_type %d direction %d search %d pup_num %d if_id %d pup_access_type %d\n", is_read_from_db, cs_num_type, operation, @@ -622,7 +730,7 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, ("ddr3_tip_read_training_result load_res = NULL")); return MV_FAIL; } - if (pup_num >= tm->num_of_bus_per_interface) { + if (pup_num >= octets_per_if_num) { DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, ("pup_num %d not valid\n", pup_num)); } @@ -640,11 +748,11 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, } else { /*pup_access_type == ACCESS_TYPE_MULTICAST) */ start_pup = 0; - end_pup = tm->num_of_bus_per_interface - 1; + end_pup = octets_per_if_num - 1; } for (pup_cnt = start_pup; pup_cnt <= end_pup; pup_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup_cnt); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup_cnt); DEBUG_TRAINING_IP_ENGINE( DEBUG_LEVEL_TRACE, ("if_id %d start_pup %d end_pup %d pup_cnt %d\n", @@ -690,11 +798,11 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, MASK_ALL_BITS)); if (is_check_result_validity == 1) { if ((read_data[if_id] & - 0x02000000) == 0) { + TIP_ENG_LOCK) == 0) { interface_train_res [reg_offset] = - 0x02000000 + - 64 + cons_tap; + TIP_ENG_LOCK + + TIP_TX_DLL_RANGE_MAX; } else { interface_train_res [reg_offset] = @@ -738,60 +846,27 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, int ddr3_tip_load_all_pattern_to_mem(u32 dev_num) { u32 pattern = 0, if_id; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); training_result[training_stage][if_id] = TEST_SUCCESS; } for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* enable single cs */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, (1 << 3), (1 << 3))); + DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3))); } - for (pattern = 0; pattern < PATTERN_LIMIT; pattern++) + for (pattern = 0; pattern < PATTERN_LAST; pattern++) ddr3_tip_load_pattern_to_mem(dev_num, pattern); return MV_OK; } -/* - * Wait till ODPG access is ready - */ -int is_odpg_access_done(u32 dev_num, u32 if_id) -{ - u32 poll_cnt = 0, data_value; - u32 read_data[MAX_INTERFACE_NUM]; - - for (poll_cnt = 0; poll_cnt < MAX_POLLING_ITERATIONS; poll_cnt++) { - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_BIST_DONE, read_data, MASK_ALL_BITS)); - data_value = read_data[if_id]; - if (((data_value >> ODPG_BIST_DONE_BIT_OFFS) & 0x1) == - ODPG_BIST_DONE_BIT_VALUE) { - data_value = data_value & 0xfffffffe; - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_UNICAST, - if_id, ODPG_BIST_DONE, data_value, - MASK_ALL_BITS)); - break; - } - } - - if (poll_cnt >= MAX_POLLING_ITERATIONS) { - DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, - ("Bist Activate: poll failure 2\n")); - return MV_FAIL; - } - - return MV_OK; -} - /* * Load specific pattern to memory using ODPG */ @@ -799,7 +874,7 @@ int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern pattern) { u32 reg_data, if_id; struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* load pattern to memory */ /* @@ -814,73 +889,65 @@ int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern pattern) (effective_cs << 26); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, reg_data, MASK_ALL_BITS)); + ODPG_DATA_CTRL_REG, reg_data, MASK_ALL_BITS)); /* ODPG Write enable from BIST */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, (0x1 | (effective_cs << 26)), + ODPG_DATA_CTRL_REG, (0x1 | (effective_cs << 26)), 0xc000003)); /* disable error injection */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_WRITE_DATA_ERROR_REG, 0, 0x1)); + ODPG_DATA_WR_DATA_ERR_REG, 0, 0x1)); /* load pattern to ODPG */ ddr3_tip_load_pattern_to_odpg(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, pattern, pattern_table[pattern].start_addr); - for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - if (IS_ACTIVE(tm->if_act_mask, if_id) == 0) - continue; + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) { + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + CHECK_STATUS(ddr3_tip_if_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + SDRAM_ODT_CTRL_HIGH_REG, + 0x3, 0xf)); + } + + mv_ddr_odpg_enable(); + } else { CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1498, - 0x3, 0xf)); + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ODPG_DATA_CTRL_REG, (u32)(0x1 << 31), + (u32)(0x1 << 31))); } - - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_ENABLE_REG, 0x1 << ODPG_ENABLE_OFFS, - (0x1 << ODPG_ENABLE_OFFS))); - mdelay(1); - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - CHECK_STATUS(is_odpg_access_done(dev_num, if_id)); - } + if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK) + return MV_FAIL; /* Disable ODPG and stop write to memory */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, (0x1 << 30), (u32) (0x3 << 30))); + ODPG_DATA_CTRL_REG, (0x1 << 30), (u32) (0x3 << 30))); /* return to default */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0, MASK_ALL_BITS)); - - /* Disable odt0 for CS0 training - need to adjust for multy CS */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0x1498, - 0x0, 0xf)); + ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS)); + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) { + /* Disable odt0 for CS0 training - need to adjust for multy CS */ + CHECK_STATUS(ddr3_tip_if_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + SDRAM_ODT_CTRL_HIGH_REG, 0x0, 0xf)); + } /* temporary added */ mdelay(1); return MV_OK; } -/* - * Load specific pattern to memory using CPU - */ -int ddr3_tip_load_pattern_to_mem_by_cpu(u32 dev_num, enum hws_pattern pattern, - u32 offset) -{ - /* eranba - TBD */ - return MV_OK; -} - /* * Training search routine */ @@ -903,8 +970,9 @@ int ddr3_tip_ip_training_wrapper_int(u32 dev_num, u32 interface_num = 0, start_if, end_if, init_value_used; enum hws_search_dir search_dir_id, start_search, end_search; enum hws_edge_compare edge_comp_used; - u8 cons_tap = (direction == OPER_WRITE) ? (64) : (0); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u8 cons_tap = 0; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (train_status == NULL) { DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, @@ -914,12 +982,12 @@ int ddr3_tip_ip_training_wrapper_int(u32 dev_num, if ((train_cs_type > CS_NON_SINGLE) || (edge_comp >= EDGE_PFP) || - (pattern >= PATTERN_LIMIT) || + (pattern >= PATTERN_LAST) || (direction > OPER_WRITE_AND_READ) || (search_dir > HWS_HIGH2LOW) || (control_element > HWS_CONTROL_ELEMENT_DQS_SKEW) || (result_type > RESULT_PER_BYTE) || - (pup_num >= tm->num_of_bus_per_interface) || + (pup_num >= octets_per_if_num) || (pup_access_type > ACCESS_TYPE_MULTICAST) || (if_id > 11) || (access_type > ACCESS_TYPE_MULTICAST)) { DEBUG_TRAINING_IP_ENGINE( @@ -969,7 +1037,7 @@ int ddr3_tip_ip_training_wrapper_int(u32 dev_num, for (interface_num = start_if; interface_num <= end_if; interface_num++) { - VALIDATE_ACTIVE(tm->if_act_mask, interface_num); + VALIDATE_IF_ACTIVE(tm->if_act_mask, interface_num); cs_num = 0; CHECK_STATUS(ddr3_tip_read_training_result (dev_num, interface_num, pup_access_type, @@ -983,48 +1051,99 @@ int ddr3_tip_ip_training_wrapper_int(u32 dev_num, return MV_OK; } - /* * Training search & read result routine + * This function implements the search algorithm + * first it calls the function ddr3_tip_ip_training_wrapper_int which triggers the search from l2h and h2l + * this function handles rx and tx search cases + * in case of rx it only triggers the search (l2h and h2l) + * in case of tx there are 3 optional algorithm phases: + * phase 1: + * it first triggers the search and handles the results as following (phase 1): + * each bit, which defined by the search two edges (e1 or VW_L and e2 or VW_H), match on of cases: + * 1. BIT_LOW_UI 0 =< VW =< 31 in case of jitter use: VW_L <= 31, VW_H <= 31 + * 2. BIT_HIGH_UI 32 =< VW =< 63 in case of jitter use: VW_L >= 32, VW_H >= 32 + * 3. BIT_SPLIT_IN VW_L <= 31 & VW_H >= 32 + * 4. BIT_SPLIT_OUT* VW_H < 32 & VW_L > 32 + * note: the VW units is adll taps + * phase 2: + * only bit case BIT_SPLIT_OUT requires another search (phase 2) from the middle range in two directions h2l and l2h + * because only this case is not locked by the search engine in the first search trigger (phase 1). + * phase 3: + * each subphy is categorized according to its bits definition. + * the sub-phy cases are as follows: + * 1.BYTE_NOT_DEFINED the byte has not yet been categorized + * 2.BYTE_HOMOGENEOUS_LOW 0 =< VW =< 31 + * 3.BYTE_HOMOGENEOUS_HIGH 32 =< VW =< 63 + * 4.BYTE_HOMOGENEOUS_SPLIT_IN VW_L <= 31 & VW_H >= 32 + * or the center of all bits in the byte =< 31 + * 5.BYTE_HOMOGENEOUS_SPLIT_OUT VW_H < 32 & VW_L > 32 + * 6.BYTE_SPLIT_OUT_MIX at least one bits is in split out state and one bit is in other + * or the center of all bits in the byte => 32 + * after the two phases above a center valid window for each subphy is calculated accordingly: + * center valid window = maximum center of all bits in the subphy - minimum center of all bits in the subphy. + * now decisions are made in each subphy as following: + * all subphys which are homogeneous remains as is + * all subphys which are homogeneous low | homogeneous high and the subphy center valid window is less than 32 + * mark this subphy as homogeneous split in. + * now the bits in the bytes which are BYTE_SPLIT_OUT_MIX needed to be reorganized and handles as following + * all bits which are BIT_LOW_UI will be added with 64 adll, + * this will hopefully ensures that all the bits in the sub phy can be sampled by the dqs */ int ddr3_tip_ip_training_wrapper(u32 dev_num, enum hws_access_type access_type, - u32 if_id, - enum hws_access_type pup_access_type, - u32 pup_num, - enum hws_training_result result_type, - enum hws_control_element control_element, - enum hws_search_dir search_dir, - enum hws_dir direction, u32 interface_mask, - u32 init_value_l2h, u32 init_value_h2l, - u32 num_iter, enum hws_pattern pattern, - enum hws_edge_compare edge_comp, - enum hws_ddr_cs train_cs_type, u32 cs_num, - enum hws_training_ip_stat *train_status) + u32 if_id, + enum hws_access_type pup_access_type, + u32 pup_num, + enum hws_training_result result_type, + enum hws_control_element control_element, + enum hws_search_dir search_dir, + enum hws_dir direction, u32 interface_mask, + u32 init_value_l2h, u32 init_value_h2l, + u32 num_iter, enum hws_pattern pattern, + enum hws_edge_compare edge_comp, + enum hws_ddr_cs train_cs_type, u32 cs_num, + enum hws_training_ip_stat *train_status) { u8 e1, e2; - u32 interface_cnt, bit_id, start_if, end_if, bit_end = 0; + u32 bit_id, start_if, end_if, bit_end = 0; u32 *result[HWS_SEARCH_DIR_LIMIT] = { 0 }; u8 cons_tap = (direction == OPER_WRITE) ? (64) : (0); u8 bit_bit_mask[MAX_BUS_NUM] = { 0 }, bit_bit_mask_active = 0; - u8 pup_id; - struct hws_topology_map *tm = ddr3_get_topology_map(); - - if (pup_num >= tm->num_of_bus_per_interface) { + u8 bit_state[MAX_BUS_NUM * BUS_WIDTH_IN_BITS] = {0}; + u8 h2l_adll_value[MAX_BUS_NUM][BUS_WIDTH_IN_BITS]; + u8 l2h_adll_value[MAX_BUS_NUM][BUS_WIDTH_IN_BITS]; + u8 center_subphy_adll_window[MAX_BUS_NUM]; + u8 min_center_subphy_adll[MAX_BUS_NUM]; + u8 max_center_subphy_adll[MAX_BUS_NUM]; + u32 *l2h_if_train_res = NULL; + u32 *h2l_if_train_res = NULL; + enum hws_search_dir search_dir_id; + int status; + u32 bit_lock_result; + + u8 sybphy_id; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + if (pup_num >= octets_per_if_num) { DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, - ("pup_num %d not valid\n", pup_num)); + ("pup_num %d not valid\n", pup_num)); } if (if_id >= MAX_INTERFACE_NUM) { DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, - ("if_id %d not valid\n", if_id)); + ("if_id %d not valid\n", if_id)); } - CHECK_STATUS(ddr3_tip_ip_training_wrapper_int - (dev_num, access_type, if_id, pup_access_type, pup_num, - ALL_BITS_PER_PUP, result_type, control_element, - search_dir, direction, interface_mask, init_value_l2h, - init_value_h2l, num_iter, pattern, edge_comp, - train_cs_type, cs_num, train_status)); + status = ddr3_tip_ip_training_wrapper_int + (dev_num, access_type, if_id, pup_access_type, pup_num, + ALL_BITS_PER_PUP, result_type, control_element, + search_dir, direction, interface_mask, init_value_l2h, + init_value_h2l, num_iter, pattern, edge_comp, + train_cs_type, cs_num, train_status); + + if (MV_OK != status) + return status; if (access_type == ACCESS_TYPE_MULTICAST) { start_if = 0; @@ -1034,181 +1153,337 @@ int ddr3_tip_ip_training_wrapper(u32 dev_num, enum hws_access_type access_type, end_if = if_id; } - for (interface_cnt = start_if; interface_cnt <= end_if; - interface_cnt++) { - VALIDATE_ACTIVE(tm->if_act_mask, interface_cnt); - for (pup_id = 0; - pup_id <= (tm->num_of_bus_per_interface - 1); pup_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup_id); + for (if_id = start_if; if_id <= end_if; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + /* zero the database */ + bit_bit_mask_active = 0; /* clean the flag for level2 search */ + memset(bit_state, 0, sizeof(bit_state)); + /* phase 1 */ + for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); if (result_type == RESULT_PER_BIT) - bit_end = BUS_WIDTH_IN_BITS - 1; + bit_end = BUS_WIDTH_IN_BITS; else bit_end = 0; - bit_bit_mask[pup_id] = 0; - for (bit_id = 0; bit_id <= bit_end; bit_id++) { - enum hws_search_dir search_dir_id; - for (search_dir_id = HWS_LOW2HIGH; - search_dir_id <= HWS_HIGH2LOW; - search_dir_id++) { - CHECK_STATUS - (ddr3_tip_read_training_result - (dev_num, interface_cnt, - ACCESS_TYPE_UNICAST, pup_id, - bit_id, search_dir_id, - direction, result_type, - TRAINING_LOAD_OPERATION_UNLOAD, - CS_SINGLE, - &result[search_dir_id], - 1, 0, 0)); + /* zero the data base */ + bit_bit_mask[sybphy_id] = 0; + byte_status[if_id][sybphy_id] = BYTE_NOT_DEFINED; + for (bit_id = 0; bit_id < bit_end; bit_id++) { + h2l_adll_value[sybphy_id][bit_id] = 64; + l2h_adll_value[sybphy_id][bit_id] = 0; + for (search_dir_id = HWS_LOW2HIGH; search_dir_id <= HWS_HIGH2LOW; + search_dir_id++) { + status = ddr3_tip_read_training_result + (dev_num, if_id, + ACCESS_TYPE_UNICAST, sybphy_id, bit_id, + search_dir_id, direction, result_type, + TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE, + &result[search_dir_id], 1, 0, 0); + + if (MV_OK != status) + return status; } - e1 = GET_TAP_RESULT(result[HWS_LOW2HIGH][0], - EDGE_1); - e2 = GET_TAP_RESULT(result[HWS_HIGH2LOW][0], - EDGE_1); - DEBUG_TRAINING_IP_ENGINE( - DEBUG_LEVEL_INFO, - ("wrapper if_id %d pup_id %d bit %d l2h 0x%x (e1 0x%x) h2l 0x%x (e2 0x%x)\n", - interface_cnt, pup_id, bit_id, - result[HWS_LOW2HIGH][0], e1, + + e1 = GET_TAP_RESULT(result[HWS_LOW2HIGH][0], EDGE_1); + e2 = GET_TAP_RESULT(result[HWS_HIGH2LOW][0], EDGE_1); + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_INFO, + ("if_id %d sybphy_id %d bit %d l2h 0x%x (e1 0x%x) h2l 0x%x (e2 0x%x)\n", + if_id, sybphy_id, bit_id, result[HWS_LOW2HIGH][0], e1, result[HWS_HIGH2LOW][0], e2)); - /* TBD validate is valid only for tx */ - if (VALIDATE_TRAINING_LIMIT(e1, e2) == 1 && - GET_LOCK_RESULT(result[HWS_LOW2HIGH][0]) && - GET_LOCK_RESULT(result[HWS_LOW2HIGH][0])) { - /* Mark problem bits */ - bit_bit_mask[pup_id] |= 1 << bit_id; - bit_bit_mask_active = 1; + bit_lock_result = + (GET_LOCK_RESULT(result[HWS_LOW2HIGH][0]) && + GET_LOCK_RESULT(result[HWS_HIGH2LOW][0])); + + if (bit_lock_result) { + /* in case of read operation set the byte status as homogeneous low */ + if (direction == OPER_READ) { + byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_LOW; + } else if ((e2 - e1) > 32) { /* oper_write */ + /* split out */ + bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] = + BIT_SPLIT_OUT; + byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_SPLIT_OUT; + /* mark problem bits */ + bit_bit_mask[sybphy_id] |= (1 << bit_id); + bit_bit_mask_active = 1; + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit %d BIT_SPLIT_OUT\n", + if_id, sybphy_id, bit_id)); + } else { + /* low ui */ + if (e1 <= 31 && e2 <= 31) { + bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] = + BIT_LOW_UI; + byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_LOW; + l2h_adll_value[sybphy_id][bit_id] = e1; + h2l_adll_value[sybphy_id][bit_id] = e2; + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit %d BIT_LOW_UI\n", + if_id, sybphy_id, bit_id)); + } + /* high ui */ + if (e1 >= 32 && e2 >= 32) { + bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] = + BIT_HIGH_UI; + byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_HIGH; + l2h_adll_value[sybphy_id][bit_id] = e1; + h2l_adll_value[sybphy_id][bit_id] = e2; + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit %d BIT_HIGH_UI\n", + if_id, sybphy_id, bit_id)); + } + /* split in */ + if (e1 <= 31 && e2 >= 32) { + bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] = + BIT_SPLIT_IN; + byte_status[if_id][sybphy_id] |= + BYTE_HOMOGENEOUS_SPLIT_IN; + l2h_adll_value[sybphy_id][bit_id] = e1; + h2l_adll_value[sybphy_id][bit_id] = e2; + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit %d BIT_SPLIT_IN\n", + if_id, sybphy_id, bit_id)); + } + } + } else { + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_INFO, + ("if_id %d sybphy_id %d bit %d l2h 0x%x (e1 0x%x)" + "h2l 0x%x (e2 0x%x): bit cannot be categorized\n", + if_id, sybphy_id, bit_id, result[HWS_LOW2HIGH][0], e1, + result[HWS_HIGH2LOW][0], e2)); + /* mark the byte as not defined */ + byte_status[if_id][sybphy_id] = BYTE_NOT_DEFINED; + break; /* continue to next pup - no reason to analyze this byte */ } - } /* For all bits */ - } /* For all PUPs */ + } /* for all bits */ + } /* for all PUPs */ - /* Fix problem bits */ + /* phase 2 will occur only in write operation */ if (bit_bit_mask_active != 0) { - u32 *l2h_if_train_res = NULL; - u32 *h2l_if_train_res = NULL; - l2h_if_train_res = - ddr3_tip_get_buf_ptr(dev_num, HWS_LOW2HIGH, - result_type, - interface_cnt); - h2l_if_train_res = - ddr3_tip_get_buf_ptr(dev_num, HWS_HIGH2LOW, - result_type, - interface_cnt); - - ddr3_tip_ip_training(dev_num, ACCESS_TYPE_UNICAST, - interface_cnt, - ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, result_type, - control_element, HWS_LOW2HIGH, - direction, interface_mask, - num_iter / 2, num_iter / 2, - pattern, EDGE_FP, train_cs_type, - cs_num, train_status); - - for (pup_id = 0; - pup_id <= (tm->num_of_bus_per_interface - 1); - pup_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup_id); - - if (bit_bit_mask[pup_id] == 0) - continue; - - for (bit_id = 0; bit_id <= bit_end; bit_id++) { - if ((bit_bit_mask[pup_id] & - (1 << bit_id)) == 0) + l2h_if_train_res = ddr3_tip_get_buf_ptr(dev_num, HWS_LOW2HIGH, result_type, if_id); + h2l_if_train_res = ddr3_tip_get_buf_ptr(dev_num, HWS_HIGH2LOW, result_type, if_id); + /* search from middle to end */ + ddr3_tip_ip_training + (dev_num, ACCESS_TYPE_UNICAST, + if_id, ACCESS_TYPE_MULTICAST, + PARAM_NOT_CARE, result_type, + control_element, HWS_LOW2HIGH, + direction, interface_mask, + num_iter / 2, num_iter / 2, + pattern, EDGE_FP, train_cs_type, + cs_num, train_status); + + for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); + if (byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) { + if (bit_bit_mask[sybphy_id] == 0) + continue; /* this byte bits have no split out state */ + + for (bit_id = 0; bit_id < bit_end; bit_id++) { + if ((bit_bit_mask[sybphy_id] & (1 << bit_id)) == 0) + continue; /* this bit is non split goto next bit */ + + /* enter the result to the data base */ + status = ddr3_tip_read_training_result + (dev_num, if_id, ACCESS_TYPE_UNICAST, sybphy_id, + bit_id, HWS_LOW2HIGH, direction, result_type, + TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE, + &l2h_if_train_res, 0, 0, 1); + + if (MV_OK != status) + return status; + + l2h_adll_value[sybphy_id][bit_id] = + l2h_if_train_res[sybphy_id * + BUS_WIDTH_IN_BITS + bit_id] & PUP_RESULT_EDGE_1_MASK; + } + } + } + /* Search from middle to start */ + ddr3_tip_ip_training + (dev_num, ACCESS_TYPE_UNICAST, + if_id, ACCESS_TYPE_MULTICAST, + PARAM_NOT_CARE, result_type, + control_element, HWS_HIGH2LOW, + direction, interface_mask, + num_iter / 2, num_iter / 2, + pattern, EDGE_FP, train_cs_type, + cs_num, train_status); + + for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); + if (byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) { + if (bit_bit_mask[sybphy_id] == 0) continue; - CHECK_STATUS - (ddr3_tip_read_training_result - (dev_num, interface_cnt, - ACCESS_TYPE_UNICAST, pup_id, - bit_id, HWS_LOW2HIGH, - direction, - result_type, - TRAINING_LOAD_OPERATION_UNLOAD, - CS_SINGLE, &l2h_if_train_res, - 0, 0, 1)); + + for (bit_id = 0; bit_id < bit_end; bit_id++) { + if ((bit_bit_mask[sybphy_id] & (1 << bit_id)) == 0) + continue; + + status = ddr3_tip_read_training_result + (dev_num, if_id, ACCESS_TYPE_UNICAST, sybphy_id, + bit_id, HWS_HIGH2LOW, direction, result_type, + TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE, + &h2l_if_train_res, 0, cons_tap, 1); + + if (MV_OK != status) + return status; + + h2l_adll_value[sybphy_id][bit_id] = + h2l_if_train_res[sybphy_id * + BUS_WIDTH_IN_BITS + bit_id] & PUP_RESULT_EDGE_1_MASK; + } } } + } /* end if bit_bit_mask_active */ + /* + * phase 3 will occur only in write operation + * find the maximum and the minimum center of each subphy + */ + for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); + + if ((byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) && (direction == OPER_WRITE)) { + /* clear the arrays and parameters */ + center_subphy_adll_window[sybphy_id] = 0; + max_center_subphy_adll[sybphy_id] = 0; + min_center_subphy_adll[sybphy_id] = 64; + /* find the max and min center adll value in the current subphy */ + for (bit_id = 0; bit_id < bit_end; bit_id++) { + /* debug print all the bit edges after alignment */ + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit %d l2h %d h2l %d\n", + if_id, sybphy_id, bit_id, l2h_adll_value[sybphy_id][bit_id], + h2l_adll_value[sybphy_id][bit_id])); + + if (((l2h_adll_value[sybphy_id][bit_id] + + h2l_adll_value[sybphy_id][bit_id]) / 2) > + max_center_subphy_adll[sybphy_id]) + max_center_subphy_adll[sybphy_id] = + (l2h_adll_value[sybphy_id][bit_id] + + h2l_adll_value[sybphy_id][bit_id]) / 2; + if (((l2h_adll_value[sybphy_id][bit_id] + + h2l_adll_value[sybphy_id][bit_id]) / 2) < + min_center_subphy_adll[sybphy_id]) + min_center_subphy_adll[sybphy_id] = + (l2h_adll_value[sybphy_id][bit_id] + + h2l_adll_value[sybphy_id][bit_id]) / 2; + } - ddr3_tip_ip_training(dev_num, ACCESS_TYPE_UNICAST, - interface_cnt, - ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, result_type, - control_element, HWS_HIGH2LOW, - direction, interface_mask, - num_iter / 2, num_iter / 2, - pattern, EDGE_FP, train_cs_type, - cs_num, train_status); - - for (pup_id = 0; - pup_id <= (tm->num_of_bus_per_interface - 1); - pup_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup_id); - - if (bit_bit_mask[pup_id] == 0) - continue; - - for (bit_id = 0; bit_id <= bit_end; bit_id++) { - if ((bit_bit_mask[pup_id] & - (1 << bit_id)) == 0) - continue; - CHECK_STATUS - (ddr3_tip_read_training_result - (dev_num, interface_cnt, - ACCESS_TYPE_UNICAST, pup_id, - bit_id, HWS_HIGH2LOW, direction, - result_type, - TRAINING_LOAD_OPERATION_UNLOAD, - CS_SINGLE, &h2l_if_train_res, - 0, cons_tap, 1)); + /* calculate the center of the current subphy */ + center_subphy_adll_window[sybphy_id] = + max_center_subphy_adll[sybphy_id] - + min_center_subphy_adll[sybphy_id]; + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d min center %d max center %d center %d\n", + if_id, sybphy_id, min_center_subphy_adll[sybphy_id], + max_center_subphy_adll[sybphy_id], + center_subphy_adll_window[sybphy_id])); + } + } + /* + * check byte state and fix bits state if needed + * in case the level 1 and 2 above subphy results are + * homogeneous continue to the next subphy + */ + for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); + if ((byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_LOW) || + (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_HIGH) || + (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_SPLIT_IN) || + (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_SPLIT_OUT) || + (byte_status[if_id][sybphy_id] == BYTE_NOT_DEFINED)) + continue; + + /* + * in case all of the bits in the current subphy are + * less than 32 which will find alignment in the subphy bits + * mark this subphy as homogeneous split in + */ + if (center_subphy_adll_window[sybphy_id] <= 31) + byte_status[if_id][sybphy_id] = BYTE_HOMOGENEOUS_SPLIT_IN; + + /* + * in case the current byte is split_out and the center is bigger than 31 + * the byte can be aligned. in this case add 64 to the the low ui bits aligning it + * to the other ui bits + */ + if (center_subphy_adll_window[sybphy_id] >= 32) { + byte_status[if_id][sybphy_id] = BYTE_SPLIT_OUT_MIX; + + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d byte state 0x%x\n", + if_id, sybphy_id, byte_status[if_id][sybphy_id])); + for (bit_id = 0; bit_id < bit_end; bit_id++) { + if (bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] == BIT_LOW_UI) { + l2h_if_train_res[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] += 64; + h2l_if_train_res[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] += 64; + } + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit_id %d added 64 adlls\n", + if_id, sybphy_id, bit_id)); } } - } /* if bit_bit_mask_active */ - } /* For all Interfacess */ + } + } /* for all interfaces */ return MV_OK; } +u8 mv_ddr_tip_sub_phy_byte_status_get(u32 if_id, u32 subphy_id) +{ + return byte_status[if_id][subphy_id]; +} + +void mv_ddr_tip_sub_phy_byte_status_set(u32 if_id, u32 subphy_id, u8 byte_status_data) +{ + byte_status[if_id][subphy_id] = byte_status_data; +} + /* * Load phy values */ int ddr3_tip_load_phy_values(int b_load) { u32 bus_cnt = 0, if_id, dev_num = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_cnt = 0; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES(); - bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); if (b_load == 1) { CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + CTX_PHY_REG(effective_cs), &phy_reg_bk[if_id][bus_cnt] [0])); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - RL_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + RL_PHY_REG(effective_cs), &phy_reg_bk[if_id][bus_cnt] [1])); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - READ_CENTRALIZATION_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + CRX_PHY_REG(effective_cs), &phy_reg_bk[if_id][bus_cnt] [2])); } else { @@ -1216,27 +1491,21 @@ int ddr3_tip_load_phy_values(int b_load) (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + CTX_PHY_REG(effective_cs), phy_reg_bk[if_id][bus_cnt] [0])); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - RL_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + RL_PHY_REG(effective_cs), phy_reg_bk[if_id][bus_cnt] [1])); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - READ_CENTRALIZATION_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + CRX_PHY_REG(effective_cs), phy_reg_bk[if_id][bus_cnt] [2])); } @@ -1258,7 +1527,8 @@ int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type, enum hws_training_ip_stat train_status[MAX_INTERFACE_NUM]; u32 *res = NULL; u32 search_state = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); ddr3_tip_load_phy_values(1); @@ -1280,11 +1550,11 @@ int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type, for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (pup_id = 0; pup_id < - tm->num_of_bus_per_interface; + octets_per_if_num; pup_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup_id); CHECK_STATUS (ddr3_tip_read_training_result @@ -1323,11 +1593,20 @@ int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type, return MV_OK; } +int mv_ddr_pattern_start_addr_set(struct pattern_info *pattern_tbl, enum hws_pattern pattern, u32 addr) +{ + pattern_tbl[pattern].start_addr = addr; + + return 0; +} + struct pattern_info *ddr3_tip_get_pattern_table() { - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0) + if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)) + return pattern_table_64; + else if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0) return pattern_table_32; else return pattern_table_16; @@ -1335,20 +1614,63 @@ struct pattern_info *ddr3_tip_get_pattern_table() u16 *ddr3_tip_get_mask_results_dq_reg() { - struct hws_topology_map *tm = ddr3_get_topology_map(); +#if MAX_BUS_NUM == 5 + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) return mask_results_dq_reg_map_pup3_ecc; else +#endif return mask_results_dq_reg_map; } u16 *ddr3_tip_get_mask_results_pup_reg_map() { - struct hws_topology_map *tm = ddr3_get_topology_map(); +#if MAX_BUS_NUM == 5 + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) return mask_results_pup_reg_map_pup3_ecc; else +#endif return mask_results_pup_reg_map; } + +/* load expected dm pattern to odpg */ +#define LOW_NIBBLE_BYTE_MASK 0xf +#define HIGH_NIBBLE_BYTE_MASK 0xf0 +int mv_ddr_load_dm_pattern_to_odpg(enum hws_access_type access_type, enum hws_pattern pattern, + enum dm_direction dm_dir) +{ + struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + u32 pattern_len = 0; + u32 data_low, data_high; + u8 dm_data; + + for (pattern_len = 0; + pattern_len < pattern_table[pattern].pattern_len; + pattern_len++) { + if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)) { + data_low = pattern_table_get_word(0, pattern, (u8)pattern_len); + data_high = data_low; + } else { + data_low = pattern_table_get_word(0, pattern, (u8)(pattern_len * 2)); + data_high = pattern_table_get_word(0, pattern, (u8)(pattern_len * 2 + 1)); + } + + /* odpg mbus dm definition is opposite to ddr4 protocol */ + if (dm_dir == DM_DIR_INVERSE) + dm_data = ~((data_low & LOW_NIBBLE_BYTE_MASK) | (data_high & HIGH_NIBBLE_BYTE_MASK)); + else + dm_data = (data_low & LOW_NIBBLE_BYTE_MASK) | (data_high & HIGH_NIBBLE_BYTE_MASK); + + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_DATA_LOW_REG, data_low, MASK_ALL_BITS); + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_DATA_HIGH_REG, data_high, MASK_ALL_BITS); + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_ADDR_REG, + pattern_len | ((dm_data & ODPG_DATA_WR_DATA_MASK) << ODPG_DATA_WR_DATA_OFFS), + MASK_ALL_BITS); + } + + return MV_OK; +} diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.h b/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.h index 25b146216ecd..f2e651bc06d5 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.h +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.h @@ -38,8 +38,6 @@ int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type, u32 num_of_iterations, u32 start_pattern, u32 end_pattern); int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern pattern); -int ddr3_tip_load_pattern_to_mem_by_cpu(u32 dev_num, enum hws_pattern pattern, - u32 offset); int ddr3_tip_load_all_pattern_to_mem(u32 dev_num); int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, enum hws_access_type pup_access_type, @@ -76,10 +74,13 @@ int ddr3_tip_ip_training_wrapper(u32 dev_num, enum hws_access_type access_type, enum hws_edge_compare edge_comp, enum hws_ddr_cs train_cs_type, u32 cs_num, enum hws_training_ip_stat *train_status); -int is_odpg_access_done(u32 dev_num, u32 if_id); +u8 mv_ddr_tip_sub_phy_byte_status_get(u32 if_id, u32 subphy_id); +void mv_ddr_tip_sub_phy_byte_status_set(u32 if_id, u32 subphy_id, u8 byte_status_data); void ddr3_tip_print_bist_res(void); struct pattern_info *ddr3_tip_get_pattern_table(void); u16 *ddr3_tip_get_mask_results_dq_reg(void); u16 *ddr3_tip_get_mask_results_pup_reg_map(void); - +int mv_ddr_load_dm_pattern_to_odpg(enum hws_access_type access_type, enum hws_pattern pattern, + enum dm_direction dm_dir); +int mv_ddr_pattern_start_addr_set(struct pattern_info *pattern_tbl, enum hws_pattern pattern, u32 addr); #endif /* _DDR3_TRAINING_IP_ENGINE_H_ */ diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h b/drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h index 22d7ce23e61e..14af632cffea 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h @@ -9,45 +9,73 @@ #include "ddr3_training_ip.h" #include "ddr3_training_ip_pbs.h" - -#define MRS0_CMD 0x3 -#define MRS1_CMD 0x4 -#define MRS2_CMD 0x8 -#define MRS3_CMD 0x9 - -/* - * Definitions of INTERFACE registers - */ - -#define READ_BUFFER_SELECT 0x14a4 - -/* - * Definitions of PHY registers - */ +#include "mv_ddr_regs.h" #define KILLER_PATTERN_LENGTH 32 #define EXT_ACCESS_BURST_LENGTH 8 -#define IS_ACTIVE(if_mask , if_id) \ - ((if_mask) & (1 << (if_id))) +#define IS_ACTIVE(mask, id) \ + ((mask) & (1 << (id))) + #define VALIDATE_ACTIVE(mask, id) \ { \ if (IS_ACTIVE(mask, id) == 0) \ continue; \ } -#define GET_TOPOLOGY_NUM_OF_BUSES() \ - (ddr3_get_topology_map()->num_of_bus_per_interface) +#define IS_IF_ACTIVE(if_mask, if_id) \ + ((if_mask) & (1 << (if_id))) + +#define VALIDATE_IF_ACTIVE(mask, id) \ + { \ + if (IS_IF_ACTIVE(mask, id) == 0) \ + continue; \ + } + +#define IS_BUS_ACTIVE(if_mask , if_id) \ + (((if_mask) >> (if_id)) & 1) + +#define VALIDATE_BUS_ACTIVE(mask, id) \ + { \ + if (IS_BUS_ACTIVE(mask, id) == 0) \ + continue; \ + } #define DDR3_IS_ECC_PUP3_MODE(if_mask) \ - (((if_mask) == 0xb) ? 1 : 0) + (((if_mask) == BUS_MASK_16BIT_ECC_PUP3) ? 1 : 0) + #define DDR3_IS_ECC_PUP4_MODE(if_mask) \ - (((((if_mask) & 0x10) == 0)) ? 0 : 1) + ((if_mask == BUS_MASK_32BIT_ECC || if_mask == BUS_MASK_16BIT_ECC) ? 1 : 0) + #define DDR3_IS_16BIT_DRAM_MODE(mask) \ - (((((mask) & 0x4) == 0)) ? 1 : 0) + ((mask == BUS_MASK_16BIT || mask == BUS_MASK_16BIT_ECC || mask == BUS_MASK_16BIT_ECC_PUP3) ? 1 : 0) +#define DDR3_IS_ECC_PUP8_MODE(if_mask) \ + ((if_mask == MV_DDR_32BIT_ECC_PUP8_BUS_MASK || if_mask == MV_DDR_64BIT_ECC_PUP8_BUS_MASK) ? 1 : 0) + +#define MV_DDR_IS_64BIT_DRAM_MODE(mask) \ + ((((mask) & MV_DDR_64BIT_BUS_MASK) == MV_DDR_64BIT_BUS_MASK) || \ + (((mask) & MV_DDR_64BIT_ECC_PUP8_BUS_MASK) == MV_DDR_64BIT_ECC_PUP8_BUS_MASK) ? 1 : 0) + +#define MV_DDR_IS_32BIT_IN_64BIT_DRAM_MODE(mask, octets_per_if_num/* FIXME: get from ATF */) \ + ((octets_per_if_num == 9/* FIXME: get from ATF */) && \ + ((mask == BUS_MASK_32BIT) || \ + (mask == MV_DDR_32BIT_ECC_PUP8_BUS_MASK)) ? 1 : 0) + +#define MV_DDR_IS_HALF_BUS_DRAM_MODE(mask, octets_per_if_num/* FIXME: get from ATF */) \ + (MV_DDR_IS_32BIT_IN_64BIT_DRAM_MODE(mask, octets_per_if_num) || DDR3_IS_16BIT_DRAM_MODE(mask)) + +#define ECC_READ_BUS_0 0 +#define ECC_PHY_ACCESS_3 3 +#define ECC_PHY_ACCESS_4 4 +#define ECC_PHY_ACCESS_8 8 #define MEGA 1000000 #define BUS_WIDTH_IN_BITS 8 +#define MAX_POLLING_ITERATIONS 1000000 +#define NUM_OF_CS 4 +#define ADLL_LENGTH 32 + +#define GP_RSVD0_REG 0x182e0 /* * DFX address Space @@ -67,205 +95,20 @@ /* nsec */ #define TREFI_LOW 7800 #define TREFI_HIGH 3900 +#define AUTO_ZQC_TIMING 15384 + +enum mr_number { + MR_CMD0, + MR_CMD1, + MR_CMD2, + MR_CMD3, + MR_LAST +}; -#define TR2R_VALUE_REG 0x180 -#define TR2R_MASK_REG 0x180 -#define TRFC_MASK_REG 0x7f -#define TR2W_MASK_REG 0x600 -#define TW2W_HIGH_VALUE_REG 0x1800 -#define TW2W_HIGH_MASK_REG 0xf800 -#define TRFC_HIGH_VALUE_REG 0x20000 -#define TRFC_HIGH_MASK_REG 0x70000 -#define TR2R_HIGH_VALUE_REG 0x0 -#define TR2R_HIGH_MASK_REG 0x380000 -#define TMOD_VALUE_REG 0x16000000 -#define TMOD_MASK_REG 0x1e000000 -#define T_VALUE_REG 0x40000000 -#define T_MASK_REG 0xc0000000 -#define AUTO_ZQC_TIMING 15384 -#define WRITE_XBAR_PORT1 0xc03f8077 -#define READ_XBAR_PORT1 0xc03f8073 -#define DISABLE_DDR_TUNING_DATA 0x02294285 -#define ENABLE_DDR_TUNING_DATA 0x12294285 - -#define ODPG_TRAINING_STATUS_REG 0x18488 -#define ODPG_TRAINING_TRIGGER_REG 0x1030 -#define ODPG_STATUS_DONE_REG 0x16fc -#define ODPG_ENABLE_REG 0x186d4 -#define ODPG_ENABLE_OFFS 0 -#define ODPG_DISABLE_OFFS 8 - -#define ODPG_TRAINING_CONTROL_REG 0x1034 -#define ODPG_OBJ1_OPCODE_REG 0x103c -#define ODPG_OBJ1_ITER_CNT_REG 0x10b4 -#define CALIB_OBJ_PRFA_REG 0x10c4 -#define ODPG_WRITE_LEVELING_DONE_CNTR_REG 0x10f8 -#define ODPG_WRITE_READ_MODE_ENABLE_REG 0x10fc -#define TRAINING_OPCODE_1_REG 0x10b4 -#define SDRAM_CONFIGURATION_REG 0x1400 -#define DDR_CONTROL_LOW_REG 0x1404 -#define SDRAM_TIMING_LOW_REG 0x1408 -#define SDRAM_TIMING_HIGH_REG 0x140c -#define SDRAM_ACCESS_CONTROL_REG 0x1410 -#define SDRAM_OPEN_PAGE_CONTROL_REG 0x1414 -#define SDRAM_OPERATION_REG 0x1418 -#define DUNIT_CONTROL_HIGH_REG 0x1424 -#define ODT_TIMING_LOW 0x1428 -#define DDR_TIMING_REG 0x142c -#define ODT_TIMING_HI_REG 0x147c -#define SDRAM_INIT_CONTROL_REG 0x1480 -#define SDRAM_ODT_CONTROL_HIGH_REG 0x1498 -#define DUNIT_ODT_CONTROL_REG 0x149c -#define READ_BUFFER_SELECT_REG 0x14a4 -#define DUNIT_MMASK_REG 0x14b0 -#define CALIB_MACHINE_CTRL_REG 0x14cc -#define DRAM_DLL_TIMING_REG 0x14e0 -#define DRAM_ZQ_INIT_TIMIMG_REG 0x14e4 -#define DRAM_ZQ_TIMING_REG 0x14e8 -#define DFS_REG 0x1528 -#define READ_DATA_SAMPLE_DELAY 0x1538 -#define READ_DATA_READY_DELAY 0x153c -#define TRAINING_REG 0x15b0 -#define TRAINING_SW_1_REG 0x15b4 -#define TRAINING_SW_2_REG 0x15b8 -#define TRAINING_PATTERN_BASE_ADDRESS_REG 0x15bc -#define TRAINING_DBG_1_REG 0x15c0 -#define TRAINING_DBG_2_REG 0x15c4 -#define TRAINING_DBG_3_REG 0x15c8 -#define RANK_CTRL_REG 0x15e0 -#define TIMING_REG 0x15e4 -#define DRAM_PHY_CONFIGURATION 0x15ec -#define MR0_REG 0x15d0 -#define MR1_REG 0x15d4 -#define MR2_REG 0x15d8 -#define MR3_REG 0x15dc -#define TIMING_REG 0x15e4 -#define ODPG_CTRL_CONTROL_REG 0x1600 -#define ODPG_DATA_CONTROL_REG 0x1630 -#define ODPG_PATTERN_ADDR_OFFSET_REG 0x1638 -#define ODPG_DATA_BUF_SIZE_REG 0x163c -#define PHY_LOCK_STATUS_REG 0x1674 -#define PHY_REG_FILE_ACCESS 0x16a0 -#define TRAINING_WRITE_LEVELING_REG 0x16ac -#define ODPG_PATTERN_ADDR_REG 0x16b0 -#define ODPG_PATTERN_DATA_HI_REG 0x16b4 -#define ODPG_PATTERN_DATA_LOW_REG 0x16b8 -#define ODPG_BIST_LAST_FAIL_ADDR_REG 0x16bc -#define ODPG_BIST_DATA_ERROR_COUNTER_REG 0x16c0 -#define ODPG_BIST_FAILED_DATA_HI_REG 0x16c4 -#define ODPG_BIST_FAILED_DATA_LOW_REG 0x16c8 -#define ODPG_WRITE_DATA_ERROR_REG 0x16cc -#define CS_ENABLE_REG 0x16d8 -#define WR_LEVELING_DQS_PATTERN_REG 0x16dc - -#define ODPG_BIST_DONE 0x186d4 -#define ODPG_BIST_DONE_BIT_OFFS 0 -#define ODPG_BIST_DONE_BIT_VALUE 0 - -#define RESULT_CONTROL_BYTE_PUP_0_REG 0x1830 -#define RESULT_CONTROL_BYTE_PUP_1_REG 0x1834 -#define RESULT_CONTROL_BYTE_PUP_2_REG 0x1838 -#define RESULT_CONTROL_BYTE_PUP_3_REG 0x183c -#define RESULT_CONTROL_BYTE_PUP_4_REG 0x18b0 - -#define RESULT_CONTROL_PUP_0_BIT_0_REG 0x18b4 -#define RESULT_CONTROL_PUP_0_BIT_1_REG 0x18b8 -#define RESULT_CONTROL_PUP_0_BIT_2_REG 0x18bc -#define RESULT_CONTROL_PUP_0_BIT_3_REG 0x18c0 -#define RESULT_CONTROL_PUP_0_BIT_4_REG 0x18c4 -#define RESULT_CONTROL_PUP_0_BIT_5_REG 0x18c8 -#define RESULT_CONTROL_PUP_0_BIT_6_REG 0x18cc -#define RESULT_CONTROL_PUP_0_BIT_7_REG 0x18f0 -#define RESULT_CONTROL_PUP_1_BIT_0_REG 0x18f4 -#define RESULT_CONTROL_PUP_1_BIT_1_REG 0x18f8 -#define RESULT_CONTROL_PUP_1_BIT_2_REG 0x18fc -#define RESULT_CONTROL_PUP_1_BIT_3_REG 0x1930 -#define RESULT_CONTROL_PUP_1_BIT_4_REG 0x1934 -#define RESULT_CONTROL_PUP_1_BIT_5_REG 0x1938 -#define RESULT_CONTROL_PUP_1_BIT_6_REG 0x193c -#define RESULT_CONTROL_PUP_1_BIT_7_REG 0x19b0 -#define RESULT_CONTROL_PUP_2_BIT_0_REG 0x19b4 -#define RESULT_CONTROL_PUP_2_BIT_1_REG 0x19b8 -#define RESULT_CONTROL_PUP_2_BIT_2_REG 0x19bc -#define RESULT_CONTROL_PUP_2_BIT_3_REG 0x19c0 -#define RESULT_CONTROL_PUP_2_BIT_4_REG 0x19c4 -#define RESULT_CONTROL_PUP_2_BIT_5_REG 0x19c8 -#define RESULT_CONTROL_PUP_2_BIT_6_REG 0x19cc -#define RESULT_CONTROL_PUP_2_BIT_7_REG 0x19f0 -#define RESULT_CONTROL_PUP_3_BIT_0_REG 0x19f4 -#define RESULT_CONTROL_PUP_3_BIT_1_REG 0x19f8 -#define RESULT_CONTROL_PUP_3_BIT_2_REG 0x19fc -#define RESULT_CONTROL_PUP_3_BIT_3_REG 0x1a30 -#define RESULT_CONTROL_PUP_3_BIT_4_REG 0x1a34 -#define RESULT_CONTROL_PUP_3_BIT_5_REG 0x1a38 -#define RESULT_CONTROL_PUP_3_BIT_6_REG 0x1a3c -#define RESULT_CONTROL_PUP_3_BIT_7_REG 0x1ab0 -#define RESULT_CONTROL_PUP_4_BIT_0_REG 0x1ab4 -#define RESULT_CONTROL_PUP_4_BIT_1_REG 0x1ab8 -#define RESULT_CONTROL_PUP_4_BIT_2_REG 0x1abc -#define RESULT_CONTROL_PUP_4_BIT_3_REG 0x1ac0 -#define RESULT_CONTROL_PUP_4_BIT_4_REG 0x1ac4 -#define RESULT_CONTROL_PUP_4_BIT_5_REG 0x1ac8 -#define RESULT_CONTROL_PUP_4_BIT_6_REG 0x1acc -#define RESULT_CONTROL_PUP_4_BIT_7_REG 0x1af0 - -#define WL_PHY_REG 0x0 -#define WRITE_CENTRALIZATION_PHY_REG 0x1 -#define RL_PHY_REG 0x2 -#define READ_CENTRALIZATION_PHY_REG 0x3 -#define PBS_RX_PHY_REG 0x50 -#define PBS_TX_PHY_REG 0x10 -#define PHY_CONTROL_PHY_REG 0x90 -#define BW_PHY_REG 0x92 -#define RATE_PHY_REG 0x94 -#define CMOS_CONFIG_PHY_REG 0xa2 -#define PAD_ZRI_CALIB_PHY_REG 0xa4 -#define PAD_ODT_CALIB_PHY_REG 0xa6 -#define PAD_CONFIG_PHY_REG 0xa8 -#define PAD_PRE_DISABLE_PHY_REG 0xa9 -#define TEST_ADLL_REG 0xbf -#define CSN_IOB_VREF_REG(cs) (0xdb + (cs * 12)) -#define CSN_IO_BASE_VREF_REG(cs) (0xd0 + (cs * 12)) - -#define RESULT_DB_PHY_REG_ADDR 0xc0 -#define RESULT_DB_PHY_REG_RX_OFFSET 5 -#define RESULT_DB_PHY_REG_TX_OFFSET 0 - -/* TBD - for NP5 use only CS 0 */ -#define PHY_WRITE_DELAY(cs) WL_PHY_REG -/*( ( _cs_ == 0 ) ? 0x0 : 0x4 )*/ -/* TBD - for NP5 use only CS 0 */ -#define PHY_READ_DELAY(cs) RL_PHY_REG - -#define DDR0_ADDR_1 0xf8258 -#define DDR0_ADDR_2 0xf8254 -#define DDR1_ADDR_1 0xf8270 -#define DDR1_ADDR_2 0xf8270 -#define DDR2_ADDR_1 0xf825c -#define DDR2_ADDR_2 0xf825c -#define DDR3_ADDR_1 0xf8264 -#define DDR3_ADDR_2 0xf8260 -#define DDR4_ADDR_1 0xf8274 -#define DDR4_ADDR_2 0xf8274 - -#define GENERAL_PURPOSE_RESERVED0_REG 0x182e0 - -#define GET_BLOCK_ID_MAX_FREQ(dev_num, block_id) 800000 -#define CS0_RD_LVL_REF_DLY_OFFS 0 -#define CS0_RD_LVL_REF_DLY_LEN 0 -#define CS0_RD_LVL_PH_SEL_OFFS 0 -#define CS0_RD_LVL_PH_SEL_LEN 0 - -#define CS_REGISTER_ADDR_OFFSET 4 -#define CALIBRATED_OBJECTS_REG_ADDR_OFFSET 0x10 - -#define MAX_POLLING_ITERATIONS 100000 - -#define PHASE_REG_OFFSET 32 -#define NUM_BYTES_IN_BURST 31 -#define NUM_OF_CS 4 -#define CS_REG_VALUE(cs_num) (cs_mask_reg[cs_num]) -#define ADLL_LENGTH 32 +struct mv_ddr_mr_data { + u32 cmd; + u32 reg_addr; +}; struct write_supp_result { enum hws_wl_supp stage; @@ -315,10 +158,11 @@ int ddr3_tip_ext_read(u32 dev_num, u32 if_id, u32 reg_addr, int ddr3_tip_ext_write(u32 dev_num, u32 if_id, u32 reg_addr, u32 num_of_bursts, u32 *addr); int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 ui_freq); +int mv_ddr_rl_dqs_burst(u32 dev_num, u32 if_id, u32 freq); int ddr3_tip_legacy_dynamic_read_leveling(u32 dev_num); int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 ui_freq); int ddr3_tip_legacy_dynamic_write_leveling(u32 dev_num); -int ddr3_tip_dynamic_write_leveling(u32 dev_num); +int ddr3_tip_dynamic_write_leveling(u32 dev_num, int phase_remove); int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num); int ddr3_tip_static_init_controller(u32 dev_num); int ddr3_tip_configure_phy(u32 dev_num); @@ -332,18 +176,21 @@ int ddr3_tip_configure_odpg(u32 dev_num, enum hws_access_type access_type, u32 delay_between_burst, u32 rd_mode, u32 cs_num, u32 addr_stress_jump, u32 single_pattern); int ddr3_tip_set_atr(u32 dev_num, u32 flag_id, u32 value); -int ddr3_tip_write_mrs_cmd(u32 dev_num, u32 *cs_mask_arr, u32 cmd, u32 data, - u32 mask); +int ddr3_tip_write_mrs_cmd(u32 dev_num, u32 *cs_mask_arr, enum mr_number mr_num, u32 data, u32 mask); int ddr3_tip_write_cs_result(u32 dev_num, u32 offset); int ddr3_tip_get_first_active_if(u8 dev_num, u32 interface_mask, u32 *if_id); int ddr3_tip_reset_fifo_ptr(u32 dev_num); -int read_pup_value(int pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], - int reg_addr, u32 mask); -int read_adll_value(u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], - int reg_addr, u32 mask); -int write_adll_value(u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], - int reg_addr); +int ddr3_tip_read_pup_value(u32 dev_num, + u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + int reg_addr, u32 mask); +int ddr3_tip_read_adll_value(u32 dev_num, + u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + u32 reg_addr, u32 mask); +int ddr3_tip_write_adll_value(u32 dev_num, + u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + u32 reg_addr); int ddr3_tip_tune_training_params(u32 dev_num, struct tune_train_params *params); +struct page_element *mv_ddr_page_tbl_get(void); #endif /* _DDR3_TRAINING_IP_FLOW_H_ */ diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_prv_if.h b/drivers/ddr/marvell/a38x/ddr3_training_ip_prv_if.h index 724b1062754f..5cf347750e3e 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip_prv_if.h +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_prv_if.h @@ -63,7 +63,7 @@ typedef int (*HWS_TRAINING_IP_PBS_TX_FUNC_PTR)(u32 dev_num); typedef int (*HWS_TRAINING_IP_SELECT_CONTROLLER_FUNC_PTR)( u32 dev_num, int enable); typedef int (*HWS_TRAINING_IP_TOPOLOGY_MAP_LOAD_FUNC_PTR)( - u32 dev_num, struct hws_topology_map *topology_map); + u32 dev_num, struct mv_ddr_topology_map *tm); typedef int (*HWS_TRAINING_IP_STATIC_CONFIG_FUNC_PTR)( u32 dev_num, enum hws_ddr_freq frequency, enum hws_static_config_type static_config_type, u32 if_id); @@ -84,16 +84,27 @@ typedef int (*HWS_TRAINING_IP_LOAD_TOPOLOGY)(u32 dev_num, u32 config_num); typedef int (*HWS_TRAINING_IP_READ_LEVELING)(u32 dev_num, u32 config_num); typedef int (*HWS_TRAINING_IP_WRITE_LEVELING)(u32 dev_num, u32 config_num); typedef u32 (*HWS_TRAINING_IP_GET_TEMP)(u8 dev_num); +typedef u8 (*HWS_TRAINING_IP_GET_RATIO)(u32 freq); struct hws_tip_config_func_db { HWS_TIP_DUNIT_MUX_SELECT_FUNC_PTR tip_dunit_mux_select_func; - HWS_TIP_DUNIT_REG_READ_FUNC_PTR tip_dunit_read_func; - HWS_TIP_DUNIT_REG_WRITE_FUNC_PTR tip_dunit_write_func; + void (*mv_ddr_dunit_read)(u32 addr, u32 mask, u32 *data); + void (*mv_ddr_dunit_write)(u32 addr, u32 mask, u32 data); HWS_TIP_GET_FREQ_CONFIG_INFO tip_get_freq_config_info_func; HWS_TIP_GET_DEVICE_INFO tip_get_device_info_func; HWS_SET_FREQ_DIVIDER_FUNC_PTR tip_set_freq_divider_func; HWS_GET_CS_CONFIG_FUNC_PTR tip_get_cs_config_info; HWS_TRAINING_IP_GET_TEMP tip_get_temperature; + HWS_TRAINING_IP_GET_RATIO tip_get_clock_ratio; + HWS_TRAINING_IP_EXTERNAL_READ_PTR tip_external_read; + HWS_TRAINING_IP_EXTERNAL_WRITE_PTR tip_external_write; + int (*mv_ddr_phy_read)(enum hws_access_type phy_access, + u32 phy, enum hws_ddr_phy phy_type, + u32 reg_addr, u32 *data); + int (*mv_ddr_phy_write)(enum hws_access_type phy_access, + u32 phy, enum hws_ddr_phy phy_type, + u32 reg_addr, u32 data, + enum hws_operation op_type); }; int ddr3_tip_init_config_func(u32 dev_num, diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_static.h b/drivers/ddr/marvell/a38x/ddr3_training_ip_static.h deleted file mode 100644 index 878068b24d7a..000000000000 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip_static.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#ifndef _DDR3_TRAINING_IP_STATIC_H_ -#define _DDR3_TRAINING_IP_STATIC_H_ - -#include "ddr3_training_ip_def.h" -#include "ddr3_training_ip.h" - -struct trip_delay_element { - u32 dqs_delay; /* DQS delay (m_sec) */ - u32 ck_delay; /* CK Delay (m_sec) */ -}; - -struct hws_tip_static_config_info { - u32 silicon_delay; - struct trip_delay_element *package_trace_arr; - struct trip_delay_element *board_trace_arr; -}; - -int ddr3_tip_run_static_alg(u32 dev_num, enum hws_ddr_freq freq); -int ddr3_tip_init_static_config_db( - u32 dev_num, struct hws_tip_static_config_info *static_config_info); -int ddr3_tip_init_specific_reg_config(u32 dev_num, - struct reg_data *reg_config_arr); -int ddr3_tip_static_phy_init_controller(u32 dev_num); - -#endif /* _DDR3_TRAINING_IP_STATIC_H_ */ diff --git a/drivers/ddr/marvell/a38x/ddr3_training_leveling.c b/drivers/ddr/marvell/a38x/ddr3_training_leveling.c index 3c40f198e775..96dc6600f095 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_leveling.c +++ b/drivers/ddr/marvell/a38x/ddr3_training_leveling.c @@ -4,17 +4,9 @@ * SPDX-License-Identifier: GPL-2.0 */ -#include -#include -#include -#include -#include - #include "ddr3_init.h" -#define WL_ITERATION_NUM 10 -#define ONE_CLOCK_ERROR_SHIFT 2 -#define ALIGN_ERROR_SHIFT -2 +#define WL_ITERATION_NUM 10 static u32 pup_mask_table[] = { 0x000000ff, @@ -28,26 +20,30 @@ static struct write_supp_result wr_supp_res[MAX_INTERFACE_NUM][MAX_BUS_NUM]; static int ddr3_tip_dynamic_write_leveling_seq(u32 dev_num); static int ddr3_tip_dynamic_read_leveling_seq(u32 dev_num); static int ddr3_tip_dynamic_per_bit_read_leveling_seq(u32 dev_num); -static int ddr3_tip_wl_supp_align_err_shift(u32 dev_num, u32 if_id, u32 bus_id, - u32 bus_id_delta); static int ddr3_tip_wl_supp_align_phase_shift(u32 dev_num, u32 if_id, - u32 bus_id, u32 offset, - u32 bus_id_delta); + u32 bus_id); static int ddr3_tip_xsb_compare_test(u32 dev_num, u32 if_id, u32 bus_id, - u32 edge_offset, u32 bus_id_delta); -static int ddr3_tip_wl_supp_one_clk_err_shift(u32 dev_num, u32 if_id, - u32 bus_id, u32 bus_id_delta); + u32 edge_offset); -u32 hws_ddr3_tip_max_cs_get(void) +u32 ddr3_tip_max_cs_get(u32 dev_num) { - u32 c_cs; + u32 c_cs, if_id, bus_id; static u32 max_cs; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); if (!max_cs) { + CHECK_STATUS(ddr3_tip_get_first_active_if((u8)dev_num, + tm->if_act_mask, + &if_id)); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); + break; + } + for (c_cs = 0; c_cs < NUM_OF_CS; c_cs++) { VALIDATE_ACTIVE(tm-> - interface_params[0].as_bus_params[0]. + interface_params[if_id].as_bus_params[bus_id]. cs_bitmask, c_cs); max_cs++; } @@ -56,13 +52,17 @@ u32 hws_ddr3_tip_max_cs_get(void) return max_cs; } +enum { + PASS, + FAIL +}; /***************************************************************************** Dynamic read leveling ******************************************************************************/ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) { u32 data, mask; - u32 max_cs = hws_ddr3_tip_max_cs_get(); + u32 max_cs = ddr3_tip_max_cs_get(dev_num); u32 bus_num, if_id, cl_val; enum hws_speed_bin speed_bin_index; /* save current CS value */ @@ -72,82 +72,9 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) u8 rl_values[NUM_OF_CS][MAX_BUS_NUM][MAX_INTERFACE_NUM]; struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); - struct hws_topology_map *tm = ddr3_get_topology_map(); - - if (rl_version == 0) { - /* OLD RL machine */ - data = 0x40; - data |= (1 << 20); - - /* TBD multi CS */ - CHECK_STATUS(ddr3_tip_if_write( - dev_num, ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, TRAINING_REG, - data, 0x11ffff)); - CHECK_STATUS(ddr3_tip_if_write( - dev_num, ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, - TRAINING_PATTERN_BASE_ADDRESS_REG, - 0, 0xfffffff8)); - CHECK_STATUS(ddr3_tip_if_write( - dev_num, ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, TRAINING_REG, - (u32)(1 << 31), (u32)(1 << 31))); - - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - training_result[training_stage][if_id] = TEST_SUCCESS; - if (ddr3_tip_if_polling - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0, - (u32)(1 << 31), TRAINING_REG, - MAX_POLLING_ITERATIONS) != MV_OK) { - DEBUG_LEVELING( - DEBUG_LEVEL_ERROR, - ("RL: DDR3 poll failed(1) IF %d\n", - if_id)); - training_result[training_stage][if_id] = - TEST_FAILED; - - if (debug_mode == 0) - return MV_FAIL; - } - } - - /* read read-leveling result */ - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_REG, data_read, 1 << 30)); - /* exit read leveling mode */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_SW_2_REG, 0x8, 0x9)); - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_SW_1_REG, 1 << 16, 1 << 16)); - - /* disable RL machine all Trn_CS[3:0] , [16:0] */ - - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_REG, 0, 0xf1ffff)); - - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - if ((data_read[if_id] & (1 << 30)) == 0) { - DEBUG_LEVELING( - DEBUG_LEVEL_ERROR, - ("\n_read Leveling failed for IF %d\n", - if_id)); - training_result[training_stage][if_id] = - TEST_FAILED; - if (debug_mode == 0) - return MV_FAIL; - } - } - return MV_OK; - } + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - /* NEW RL machine */ for (effective_cs = 0; effective_cs < NUM_OF_CS; effective_cs++) for (bus_num = 0; bus_num < MAX_BUS_NUM; bus_num++) for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) @@ -155,18 +82,18 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); training_result[training_stage][if_id] = TEST_SUCCESS; /* save current cs enable reg val */ CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, cs_enable_reg_val, + DUAL_DUNIT_CFG_REG, cs_enable_reg_val, MASK_ALL_BITS)); /* enable single cs */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, (1 << 3), (1 << 3))); + DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3))); } ddr3_tip_reset_fifo_ptr(dev_num); @@ -184,7 +111,7 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) /* BUS count is 0 shifted 26 */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0x3, 0x3)); + ODPG_DATA_CTRL_REG, 0x3, 0x3)); CHECK_STATUS(ddr3_tip_configure_odpg (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0, pattern_table[PATTERN_RL].num_of_phases_tx, 0, @@ -204,17 +131,17 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) /* General Training Opcode register */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_WRITE_READ_MODE_ENABLE_REG, 0, + ODPG_WR_RD_MODE_ENA_REG, 0, MASK_ALL_BITS)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_TRAINING_CONTROL_REG, + GENERAL_TRAINING_OPCODE_REG, (0x301b01 | effective_cs << 2), 0x3c3fef)); /* Object1 opcode register 0 & 1 */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); speed_bin_index = tm->interface_params[if_id].speed_bin_index; cl_val = @@ -223,13 +150,13 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) mask = (0xff << 9) | (0x1f << 17) | (0x3 << 25); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_OBJ1_OPCODE_REG, data, mask)); + OPCODE_REG0_REG(1), data, mask)); } /* Set iteration count to max value */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_OPCODE_1_REG, 0xd00, 0xd00)); + OPCODE_REG1_REG(1), 0xd00, 0xd00)); /* * Phase 2: Mask config @@ -253,11 +180,11 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) /* data pup rd reset enable */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - SDRAM_CONFIGURATION_REG, 0, (1 << 30))); + SDRAM_CFG_REG, 0, (1 << 30))); /* data pup rd reset disable */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - SDRAM_CONFIGURATION_REG, (1 << 30), (1 << 30))); + SDRAM_CFG_REG, (1 << 30), (1 << 30))); /* training SW override & training RL mode */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, @@ -271,72 +198,46 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, TRAINING_REG, (u32)(1 << 31), (u32)(1 << 31))); - /********* trigger training *******************/ - /* Trigger, poll on status and disable ODPG */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_TRAINING_TRIGGER_REG, 0x1, 0x1)); - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_TRAINING_STATUS_REG, 0x1, 0x1)); + /* trigger training */ + mv_ddr_training_enable(); - /* check for training done + results pass */ - if (ddr3_tip_if_polling - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0x2, 0x2, - ODPG_TRAINING_STATUS_REG, - MAX_POLLING_ITERATIONS) != MV_OK) { - DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("Training Done Failed\n")); + /* check for training done */ + if (mv_ddr_is_training_done(MAX_POLLING_ITERATIONS, &data) != MV_OK) { + DEBUG_LEVELING(DEBUG_LEVEL_ERROR, ("training done failed\n")); return MV_FAIL; } + /* check for training pass */ + if (data != PASS) + DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("training result failed\n")); - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, - if_id, - ODPG_TRAINING_TRIGGER_REG, data_read, - 0x4)); - data = data_read[if_id]; - if (data != 0x0) { - DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("Training Result Failed\n")); - } - } + /* disable odpg; switch back to functional mode */ + mv_ddr_odpg_disable(); - /*disable ODPG - Back to functional mode */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_ENABLE_REG, 0x1 << ODPG_DISABLE_OFFS, - (0x1 << ODPG_DISABLE_OFFS))); - if (ddr3_tip_if_polling - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0x0, 0x1, - ODPG_ENABLE_REG, MAX_POLLING_ITERATIONS) != MV_OK) { - DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("ODPG disable failed ")); + if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK) { + DEBUG_LEVELING(DEBUG_LEVEL_ERROR, ("odpg disable failed\n")); return MV_FAIL; } - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0, MASK_ALL_BITS)); + + ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS); /* double loop on bus, pup */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* check training done */ is_any_pup_fail = 0; for (bus_num = 0; - bus_num < tm->num_of_bus_per_interface; + bus_num < octets_per_if_num; bus_num++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_num); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num); if (ddr3_tip_if_polling (dev_num, ACCESS_TYPE_UNICAST, if_id, (1 << 25), (1 << 25), mask_results_pup_reg_map[bus_num], MAX_POLLING_ITERATIONS) != MV_OK) { DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("\n_r_l: DDR3 poll failed(2) for bus %d", - bus_num)); + ("\n_r_l: DDR3 poll failed(2) for IF %d CS %d bus %d", + if_id, effective_cs, bus_num)); is_any_pup_fail = 1; } else { /* read result per pup */ @@ -375,26 +276,26 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) /* set ODPG to functional */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0x0, MASK_ALL_BITS)); + ODPG_DATA_CTRL_REG, 0x0, MASK_ALL_BITS)); /* * Copy the result from the effective CS search to the * real Functional CS */ - /*ddr3_tip_write_cs_result(dev_num, RL_PHY_REG); */ + /*ddr3_tip_write_cs_result(dev_num, RL_PHY_REG(0); */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0x0, MASK_ALL_BITS)); + ODPG_DATA_CTRL_REG, 0x0, MASK_ALL_BITS)); } for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { /* double loop on bus, pup */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (bus_num = 0; - bus_num < tm->num_of_bus_per_interface; + bus_num < octets_per_if_num; bus_num++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_num); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num); /* read result per pup from arry */ data = rl_values[effective_cs][bus_num][if_id]; data = (data & 0x1f) | @@ -404,9 +305,8 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) if_id, ACCESS_TYPE_UNICAST, bus_num, DDR_PHY_DATA, - RL_PHY_REG + - ((effective_cs == - 0) ? 0x0 : 0x4), data); + RL_PHY_REG(effective_cs), + data); } } } @@ -414,11 +314,11 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) effective_cs = 0; for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* restore cs enable value */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, cs_enable_reg_val[if_id], + DUAL_DUNIT_CFG_REG, cs_enable_reg_val[if_id], MASK_ALL_BITS)); if (odt_config != 0) { CHECK_STATUS(ddr3_tip_write_additional_odt_setting @@ -427,7 +327,7 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) } for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (training_result[training_stage][if_id] == TEST_FAILED) return MV_FAIL; } @@ -441,8 +341,8 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) int ddr3_tip_legacy_dynamic_write_leveling(u32 dev_num) { u32 c_cs, if_id, cs_mask = 0; - u32 max_cs = hws_ddr3_tip_max_cs_get(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 max_cs = ddr3_tip_max_cs_get(dev_num); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* * In TRAINIUNG reg (0x15b0) write 0x80000008 | cs_mask: @@ -457,7 +357,7 @@ int ddr3_tip_legacy_dynamic_write_leveling(u32 dev_num) cs_mask = cs_mask | 1 << (20 + c_cs); for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, 0, TRAINING_REG, (0x80000008 | cs_mask), @@ -482,8 +382,8 @@ int ddr3_tip_legacy_dynamic_write_leveling(u32 dev_num) int ddr3_tip_legacy_dynamic_read_leveling(u32 dev_num) { u32 c_cs, if_id, cs_mask = 0; - u32 max_cs = hws_ddr3_tip_max_cs_get(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 max_cs = ddr3_tip_max_cs_get(dev_num); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* * In TRAINIUNG reg (0x15b0) write 0x80000040 | cs_mask: @@ -503,7 +403,7 @@ int ddr3_tip_legacy_dynamic_read_leveling(u32 dev_num) mdelay(100); for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (ddr3_tip_if_polling (dev_num, ACCESS_TYPE_UNICAST, if_id, 0, (u32)0x80000000, TRAINING_REG, @@ -536,38 +436,39 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) u32 data2_write[MAX_INTERFACE_NUM][MAX_BUS_NUM]; struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (bus_num = 0; - bus_num <= tm->num_of_bus_per_interface; bus_num++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_num); + bus_num <= octets_per_if_num; bus_num++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num); per_bit_rl_pup_status[if_id][bus_num] = 0; data2_write[if_id][bus_num] = 0; /* read current value of phy register 0x3 */ CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_num, DDR_PHY_DATA, - READ_CENTRALIZATION_PHY_REG, + CRX_PHY_REG(0), &phyreg3_arr[if_id][bus_num])); } } /* NEW RL machine */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); training_result[training_stage][if_id] = TEST_SUCCESS; /* save current cs enable reg val */ CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, &cs_enable_reg_val[if_id], + DUAL_DUNIT_CFG_REG, &cs_enable_reg_val[if_id], MASK_ALL_BITS)); /* enable single cs */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, (1 << 3), (1 << 3))); + DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3))); } ddr3_tip_reset_fifo_ptr(dev_num); @@ -585,7 +486,7 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) /* BUS count is 0 shifted 26 */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0x3, 0x3)); + ODPG_DATA_CTRL_REG, 0x3, 0x3)); CHECK_STATUS(ddr3_tip_configure_odpg (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0, pattern_table[PATTERN_TEST].num_of_phases_tx, 0, @@ -605,15 +506,15 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) /* General Training Opcode register */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_WRITE_READ_MODE_ENABLE_REG, 0, + ODPG_WR_RD_MODE_ENA_REG, 0, MASK_ALL_BITS)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_TRAINING_CONTROL_REG, 0x301b01, 0x3c3fef)); + GENERAL_TRAINING_OPCODE_REG, 0x301b01, 0x3c3fef)); /* Object1 opcode register 0 & 1 */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); speed_bin_index = tm->interface_params[if_id].speed_bin_index; cl_val = @@ -622,13 +523,13 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) mask = (0xff << 9) | (0x1f << 17) | (0x3 << 25); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_OBJ1_OPCODE_REG, data, mask)); + OPCODE_REG0_REG(1), data, mask)); } /* Set iteration count to max value */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_OPCODE_1_REG, 0xd00, 0xd00)); + OPCODE_REG1_REG(1), 0xd00, 0xd00)); /* * Phase 2: Mask config @@ -652,11 +553,11 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) /* data pup rd reset enable */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - SDRAM_CONFIGURATION_REG, 0, (1 << 30))); + SDRAM_CFG_REG, 0, (1 << 30))); /* data pup rd reset disable */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - SDRAM_CONFIGURATION_REG, (1 << 30), (1 << 30))); + SDRAM_CFG_REG, (1 << 30), (1 << 30))); /* training SW override & training RL mode */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, @@ -670,63 +571,37 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, TRAINING_REG, (u32)(1 << 31), (u32)(1 << 31))); - /********* trigger training *******************/ - /* Trigger, poll on status and disable ODPG */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_TRAINING_TRIGGER_REG, 0x1, 0x1)); - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_TRAINING_STATUS_REG, 0x1, 0x1)); + /* trigger training */ + mv_ddr_training_enable(); - /*check for training done + results pass */ - if (ddr3_tip_if_polling - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0x2, 0x2, - ODPG_TRAINING_STATUS_REG, - MAX_POLLING_ITERATIONS) != MV_OK) { - DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("Training Done Failed\n")); + /* check for training done */ + if (mv_ddr_is_training_done(MAX_POLLING_ITERATIONS, &data) != MV_OK) { + DEBUG_LEVELING(DEBUG_LEVEL_ERROR, ("training done failed\n")); return MV_FAIL; } + /* check for training pass */ + if (data != PASS) + DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("training result failed\n")); - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, - if_id, - ODPG_TRAINING_TRIGGER_REG, data_read, - 0x4)); - data = data_read[if_id]; - if (data != 0x0) { - DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("Training Result Failed\n")); - } - } + /* disable odpg; switch back to functional mode */ + mv_ddr_odpg_disable(); - /*disable ODPG - Back to functional mode */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_ENABLE_REG, 0x1 << ODPG_DISABLE_OFFS, - (0x1 << ODPG_DISABLE_OFFS))); - if (ddr3_tip_if_polling - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0x0, 0x1, - ODPG_ENABLE_REG, MAX_POLLING_ITERATIONS) != MV_OK) { - DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("ODPG disable failed ")); + if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK) { + DEBUG_LEVELING(DEBUG_LEVEL_ERROR, ("odpg disable failed\n")); return MV_FAIL; } - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0, MASK_ALL_BITS)); + + ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS); /* double loop on bus, pup */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* check training done */ for (bus_num = 0; - bus_num < tm->num_of_bus_per_interface; + bus_num < octets_per_if_num; bus_num++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_num); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num); if (per_bit_rl_pup_status[if_id][bus_num] == 0) { @@ -796,11 +671,11 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) /* if there is DLL that is not checked yet */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (bus_num = 0; - bus_num < tm->num_of_bus_per_interface; + bus_num < octets_per_if_num; bus_num++) { - VALIDATE_ACTIVE(tm->bus_act_mask, + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num); if (per_bit_rl_pup_status[if_id] [bus_num] != 1) { @@ -812,7 +687,7 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) if_id, ACCESS_TYPE_UNICAST, bus_num, DDR_PHY_DATA, - READ_CENTRALIZATION_PHY_REG, + CRX_PHY_REG(0), (phyreg3_arr[if_id] [bus_num] + adll_array[curr_numb]))); @@ -829,18 +704,17 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) } /* for ( curr_numb = 0; curr_numb <3; curr_numb++) */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_num = 0; bus_num < tm->num_of_bus_per_interface; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_num = 0; bus_num < octets_per_if_num; bus_num++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_num); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num); if (per_bit_rl_pup_status[if_id][bus_num] == 1) ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, bus_num, DDR_PHY_DATA, - RL_PHY_REG + - CS_REG_VALUE(effective_cs), + RL_PHY_REG(effective_cs), data2_write[if_id] [bus_num]); else @@ -882,22 +756,22 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) /* set ODPG to functional */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0x0, MASK_ALL_BITS)); + ODPG_DATA_CTRL_REG, 0x0, MASK_ALL_BITS)); /* * Copy the result from the effective CS search to the real * Functional CS */ - ddr3_tip_write_cs_result(dev_num, RL_PHY_REG); + ddr3_tip_write_cs_result(dev_num, RL_PHY_REG(0)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0x0, MASK_ALL_BITS)); + ODPG_DATA_CTRL_REG, 0x0, MASK_ALL_BITS)); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* restore cs enable value */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, cs_enable_reg_val[if_id], + DUAL_DUNIT_CFG_REG, cs_enable_reg_val[if_id], MASK_ALL_BITS)); if (odt_config != 0) { CHECK_STATUS(ddr3_tip_write_additional_odt_setting @@ -906,7 +780,7 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) } for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (training_result[training_stage][if_id] == TEST_FAILED) return MV_FAIL; } @@ -919,7 +793,8 @@ int ddr3_tip_calc_cs_mask(u32 dev_num, u32 if_id, u32 effective_cs, { u32 all_bus_cs = 0, same_bus_cs; u32 bus_cnt; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); *cs_mask = same_bus_cs = CS_BIT_MASK; @@ -932,8 +807,8 @@ int ddr3_tip_calc_cs_mask(u32 dev_num, u32 if_id, u32 effective_cs, * If they are they are not the same then it's mixed mode so all CS * should be configured (when configuring the MRS) */ - for (bus_cnt = 0; bus_cnt < tm->num_of_bus_per_interface; bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); all_bus_cs |= tm->interface_params[if_id]. as_bus_params[bus_cnt].cs_bitmask; @@ -954,9 +829,9 @@ int ddr3_tip_calc_cs_mask(u32 dev_num, u32 if_id, u32 effective_cs, /* * Dynamic write leveling */ -int ddr3_tip_dynamic_write_leveling(u32 dev_num) +int ddr3_tip_dynamic_write_leveling(u32 dev_num, int phase_remove) { - u32 reg_data = 0, iter, if_id, bus_cnt; + u32 reg_data = 0, temp = 0, iter, if_id, bus_cnt; u32 cs_enable_reg_val[MAX_INTERFACE_NUM] = { 0 }; u32 cs_mask[MAX_INTERFACE_NUM]; u32 read_data_sample_delay_vals[MAX_INTERFACE_NUM] = { 0 }; @@ -968,28 +843,36 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) u8 wl_values[NUM_OF_CS][MAX_BUS_NUM][MAX_INTERFACE_NUM]; u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); u32 cs_mask0[MAX_INTERFACE_NUM] = { 0 }; - u32 max_cs = hws_ddr3_tip_max_cs_get(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 max_cs = ddr3_tip_max_cs_get(dev_num); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); training_result[training_stage][if_id] = TEST_SUCCESS; /* save Read Data Sample Delay */ CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, - READ_DATA_SAMPLE_DELAY, + RD_DATA_SMPL_DLYS_REG, read_data_sample_delay_vals, MASK_ALL_BITS)); /* save Read Data Ready Delay */ CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, - READ_DATA_READY_DELAY, read_data_ready_delay_vals, + RD_DATA_RDY_DLYS_REG, read_data_ready_delay_vals, MASK_ALL_BITS)); /* save current cs reg val */ CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, cs_enable_reg_val, MASK_ALL_BITS)); + DUAL_DUNIT_CFG_REG, cs_enable_reg_val, MASK_ALL_BITS)); + } + + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) < MV_TIP_REV_3) { + /* Enable multi-CS */ + CHECK_STATUS(ddr3_tip_if_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + DUAL_DUNIT_CFG_REG, 0, (1 << 3))); } /* @@ -999,19 +882,19 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) /*Assert 10 refresh commands to DRAM to all CS */ for (iter = 0; iter < WL_ITERATION_NUM; iter++) { for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, - if_id, SDRAM_OPERATION_REG, + if_id, SDRAM_OP_REG, (u32)((~(0xf) << 8) | 0x2), 0xf1f)); } } /* check controller back to normal */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (ddr3_tip_if_polling (dev_num, ACCESS_TYPE_UNICAST, if_id, 0, 0x1f, - SDRAM_OPERATION_REG, MAX_POLLING_ITERATIONS) != MV_OK) { + SDRAM_OP_REG, MAX_POLLING_ITERATIONS) != MV_OK) { DEBUG_LEVELING(DEBUG_LEVEL_ERROR, ("WL: DDR3 poll failed(3)")); } @@ -1020,24 +903,30 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { /*enable write leveling to all cs - Q off , WL n */ /* calculate interface cs mask */ - CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask0, MRS1_CMD, + CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask0, MR_CMD1, 0x1000, 0x1080)); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* cs enable is active low */ ddr3_tip_calc_cs_mask(dev_num, if_id, effective_cs, &cs_mask[if_id]); } - /* Enable Output buffer to relevant CS - Q on , WL on */ - CHECK_STATUS(ddr3_tip_write_mrs_cmd - (dev_num, cs_mask, MRS1_CMD, 0x80, 0x1080)); + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) { + /* Enable Output buffer to relevant CS - Q on , WL on */ + CHECK_STATUS(ddr3_tip_write_mrs_cmd + (dev_num, cs_mask, MR_CMD1, 0x80, 0x1080)); - /*enable odt for relevant CS */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - 0x1498, (0x3 << (effective_cs * 2)), 0xf)); + /*enable odt for relevant CS */ + CHECK_STATUS(ddr3_tip_if_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + 0x1498, (0x3 << (effective_cs * 2)), 0xf)); + } else { + /* FIXME: should be the same as _CPU case */ + CHECK_STATUS(ddr3_tip_write_mrs_cmd + (dev_num, cs_mask, MR_CMD1, 0xc0, 0x12c4)); + } /* * Phase 2: Set training IP to write leveling mode @@ -1045,110 +934,91 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) CHECK_STATUS(ddr3_tip_dynamic_write_leveling_seq(dev_num)); + /* phase 3: trigger training */ + mv_ddr_training_enable(); + + /* check for training done */ + if (mv_ddr_is_training_done(MAX_POLLING_ITERATIONS, data_read) != MV_OK) { + DEBUG_LEVELING(DEBUG_LEVEL_ERROR, ("training done failed\n")); + } else { /* check for training pass */ + reg_data = data_read[0]; +#if defined(CONFIG_ARMADA_38X) /* JIRA #1498 for 16 bit with ECC */ + if (tm->bus_act_mask == 0xb) /* set to data to 0 to skip the check */ + reg_data = 0; +#endif + if (reg_data != PASS) + DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("training result failed\n")); + + /* check for training completion per bus */ + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); + /* training status */ + ddr3_tip_if_read(0, ACCESS_TYPE_UNICAST, 0, + mask_results_pup_reg_map[bus_cnt], + data_read, MASK_ALL_BITS); + reg_data = data_read[0]; + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, ("WL: IF %d BUS %d reg 0x%x\n", + 0, bus_cnt, reg_data)); + if ((reg_data & (1 << 25)) == 0) + res_values[bus_cnt] = 1; + ddr3_tip_if_read(0, ACCESS_TYPE_UNICAST, 0, + mask_results_pup_reg_map[bus_cnt], + data_read, 0xff); + /* + * Save the read value that should be + * write to PHY register + */ + wl_values[effective_cs][bus_cnt][0] = (u8)data_read[0]; + } + } + /* - * Phase 3: Trigger training + * Phase 3.5: Validate result */ - - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_TRAINING_TRIGGER_REG, 0x1, 0x1)); - for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - - /* training done */ - if (ddr3_tip_if_polling - (dev_num, ACCESS_TYPE_UNICAST, if_id, - (1 << 1), (1 << 1), ODPG_TRAINING_STATUS_REG, - MAX_POLLING_ITERATIONS) != MV_OK) { - DEBUG_LEVELING( - DEBUG_LEVEL_ERROR, - ("WL: DDR3 poll (4) failed (Data: 0x%x)\n", - reg_data)); - } -#if !defined(CONFIG_ARMADA_38X) /*Disabled. JIRA #1498 */ - else { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); + /* + * Read result control register according to subphy + * "16" below is for a half-phase + */ + reg_data = wl_values[effective_cs][bus_cnt][if_id] + 16; + /* + * Write to WL register: ADLL [4:0], Phase [8:6], + * Centralization ADLL [15:10] + 0x10 + */ + reg_data = (reg_data & 0x1f) | + (((reg_data & 0xe0) >> 5) << 6) | + (((reg_data & 0x1f) + phy_reg1_val) << 10); + /* Search with WL CS0 subphy reg */ + ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, bus_cnt, + DDR_PHY_DATA, WL_PHY_REG(0), reg_data); + /* + * Check for change in data read from DRAM. + * If changed, fix the result + */ CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, + (dev_num, + ACCESS_TYPE_UNICAST, if_id, - ODPG_TRAINING_TRIGGER_REG, - ®_data, (1 << 2))); - if (reg_data != 0) { + TRAINING_WL_REG, + data_read, MASK_ALL_BITS)); + if (((data_read[if_id] & (1 << (bus_cnt + 20))) >> + (bus_cnt + 20)) == 0) { DEBUG_LEVELING( DEBUG_LEVEL_ERROR, - ("WL: WL failed IF %d reg_data=0x%x\n", - if_id, reg_data)); - } - } -#endif - } - - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - /* training done */ - if (ddr3_tip_if_polling - (dev_num, ACCESS_TYPE_UNICAST, if_id, - (1 << 1), (1 << 1), ODPG_TRAINING_STATUS_REG, - MAX_POLLING_ITERATIONS) != MV_OK) { - DEBUG_LEVELING( - DEBUG_LEVEL_ERROR, - ("WL: DDR3 poll (4) failed (Data: 0x%x)\n", - reg_data)); - } else { -#if !defined(CONFIG_ARMADA_38X) /*Disabled. JIRA #1498 */ - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, - if_id, - ODPG_TRAINING_STATUS_REG, - data_read, (1 << 2))); - reg_data = data_read[if_id]; - if (reg_data != 0) { + ("WLValues was changed from 0x%X", + wl_values[effective_cs] + [bus_cnt][if_id])); + wl_values[effective_cs] + [bus_cnt][if_id] += 32; DEBUG_LEVELING( DEBUG_LEVEL_ERROR, - ("WL: WL failed IF %d reg_data=0x%x\n", - if_id, reg_data)); - } -#endif - - /* check for training completion per bus */ - for (bus_cnt = 0; - bus_cnt < tm->num_of_bus_per_interface; - bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, - bus_cnt); - /* training status */ - CHECK_STATUS(ddr3_tip_if_read - (dev_num, - ACCESS_TYPE_UNICAST, - if_id, - mask_results_pup_reg_map - [bus_cnt], data_read, - (1 << 25))); - reg_data = data_read[if_id]; - DEBUG_LEVELING( - DEBUG_LEVEL_TRACE, - ("WL: IF %d BUS %d reg 0x%x\n", - if_id, bus_cnt, reg_data)); - if (reg_data == 0) { - res_values[ - (if_id * - tm->num_of_bus_per_interface) - + bus_cnt] = 1; - } - CHECK_STATUS(ddr3_tip_if_read - (dev_num, - ACCESS_TYPE_UNICAST, - if_id, - mask_results_pup_reg_map - [bus_cnt], data_read, - 0xff)); - /* - * Save the read value that should be - * write to PHY register - */ - wl_values[effective_cs] - [bus_cnt][if_id] = - (u8)data_read[if_id]; + ("to 0x%X", + wl_values[effective_cs] + [bus_cnt][if_id])); } } } @@ -1160,15 +1030,21 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) /* disable DQs toggling */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - WR_LEVELING_DQS_PATTERN_REG, 0x0, 0x1)); + WL_DQS_PATTERN_REG, 0x0, 0x1)); /* Update MRS 1 (WL off) */ - CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask0, MRS1_CMD, - 0x1000, 0x1080)); + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) { + CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask0, MR_CMD1, + 0x1000, 0x1080)); + } else { + /* FIXME: should be same as _CPU case */ + CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask0, MR_CMD1, + 0x1000, 0x12c4)); + } /* Update MRS 1 (return to functional mode - Q on , WL off) */ CHECK_STATUS(ddr3_tip_write_mrs_cmd - (dev_num, cs_mask0, MRS1_CMD, 0x0, 0x1080)); + (dev_num, cs_mask0, MR_CMD1, 0x0, 0x1080)); /* set phy to normal mode */ CHECK_STATUS(ddr3_tip_if_write @@ -1187,16 +1063,16 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); test_res = 0; for (bus_cnt = 0; - bus_cnt < tm->num_of_bus_per_interface; + bus_cnt < octets_per_if_num; bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); /* check if result == pass */ if (res_values [(if_id * - tm->num_of_bus_per_interface) + + octets_per_if_num) + bus_cnt] == 0) { /* * read result control register @@ -1215,6 +1091,18 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) (((reg_data & 0xe0) >> 5) << 6) | (((reg_data & 0x1f) + phy_reg1_val) << 10); + /* + * in case phase remove should be executed + * need to remove more than one phase. + * this will take place only in low frequency, + * where there could be more than one phase between sub-phys + */ + if (phase_remove == 1) { + temp = (reg_data >> WR_LVL_PH_SEL_OFFS) & WR_LVL_PH_SEL_PHASE1; + reg_data &= ~(WR_LVL_PH_SEL_MASK << WR_LVL_PH_SEL_OFFS); + reg_data |= (temp << WR_LVL_PH_SEL_OFFS); + } + ddr3_tip_bus_write( dev_num, ACCESS_TYPE_UNICAST, @@ -1222,9 +1110,7 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - WL_PHY_REG + - effective_cs * - CS_REGISTER_ADDR_OFFSET, + WL_PHY_REG(effective_cs), reg_data); } else { test_res = 1; @@ -1260,38 +1146,48 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) * Copy the result from the effective CS search to the real * Functional CS */ - /* ddr3_tip_write_cs_result(dev_num, WL_PHY_REG); */ + /* ddr3_tip_write_cs_result(dev_num, WL_PHY_REG(0); */ /* restore saved values */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* restore Read Data Sample Delay */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - READ_DATA_SAMPLE_DELAY, + RD_DATA_SMPL_DLYS_REG, read_data_sample_delay_vals[if_id], MASK_ALL_BITS)); /* restore Read Data Ready Delay */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - READ_DATA_READY_DELAY, + RD_DATA_RDY_DLYS_REG, read_data_ready_delay_vals[if_id], MASK_ALL_BITS)); /* enable multi cs */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, cs_enable_reg_val[if_id], + DUAL_DUNIT_CFG_REG, cs_enable_reg_val[if_id], MASK_ALL_BITS)); } - /* Disable modt0 for CS0 training - need to adjust for multy CS */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0x1498, - 0x0, 0xf)); + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) { + /* Disable modt0 for CS0 training - need to adjust for multi-CS + * in case of ddr4 set 0xf else 0 + */ + if (odt_config != 0) { + CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + SDRAM_ODT_CTRL_HIGH_REG, 0x0, 0xf)); + } + else { + CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + SDRAM_ODT_CTRL_HIGH_REG, 0xf, 0xf)); + } + + } for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (training_result[training_stage][if_id] == TEST_FAILED) return MV_FAIL; } @@ -1307,28 +1203,27 @@ int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num) int adll_offset; u32 if_id, bus_id, data, data_tmp; int is_if_fail = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); is_if_fail = 0; - for (bus_id = 0; bus_id < GET_TOPOLOGY_NUM_OF_BUSES(); - bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); wr_supp_res[if_id][bus_id].is_pup_fail = 1; CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - effective_cs * CS_REGISTER_ADDR_OFFSET, + CTX_PHY_REG(effective_cs), &data)); DEBUG_LEVELING( DEBUG_LEVEL_TRACE, ("WL Supp: adll_offset=0 data delay = %d\n", data)); if (ddr3_tip_wl_supp_align_phase_shift - (dev_num, if_id, bus_id, 0, 0) == MV_OK) { + (dev_num, if_id, bus_id) == MV_OK) { DEBUG_LEVELING( DEBUG_LEVEL_TRACE, ("WL Supp: IF %d bus_id %d adll_offset=0 Success !\n", @@ -1341,14 +1236,12 @@ int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num) CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - effective_cs * CS_REGISTER_ADDR_OFFSET, + CTX_PHY_REG(effective_cs), data + adll_offset)); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - effective_cs * CS_REGISTER_ADDR_OFFSET, + CTX_PHY_REG(effective_cs), &data_tmp)); DEBUG_LEVELING( DEBUG_LEVEL_TRACE, @@ -1356,7 +1249,7 @@ int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num) adll_offset, data_tmp)); if (ddr3_tip_wl_supp_align_phase_shift - (dev_num, if_id, bus_id, adll_offset, 0) == MV_OK) { + (dev_num, if_id, bus_id) == MV_OK) { DEBUG_LEVELING( DEBUG_LEVEL_TRACE, ("WL Supp: IF %d bus_id %d adll_offset= %d Success !\n", @@ -1369,21 +1262,19 @@ int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num) CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - effective_cs * CS_REGISTER_ADDR_OFFSET, + CTX_PHY_REG(effective_cs), data + adll_offset)); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - effective_cs * CS_REGISTER_ADDR_OFFSET, + CTX_PHY_REG(effective_cs), &data_tmp)); DEBUG_LEVELING( DEBUG_LEVEL_TRACE, ("WL Supp: adll_offset= %d data delay = %d\n", adll_offset, data_tmp)); if (ddr3_tip_wl_supp_align_phase_shift - (dev_num, if_id, bus_id, adll_offset, 0) == MV_OK) { + (dev_num, if_id, bus_id) == MV_OK) { DEBUG_LEVELING( DEBUG_LEVEL_TRACE, ("WL Supp: IF %d bus_id %d adll_offset= %d Success !\n", @@ -1397,13 +1288,11 @@ int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num) is_if_fail = 1; } } - DEBUG_LEVELING(DEBUG_LEVEL_TRACE, - ("WL Supp: IF %d bus_id %d is_pup_fail %d\n", - if_id, bus_id, is_if_fail)); if (is_if_fail == 1) { DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("WL Supp: IF %d failed\n", if_id)); + ("WL Supp: CS# %d: IF %d failed\n", + effective_cs, if_id)); training_result[training_stage][if_id] = TEST_FAILED; } else { training_result[training_stage][if_id] = TEST_SUCCESS; @@ -1411,7 +1300,7 @@ int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num) } for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (training_result[training_stage][if_id] == TEST_FAILED) return MV_FAIL; } @@ -1423,87 +1312,129 @@ int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num) * Phase Shift */ static int ddr3_tip_wl_supp_align_phase_shift(u32 dev_num, u32 if_id, - u32 bus_id, u32 offset, - u32 bus_id_delta) + u32 bus_id) { + u32 original_phase; + u32 data, write_data; + wr_supp_res[if_id][bus_id].stage = PHASE_SHIFT; - if (ddr3_tip_xsb_compare_test(dev_num, if_id, bus_id, - 0, bus_id_delta) == MV_OK) { - wr_supp_res[if_id][bus_id].is_pup_fail = 0; - return MV_OK; - } else if (ddr3_tip_xsb_compare_test(dev_num, if_id, bus_id, - ONE_CLOCK_ERROR_SHIFT, - bus_id_delta) == MV_OK) { - /* 1 clock error */ - wr_supp_res[if_id][bus_id].stage = CLOCK_SHIFT; - DEBUG_LEVELING(DEBUG_LEVEL_TRACE, - ("Supp: 1 error clock for if %d pup %d with ofsset %d success\n", - if_id, bus_id, offset)); - ddr3_tip_wl_supp_one_clk_err_shift(dev_num, if_id, bus_id, 0); - wr_supp_res[if_id][bus_id].is_pup_fail = 0; - return MV_OK; - } else if (ddr3_tip_xsb_compare_test(dev_num, if_id, bus_id, - ALIGN_ERROR_SHIFT, - bus_id_delta) == MV_OK) { - /* align error */ - DEBUG_LEVELING(DEBUG_LEVEL_TRACE, - ("Supp: align error for if %d pup %d with ofsset %d success\n", - if_id, bus_id, offset)); - wr_supp_res[if_id][bus_id].stage = ALIGN_SHIFT; - ddr3_tip_wl_supp_align_err_shift(dev_num, if_id, bus_id, 0); - wr_supp_res[if_id][bus_id].is_pup_fail = 0; + if (ddr3_tip_xsb_compare_test + (dev_num, if_id, bus_id, 0) == MV_OK) return MV_OK; - } else { - wr_supp_res[if_id][bus_id].is_pup_fail = 1; - return MV_FAIL; + + /* Read current phase */ + CHECK_STATUS(ddr3_tip_bus_read + (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, + DDR_PHY_DATA, WL_PHY_REG(effective_cs), &data)); + original_phase = (data >> 6) & 0x7; + + /* Set phase (0x0[6-8]) -2 */ + if (original_phase >= 1) { + if (original_phase == 1) + write_data = data & ~0x1df; + else + write_data = (data & ~0x1c0) | + ((original_phase - 2) << 6); + ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, + WL_PHY_REG(effective_cs), write_data); + if (ddr3_tip_xsb_compare_test + (dev_num, if_id, bus_id, -2) == MV_OK) + return MV_OK; } + + /* Set phase (0x0[6-8]) +2 */ + if (original_phase <= 5) { + write_data = (data & ~0x1c0) | + ((original_phase + 2) << 6); + ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, + WL_PHY_REG(effective_cs), write_data); + if (ddr3_tip_xsb_compare_test + (dev_num, if_id, bus_id, 2) == MV_OK) + return MV_OK; + } + + /* Set phase (0x0[6-8]) +4 */ + if (original_phase <= 3) { + write_data = (data & ~0x1c0) | + ((original_phase + 4) << 6); + ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, + WL_PHY_REG(effective_cs), write_data); + if (ddr3_tip_xsb_compare_test + (dev_num, if_id, bus_id, 4) == MV_OK) + return MV_OK; + } + + /* Set phase (0x0[6-8]) +6 */ + if (original_phase <= 1) { + write_data = (data & ~0x1c0) | + ((original_phase + 6) << 6); + ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, + WL_PHY_REG(effective_cs), write_data); + if (ddr3_tip_xsb_compare_test + (dev_num, if_id, bus_id, 6) == MV_OK) + return MV_OK; + } + + /* Write original WL result back */ + ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, + WL_PHY_REG(effective_cs), data); + wr_supp_res[if_id][bus_id].is_pup_fail = 1; + + return MV_FAIL; } /* * Compare Test */ static int ddr3_tip_xsb_compare_test(u32 dev_num, u32 if_id, u32 bus_id, - u32 edge_offset, u32 bus_id_delta) + u32 edge_offset) { - u32 num_of_succ_byte_compare, word_in_pattern, abs_offset; - u32 word_offset, i; + u32 num_of_succ_byte_compare, word_in_pattern; + u32 word_offset, i, num_of_word_mult; u32 read_pattern[TEST_PATTERN_LENGTH * 2]; struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); u32 pattern_test_pattern_table[8]; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + /* 3 below for INTERFACE_BUS_MASK_16BIT */ + num_of_word_mult = (tm->bus_act_mask == 3) ? 1 : 2; for (i = 0; i < 8; i++) { pattern_test_pattern_table[i] = pattern_table_get_word(dev_num, PATTERN_TEST, (u8)i); } - /* extern write, than read and compare */ - CHECK_STATUS(ddr3_tip_ext_write - (dev_num, if_id, - (pattern_table[PATTERN_TEST].start_addr + - ((SDRAM_CS_SIZE + 1) * effective_cs)), 1, - pattern_test_pattern_table)); + /* External write, read and compare */ + CHECK_STATUS(ddr3_tip_load_pattern_to_mem(dev_num, PATTERN_TEST)); CHECK_STATUS(ddr3_tip_reset_fifo_ptr(dev_num)); CHECK_STATUS(ddr3_tip_ext_read (dev_num, if_id, - (pattern_table[PATTERN_TEST].start_addr + + ((pattern_table[PATTERN_TEST].start_addr << 3) + ((SDRAM_CS_SIZE + 1) * effective_cs)), 1, read_pattern)); DEBUG_LEVELING( DEBUG_LEVEL_TRACE, - ("XSB-compt: IF %d bus_id %d 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", - if_id, bus_id, read_pattern[0], read_pattern[1], - read_pattern[2], read_pattern[3], read_pattern[4], - read_pattern[5], read_pattern[6], read_pattern[7])); + ("XSB-compt CS#%d: IF %d bus_id %d 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + effective_cs, if_id, bus_id, + read_pattern[0], read_pattern[1], + read_pattern[2], read_pattern[3], + read_pattern[4], read_pattern[5], + read_pattern[6], read_pattern[7])); /* compare byte per pup */ num_of_succ_byte_compare = 0; for (word_in_pattern = start_xsb_offset; - word_in_pattern < (TEST_PATTERN_LENGTH * 2); word_in_pattern++) { - word_offset = word_in_pattern + edge_offset; - if ((word_offset > (TEST_PATTERN_LENGTH * 2 - 1)) || - (word_offset < 0)) + word_in_pattern < (TEST_PATTERN_LENGTH * num_of_word_mult); + word_in_pattern++) { + word_offset = word_in_pattern; + if ((word_offset > (TEST_PATTERN_LENGTH * 2 - 1))) continue; if ((read_pattern[word_in_pattern] & pup_mask_table[bus_id]) == @@ -1512,19 +1443,20 @@ static int ddr3_tip_xsb_compare_test(u32 dev_num, u32 if_id, u32 bus_id, num_of_succ_byte_compare++; } - abs_offset = (edge_offset > 0) ? edge_offset : -edge_offset; - if (num_of_succ_byte_compare == ((TEST_PATTERN_LENGTH * 2) - - abs_offset - start_xsb_offset)) { - DEBUG_LEVELING( - DEBUG_LEVEL_TRACE, - ("XSB-compt: IF %d bus_id %d num_of_succ_byte_compare %d - Success\n", - if_id, bus_id, num_of_succ_byte_compare)); + if ((TEST_PATTERN_LENGTH * num_of_word_mult - start_xsb_offset) == + num_of_succ_byte_compare) { + wr_supp_res[if_id][bus_id].stage = edge_offset; + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, + ("supplementary: shift to %d for if %d pup %d success\n", + edge_offset, if_id, bus_id)); + wr_supp_res[if_id][bus_id].is_pup_fail = 0; + return MV_OK; } else { DEBUG_LEVELING( DEBUG_LEVEL_TRACE, - ("XSB-compt: IF %d bus_id %d num_of_succ_byte_compare %d - Fail !\n", - if_id, bus_id, num_of_succ_byte_compare)); + ("XSB-compt CS#%d: IF %d bus_id %d num_of_succ_byte_compare %d - Fail!\n", + effective_cs, if_id, bus_id, num_of_succ_byte_compare)); DEBUG_LEVELING( DEBUG_LEVEL_TRACE, @@ -1545,116 +1477,10 @@ static int ddr3_tip_xsb_compare_test(u32 dev_num, u32 if_id, u32 bus_id, read_pattern[4], read_pattern[5], read_pattern[6], read_pattern[7])); - DEBUG_LEVELING( - DEBUG_LEVEL_TRACE, - ("XSB-compt: IF %d bus_id %d num_of_succ_byte_compare %d - Fail !\n", - if_id, bus_id, num_of_succ_byte_compare)); - return MV_FAIL; } } -/* - * Clock error shift - function moves the write leveling delay 1cc forward - */ -static int ddr3_tip_wl_supp_one_clk_err_shift(u32 dev_num, u32 if_id, - u32 bus_id, u32 bus_id_delta) -{ - int phase, adll; - u32 data; - DEBUG_LEVELING(DEBUG_LEVEL_TRACE, ("One_clk_err_shift\n")); - - CHECK_STATUS(ddr3_tip_bus_read - (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, - DDR_PHY_DATA, WL_PHY_REG, &data)); - phase = ((data >> 6) & 0x7); - adll = data & 0x1f; - DEBUG_LEVELING(DEBUG_LEVEL_TRACE, - ("One_clk_err_shift: IF %d bus_id %d phase %d adll %d\n", - if_id, bus_id, phase, adll)); - - if ((phase == 0) || (phase == 1)) { - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, bus_id, - DDR_PHY_DATA, 0, (phase + 2), 0x1f)); - } else if (phase == 2) { - if (adll < 6) { - data = (3 << 6) + (0x1f); - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, - bus_id, DDR_PHY_DATA, 0, data, - (0x7 << 6 | 0x1f))); - data = 0x2f; - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, - bus_id, DDR_PHY_DATA, 1, data, 0x3f)); - } - } else { - /* phase 3 */ - return MV_FAIL; - } - - return MV_OK; -} - -/* - * Align error shift - */ -static int ddr3_tip_wl_supp_align_err_shift(u32 dev_num, u32 if_id, - u32 bus_id, u32 bus_id_delta) -{ - int phase, adll; - u32 data; - - /* Shift WL result 1 phase back */ - CHECK_STATUS(ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, - bus_id, DDR_PHY_DATA, WL_PHY_REG, - &data)); - phase = ((data >> 6) & 0x7); - adll = data & 0x1f; - DEBUG_LEVELING( - DEBUG_LEVEL_TRACE, - ("Wl_supp_align_err_shift: IF %d bus_id %d phase %d adll %d\n", - if_id, bus_id, phase, adll)); - - if (phase < 2) { - if (adll > 0x1a) { - if (phase == 0) - return MV_FAIL; - - if (phase == 1) { - data = 0; - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, - if_id, bus_id, DDR_PHY_DATA, - 0, data, (0x7 << 6 | 0x1f))); - data = 0xf; - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, - if_id, bus_id, DDR_PHY_DATA, - 1, data, 0x1f)); - return MV_OK; - } - } else { - return MV_FAIL; - } - } else if ((phase == 2) || (phase == 3)) { - phase = phase - 2; - data = (phase << 6) + (adll & 0x1f); - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, bus_id, - DDR_PHY_DATA, 0, data, (0x7 << 6 | 0x1f))); - return MV_OK; - } else { - DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("Wl_supp_align_err_shift: unexpected phase\n")); - - return MV_FAIL; - } - - return MV_OK; -} - /* * Dynamic write leveling sequence */ @@ -1663,32 +1489,33 @@ static int ddr3_tip_dynamic_write_leveling_seq(u32 dev_num) u32 bus_id, dq_id; u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, TRAINING_SW_2_REG, 0x1, 0x5)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_WRITE_LEVELING_REG, 0x50, 0xff)); + TRAINING_WL_REG, 0x50, 0xff)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_WRITE_LEVELING_REG, 0x5c, 0xff)); + TRAINING_WL_REG, 0x5c, 0xff)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_TRAINING_CONTROL_REG, 0x381b82, 0x3c3faf)); + GENERAL_TRAINING_OPCODE_REG, 0x381b82, 0x3c3faf)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_OBJ1_OPCODE_REG, (0x3 << 25), (0x3ffff << 9))); + OPCODE_REG0_REG(1), (0x3 << 25), (0x3ffff << 9))); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_OBJ1_ITER_CNT_REG, 0x80, 0xffff)); + OPCODE_REG1_REG(1), 0x80, 0xffff)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_WRITE_LEVELING_DONE_CNTR_REG, 0x14, 0xff)); + WL_DONE_CNTR_REF_REG, 0x14, 0xff)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_WRITE_LEVELING_REG, 0xff5c, 0xffff)); + TRAINING_WL_REG, 0xff5c, 0xffff)); /* mask PBS */ for (dq_id = 0; dq_id < MAX_DQ_NUM; dq_id++) { @@ -1699,7 +1526,7 @@ static int ddr3_tip_dynamic_write_leveling_seq(u32 dev_num) } /* Mask all results */ - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; bus_id++) { + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, mask_results_pup_reg_map[bus_id], 0x1 << 24, @@ -1707,8 +1534,8 @@ static int ddr3_tip_dynamic_write_leveling_seq(u32 dev_num) } /* Unmask only wanted */ - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, mask_results_pup_reg_map[bus_id], 0, 0x1 << 24)); @@ -1716,7 +1543,7 @@ static int ddr3_tip_dynamic_write_leveling_seq(u32 dev_num) CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - WR_LEVELING_DQS_PATTERN_REG, 0x1, 0x1)); + WL_DQS_PATTERN_REG, 0x1, 0x1)); return MV_OK; } @@ -1729,7 +1556,8 @@ static int ddr3_tip_dynamic_read_leveling_seq(u32 dev_num) u32 bus_id, dq_id; u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* mask PBS */ for (dq_id = 0; dq_id < MAX_DQ_NUM; dq_id++) { @@ -1740,7 +1568,7 @@ static int ddr3_tip_dynamic_read_leveling_seq(u32 dev_num) } /* Mask all results */ - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; bus_id++) { + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, mask_results_pup_reg_map[bus_id], 0x1 << 24, @@ -1748,8 +1576,8 @@ static int ddr3_tip_dynamic_read_leveling_seq(u32 dev_num) } /* Unmask only wanted */ - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, mask_results_pup_reg_map[bus_id], 0, 0x1 << 24)); @@ -1766,7 +1594,8 @@ static int ddr3_tip_dynamic_per_bit_read_leveling_seq(u32 dev_num) u32 bus_id, dq_id; u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* mask PBS */ for (dq_id = 0; dq_id < MAX_DQ_NUM; dq_id++) { @@ -1777,7 +1606,7 @@ static int ddr3_tip_dynamic_per_bit_read_leveling_seq(u32 dev_num) } /* Mask all results */ - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; bus_id++) { + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, mask_results_pup_reg_map[bus_id], 0x1 << 24, @@ -1786,7 +1615,7 @@ static int ddr3_tip_dynamic_per_bit_read_leveling_seq(u32 dev_num) /* Unmask only wanted */ for (dq_id = 0; dq_id < MAX_DQ_NUM; dq_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, dq_id / 8); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, dq_id / 8); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, mask_results_dq_reg_map[dq_id], 0x0 << 24, @@ -1802,16 +1631,17 @@ static int ddr3_tip_dynamic_per_bit_read_leveling_seq(u32 dev_num) int ddr3_tip_print_wl_supp_result(u32 dev_num) { u32 bus_id = 0, if_id = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("I/F0 PUP0 Result[0 - success, 1-fail] ...\n")); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("%d ,", wr_supp_res[if_id] [bus_id].is_pup_fail)); @@ -1822,10 +1652,10 @@ int ddr3_tip_print_wl_supp_result(u32 dev_num) ("I/F0 PUP0 Stage[0-phase_shift, 1-clock_shift, 2-align_shift] ...\n")); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("%d ,", wr_supp_res[if_id] [bus_id].stage)); @@ -1834,3 +1664,324 @@ int ddr3_tip_print_wl_supp_result(u32 dev_num) return MV_OK; } + +#define RD_FIFO_PTR_LOW_STAT_INDIR_ADDR 0x9a +#define RD_FIFO_PTR_HIGH_STAT_INDIR_ADDR 0x9b +/* position of falling dqs edge in fifo; walking 1 */ +#define RD_FIFO_DQS_FALL_EDGE_POS_0 0x1 +#define RD_FIFO_DQS_FALL_EDGE_POS_1 0x2 +#define RD_FIFO_DQS_FALL_EDGE_POS_2 0x4 +#define RD_FIFO_DQS_FALL_EDGE_POS_3 0x8 +#define RD_FIFO_DQS_FALL_EDGE_POS_4 0x10 /* lock */ +/* position of rising dqs edge in fifo; walking 0 */ +#define RD_FIFO_DQS_RISE_EDGE_POS_0 0x1fff +#define RD_FIFO_DQS_RISE_EDGE_POS_1 0x3ffe +#define RD_FIFO_DQS_RISE_EDGE_POS_2 0x3ffd +#define RD_FIFO_DQS_RISE_EDGE_POS_3 0x3ffb +#define RD_FIFO_DQS_RISE_EDGE_POS_4 0x3ff7 /* lock */ +#define TEST_ADDR 0x8 +#define TAPS_PER_UI 32 +#define UI_PER_RD_SAMPLE 4 +#define TAPS_PER_RD_SAMPLE ((UI_PER_RD_SAMPLE) * (TAPS_PER_UI)) +#define MAX_RD_SAMPLES 32 +#define MAX_RL_VALUE ((MAX_RD_SAMPLES) * (TAPS_PER_RD_SAMPLE)) +#define RD_FIFO_DLY 8 +#define STEP_SIZE 64 +#define RL_JITTER_WIDTH_LMT 20 +#define ADLL_TAPS_IN_CYCLE 64 + +enum rl_dqs_burst_state { + RL_AHEAD = 0, + RL_INSIDE, + RL_BEHIND +}; +int mv_ddr_rl_dqs_burst(u32 dev_num, u32 if_id, u32 freq) +{ + enum rl_dqs_burst_state rl_state[NUM_OF_CS][MAX_BUS_NUM][MAX_INTERFACE_NUM] = { { {0} } }; + enum hws_ddr_phy subphy_type = DDR_PHY_DATA; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + int cl_val = tm->interface_params[0].cas_l; + int rl_adll_val, rl_phase_val, sdr_cycle_incr, rd_sample, rd_ready; + int final_rd_sample, final_rd_ready; + int i, subphy_id, step; + int pass_lock_num = 0; + int init_pass_lock_num; + int phase_delta; + int min_phase, max_phase; + u32 max_cs = ddr3_tip_max_cs_get(dev_num); + u32 rl_values[NUM_OF_CS][MAX_BUS_NUM][MAX_INTERFACE_NUM] = { { {0} } }; + u32 rl_min_values[NUM_OF_CS][MAX_BUS_NUM][MAX_INTERFACE_NUM] = { { {0} } }; + u32 rl_max_values[NUM_OF_CS][MAX_BUS_NUM][MAX_INTERFACE_NUM] = { { {0} } }; + u32 rl_val, rl_min_val[NUM_OF_CS], rl_max_val[NUM_OF_CS]; + u32 reg_val_low, reg_val_high; + u32 reg_val, reg_mask; + uintptr_t test_addr = TEST_ADDR; + + /* initialization */ + if (ddr3_if_ecc_enabled()) { + ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, TRAINING_SW_2_REG, + ®_val, MASK_ALL_BITS); + reg_mask = (TRAINING_ECC_MUX_MASK << TRAINING_ECC_MUX_OFFS) | + (TRAINING_SW_OVRD_MASK << TRAINING_SW_OVRD_OFFS); + reg_val &= ~reg_mask; + reg_val |= (TRAINING_ECC_MUX_DIS << TRAINING_ECC_MUX_OFFS) | + (TRAINING_SW_OVRD_ENA << TRAINING_SW_OVRD_OFFS); + ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, TRAINING_SW_2_REG, + reg_val, MASK_ALL_BITS); + ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, TRAINING_REG, + ®_val, MASK_ALL_BITS); + reg_mask = (TRN_START_MASK << TRN_START_OFFS); + reg_val &= ~reg_mask; + reg_val |= TRN_START_ENA << TRN_START_OFFS; + ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, TRAINING_REG, + reg_val, MASK_ALL_BITS); + } + + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) + for (subphy_id = 0; subphy_id < MAX_BUS_NUM; subphy_id++) + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) + if (IS_BUS_ACTIVE(tm->bus_act_mask, subphy_id) == 0) + pass_lock_num++; /* increment on inactive subphys */ + + init_pass_lock_num = pass_lock_num / max_cs; + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + training_result[training_stage][if_id] = TEST_SUCCESS; + } + } + + /* search for dqs edges per subphy */ + if_id = 0; + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { + pass_lock_num = init_pass_lock_num; + ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ODPG_DATA_CTRL_REG, + effective_cs << ODPG_DATA_CS_OFFS, + ODPG_DATA_CS_MASK << ODPG_DATA_CS_OFFS); + rl_min_val[effective_cs] = MAX_RL_VALUE; + rl_max_val[effective_cs] = 0; + step = STEP_SIZE; + for (i = 0; i < MAX_RL_VALUE; i += step) { + rl_val = 0; + sdr_cycle_incr = i / TAPS_PER_RD_SAMPLE; /* sdr cycle increment */ + rd_sample = cl_val + 2 * sdr_cycle_incr; + /* fifo out to in delay in search is constant */ + rd_ready = rd_sample + RD_FIFO_DLY; + + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, RD_DATA_SMPL_DLYS_REG, + rd_sample << RD_SMPL_DLY_CS_OFFS(effective_cs), + RD_SMPL_DLY_CS_MASK << RD_SMPL_DLY_CS_OFFS(effective_cs)); + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, RD_DATA_RDY_DLYS_REG, + rd_ready << RD_RDY_DLY_CS_OFFS(effective_cs), + RD_RDY_DLY_CS_MASK << RD_RDY_DLY_CS_OFFS(effective_cs)); + + /* one sdr (single data rate) cycle incremented on every four phases of ddr clock */ + sdr_cycle_incr = i % TAPS_PER_RD_SAMPLE; + rl_adll_val = sdr_cycle_incr % MAX_RD_SAMPLES; + rl_phase_val = sdr_cycle_incr / MAX_RD_SAMPLES; + rl_val = ((rl_adll_val & RL_REF_DLY_MASK) << RL_REF_DLY_OFFS) | + ((rl_phase_val & RL_PH_SEL_MASK) << RL_PH_SEL_OFFS); + + /* write to all subphys (even to not connected or locked) */ + ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST, + 0, DDR_PHY_DATA, RL_PHY_REG(effective_cs), rl_val); + + /* reset read fifo assertion */ + ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, if_id, SDRAM_CFG_REG, + DATA_PUP_RD_RESET_ENA << DATA_PUP_RD_RESET_OFFS, + DATA_PUP_RD_RESET_MASK << DATA_PUP_RD_RESET_OFFS); + + /* reset read fifo deassertion */ + ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, if_id, SDRAM_CFG_REG, + DATA_PUP_RD_RESET_DIS << DATA_PUP_RD_RESET_OFFS, + DATA_PUP_RD_RESET_MASK << DATA_PUP_RD_RESET_OFFS); + + /* perform one read burst */ + if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)) + readq(test_addr); + else + readl(test_addr); + + /* progress read ptr; decide on rl state per byte */ + for (subphy_id = 0; subphy_id < MAX_BUS_NUM; subphy_id++) { + if (rl_state[effective_cs][subphy_id][if_id] == RL_BEHIND) + continue; /* skip locked subphys */ + ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, subphy_id, DDR_PHY_DATA, + RD_FIFO_PTR_LOW_STAT_INDIR_ADDR, ®_val_low); + ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, subphy_id, DDR_PHY_DATA, + RD_FIFO_PTR_HIGH_STAT_INDIR_ADDR, ®_val_high); + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, + ("%s: cs %d, step %d, subphy %d, state %d, low 0x%04x, high 0x%04x; move to ", + __func__, effective_cs, i, subphy_id, + rl_state[effective_cs][subphy_id][if_id], + reg_val_low, reg_val_high)); + + switch (rl_state[effective_cs][subphy_id][if_id]) { + case RL_AHEAD: + /* improve search resolution getting closer to the window */ + if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_4 && + reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_4) { + rl_state[effective_cs][subphy_id][if_id] = RL_INSIDE; + rl_values[effective_cs][subphy_id][if_id] = i; + rl_min_values[effective_cs][subphy_id][if_id] = i; + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, + ("new state %d\n", + rl_state[effective_cs][subphy_id][if_id])); + } else if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_3 && + reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_3) { + step = (step < 2) ? step : 2; + } else if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_2 && + reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_2) { + step = (step < 16) ? step : 16; + } else if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_1 && + reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_1) { + step = (step < 32) ? step : 32; + } else if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_0 && + reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_0) { + step = (step < 64) ? step : 64; + } else { + /* otherwise, step is unchanged */ + } + break; + case RL_INSIDE: + if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_4 && + reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_4) { + rl_max_values[effective_cs][subphy_id][if_id] = i; + if ((rl_max_values[effective_cs][subphy_id][if_id] - + rl_min_values[effective_cs][subphy_id][if_id]) > + ADLL_TAPS_IN_CYCLE) { + rl_state[effective_cs][subphy_id][if_id] = RL_BEHIND; + rl_values[effective_cs][subphy_id][if_id] = + (i + rl_values[effective_cs][subphy_id][if_id]) / 2; + pass_lock_num++; + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, + ("new lock %d\n", pass_lock_num)); + if (rl_min_val[effective_cs] > + rl_values[effective_cs][subphy_id][if_id]) + rl_min_val[effective_cs] = + rl_values[effective_cs][subphy_id][if_id]; + if (rl_max_val[effective_cs] < + rl_values[effective_cs][subphy_id][if_id]) + rl_max_val[effective_cs] = + rl_values[effective_cs][subphy_id][if_id]; + step = 2; + } + } + if (reg_val_low != RD_FIFO_DQS_FALL_EDGE_POS_4 || + reg_val_high != RD_FIFO_DQS_RISE_EDGE_POS_4) { + if ((i - rl_values[effective_cs][subphy_id][if_id]) < + RL_JITTER_WIDTH_LMT) { + /* inside the jitter; not valid segment */ + rl_state[effective_cs][subphy_id][if_id] = RL_AHEAD; + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, + ("new state %d; jitter on mask\n", + rl_state[effective_cs][subphy_id][if_id])); + } else { /* finished valid segment */ + rl_state[effective_cs][subphy_id][if_id] = RL_BEHIND; + rl_values[effective_cs][subphy_id][if_id] = + (i + rl_values[effective_cs][subphy_id][if_id]) / 2; + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, + ("new state %d, solution %d\n", + rl_state[effective_cs][subphy_id][if_id], + rl_values[effective_cs][subphy_id][if_id])); + pass_lock_num++; + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, + ("new lock %d\n", pass_lock_num)); + if (rl_min_val[effective_cs] > + rl_values[effective_cs][subphy_id][if_id]) + rl_min_val[effective_cs] = + rl_values[effective_cs][subphy_id][if_id]; + if (rl_max_val[effective_cs] < + rl_values[effective_cs][subphy_id][if_id]) + rl_max_val[effective_cs] = + rl_values[effective_cs][subphy_id][if_id]; + step = 2; + } + } + break; + case RL_BEHIND: /* do nothing */ + break; + } + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, ("\n")); + } + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, ("pass_lock_num %d\n", pass_lock_num)); + /* exit condition */ + if (pass_lock_num == MAX_BUS_NUM) + break; + } /* for-loop on i */ + + if (pass_lock_num != MAX_BUS_NUM) { + DEBUG_LEVELING(DEBUG_LEVEL_ERROR, + ("%s: cs %d, pass_lock_num %d, max_bus_num %d, init_pass_lock_num %d\n", + __func__, effective_cs, pass_lock_num, MAX_BUS_NUM, init_pass_lock_num)); + for (subphy_id = 0; subphy_id < MAX_BUS_NUM; subphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_id); + DEBUG_LEVELING(DEBUG_LEVEL_ERROR, + ("%s: subphy %d %s\n", + __func__, subphy_id, + (rl_state[effective_cs][subphy_id][if_id] == RL_BEHIND) ? + "locked" : "not locked")); + } + } + } /* for-loop on effective_cs */ + + /* post-processing read leveling results */ + if_id = 0; + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { + phase_delta = 0; + i = rl_min_val[effective_cs]; + sdr_cycle_incr = i / TAPS_PER_RD_SAMPLE; /* sdr cycle increment */ + rd_sample = cl_val + 2 * sdr_cycle_incr; + rd_ready = rd_sample + RD_FIFO_DLY; + min_phase = (rl_min_val[effective_cs] - (sdr_cycle_incr * TAPS_PER_RD_SAMPLE)) % MAX_RD_SAMPLES; + max_phase = (rl_max_val[effective_cs] - (sdr_cycle_incr * TAPS_PER_RD_SAMPLE)) % MAX_RD_SAMPLES; + final_rd_sample = rd_sample; + final_rd_ready = rd_ready; + + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, RD_DATA_SMPL_DLYS_REG, + rd_sample << RD_SMPL_DLY_CS_OFFS(effective_cs), + RD_SMPL_DLY_CS_MASK << RD_SMPL_DLY_CS_OFFS(effective_cs)); + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, RD_DATA_RDY_DLYS_REG, + rd_ready << RD_RDY_DLY_CS_OFFS(effective_cs), + RD_RDY_DLY_CS_MASK << RD_RDY_DLY_CS_OFFS(effective_cs)); + DEBUG_LEVELING(DEBUG_LEVEL_INFO, + ("%s: cs %d, min phase %d, max phase %d, read sample %d\n", + __func__, effective_cs, min_phase, max_phase, rd_sample)); + + for (subphy_id = 0; subphy_id < MAX_BUS_NUM; subphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_id); + /* reduce sdr cycle per cs; extract rl adll and phase values */ + i = rl_values[effective_cs][subphy_id][if_id] - (sdr_cycle_incr * TAPS_PER_RD_SAMPLE); + rl_adll_val = i % MAX_RD_SAMPLES; + rl_phase_val = i / MAX_RD_SAMPLES; + rl_phase_val -= phase_delta; + DEBUG_LEVELING(DEBUG_LEVEL_INFO, + ("%s: final results: cs %d, subphy %d, read sample %d read ready %d, rl_phase_val %d, rl_adll_val %d\n", + __func__, effective_cs, subphy_id, final_rd_sample, + final_rd_ready, rl_phase_val, rl_adll_val)); + + rl_val = ((rl_adll_val & RL_REF_DLY_MASK) << RL_REF_DLY_OFFS) | + ((rl_phase_val & RL_PH_SEL_MASK) << RL_PH_SEL_OFFS); + ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_UNICAST, + subphy_id, subphy_type, RL_PHY_REG(effective_cs), rl_val); + } + } /* for-loop on effective cs */ + + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + if (odt_config != 0) + CHECK_STATUS(ddr3_tip_write_additional_odt_setting(dev_num, if_id)); + } + + /* reset read fifo assertion */ + ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, if_id, SDRAM_CFG_REG, + DATA_PUP_RD_RESET_ENA << DATA_PUP_RD_RESET_OFFS, + DATA_PUP_RD_RESET_MASK << DATA_PUP_RD_RESET_OFFS); + + /* reset read fifo deassertion */ + ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, if_id, SDRAM_CFG_REG, + DATA_PUP_RD_RESET_DIS << DATA_PUP_RD_RESET_OFFS, + DATA_PUP_RD_RESET_MASK << DATA_PUP_RD_RESET_OFFS); + + return MV_OK; +} diff --git a/drivers/ddr/marvell/a38x/ddr3_training_leveling.h b/drivers/ddr/marvell/a38x/ddr3_training_leveling.h index f2b4177082c4..b6ebe731a1f7 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_leveling.h +++ b/drivers/ddr/marvell/a38x/ddr3_training_leveling.h @@ -12,6 +12,6 @@ int ddr3_tip_print_wl_supp_result(u32 dev_num); int ddr3_tip_calc_cs_mask(u32 dev_num, u32 if_id, u32 effective_cs, u32 *cs_mask); -u32 hws_ddr3_tip_max_cs_get(void); +u32 ddr3_tip_max_cs_get(u32 dev_num); #endif /* _DDR3_TRAINING_LEVELING_H_ */ diff --git a/drivers/ddr/marvell/a38x/ddr3_training_pbs.c b/drivers/ddr/marvell/a38x/ddr3_training_pbs.c index 2b4a58fb9fcc..9f54d96a1eb9 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_pbs.c +++ b/drivers/ddr/marvell/a38x/ddr3_training_pbs.c @@ -4,12 +4,6 @@ * SPDX-License-Identifier: GPL-2.0 */ -#include -#include -#include -#include -#include - #include "ddr3_init.h" #define TYPICAL_PBS_VALUE 12 @@ -24,7 +18,7 @@ u8 max_pbs_per_pup[MAX_INTERFACE_NUM][MAX_BUS_NUM]; u8 min_pbs_per_pup[MAX_INTERFACE_NUM][MAX_BUS_NUM]; u8 max_adll_per_pup[MAX_INTERFACE_NUM][MAX_BUS_NUM]; u8 min_adll_per_pup[MAX_INTERFACE_NUM][MAX_BUS_NUM]; -u32 pbsdelay_per_pup[NUM_OF_PBS_MODES][MAX_INTERFACE_NUM][MAX_BUS_NUM]; +u32 pbsdelay_per_pup[NUM_OF_PBS_MODES][MAX_INTERFACE_NUM][MAX_BUS_NUM][MAX_CS_NUM]; u8 adll_shift_lock[MAX_INTERFACE_NUM][MAX_BUS_NUM]; u8 adll_shift_val[MAX_INTERFACE_NUM][MAX_BUS_NUM]; enum hws_pattern pbs_pattern = PATTERN_VREF; @@ -50,34 +44,33 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) int init_val = (search_dir == HWS_LOW2HIGH) ? 0 : iterations; enum hws_edge_compare search_edge = EDGE_FP; u32 pup = 0, bit = 0, if_id = 0, all_lock = 0, cs_num = 0; - int reg_addr = 0; + u32 reg_addr = 0; u32 validation_val = 0; u32 cs_enable_reg_val[MAX_INTERFACE_NUM]; u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); u8 temp = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* save current cs enable reg val */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* save current cs enable reg val */ CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, cs_enable_reg_val, MASK_ALL_BITS)); + DUAL_DUNIT_CFG_REG, cs_enable_reg_val, MASK_ALL_BITS)); /* enable single cs */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, (1 << 3), (1 << 3))); + DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3))); } reg_addr = (pbs_mode == PBS_RX_MODE) ? - (READ_CENTRALIZATION_PHY_REG + - (effective_cs * CS_REGISTER_ADDR_OFFSET)) : - (WRITE_CENTRALIZATION_PHY_REG + - (effective_cs * CS_REGISTER_ADDR_OFFSET)); - read_adll_value(nominal_adll, reg_addr, MASK_ALL_BITS); + CRX_PHY_REG(effective_cs) : + CTX_PHY_REG(effective_cs); + ddr3_tip_read_adll_value(dev_num, nominal_adll, reg_addr, MASK_ALL_BITS); /* stage 1 shift ADLL */ ddr3_tip_ip_training(dev_num, ACCESS_TYPE_MULTICAST, @@ -88,10 +81,10 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) pbs_pattern, search_edge, CS_SINGLE, cs_num, train_status); validation_val = (pbs_mode == PBS_RX_MODE) ? 0x1f : 0; - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); min_adll_per_pup[if_id][pup] = (pbs_mode == PBS_RX_MODE) ? 0x1f : 0x3f; pup_state[if_id][pup] = 0x3; @@ -101,8 +94,8 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) } /* EBA */ - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) { CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_MULTICAST, @@ -112,7 +105,7 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) res0, MASK_ALL_BITS)); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE, ("FP I/F %d, bit:%d, pup:%d res0 0x%x\n", if_id, bit, pup, @@ -177,10 +170,10 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) } /* EEBA */ - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (pup_state[if_id][pup] != 4) continue; @@ -336,10 +329,10 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) } /* Print Stage result */ - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE, ("FP I/F %d, ADLL Shift for EBA: pup[%d] Lock status = %d Lock Val = %d,%d\n", if_id, pup, @@ -351,10 +344,10 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO, ("Update ADLL Shift of all pups:\n")); - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (adll_shift_lock[if_id][pup] != 1) continue; /* if pup not locked continue to next pup */ @@ -374,10 +367,10 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) /* PBS EEBA&EBA */ /* Start the Per Bit Skew search */ - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); max_pbs_per_pup[if_id][pup] = 0x0; min_pbs_per_pup[if_id][pup] = 0x1f; for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) { @@ -401,10 +394,10 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) iterations, pbs_pattern, search_edge, CS_SINGLE, cs_num, train_status); - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (adll_shift_lock[if_id][pup] != 1) { /* if pup not lock continue to next pup */ continue; @@ -462,10 +455,10 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) /* Check all Pup lock */ all_lock = 1; - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); all_lock = all_lock * adll_shift_lock[if_id][pup]; } } @@ -479,11 +472,11 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) search_dir = (pbs_mode == PBS_RX_MODE) ? HWS_LOW2HIGH : HWS_HIGH2LOW; init_val = (search_dir == HWS_LOW2HIGH) ? 0 : iterations; - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (adll_shift_lock[if_id][pup] == 1) { /*if pup lock continue to next pup */ continue; @@ -628,11 +621,11 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) search_edge, CS_SINGLE, cs_num, train_status); - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) { CHECK_STATUS(ddr3_tip_if_read (dev_num, @@ -697,7 +690,7 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) /* Check all Pup state */ all_lock = 1; - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { + for (pup = 0; pup < octets_per_if_num; pup++) { /* * DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO, * ("pup_state[%d][%d] = %d\n",if_id,pup,pup_state @@ -708,12 +701,12 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) /* END OF SBA */ /* Norm */ - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) { for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* if pup not lock continue to next pup */ if (adll_shift_lock[if_id][pup] != 1) { DEBUG_PBS_ENGINE( @@ -754,9 +747,9 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) /* DQ PBS register update with the final result */ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); DEBUG_PBS_ENGINE( DEBUG_LEVEL_INFO, @@ -772,28 +765,32 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) pad_num = dq_map_table[ bit + pup * BUS_WIDTH_IN_BITS + if_id * BUS_WIDTH_IN_BITS * - tm->num_of_bus_per_interface]; + MAX_BUS_NUM]; DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO, ("result_mat: %d ", result_mat[if_id][pup] [bit])); reg_addr = (pbs_mode == PBS_RX_MODE) ? - (PBS_RX_PHY_REG + effective_cs * 0x10) : - (PBS_TX_PHY_REG + effective_cs * 0x10); + PBS_RX_PHY_REG(effective_cs, 0) : + PBS_TX_PHY_REG(effective_cs, 0); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, pup, DDR_PHY_DATA, reg_addr + pad_num, result_mat[if_id][pup][bit])); } - pbsdelay_per_pup[pbs_mode][if_id][pup] = - (max_pbs_per_pup[if_id][pup] == - min_pbs_per_pup[if_id][pup]) ? - TYPICAL_PBS_VALUE : - ((max_adll_per_pup[if_id][pup] - - min_adll_per_pup[if_id][pup]) * adll_tap / - (max_pbs_per_pup[if_id][pup] - - min_pbs_per_pup[if_id][pup])); + + if (max_pbs_per_pup[if_id][pup] == min_pbs_per_pup[if_id][pup]) { + temp = TYPICAL_PBS_VALUE; + } else { + temp = ((max_adll_per_pup[if_id][pup] - + min_adll_per_pup[if_id][pup]) * + adll_tap / + (max_pbs_per_pup[if_id][pup] - + min_pbs_per_pup[if_id][pup])); + } + pbsdelay_per_pup[pbs_mode] + [if_id][pup][effective_cs] = temp; /* RX results ready, write RX also */ if (pbs_mode == PBS_TX_MODE) { @@ -843,18 +840,18 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) DEBUG_PBS_ENGINE( DEBUG_LEVEL_INFO, (", PBS tap=%d [psec] ==> skew observed = %d\n", - pbsdelay_per_pup[pbs_mode][if_id][pup], + temp, ((max_pbs_per_pup[if_id][pup] - min_pbs_per_pup[if_id][pup]) * - pbsdelay_per_pup[pbs_mode][if_id][pup]))); + temp))); } } /* Write back to the phy the default values */ reg_addr = (pbs_mode == PBS_RX_MODE) ? - (READ_CENTRALIZATION_PHY_REG + effective_cs * 4) : - (WRITE_CENTRALIZATION_PHY_REG + effective_cs * 4); - write_adll_value(nominal_adll, reg_addr); + CRX_PHY_REG(effective_cs) : + CTX_PHY_REG(effective_cs); + ddr3_tip_write_adll_value(dev_num, nominal_adll, reg_addr); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { reg_addr = (pbs_mode == PBS_RX_MODE) ? @@ -866,24 +863,29 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) 0)); /* restore cs enable value */ - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, cs_enable_reg_val[if_id], + DUAL_DUNIT_CFG_REG, cs_enable_reg_val[if_id], MASK_ALL_BITS)); } /* exit test mode */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_WRITE_READ_MODE_ENABLE_REG, 0xffff, MASK_ALL_BITS)); + ODPG_WR_RD_MODE_ENA_REG, 0xffff, MASK_ALL_BITS)); + for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - /* - * meaning that there is no VW exist at all (No lock at - * the EBA ADLL shift@EBS) - */ - if (pup_state[if_id][pup] == 1) - return MV_FAIL; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); + /* + * no valid window found + * (no lock at EBA ADLL shift at EBS) + */ + if (pup_state[if_id][pup] == 1) + return MV_FAIL; + } } return MV_OK; @@ -913,14 +915,14 @@ int ddr3_tip_pbs_tx(u32 uidev_num) return ddr3_tip_pbs(uidev_num, PBS_TX_MODE); } -#ifndef EXCLUDE_SWITCH_DEBUG +#ifdef DDR_VIEWER_TOOL /* * Print PBS Result */ int ddr3_tip_print_all_pbs_result(u32 dev_num) { u32 curr_cs; - u32 max_cs = hws_ddr3_tip_max_cs_get(); + u32 max_cs = ddr3_tip_max_cs_get(dev_num); for (curr_cs = 0; curr_cs < max_cs; curr_cs++) { ddr3_tip_print_pbs_result(dev_num, curr_cs, PBS_RX_MODE); @@ -937,21 +939,33 @@ int ddr3_tip_print_pbs_result(u32 dev_num, u32 cs_num, enum pbs_dir pbs_mode) { u32 data_value = 0, bit = 0, if_id = 0, pup = 0; u32 reg_addr = (pbs_mode == PBS_RX_MODE) ? - (PBS_RX_PHY_REG + cs_num * 0x10) : - (PBS_TX_PHY_REG + cs_num * 0x10); - struct hws_topology_map *tm = ddr3_get_topology_map(); + PBS_RX_PHY_REG(cs_num, 0) : + PBS_TX_PHY_REG(cs_num , 0); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + printf("%s,CS%d,PBS,ADLLRATIO,,,", + (pbs_mode == PBS_RX_MODE) ? "Rx" : "Tx", cs_num); + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); + printf("%d,", + pbsdelay_per_pup[pbs_mode][if_id][pup][cs_num]); + } + } printf("CS%d, %s ,PBS\n", cs_num, (pbs_mode == PBS_RX_MODE) ? "Rx" : "Tx"); for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) { printf("%s, DQ", (pbs_mode == PBS_RX_MODE) ? "Rx" : "Tx"); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); printf("%d ,PBS,,, ", bit); - for (pup = 0; pup <= tm->num_of_bus_per_interface; + for (pup = 0; pup <= octets_per_if_num; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, pup, @@ -966,7 +980,7 @@ int ddr3_tip_print_pbs_result(u32 dev_num, u32 cs_num, enum pbs_dir pbs_mode) return MV_OK; } -#endif +#endif /* DDR_VIEWER_TOOL */ /* * Fixup PBS Result @@ -975,13 +989,14 @@ int ddr3_tip_clean_pbs_result(u32 dev_num, enum pbs_dir pbs_mode) { u32 if_id, pup, bit; u32 reg_addr = (pbs_mode == PBS_RX_MODE) ? - (PBS_RX_PHY_REG + effective_cs * 0x10) : - (PBS_TX_PHY_REG + effective_cs * 0x10); - struct hws_topology_map *tm = ddr3_get_topology_map(); + PBS_RX_PHY_REG(effective_cs, 0) : + PBS_TX_PHY_REG(effective_cs, 0); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (pup = 0; pup <= tm->num_of_bus_per_interface; pup++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (pup = 0; pup <= octets_per_if_num; pup++) { for (bit = 0; bit <= BUS_WIDTH_IN_BITS + 3; bit++) { CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, diff --git a/drivers/ddr/marvell/a38x/ddr3_training_static.c b/drivers/ddr/marvell/a38x/ddr3_training_static.c deleted file mode 100644 index 318634eb90dd..000000000000 --- a/drivers/ddr/marvell/a38x/ddr3_training_static.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#include -#include -#include -#include -#include - -#include "ddr3_init.h" - -/* Design Guidelines parameters */ -u32 g_zpri_data = 123; /* controller data - P drive strength */ -u32 g_znri_data = 123; /* controller data - N drive strength */ -u32 g_zpri_ctrl = 74; /* controller C/A - P drive strength */ -u32 g_znri_ctrl = 74; /* controller C/A - N drive strength */ -u32 g_zpodt_data = 45; /* controller data - P ODT */ -u32 g_znodt_data = 45; /* controller data - N ODT */ -u32 g_zpodt_ctrl = 45; /* controller data - P ODT */ -u32 g_znodt_ctrl = 45; /* controller data - N ODT */ -u32 g_odt_config_2cs = 0x120012; -u32 g_odt_config_1cs = 0x10000; -u32 g_rtt_nom = 0x44; -u32 g_dic = 0x2; - - -/* - * Configure phy (called by static init controller) for static flow - */ -int ddr3_tip_configure_phy(u32 dev_num) -{ - u32 if_id, phy_id; - struct hws_topology_map *tm = ddr3_get_topology_map(); - - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, - PAD_ZRI_CALIB_PHY_REG, - ((0x7f & g_zpri_data) << 7 | (0x7f & g_znri_data)))); - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_CONTROL, - PAD_ZRI_CALIB_PHY_REG, - ((0x7f & g_zpri_ctrl) << 7 | (0x7f & g_znri_ctrl)))); - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, - PAD_ODT_CALIB_PHY_REG, - ((0x3f & g_zpodt_data) << 6 | (0x3f & g_znodt_data)))); - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_CONTROL, - PAD_ODT_CALIB_PHY_REG, - ((0x3f & g_zpodt_ctrl) << 6 | (0x3f & g_znodt_ctrl)))); - - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, - PAD_PRE_DISABLE_PHY_REG, 0)); - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, - CMOS_CONFIG_PHY_REG, 0)); - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_CONTROL, - CMOS_CONFIG_PHY_REG, 0)); - - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - /* check if the interface is enabled */ - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - - for (phy_id = 0; - phy_id < tm->num_of_bus_per_interface; - phy_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, phy_id); - /* Vref & clamp */ - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, - if_id, phy_id, DDR_PHY_DATA, - PAD_CONFIG_PHY_REG, - ((clamp_tbl[if_id] << 4) | vref), - ((0x7 << 4) | 0x7))); - /* clamp not relevant for control */ - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, - if_id, phy_id, DDR_PHY_CONTROL, - PAD_CONFIG_PHY_REG, 0x4, 0x7)); - } - } - - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, 0x90, - 0x6002)); - - return MV_OK; -} diff --git a/drivers/ddr/marvell/a38x/ddr_ml_wrapper.h b/drivers/ddr/marvell/a38x/ddr_ml_wrapper.h new file mode 100644 index 000000000000..de55632fee69 --- /dev/null +++ b/drivers/ddr/marvell/a38x/ddr_ml_wrapper.h @@ -0,0 +1,149 @@ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _DDR_ML_WRAPPER_H +#define _DDR_ML_WRAPPER_H + +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_39X) +#define INTER_REGS_BASE SOC_REGS_PHY_BASE +#endif + +/* + * MV_DEBUG_INIT need to be defines, otherwise the output of the + * DDR2 training code is not complete and misleading + */ +#define MV_DEBUG_INIT + +#ifdef MV_DEBUG_INIT +#define DEBUG_INIT_S(s) puts(s) +#define DEBUG_INIT_D(d, l) printf("%x", d) +#define DEBUG_INIT_D_10(d, l) printf("%d", d) +#else +#define DEBUG_INIT_S(s) +#define DEBUG_INIT_D(d, l) +#define DEBUG_INIT_D_10(d, l) +#endif + +#ifdef MV_DEBUG_INIT_FULL +#define DEBUG_INIT_FULL_S(s) puts(s) +#define DEBUG_INIT_FULL_D(d, l) printf("%x", d) +#define DEBUG_INIT_FULL_D_10(d, l) printf("%d", d) +#define DEBUG_WR_REG(reg, val) \ + { DEBUG_INIT_S("Write Reg: 0x"); DEBUG_INIT_D((reg), 8); \ + DEBUG_INIT_S("= "); DEBUG_INIT_D((val), 8); DEBUG_INIT_S("\n"); } +#define DEBUG_RD_REG(reg, val) \ + { DEBUG_INIT_S("Read Reg: 0x"); DEBUG_INIT_D((reg), 8); \ + DEBUG_INIT_S("= "); DEBUG_INIT_D((val), 8); DEBUG_INIT_S("\n"); } +#else +#define DEBUG_INIT_FULL_S(s) +#define DEBUG_INIT_FULL_D(d, l) +#define DEBUG_INIT_FULL_D_10(d, l) +#define DEBUG_WR_REG(reg, val) +#define DEBUG_RD_REG(reg, val) +#endif + +#define DEBUG_INIT_FULL_C(s, d, l) \ + { DEBUG_INIT_FULL_S(s); \ + DEBUG_INIT_FULL_D(d, l); \ + DEBUG_INIT_FULL_S("\n"); } +#define DEBUG_INIT_C(s, d, l) \ + { DEBUG_INIT_S(s); DEBUG_INIT_D(d, l); DEBUG_INIT_S("\n"); } + +/* + * Debug (Enable/Disable modules) and Error report + */ + +#ifdef BASIC_DEBUG +#define MV_DEBUG_WL +#define MV_DEBUG_RL +#define MV_DEBUG_DQS_RESULTS +#endif + +#ifdef FULL_DEBUG +#define MV_DEBUG_WL +#define MV_DEBUG_RL +#define MV_DEBUG_DQS + +#define MV_DEBUG_PBS +#define MV_DEBUG_DFS +#define MV_DEBUG_MAIN_FULL +#define MV_DEBUG_DFS_FULL +#define MV_DEBUG_DQS_FULL +#define MV_DEBUG_RL_FULL +#define MV_DEBUG_WL_FULL +#endif + + +/* The following is a list of Marvell status */ +#define MV_ERROR (-1) +#define MV_OK (0x00) /* Operation succeeded */ +#define MV_FAIL (0x01) /* Operation failed */ +#define MV_BAD_VALUE (0x02) /* Illegal value (general) */ +#define MV_OUT_OF_RANGE (0x03) /* The value is out of range */ +#define MV_BAD_PARAM (0x04) /* Illegal parameter in function called */ +#define MV_BAD_PTR (0x05) /* Illegal pointer value */ +#define MV_BAD_SIZE (0x06) /* Illegal size */ +#define MV_BAD_STATE (0x07) /* Illegal state of state machine */ +#define MV_SET_ERROR (0x08) /* Set operation failed */ +#define MV_GET_ERROR (0x09) /* Get operation failed */ +#define MV_CREATE_ERROR (0x0a) /* Fail while creating an item */ +#define MV_NOT_FOUND (0x0b) /* Item not found */ +#define MV_NO_MORE (0x0c) /* No more items found */ +#define MV_NO_SUCH (0x0d) /* No such item */ +#define MV_TIMEOUT (0x0e) /* Time Out */ +#define MV_NO_CHANGE (0x0f) /* Parameter(s) is already in this value */ +#define MV_NOT_SUPPORTED (0x10) /* This request is not support */ +#define MV_NOT_IMPLEMENTED (0x11) /* Request supported but not implemented*/ +#define MV_NOT_INITIALIZED (0x12) /* The item is not initialized */ +#define MV_NO_RESOURCE (0x13) /* Resource not available (memory ...) */ +#define MV_FULL (0x14) /* Item is full (Queue or table etc...) */ +#define MV_EMPTY (0x15) /* Item is empty (Queue or table etc...) */ +#define MV_INIT_ERROR (0x16) /* Error occured while INIT process */ +#define MV_HW_ERROR (0x17) /* Hardware error */ +#define MV_TX_ERROR (0x18) /* Transmit operation not succeeded */ +#define MV_RX_ERROR (0x19) /* Recieve operation not succeeded */ +#define MV_NOT_READY (0x1a) /* The other side is not ready yet */ +#define MV_ALREADY_EXIST (0x1b) /* Tried to create existing item */ +#define MV_OUT_OF_CPU_MEM (0x1c) /* Cpu memory allocation failed. */ +#define MV_NOT_STARTED (0x1d) /* Not started yet */ +#define MV_BUSY (0x1e) /* Item is busy. */ +#define MV_TERMINATE (0x1f) /* Item terminates it's work. */ +#define MV_NOT_ALIGNED (0x20) /* Wrong alignment */ +#define MV_NOT_ALLOWED (0x21) /* Operation NOT allowed */ +#define MV_WRITE_PROTECT (0x22) /* Write protected */ +#define MV_INVALID (int)(-1) + +/* + * Accessor functions for the registers + */ +static inline void reg_write(u32 addr, u32 val) +{ + writel(val, INTER_REGS_BASE + addr); +} + +static inline u32 reg_read(u32 addr) +{ + return readl(INTER_REGS_BASE + addr); +} + +static inline void reg_bit_set(u32 addr, u32 mask) +{ + setbits_le32(INTER_REGS_BASE + addr, mask); +} + +static inline void reg_bit_clr(u32 addr, u32 mask) +{ + clrbits_le32(INTER_REGS_BASE + addr, mask); +} + +#endif /* _DDR_ML_WRAPPER_H */ diff --git a/drivers/ddr/marvell/a38x/ddr_topology_def.h b/drivers/ddr/marvell/a38x/ddr_topology_def.h index 229c3a127a83..8fd0361dfbd4 100644 --- a/drivers/ddr/marvell/a38x/ddr_topology_def.h +++ b/drivers/ddr/marvell/a38x/ddr_topology_def.h @@ -1,7 +1,7 @@ /* * Copyright (C) Marvell International Ltd. and its affiliates * - * SPDX-License-Identifier: GPL-2.0 + * SPDX-License-Identifier: GPL-2.0 */ #ifndef _DDR_TOPOLOGY_DEF_H @@ -10,38 +10,13 @@ #include "ddr3_training_ip_def.h" #include "ddr3_topology_def.h" -#if defined(CONFIG_ARMADA_38X) -#include "ddr3_a38x.h" +#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_39X) +#include "mv_ddr_plat.h" #endif -/* bus width in bits */ -enum hws_bus_width { - BUS_WIDTH_4, - BUS_WIDTH_8, - BUS_WIDTH_16, - BUS_WIDTH_32 -}; - -enum hws_temperature { - HWS_TEMP_LOW, - HWS_TEMP_NORMAL, - HWS_TEMP_HIGH -}; - -enum hws_mem_size { - MEM_512M, - MEM_1G, - MEM_2G, - MEM_4G, - MEM_8G, - MEM_SIZE_LAST -}; - -enum hws_timing { - HWS_TIM_DEFAULT, - HWS_TIM_1T, - HWS_TIM_2T -}; +#include "mv_ddr_topology.h" +#include "mv_ddr_spd.h" +#include "ddr3_logging_def.h" struct bus_params { /* Chip Select (CS) bitmask (bits 0-CS0, bit 1- CS1 ...) */ @@ -67,11 +42,11 @@ struct if_params { /* Speed Bin Table */ enum hws_speed_bin speed_bin_index; - /* bus width of memory */ - enum hws_bus_width bus_width; + /* sdram device width */ + enum mv_ddr_dev_width bus_width; - /* Bus memory size (MBit) */ - enum hws_mem_size memory_size; + /* total sdram capacity per die, megabits */ + enum mv_ddr_die_capacity memory_size; /* The DDR frequency for each interfaces */ enum hws_ddr_freq memory_freq; @@ -89,33 +64,49 @@ struct if_params { u8 cas_l; /* operation temperature */ - enum hws_temperature interface_temp; - - /* 2T vs 1T mode (by default computed from number of CSs) */ - enum hws_timing timing; + enum mv_ddr_temperature interface_temp; }; -struct hws_topology_map { +struct mv_ddr_topology_map { + /* debug level configuration */ + enum mv_ddr_debug_level debug_level; + /* Number of interfaces (default is 12) */ u8 if_act_mask; /* Controller configuration per interface */ struct if_params interface_params[MAX_INTERFACE_NUM]; - /* BUS per interface (default is 4) */ - u8 num_of_bus_per_interface; - /* Bit mask for active buses */ - u8 bus_act_mask; + u16 bus_act_mask; + + /* source of ddr configuration data */ + enum mv_ddr_cfg_src cfg_src; + + /* raw spd data */ + union mv_ddr_spd_data spd_data; + + /* timing parameters */ + unsigned int timing_data[MV_DDR_TDATA_LAST]; }; /* DDR3 training global configuration parameters */ struct tune_train_params { u32 ck_delay; - u32 ck_delay_16; - u32 p_finger; - u32 n_finger; u32 phy_reg3_val; + u32 g_zpri_data; + u32 g_znri_data; + u32 g_zpri_ctrl; + u32 g_znri_ctrl; + u32 g_zpodt_data; + u32 g_znodt_data; + u32 g_zpodt_ctrl; + u32 g_znodt_ctrl; + u32 g_dic; + u32 g_odt_config; + u32 g_rtt_nom; + u32 g_rtt_wr; + u32 g_rtt_park; }; #endif /* _DDR_TOPOLOGY_DEF_H */ diff --git a/drivers/ddr/marvell/a38x/mv_ddr_build_message.c b/drivers/ddr/marvell/a38x/mv_ddr_build_message.c new file mode 100644 index 000000000000..8e60448318f2 --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_build_message.c @@ -0,0 +1 @@ +const char mv_ddr_build_message[] = ""; const char mv_ddr_version_string[] = "mv_ddr: mv_ddr-armada-17.10.4"; diff --git a/drivers/ddr/marvell/a38x/mv_ddr_common.c b/drivers/ddr/marvell/a38x/mv_ddr_common.c new file mode 100644 index 000000000000..25c452a469c1 --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_common.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include "mv_ddr_common.h" +#include "ddr_ml_wrapper.h" + +void mv_ddr_ver_print(void) +{ + printf("%s %s\n", mv_ddr_version_string, mv_ddr_build_message); +} + +/* ceiling division for positive integers */ +unsigned int ceil_div(unsigned int x, unsigned int y) +{ + return (x % y) ? (x / y + 1) : (x / y); +} + +/* + * time to number of clocks calculation based on the rounding algorithm + * using 97.4% inverse factor per JEDEC Standard No. 21-C, 4.1.2.L-4: + * Serial Presence Detect (SPD) for DDR4 SDRAM Modules + */ +unsigned int time_to_nclk(unsigned int t, unsigned int tclk) +{ + /* t & tclk parameters are in ps */ + return ((unsigned long)t * 1000 / tclk + 974) / 1000; +} + +/* round division of two positive integers to the nearest whole number */ +int round_div(unsigned int dividend, unsigned int divisor, unsigned int *quotient) +{ + if (quotient == NULL) { + printf("%s: error: NULL quotient pointer found\n", __func__); + return MV_FAIL; + } + + if (divisor == 0) { + printf("%s: error: division by zero\n", __func__); + return MV_FAIL; + } else { + *quotient = (dividend + divisor / 2) / divisor; + } + + return MV_OK; +} diff --git a/drivers/ddr/marvell/a38x/mv_ddr_common.h b/drivers/ddr/marvell/a38x/mv_ddr_common.h new file mode 100644 index 000000000000..edf4c4ca251f --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_common.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _MV_DDR_COMMON_H +#define _MV_DDR_COMMON_H + +extern const char mv_ddr_build_message[]; +extern const char mv_ddr_version_string[]; + +#define MV_DDR_NUM_BITS_IN_BYTE 8 +#define MV_DDR_MEGA_BITS (1024 * 1024) +#define MV_DDR_32_BITS_MASK 0xffffffff + +unsigned int ceil_div(unsigned int x, unsigned int y); +unsigned int time_to_nclk(unsigned int t, unsigned int tclk); +int round_div(unsigned int dividend, unsigned int divisor, unsigned int *quotient); + +#endif /* _MV_DDR_COMMON_H */ diff --git a/drivers/ddr/marvell/a38x/mv_ddr_plat.c b/drivers/ddr/marvell/a38x/mv_ddr_plat.c new file mode 100644 index 000000000000..058e262a61ad --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_plat.c @@ -0,0 +1,1456 @@ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include "ddr3_init.h" + +#include "mv_ddr_sys_env_lib.h" + +#define DDR_INTERFACES_NUM 1 +#define DDR_INTERFACE_OCTETS_NUM 5 + +/* + * 1. L2 filter should be set at binary header to 0xD000000, + * to avoid conflict with internal register IO. + * 2. U-Boot modifies internal registers base to 0xf100000, + * and than should update L2 filter accordingly to 0xf000000 (3.75 GB) + */ +#define L2_FILTER_FOR_MAX_MEMORY_SIZE 0xC0000000 /* temporary limit l2 filter to 3gb (LSP issue) */ +#define ADDRESS_FILTERING_END_REGISTER 0x8c04 + +#define DYNAMIC_CS_SIZE_CONFIG +#define DISABLE_L2_FILTERING_DURING_DDR_TRAINING + +/* Termal Sensor Registers */ +#define TSEN_CONTROL_LSB_REG 0xE4070 +#define TSEN_CONTROL_LSB_TC_TRIM_OFFSET 0 +#define TSEN_CONTROL_LSB_TC_TRIM_MASK (0x7 << TSEN_CONTROL_LSB_TC_TRIM_OFFSET) +#define TSEN_CONTROL_MSB_REG 0xE4074 +#define TSEN_CONTROL_MSB_RST_OFFSET 8 +#define TSEN_CONTROL_MSB_RST_MASK (0x1 << TSEN_CONTROL_MSB_RST_OFFSET) +#define TSEN_STATUS_REG 0xe4078 +#define TSEN_STATUS_READOUT_VALID_OFFSET 10 +#define TSEN_STATUS_READOUT_VALID_MASK (0x1 << \ + TSEN_STATUS_READOUT_VALID_OFFSET) +#define TSEN_STATUS_TEMP_OUT_OFFSET 0 +#define TSEN_STATUS_TEMP_OUT_MASK (0x3ff << TSEN_STATUS_TEMP_OUT_OFFSET) + +static struct dlb_config ddr3_dlb_config_table[] = { + {DLB_CTRL_REG, 0x2000005c}, + {DLB_BUS_OPT_WT_REG, 0x00880000}, + {DLB_AGING_REG, 0x0f7f007f}, + {DLB_EVICTION_CTRL_REG, 0x0000129f}, + {DLB_EVICTION_TIMERS_REG, 0x00ff0000}, + {DLB_WTS_DIFF_CS_REG, 0x04030802}, + {DLB_WTS_DIFF_BG_REG, 0x00000a02}, + {DLB_WTS_SAME_BG_REG, 0x09000a01}, + {DLB_WTS_CMDS_REG, 0x00020005}, + {DLB_WTS_ATTR_PRIO_REG, 0x00060f10}, + {DLB_QUEUE_MAP_REG, 0x00000543}, + {DLB_SPLIT_REG, 0x00000000}, + {DLB_USER_CMD_REG, 0x00000000}, + {0x0, 0x0} +}; + +static struct dlb_config *sys_env_dlb_config_ptr_get(void) +{ + return &ddr3_dlb_config_table[0]; +} + +static u8 a38x_bw_per_freq[DDR_FREQ_LAST] = { + 0x3, /* DDR_FREQ_100 */ + 0x4, /* DDR_FREQ_400 */ + 0x4, /* DDR_FREQ_533 */ + 0x5, /* DDR_FREQ_667 */ + 0x5, /* DDR_FREQ_800 */ + 0x5, /* DDR_FREQ_933 */ + 0x5, /* DDR_FREQ_1066 */ + 0x3, /* DDR_FREQ_311 */ + 0x3, /* DDR_FREQ_333 */ + 0x4, /* DDR_FREQ_467 */ + 0x5, /* DDR_FREQ_850 */ + 0x5, /* DDR_FREQ_600 */ + 0x3, /* DDR_FREQ_300 */ + 0x5, /* DDR_FREQ_900 */ + 0x3, /* DDR_FREQ_360 */ + 0x5 /* DDR_FREQ_1000 */ +}; + +static u8 a38x_rate_per_freq[DDR_FREQ_LAST] = { + 0x1, /* DDR_FREQ_100 */ + 0x2, /* DDR_FREQ_400 */ + 0x2, /* DDR_FREQ_533 */ + 0x2, /* DDR_FREQ_667 */ + 0x2, /* DDR_FREQ_800 */ + 0x3, /* DDR_FREQ_933 */ + 0x3, /* DDR_FREQ_1066 */ + 0x1, /* DDR_FREQ_311 */ + 0x1, /* DDR_FREQ_333 */ + 0x2, /* DDR_FREQ_467 */ + 0x2, /* DDR_FREQ_850 */ + 0x2, /* DDR_FREQ_600 */ + 0x1, /* DDR_FREQ_300 */ + 0x2, /* DDR_FREQ_900 */ + 0x1, /* DDR_FREQ_360 */ + 0x2 /* DDR_FREQ_1000 */ +}; + +static u16 a38x_vco_freq_per_sar_ref_clk_25_mhz[] = { + 666, /* 0 */ + 1332, + 800, + 1600, + 1066, + 2132, + 1200, + 2400, + 1332, + 1332, + 1500, + 1500, + 1600, /* 12 */ + 1600, + 1700, + 1700, + 1866, + 1866, + 1800, /* 18 */ + 2000, + 2000, + 4000, + 2132, + 2132, + 2300, + 2300, + 2400, + 2400, + 2500, + 2500, + 800 +}; + +static u16 a38x_vco_freq_per_sar_ref_clk_40_mhz[] = { + 666, /* 0 */ + 1332, + 800, + 800, /* 0x3 */ + 1066, + 1066, /* 0x5 */ + 1200, + 2400, + 1332, + 1332, + 1500, /* 10 */ + 1600, /* 0xB */ + 1600, + 1600, + 1700, + 1560, /* 0xF */ + 1866, + 1866, + 1800, + 2000, + 2000, /* 20 */ + 4000, + 2132, + 2132, + 2300, + 2300, + 2400, + 2400, + 2500, + 2500, + 1800 /* 30 - 0x1E */ +}; + + +static u32 async_mode_at_tf; + +static u32 dq_bit_map_2_phy_pin[] = { + 1, 0, 2, 6, 9, 8, 3, 7, /* 0 */ + 8, 9, 1, 7, 2, 6, 3, 0, /* 1 */ + 3, 9, 7, 8, 1, 0, 2, 6, /* 2 */ + 1, 0, 6, 2, 8, 3, 7, 9, /* 3 */ + 0, 1, 2, 9, 7, 8, 3, 6, /* 4 */ +}; + +void mv_ddr_mem_scrubbing(void) +{ +} + +static int ddr3_tip_a38x_set_divider(u8 dev_num, u32 if_id, + enum hws_ddr_freq freq); + +/* + * Read temperature TJ value + */ +static u32 ddr3_ctrl_get_junc_temp(u8 dev_num) +{ + int reg = 0; + + /* Initiates TSEN hardware reset once */ + if ((reg_read(TSEN_CONTROL_MSB_REG) & TSEN_CONTROL_MSB_RST_MASK) == 0) { + reg_bit_set(TSEN_CONTROL_MSB_REG, TSEN_CONTROL_MSB_RST_MASK); + /* set Tsen Tc Trim to correct default value (errata #132698) */ + reg = reg_read(TSEN_CONTROL_LSB_REG); + reg &= ~TSEN_CONTROL_LSB_TC_TRIM_MASK; + reg |= 0x3 << TSEN_CONTROL_LSB_TC_TRIM_OFFSET; + reg_write(TSEN_CONTROL_LSB_REG, reg); + } + mdelay(10); + + /* Check if the readout field is valid */ + if ((reg_read(TSEN_STATUS_REG) & TSEN_STATUS_READOUT_VALID_MASK) == 0) { + printf("%s: TSEN not ready\n", __func__); + return 0; + } + + reg = reg_read(TSEN_STATUS_REG); + reg = (reg & TSEN_STATUS_TEMP_OUT_MASK) >> TSEN_STATUS_TEMP_OUT_OFFSET; + + return ((((10000 * reg) / 21445) * 1000) - 272674) / 1000; +} + +/* + * Name: ddr3_tip_a38x_get_freq_config. + * Desc: + * Args: + * Notes: + * Returns: MV_OK if success, other error code if fail. + */ +static int ddr3_tip_a38x_get_freq_config(u8 dev_num, enum hws_ddr_freq freq, + struct hws_tip_freq_config_info + *freq_config_info) +{ + if (a38x_bw_per_freq[freq] == 0xff) + return MV_NOT_SUPPORTED; + + if (freq_config_info == NULL) + return MV_BAD_PARAM; + + freq_config_info->bw_per_freq = a38x_bw_per_freq[freq]; + freq_config_info->rate_per_freq = a38x_rate_per_freq[freq]; + freq_config_info->is_supported = 1; + + return MV_OK; +} + +static void dunit_read(u32 addr, u32 mask, u32 *data) +{ + *data = reg_read(addr) & mask; +} + +static void dunit_write(u32 addr, u32 mask, u32 data) +{ + u32 reg_val = data; + + if (mask != MASK_ALL_BITS) { + dunit_read(addr, MASK_ALL_BITS, ®_val); + reg_val &= (~mask); + reg_val |= (data & mask); + } + + reg_write(addr, reg_val); +} + +#define ODPG_ENABLE_REG 0x186d4 +#define ODPG_EN_OFFS 0 +#define ODPG_EN_MASK 0x1 +#define ODPG_EN_ENA 1 +#define ODPG_EN_DONE 0 +#define ODPG_DIS_OFFS 8 +#define ODPG_DIS_MASK 0x1 +#define ODPG_DIS_DIS 1 +void mv_ddr_odpg_enable(void) +{ + dunit_write(ODPG_ENABLE_REG, + ODPG_EN_MASK << ODPG_EN_OFFS, + ODPG_EN_ENA << ODPG_EN_OFFS); +} + +void mv_ddr_odpg_disable(void) +{ + dunit_write(ODPG_ENABLE_REG, + ODPG_DIS_MASK << ODPG_DIS_OFFS, + ODPG_DIS_DIS << ODPG_DIS_OFFS); +} + +void mv_ddr_odpg_done_clr(void) +{ + return; +} + +int mv_ddr_is_odpg_done(u32 count) +{ + u32 i, data; + + for (i = 0; i < count; i++) { + dunit_read(ODPG_ENABLE_REG, MASK_ALL_BITS, &data); + if (((data >> ODPG_EN_OFFS) & ODPG_EN_MASK) == + ODPG_EN_DONE) + break; + } + + if (i >= count) { + printf("%s: timeout\n", __func__); + return MV_FAIL; + } + + return MV_OK; +} + +void mv_ddr_training_enable(void) +{ + dunit_write(GLOB_CTRL_STATUS_REG, + TRAINING_TRIGGER_MASK << TRAINING_TRIGGER_OFFS, + TRAINING_TRIGGER_ENA << TRAINING_TRIGGER_OFFS); +} + +#define DRAM_INIT_CTRL_STATUS_REG 0x18488 +#define TRAINING_TRIGGER_OFFS 0 +#define TRAINING_TRIGGER_MASK 0x1 +#define TRAINING_TRIGGER_ENA 1 +#define TRAINING_DONE_OFFS 1 +#define TRAINING_DONE_MASK 0x1 +#define TRAINING_DONE_DONE 1 +#define TRAINING_DONE_NOT_DONE 0 +#define TRAINING_RESULT_OFFS 2 +#define TRAINING_RESULT_MASK 0x1 +#define TRAINING_RESULT_PASS 0 +#define TRAINING_RESULT_FAIL 1 +int mv_ddr_is_training_done(u32 count, u32 *result) +{ + u32 i, data; + + if (result == NULL) { + printf("%s: NULL result pointer found\n", __func__); + return MV_FAIL; + } + + for (i = 0; i < count; i++) { + dunit_read(DRAM_INIT_CTRL_STATUS_REG, MASK_ALL_BITS, &data); + if (((data >> TRAINING_DONE_OFFS) & TRAINING_DONE_MASK) == + TRAINING_DONE_DONE) + break; + } + + if (i >= count) { + printf("%s: timeout\n", __func__); + return MV_FAIL; + } + + *result = (data >> TRAINING_RESULT_OFFS) & TRAINING_RESULT_MASK; + + return MV_OK; +} + +#define DM_PAD 10 +u32 mv_ddr_dm_pad_get(void) +{ + return DM_PAD; +} + +/* + * Name: ddr3_tip_a38x_select_ddr_controller. + * Desc: Enable/Disable access to Marvell's server. + * Args: dev_num - device number + * enable - whether to enable or disable the server + * Notes: + * Returns: MV_OK if success, other error code if fail. + */ +static int ddr3_tip_a38x_select_ddr_controller(u8 dev_num, int enable) +{ + u32 reg; + + reg = reg_read(DUAL_DUNIT_CFG_REG); + + if (enable) + reg |= (1 << 6); + else + reg &= ~(1 << 6); + + reg_write(DUAL_DUNIT_CFG_REG, reg); + + return MV_OK; +} + +static u8 ddr3_tip_clock_mode(u32 frequency) +{ + if ((frequency == DDR_FREQ_LOW_FREQ) || (freq_val[frequency] <= 400)) + return 1; + + return 2; +} + +static int mv_ddr_sar_freq_get(int dev_num, enum hws_ddr_freq *freq) +{ + u32 reg, ref_clk_satr; + + /* Read sample@reset setting */ + reg = (reg_read(REG_DEVICE_SAR1_ADDR) >> + RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) & + RST2_CPU_DDR_CLOCK_SELECT_IN_MASK; + + ref_clk_satr = reg_read(DEVICE_SAMPLE_AT_RESET2_REG); + if (((ref_clk_satr >> DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_OFFSET) & 0x1) == + DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_25MHZ) { + switch (reg) { + case 0x1: + DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR, + ("Warning: Unsupported freq mode for 333Mhz configured(%d)\n", + reg)); + /* fallthrough */ + case 0x0: + *freq = DDR_FREQ_333; + break; + case 0x3: + DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR, + ("Warning: Unsupported freq mode for 400Mhz configured(%d)\n", + reg)); + /* fallthrough */ + case 0x2: + *freq = DDR_FREQ_400; + break; + case 0xd: + DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR, + ("Warning: Unsupported freq mode for 533Mhz configured(%d)\n", + reg)); + /* fallthrough */ + case 0x4: + *freq = DDR_FREQ_533; + break; + case 0x6: + *freq = DDR_FREQ_600; + break; + case 0x11: + case 0x14: + DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR, + ("Warning: Unsupported freq mode for 667Mhz configured(%d)\n", + reg)); + /* fallthrough */ + case 0x8: + *freq = DDR_FREQ_667; + break; + case 0x15: + case 0x1b: + DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR, + ("Warning: Unsupported freq mode for 800Mhz configured(%d)\n", + reg)); + /* fallthrough */ + case 0xc: + *freq = DDR_FREQ_800; + break; + case 0x10: + *freq = DDR_FREQ_933; + break; + case 0x12: + *freq = DDR_FREQ_900; + break; + case 0x13: + *freq = DDR_FREQ_933; + break; + default: + *freq = 0; + return MV_NOT_SUPPORTED; + } + } else { /* REFCLK 40MHz case */ + switch (reg) { + case 0x3: + *freq = DDR_FREQ_400; + break; + case 0x5: + *freq = DDR_FREQ_533; + break; + case 0xb: + *freq = DDR_FREQ_800; + break; + case 0x1e: + *freq = DDR_FREQ_900; + break; + default: + *freq = 0; + return MV_NOT_SUPPORTED; + } + } + + return MV_OK; +} + +static int ddr3_tip_a38x_get_medium_freq(int dev_num, enum hws_ddr_freq *freq) +{ + u32 reg, ref_clk_satr; + + /* Read sample at reset setting */ + reg = (reg_read(REG_DEVICE_SAR1_ADDR) >> + RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) & + RST2_CPU_DDR_CLOCK_SELECT_IN_MASK; + + ref_clk_satr = reg_read(DEVICE_SAMPLE_AT_RESET2_REG); + if (((ref_clk_satr >> DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_OFFSET) & 0x1) == + DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_25MHZ) { + switch (reg) { + case 0x0: + case 0x1: + /* Medium is same as TF to run PBS in this freq */ + *freq = DDR_FREQ_333; + break; + case 0x2: + case 0x3: + /* Medium is same as TF to run PBS in this freq */ + *freq = DDR_FREQ_400; + break; + case 0x4: + case 0xd: + /* Medium is same as TF to run PBS in this freq */ + *freq = DDR_FREQ_533; + break; + case 0x8: + case 0x10: + case 0x11: + case 0x14: + *freq = DDR_FREQ_333; + break; + case 0xc: + case 0x15: + case 0x1b: + *freq = DDR_FREQ_400; + break; + case 0x6: + *freq = DDR_FREQ_300; + break; + case 0x12: + *freq = DDR_FREQ_360; + break; + case 0x13: + *freq = DDR_FREQ_400; + break; + default: + *freq = 0; + return MV_NOT_SUPPORTED; + } + } else { /* REFCLK 40MHz case */ + switch (reg) { + case 0x3: + /* Medium is same as TF to run PBS in this freq */ + *freq = DDR_FREQ_400; + break; + case 0x5: + /* Medium is same as TF to run PBS in this freq */ + *freq = DDR_FREQ_533; + break; + case 0xb: + *freq = DDR_FREQ_400; + break; + case 0x1e: + *freq = DDR_FREQ_360; + break; + default: + *freq = 0; + return MV_NOT_SUPPORTED; + } + } + + return MV_OK; +} + +static int ddr3_tip_a38x_get_device_info(u8 dev_num, struct ddr3_device_info *info_ptr) +{ +#if defined(CONFIG_ARMADA_39X) + info_ptr->device_id = 0x6900; +#else + info_ptr->device_id = 0x6800; +#endif + info_ptr->ck_delay = ck_delay; + + return MV_OK; +} + +/* check indirect access to phy register file completed */ +static int is_prfa_done(void) +{ + u32 reg_val; + u32 iter = 0; + + do { + if (iter++ > MAX_POLLING_ITERATIONS) { + printf("error: %s: polling timeout\n", __func__); + return MV_FAIL; + } + dunit_read(PHY_REG_FILE_ACCESS_REG, MASK_ALL_BITS, ®_val); + reg_val >>= PRFA_REQ_OFFS; + reg_val &= PRFA_REQ_MASK; + } while (reg_val == PRFA_REQ_ENA); /* request pending */ + + return MV_OK; +} + +/* write to phy register thru indirect access */ +static int prfa_write(enum hws_access_type phy_access, u32 phy, + enum hws_ddr_phy phy_type, u32 addr, + u32 data, enum hws_operation op_type) +{ + u32 reg_val = ((data & PRFA_DATA_MASK) << PRFA_DATA_OFFS) | + ((addr & PRFA_REG_NUM_MASK) << PRFA_REG_NUM_OFFS) | + ((phy & PRFA_PUP_NUM_MASK) << PRFA_PUP_NUM_OFFS) | + ((phy_type & PRFA_PUP_CTRL_DATA_MASK) << PRFA_PUP_CTRL_DATA_OFFS) | + ((phy_access & PRFA_PUP_BCAST_WR_ENA_MASK) << PRFA_PUP_BCAST_WR_ENA_OFFS) | + (((addr >> 6) & PRFA_REG_NUM_HI_MASK) << PRFA_REG_NUM_HI_OFFS) | + ((op_type & PRFA_TYPE_MASK) << PRFA_TYPE_OFFS); + dunit_write(PHY_REG_FILE_ACCESS_REG, MASK_ALL_BITS, reg_val); + reg_val |= (PRFA_REQ_ENA << PRFA_REQ_OFFS); + dunit_write(PHY_REG_FILE_ACCESS_REG, MASK_ALL_BITS, reg_val); + + /* polling for prfa request completion */ + if (is_prfa_done() != MV_OK) + return MV_FAIL; + + return MV_OK; +} + +/* read from phy register thru indirect access */ +static int prfa_read(enum hws_access_type phy_access, u32 phy, + enum hws_ddr_phy phy_type, u32 addr, u32 *data) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + u32 max_phy = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE); + u32 i, reg_val; + + if (phy_access == ACCESS_TYPE_MULTICAST) { + for (i = 0; i < max_phy; i++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, i); + if (prfa_write(ACCESS_TYPE_UNICAST, i, phy_type, addr, 0, OPERATION_READ) != MV_OK) + return MV_FAIL; + dunit_read(PHY_REG_FILE_ACCESS_REG, MASK_ALL_BITS, ®_val); + data[i] = (reg_val >> PRFA_DATA_OFFS) & PRFA_DATA_MASK; + } + } else { + if (prfa_write(phy_access, phy, phy_type, addr, 0, OPERATION_READ) != MV_OK) + return MV_FAIL; + dunit_read(PHY_REG_FILE_ACCESS_REG, MASK_ALL_BITS, ®_val); + *data = (reg_val >> PRFA_DATA_OFFS) & PRFA_DATA_MASK; + } + + return MV_OK; +} + +static int mv_ddr_sw_db_init(u32 dev_num, u32 board_id) +{ + struct hws_tip_config_func_db config_func; + + /* new read leveling version */ + config_func.mv_ddr_dunit_read = dunit_read; + config_func.mv_ddr_dunit_write = dunit_write; + config_func.tip_dunit_mux_select_func = + ddr3_tip_a38x_select_ddr_controller; + config_func.tip_get_freq_config_info_func = + ddr3_tip_a38x_get_freq_config; + config_func.tip_set_freq_divider_func = ddr3_tip_a38x_set_divider; + config_func.tip_get_device_info_func = ddr3_tip_a38x_get_device_info; + config_func.tip_get_temperature = ddr3_ctrl_get_junc_temp; + config_func.tip_get_clock_ratio = ddr3_tip_clock_mode; + config_func.tip_external_read = ddr3_tip_ext_read; + config_func.tip_external_write = ddr3_tip_ext_write; + config_func.mv_ddr_phy_read = prfa_read; + config_func.mv_ddr_phy_write = prfa_write; + + ddr3_tip_init_config_func(dev_num, &config_func); + + ddr3_tip_register_dq_table(dev_num, dq_bit_map_2_phy_pin); + + /* set device attributes*/ + ddr3_tip_dev_attr_init(dev_num); + ddr3_tip_dev_attr_set(dev_num, MV_ATTR_TIP_REV, MV_TIP_REV_4); + ddr3_tip_dev_attr_set(dev_num, MV_ATTR_PHY_EDGE, MV_DDR_PHY_EDGE_POSITIVE); + ddr3_tip_dev_attr_set(dev_num, MV_ATTR_OCTET_PER_INTERFACE, DDR_INTERFACE_OCTETS_NUM); +#ifdef CONFIG_ARMADA_39X + ddr3_tip_dev_attr_set(dev_num, MV_ATTR_INTERLEAVE_WA, 1); +#else + ddr3_tip_dev_attr_set(dev_num, MV_ATTR_INTERLEAVE_WA, 0); +#endif + + ca_delay = 0; + delay_enable = 1; + dfs_low_freq = DFS_LOW_FREQ_VALUE; + calibration_update_control = 1; + +#ifdef CONFIG_ARMADA_38X + /* For a38x only, change to 2T mode to resolve low freq instability */ + mode_2t = 1; +#endif + + ddr3_tip_a38x_get_medium_freq(dev_num, &medium_freq); + + return MV_OK; +} + +static int mv_ddr_training_mask_set(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + enum hws_ddr_freq ddr_freq = tm->interface_params[0].memory_freq; + + mask_tune_func = (SET_LOW_FREQ_MASK_BIT | + LOAD_PATTERN_MASK_BIT | + SET_MEDIUM_FREQ_MASK_BIT | WRITE_LEVELING_MASK_BIT | + WRITE_LEVELING_SUPP_MASK_BIT | + READ_LEVELING_MASK_BIT | + PBS_RX_MASK_BIT | + PBS_TX_MASK_BIT | + SET_TARGET_FREQ_MASK_BIT | + WRITE_LEVELING_TF_MASK_BIT | + WRITE_LEVELING_SUPP_TF_MASK_BIT | + READ_LEVELING_TF_MASK_BIT | + CENTRALIZATION_RX_MASK_BIT | + CENTRALIZATION_TX_MASK_BIT); + rl_mid_freq_wa = 1; + + if ((ddr_freq == DDR_FREQ_333) || (ddr_freq == DDR_FREQ_400)) { + mask_tune_func = (WRITE_LEVELING_MASK_BIT | + LOAD_PATTERN_2_MASK_BIT | + WRITE_LEVELING_SUPP_MASK_BIT | + READ_LEVELING_MASK_BIT | + PBS_RX_MASK_BIT | + PBS_TX_MASK_BIT | + CENTRALIZATION_RX_MASK_BIT | + CENTRALIZATION_TX_MASK_BIT); + rl_mid_freq_wa = 0; /* WA not needed if 333/400 is TF */ + } + + /* Supplementary not supported for ECC modes */ + if (1 == ddr3_if_ecc_enabled()) { + mask_tune_func &= ~WRITE_LEVELING_SUPP_TF_MASK_BIT; + mask_tune_func &= ~WRITE_LEVELING_SUPP_MASK_BIT; + mask_tune_func &= ~PBS_TX_MASK_BIT; + mask_tune_func &= ~PBS_RX_MASK_BIT; + } + + return MV_OK; +} + +/* function: mv_ddr_set_calib_controller + * this function sets the controller which will control + * the calibration cycle in the end of the training. + * 1 - internal controller + * 2 - external controller + */ +void mv_ddr_set_calib_controller(void) +{ + calibration_update_control = CAL_UPDATE_CTRL_INT; +} + +static int ddr3_tip_a38x_set_divider(u8 dev_num, u32 if_id, + enum hws_ddr_freq frequency) +{ + u32 divider = 0; + u32 sar_val, ref_clk_satr; + u32 async_val; + + if (if_id != 0) { + DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR, + ("A38x does not support interface 0x%x\n", + if_id)); + return MV_BAD_PARAM; + } + + /* get VCO freq index */ + sar_val = (reg_read(REG_DEVICE_SAR1_ADDR) >> + RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) & + RST2_CPU_DDR_CLOCK_SELECT_IN_MASK; + + ref_clk_satr = reg_read(DEVICE_SAMPLE_AT_RESET2_REG); + if (((ref_clk_satr >> DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_OFFSET) & 0x1) == + DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_25MHZ) + divider = a38x_vco_freq_per_sar_ref_clk_25_mhz[sar_val] / freq_val[frequency]; + else + divider = a38x_vco_freq_per_sar_ref_clk_40_mhz[sar_val] / freq_val[frequency]; + + if ((async_mode_at_tf == 1) && (freq_val[frequency] > 400)) { + /* Set async mode */ + dunit_write(0x20220, 0x1000, 0x1000); + dunit_write(0xe42f4, 0x200, 0x200); + + /* Wait for async mode setup */ + mdelay(5); + + /* Set KNL values */ + switch (frequency) { +#ifdef CONFIG_DDR3 + case DDR_FREQ_467: + async_val = 0x806f012; + break; + case DDR_FREQ_533: + async_val = 0x807f012; + break; + case DDR_FREQ_600: + async_val = 0x805f00a; + break; +#endif + case DDR_FREQ_667: + async_val = 0x809f012; + break; + case DDR_FREQ_800: + async_val = 0x807f00a; + break; +#ifdef CONFIG_DDR3 + case DDR_FREQ_850: + async_val = 0x80cb012; + break; +#endif + case DDR_FREQ_900: + async_val = 0x80d7012; + break; + case DDR_FREQ_933: + async_val = 0x80df012; + break; + case DDR_FREQ_1000: + async_val = 0x80ef012; + break; + case DDR_FREQ_1066: + async_val = 0x80ff012; + break; + default: + /* set DDR_FREQ_667 as default */ + async_val = 0x809f012; + } + dunit_write(0xe42f0, 0xffffffff, async_val); + } else { + /* Set sync mode */ + dunit_write(0x20220, 0x1000, 0x0); + dunit_write(0xe42f4, 0x200, 0x0); + + /* cpupll_clkdiv_reset_mask */ + dunit_write(0xe4264, 0xff, 0x1f); + + /* cpupll_clkdiv_reload_smooth */ + dunit_write(0xe4260, (0xff << 8), (0x2 << 8)); + + /* cpupll_clkdiv_relax_en */ + dunit_write(0xe4260, (0xff << 24), (0x2 << 24)); + + /* write the divider */ + dunit_write(0xe4268, (0x3f << 8), (divider << 8)); + + /* set cpupll_clkdiv_reload_ratio */ + dunit_write(0xe4264, (1 << 8), (1 << 8)); + + /* undet cpupll_clkdiv_reload_ratio */ + dunit_write(0xe4264, (1 << 8), 0x0); + + /* clear cpupll_clkdiv_reload_force */ + dunit_write(0xe4260, (0xff << 8), 0x0); + + /* clear cpupll_clkdiv_relax_en */ + dunit_write(0xe4260, (0xff << 24), 0x0); + + /* clear cpupll_clkdiv_reset_mask */ + dunit_write(0xe4264, 0xff, 0x0); + } + + /* Dunit training clock + 1:1/2:1 mode */ + dunit_write(0x18488, (1 << 16), ((ddr3_tip_clock_mode(frequency) & 0x1) << 16)); + dunit_write(0x1524, (1 << 15), ((ddr3_tip_clock_mode(frequency) - 1) << 15)); + + return MV_OK; +} + +/* + * external read from memory + */ +int ddr3_tip_ext_read(u32 dev_num, u32 if_id, u32 reg_addr, + u32 num_of_bursts, u32 *data) +{ + u32 burst_num; + + for (burst_num = 0; burst_num < num_of_bursts * 8; burst_num++) + data[burst_num] = readl(reg_addr + 4 * burst_num); + + return MV_OK; +} + +/* + * external write to memory + */ +int ddr3_tip_ext_write(u32 dev_num, u32 if_id, u32 reg_addr, + u32 num_of_bursts, u32 *data) { + u32 burst_num; + + for (burst_num = 0; burst_num < num_of_bursts * 8; burst_num++) + writel(data[burst_num], reg_addr + 4 * burst_num); + + return MV_OK; +} + +int mv_ddr_early_init(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + /* FIXME: change this configuration per ddr type + * configure a380 and a390 to work with receiver odt timing + * the odt_config is defined: + * '1' in ddr4 + * '0' in ddr3 + * here the parameter is run over in ddr4 and ddr3 to '1' (in ddr4 the default is '1') + * to configure the odt to work with timing restrictions + */ + + mv_ddr_sw_db_init(0, 0); + + if (tm->interface_params[0].memory_freq != DDR_FREQ_SAR) + async_mode_at_tf = 1; + + return MV_OK; +} + +int mv_ddr_early_init2(void) +{ + mv_ddr_training_mask_set(); + + return MV_OK; +} + +int mv_ddr_pre_training_fixup(void) +{ + return 0; +} + +int mv_ddr_post_training_fixup(void) +{ + return 0; +} + +int ddr3_post_run_alg(void) +{ + return MV_OK; +} + +int ddr3_silicon_post_init(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + /* Set half bus width */ + if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask)) { + CHECK_STATUS(ddr3_tip_if_write + (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, + SDRAM_CFG_REG, 0x0, 0x8000)); + } + + return MV_OK; +} + +u32 mv_ddr_init_freq_get(void) +{ + enum hws_ddr_freq freq; + + mv_ddr_sar_freq_get(0, &freq); + + return freq; +} + +static u32 ddr3_get_bus_width(void) +{ + u32 bus_width; + + bus_width = (reg_read(SDRAM_CFG_REG) & 0x8000) >> + BUS_IN_USE_OFFS; + + return (bus_width == 0) ? 16 : 32; +} + +static u32 ddr3_get_device_width(u32 cs) +{ + u32 device_width; + + device_width = (reg_read(SDRAM_ADDR_CTRL_REG) & + (CS_STRUCT_MASK << CS_STRUCT_OFFS(cs))) >> + CS_STRUCT_OFFS(cs); + + return (device_width == 0) ? 8 : 16; +} + +static u32 ddr3_get_device_size(u32 cs) +{ + u32 device_size_low, device_size_high, device_size; + u32 data, cs_low_offset, cs_high_offset; + + cs_low_offset = CS_SIZE_OFFS(cs); + cs_high_offset = CS_SIZE_HIGH_OFFS(cs); + + data = reg_read(SDRAM_ADDR_CTRL_REG); + device_size_low = (data >> cs_low_offset) & 0x3; + device_size_high = (data >> cs_high_offset) & 0x1; + + device_size = device_size_low | (device_size_high << 2); + + switch (device_size) { + case 0: + return 2048; + case 2: + return 512; + case 3: + return 1024; + case 4: + return 4096; + case 5: + return 8192; + case 1: + default: + DEBUG_INIT_C("Error: Wrong device size of Cs: ", cs, 1); + /* zeroes mem size in ddr3_calc_mem_cs_size */ + return 0; + } +} + +static int ddr3_calc_mem_cs_size(u32 cs, uint64_t *cs_size) +{ + u32 cs_mem_size; + + /* Calculate in MiB */ + cs_mem_size = ((ddr3_get_bus_width() / ddr3_get_device_width(cs)) * + ddr3_get_device_size(cs)) / 8; + + /* + * Multiple controller bus width, 2x for 64 bit + * (SoC controller may be 32 or 64 bit, + * so bit 15 in 0x1400, that means if whole bus used or only half, + * have a differnt meaning + */ + cs_mem_size *= DDR_CONTROLLER_BUS_WIDTH_MULTIPLIER; + + if ((cs_mem_size < 128) || (cs_mem_size > 4096)) { + DEBUG_INIT_C("Error: Wrong Memory size of Cs: ", cs, 1); + return MV_BAD_VALUE; + } + + *cs_size = cs_mem_size << 20; /* write cs size in bytes */ + + return MV_OK; +} + +static int ddr3_fast_path_dynamic_cs_size_config(u32 cs_ena) +{ + u32 reg, cs; + uint64_t mem_total_size = 0; + uint64_t cs_mem_size = 0; + uint64_t mem_total_size_c, cs_mem_size_c; + +#ifdef DEVICE_MAX_DRAM_ADDRESS_SIZE + u32 physical_mem_size; + u32 max_mem_size = DEVICE_MAX_DRAM_ADDRESS_SIZE; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); +#endif + + /* Open fast path windows */ + for (cs = 0; cs < MAX_CS_NUM; cs++) { + if (cs_ena & (1 << cs)) { + /* get CS size */ + if (ddr3_calc_mem_cs_size(cs, &cs_mem_size) != MV_OK) + return MV_FAIL; + +#ifdef DEVICE_MAX_DRAM_ADDRESS_SIZE + /* + * if number of address pins doesn't allow to use max + * mem size that is defined in topology + * mem size is defined by DEVICE_MAX_DRAM_ADDRESS_SIZE + */ + physical_mem_size = mem_size + [tm->interface_params[0].memory_size]; + + if (ddr3_get_device_width(cs) == 16) { + /* + * 16bit mem device can be twice more - no need + * in less significant pin + */ + max_mem_size = DEVICE_MAX_DRAM_ADDRESS_SIZE * 2; + } + + if (physical_mem_size > max_mem_size) { + cs_mem_size = max_mem_size * + (ddr3_get_bus_width() / + ddr3_get_device_width(cs)); + printf("Updated Physical Mem size is from 0x%x to %x\n", + physical_mem_size, + DEVICE_MAX_DRAM_ADDRESS_SIZE); + } +#endif + + /* set fast path window control for the cs */ + reg = 0xffffe1; + reg |= (cs << 2); + reg |= (cs_mem_size - 1) & 0xffff0000; + /*Open fast path Window */ + reg_write(REG_FASTPATH_WIN_CTRL_ADDR(cs), reg); + + /* Set fast path window base address for the cs */ + reg = ((cs_mem_size) * cs) & 0xffff0000; + /* Set base address */ + reg_write(REG_FASTPATH_WIN_BASE_ADDR(cs), reg); + + /* + * Since memory size may be bigger than 4G the summ may + * be more than 32 bit word, + * so to estimate the result divide mem_total_size and + * cs_mem_size by 0x10000 (it is equal to >> 16) + */ + mem_total_size_c = (mem_total_size >> 16) & 0xffffffffffff; + cs_mem_size_c = (cs_mem_size >> 16) & 0xffffffffffff; + /* if the sum less than 2 G - calculate the value */ + if (mem_total_size_c + cs_mem_size_c < 0x10000) + mem_total_size += cs_mem_size; + else /* put max possible size */ + mem_total_size = L2_FILTER_FOR_MAX_MEMORY_SIZE; + } + } + + /* Set L2 filtering to Max Memory size */ + reg_write(ADDRESS_FILTERING_END_REGISTER, mem_total_size); + + return MV_OK; +} + +static int ddr3_restore_and_set_final_windows(u32 *win, const char *ddr_type) +{ + u32 win_ctrl_reg, num_of_win_regs; + u32 cs_ena = mv_ddr_sys_env_get_cs_ena_from_reg(); + u32 ui; + + win_ctrl_reg = REG_XBAR_WIN_4_CTRL_ADDR; + num_of_win_regs = 16; + + /* Return XBAR windows 4-7 or 16-19 init configuration */ + for (ui = 0; ui < num_of_win_regs; ui++) + reg_write((win_ctrl_reg + 0x4 * ui), win[ui]); + + printf("%s Training Sequence - Switching XBAR Window to FastPath Window\n", + ddr_type); + +#if defined DYNAMIC_CS_SIZE_CONFIG + if (ddr3_fast_path_dynamic_cs_size_config(cs_ena) != MV_OK) + printf("ddr3_fast_path_dynamic_cs_size_config FAILED\n"); +#else + u32 reg, cs; + reg = 0x1fffffe1; + for (cs = 0; cs < MAX_CS_NUM; cs++) { + if (cs_ena & (1 << cs)) { + reg |= (cs << 2); + break; + } + } + /* Open fast path Window to - 0.5G */ + reg_write(REG_FASTPATH_WIN_CTRL_ADDR(0), reg); +#endif + + return MV_OK; +} + +static int ddr3_save_and_set_training_windows(u32 *win) +{ + u32 cs_ena; + u32 reg, tmp_count, cs, ui; + u32 win_ctrl_reg, win_base_reg, win_remap_reg; + u32 num_of_win_regs, win_jump_index; + win_ctrl_reg = REG_XBAR_WIN_4_CTRL_ADDR; + win_base_reg = REG_XBAR_WIN_4_BASE_ADDR; + win_remap_reg = REG_XBAR_WIN_4_REMAP_ADDR; + win_jump_index = 0x10; + num_of_win_regs = 16; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + +#ifdef DISABLE_L2_FILTERING_DURING_DDR_TRAINING + /* + * Disable L2 filtering during DDR training + * (when Cross Bar window is open) + */ + reg_write(ADDRESS_FILTERING_END_REGISTER, 0); +#endif + + cs_ena = tm->interface_params[0].as_bus_params[0].cs_bitmask; + + /* Close XBAR Window 19 - Not needed */ + /* {0x000200e8} - Open Mbus Window - 2G */ + reg_write(REG_XBAR_WIN_19_CTRL_ADDR, 0); + + /* Save XBAR Windows 4-19 init configurations */ + for (ui = 0; ui < num_of_win_regs; ui++) + win[ui] = reg_read(win_ctrl_reg + 0x4 * ui); + + /* Open XBAR Windows 4-7 or 16-19 for other CS */ + reg = 0; + tmp_count = 0; + for (cs = 0; cs < MAX_CS_NUM; cs++) { + if (cs_ena & (1 << cs)) { + switch (cs) { + case 0: + reg = 0x0e00; + break; + case 1: + reg = 0x0d00; + break; + case 2: + reg = 0x0b00; + break; + case 3: + reg = 0x0700; + break; + } + reg |= (1 << 0); + reg |= (SDRAM_CS_SIZE & 0xffff0000); + + reg_write(win_ctrl_reg + win_jump_index * tmp_count, + reg); + reg = (((SDRAM_CS_SIZE + 1) * (tmp_count)) & + 0xffff0000); + reg_write(win_base_reg + win_jump_index * tmp_count, + reg); + + if (win_remap_reg <= REG_XBAR_WIN_7_REMAP_ADDR) + reg_write(win_remap_reg + + win_jump_index * tmp_count, 0); + + tmp_count++; + } + } + + return MV_OK; +} + +static u32 win[16]; + +int mv_ddr_pre_training_soc_config(const char *ddr_type) +{ + u32 soc_num; + u32 reg_val; + + /* Switching CPU to MRVL ID */ + soc_num = (reg_read(REG_SAMPLE_RESET_HIGH_ADDR) & SAR1_CPU_CORE_MASK) >> + SAR1_CPU_CORE_OFFSET; + switch (soc_num) { + case 0x3: + reg_bit_set(CPU_CONFIGURATION_REG(3), CPU_MRVL_ID_OFFSET); + reg_bit_set(CPU_CONFIGURATION_REG(2), CPU_MRVL_ID_OFFSET); + /* fallthrough */ + case 0x1: + reg_bit_set(CPU_CONFIGURATION_REG(1), CPU_MRVL_ID_OFFSET); + /* fallthrough */ + case 0x0: + reg_bit_set(CPU_CONFIGURATION_REG(0), CPU_MRVL_ID_OFFSET); + /* fallthrough */ + default: + break; + } + + /* + * Set DRAM Reset Mask in case detected GPIO indication of wakeup from + * suspend i.e the DRAM values will not be overwritten / reset when + * waking from suspend + */ + if (mv_ddr_sys_env_suspend_wakeup_check() == + SUSPEND_WAKEUP_ENABLED_GPIO_DETECTED) { + reg_bit_set(SDRAM_INIT_CTRL_REG, + DRAM_RESET_MASK_MASKED << DRAM_RESET_MASK_OFFS); + } + + /* Check if DRAM is already initialized */ + if (reg_read(REG_BOOTROM_ROUTINE_ADDR) & + (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)) { + printf("%s Training Sequence - 2nd boot - Skip\n", ddr_type); + return MV_OK; + } + + /* Fix read ready phases for all SOC in reg 0x15c8 */ + reg_val = reg_read(TRAINING_DBG_3_REG); + + reg_val &= ~(TRN_DBG_RDY_INC_PH_2TO1_MASK << TRN_DBG_RDY_INC_PH_2TO1_OFFS(0)); + reg_val |= (0x4 << TRN_DBG_RDY_INC_PH_2TO1_OFFS(0)); /* phase 0 */ + + reg_val &= ~(TRN_DBG_RDY_INC_PH_2TO1_MASK << TRN_DBG_RDY_INC_PH_2TO1_OFFS(1)); + reg_val |= (0x4 << TRN_DBG_RDY_INC_PH_2TO1_OFFS(1)); /* phase 1 */ + + reg_val &= ~(TRN_DBG_RDY_INC_PH_2TO1_MASK << TRN_DBG_RDY_INC_PH_2TO1_OFFS(3)); + reg_val |= (0x6 << TRN_DBG_RDY_INC_PH_2TO1_OFFS(3)); /* phase 3 */ + + reg_val &= ~(TRN_DBG_RDY_INC_PH_2TO1_MASK << TRN_DBG_RDY_INC_PH_2TO1_OFFS(4)); + reg_val |= (0x6 << TRN_DBG_RDY_INC_PH_2TO1_OFFS(4)); /* phase 4 */ + + reg_val &= ~(TRN_DBG_RDY_INC_PH_2TO1_MASK << TRN_DBG_RDY_INC_PH_2TO1_OFFS(5)); + reg_val |= (0x6 << TRN_DBG_RDY_INC_PH_2TO1_OFFS(5)); /* phase 5 */ + + reg_write(TRAINING_DBG_3_REG, reg_val); + + /* + * Axi_bresp_mode[8] = Compliant, + * Axi_addr_decode_cntrl[11] = Internal, + * Axi_data_bus_width[0] = 128bit + * */ + /* 0x14a8 - AXI Control Register */ + reg_write(AXI_CTRL_REG, 0); + + /* + * Stage 2 - Training Values Setup + */ + /* Set X-BAR windows for the training sequence */ + ddr3_save_and_set_training_windows(win); + + return MV_OK; +} + +static int ddr3_new_tip_dlb_config(void) +{ + u32 reg, i = 0; + struct dlb_config *config_table_ptr = sys_env_dlb_config_ptr_get(); + + /* Write the configuration */ + while (config_table_ptr[i].reg_addr != 0) { + reg_write(config_table_ptr[i].reg_addr, + config_table_ptr[i].reg_data); + i++; + } + + + /* Enable DLB */ + reg = reg_read(DLB_CTRL_REG); + reg &= ~(DLB_EN_MASK << DLB_EN_OFFS) & + ~(WR_COALESCE_EN_MASK << WR_COALESCE_EN_OFFS) & + ~(AXI_PREFETCH_EN_MASK << AXI_PREFETCH_EN_OFFS) & + ~(MBUS_PREFETCH_EN_MASK << MBUS_PREFETCH_EN_OFFS) & + ~(PREFETCH_NXT_LN_SZ_TRIG_MASK << PREFETCH_NXT_LN_SZ_TRIG_OFFS); + + reg |= (DLB_EN_ENA << DLB_EN_OFFS) | + (WR_COALESCE_EN_ENA << WR_COALESCE_EN_OFFS) | + (AXI_PREFETCH_EN_ENA << AXI_PREFETCH_EN_OFFS) | + (MBUS_PREFETCH_EN_ENA << MBUS_PREFETCH_EN_OFFS) | + (PREFETCH_NXT_LN_SZ_TRIG_ENA << PREFETCH_NXT_LN_SZ_TRIG_OFFS); + + reg_write(DLB_CTRL_REG, reg); + + return MV_OK; +} + +int mv_ddr_post_training_soc_config(const char *ddr_type) +{ + u32 reg_val; + + /* Restore and set windows */ + ddr3_restore_and_set_final_windows(win, ddr_type); + + /* Update DRAM init indication in bootROM register */ + reg_val = reg_read(REG_BOOTROM_ROUTINE_ADDR); + reg_write(REG_BOOTROM_ROUTINE_ADDR, + reg_val | (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)); + + /* DLB config */ + ddr3_new_tip_dlb_config(); + + return MV_OK; +} + +void mv_ddr_mc_config(void) +{ + /* Memory controller initializations */ + struct init_cntr_param init_param; + int status; + + init_param.do_mrs_phy = 1; + init_param.is_ctrl64_bit = 0; + init_param.init_phy = 1; + init_param.msys_init = 1; + status = hws_ddr3_tip_init_controller(0, &init_param); + if (status != MV_OK) + printf("DDR3 init controller - FAILED 0x%x\n", status); + + status = mv_ddr_mc_init(); + if (status != MV_OK) + printf("DDR3 init_sequence - FAILED 0x%x\n", status); +} +/* function: mv_ddr_mc_init + * this function enables the dunit after init controller configuration + */ +int mv_ddr_mc_init(void) +{ + CHECK_STATUS(ddr3_tip_enable_init_sequence(0)); + + return MV_OK; +} + +/* function: ddr3_tip_configure_phy + * configures phy and electrical parameters + */ +int ddr3_tip_configure_phy(u32 dev_num) +{ + u32 if_id, phy_id; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, + PAD_ZRI_CAL_PHY_REG, + ((0x7f & g_zpri_data) << 7 | (0x7f & g_znri_data)))); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_CONTROL, + PAD_ZRI_CAL_PHY_REG, + ((0x7f & g_zpri_ctrl) << 7 | (0x7f & g_znri_ctrl)))); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, + PAD_ODT_CAL_PHY_REG, + ((0x3f & g_zpodt_data) << 6 | (0x3f & g_znodt_data)))); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_CONTROL, + PAD_ODT_CAL_PHY_REG, + ((0x3f & g_zpodt_ctrl) << 6 | (0x3f & g_znodt_ctrl)))); + + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, + PAD_PRE_DISABLE_PHY_REG, 0)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, + CMOS_CONFIG_PHY_REG, 0)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_CONTROL, + CMOS_CONFIG_PHY_REG, 0)); + + for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { + /* check if the interface is enabled */ + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + + for (phy_id = 0; + phy_id < octets_per_if_num; + phy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, phy_id); + /* Vref & clamp */ + CHECK_STATUS(ddr3_tip_bus_read_modify_write + (dev_num, ACCESS_TYPE_UNICAST, + if_id, phy_id, DDR_PHY_DATA, + PAD_CFG_PHY_REG, + ((clamp_tbl[if_id] << 4) | vref_init_val), + ((0x7 << 4) | 0x7))); + /* clamp not relevant for control */ + CHECK_STATUS(ddr3_tip_bus_read_modify_write + (dev_num, ACCESS_TYPE_UNICAST, + if_id, phy_id, DDR_PHY_CONTROL, + PAD_CFG_PHY_REG, 0x4, 0x7)); + } + } + + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_PHY_EDGE) == + MV_DDR_PHY_EDGE_POSITIVE) + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + DDR_PHY_DATA, 0x90, 0x6002)); + + + return MV_OK; +} + + +int mv_ddr_manual_cal_do(void) +{ + return 0; +} diff --git a/drivers/ddr/marvell/a38x/mv_ddr_plat.h b/drivers/ddr/marvell/a38x/mv_ddr_plat.h new file mode 100644 index 000000000000..73e54c4b735c --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_plat.h @@ -0,0 +1,236 @@ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _MV_DDR_PLAT_H +#define _MV_DDR_PLAT_H + +#define MAX_INTERFACE_NUM 1 +#define MAX_BUS_NUM 5 +#define DDR_IF_CTRL_SUBPHYS_NUM 3 + +#define DFS_LOW_FREQ_VALUE 120 +#define SDRAM_CS_SIZE 0xfffffff /* FIXME: implement a function for cs size for each platform */ + +#define INTER_REGS_BASE SOC_REGS_PHY_BASE +#define AP_INT_REG_START_ADDR 0xd0000000 +#define AP_INT_REG_END_ADDR 0xd0100000 + +/* Controler bus divider 1 for 32 bit, 2 for 64 bit */ +#define DDR_CONTROLLER_BUS_WIDTH_MULTIPLIER 1 + +/* Tune internal training params values */ +#define TUNE_TRAINING_PARAMS_CK_DELAY 160 +#define TUNE_TRAINING_PARAMS_PHYREG3VAL 0xA +#define TUNE_TRAINING_PARAMS_PRI_DATA 123 +#define TUNE_TRAINING_PARAMS_NRI_DATA 123 +#define TUNE_TRAINING_PARAMS_PRI_CTRL 74 +#define TUNE_TRAINING_PARAMS_NRI_CTRL 74 +#define TUNE_TRAINING_PARAMS_P_ODT_DATA 45 +#define TUNE_TRAINING_PARAMS_N_ODT_DATA 45 +#define TUNE_TRAINING_PARAMS_P_ODT_CTRL 45 +#define TUNE_TRAINING_PARAMS_N_ODT_CTRL 45 +#define TUNE_TRAINING_PARAMS_DIC 0x2 +#define TUNE_TRAINING_PARAMS_ODT_CONFIG_2CS 0x120012 +#define TUNE_TRAINING_PARAMS_ODT_CONFIG_1CS 0x10000 +#define TUNE_TRAINING_PARAMS_RTT_NOM 0x44 + +#define TUNE_TRAINING_PARAMS_RTT_WR_1CS 0x0 /*off*/ +#define TUNE_TRAINING_PARAMS_RTT_WR_2CS 0x0 /*off*/ + +#define MARVELL_BOARD MARVELL_BOARD_ID_BASE + + +#define REG_DEVICE_SAR1_ADDR 0xe4204 +#define RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET 17 +#define RST2_CPU_DDR_CLOCK_SELECT_IN_MASK 0x1f +#define DEVICE_SAMPLE_AT_RESET2_REG 0x18604 + +#define DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_OFFSET 0 +#define DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_25MHZ 0 +#define DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_40MHZ 1 + +/* DRAM Windows */ +#define REG_XBAR_WIN_5_CTRL_ADDR 0x20050 +#define REG_XBAR_WIN_5_BASE_ADDR 0x20054 + +/* DRAM Windows */ +#define REG_XBAR_WIN_4_CTRL_ADDR 0x20040 +#define REG_XBAR_WIN_4_BASE_ADDR 0x20044 +#define REG_XBAR_WIN_4_REMAP_ADDR 0x20048 +#define REG_XBAR_WIN_7_REMAP_ADDR 0x20078 +#define REG_XBAR_WIN_16_CTRL_ADDR 0x200d0 +#define REG_XBAR_WIN_16_BASE_ADDR 0x200d4 +#define REG_XBAR_WIN_16_REMAP_ADDR 0x200dc +#define REG_XBAR_WIN_19_CTRL_ADDR 0x200e8 + +#define REG_FASTPATH_WIN_BASE_ADDR(win) (0x20180 + (0x8 * win)) +#define REG_FASTPATH_WIN_CTRL_ADDR(win) (0x20184 + (0x8 * win)) + +#define CPU_CONFIGURATION_REG(id) (0x21800 + (id * 0x100)) +#define CPU_MRVL_ID_OFFSET 0x10 +#define SAR1_CPU_CORE_MASK 0x00000018 +#define SAR1_CPU_CORE_OFFSET 3 + +/* SatR defined too change topology busWidth and ECC configuration */ +#define DDR_SATR_CONFIG_MASK_WIDTH 0x8 +#define DDR_SATR_CONFIG_MASK_ECC 0x10 +#define DDR_SATR_CONFIG_MASK_ECC_PUP 0x20 + +#define REG_SAMPLE_RESET_HIGH_ADDR 0x18600 + +#define MV_BOARD_REFCLK_25MHZ 25000000 +#define MV_BOARD_REFCLK MV_BOARD_REFCLK_25MHZ + +#define MAX_DQ_NUM 40 + +/* dram line buffer registers */ +#define DLB_CTRL_REG 0x1700 +#define DLB_EN_OFFS 0 +#define DLB_EN_MASK 0x1 +#define DLB_EN_ENA 1 +#define DLB_EN_DIS 0 +#define WR_COALESCE_EN_OFFS 2 +#define WR_COALESCE_EN_MASK 0x1 +#define WR_COALESCE_EN_ENA 1 +#define WR_COALESCE_EN_DIS 0 +#define AXI_PREFETCH_EN_OFFS 3 +#define AXI_PREFETCH_EN_MASK 0x1 +#define AXI_PREFETCH_EN_ENA 1 +#define AXI_PREFETCH_EN_DIS 0 +#define MBUS_PREFETCH_EN_OFFS 4 +#define MBUS_PREFETCH_EN_MASK 0x1 +#define MBUS_PREFETCH_EN_ENA 1 +#define MBUS_PREFETCH_EN_DIS 0 +#define PREFETCH_NXT_LN_SZ_TRIG_OFFS 6 +#define PREFETCH_NXT_LN_SZ_TRIG_MASK 0x1 +#define PREFETCH_NXT_LN_SZ_TRIG_ENA 1 +#define PREFETCH_NXT_LN_SZ_TRIG_DIS 0 + +#define DLB_BUS_OPT_WT_REG 0x1704 +#define DLB_AGING_REG 0x1708 +#define DLB_EVICTION_CTRL_REG 0x170c +#define DLB_EVICTION_TIMERS_REG 0x1710 +#define DLB_USER_CMD_REG 0x1714 +#define DLB_WTS_DIFF_CS_REG 0x1770 +#define DLB_WTS_DIFF_BG_REG 0x1774 +#define DLB_WTS_SAME_BG_REG 0x1778 +#define DLB_WTS_CMDS_REG 0x177c +#define DLB_WTS_ATTR_PRIO_REG 0x1780 +#define DLB_QUEUE_MAP_REG 0x1784 +#define DLB_SPLIT_REG 0x1788 + +/* Subphy result control per byte registers */ +#define RESULT_CONTROL_BYTE_PUP_0_REG 0x1830 +#define RESULT_CONTROL_BYTE_PUP_1_REG 0x1834 +#define RESULT_CONTROL_BYTE_PUP_2_REG 0x1838 +#define RESULT_CONTROL_BYTE_PUP_3_REG 0x183c +#define RESULT_CONTROL_BYTE_PUP_4_REG 0x18b0 + +/* Subphy result control per bit registers */ +#define RESULT_CONTROL_PUP_0_BIT_0_REG 0x18b4 +#define RESULT_CONTROL_PUP_0_BIT_1_REG 0x18b8 +#define RESULT_CONTROL_PUP_0_BIT_2_REG 0x18bc +#define RESULT_CONTROL_PUP_0_BIT_3_REG 0x18c0 +#define RESULT_CONTROL_PUP_0_BIT_4_REG 0x18c4 +#define RESULT_CONTROL_PUP_0_BIT_5_REG 0x18c8 +#define RESULT_CONTROL_PUP_0_BIT_6_REG 0x18cc +#define RESULT_CONTROL_PUP_0_BIT_7_REG 0x18f0 + +#define RESULT_CONTROL_PUP_1_BIT_0_REG 0x18f4 +#define RESULT_CONTROL_PUP_1_BIT_1_REG 0x18f8 +#define RESULT_CONTROL_PUP_1_BIT_2_REG 0x18fc +#define RESULT_CONTROL_PUP_1_BIT_3_REG 0x1930 +#define RESULT_CONTROL_PUP_1_BIT_4_REG 0x1934 +#define RESULT_CONTROL_PUP_1_BIT_5_REG 0x1938 +#define RESULT_CONTROL_PUP_1_BIT_6_REG 0x193c +#define RESULT_CONTROL_PUP_1_BIT_7_REG 0x19b0 + +#define RESULT_CONTROL_PUP_2_BIT_0_REG 0x19b4 +#define RESULT_CONTROL_PUP_2_BIT_1_REG 0x19b8 +#define RESULT_CONTROL_PUP_2_BIT_2_REG 0x19bc +#define RESULT_CONTROL_PUP_2_BIT_3_REG 0x19c0 +#define RESULT_CONTROL_PUP_2_BIT_4_REG 0x19c4 +#define RESULT_CONTROL_PUP_2_BIT_5_REG 0x19c8 +#define RESULT_CONTROL_PUP_2_BIT_6_REG 0x19cc +#define RESULT_CONTROL_PUP_2_BIT_7_REG 0x19f0 + +#define RESULT_CONTROL_PUP_3_BIT_0_REG 0x19f4 +#define RESULT_CONTROL_PUP_3_BIT_1_REG 0x19f8 +#define RESULT_CONTROL_PUP_3_BIT_2_REG 0x19fc +#define RESULT_CONTROL_PUP_3_BIT_3_REG 0x1a30 +#define RESULT_CONTROL_PUP_3_BIT_4_REG 0x1a34 +#define RESULT_CONTROL_PUP_3_BIT_5_REG 0x1a38 +#define RESULT_CONTROL_PUP_3_BIT_6_REG 0x1a3c +#define RESULT_CONTROL_PUP_3_BIT_7_REG 0x1ab0 + +#define RESULT_CONTROL_PUP_4_BIT_0_REG 0x1ab4 +#define RESULT_CONTROL_PUP_4_BIT_1_REG 0x1ab8 +#define RESULT_CONTROL_PUP_4_BIT_2_REG 0x1abc +#define RESULT_CONTROL_PUP_4_BIT_3_REG 0x1ac0 +#define RESULT_CONTROL_PUP_4_BIT_4_REG 0x1ac4 +#define RESULT_CONTROL_PUP_4_BIT_5_REG 0x1ac8 +#define RESULT_CONTROL_PUP_4_BIT_6_REG 0x1acc +#define RESULT_CONTROL_PUP_4_BIT_7_REG 0x1af0 + +/* CPU */ +#define REG_BOOTROM_ROUTINE_ADDR 0x182d0 +#define REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS 12 + +/* Matrix enables DRAM modes (bus width/ECC) per boardId */ +#define TOPOLOGY_UPDATE_32BIT 0 +#define TOPOLOGY_UPDATE_32BIT_ECC 1 +#define TOPOLOGY_UPDATE_16BIT 2 +#define TOPOLOGY_UPDATE_16BIT_ECC 3 +#define TOPOLOGY_UPDATE_16BIT_ECC_PUP3 4 +#define TOPOLOGY_UPDATE { \ + /* 32Bit, 32bit ECC, 16bit, 16bit ECC PUP4, 16bit ECC PUP3 */ \ + {1, 1, 1, 1, 1}, /* RD_NAS_68XX_ID */ \ + {1, 1, 1, 1, 1}, /* DB_68XX_ID */ \ + {1, 0, 1, 0, 1}, /* RD_AP_68XX_ID */ \ + {1, 0, 1, 0, 1}, /* DB_AP_68XX_ID */ \ + {1, 0, 1, 0, 1}, /* DB_GP_68XX_ID */ \ + {0, 0, 1, 1, 0}, /* DB_BP_6821_ID */ \ + {1, 1, 1, 1, 1} /* DB_AMC_6820_ID */ \ + }; + +enum { + CPU_1066MHZ_DDR_400MHZ, + CPU_RESERVED_DDR_RESERVED0, + CPU_667MHZ_DDR_667MHZ, + CPU_800MHZ_DDR_800MHZ, + CPU_RESERVED_DDR_RESERVED1, + CPU_RESERVED_DDR_RESERVED2, + CPU_RESERVED_DDR_RESERVED3, + LAST_FREQ +}; + +/* struct used for DLB configuration array */ +struct dlb_config { + u32 reg_addr; + u32 reg_data; +}; + +#define ACTIVE_INTERFACE_MASK 0x1 + +extern u32 dmin_phy_reg_table[][2]; +extern u16 odt_slope[]; +extern u16 odt_intercept[]; + +int mv_ddr_pre_training_soc_config(const char *ddr_type); +int mv_ddr_post_training_soc_config(const char *ddr_type); +void mv_ddr_mem_scrubbing(void); + +void mv_ddr_odpg_enable(void); +void mv_ddr_odpg_disable(void); +void mv_ddr_odpg_done_clr(void); +int mv_ddr_is_odpg_done(u32 count); +void mv_ddr_training_enable(void); +int mv_ddr_is_training_done(u32 count, u32 *result); +u32 mv_ddr_dm_pad_get(void); +int mv_ddr_pre_training_fixup(void); +int mv_ddr_post_training_fixup(void); +int mv_ddr_manual_cal_do(void); +#endif /* _MV_DDR_PLAT_H */ diff --git a/drivers/ddr/marvell/a38x/mv_ddr_regs.h b/drivers/ddr/marvell/a38x/mv_ddr_regs.h new file mode 100644 index 000000000000..0fc5541e801c --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_regs.h @@ -0,0 +1,447 @@ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _MV_DDR_REGS_H +#define _MV_DDR_REGS_H + +#define GLOB_CTRL_STATUS_REG 0x1030 +#define TRAINING_TRIGGER_OFFS 0 +#define TRAINING_TRIGGER_MASK 0x1 +#define TRAINING_TRIGGER_ENA 1 +#define TRAINING_DONE_OFFS 1 +#define TRAINING_DONE_MASK 0x1 +#define TRAINING_DONE_DONE 1 +#define TRAINING_DONE_NOT_DONE 0 +#define TRAINING_RESULT_OFFS 2 +#define TRAINING_RESULT_MASK 0x1 +#define TRAINING_RESULT_PASS 0 +#define TRAINING_RESULT_FAIL 1 + +#define GENERAL_TRAINING_OPCODE_REG 0x1034 + +#define OPCODE_REG0_BASE 0x1038 +#define OPCODE_REG0_REG(obj) (OPCODE_REG0_BASE + (obj) * 0x4) + +#define OPCODE_REG1_BASE 0x10b0 +#define OPCODE_REG1_REG(obj) (OPCODE_REG1_BASE + (obj) * 0x4) + +#define CAL_PHY_BASE 0x10c0 +#define CAL_PHY_REG(obj) (CAL_PHY_BASE + (obj) * 0x4) + +#define WL_DONE_CNTR_REF_REG 0x10f8 +#define ODPG_WR_RD_MODE_ENA_REG 0x10fc + +#define SDRAM_CFG_REG 0x1400 +#define REFRESH_OFFS 0 +#define REFRESH_MASK 0x3fff +#define DRAM_TYPE_OFFS 14 +#define DRAM_TYPE_MASK 0x1 +#define BUS_IN_USE_OFFS 15 +#define BUS_IN_USE_MASK 0x1 +#define CPU_2DRAM_WR_BUFF_CUT_TH_OFFS 16 +#define CPU_2DRAM_WR_BUFF_CUT_TH_MASK 0x1 +#define REG_DIMM_OFFS 17 +#define REG_DIMM_MASK 0x1 +#define ECC_OFFS 18 +#define ECC_MASK 0x1 +#define IGNORE_ERRORS_OFFS 19 +#define IGNORE_ERRORS_MASK 0x1 +#define DRAM_TYPE_HIGH_OFFS 20 +#define DRAM_TYPE_HIGH_MASK 0x1 +#define SELF_REFRESH_MODE_OFFS 24 +#define SELF_REFRESH_MODE_MASK 0x1 +#define CPU_RD_PER_PROP_OFFS 25 +#define CPU_RD_PER_PROP_MASK 0x1 +#define DDR4_EMULATION_OFFS 26 +#define DDR4_EMULATION_MASK 0x1 +#define PHY_RF_RST_OFFS 27 +#define PHY_RF_RST_MASK 0x1 +#define PUP_RST_DIVIDER_OFFS 28 +#define PUP_RST_DIVIDER_MASK 0x1 +#define DATA_PUP_WR_RESET_OFFS 29 +#define DATA_PUP_WR_RESET_MASK 0x1 +#define DATA_PUP_RD_RESET_OFFS 30 +#define DATA_PUP_RD_RESET_MASK 0x1 +#define DATA_PUP_RD_RESET_ENA 0x0 +#define DATA_PUP_RD_RESET_DIS 0x1 +#define IO_BIST_OFFS 31 +#define DATA_PUP_RD_RESET_MASK 0x1 + +#define DUNIT_CTRL_LOW_REG 0x1404 + +#define SDRAM_TIMING_LOW_REG 0x1408 +#define SDRAM_TIMING_LOW_TRAS_OFFS 0 +#define SDRAM_TIMING_LOW_TRAS_MASK 0xf +#define SDRAM_TIMING_LOW_TRCD_OFFS 4 +#define SDRAM_TIMING_LOW_TRCD_MASK 0xf +#define SDRAM_TIMING_HIGH_TRCD_OFFS 22 +#define SDRAM_TIMING_HIGH_TRCD_MASK 0x1 +#define SDRAM_TIMING_LOW_TRP_OFFS 8 +#define SDRAM_TIMING_LOW_TRP_MASK 0xf +#define SDRAM_TIMING_HIGH_TRP_OFFS 23 +#define SDRAM_TIMING_HIGH_TRP_MASK 0x1 +#define SDRAM_TIMING_LOW_TWR_OFFS 12 +#define SDRAM_TIMING_LOW_TWR_MASK 0xf +#define SDRAM_TIMING_LOW_TWTR_OFFS 16 +#define SDRAM_TIMING_LOW_TWTR_MASK 0xf +#define SDRAM_TIMING_LOW_TRAS_HIGH_OFFS 20 +#define SDRAM_TIMING_LOW_TRAS_HIGH_MASK 0x3 +#define SDRAM_TIMING_LOW_TRRD_OFFS 24 +#define SDRAM_TIMING_LOW_TRRD_MASK 0xf +#define SDRAM_TIMING_LOW_TRTP_OFFS 28 +#define SDRAM_TIMING_LOW_TRTP_MASK 0xf + +#define SDRAM_TIMING_HIGH_REG 0x140c +#define SDRAM_TIMING_HIGH_TRFC_OFFS 0 +#define SDRAM_TIMING_HIGH_TRFC_MASK 0x7f +#define SDRAM_TIMING_HIGH_TR2R_OFFS 7 +#define SDRAM_TIMING_HIGH_TR2R_MASK 0x3 +#define SDRAM_TIMING_HIGH_TR2W_W2R_OFFS 9 +#define SDRAM_TIMING_HIGH_TR2W_W2R_MASK 0x3 +#define SDRAM_TIMING_HIGH_TW2W_OFFS 11 +#define SDRAM_TIMING_HIGH_TW2W_MASK 0x1f +#define SDRAM_TIMING_HIGH_TRFC_HIGH_OFFS 16 +#define SDRAM_TIMING_HIGH_TRFC_HIGH_MASK 0x7 +#define SDRAM_TIMING_HIGH_TR2R_HIGH_OFFS 19 +#define SDRAM_TIMING_HIGH_TR2R_HIGH_MASK 0x7 +#define SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_OFFS 22 +#define SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_MASK 0x7 +#define SDRAM_TIMING_HIGH_TMOD_OFFS 25 +#define SDRAM_TIMING_HIGH_TMOD_MASK 0xf +#define SDRAM_TIMING_HIGH_TMOD_HIGH_OFFS 30 +#define SDRAM_TIMING_HIGH_TMOD_HIGH_MASK 0x3 + +#define SDRAM_ADDR_CTRL_REG 0x1410 +#define CS_STRUCT_BASE 0 +#define CS_STRUCT_OFFS(cs) (CS_STRUCT_BASE + (cs) * 4) +#define CS_STRUCT_MASK 0x3 +#define CS_SIZE_BASE 2 +#define CS_SIZE_OFFS(cs) (CS_SIZE_BASE + (cs) * 4) +#define CS_SIZE_MASK 0x3 +#define CS_SIZE_HIGH_BASE 20 +#define CS_SIZE_HIGH_OFFS(cs) (CS_SIZE_HIGH_BASE + (cs)) +#define CS_SIZE_HIGH_MASK 0x1 +#define T_FAW_OFFS 24 +#define T_FAW_MASK 0x7f + +#define SDRAM_OPEN_PAGES_CTRL_REG 0x1414 + +#define SDRAM_OP_REG 0x1418 +#define SDRAM_OP_CMD_OFFS 0 +#define SDRAM_OP_CMD_MASK 0x1f +#define SDRAM_OP_CMD_CS_BASE 8 +#define SDRAM_OP_CMD_CS_OFFS(cs) (SDRAM_OP_CMD_CS_BASE + (cs)) +#define SDRAM_OP_CMD_CS_MASK 0x1 +enum { + CMD_NORMAL, + CMD_PRECHARGE, + CMD_REFRESH, + CMD_DDR3_DDR4_MR0, + CMD_DDR3_DDR4_MR1, + CMD_NOP, + CMD_RES_0X6, + CMD_SELFREFRESH, + CMD_DDR3_DDR4_MR2, + CMD_DDR3_DDR4_MR3, + CMD_ACT_PDE, + CMD_PRE_PDE, + CMD_ZQCL, + CMD_ZQCS, + CMD_CWA, + CMD_RES_0XF, + CMD_DDR4_MR4, + CMD_DDR4_MR5, + CMD_DDR4_MR6, + DDR4_MPR_WR +}; + +#define DUNIT_CTRL_HIGH_REG 0x1424 +#define CPU_INTERJECTION_ENA_OFFS 3 +#define CPU_INTERJECTION_ENA_MASK 0x1 +#define CPU_INTERJECTION_ENA_SPLIT_ENA 0 +#define CPU_INTERJECTION_ENA_SPLIT_DIS 1 + +#define DDR_ODT_TIMING_LOW_REG 0x1428 + +#define DDR_TIMING_REG 0x142c +#define DDR_TIMING_TCCD_OFFS 18 +#define DDR_TIMING_TCCD_MASK 0x7 +#define DDR_TIMING_TPD_OFFS 0 +#define DDR_TIMING_TPD_MASK 0xf +#define DDR_TIMING_TXPDLL_OFFS 4 +#define DDR_TIMING_TXPDLL_MASK 0x1f + +#define DDR_ODT_TIMING_HIGH_REG 0x147c + +#define SDRAM_INIT_CTRL_REG 0x1480 +#define DRAM_RESET_MASK_OFFS 1 +#define DRAM_RESET_MASK_MASK 0x1 +#define DRAM_RESET_MASK_NORMAL 0 +#define DRAM_RESET_MASK_MASKED 1 + +#define SDRAM_ODT_CTRL_HIGH_REG 0x1498 +#define DUNIT_ODT_CTRL_REG 0x149c +#define RD_BUFFER_SEL_REG 0x14a4 +#define AXI_CTRL_REG 0x14a8 +#define DUNIT_MMASK_REG 0x14b0 + +#define HORZ_SSTL_CAL_MACH_CTRL_REG 0x14c8 +#define HORZ_POD_CAL_MACH_CTRL_REG 0x17c8 +#define VERT_SSTL_CAL_MACH_CTRL_REG 0x1dc8 +#define VERT_POD_CAL_MACH_CTRL_REG 0x1ec8 + +#define MAIN_PADS_CAL_MACH_CTRL_REG 0x14cc +#define DYN_PADS_CAL_ENABLE_OFFS 0 +#define DYN_PADS_CAL_ENABLE_MASK 0x1 +#define DYN_PADS_CAL_ENABLE_DIS 0 +#define DYN_PADS_CAL_ENABLE_ENA 1 +#define PADS_RECAL_OFFS 1 +#define PADS_RECAL_MASK 0x1 +#define DYN_PADS_CAL_BLOCK_OFFS 2 +#define DYN_PADS_CAL_BLOCK_MASK 0x1 +#define CAL_UPDATE_CTRL_OFFS 3 +#define CAL_UPDATE_CTRL_MASK 0x3 +#define CAL_UPDATE_CTRL_INT 1 +#define CAL_UPDATE_CTRL_EXT 2 +#define DYN_PADS_CAL_CNTR_OFFS 13 +#define DYN_PADS_CAL_CNTR_MASK 0x3ffff +#define CAL_MACH_STATUS_OFFS 31 +#define CAL_MACH_STATUS_MASK 0x1 +#define CAL_MACH_BUSY 0 +#define CAL_MACH_RDY 1 + +#define DRAM_DLL_TIMING_REG 0x14e0 +#define DRAM_ZQ_INIT_TIMIMG_REG 0x14e4 +#define DRAM_ZQ_TIMING_REG 0x14e8 + +#define DRAM_LONG_TIMING_REG 0x14ec +#define DDR4_TRRD_L_OFFS 0 +#define DDR4_TRRD_L_MASK 0xf +#define DDR4_TWTR_L_OFFS 4 +#define DDR4_TWTR_L_MASK 0xf + +#define DDR_IO_REG 0x1524 +#define DFS_REG 0x1528 + +#define RD_DATA_SMPL_DLYS_REG 0x1538 +#define RD_SMPL_DLY_CS_BASE 0 +#define RD_SMPL_DLY_CS_OFFS(cs) (RD_SMPL_DLY_CS_BASE + (cs) * 8) +#define RD_SMPL_DLY_CS_MASK 0x1f + +#define RD_DATA_RDY_DLYS_REG 0x153c +#define RD_RDY_DLY_CS_BASE 0 +#define RD_RDY_DLY_CS_OFFS(cs) (RD_RDY_DLY_CS_BASE + (cs) * 8) +#define RD_RDY_DLY_CS_MASK 0x1f + +#define TRAINING_REG 0x15b0 +#define TRN_START_OFFS 31 +#define TRN_START_MASK 0x1 +#define TRN_START_ENA 1 +#define TRN_START_DIS 0 + +#define TRAINING_SW_1_REG 0x15b4 + +#define TRAINING_SW_2_REG 0x15b8 +#define TRAINING_ECC_MUX_OFFS 1 +#define TRAINING_ECC_MUX_MASK 0x1 +#define TRAINING_ECC_MUX_DIS 0 +#define TRAINING_ECC_MUX_ENA 1 +#define TRAINING_SW_OVRD_OFFS 0 +#define TRAINING_SW_OVRD_MASK 0x1 +#define TRAINING_SW_OVRD_DIS 0 +#define TRAINING_SW_OVRD_ENA 1 + +#define TRAINING_PATTERN_BASE_ADDR_REG 0x15bc +#define TRAINING_DBG_1_REG 0x15c0 +#define TRAINING_DBG_2_REG 0x15c4 + +#define TRAINING_DBG_3_REG 0x15c8 +#define TRN_DBG_RDY_INC_PH_2TO1_BASE 0 +#define TRN_DBG_RDY_INC_PH_2TO1_OFFS(phase) (TRN_DBG_RDY_INC_PH_2TO1_BASE + (phase) * 3) +#define TRN_DBG_RDY_INC_PH_2TO1_MASK 0x7 + +#define DDR3_RANK_CTRL_REG 0x15e0 +#define CS_EXIST_BASE 0 +#define CS_EXIST_OFFS(cs) (CS_EXIST_BASE + (cs)) +#define CS_EXIST_MASK 0x1 + +#define ZQC_CFG_REG 0x15e4 +#define DRAM_PHY_CFG_REG 0x15ec +#define ODPG_CTRL_CTRL_REG 0x1600 + +#define ODPG_DATA_CTRL_REG 0x1630 +#define ODPG_WRBUF_WR_CTRL_OFFS 0 +#define ODPG_WRBUF_WR_CTRL_MASK 0x1 +#define ODPG_WRBUF_WR_CTRL_DIS 0 +#define ODPG_WRBUF_WR_CTRL_ENA 1 +#define ODPG_WRBUF_RD_CTRL_OFFS 1 +#define ODPG_WRBUF_RD_CTRL_MASK 0x1 +#define ODPG_WRBUF_RD_CTRL_DIS 0 +#define ODPG_WRBUF_RD_CTRL_ENA 1 +#define ODPG_DATA_CBDEL_OFFS 15 +#define ODPG_DATA_CBDEL_MASK 0x3f +#define ODPG_MODE_OFFS 25 +#define ODPG_MODE_MASK 0x1 +#define ODPG_MODE_RX 0 +#define ODPG_MODE_TX 1 +#define ODPG_DATA_CS_OFFS 26 +#define ODPG_DATA_CS_MASK 0x3 +#define ODPG_DISABLE_OFFS 30 +#define ODPG_DISABLE_MASK 0x1 +#define ODPG_DISABLE_DIS 1 +#define ODPG_ENABLE_OFFS 31 +#define ODPG_ENABLE_MASK 0x1 +#define ODPG_ENABLE_ENA 1 + +#define ODPG_DATA_BUFFER_OFFS_REG 0x1638 +#define ODPG_DATA_BUFFER_SIZE_REG 0x163c +#define PHY_LOCK_STATUS_REG 0x1674 + +#define PHY_REG_FILE_ACCESS_REG 0x16a0 +#define PRFA_DATA_OFFS 0 +#define PRFA_DATA_MASK 0xffff +#define PRFA_REG_NUM_OFFS 16 +#define PRFA_REG_NUM_MASK 0x3f +#define PRFA_PUP_NUM_OFFS 22 +#define PRFA_PUP_NUM_MASK 0xf +#define PRFA_PUP_CTRL_DATA_OFFS 26 +#define PRFA_PUP_CTRL_DATA_MASK 0x1 +#define PRFA_PUP_BCAST_WR_ENA_OFFS 27 +#define PRFA_PUP_BCAST_WR_ENA_MASK 0x1 +#define PRFA_REG_NUM_HI_OFFS 28 +#define PRFA_REG_NUM_HI_MASK 0x3 +#define PRFA_TYPE_OFFS 30 +#define PRFA_TYPE_MASK 0x1 +#define PRFA_REQ_OFFS 31 +#define PRFA_REQ_MASK 0x1 +#define PRFA_REQ_DIS 0x0 +#define PRFA_REQ_ENA 0x1 + +#define TRAINING_WL_REG 0x16ac + +#define ODPG_DATA_WR_ADDR_REG 0x16b0 +#define ODPG_DATA_WR_ACK_OFFS 0 +#define ODPG_DATA_WR_ACK_MASK 0x7f +#define ODPG_DATA_WR_DATA_OFFS 8 +#define ODPG_DATA_WR_DATA_MASK 0xff + +#define ODPG_DATA_WR_DATA_HIGH_REG 0x16b4 +#define ODPG_DATA_WR_DATA_LOW_REG 0x16b8 +#define ODPG_DATA_RX_WORD_ERR_ADDR_REG 0x16bc +#define ODPG_DATA_RX_WORD_ERR_CNTR_REG 0x16c0 +#define ODPG_DATA_RX_WORD_ERR_DATA_HIGH_REG 0x16c4 +#define ODPG_DATA_RX_WORD_ERR_DATA_LOW_REG 0x16c8 +#define ODPG_DATA_WR_DATA_ERR_REG 0x16cc + +#define DUAL_DUNIT_CFG_REG 0x16d8 +#define FC_SAMPLE_STAGES_OFFS 0 +#define FC_SAMPLE_STAGES_MASK 0x7 +#define SINGLE_CS_PIN_OFFS 3 +#define SINGLE_CS_PIN_MASK 0x1 +#define SINGLE_CS_ENA 1 +#define TUNING_ACTIVE_SEL_OFFS 6 +#define TUNING_ACTIVE_SEL_MASK 0x1 +#define TUNING_ACTIVE_SEL_MC 0 +#define TUNING_ACTIVE_SEL_TIP 1 + +#define WL_DQS_PATTERN_REG 0x16dc +#define ODPG_DONE_STATUS_REG 0x16fc +#define ODPG_DONE_STATUS_BIT_OFFS 0 +#define ODPG_DONE_STATUS_BIT_MASK 0x1 +#define ODPG_DONE_STATUS_BIT_CLR 0 +#define ODPG_DONE_STATUS_BIT_SET 1 + +#define RESULT_CTRL_BASE 0x1830 +#define BLOCK_STATUS_OFFS 25 +#define BLOCK_STATUS_MASK 0x1 +#define BLOCK_STATUS_LOCK 1 +#define BLOCK_STATUS_NOT_LOCKED 0 + +#define MR0_REG 0x15d0 +#define MR1_REG 0x15d4 +#define MR2_REG 0x15d8 +#define MR3_REG 0x15dc +#define MRS0_CMD 0x3 +#define MRS1_CMD 0x4 +#define MRS2_CMD 0x8 +#define MRS3_CMD 0x9 + + +#define DRAM_PINS_MUX_REG 0x19d4 +#define CTRL_PINS_MUX_OFFS 0 +#define CTRL_PINS_MUX_MASK 0x3 +enum { + DUNIT_DDR3_ON_BOARD, + DUNIT_DDR3_DIMM, + DUNIT_DDR4_ON_BOARD, + DUNIT_DDR4_DIMM +}; + +/* ddr phy registers */ +#define WL_PHY_BASE 0x0 +#define WL_PHY_REG(cs) (WL_PHY_BASE + (cs) * 0x4) +#define WR_LVL_PH_SEL_OFFS 6 +#define WR_LVL_PH_SEL_MASK 0x7 +#define WR_LVL_PH_SEL_PHASE1 1 +#define WR_LVL_REF_DLY_OFFS 0 +#define WR_LVL_REF_DLY_MASK 0x1f +#define CTRL_CENTER_DLY_OFFS 10 +#define CTRL_CENTER_DLY_MASK 0x1f +#define CTRL_CENTER_DLY_INV_OFFS 15 +#define CTRL_CENTER_DLY_INV_MASK 0x1 + +#define CTX_PHY_BASE 0x1 +#define CTX_PHY_REG(cs) (CTX_PHY_BASE + (cs) * 0x4) + +#define RL_PHY_BASE 0x2 +#define RL_PHY_REG(cs) (RL_PHY_BASE + (cs) * 0x4) +#define RL_REF_DLY_OFFS 0 +#define RL_REF_DLY_MASK 0x1f +#define RL_PH_SEL_OFFS 6 +#define RL_PH_SEL_MASK 0x7 + +#define CRX_PHY_BASE 0x3 +#define CRX_PHY_REG(cs) (CRX_PHY_BASE + (cs) * 0x4) + +#define PHY_CTRL_PHY_REG 0x90 +#define ADLL_CFG0_PHY_REG 0x92 +#define ADLL_CFG1_PHY_REG 0x93 +#define ADLL_CFG2_PHY_REG 0x94 +#define CMOS_CONFIG_PHY_REG 0xa2 +#define PAD_ZRI_CAL_PHY_REG 0xa4 +#define PAD_ODT_CAL_PHY_REG 0xa6 +#define PAD_CFG_PHY_REG 0xa8 +#define PAD_PRE_DISABLE_PHY_REG 0xa9 +#define TEST_ADLL_PHY_REG 0xbf + +#define VREF_PHY_BASE 0xd0 +#define VREF_PHY_REG(cs, bit) (VREF_PHY_BASE + (cs) * 12 + bit) +enum { + DQSP_PAD = 4, + DQSN_PAD +}; + +#define VREF_BCAST_PHY_BASE 0xdb +#define VREF_BCAST_PHY_REG(cs) (VREF_BCAST_PHY_BASE + (cs) * 12) + +#define PBS_TX_PHY_BASE 0x10 +#define PBS_TX_PHY_REG(cs, bit) (PBS_TX_PHY_BASE + (cs) * 0x10 + (bit)) + +#define PBS_TX_BCAST_PHY_BASE 0x1f +#define PBS_TX_BCAST_PHY_REG(cs) (PBS_TX_BCAST_PHY_BASE + (cs) * 0x10) + +#define PBS_RX_PHY_BASE 0x50 +#define PBS_RX_PHY_REG(cs, bit) (PBS_RX_PHY_BASE + (cs) * 0x10 + (bit)) + +#define PBS_RX_BCAST_PHY_BASE 0x5f +#define PBS_RX_BCAST_PHY_REG(cs) (PBS_RX_BCAST_PHY_BASE + (cs) * 0x10) + +#define RESULT_PHY_REG 0xc0 +#define RESULT_PHY_RX_OFFS 5 +#define RESULT_PHY_TX_OFFS 0 + + +#endif /* _MV_DDR_REGS_H */ diff --git a/drivers/ddr/marvell/a38x/mv_ddr_spd.c b/drivers/ddr/marvell/a38x/mv_ddr_spd.c new file mode 100644 index 000000000000..eaf6597e43ce --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_spd.c @@ -0,0 +1,378 @@ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include "mv_ddr_spd.h" + +#define MV_DDR_SPD_DATA_MTB 125 /* medium timebase, ps */ +#define MV_DDR_SPD_DATA_FTB 1 /* fine timebase, ps */ +#define MV_DDR_SPD_MSB_OFFS 8 /* most significant byte offset, bits */ + +#define MV_DDR_SPD_SUPPORTED_CLS_NUM 30 + +static unsigned int mv_ddr_spd_supported_cls[MV_DDR_SPD_SUPPORTED_CLS_NUM]; + +int mv_ddr_spd_supported_cls_calc(union mv_ddr_spd_data *spd_data) +{ + unsigned int byte, bit, start_cl; + + start_cl = (spd_data->all_bytes[23] & 0x8) ? 23 : 7; + + for (byte = 20; byte < 23; byte++) { + for (bit = 0; bit < 8; bit++) { + if (spd_data->all_bytes[byte] & (1 << bit)) + mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = start_cl + (byte - 20) * 8 + bit; + else + mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = 0; + } + } + + for (byte = 23, bit = 0; bit < 6; bit++) { + if (spd_data->all_bytes[byte] & (1 << bit)) + mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = start_cl + (byte - 20) * 8 + bit; + else + mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = 0; + } + + return 0; +} + +unsigned int mv_ddr_spd_supported_cl_get(unsigned int cl) +{ + unsigned int supported_cl; + int i = 0; + + while (i < MV_DDR_SPD_SUPPORTED_CLS_NUM && + mv_ddr_spd_supported_cls[i] < cl) + i++; + + if (i < MV_DDR_SPD_SUPPORTED_CLS_NUM) + supported_cl = mv_ddr_spd_supported_cls[i]; + else + supported_cl = 0; + + return supported_cl; +} + +int mv_ddr_spd_timing_calc(union mv_ddr_spd_data *spd_data, unsigned int timing_data[]) +{ + int calc_val; + + /* t ck avg min, ps */ + calc_val = spd_data->byte_fields.byte_18 * MV_DDR_SPD_DATA_MTB + + (signed char)spd_data->byte_fields.byte_125 * MV_DDR_SPD_DATA_FTB; + if (calc_val < 0) + return 1; + timing_data[MV_DDR_TCK_AVG_MIN] = calc_val; + + /* t aa min, ps */ + calc_val = spd_data->byte_fields.byte_24 * MV_DDR_SPD_DATA_MTB + + (signed char)spd_data->byte_fields.byte_123 * MV_DDR_SPD_DATA_FTB; + if (calc_val < 0) + return 1; + timing_data[MV_DDR_TAA_MIN] = calc_val; + + /* t rfc1 min, ps */ + timing_data[MV_DDR_TRFC1_MIN] = (spd_data->byte_fields.byte_30 + + (spd_data->byte_fields.byte_31 << MV_DDR_SPD_MSB_OFFS)) * MV_DDR_SPD_DATA_MTB; + + /* t wr min, ps */ + timing_data[MV_DDR_TWR_MIN] = (spd_data->byte_fields.byte_42 + + (spd_data->byte_fields.byte_41.bit_fields.t_wr_min_msn << MV_DDR_SPD_MSB_OFFS)) * + MV_DDR_SPD_DATA_MTB; + /* FIXME: wa: set twr to a default value, if it's unset on spd */ + if (timing_data[MV_DDR_TWR_MIN] == 0) + timing_data[MV_DDR_TWR_MIN] = 15000; + + /* t rcd min, ps */ + calc_val = spd_data->byte_fields.byte_25 * MV_DDR_SPD_DATA_MTB + + (signed char)spd_data->byte_fields.byte_122 * MV_DDR_SPD_DATA_FTB; + if (calc_val < 0) + return 1; + timing_data[MV_DDR_TRCD_MIN] = calc_val; + + /* t rp min, ps */ + calc_val = spd_data->byte_fields.byte_26 * MV_DDR_SPD_DATA_MTB + + (signed char)spd_data->byte_fields.byte_121 * MV_DDR_SPD_DATA_FTB; + if (calc_val < 0) + return 1; + timing_data[MV_DDR_TRP_MIN] = calc_val; + + /* t rc min, ps */ + calc_val = (spd_data->byte_fields.byte_29 + + (spd_data->byte_fields.byte_27.bit_fields.t_rc_min_msn << MV_DDR_SPD_MSB_OFFS)) * + MV_DDR_SPD_DATA_MTB + + (signed char)spd_data->byte_fields.byte_120 * MV_DDR_SPD_DATA_FTB; + if (calc_val < 0) + return 1; + timing_data[MV_DDR_TRC_MIN] = calc_val; + + /* t ras min, ps */ + timing_data[MV_DDR_TRAS_MIN] = (spd_data->byte_fields.byte_28 + + (spd_data->byte_fields.byte_27.bit_fields.t_ras_min_msn << MV_DDR_SPD_MSB_OFFS)) * + MV_DDR_SPD_DATA_MTB; + + /* t rrd s min, ps */ + calc_val = spd_data->byte_fields.byte_38 * MV_DDR_SPD_DATA_MTB + + (signed char)spd_data->byte_fields.byte_119 * MV_DDR_SPD_DATA_FTB; + if (calc_val < 0) + return 1; + timing_data[MV_DDR_TRRD_S_MIN] = calc_val; + + /* t rrd l min, ps */ + calc_val = spd_data->byte_fields.byte_39 * MV_DDR_SPD_DATA_MTB + + (signed char)spd_data->byte_fields.byte_118 * MV_DDR_SPD_DATA_FTB; + if (calc_val < 0) + return 1; + timing_data[MV_DDR_TRRD_L_MIN] = calc_val; + + /* t faw min, ps */ + timing_data[MV_DDR_TFAW_MIN] = (spd_data->byte_fields.byte_37 + + (spd_data->byte_fields.byte_36.bit_fields.t_faw_min_msn << MV_DDR_SPD_MSB_OFFS)) * + MV_DDR_SPD_DATA_MTB; + + /* t wtr s min, ps */ + timing_data[MV_DDR_TWTR_S_MIN] = (spd_data->byte_fields.byte_44 + + (spd_data->byte_fields.byte_43.bit_fields.t_wtr_s_min_msn << MV_DDR_SPD_MSB_OFFS)) * + MV_DDR_SPD_DATA_MTB; + /* FIXME: wa: set twtr_s to a default value, if it's unset on spd */ + if (timing_data[MV_DDR_TWTR_S_MIN] == 0) + timing_data[MV_DDR_TWTR_S_MIN] = 2500; + + /* t wtr l min, ps */ + timing_data[MV_DDR_TWTR_L_MIN] = (spd_data->byte_fields.byte_45 + + (spd_data->byte_fields.byte_43.bit_fields.t_wtr_l_min_msn << MV_DDR_SPD_MSB_OFFS)) * + MV_DDR_SPD_DATA_MTB; + /* FIXME: wa: set twtr_l to a default value, if it's unset on spd */ + if (timing_data[MV_DDR_TWTR_L_MIN] == 0) + timing_data[MV_DDR_TWTR_L_MIN] = 7500; + + return 0; +} + +enum mv_ddr_dev_width mv_ddr_spd_dev_width_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char dev_width = spd_data->byte_fields.byte_12.bit_fields.device_width; + enum mv_ddr_dev_width ret_val; + + switch (dev_width) { + case 0x00: + ret_val = MV_DDR_DEV_WIDTH_4BIT; + break; + case 0x01: + ret_val = MV_DDR_DEV_WIDTH_8BIT; + break; + case 0x02: + ret_val = MV_DDR_DEV_WIDTH_16BIT; + break; + case 0x03: + ret_val = MV_DDR_DEV_WIDTH_32BIT; + break; + default: + ret_val = MV_DDR_DEV_WIDTH_LAST; + } + + return ret_val; +} + +enum mv_ddr_die_capacity mv_ddr_spd_die_capacity_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char die_cap = spd_data->byte_fields.byte_4.bit_fields.die_capacity; + enum mv_ddr_die_capacity ret_val; + + switch (die_cap) { + case 0x00: + ret_val = MV_DDR_DIE_CAP_256MBIT; + break; + case 0x01: + ret_val = MV_DDR_DIE_CAP_512MBIT; + break; + case 0x02: + ret_val = MV_DDR_DIE_CAP_1GBIT; + break; + case 0x03: + ret_val = MV_DDR_DIE_CAP_2GBIT; + break; + case 0x04: + ret_val = MV_DDR_DIE_CAP_4GBIT; + break; + case 0x05: + ret_val = MV_DDR_DIE_CAP_8GBIT; + break; + case 0x06: + ret_val = MV_DDR_DIE_CAP_16GBIT; + break; + case 0x07: + ret_val = MV_DDR_DIE_CAP_32GBIT; + break; + case 0x08: + ret_val = MV_DDR_DIE_CAP_12GBIT; + break; + case 0x09: + ret_val = MV_DDR_DIE_CAP_24GBIT; + break; + default: + ret_val = MV_DDR_DIE_CAP_LAST; + } + + return ret_val; +} + +unsigned char mv_ddr_spd_mem_mirror_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char mem_mirror = spd_data->byte_fields.byte_131.bit_fields.rank_1_mapping; + + return mem_mirror; +} + +enum mv_ddr_pkg_rank mv_ddr_spd_pri_bus_width_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char pri_bus_width = spd_data->byte_fields.byte_13.bit_fields.primary_bus_width; + enum mv_ddr_pri_bus_width ret_val; + + switch (pri_bus_width) { + case 0x00: + ret_val = MV_DDR_PRI_BUS_WIDTH_8; + break; + case 0x01: + ret_val = MV_DDR_PRI_BUS_WIDTH_16; + break; + case 0x02: + ret_val = MV_DDR_PRI_BUS_WIDTH_32; + break; + case 0x03: + ret_val = MV_DDR_PRI_BUS_WIDTH_64; + break; + default: + ret_val = MV_DDR_PRI_BUS_WIDTH_LAST; + } + + return ret_val; +} + +enum mv_ddr_pkg_rank mv_ddr_spd_bus_width_ext_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char bus_width_ext = spd_data->byte_fields.byte_13.bit_fields.bus_width_ext; + enum mv_ddr_bus_width_ext ret_val; + + switch (bus_width_ext) { + case 0x00: + ret_val = MV_DDR_BUS_WIDTH_EXT_0; + break; + case 0x01: + ret_val = MV_DDR_BUS_WIDTH_EXT_8; + break; + default: + ret_val = MV_DDR_BUS_WIDTH_EXT_LAST; + } + + return ret_val; +} + +static enum mv_ddr_pkg_rank mv_ddr_spd_pkg_rank_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char pkg_rank = spd_data->byte_fields.byte_12.bit_fields.dimm_pkg_ranks_num; + enum mv_ddr_pkg_rank ret_val; + + switch (pkg_rank) { + case 0x00: + ret_val = MV_DDR_PKG_RANK_1; + break; + case 0x01: + ret_val = MV_DDR_PKG_RANK_2; + break; + case 0x02: + ret_val = MV_DDR_PKG_RANK_3; + break; + case 0x03: + ret_val = MV_DDR_PKG_RANK_4; + break; + case 0x04: + ret_val = MV_DDR_PKG_RANK_5; + break; + case 0x05: + ret_val = MV_DDR_PKG_RANK_6; + break; + case 0x06: + ret_val = MV_DDR_PKG_RANK_7; + break; + case 0x07: + ret_val = MV_DDR_PKG_RANK_8; + break; + default: + ret_val = MV_DDR_PKG_RANK_LAST; + } + + return ret_val; +} + +static enum mv_ddr_die_count mv_ddr_spd_die_count_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char die_count = spd_data->byte_fields.byte_6.bit_fields.die_count; + enum mv_ddr_die_count ret_val; + + switch (die_count) { + case 0x00: + ret_val = MV_DDR_DIE_CNT_1; + break; + case 0x01: + ret_val = MV_DDR_DIE_CNT_2; + break; + case 0x02: + ret_val = MV_DDR_DIE_CNT_3; + break; + case 0x03: + ret_val = MV_DDR_DIE_CNT_4; + break; + case 0x04: + ret_val = MV_DDR_DIE_CNT_5; + break; + case 0x05: + ret_val = MV_DDR_DIE_CNT_6; + break; + case 0x06: + ret_val = MV_DDR_DIE_CNT_7; + break; + case 0x07: + ret_val = MV_DDR_DIE_CNT_8; + break; + default: + ret_val = MV_DDR_DIE_CNT_LAST; + } + + return ret_val; +} + +unsigned char mv_ddr_spd_cs_bit_mask_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char cs_bit_mask = 0x0; + enum mv_ddr_pkg_rank pkg_rank = mv_ddr_spd_pkg_rank_get(spd_data); + enum mv_ddr_die_count die_cnt = mv_ddr_spd_die_count_get(spd_data); + + if (pkg_rank == MV_DDR_PKG_RANK_1 && die_cnt == MV_DDR_DIE_CNT_1) + cs_bit_mask = 0x1; + else if (pkg_rank == MV_DDR_PKG_RANK_1 && die_cnt == MV_DDR_DIE_CNT_2) + cs_bit_mask = 0x3; + else if (pkg_rank == MV_DDR_PKG_RANK_2 && die_cnt == MV_DDR_DIE_CNT_1) + cs_bit_mask = 0x3; + else if (pkg_rank == MV_DDR_PKG_RANK_2 && die_cnt == MV_DDR_DIE_CNT_2) + cs_bit_mask = 0xf; + + return cs_bit_mask; +} + +unsigned char mv_ddr_spd_dev_type_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char dev_type = spd_data->byte_fields.byte_2; + + return dev_type; +} + +unsigned char mv_ddr_spd_module_type_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char module_type = spd_data->byte_fields.byte_3.bit_fields.module_type; + + return module_type; +} diff --git a/drivers/ddr/marvell/a38x/mv_ddr_spd.h b/drivers/ddr/marvell/a38x/mv_ddr_spd.h new file mode 100644 index 000000000000..b14293f8f0e2 --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_spd.h @@ -0,0 +1,290 @@ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _MV_DDR_SPD_H +#define _MV_DDR_SPD_H + +#include "mv_ddr_topology.h" + +/* + * Based on JEDEC Standard No. 21-C, 4.1.2.L-4: + * Serial Presence Detect (SPD) for DDR4 SDRAM Modules + */ + +/* block 0: base configuration and dram parameters */ +#define MV_DDR_SPD_DATA_BLOCK0_SIZE 128 +/* block 1: module specific parameters sub-block */ +#define MV_DDR_SPD_DATA_BLOCK1M_SIZE 64 +/* block 1: hybrid memory parameters sub-block */ +#define MV_DDR_SPD_DATA_BLOCK1H_SIZE 64 +/* block 2: extended function parameter block */ +#define MV_DDR_SPD_DATA_BLOCK2E_SIZE 64 +/* block 2: manufacturing information */ +#define MV_DDR_SPD_DATA_BLOCK2M_SIZE 64 +/* block 3: end user programmable */ +#define MV_DDR_SPD_DATA_BLOCK3_SIZE 128 + +#define MV_DDR_SPD_DEV_TYPE_DDR4 0xc +#define MV_DDR_SPD_MODULE_TYPE_UDIMM 0x2 +#define MV_DDR_SPD_MODULE_TYPE_SO_DIMM 0x3 +#define MV_DDR_SPD_MODULE_TYPE_MINI_UDIMM 0x6 +#define MV_DDR_SPD_MODULE_TYPE_72BIT_SO_UDIMM 0x9 +#define MV_DDR_SPD_MODULE_TYPE_16BIT_SO_DIMM 0xc +#define MV_DDR_SPD_MODULE_TYPE_32BIT_SO_DIMM 0xd + +/* + * TODO: For now, the struct contains block 0 & block 1 with module specific + * parameters for unbuffered memory module types only. + */ +union mv_ddr_spd_data { + unsigned char all_bytes[MV_DDR_SPD_DATA_BLOCK0_SIZE + + MV_DDR_SPD_DATA_BLOCK1M_SIZE]; + struct { + /* block 0 */ + union { /* num of bytes used/num of bytes in spd device/crc coverage */ + unsigned char all_bits; + struct { + unsigned char spd_bytes_used:4, + spd_bytes_total:3, + reserved:1; + } bit_fields; + } byte_0; + union { /* spd revision */ + unsigned char all_bits; + struct { + unsigned char addtions_level:4, + encoding_level:4; + } bit_fields; + } byte_1; + unsigned char byte_2; /* key_byte/dram device type */ + union { /* key byte/module type */ + unsigned char all_bits; + struct { + unsigned char module_type:4, + hybrid_media:3, + hybrid:1; + } bit_fields; + } byte_3; + union { /* sdram density & banks */ + unsigned char all_bits; + struct { + unsigned char die_capacity:4, + bank_address:2, + bank_group:2; + } bit_fields; + } byte_4; + union { /* sdram addressing */ + unsigned char all_bits; + struct { + unsigned char col_address:3, + row_address:3, + reserved:2; + } bit_fields; + } byte_5; + union { /* sdram package type */ + unsigned char all_bits; + struct { + unsigned char signal_loading:2, + reserved:2, + die_count:3, + sdram_package_type:1; + } bit_fields; + } byte_6; + union { /* sdram optional features */ + unsigned char all_bits; + struct { + unsigned char mac:4, /* max activate count */ + t_maw:2, /* max activate window */ + reserved:2; /* all 0s */ + } bit_fields; + } byte_7; + unsigned char byte_8; /* sdram thermal & refresh options; reserved; 0x00 */ + union { /* other sdram optional features */ + unsigned char all_bits; + struct { + unsigned char reserved:5, /* all 0s */ + soft_ppr:1, + ppr:2; /* post package repair */ + } bit_fields; + } byte_9; + union { /* secondary sdram package type */ + unsigned char all_bits; + struct { + unsigned char signal_loading:2, + density_ratio:2, /* dram density ratio */ + die_count:3, + sdram_package_type:1; + } bit_fields; + } byte_10; + union { /* module nominal voltage, vdd */ + unsigned char all_bits; + struct { + unsigned char operable:1, + endurant:1, + reserved:5; /* all 0s */ + } bit_fields; + } byte_11; + union { /* module organization*/ + unsigned char all_bits; + struct { + unsigned char device_width:3, + dimm_pkg_ranks_num:3, /* package ranks per dimm number */ + rank_mix:1, + reserved:1; /* 0 */ + } bit_fields; + } byte_12; + union { /* module memory bus width */ + unsigned char all_bits; + struct { + unsigned char primary_bus_width:3, /* in bits */ + bus_width_ext:2, /* in bits */ + reserved:3; /* all 0s */ + } bit_fields; + } byte_13; + union { /* module thernal sensor */ + unsigned char all_bits; + struct { + unsigned char reserved:7, + thermal_sensor:1; + } bit_fields; + } byte_14; + union { /* extended module type */ + unsigned char all_bits; + struct { + unsigned char ext_base_module_type:4, + reserved:4; /* all 0s */ + } bit_fields; + } byte_15; + unsigned char byte_16; /* reserved; 0x00 */ + union { /* timebases */ + unsigned char all_bits; + struct { + unsigned char ftb:2, /* fine timebase */ + mtb:2, /* medium timebase */ + reserved:4; /* all 0s */ + } bit_fields; + } byte_17; + unsigned char byte_18; /* sdram min cycle time (t ck avg min), mtb */ + unsigned char byte_19; /* sdram max cycle time (t ck avg max), mtb */ + unsigned char byte_20; /* cas latencies supported, first byte */ + unsigned char byte_21; /* cas latencies supported, second byte */ + unsigned char byte_22; /* cas latencies supported, third byte */ + unsigned char byte_23; /* cas latencies supported, fourth byte */ + unsigned char byte_24; /* min cas latency time (t aa min), mtb */ + unsigned char byte_25; /* min ras to cas delay time (t rcd min), mtb */ + unsigned char byte_26; /* min row precharge delay time (t rp min), mtb */ + union { /* upper nibbles for t ras min & t rc min */ + unsigned char all_bits; + struct { + unsigned char t_ras_min_msn:4, /* t ras min most significant nibble */ + t_rc_min_msn:4; /* t rc min most significant nibble */ + } bit_fields; + } byte_27; + unsigned char byte_28; /* min active to precharge delay time (t ras min), l-s-byte, mtb */ + unsigned char byte_29; /* min active to active/refresh delay time (t rc min), l-s-byte, mtb */ + unsigned char byte_30; /* min refresh recovery delay time (t rfc1 min), l-s-byte, mtb */ + unsigned char byte_31; /* min refresh recovery delay time (t rfc1 min), m-s-byte, mtb */ + unsigned char byte_32; /* min refresh recovery delay time (t rfc2 min), l-s-byte, mtb */ + unsigned char byte_33; /* min refresh recovery delay time (t rfc2 min), m-s-byte, mtb */ + unsigned char byte_34; /* min refresh recovery delay time (t rfc4 min), l-s-byte, mtb */ + unsigned char byte_35; /* min refresh recovery delay time (t rfc4 min), m-s-byte, mtb */ + union { /* upper nibble for t faw */ + unsigned char all_bits; + struct { + unsigned char t_faw_min_msn:4, /* t faw min most significant nibble */ + reserved:4; + } bit_fields; + } byte_36; + unsigned char byte_37; /* min four activate window delay time (t faw min), l-s-byte, mtb */ + /* byte 38: min activate to activate delay time (t rrd_s min), diff bank group, mtb */ + unsigned char byte_38; + /* byte 39: min activate to activate delay time (t rrd_l min), same bank group, mtb */ + unsigned char byte_39; + unsigned char byte_40; /* min cas to cas delay time (t ccd_l min), same bank group, mtb */ + union { /* upper nibble for t wr min */ + unsigned char all_bits; + struct { + unsigned char t_wr_min_msn:4, /* t wr min most significant nibble */ + reserved:4; + } bit_fields; + } byte_41; + unsigned char byte_42; /* min write recovery time (t wr min) */ + union { /* upper nibbles for t wtr min */ + unsigned char all_bits; + struct { + unsigned char t_wtr_s_min_msn:4, /* t wtr s min most significant nibble */ + t_wtr_l_min_msn:4; /* t wtr l min most significant nibble */ + } bit_fields; + } byte_43; + unsigned char byte_44; /* min write to read time (t wtr s min), diff bank group, mtb */ + unsigned char byte_45; /* min write to read time (t wtr l min), same bank group, mtb */ + unsigned char bytes_46_59[14]; /* reserved; all 0s */ + unsigned char bytes_60_77[18]; /* TODO: connector to sdram bit mapping */ + unsigned char bytes_78_116[39]; /* reserved; all 0s */ + /* fine offset for min cas to cas delay time (t ccd_l min), same bank group, ftb */ + unsigned char byte_117; + /* fine offset for min activate to activate delay time (t rrd_l min), same bank group, ftb */ + unsigned char byte_118; + /* fine offset for min activate to activate delay time (t rrd_s min), diff bank group, ftb */ + unsigned char byte_119; + /* fine offset for min active to active/refresh delay time (t rc min), ftb */ + unsigned char byte_120; + unsigned char byte_121; /* fine offset for min row precharge delay time (t rp min), ftb */ + unsigned char byte_122; /* fine offset for min ras to cas delay time (t rcd min), ftb */ + unsigned char byte_123; /* fine offset for min cas latency time (t aa min), ftb */ + unsigned char byte_124; /* fine offset for sdram max cycle time (t ck avg max), ftb */ + unsigned char byte_125; /* fine offset for sdram min cycle time (t ck avg min), ftb */ + unsigned char byte_126; /* crc for base configuration section, l-s-byte */ + unsigned char byte_127; /* crc for base configuration section, m-s-byte */ + /* + * block 1: module specific parameters for unbuffered memory module types only + */ + union { /* (unbuffered) raw card extension, module nominal height */ + unsigned char all_bits; + struct { + unsigned char nom_height_max:5, /* in mm */ + raw_cad_ext:3; + } bit_fields; + } byte_128; + union { /* (unbuffered) module maximum thickness */ + unsigned char all_bits; + struct { + unsigned char front_thickness_max:4, /* in mm */ + back_thickness_max:4; /* in mm */ + } bit_fields; + } byte_129; + union { /* (unbuffered) reference raw card used */ + unsigned char all_bits; + struct { + unsigned char ref_raw_card:5, + ref_raw_card_rev:2, + ref_raw_card_ext:1; + } bit_fields; + } byte_130; + union { /* (unbuffered) address mapping from edge connector to dram */ + unsigned char all_bits; + struct { + unsigned char rank_1_mapping:1, + reserved:7; + } bit_fields; + } byte_131; + unsigned char bytes_132_191[60]; /* reserved; all 0s */ + } byte_fields; +}; + +int mv_ddr_spd_timing_calc(union mv_ddr_spd_data *spd_data, unsigned int timing_data[]); +enum mv_ddr_dev_width mv_ddr_spd_dev_width_get(union mv_ddr_spd_data *spd_data); +enum mv_ddr_die_capacity mv_ddr_spd_die_capacity_get(union mv_ddr_spd_data *spd_data); +unsigned char mv_ddr_spd_mem_mirror_get(union mv_ddr_spd_data *spd_data); +unsigned char mv_ddr_spd_cs_bit_mask_get(union mv_ddr_spd_data *spd_data); +unsigned char mv_ddr_spd_dev_type_get(union mv_ddr_spd_data *spd_data); +unsigned char mv_ddr_spd_module_type_get(union mv_ddr_spd_data *spd_data); +int mv_ddr_spd_supported_cls_calc(union mv_ddr_spd_data *spd_data); +unsigned int mv_ddr_spd_supported_cl_get(unsigned int cl); +enum mv_ddr_pkg_rank mv_ddr_spd_pri_bus_width_get(union mv_ddr_spd_data *spd_data); +enum mv_ddr_pkg_rank mv_ddr_spd_bus_width_ext_get(union mv_ddr_spd_data *spd_data); + +#endif /* _MV_DDR_SPD_H */ diff --git a/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.c b/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.c new file mode 100644 index 000000000000..505ba28fe28f --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include "mv_ddr_regs.h" +#include "mv_ddr_sys_env_lib.h" + +static u32 mv_ddr_board_id_get(void) +{ +#if defined(CONFIG_TARGET_DB_88F6820_GP) + return DB_GP_68XX_ID; +#else + /* + * Return 0 here for custom board as this should not be used + * for custom boards. + */ + return 0; +#endif +} + +static u32 mv_ddr_board_id_index_get(u32 board_id) +{ + /* + * Marvell Boards use 0x10 as base for Board ID: + * mask MSB to receive index for board ID + */ + return board_id & (MARVELL_BOARD_ID_MASK - 1); +} + +/* + * read gpio input for suspend-wakeup indication + * return indicating suspend wakeup status: + * 0 - not supported, + * 1 - supported: read magic word detect wakeup, + * 2 - detected wakeup from gpio + */ +enum suspend_wakeup_status mv_ddr_sys_env_suspend_wakeup_check(void) +{ + u32 reg, board_id_index, gpio; + struct board_wakeup_gpio board_gpio[] = MV_BOARD_WAKEUP_GPIO_INFO; + + board_id_index = mv_ddr_board_id_index_get(mv_ddr_board_id_get()); + if (!(sizeof(board_gpio) / sizeof(struct board_wakeup_gpio) > + board_id_index)) { + printf("\n_failed loading Suspend-Wakeup information (invalid board ID)\n"); + return SUSPEND_WAKEUP_DISABLED; + } + + /* + * - Detect if Suspend-Wakeup is supported on current board + * - Fetch the GPIO number for wakeup status input indication + */ + if (board_gpio[board_id_index].gpio_num == -1) { + /* Suspend to RAM is not supported */ + return SUSPEND_WAKEUP_DISABLED; + } else if (board_gpio[board_id_index].gpio_num == -2) { + /* + * Suspend to RAM is supported but GPIO indication is + * not implemented - Skip + */ + return SUSPEND_WAKEUP_ENABLED; + } else { + gpio = board_gpio[board_id_index].gpio_num; + } + + /* Initialize MPP for GPIO (set MPP = 0x0) */ + reg = reg_read(MPP_CONTROL_REG(MPP_REG_NUM(gpio))); + /* reset MPP21 to 0x0, keep rest of MPP settings*/ + reg &= ~MPP_MASK(gpio); + reg_write(MPP_CONTROL_REG(MPP_REG_NUM(gpio)), reg); + + /* Initialize GPIO as input */ + reg = reg_read(GPP_DATA_OUT_EN_REG(GPP_REG_NUM(gpio))); + reg |= GPP_MASK(gpio); + reg_write(GPP_DATA_OUT_EN_REG(GPP_REG_NUM(gpio)), reg); + + /* + * Check GPP for input status from PIC: 0 - regular init, + * 1 - suspend wakeup + */ + reg = reg_read(GPP_DATA_IN_REG(GPP_REG_NUM(gpio))); + + /* if GPIO is ON: wakeup from S2RAM indication detected */ + return (reg & GPP_MASK(gpio)) ? SUSPEND_WAKEUP_ENABLED_GPIO_DETECTED : + SUSPEND_WAKEUP_DISABLED; +} + +/* + * get bit mask of enabled cs + * return bit mask of enabled cs: + * 1 - only cs0 enabled, + * 3 - both cs0 and cs1 enabled + */ +u32 mv_ddr_sys_env_get_cs_ena_from_reg(void) +{ + return reg_read(DDR3_RANK_CTRL_REG) & + ((CS_EXIST_MASK << CS_EXIST_OFFS(0)) | + (CS_EXIST_MASK << CS_EXIST_OFFS(1)) | + (CS_EXIST_MASK << CS_EXIST_OFFS(2)) | + (CS_EXIST_MASK << CS_EXIST_OFFS(3))); +} diff --git a/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.h b/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.h new file mode 100644 index 000000000000..229f2f10352e --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.h @@ -0,0 +1,118 @@ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _MV_DDR_SYS_ENV_LIB_H +#define _MV_DDR_SYS_ENV_LIB_H + +#include "ddr_ml_wrapper.h" + +/* device revision */ +#define DEV_ID_REG 0x18238 +#define DEV_VERSION_ID_REG 0x1823c +#define REVISON_ID_OFFS 8 +#define REVISON_ID_MASK 0xf00 + +#define MPP_CONTROL_REG(id) (0x18000 + (id * 4)) +#define GPP_DATA_OUT_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x00) +#define GPP_DATA_OUT_EN_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x04) +#define GPP_DATA_IN_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x10) +#define MV_GPP_REGS_BASE(unit) (0x18100 + ((unit) * 0x40)) + +#define MPP_REG_NUM(GPIO_NUM) (GPIO_NUM / 8) +#define MPP_MASK(GPIO_NUM) (0xf << 4 * (GPIO_NUM - \ + (MPP_REG_NUM(GPIO_NUM) * 8))); +#define GPP_REG_NUM(GPIO_NUM) (GPIO_NUM / 32) +#define GPP_MASK(GPIO_NUM) (1 << GPIO_NUM % 32) + +/* device ID */ +/* Board ID numbers */ +#define MARVELL_BOARD_ID_MASK 0x10 + +/* Customer boards for A38x */ +#define A38X_CUSTOMER_BOARD_ID_BASE 0x0 +#define A38X_CUSTOMER_BOARD_ID0 (A38X_CUSTOMER_BOARD_ID_BASE + 0) +#define A38X_CUSTOMER_BOARD_ID1 (A38X_CUSTOMER_BOARD_ID_BASE + 1) +#define A38X_MV_MAX_CUSTOMER_BOARD_ID (A38X_CUSTOMER_BOARD_ID_BASE + 2) +#define A38X_MV_CUSTOMER_BOARD_NUM (A38X_MV_MAX_CUSTOMER_BOARD_ID - \ + A38X_CUSTOMER_BOARD_ID_BASE) + +/* Marvell boards for A38x */ +#define A38X_MARVELL_BOARD_ID_BASE 0x10 +#define RD_NAS_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 0) +#define DB_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 1) +#define RD_AP_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 2) +#define DB_AP_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 3) +#define DB_GP_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 4) +#define DB_BP_6821_ID (A38X_MARVELL_BOARD_ID_BASE + 5) +#define DB_AMC_6820_ID (A38X_MARVELL_BOARD_ID_BASE + 6) +#define A38X_MV_MAX_MARVELL_BOARD_ID (A38X_MARVELL_BOARD_ID_BASE + 7) +#define A38X_MV_MARVELL_BOARD_NUM (A38X_MV_MAX_MARVELL_BOARD_ID - \ + A38X_MARVELL_BOARD_ID_BASE) + +/* Marvell boards for A39x */ +#define A39X_MARVELL_BOARD_ID_BASE 0x30 +#define A39X_DB_69XX_ID (A39X_MARVELL_BOARD_ID_BASE + 0) +#define A39X_RD_69XX_ID (A39X_MARVELL_BOARD_ID_BASE + 1) +#define A39X_MV_MAX_MARVELL_BOARD_ID (A39X_MARVELL_BOARD_ID_BASE + 2) +#define A39X_MV_MARVELL_BOARD_NUM (A39X_MV_MAX_MARVELL_BOARD_ID - \ + A39X_MARVELL_BOARD_ID_BASE) + +struct board_wakeup_gpio { + u32 board_id; + int gpio_num; +}; + +enum suspend_wakeup_status { + SUSPEND_WAKEUP_DISABLED, + SUSPEND_WAKEUP_ENABLED, + SUSPEND_WAKEUP_ENABLED_GPIO_DETECTED, +}; + +/* + * GPIO status indication for Suspend Wakeup: + * If suspend to RAM is supported and GPIO inidcation is implemented, + * set the gpio number + * If suspend to RAM is supported but GPIO indication is not implemented + * set '-2' + * If suspend to RAM is not supported set '-1' + */ +#ifdef CONFIG_CUSTOMER_BOARD_SUPPORT +#ifdef CONFIG_ARMADA_38X +#define MV_BOARD_WAKEUP_GPIO_INFO { \ + {A38X_CUSTOMER_BOARD_ID0, -1 }, \ + {A38X_CUSTOMER_BOARD_ID0, -1 }, \ +}; +#else +#define MV_BOARD_WAKEUP_GPIO_INFO { \ + {A39X_CUSTOMER_BOARD_ID0, -1 }, \ + {A39X_CUSTOMER_BOARD_ID0, -1 }, \ +}; +#endif /* CONFIG_ARMADA_38X */ + +#else + +#ifdef CONFIG_ARMADA_38X +#define MV_BOARD_WAKEUP_GPIO_INFO { \ + {RD_NAS_68XX_ID, -2 }, \ + {DB_68XX_ID, -1 }, \ + {RD_AP_68XX_ID, -2 }, \ + {DB_AP_68XX_ID, -2 }, \ + {DB_GP_68XX_ID, -2 }, \ + {DB_BP_6821_ID, -2 }, \ + {DB_AMC_6820_ID, -2 }, \ +}; +#else +#define MV_BOARD_WAKEUP_GPIO_INFO { \ + {A39X_RD_69XX_ID, -1 }, \ + {A39X_DB_69XX_ID, -1 }, \ +}; +#endif /* CONFIG_ARMADA_38X */ +#endif /* CONFIG_CUSTOMER_BOARD_SUPPORT */ + +enum suspend_wakeup_status mv_ddr_sys_env_suspend_wakeup_check(void); +u32 mv_ddr_sys_env_get_cs_ena_from_reg(void); + +#endif /* _MV_DDR_SYS_ENV_LIB_H */ diff --git a/drivers/ddr/marvell/a38x/mv_ddr_topology.c b/drivers/ddr/marvell/a38x/mv_ddr_topology.c new file mode 100644 index 000000000000..e82f35275061 --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_topology.c @@ -0,0 +1,198 @@ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include "mv_ddr_topology.h" +#include "mv_ddr_common.h" +#include "mv_ddr_spd.h" +#include "ddr3_init.h" +#include "ddr_topology_def.h" +#include "ddr3_training_ip_db.h" +#include "ddr3_training_ip.h" + + +unsigned int mv_ddr_cl_calc(unsigned int taa_min, unsigned int tclk) +{ + unsigned int cl = ceil_div(taa_min, tclk); + + return mv_ddr_spd_supported_cl_get(cl); + +} + +unsigned int mv_ddr_cwl_calc(unsigned int tclk) +{ + unsigned int cwl; + + if (tclk >= 1250) + cwl = 9; + else if (tclk >= 1071) + cwl = 10; + else if (tclk >= 938) + cwl = 11; + else if (tclk >= 833) + cwl = 12; + else + cwl = 0; + + return cwl; +} + +struct mv_ddr_topology_map *mv_ddr_topology_map_update(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + unsigned int octets_per_if_num = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE); + enum hws_speed_bin speed_bin_index; + enum hws_ddr_freq freq = DDR_FREQ_LAST; + unsigned int tclk; + unsigned char val = 0; + int i; + + + if (tm->interface_params[0].memory_freq == DDR_FREQ_SAR) + tm->interface_params[0].memory_freq = mv_ddr_init_freq_get(); + + if (tm->cfg_src == MV_DDR_CFG_SPD) { + /* check dram device type */ + val = mv_ddr_spd_dev_type_get(&tm->spd_data); + if (val != MV_DDR_SPD_DEV_TYPE_DDR4) { + printf("mv_ddr: unsupported dram device type found\n"); + return NULL; + } + + /* update topology map with timing data */ + if (mv_ddr_spd_timing_calc(&tm->spd_data, tm->timing_data) > 0) { + printf("mv_ddr: negative timing data found\n"); + return NULL; + } + + /* update device width in topology map */ + tm->interface_params[0].bus_width = mv_ddr_spd_dev_width_get(&tm->spd_data); + + /* update die capacity in topology map */ + tm->interface_params[0].memory_size = mv_ddr_spd_die_capacity_get(&tm->spd_data); + + /* update bus bit mask in topology map */ + tm->bus_act_mask = mv_ddr_bus_bit_mask_get(); + + /* update cs bit mask in topology map */ + val = mv_ddr_spd_cs_bit_mask_get(&tm->spd_data); + for (i = 0; i < octets_per_if_num; i++) { + tm->interface_params[0].as_bus_params[i].cs_bitmask = val; + } + + /* check dram module type */ + val = mv_ddr_spd_module_type_get(&tm->spd_data); + switch (val) { + case MV_DDR_SPD_MODULE_TYPE_UDIMM: + case MV_DDR_SPD_MODULE_TYPE_SO_DIMM: + case MV_DDR_SPD_MODULE_TYPE_MINI_UDIMM: + case MV_DDR_SPD_MODULE_TYPE_72BIT_SO_UDIMM: + case MV_DDR_SPD_MODULE_TYPE_16BIT_SO_DIMM: + case MV_DDR_SPD_MODULE_TYPE_32BIT_SO_DIMM: + break; + default: + printf("mv_ddr: unsupported dram module type found\n"); + return NULL; + } + + /* update mirror bit mask in topology map */ + val = mv_ddr_spd_mem_mirror_get(&tm->spd_data); + for (i = 0; i < octets_per_if_num; i++) { + tm->interface_params[0].as_bus_params[i].mirror_enable_bitmask = val << 1; + } + + tclk = 1000000 / freq_val[tm->interface_params[0].memory_freq]; + /* update cas write latency (cwl) */ + val = mv_ddr_cwl_calc(tclk); + if (val == 0) { + printf("mv_ddr: unsupported cas write latency value found\n"); + return NULL; + } + tm->interface_params[0].cas_wl = val; + + /* update cas latency (cl) */ + mv_ddr_spd_supported_cls_calc(&tm->spd_data); + val = mv_ddr_cl_calc(tm->timing_data[MV_DDR_TAA_MIN], tclk); + if (val == 0) { + printf("mv_ddr: unsupported cas latency value found\n"); + return NULL; + } + tm->interface_params[0].cas_l = val; + } else if (tm->cfg_src == MV_DDR_CFG_DEFAULT) { + /* set cas and cas-write latencies per speed bin, if they unset */ + speed_bin_index = tm->interface_params[0].speed_bin_index; + freq = tm->interface_params[0].memory_freq; + + if (tm->interface_params[0].cas_l == 0) + tm->interface_params[0].cas_l = + cas_latency_table[speed_bin_index].cl_val[freq]; + + if (tm->interface_params[0].cas_wl == 0) + tm->interface_params[0].cas_wl = + cas_write_latency_table[speed_bin_index].cl_val[freq]; + } + + + return tm; +} + +unsigned short mv_ddr_bus_bit_mask_get(void) +{ + unsigned short pri_and_ext_bus_width = 0x0; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + unsigned int octets_per_if_num = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE); + + if (tm->cfg_src == MV_DDR_CFG_SPD) { + enum mv_ddr_pri_bus_width pri_bus_width = mv_ddr_spd_pri_bus_width_get(&tm->spd_data); + enum mv_ddr_bus_width_ext bus_width_ext = mv_ddr_spd_bus_width_ext_get(&tm->spd_data); + + switch (pri_bus_width) { + case MV_DDR_PRI_BUS_WIDTH_16: + pri_and_ext_bus_width = BUS_MASK_16BIT; + break; + case MV_DDR_PRI_BUS_WIDTH_32: + pri_and_ext_bus_width = BUS_MASK_32BIT; + break; + case MV_DDR_PRI_BUS_WIDTH_64: + pri_and_ext_bus_width = MV_DDR_64BIT_BUS_MASK; + break; + default: + pri_and_ext_bus_width = 0x0; + } + + if (bus_width_ext == MV_DDR_BUS_WIDTH_EXT_8) + pri_and_ext_bus_width |= 1 << (octets_per_if_num - 1); + } + + return pri_and_ext_bus_width; +} + +unsigned int mv_ddr_if_bus_width_get(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + unsigned int bus_width; + + switch (tm->bus_act_mask) { + case BUS_MASK_16BIT: + case BUS_MASK_16BIT_ECC: + case BUS_MASK_16BIT_ECC_PUP3: + bus_width = 16; + break; + case BUS_MASK_32BIT: + case BUS_MASK_32BIT_ECC: + case MV_DDR_32BIT_ECC_PUP8_BUS_MASK: + bus_width = 32; + break; + case MV_DDR_64BIT_BUS_MASK: + case MV_DDR_64BIT_ECC_PUP8_BUS_MASK: + bus_width = 64; + break; + default: + printf("mv_ddr: unsupported bus active mask parameter found\n"); + bus_width = 0; + } + + return bus_width; +} diff --git a/drivers/ddr/marvell/a38x/mv_ddr_topology.h b/drivers/ddr/marvell/a38x/mv_ddr_topology.h new file mode 100644 index 000000000000..9fd5019ff235 --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_topology.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _MV_DDR_TOPOLOGY_H +#define _MV_DDR_TOPOLOGY_H + +/* ddr bus masks */ +#define BUS_MASK_32BIT 0xf +#define BUS_MASK_32BIT_ECC 0x1f +#define BUS_MASK_16BIT 0x3 +#define BUS_MASK_16BIT_ECC 0x13 +#define BUS_MASK_16BIT_ECC_PUP3 0xb +#define MV_DDR_64BIT_BUS_MASK 0xff +#define MV_DDR_64BIT_ECC_PUP8_BUS_MASK 0x1ff +#define MV_DDR_32BIT_ECC_PUP8_BUS_MASK 0x10f + +/* source of ddr configuration data */ +enum mv_ddr_cfg_src { + MV_DDR_CFG_DEFAULT, /* based on data in mv_ddr_topology_map structure */ + MV_DDR_CFG_SPD, /* based on data in spd */ + MV_DDR_CFG_USER, /* based on data from user */ + MV_DDR_CFG_STATIC, /* based on data from user in register-value format */ + MV_DDR_CFG_LAST +}; + +enum mv_ddr_num_of_sub_phys_per_ddr_unit { + SINGLE_SUB_PHY = 1, + TWO_SUB_PHYS = 2 +}; + +enum mv_ddr_temperature { + MV_DDR_TEMP_LOW, + MV_DDR_TEMP_NORMAL, + MV_DDR_TEMP_HIGH +}; + +enum mv_ddr_timing_data { + MV_DDR_TCK_AVG_MIN, /* sdram min cycle time (t ck avg min) */ + MV_DDR_TAA_MIN, /* min cas latency time (t aa min) */ + MV_DDR_TRFC1_MIN, /* min refresh recovery delay time (t rfc1 min) */ + MV_DDR_TWR_MIN, /* min write recovery time (t wr min) */ + MV_DDR_TRCD_MIN, /* min ras to cas delay time (t rcd min) */ + MV_DDR_TRP_MIN, /* min row precharge delay time (t rp min) */ + MV_DDR_TRC_MIN, /* min active to active/refresh delay time (t rc min) */ + MV_DDR_TRAS_MIN, /* min active to precharge delay time (t ras min) */ + MV_DDR_TRRD_S_MIN, /* min activate to activate delay time (t rrd_s min), diff bank group */ + MV_DDR_TRRD_L_MIN, /* min activate to activate delay time (t rrd_l min), same bank group */ + MV_DDR_TFAW_MIN, /* min four activate window delay time (t faw min) */ + MV_DDR_TWTR_S_MIN, /* min write to read time (t wtr s min), diff bank group */ + MV_DDR_TWTR_L_MIN, /* min write to read time (t wtr l min), same bank group */ + MV_DDR_TDATA_LAST +}; + +enum mv_ddr_dev_width { /* sdram device width */ + MV_DDR_DEV_WIDTH_4BIT, + MV_DDR_DEV_WIDTH_8BIT, + MV_DDR_DEV_WIDTH_16BIT, + MV_DDR_DEV_WIDTH_32BIT, + MV_DDR_DEV_WIDTH_LAST +}; + +enum mv_ddr_die_capacity { /* total sdram capacity per die, megabits */ + MV_DDR_DIE_CAP_256MBIT, + MV_DDR_DIE_CAP_512MBIT = 0, + MV_DDR_DIE_CAP_1GBIT, + MV_DDR_DIE_CAP_2GBIT, + MV_DDR_DIE_CAP_4GBIT, + MV_DDR_DIE_CAP_8GBIT, + MV_DDR_DIE_CAP_16GBIT, + MV_DDR_DIE_CAP_32GBIT, + MV_DDR_DIE_CAP_12GBIT, + MV_DDR_DIE_CAP_24GBIT, + MV_DDR_DIE_CAP_LAST +}; + +enum mv_ddr_pkg_rank { /* number of package ranks per dimm */ + MV_DDR_PKG_RANK_1, + MV_DDR_PKG_RANK_2, + MV_DDR_PKG_RANK_3, + MV_DDR_PKG_RANK_4, + MV_DDR_PKG_RANK_5, + MV_DDR_PKG_RANK_6, + MV_DDR_PKG_RANK_7, + MV_DDR_PKG_RANK_8, + MV_DDR_PKG_RANK_LAST +}; + +enum mv_ddr_pri_bus_width { /* number of primary bus width bits */ + MV_DDR_PRI_BUS_WIDTH_8, + MV_DDR_PRI_BUS_WIDTH_16, + MV_DDR_PRI_BUS_WIDTH_32, + MV_DDR_PRI_BUS_WIDTH_64, + MV_DDR_PRI_BUS_WIDTH_LAST +}; + +enum mv_ddr_bus_width_ext { /* number of extension bus width bits */ + MV_DDR_BUS_WIDTH_EXT_0, + MV_DDR_BUS_WIDTH_EXT_8, + MV_DDR_BUS_WIDTH_EXT_LAST +}; + +enum mv_ddr_die_count { + MV_DDR_DIE_CNT_1, + MV_DDR_DIE_CNT_2, + MV_DDR_DIE_CNT_3, + MV_DDR_DIE_CNT_4, + MV_DDR_DIE_CNT_5, + MV_DDR_DIE_CNT_6, + MV_DDR_DIE_CNT_7, + MV_DDR_DIE_CNT_8, + MV_DDR_DIE_CNT_LAST +}; + +unsigned int mv_ddr_cl_calc(unsigned int taa_min, unsigned int tclk); +unsigned int mv_ddr_cwl_calc(unsigned int tclk); +struct mv_ddr_topology_map *mv_ddr_topology_map_update(void); +struct dram_config *mv_ddr_dram_config_update(void); +unsigned short mv_ddr_bus_bit_mask_get(void); +unsigned int mv_ddr_if_bus_width_get(void); + +#endif /* _MV_DDR_TOPOLOGY_H */ diff --git a/drivers/ddr/marvell/a38x/seq_exec.h b/drivers/ddr/marvell/a38x/seq_exec.h new file mode 100644 index 000000000000..14f406a75f63 --- /dev/null +++ b/drivers/ddr/marvell/a38x/seq_exec.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _SEQ_EXEC_H +#define _SEQ_EXEC_H + +#define NA 0xff +#define DEFAULT_PARAM 0 +#define MV_BOARD_TCLK_ERROR 0xffffffff + +#define NO_DATA 0xffffffff +#define MAX_DATA_ARRAY 5 +#define FIRST_CELL 0 + +/* Operation types */ +enum mv_op { + WRITE_OP, + DELAY_OP, + POLL_OP, +}; + +/* Operation parameters */ +struct op_params { + u32 unit_base_reg; + u32 unit_offset; + u32 mask; + u32 data[MAX_DATA_ARRAY]; /* data array */ + u8 wait_time; /* msec */ + u16 num_of_loops; /* for polling only */ +}; + +/* + * Sequence parameters. Each sequence contains: + * 1. Sequence id. + * 2. Sequence size (total amount of operations during the sequence) + * 3. a series of operations. operations can be write, poll or delay + * 4. index in the data array (the entry where the relevant data sits) + */ +struct cfg_seq { + struct op_params *op_params_ptr; + u8 cfg_seq_size; + u8 data_arr_idx; +}; + +extern struct cfg_seq serdes_seq_db[]; + +/* + * A generic function type for executing an operation (write, poll or delay) + */ +typedef int (*op_execute_func_ptr)(u32 serdes_num, struct op_params *params, + u32 data_arr_idx); + +/* Specific functions for executing each operation */ +int write_op_execute(u32 serdes_num, struct op_params *params, + u32 data_arr_idx); +int delay_op_execute(u32 serdes_num, struct op_params *params, + u32 data_arr_idx); +int poll_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx); +enum mv_op get_cfg_seq_op(struct op_params *params); +int mv_seq_exec(u32 serdes_num, u32 seq_id); + +#endif /*_SEQ_EXEC_H*/ diff --git a/drivers/ddr/marvell/a38x/silicon_if.h b/drivers/ddr/marvell/a38x/silicon_if.h deleted file mode 100644 index 7fce27da1238..000000000000 --- a/drivers/ddr/marvell/a38x/silicon_if.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - * - * SPDX-License-Identifier: GPL-2.0 - */ - -#ifndef __silicon_if_H -#define __silicon_if_H - -/* max number of devices supported by driver */ -#ifdef CO_CPU_RUN -#define HWS_MAX_DEVICE_NUM (1) -#else -#define HWS_MAX_DEVICE_NUM (16) -#endif - -#endif /* __silicon_if_H */ diff --git a/drivers/ddr/marvell/a38x/xor.c b/drivers/ddr/marvell/a38x/xor.c index 9c73c54eec54..368432165fa3 100644 --- a/drivers/ddr/marvell/a38x/xor.c +++ b/drivers/ddr/marvell/a38x/xor.c @@ -4,13 +4,6 @@ * SPDX-License-Identifier: GPL-2.0 */ -#include -#include -#include -#include -#include -#include - #include "ddr3_init.h" #include "xor_regs.h" @@ -22,39 +15,48 @@ #endif static u32 ui_xor_regs_ctrl_backup; -static u32 ui_xor_regs_base_backup[MAX_CS]; -static u32 ui_xor_regs_mask_backup[MAX_CS]; +static u32 ui_xor_regs_base_backup[MAX_CS_NUM + 1]; +static u32 ui_xor_regs_mask_backup[MAX_CS_NUM + 1]; -void mv_sys_xor_init(u32 num_of_cs, u32 cs_ena, u32 cs_size, u32 base_delta) +void mv_sys_xor_init(u32 num_of_cs, u32 cs_ena, uint64_t cs_size, u32 base_delta) { - u32 reg, ui, base, cs_count; + u32 reg, ui, cs_count; + uint64_t base, size_mask; ui_xor_regs_ctrl_backup = reg_read(XOR_WINDOW_CTRL_REG(0, 0)); - for (ui = 0; ui < MAX_CS; ui++) + for (ui = 0; ui < MAX_CS_NUM + 1; ui++) ui_xor_regs_base_backup[ui] = reg_read(XOR_BASE_ADDR_REG(0, ui)); - for (ui = 0; ui < MAX_CS; ui++) + for (ui = 0; ui < MAX_CS_NUM + 1; ui++) ui_xor_regs_mask_backup[ui] = reg_read(XOR_SIZE_MASK_REG(0, ui)); reg = 0; - for (ui = 0; ui < (num_of_cs); ui++) { - /* Enable Window x for each CS */ - reg |= (0x1 << (ui)); - /* Enable Window x for each CS */ - reg |= (0x3 << ((ui * 2) + 16)); + for (ui = 0, cs_count = 0; + (cs_count < num_of_cs) && (ui < 8); + ui++, cs_count++) { + if (cs_ena & (1 << ui)) { + /* Enable Window x for each CS */ + reg |= (0x1 << (ui)); + /* Enable Window x for each CS */ + reg |= (0x3 << ((ui * 2) + 16)); + } } reg_write(XOR_WINDOW_CTRL_REG(0, 0), reg); cs_count = 0; - for (ui = 0; ui < num_of_cs; ui++) { + for (ui = 0, cs_count = 0; + (cs_count < num_of_cs) && (ui < 8); + ui++, cs_count++) { if (cs_ena & (1 << ui)) { /* * window x - Base - 0x00000000, * Attribute 0x0e - DRAM */ base = cs_size * ui + base_delta; + /* fixed size 2GB for each CS */ + size_mask = 0x7FFF0000; switch (ui) { case 0: base |= 0xe00; @@ -68,13 +70,19 @@ void mv_sys_xor_init(u32 num_of_cs, u32 cs_ena, u32 cs_size, u32 base_delta) case 3: base |= 0x700; break; + case 4: /* SRAM */ + base = 0x40000000; + /* configure as shared transaction */ + base |= 0x1F00; + size_mask = 0xF0000; + break; } - reg_write(XOR_BASE_ADDR_REG(0, cs_count), base); - + reg_write(XOR_BASE_ADDR_REG(0, ui), (u32)base); + size_mask = (cs_size / _64K) - 1; + size_mask = (size_mask << XESMRX_SIZE_MASK_OFFS) & XESMRX_SIZE_MASK_MASK; /* window x - Size */ - reg_write(XOR_SIZE_MASK_REG(0, cs_count), 0x7fff0000); - cs_count++; + reg_write(XOR_SIZE_MASK_REG(0, ui), (u32)size_mask); } } @@ -88,10 +96,10 @@ void mv_sys_xor_finish(void) u32 ui; reg_write(XOR_WINDOW_CTRL_REG(0, 0), ui_xor_regs_ctrl_backup); - for (ui = 0; ui < MAX_CS; ui++) + for (ui = 0; ui < MAX_CS_NUM + 1; ui++) reg_write(XOR_BASE_ADDR_REG(0, ui), ui_xor_regs_base_backup[ui]); - for (ui = 0; ui < MAX_CS; ui++) + for (ui = 0; ui < MAX_CS_NUM + 1; ui++) reg_write(XOR_SIZE_MASK_REG(0, ui), ui_xor_regs_mask_backup[ui]); @@ -154,11 +162,14 @@ int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl) return MV_OK; } -int mv_xor_mem_init(u32 chan, u32 start_ptr, u32 block_size, +int mv_xor_mem_init(u32 chan, u32 start_ptr, unsigned long long block_size, u32 init_val_high, u32 init_val_low) { u32 temp; + if (block_size == _4G) + block_size -= 1; + /* Parameter checking */ if (chan >= MV_XOR_MAX_CHAN) return MV_BAD_PARAM; @@ -329,28 +340,123 @@ void ddr3_new_tip_ecc_scrub(void) { u32 cs_c, max_cs; u32 cs_ena = 0; + u32 dev_num = 0; + uint64_t total_mem_size, cs_mem_size = 0; - printf("DDR3 Training Sequence - Start scrubbing\n"); - - max_cs = hws_ddr3_tip_max_cs_get(); + printf("DDR Training Sequence - Start scrubbing\n"); + max_cs = ddr3_tip_max_cs_get(dev_num); for (cs_c = 0; cs_c < max_cs; cs_c++) cs_ena |= 1 << cs_c; - mv_sys_xor_init(max_cs, cs_ena, 0x80000000, 0); - - mv_xor_mem_init(0, 0x00000000, 0x80000000, 0xdeadbeef, 0xdeadbeef); - /* wait for previous transfer completion */ - while (mv_xor_state_get(0) != MV_IDLE) - ; - - mv_xor_mem_init(0, 0x80000000, 0x40000000, 0xdeadbeef, 0xdeadbeef); - + mv_sys_xor_init(max_cs, cs_ena, cs_mem_size, 0); + total_mem_size = max_cs * cs_mem_size; + mv_xor_mem_init(0, 0, total_mem_size, 0xdeadbeef, 0xdeadbeef); /* wait for previous transfer completion */ while (mv_xor_state_get(0) != MV_IDLE) ; - /* Return XOR State */ mv_sys_xor_finish(); printf("DDR3 Training Sequence - End scrubbing\n"); } + +/* +* mv_xor_transfer - Transfer data from source to destination in one of +* three modes: XOR, CRC32 or DMA +* +* DESCRIPTION: +* This function initiates XOR channel, according to function parameters, +* in order to perform XOR, CRC32 or DMA transaction. +* To gain maximum performance the user is asked to keep the following +* restrictions: +* 1) Selected engine is available (not busy). +* 2) This module does not take into consideration CPU MMU issues. +* In order for the XOR engine to access the appropriate source +* and destination, address parameters must be given in system +* physical mode. +* 3) This API does not take care of cache coherency issues. The source, +* destination and, in case of chain, the descriptor list are assumed +* to be cache coherent. +* 4) Parameters validity. +* +* INPUT: +* chan - XOR channel number. +* type - One of three: XOR, CRC32 and DMA operations. +* xor_chain_ptr - address of chain pointer +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. +* +*******************************************************************************/ +int mv_xor_transfer(u32 chan, enum xor_type type, u32 xor_chain_ptr) +{ + u32 temp; + + /* Parameter checking */ + if (chan >= MV_XOR_MAX_CHAN) { + DB(printf("%s: ERR. Invalid chan num %d\n", __func__, chan)); + return MV_BAD_PARAM; + } + if (mv_xor_state_get(chan) == MV_ACTIVE) { + DB(printf("%s: ERR. Channel is already active\n", __func__)); + return MV_BUSY; + } + if (xor_chain_ptr == 0x0) { + DB(printf("%s: ERR. xor_chain_ptr is NULL pointer\n", __func__)); + return MV_BAD_PARAM; + } + + /* read configuration register and mask the operation mode field */ + temp = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan))); + temp &= ~XEXCR_OPERATION_MODE_MASK; + + switch (type) { + case MV_XOR: + if ((xor_chain_ptr & XEXDPR_DST_PTR_XOR_MASK) != 0) { + DB(printf("%s: ERR. Invalid chain pointer (bits [5:0] must be cleared)\n", + __func__)); + return MV_BAD_PARAM; + } + /* set the operation mode to XOR */ + temp |= XEXCR_OPERATION_MODE_XOR; + break; + case MV_DMA: + if ((xor_chain_ptr & XEXDPR_DST_PTR_DMA_MASK) != 0) { + DB(printf("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n", + __func__)); + return MV_BAD_PARAM; + } + /* set the operation mode to DMA */ + temp |= XEXCR_OPERATION_MODE_DMA; + break; + case MV_CRC32: + if ((xor_chain_ptr & XEXDPR_DST_PTR_CRC_MASK) != 0) { + DB(printf("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n", + __func__)); + return MV_BAD_PARAM; + } + /* set the operation mode to CRC32 */ + temp |= XEXCR_OPERATION_MODE_CRC; + break; + default: + return MV_BAD_PARAM; + } + + /* write the operation mode to the register */ + reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), temp); + /* + * update the NextDescPtr field in the XOR Engine [0..1] Next Descriptor + * Pointer Register (XExNDPR) + */ + reg_write(XOR_NEXT_DESC_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)), + xor_chain_ptr); + + /* start transfer */ + reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)), + XEXACTR_XESTART_MASK); + + return MV_OK; +} diff --git a/drivers/ddr/marvell/a38x/xor.h b/drivers/ddr/marvell/a38x/xor.h index 7b1e3161772c..f389769409a1 100644 --- a/drivers/ddr/marvell/a38x/xor.h +++ b/drivers/ddr/marvell/a38x/xor.h @@ -9,8 +9,6 @@ #define SRAM_BASE 0x40000000 -#include "ddr3_hws_hw_training_def.h" - #define MV_XOR_MAX_UNIT 2 /* XOR unit == XOR engine */ #define MV_XOR_MAX_CHAN 4 /* total channels for all units */ #define MV_XOR_MAX_CHAN_PER_UNIT 2 /* channels for units */ @@ -88,5 +86,6 @@ int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl); int mv_xor_command_set(u32 chan, enum mv_command command); int mv_xor_override_set(u32 chan, enum xor_override_target target, u32 win_num, int enable); +int mv_xor_transfer(u32 chan, enum xor_type type, u32 xor_chain_ptr); #endif -- 2.16.2