Skip to content

Commit

Permalink
arch/risc-v/src/mpfs/mpfs_ddr.c: Re-write write calibration
Browse files Browse the repository at this point in the history
Clean up the code and remove un-used global variables & structs

Signed-off-by: Jukka Laitinen <[email protected]>
  • Loading branch information
jlaitine committed Aug 29, 2023
1 parent c356bfb commit 3ce090e
Showing 1 changed file with 51 additions and 145 deletions.
196 changes: 51 additions & 145 deletions arch/risc-v/src/mpfs/mpfs_ddr.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,37 +192,6 @@ enum ddr_access_size_e
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
{
uint32_t tip_cfg_params;
Expand All @@ -238,8 +207,6 @@ struct mpfs_ddr_priv_s
* Private Data
****************************************************************************/

static mss_ddr_calibration_t calib_data;

static struct mpfs_ddr_priv_s g_mpfs_ddr_priv =
{
.en_addcmd0_ovrt9 = true,
Expand Down Expand Up @@ -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);

/* Write TXDLY offset data. 0x14 is a constant copied from HSS reference code, it is
* unknown whether this needs to be adjustable at the moment
/* Write TXDLY offset data. 0x14 is a constant copied from HSS reference
* code, it is unknown whether this needs to be adjustable at the moment
*/

putreg32(0x14, MPFS_CFG_DDR_SGMII_PHY_RPC226);
Expand Down Expand Up @@ -1731,8 +1698,6 @@ static void mpfs_load_dq(uint8_t lane)
{
modifyreg32(MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1, 0x0f, 0);
}

putreg32(0x08, MPFS_CFG_DDR_SGMII_PHY_EXPERT_MODE_EN);
}
#endif

Expand Down Expand Up @@ -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);
}

/* 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 */

putreg32(0, MPFS_DDR_CSR_APB_MT_EN_SINGLE);
Expand Down Expand Up @@ -1969,6 +1928,7 @@ static int mpfs_mtc_test_all(uint8_t mask, uint64_t start_address,

/* Test all patterns except MTC_USER */

result = 0;
for (test_pattern = MTC_COUNTING_PATTERN;
test_pattern <= MTC_PSEUDO_RANDOM_8BIT && result == 0;
test_pattern++)
Expand All @@ -1988,50 +1948,6 @@ static int mpfs_mtc_test_all(uint8_t mask, uint64_t start_address,
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
*
Expand All @@ -2054,17 +1970,24 @@ static int mpfs_write_calibration_using_mtc(struct mpfs_ddr_priv_s *priv)
uint64_t start_address = 0x00;
uint32_t size = ONE_MB_MTC;
int result = 0;
uint8_t lane_to_test;
uint8_t done = 0x0;
uint8_t lane;
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. */

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
* Explanation: A register, expert_wrcalib, is described in MSS DDR TIP
Expand All @@ -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.
*/

for (cal_data = 0x00000; cal_data < 0xfffff && result != -ETIMEDOUT;
for (cal_data = 0x00000;
cal_data < 0xfffff && done != done_mask && result != -ETIMEDOUT;
cal_data += 0x11111)
{
putreg32(cal_data, MPFS_CFG_DDR_SGMII_PHY_EXPERT_WRCALIB);

for (lane_to_test = 0x00;
lane_to_test < lanes && result != -ETIMEDOUT;
lane_to_test++)
for (lane = 0; lane < lanes && result != -ETIMEDOUT; lane++)
{
uint8_t mask = (uint8_t)(1 << lane_to_test);
result = mpfs_mtc_test_all(mask, start_address, size,
MTC_ADD_SEQUENTIAL);

if (result == 0) /* if passed for this lane */
{
if ((calib_data.write_cal.status_lower &
(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);
}
uint8_t cal_value = cal_data & 0xf;
uint8_t mask = (uint8_t)(0x1 << lane);

/* Check the result */
/* Check if this lane is not yet done and the test passes */

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;
}
}
if (!(done & (0x1 << lane)))
{
/* First passing value is the offset point, record it */

result = mpfs_mtc_test_all(mask, start_address, size,
MTC_ADD_SEQUENTIAL);
if (result == 0)
{
/* We're good for all lanes, can stop */

break;
offset[lane] = cal_value;
done |= 1 << lane;
}
}
}
}

if (result == 0)
{
/* if true, we are good for all lanes, can stop searching */
/* If calibration was successful, calculate and set the value */

break;
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);
}
}

/* If calibration successful, calculate and set the value */
/* Set the write calibration which has been calculated */

if (result == 0)
putreg32(cal_data,
MPFS_CFG_DDR_SGMII_PHY_EXPERT_WRCALIB);
}
else if (result == 0)
{
/* Set the write calibration which has been calculated */
/* Just in case calibration is not done but last result from lane test
* was OK
*/

mpfs_set_write_calib(priv);
result = 1;
}

return result;
Expand Down Expand Up @@ -3076,8 +2988,6 @@ static void mpfs_ddr_sm_init(struct mpfs_ddr_priv_s *priv)
priv->refclk_sweep_index = 0xf;

priv->number_of_lanes_to_calibrate = mpfs_get_num_lanes();

memset(&calib_data, 0, sizeof(calib_data));
}

/****************************************************************************
Expand All @@ -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)
{
memset(&calib_data, 0, sizeof(calib_data));

putreg32(0, MPFS_DDR_CSR_APB_PHY_DFI_INIT_START);

/* Reset controller */
Expand Down Expand Up @@ -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 */

#ifdef CONFIG_MPFS_DDR_TYPE_LPDDR4
uint32_t nr_lanes;
uint8_t lane;

/* Changed default value to centre dq/dqs on window */

putreg32(0x0c, MPFS_CFG_DDR_SGMII_PHY_RPC220);

nr_lanes = mpfs_get_num_lanes();
for (lane = 0; lane < nr_lanes; lane++)
for (lane = 0; lane < priv->number_of_lanes_to_calibrate; lane++)
{
mpfs_load_dq(lane);
}
Expand Down

0 comments on commit 3ce090e

Please sign in to comment.