summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrzegorz Jaszczyk <jaz@semihalf.com>2018-06-29 18:00:33 +0200
committerKonstantin Porotchkin <kostap@marvell.com>2018-09-03 14:45:20 +0300
commit19bcbdba30a0cd341bca222cd1d22580db452e9e (patch)
tree682012b907c0483d0a698bd0b3e323014cf39b8a
parent2a9a98536ce82dbb047ba4948ce94f91dd4d10fb (diff)
mvebu: cp110: introduce new version of rx_training procedure
The old version of rx_training was not sufficient for all setups. Moreover some parameters was chosen manually (ffe) and then partial training was run in loop with different values and the best result was determined. With new version some steps are added but the whole training is performed by hardware. Change-Id: Iff5cd08094f969ebbbdb59176e895406f27b0e48 Signed-off-by: Grzegorz Jaszczyk <jaz@semihalf.com> Reviewed-on: http://vgitil04.il.marvell.com:8080/57529 Reviewed-by: Kostya Porotchkin <kostap@marvell.com> Reviewed-by: Igal Liberman <igall@marvell.com> Tested-by: iSoC Platform CI <ykjenk@marvell.com>
-rw-r--r--drivers/marvell/comphy/comphy-cp110.h55
-rw-r--r--drivers/marvell/comphy/phy-comphy-cp110.c304
2 files changed, 222 insertions, 137 deletions
diff --git a/drivers/marvell/comphy/comphy-cp110.h b/drivers/marvell/comphy/comphy-cp110.h
index 42cdba46..4fd4d0b5 100644
--- a/drivers/marvell/comphy/comphy-cp110.h
+++ b/drivers/marvell/comphy/comphy-cp110.h
@@ -159,6 +159,10 @@
#define HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET 15
#define HPIPE_DFE_F3_F5_DFE_CTRL_MASK (0x1 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET)
+#define HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG 0x30
+#define HPIPE_ADAPTED_DFE_RES_OFFSET 13
+#define HPIPE_ADAPTED_DFE_RES_MASK (0x3 << HPIPE_ADAPTED_DFE_RES_OFFSET)
+
#define HPIPE_G1_SET_0_REG 0x34
#define HPIPE_G1_SET_0_G1_TX_AMP_OFFSET 1
#define HPIPE_G1_SET_0_G1_TX_AMP_MASK (0x1f << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET)
@@ -249,6 +253,14 @@
#define HPIPE_PHY_TEST_DATA_OFFSET 0
#define HPIPE_PHY_TEST_DATA_MASK (0xffff << HPIPE_PHY_TEST_DATA_OFFSET)
+#define HPIPE_PHY_TEST_PRBS_ERROR_COUNTER_1_REG 0x80
+
+#define HPIPE_PHY_TEST_OOB_0_REGISTER 0x84
+#define HPIPE_PHY_PT_OOB_EN_OFFSET 14
+#define HPIPE_PHY_PT_OOB_EN_MASK (0x1 << HPIPE_PHY_PT_OOB_EN_OFFSET)
+#define HPIPE_PHY_TEST_PT_TESTMODE_OFFSET 12
+#define HPIPE_PHY_TEST_PT_TESTMODE_MASK (0x3 << HPIPE_PHY_TEST_PT_TESTMODE_OFFSET)
+
#define HPIPE_LOOPBACK_REG 0x8c
#define HPIPE_LOOPBACK_SEL_OFFSET 1
#define HPIPE_LOOPBACK_SEL_MASK (0x7 << HPIPE_LOOPBACK_SEL_OFFSET)
@@ -329,6 +341,13 @@
#define HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_OFFSET 15
#define HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_MASK (0x1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_OFFSET)
+/* HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIBRATION_CTRL_REG */
+#define HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG 0x168
+#define HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET 15
+#define HPIPE_CAL_RXCLKALIGN_90_EXT_EN_MASK (0x1 << HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET)
+#define HPIPE_CAL_OS_PH_EXT_OFFSET 8
+#define HPIPE_CAL_OS_PH_EXT_MASK (0x7f << HPIPE_CAL_OS_PH_EXT_OFFSET)
+
#define HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG 0x16C
#define HPIPE_RX_SAMPLER_OS_GAIN_OFFSET 6
#define HPIPE_RX_SAMPLER_OS_GAIN_MASK (0x3 << HPIPE_RX_SAMPLER_OS_GAIN_OFFSET)
@@ -365,6 +384,16 @@
#define HPIPE_OS_PH_VALID_OFFSET 8
#define HPIPE_OS_PH_VALID_MASK (0x1 << HPIPE_OS_PH_VALID_OFFSET)
+#define HPIPE_DATA_PHASE_OFF_CTRL_REG 0x1A0
+#define HPIPE_DATA_PHASE_ADAPTED_OS_PH_OFFSET 9
+#define HPIPE_DATA_PHASE_ADAPTED_OS_PH_MASK (0x7f << HPIPE_DATA_PHASE_ADAPTED_OS_PH_OFFSET)
+
+#define HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG 0x1A4
+#define HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_OFFSET 12
+#define HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_MASK (0x3 << HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_OFFSET)
+#define HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_OFFSET 8
+#define HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_MASK (0xf << HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_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)
@@ -385,6 +414,20 @@
#define HPIPE_DME_ETHERNET_MODE_OFFSET 7
#define HPIPE_DME_ETHERNET_MODE_MASK (0x1 << HPIPE_DME_ETHERNET_MODE_OFFSET)
+#define HPIPE_TRX_TRAIN_CTRL_0_REG 0x22c
+#define HPIPE_TRX_TX_F0T_EO_BASED_OFFSET 14
+#define HPIPE_TRX_TX_F0T_EO_BASED_MASK (1 << HPIPE_TRX_TX_F0T_EO_BASED_OFFSET)
+#define HPIPE_TRX_UPDATE_THEN_HOLD_OFFSET 6
+#define HPIPE_TRX_UPDATE_THEN_HOLD_MASK (1 << HPIPE_TRX_UPDATE_THEN_HOLD_OFFSET)
+#define HPIPE_TRX_TX_CTRL_CLK_EN_OFFSET 5
+#define HPIPE_TRX_TX_CTRL_CLK_EN_MASK (1 << HPIPE_TRX_TX_CTRL_CLK_EN_OFFSET)
+#define HPIPE_TRX_RX_ANA_IF_CLK_ENE_OFFSET 4
+#define HPIPE_TRX_RX_ANA_IF_CLK_ENE_MASK (1 << HPIPE_TRX_RX_ANA_IF_CLK_ENE_OFFSET)
+#define HPIPE_TRX_TX_TRAIN_EN_OFFSET 1
+#define HPIPE_TRX_TX_TRAIN_EN_MASK (1 << HPIPE_TRX_TX_TRAIN_EN_OFFSET)
+#define HPIPE_TRX_RX_TRAIN_EN_OFFSET 0
+#define HPIPE_TRX_RX_TRAIN_EN_MASK (1 << HPIPE_TRX_RX_TRAIN_EN_OFFSET)
+
#define HPIPE_TX_TRAIN_CTRL_0_REG 0x268
#define HPIPE_TX_TRAIN_P2P_HOLD_OFFSET 15
#define HPIPE_TX_TRAIN_P2P_HOLD_MASK (0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET)
@@ -413,6 +456,18 @@
#define HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET 14
#define HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK (0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET)
+#define HPIPE_INTERRUPT_1_REGISTER 0x2AC
+#define HPIPE_TRX_TRAIN_FAILED_OFFSET 6
+#define HPIPE_TRX_TRAIN_FAILED_MASK (1 << HPIPE_TRX_TRAIN_FAILED_OFFSET)
+#define HPIPE_TRX_TRAIN_TIME_OUT_INT_OFFSET 5
+#define HPIPE_TRX_TRAIN_TIME_OUT_INT_MASK (1 << HPIPE_TRX_TRAIN_TIME_OUT_INT_OFFSET)
+#define HPIPE_INTERRUPT_TRX_TRAIN_DONE_OFFSET 4
+#define HPIPE_INTERRUPT_TRX_TRAIN_DONE_MASK (1 << HPIPE_INTERRUPT_TRX_TRAIN_DONE_OFFSET)
+#define HPIPE_INTERRUPT_DFE_DONE_INT_OFFSET 3
+#define HPIPE_INTERRUPT_DFE_DONE_INT_MASK (1 << HPIPE_INTERRUPT_DFE_DONE_INT_OFFSET)
+#define HPIPE_INTERRUPT_RX_TRAIN_COMPLETE_INT_OFFSET 1
+#define HPIPE_INTERRUPT_RX_TRAIN_COMPLETE_INT_MASK (1 << HPIPE_INTERRUPT_RX_TRAIN_COMPLETE_INT_OFFSET)
+
#define HPIPE_TX_TRAIN_REG 0x31C
#define HPIPE_TX_TRAIN_CHK_INIT_OFFSET 4
#define HPIPE_TX_TRAIN_CHK_INIT_MASK (0x1 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET)
diff --git a/drivers/marvell/comphy/phy-comphy-cp110.c b/drivers/marvell/comphy/phy-comphy-cp110.c
index bacfad78..13d1405d 100644
--- a/drivers/marvell/comphy/phy-comphy-cp110.c
+++ b/drivers/marvell/comphy/phy-comphy-cp110.c
@@ -1889,191 +1889,221 @@ static int mvebu_cp110_comphy_usb3_power_on(uint64_t comphy_base,
return ret;
}
-/* This function performs RX training for one Feed Forward Equalization (FFE)
- * value.
- * The RX traiing result is stored in 'Saved DFE values Register' (SAV_F0D).
- *
- * Return '0' on success, error code in a case of failure.
- */
-static int mvebu_cp110_comphy_test_single_ffe(uint64_t comphy_base,
- uint8_t comphy_index,
- uint32_t ffe, uint32_t *result)
+int mvebu_cp110_comphy_xfi_rx_training(uint64_t comphy_base,
+ uint8_t comphy_index)
{
- uint32_t mask, data, timeout;
+ uint32_t mask, data, timeout, ffe_cap, ffe_res, align90, adapted_dfe;
uintptr_t hpipe_addr, sd_ip_addr;
hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
comphy_index);
-
sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), comphy_index);
+ debug_enter();
+
+ debug("stage: RF Reset\n");
+
+ /* Release from hard reset */
+ mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
+ data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
+ data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK;
+ data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
+
+ mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK;
+ data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET;
+ mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK;
+ data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET;
+ reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask);
+
+ /* Wait 50ms - until band gap and ref clock ready */
+ mdelay(50);
+
+ debug("Preparation for rx_training\n\n");
+
+ /* Use the FFE table */
+ mask = HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK;
+ data = 0 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
+
+ /* Use auto-calibration value */
+ mask = HPIPE_CAL_RXCLKALIGN_90_EXT_EN_MASK;
+ data = 0 << HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG, data, mask);
+
+ /* Use Tx/Rx training results */
+ mask = HPIPE_DFE_RES_FORCE_MASK;
+ data = 0 << HPIPE_DFE_RES_FORCE_OFFSET;
+ reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
+
+ debug("PRBS31 loppback\n\n");
+
/* 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;
+ data = 0xc4 << 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);
+ mdelay(10);
+ debug("Enable TX/RX training\n\n");
+
+ mask = HPIPE_TRX_RX_TRAIN_EN_MASK;
+ data = 0x1 << HPIPE_TRX_RX_TRAIN_EN_OFFSET;
+ mask |= HPIPE_TRX_RX_ANA_IF_CLK_ENE_MASK;
+ data |= 0x1 << HPIPE_TRX_RX_ANA_IF_CLK_ENE_OFFSET;
+ mask |= HPIPE_TRX_TX_CTRL_CLK_EN_MASK;
+ data |= 0x1 << HPIPE_TRX_TX_CTRL_CLK_EN_OFFSET;
+ mask |= HPIPE_TRX_UPDATE_THEN_HOLD_MASK;
+ data |= 0x1 << HPIPE_TRX_UPDATE_THEN_HOLD_OFFSET;
+ mask |= HPIPE_TRX_TX_F0T_EO_BASED_MASK;
+ data |= 0x1 << HPIPE_TRX_TX_F0T_EO_BASED_OFFSET;
+ reg_set(hpipe_addr + HPIPE_TRX_TRAIN_CTRL_0_REG, data, mask);
/* Check the result of RX training */
timeout = RX_TRAINING_TIMEOUT;
+ mask = HPIPE_INTERRUPT_TRX_TRAIN_DONE_OFFSET |
+ HPIPE_INTERRUPT_DFE_DONE_INT_OFFSET |
+ HPIPE_INTERRUPT_RX_TRAIN_COMPLETE_INT_MASK;
while (timeout) {
- data = mmio_read_32(sd_ip_addr + SD_EXTERNAL_STATAUS1_REG);
- if (data & SD_EXTERNAL_STATAUS1_REG_RX_TRAIN_COMP_MASK)
+ data = mmio_read_32(hpipe_addr + HPIPE_INTERRUPT_1_REGISTER);
+ if (data & mask)
break;
mdelay(1);
timeout--;
}
- if (timeout == 0)
+ debug("RX training result: interrupt reg 0x%lx = 0x%x\n\n",
+ hpipe_addr + HPIPE_INTERRUPT_1_REGISTER, data);
+
+ if (timeout == 0 || data & HPIPE_TRX_TRAIN_TIME_OUT_INT_MASK) {
+ ERROR("Rx training timeout...\n");
return -ETIMEDOUT;
+ }
- if (data & SD_EXTERNAL_STATAUS1_REG_RX_TRAIN_FAILED_MASK)
+ if (data & HPIPE_TRX_TRAIN_FAILED_MASK) {
+ ERROR("Rx training failed...\n");
return -EINVAL;
+ }
- /* 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 = mmio_read_32(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;
+ mask = HPIPE_TRX_RX_TRAIN_EN_MASK;
+ data = 0x0 << HPIPE_TRX_RX_TRAIN_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_TRX_TRAIN_CTRL_0_REG, data, mask);
+
+ debug("Training done, reading results...\n\n");
+
+ mask = HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_MASK;
+ ffe_res = ((mmio_read_32(hpipe_addr + HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG)
+ & mask) >> HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_OFFSET);
+
+ mask = HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_MASK;
+ ffe_cap = ((mmio_read_32(hpipe_addr + HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG)
+ & mask) >> HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_OFFSET);
+
+ mask = HPIPE_DATA_PHASE_ADAPTED_OS_PH_MASK;
+ align90 = ((mmio_read_32(hpipe_addr + HPIPE_DATA_PHASE_OFF_CTRL_REG)
+ & mask) >> HPIPE_DATA_PHASE_ADAPTED_OS_PH_OFFSET);
+
+ mask = HPIPE_ADAPTED_DFE_RES_MASK;
+ adapted_dfe = ((mmio_read_32(hpipe_addr + HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG)
+ & mask) >> HPIPE_ADAPTED_DFE_RES_OFFSET);
+
+ debug("================================================\n");
+ debug("Switching to static configuration:\n");
+ debug("FFE_RES = 0x%x FFE_CAP = 0x%x align90 = 0x%x adapted_dfe 0x%x\n",
+ ffe_res, ffe_cap, align90, adapted_dfe);
+ debug("Full results after training: 0x%lx = 0x%x, 0x%lx = 0x%x, 0x%lx = 0x%x\n",
+ (hpipe_addr + HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG),
+ mmio_read_32(hpipe_addr + HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG),
+ (hpipe_addr + HPIPE_DATA_PHASE_OFF_CTRL_REG),
+ mmio_read_32(hpipe_addr + HPIPE_DATA_PHASE_OFF_CTRL_REG),
+ (hpipe_addr + HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG),
+ mmio_read_32(hpipe_addr + HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG));
+ debug("================================================\n");
+
+ /* Update FFE_RES */
+ mask = HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK;
+ data = ffe_res << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask);
- 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);
+ /* Update FFE_CAP */
+ mask = HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK;
+ data = ffe_cap << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_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);
+ /* Bypass the FFE table settings and use the FFE settings directly from
+ * registers FFE_RES_SEL and FFE_CAP_SEL
+ */
+ 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);
- return 0;
-}
+ /* Use the value from CAL_OS_PH_EXT */
+ mask = HPIPE_CAL_RXCLKALIGN_90_EXT_EN_MASK;
+ data = 1 << HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG, data, mask);
-/* This function runs complete RX training sequence:
- * - Run RX training for all possible Feed Forward Equalization values
- * - Choose the FFE which gives the best result.
- * - Run RX training again with the best result.
- *
- * Return '0' on success, error code in a case of failure.
- */
-int mvebu_cp110_comphy_xfi_rx_training(uint64_t comphy_base,
- uint8_t comphy_index)
-{
- uint32_t mask, data, max_rx_train = 0, max_rx_train_index = 0;
- uintptr_t hpipe_addr;
- uint32_t rx_train_result;
- int ret, i;
+ /* Update align90 */
+ mask = HPIPE_CAL_OS_PH_EXT_MASK;
+ data = align90 << HPIPE_CAL_OS_PH_EXT_OFFSET;
+ reg_set(hpipe_addr + HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG, data, mask);
- hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base),
- comphy_index);
+ /* Force DFE resolution (use gen table value) */
+ mask = HPIPE_DFE_RES_FORCE_MASK;
+ data = 0x0 << HPIPE_DFE_RES_FORCE_OFFSET;
+ reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask);
- debug_enter();
+ /* 0x111-G1 DFE_Setting_4 */
+ mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK;
+ data = adapted_dfe << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET;
+ reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask);
- /* 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);
+ debug("PRBS31 loppback\n\n");
- udelay(100);
+ mask = HPIPE_PHY_TEST_PT_TESTMODE_MASK;
+ data = 0x1 << HPIPE_PHY_TEST_PT_TESTMODE_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PHY_TEST_OOB_0_REGISTER, data, mask);
- /* Determine if we have a cable attached to this comphy, if not,
- * we can't perform RX training.
- */
- data = mmio_read_32(hpipe_addr + HPIPE_SQUELCH_FFE_SETTING_REG);
- if (data & HPIPE_SQUELCH_DETECTED_MASK) {
- ERROR("Squelsh is not detected, can't perform RX training\n");
- return -EINVAL;
- }
+ /* 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);
- data = mmio_read_32(hpipe_addr + HPIPE_LOOPBACK_REG);
- if (!(data & HPIPE_CDR_LOCK_MASK)) {
- ERROR("CDR is not locked, can't perform RX training\n");
- return -EINVAL;
- }
+ mask = HPIPE_PHY_TEST_DATA_MASK;
+ data = 0xc4 << HPIPE_PHY_TEST_DATA_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PHY_TEST_DATA_REG, data, mask);
- /* 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_PHY_TEST_EN_MASK;
+ data = 0x1 << HPIPE_PHY_TEST_EN_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, 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);
+ /* Reset PRBS error counter */
+ mask = HPIPE_PHY_TEST_PATTERN_SEL_MASK;
+ data = 0x1 << HPIPE_PHY_TEST_RESET_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
- /* Perform 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 = mvebu_cp110_comphy_test_single_ffe(comphy_base,
- comphy_index, i,
- &rx_train_result);
-
- if ((!ret) && (rx_train_result > max_rx_train)) {
- max_rx_train = rx_train_result;
- max_rx_train_index = i;
- }
- }
+ mask = HPIPE_PHY_TEST_PATTERN_SEL_MASK;
+ data = 0x0 << HPIPE_PHY_TEST_RESET_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PHY_TEST_CONTROL_REG, data, mask);
- /* 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 = mvebu_cp110_comphy_test_single_ffe(comphy_base,
- comphy_index,
- max_rx_train_index,
- &rx_train_result);
-
- if (ret == 0)
- debug("RX Training passed (FFE = %d, result = 0x%x)\n",
- max_rx_train_index, rx_train_result);
- } else {
- ERROR("RX Training failed for comphy%d\n", comphy_index);
- ret = -EINVAL;
- }
+ mask = HPIPE_PHY_TEST_PT_TESTMODE_MASK;
+ data = 0x1 << HPIPE_PHY_TEST_PT_TESTMODE_OFFSET;
+ reg_set(hpipe_addr + HPIPE_PHY_TEST_OOB_0_REGISTER, data, mask);
- debug_exit();
+ /* check */
+ debug("PRBS error counter[0x%lx] 0x%x\n\n",
+ hpipe_addr + HPIPE_PHY_TEST_PRBS_ERROR_COUNTER_1_REG,
+ mmio_read_32(hpipe_addr + HPIPE_PHY_TEST_PRBS_ERROR_COUNTER_1_REG));
- return ret;
+ return 0;
}
/* During AP the proper mode is auto-negotiated and the mac, pcs and serdes