arch/risc-v/src/mpfs/mpfs_ddr.c: Re-write write calibration

Clean up the code and remove un-used global variables & structs

Signed-off-by: Jukka Laitinen <jukkax@ssrc.tii.ae>
This commit is contained in:
Jukka Laitinen 2023-08-27 14:41:06 +03:00 committed by Petro Karashchenko
parent f10dab5531
commit 697472dc07

View File

@ -192,37 +192,6 @@ enum ddr_access_size_e
DDR_64_BIT DDR_64_BIT
}; };
typedef struct
{
uint32_t status_lower;
uint32_t status_upper;
uint32_t lower;
uint32_t upper;
uint32_t vref_result;
} mss_ddr_vref_t;
typedef struct
{
uint32_t status_lower;
uint32_t lower[MAX_LANES];
uint32_t lane_calib_result;
} mss_mpfs_ddr_write_calibration_t;
typedef struct
{
uint32_t lower[MAX_LANES];
uint32_t upper[MAX_LANES];
uint32_t calibration_found[MAX_LANES];
} mss_lpddr4_dq_calibration_t;
typedef struct
{
mss_mpfs_ddr_write_calibration_t write_cal;
mss_lpddr4_dq_calibration_t dq_cal;
mss_ddr_vref_t fpga_vref;
mss_ddr_vref_t mem_vref;
} mss_ddr_calibration_t;
struct mpfs_ddr_priv_s struct mpfs_ddr_priv_s
{ {
uint32_t tip_cfg_params; uint32_t tip_cfg_params;
@ -238,8 +207,6 @@ struct mpfs_ddr_priv_s
* Private Data * Private Data
****************************************************************************/ ****************************************************************************/
static mss_ddr_calibration_t calib_data;
static struct mpfs_ddr_priv_s g_mpfs_ddr_priv = static struct mpfs_ddr_priv_s g_mpfs_ddr_priv =
{ {
.en_addcmd0_ovrt9 = true, .en_addcmd0_ovrt9 = true,
@ -582,8 +549,8 @@ static void mpfs_set_ddr_rpc_regs(struct mpfs_ddr_priv_s *priv)
putreg32(0x04, MPFS_CFG_DDR_SGMII_PHY_RPC98); putreg32(0x04, MPFS_CFG_DDR_SGMII_PHY_RPC98);
/* Write TXDLY offset data. 0x14 is a constant copied from HSS reference code, it is /* Write TXDLY offset data. 0x14 is a constant copied from HSS reference
* unknown whether this needs to be adjustable at the moment * code, it is unknown whether this needs to be adjustable at the moment
*/ */
putreg32(0x14, MPFS_CFG_DDR_SGMII_PHY_RPC226); putreg32(0x14, MPFS_CFG_DDR_SGMII_PHY_RPC226);
@ -1731,8 +1698,6 @@ static void mpfs_load_dq(uint8_t lane)
{ {
modifyreg32(MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1, 0x0f, 0); modifyreg32(MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1, 0x0f, 0);
} }
putreg32(0x08, MPFS_CFG_DDR_SGMII_PHY_EXPERT_MODE_EN);
} }
#endif #endif
@ -1900,12 +1865,6 @@ static int mpfs_mtc_test(uint8_t mask, uint64_t start_address,
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_4, 0x0000f000, 0); modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_4, 0x0000f000, 0);
} }
/* MT_EN - Enables memory test. If asserted at end of memory test,
* will keep going.
*/
putreg32(0, MPFS_DDR_CSR_APB_MT_EN);
/* MT_EN_SINGLE - Will not repeat if this is set */ /* MT_EN_SINGLE - Will not repeat if this is set */
putreg32(0, MPFS_DDR_CSR_APB_MT_EN_SINGLE); putreg32(0, MPFS_DDR_CSR_APB_MT_EN_SINGLE);
@ -1969,6 +1928,7 @@ static int mpfs_mtc_test_all(uint8_t mask, uint64_t start_address,
/* Test all patterns except MTC_USER */ /* Test all patterns except MTC_USER */
result = 0;
for (test_pattern = MTC_COUNTING_PATTERN; for (test_pattern = MTC_COUNTING_PATTERN;
test_pattern <= MTC_PSEUDO_RANDOM_8BIT && result == 0; test_pattern <= MTC_PSEUDO_RANDOM_8BIT && result == 0;
test_pattern++) test_pattern++)
@ -1988,50 +1948,6 @@ static int mpfs_mtc_test_all(uint8_t mask, uint64_t start_address,
return result; return result;
} }
/****************************************************************************
* Name: mpfs_set_write_calib
*
* Description:
* Sets and stores the calibrated values.
*
* Input Parameters:
* priv - Instance of the ddr private state structure
*
* Returned Value:
* Zero (OK) is returned on success. A nonzero value indicates a fail.
*
****************************************************************************/
static void mpfs_set_write_calib(struct mpfs_ddr_priv_s *priv)
{
uint32_t temp = 0;
uint8_t lane_to_set;
uint8_t shift = 0;
uint32_t lanes = priv->number_of_lanes_to_calibrate;
/* Calculate the calibrated value and write back */
calib_data.write_cal.lane_calib_result = 0;
for (lane_to_set = 0; lane_to_set < lanes; lane_to_set++)
{
temp = calib_data.write_cal.lower[lane_to_set];
calib_data.write_cal.lane_calib_result = \
calib_data.write_cal.lane_calib_result | (temp << (shift));
shift = (uint8_t)(shift + 0x04);
}
/* bit 3 must be set if we want to use the expert_wrcalib
* register.
*/
putreg32(0x08, MPFS_CFG_DDR_SGMII_PHY_EXPERT_MODE_EN);
/* Set the calibrated value */
putreg32(calib_data.write_cal.lane_calib_result,
MPFS_CFG_DDR_SGMII_PHY_EXPERT_WRCALIB);
}
/**************************************************************************** /****************************************************************************
* Name: mpfs_write_calibration_using_mtc * Name: mpfs_write_calibration_using_mtc
* *
@ -2054,17 +1970,24 @@ static int mpfs_write_calibration_using_mtc(struct mpfs_ddr_priv_s *priv)
uint64_t start_address = 0x00; uint64_t start_address = 0x00;
uint32_t size = ONE_MB_MTC; uint32_t size = ONE_MB_MTC;
int result = 0; int result = 0;
uint8_t lane_to_test; uint8_t done = 0x0;
uint8_t lane;
uint32_t cal_data; uint32_t cal_data;
uint32_t lanes; int lanes;
uint8_t offset[MAX_LANES];
uint8_t done_mask;
calib_data.write_cal.status_lower = 0U; /* Initialize number of lanes */
lanes = priv->number_of_lanes_to_calibrate;
/* Bit 3 must be set if we want to use the expert_wrcalib register. */ /* Bit 3 must be set if we want to use the expert_wrcalib register. */
putreg32(0x08, MPFS_CFG_DDR_SGMII_PHY_EXPERT_MODE_EN); putreg32(0x08, MPFS_CFG_DDR_SGMII_PHY_EXPERT_MODE_EN);
lanes = priv->number_of_lanes_to_calibrate; /* mask of as many 1 bits as there are lanes */
done_mask = 0xff >> (8 - lanes);
/* Training carried out here: sweeping write calibration offset from 0 to F /* Training carried out here: sweeping write calibration offset from 0 to F
* Explanation: A register, expert_wrcalib, is described in MSS DDR TIP * Explanation: A register, expert_wrcalib, is described in MSS DDR TIP
@ -2073,73 +1996,62 @@ static int mpfs_write_calibration_using_mtc(struct mpfs_ddr_priv_s *priv)
* with the respect to the address and command for each lane. * with the respect to the address and command for each lane.
*/ */
for (cal_data = 0x00000; cal_data < 0xfffff && result != -ETIMEDOUT; for (cal_data = 0x00000;
cal_data < 0xfffff && done != done_mask && result != -ETIMEDOUT;
cal_data += 0x11111) cal_data += 0x11111)
{ {
putreg32(cal_data, MPFS_CFG_DDR_SGMII_PHY_EXPERT_WRCALIB); putreg32(cal_data, MPFS_CFG_DDR_SGMII_PHY_EXPERT_WRCALIB);
for (lane_to_test = 0x00; for (lane = 0; lane < lanes && result != -ETIMEDOUT; lane++)
lane_to_test < lanes && result != -ETIMEDOUT;
lane_to_test++)
{ {
uint8_t mask = (uint8_t)(1 << lane_to_test); uint8_t cal_value = cal_data & 0xf;
result = mpfs_mtc_test_all(mask, start_address, size, uint8_t mask = (uint8_t)(0x1 << lane);
MTC_ADD_SEQUENTIAL);
if (result == 0) /* if passed for this lane */ /* Check if this lane is not yet done and the test passes */
if (!(done & (0x1 << lane)))
{ {
if ((calib_data.write_cal.status_lower & /* First passing value is the offset point, record it */
(0x01 << lane_to_test)) == 0)
{
/* Still looking for good value */
calib_data.write_cal.lower[lane_to_test] =
(cal_data & 0xf);
calib_data.write_cal.status_lower |=
(0x01 << lane_to_test);
}
/* Check the result */
uint32_t lane_to_check;
for (lane_to_check = 0; lane_to_check < lanes;
lane_to_check++)
{
if (((calib_data.write_cal.status_lower) &
(0x01 << lane_to_check)) == 0)
{
/* not finished, still looking */
result = 1;
break;
}
}
result = mpfs_mtc_test_all(mask, start_address, size,
MTC_ADD_SEQUENTIAL);
if (result == 0) if (result == 0)
{ {
/* We're good for all lanes, can stop */ offset[lane] = cal_value;
done |= 1 << lane;
break;
} }
} }
} }
if (result == 0)
{
/* if true, we are good for all lanes, can stop searching */
break;
}
} }
/* If calibration successful, calculate and set the value */ /* If calibration was successful, calculate and set the value */
if (result == 0) if (done == done_mask)
{ {
/* Calibration succeeded, set the result */
result = 0;
/* Create cal_data mask from individua lane offsets */
cal_data = 0x0;
for (lane = 0; lane < lanes; lane++)
{
cal_data |= offset[lane] << (lane * 4);
}
/* Set the write calibration which has been calculated */ /* Set the write calibration which has been calculated */
mpfs_set_write_calib(priv); putreg32(cal_data,
MPFS_CFG_DDR_SGMII_PHY_EXPERT_WRCALIB);
}
else if (result == 0)
{
/* Just in case calibration is not done but last result from lane test
* was OK
*/
result = 1;
} }
return result; return result;
@ -3076,8 +2988,6 @@ static void mpfs_ddr_sm_init(struct mpfs_ddr_priv_s *priv)
priv->refclk_sweep_index = 0xf; priv->refclk_sweep_index = 0xf;
priv->number_of_lanes_to_calibrate = mpfs_get_num_lanes(); priv->number_of_lanes_to_calibrate = mpfs_get_num_lanes();
memset(&calib_data, 0, sizeof(calib_data));
} }
/**************************************************************************** /****************************************************************************
@ -3094,8 +3004,6 @@ static void mpfs_ddr_sm_init(struct mpfs_ddr_priv_s *priv)
static void mpfs_ddr_fail(struct mpfs_ddr_priv_s *priv) static void mpfs_ddr_fail(struct mpfs_ddr_priv_s *priv)
{ {
memset(&calib_data, 0, sizeof(calib_data));
putreg32(0, MPFS_DDR_CSR_APB_PHY_DFI_INIT_START); putreg32(0, MPFS_DDR_CSR_APB_PHY_DFI_INIT_START);
/* Reset controller */ /* Reset controller */
@ -3774,15 +3682,13 @@ static int mpfs_training_write_calibration(struct mpfs_ddr_priv_s *priv)
/* Now start the write calibration as training has been successful */ /* Now start the write calibration as training has been successful */
#ifdef CONFIG_MPFS_DDR_TYPE_LPDDR4 #ifdef CONFIG_MPFS_DDR_TYPE_LPDDR4
uint32_t nr_lanes;
uint8_t lane; uint8_t lane;
/* Changed default value to centre dq/dqs on window */ /* Changed default value to centre dq/dqs on window */
putreg32(0x0c, MPFS_CFG_DDR_SGMII_PHY_RPC220); putreg32(0x0c, MPFS_CFG_DDR_SGMII_PHY_RPC220);
nr_lanes = mpfs_get_num_lanes(); for (lane = 0; lane < priv->number_of_lanes_to_calibrate; lane++)
for (lane = 0; lane < nr_lanes; lane++)
{ {
mpfs_load_dq(lane); mpfs_load_dq(lane);
} }