diff mbox series

[v1,08/23] phy: marvell: add RX training command

Message ID 20210324150325.v1.8.I818fe67ccaf19a87af50d4c34a9db7d6802049a5@changeid
State Accepted
Commit e49cdbe10b082980029b8e215842be4fbbd13f5f
Delegated to: Stefan Roese
Headers show
Series phy: marvell: Sync Armada 3k/7k/8k SERDES code with Marvell version | expand

Commit Message

Stefan Roese March 24, 2021, 2:06 p.m. UTC
From: Igal Liberman <igall@marvell.com>

This patch adds support for running RX training using new command called
"rx_training"
Usage:
rx_training - rx_training <cp id> <comphy id>

RX training allows to improve link quality (for SFI mode)
by running training sequence between us and the link partner,
this allows to reach better link quality then using static configuration.

Signed-off-by: Igal Liberman <igall@marvell.com>
Signed-off-by: Marcin Wojtas <mw@semihalf.com>
Signed-off-by: Stefan Roese <sr@denx.de>
---

 cmd/mvebu/Kconfig                   |   7 +
 cmd/mvebu/Makefile                  |   2 +-
 cmd/mvebu/rx_training.c             |  57 +++++++++
 configs/mvebu_db_armada8k_defconfig |   1 +
 drivers/phy/marvell/comphy_core.c   |  18 ++-
 drivers/phy/marvell/comphy_core.h   |  14 ++
 drivers/phy/marvell/comphy_cp110.c  | 190 ++++++++++++++++++++++++++++
 drivers/phy/marvell/comphy_hpipe.h  |  62 ++++++++-
 include/mvebu/comphy.h              |   2 +-
 9 files changed, 348 insertions(+), 5 deletions(-)
 create mode 100644 cmd/mvebu/rx_training.c

Comments

Marek BehĂșn March 24, 2021, 5:46 p.m. UTC | #1
On Wed, 24 Mar 2021 15:06:34 +0100
Stefan Roese <sr@denx.de> wrote:

> From: Igal Liberman <igall@marvell.com>
> 
> This patch adds support for running RX training using new command called
> "rx_training"
> Usage:
> rx_training - rx_training <cp id> <comphy id>
> 
> RX training allows to improve link quality (for SFI mode)
> by running training sequence between us and the link partner,
> this allows to reach better link quality then using static configuration.

PLEASE do not add another vendor specific command. PLEASE !

Create a generic command, with name 'ddr' or something, with API and
documentation.

Also the name "rx_training" is the worst thing ever. It could be
interpreted as training for RX on ethernet PHY, or even on UART.

Maybe people from Marvell could work more on their cooperation with
community. It is not terrible, but it is bad. There are hundreds if not
thousand of patches in their SDKs for both U-Boot and Linux. It is a
nightmare.

Marek
Stefan Roese April 8, 2021, 8:46 a.m. UTC | #2
Hi Marek,

On 24.03.21 18:46, Marek Behun wrote:
> On Wed, 24 Mar 2021 15:06:34 +0100
> Stefan Roese <sr@denx.de> wrote:
> 
>> From: Igal Liberman <igall@marvell.com>
>>
>> This patch adds support for running RX training using new command called
>> "rx_training"
>> Usage:
>> rx_training - rx_training <cp id> <comphy id>
>>
>> RX training allows to improve link quality (for SFI mode)
>> by running training sequence between us and the link partner,
>> this allows to reach better link quality then using static configuration.
> 
> PLEASE do not add another vendor specific command. PLEASE !

Why not? We have many vendor specific commands in U-Boot. We also have
board specific commands as well.

I agree that generic / common commands should be implemented in a way,
that they can be used by all platforms. But this is not possible or
for all commands. And this command does not look very "generic" at least
not to me.

> Create a generic command, with name 'ddr' or something, with API and
> documentation.
> 
> Also the name "rx_training" is the worst thing ever. It could be
> interpreted as training for RX on ethernet PHY, or even on UART.

"RX" is of course not very specific, I agree. AFAICT, only
comphy_cp110_sfi_rx_training() is supported (right now). Not sure if
this will be extended at a later time. Perhaps using something like
"comphy_rx_training" would be more suitable?

Thanks,
Stefan
diff mbox series

Patch

diff --git a/cmd/mvebu/Kconfig b/cmd/mvebu/Kconfig
index f1eb00614dd6..f0e4f884d703 100644
--- a/cmd/mvebu/Kconfig
+++ b/cmd/mvebu/Kconfig
@@ -49,4 +49,11 @@  config MVEBU_UBOOT_DFLT_NAME
 	  This option should contain a default file name to be used with
 	  MVEBU "bubt" command if the source file name is omitted
 
+config CMD_MVEBU_RX_TRAINING
+	bool "rx_training"
+	depends on TARGET_MVEBU_ARMADA_8K
+	default n
+	help
+	  Perform RX training sequence
+
 endmenu
diff --git a/cmd/mvebu/Makefile b/cmd/mvebu/Makefile
index 96829c48ebdc..79299b0814f4 100644
--- a/cmd/mvebu/Makefile
+++ b/cmd/mvebu/Makefile
@@ -4,5 +4,5 @@ 
 #
 # https://spdx.org/licenses
 
-
 obj-$(CONFIG_CMD_MVEBU_BUBT) += bubt.o
+obj-$(CONFIG_CMD_MVEBU_RX_TRAINING) += rx_training.o
diff --git a/cmd/mvebu/rx_training.c b/cmd/mvebu/rx_training.c
new file mode 100644
index 000000000000..4bae7653aca3
--- /dev/null
+++ b/cmd/mvebu/rx_training.c
@@ -0,0 +1,57 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2017 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <dm/device-internal.h>
+#include <mvebu/comphy.h>
+
+int rx_training_cmd(struct cmd_tbl *cmdtp, int flag, int argc,
+		    char * const argv[])
+{
+	struct udevice *dev;
+	struct uclass *uc;
+	int ret, cp_index, comphy_index, i = 0;
+
+	if (argc != 3) {
+		printf("missing arguments\n");
+		return -1;
+	}
+
+	cp_index = simple_strtoul(argv[1], NULL, 16);
+	comphy_index = simple_strtoul(argv[2], NULL, 16);
+
+	ret = uclass_get(UCLASS_MISC, &uc);
+	if (ret) {
+		printf("Couldn't find UCLASS_MISC\n");
+		return ret;
+	}
+
+	uclass_foreach_dev(dev, uc) {
+		if (!(memcmp(dev->name, "comphy", 5))) {
+			if (i == cp_index) {
+				comphy_rx_training(dev, comphy_index);
+				return 0;
+			}
+
+			i++;
+		}
+	}
+
+	printf("Coudn't find comphy %d\n", cp_index);
+
+	return 0;
+}
+
+U_BOOT_CMD(
+	rx_training, 3, 0, rx_training_cmd,
+	"rx_training <cp id> <comphy id>\n",
+	"\n\tRun RX training sequence, the user must state CP index (0/1) and comphy ID (0/5)"
+);
diff --git a/configs/mvebu_db_armada8k_defconfig b/configs/mvebu_db_armada8k_defconfig
index ffe8e029050f..96baea76fc1c 100644
--- a/configs/mvebu_db_armada8k_defconfig
+++ b/configs/mvebu_db_armada8k_defconfig
@@ -32,6 +32,7 @@  CONFIG_CMD_TFTPPUT=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_MVEBU_BUBT=y
+CONFIG_CMD_MVEBU_RX_TRAINING=y
 CONFIG_CMD_EXT4_WRITE=y
 CONFIG_MAC_PARTITION=y
 CONFIG_ENV_OVERWRITE=y
diff --git a/drivers/phy/marvell/comphy_core.c b/drivers/phy/marvell/comphy_core.c
index d8df7ac949a3..b29decd82693 100644
--- a/drivers/phy/marvell/comphy_core.c
+++ b/drivers/phy/marvell/comphy_core.c
@@ -71,6 +71,16 @@  void comphy_print(struct chip_serdes_phy_config *chip_cfg,
 	}
 }
 
+int comphy_rx_training(struct udevice *dev, u32 lane)
+{
+	struct chip_serdes_phy_config *chip_cfg = dev_get_priv(dev);
+
+	if (chip_cfg->rx_training)
+		return chip_cfg->rx_training(chip_cfg, lane);
+
+	return 0;
+}
+
 __weak int comphy_update_map(struct comphy_map *serdes_map, int count)
 {
 	return 0;
@@ -114,11 +124,15 @@  static int comphy_probe(struct udevice *dev)
 		fdtdec_locate_array(blob, node, "mux-lane-order",
 				    chip_cfg->comphy_lanes_count);
 
-	if (device_is_compatible(dev, "marvell,comphy-armada-3700"))
+	if (device_is_compatible(dev, "marvell,comphy-armada-3700")) {
 		chip_cfg->ptr_comphy_chip_init = comphy_a3700_init;
+		chip_cfg->rx_training = NULL;
+	}
 
-	if (device_is_compatible(dev, "marvell,comphy-cp110"))
+	if (device_is_compatible(dev, "marvell,comphy-cp110")) {
 		chip_cfg->ptr_comphy_chip_init = comphy_cp110_init;
+		chip_cfg->rx_training = comphy_cp110_sfi_rx_training;
+	}
 
 	/*
 	 * Bail out if no chip_init function is defined, e.g. no
diff --git a/drivers/phy/marvell/comphy_core.h b/drivers/phy/marvell/comphy_core.h
index c08677e56d2e..32895dc4aa3d 100644
--- a/drivers/phy/marvell/comphy_core.h
+++ b/drivers/phy/marvell/comphy_core.h
@@ -84,6 +84,7 @@  struct chip_serdes_phy_config {
 	struct comphy_mux_data *mux_data;
 	int (*ptr_comphy_chip_init)(struct chip_serdes_phy_config *,
 				    struct comphy_map *);
+	int (*rx_training)(struct chip_serdes_phy_config *, u32);
 	void __iomem *comphy_base_addr;
 	void __iomem *hpipe3_base_addr;
 	u32 comphy_lanes_count;
@@ -151,6 +152,8 @@  static inline int comphy_a3700_init(struct chip_serdes_phy_config *ptr_chip_cfg,
 #ifdef CONFIG_ARMADA_8K
 int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg,
 		      struct comphy_map *serdes_map);
+int comphy_cp110_sfi_rx_training(struct chip_serdes_phy_config *ptr_chip_cfg,
+				 u32 lane);
 #else
 static inline int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg,
 		      struct comphy_map *serdes_map)
@@ -161,6 +164,17 @@  static inline int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg,
 	 */
 	return -1;
 }
+
+static inline int comphy_cp110_sfi_rx_training(
+	struct chip_serdes_phy_config *ptr_chip_cfg,
+	u32 lane)
+{
+	/*
+	 * This function should never be called in this configuration, so
+	 * lets return an error here.
+	 */
+	return -1;
+}
 #endif
 
 void comphy_dedicated_phys_init(void);
diff --git a/drivers/phy/marvell/comphy_cp110.c b/drivers/phy/marvell/comphy_cp110.c
index 72563f8bc1c5..11dc46b28a63 100644
--- a/drivers/phy/marvell/comphy_cp110.c
+++ b/drivers/phy/marvell/comphy_cp110.c
@@ -133,6 +133,196 @@  static u32 polling_with_timeout(void __iomem *addr, u32 val,
 	return 0;
 }
 
+/* This function performs RX training for single FFE value.
+ * The result of the RX training is located in:
+ *	Saved DFE values Register[10:15].
+ *
+ * The result is returned to the caller using *result
+ *
+ * Return '1' on succsess.
+ * Return '0' on failure.
+ */
+static int comphy_cp110_test_single_ffe(
+			struct chip_serdes_phy_config *ptr_chip_cfg,
+			u32 lane, u32 ffe, u32 *result)
+{
+	u32 mask, data, timeout;
+	void __iomem *hpipe_base_addr = ptr_chip_cfg->hpipe3_base_addr;
+	void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base_addr, lane);
+	void __iomem *sd_ip_addr = SD_ADDR(hpipe_base_addr, lane);
+
+	/* Configure PRBS counters */
+	mask = HPIPE_PHY_TEST_PATTERN_SEL_MASK;
+	data = 0xe << HPIPE_PHY_TEST_PATTERN_SEL_OFFSET;
+	reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
+
+	mask = HPIPE_PHY_TEST_DATA_MASK;
+	data = 0x64 << HPIPE_PHY_TEST_DATA_OFFSET;
+	reg_set(hpipe_addr + HPIPE_PHY_TEST_DATA_REG, data, mask);
+
+	mask = HPIPE_PHY_TEST_EN_MASK;
+	data = 0x1 << HPIPE_PHY_TEST_EN_OFFSET;
+	reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
+
+	mdelay(50);
+
+	/* Set the FFE value */
+	mask = HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK;
+	data = ffe << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET;
+	reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
+
+	/* Start RX training */
+	mask = SD_EXTERNAL_STATUS_START_RX_TRAINING_MASK;
+	data = 1 << SD_EXTERNAL_STATUS_START_RX_TRAINING_OFFSET;
+	reg_set(sd_ip_addr + SD_EXTERNAL_STATUS_REG, data, mask);
+
+	/* Check the result of RX training */
+	timeout = RX_TRAINING_TIMEOUT;
+	while (timeout) {
+		data = readl(sd_ip_addr + SD_EXTERNAL_STATUS1_REG);
+		if (data & SD_EXTERNAL_STATUS1_REG_RX_TRAIN_COMP_MASK)
+			break;
+		mdelay(1);
+		timeout--;
+	}
+
+	if (timeout == 0)
+		return 0;
+
+	if (data & SD_EXTERNAL_STATUS1_REG_RX_TRAIN_FAILED_MASK)
+		return 0;
+
+	/* Stop RX training */
+	mask = SD_EXTERNAL_STATUS_START_RX_TRAINING_MASK;
+	data = 0 << SD_EXTERNAL_STATUS_START_RX_TRAINING_OFFSET;
+	reg_set(sd_ip_addr + SD_EXTERNAL_STATUS_REG, data, mask);
+
+	/* Read the result */
+	data = readl(hpipe_addr + HPIPE_SAVED_DFE_VALUES_REG);
+	data &= HPIPE_SAVED_DFE_VALUES_SAV_F0D_MASK;
+	data >>= HPIPE_SAVED_DFE_VALUES_SAV_F0D_OFFSET;
+	*result = data;
+
+	printf("FFE = %d, result = 0x%x\n", ffe, *result);
+
+	/* Clear the PRBS counters */
+	mask = HPIPE_PHY_TEST_RESET_MASK;
+	data = 0x1 << HPIPE_PHY_TEST_RESET_OFFSET;
+	mask |= HPIPE_PHY_TEST_EN_MASK;
+	data |= 0x0 << HPIPE_PHY_TEST_EN_OFFSET;
+	reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
+
+	mask = HPIPE_PHY_TEST_RESET_MASK;
+	data = 0x0 << HPIPE_PHY_TEST_RESET_OFFSET;
+	reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
+
+	return 1;
+}
+
+/* This function performs RX training for all FFE possible values.
+ * We get the result for each FFE and eventually the best FFE will
+ * be used and set to the HW.
+ *
+ * Return '1' on succsess.
+ * Return '0' on failure.
+ */
+int comphy_cp110_sfi_rx_training(struct chip_serdes_phy_config *ptr_chip_cfg,
+				 u32 lane)
+{
+	u32 mask, data, i, rx_train_result;
+	u32 max_rx_train = 0, max_rx_train_index = 0;
+	void __iomem *hpipe_base_addr = ptr_chip_cfg->hpipe3_base_addr;
+	void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base_addr, lane);
+	int ret;
+
+	debug_enter();
+
+	if (ptr_chip_cfg->comphy_map_data[lane].type != COMPHY_TYPE_SFI) {
+		pr_err("Comphy %d isn't configured to SFI\n", lane);
+		return 0;
+	}
+
+	/* Configure SQ threshold and CDR lock */
+	mask = HPIPE_SQUELCH_THRESH_IN_MASK;
+	data = 0xc << HPIPE_SQUELCH_THRESH_IN_OFFSET;
+	reg_set(hpipe_addr + HPIPE_SQUELCH_FFE_SETTING_REG, data, mask);
+
+	mask = HPIPE_SQ_DEGLITCH_WIDTH_P_MASK;
+	data = 0xf << HPIPE_SQ_DEGLITCH_WIDTH_P_OFFSET;
+	mask |= HPIPE_SQ_DEGLITCH_WIDTH_N_MASK;
+	data |= 0xf << HPIPE_SQ_DEGLITCH_WIDTH_N_OFFSET;
+	mask |= HPIPE_SQ_DEGLITCH_EN_MASK;
+	data |= 0x1 << HPIPE_SQ_DEGLITCH_EN_OFFSET;
+	reg_set(hpipe_addr + HPIPE_SQ_GLITCH_FILTER_CTRL, data, mask);
+
+	mask = HPIPE_CDR_LOCK_DET_EN_MASK;
+	data = 0x1 << HPIPE_CDR_LOCK_DET_EN_OFFSET;
+	reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask);
+
+	udelay(100);
+
+	/* Determine if we have a cable attached to this comphy, if not,
+	 * we can't perform RX training.
+	 */
+	data = readl(hpipe_addr + HPIPE_SQUELCH_FFE_SETTING_REG);
+	if (data & HPIPE_SQUELCH_DETECTED_MASK) {
+		pr_err("Squelsh is not detected, can't perform RX training\n");
+		return 0;
+	}
+
+	data = readl(hpipe_addr + HPIPE_LOOPBACK_REG);
+	if (!(data & HPIPE_CDR_LOCK_MASK)) {
+		pr_err("CDR is not locked, can't perform RX training\n");
+		return 0;
+	}
+
+	/* Do preparations for RX training */
+	mask = HPIPE_DFE_RES_FORCE_MASK;
+	data = 0x0 << HPIPE_DFE_RES_FORCE_OFFSET;
+	reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
+
+	mask = HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK;
+	data = 0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET;
+	mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK;
+	data |= 1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET;
+	reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
+
+	/* Performs RX training for all possible FFE (Feed Forward
+	 * Equalization, possible values are 0-7).
+	 * We update the best value reached and the FFE which gave this value.
+	 */
+	for (i = 0; i < MAX_NUM_OF_FFE; i++) {
+		rx_train_result = 0;
+		ret = comphy_cp110_test_single_ffe(ptr_chip_cfg, lane,
+						   i, &rx_train_result);
+
+		if (ret && (rx_train_result > max_rx_train)) {
+			max_rx_train = rx_train_result;
+			max_rx_train_index = i;
+		}
+	}
+
+	/* If we were able to determine which FFE gives the best value,
+	 * now we need to set it and run RX training again (only for this
+	 * FFE).
+	 */
+	if (max_rx_train) {
+		ret = comphy_cp110_test_single_ffe(ptr_chip_cfg, lane,
+						   max_rx_train_index,
+						   &rx_train_result);
+		if (ret == 1)
+			printf("RX Training passed(FFE = %d, result = 0x%x)\n",
+			       max_rx_train_index, rx_train_result);
+	} else {
+		pr_err("RX training failed\n");
+		ret = 0;
+	}
+
+	debug_exit();
+
+	return ret;
+}
+
 static int comphy_usb3_power_up(u32 lane, void __iomem *hpipe_base,
 				void __iomem *comphy_base)
 {
diff --git a/drivers/phy/marvell/comphy_hpipe.h b/drivers/phy/marvell/comphy_hpipe.h
index a692035c9417..cf2f986281ea 100644
--- a/drivers/phy/marvell/comphy_hpipe.h
+++ b/drivers/phy/marvell/comphy_hpipe.h
@@ -6,6 +6,9 @@ 
 #ifndef _COMPHY_HPIPE_H_
 #define _COMPHY_HPIPE_H_
 
+#define MAX_NUM_OF_FFE				8
+#define RX_TRAINING_TIMEOUT			500
+
 /* SerDes IP register */
 #define SD_EXTERNAL_CONFIG0_REG			0
 #define SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET	1
@@ -52,6 +55,11 @@ 
 #define SD_EXTERNAL_CONFIG2_SSC_ENABLE_MASK	\
 	(0x1 << SD_EXTERNAL_CONFIG2_SSC_ENABLE_OFFSET)
 
+#define SD_EXTERNAL_STATUS_REG				0xc
+#define SD_EXTERNAL_STATUS_START_RX_TRAINING_OFFSET	7
+#define SD_EXTERNAL_STATUS_START_RX_TRAINING_MASK	\
+	(1 << SD_EXTERNAL_STATUS_START_RX_TRAINING_OFFSET)
+
 #define SD_EXTERNAL_STATUS0_REG			0x18
 #define SD_EXTERNAL_STATUS0_PLL_TX_OFFSET	2
 #define SD_EXTERNAL_STATUS0_PLL_TX_MASK		\
@@ -66,6 +74,14 @@ 
 #define SD_EXTERNAL_STATUS0_RF_RESET_IN_MASK	\
 	(0x1 << SD_EXTERNAL_STATUS0_RF_RESET_IN_OFFSET)
 
+#define SD_EXTERNAL_STATUS1_REG			0x1c
+#define SD_EXTERNAL_STATUS1_REG_RX_TRAIN_COMP_OFFSET	0
+#define SD_EXTERNAL_STATUS1_REG_RX_TRAIN_COMP_MASK	\
+	(1 << SD_EXTERNAL_STATUS1_REG_RX_TRAIN_COMP_OFFSET)
+#define SD_EXTERNAL_STATUS1_REG_RX_TRAIN_FAILED_OFFSET	1
+#define SD_EXTERNAL_STATUS1_REG_RX_TRAIN_FAILED_MASK	\
+	(1 << SD_EXTERNAL_STATUS1_REG_RX_TRAIN_FAILED_OFFSET)
+
 /* HPIPE register */
 #define HPIPE_PWR_PLL_REG			0x4
 #define HPIPE_PWR_PLL_REF_FREQ_OFFSET		0
@@ -88,7 +104,13 @@ 
 #define HPIPE_CAL_REG_1_EXT_TXIMP_EN_MASK	\
 	(0x1 << HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET)
 
-#define HPIPE_SQUELCH_FFE_SETTING_REG           0x018
+#define HPIPE_SQUELCH_FFE_SETTING_REG           0x18
+#define HPIPE_SQUELCH_THRESH_IN_OFFSET		8
+#define HPIPE_SQUELCH_THRESH_IN_MASK		\
+	(0xf << HPIPE_SQUELCH_THRESH_IN_OFFSET)
+#define HPIPE_SQUELCH_DETECTED_OFFSET		14
+#define HPIPE_SQUELCH_DETECTED_MASK		\
+	(0x1 << HPIPE_SQUELCH_DETECTED_OFFSET)
 
 #define HPIPE_DFE_REG0				0x01C
 #define HPIPE_DFE_RES_FORCE_OFFSET		15
@@ -215,10 +237,32 @@ 
 #define HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK	\
 	(0x1 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET)
 
+#define HPIPE_PHY_TEST_CONTROL_REG		0x54
+#define HPIPE_PHY_TEST_PATTERN_SEL_OFFSET	4
+#define HPIPE_PHY_TEST_PATTERN_SEL_MASK		\
+	(0xf << HPIPE_PHY_TEST_PATTERN_SEL_OFFSET)
+#define HPIPE_PHY_TEST_RESET_OFFSET		14
+#define HPIPE_PHY_TEST_RESET_MASK		\
+	(0x1 << HPIPE_PHY_TEST_RESET_OFFSET)
+#define HPIPE_PHY_TEST_EN_OFFSET		15
+#define HPIPE_PHY_TEST_EN_MASK			\
+	(0x1 << HPIPE_PHY_TEST_EN_OFFSET)
+
+#define HPIPE_PHY_TEST_DATA_REG			0x6c
+#define HPIPE_PHY_TEST_DATA_OFFSET		0
+#define HPIPE_PHY_TEST_DATA_MASK		\
+	(0xffff << HPIPE_PHY_TEST_DATA_OFFSET)
+
 #define HPIPE_LOOPBACK_REG			0x08c
 #define HPIPE_LOOPBACK_SEL_OFFSET		1
 #define HPIPE_LOOPBACK_SEL_MASK			\
 	(0x7 << HPIPE_LOOPBACK_SEL_OFFSET)
+#define HPIPE_CDR_LOCK_OFFSET			7
+#define HPIPE_CDR_LOCK_MASK			\
+	(0x1 << HPIPE_CDR_LOCK_OFFSET)
+#define HPIPE_CDR_LOCK_DET_EN_OFFSET		8
+#define HPIPE_CDR_LOCK_DET_EN_MASK		\
+	(0x1 << HPIPE_CDR_LOCK_DET_EN_OFFSET)
 
 #define HPIPE_SYNC_PATTERN_REG                  0x090
 #define HPIPE_SYNC_PATTERN_TXD_SWAP_OFFSET	10
@@ -382,6 +426,17 @@ 
 #define HPIPE_OS_PH_VALID_MASK			\
 	(0x1 << HPIPE_OS_PH_VALID_OFFSET)
 
+#define HPIPE_SQ_GLITCH_FILTER_CTRL		0x1c8
+#define HPIPE_SQ_DEGLITCH_WIDTH_P_OFFSET	0
+#define HPIPE_SQ_DEGLITCH_WIDTH_P_MASK		\
+	(0xf << HPIPE_SQ_DEGLITCH_WIDTH_P_OFFSET)
+#define HPIPE_SQ_DEGLITCH_WIDTH_N_OFFSET	4
+#define HPIPE_SQ_DEGLITCH_WIDTH_N_MASK		\
+	(0xf << HPIPE_SQ_DEGLITCH_WIDTH_N_OFFSET)
+#define HPIPE_SQ_DEGLITCH_EN_OFFSET		8
+#define HPIPE_SQ_DEGLITCH_EN_MASK		\
+	(0x1 << HPIPE_SQ_DEGLITCH_EN_OFFSET)
+
 #define HPIPE_FRAME_DETECT_CTRL_0_REG			0x214
 #define HPIPE_TRAIN_PAT_NUM_OFFSET			0x7
 #define HPIPE_TRAIN_PAT_NUM_MASK			\
@@ -452,6 +507,11 @@ 
 #define HPIPE_TX_TRAIN_PAT_SEL_MASK		\
 	(0x1 << HPIPE_TX_TRAIN_PAT_SEL_OFFSET)
 
+#define HPIPE_SAVED_DFE_VALUES_REG             0x328
+#define HPIPE_SAVED_DFE_VALUES_SAV_F0D_OFFSET  10
+#define HPIPE_SAVED_DFE_VALUES_SAV_F0D_MASK	\
+	(0x3f << HPIPE_SAVED_DFE_VALUES_SAV_F0D_OFFSET)
+
 #define HPIPE_CDR_CONTROL_REG			0x418
 #define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET	12
 #define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_MASK	\
diff --git a/include/mvebu/comphy.h b/include/mvebu/comphy.h
index cde7a022af1c..4d1b70393b20 100644
--- a/include/mvebu/comphy.h
+++ b/include/mvebu/comphy.h
@@ -16,7 +16,7 @@  struct comphy_map {
 	bool end_point;
 };
 
+int comphy_rx_training(struct udevice *dev, u32 lane);
 int comphy_update_map(struct comphy_map *serdes_map, int count);
 
 #endif /* _MVEBU_COMPHY_H_ */
-