in drivers/ddr/marvell/a38x/ddr3_training_hw_algo.c [147:624]
int ddr3_tip_vref(u32 dev_num)
{
/*
* The Vref register have non linear order. Need to check what will be
* in future projects.
*/
u32 vref_map[8] = {
1, 2, 3, 4, 5, 6, 7, 0
};
/* State and parameter definitions */
u32 initial_step = VREF_INITIAL_STEP;
/* need to be assign with minus ????? */
u32 second_step = VREF_SECOND_STEP;
u32 algo_run_flag = 0, currrent_vref = 0;
u32 while_count = 0;
u32 pup = 0, if_id = 0, num_pup = 0, rep = 0;
u32 val = 0;
u32 reg_addr = 0xa8;
u32 copy_start_pattern, copy_end_pattern;
enum hws_result *flow_result = ddr3_tip_get_result_ptr(training_stage);
u8 res[4];
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));
/* save start/end pattern */
copy_start_pattern = start_pattern;
copy_end_pattern = end_pattern;
/* set vref as centralization pattern */
start_pattern = PATTERN_VREF;
end_pattern = PATTERN_VREF;
/* init params */
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++) {
current_vref[pup][if_id] = 0;
last_vref[pup][if_id] = 0;
lim_vref[pup][if_id] = 0;
current_valid_window[pup][if_id] = 0;
last_valid_window[pup][if_id] = 0;
if (vref_window_size[if_id][pup] >
vref_window_size_th) {
pup_st[pup][if_id] = VREF_CONVERGE;
DEBUG_TRAINING_HW_ALG(
DEBUG_LEVEL_INFO,
("VREF config, IF[ %d ]pup[ %d ] - Vref tune not requered (%d)\n",
if_id, pup, __LINE__));
} else {
pup_st[pup][if_id] = VREF_STEP_1;
CHECK_STATUS(ddr3_tip_bus_read
(dev_num, if_id,
ACCESS_TYPE_UNICAST, pup,
DDR_PHY_DATA, reg_addr, &val));
CHECK_STATUS(ddr3_tip_bus_write
(dev_num, ACCESS_TYPE_UNICAST,
if_id, ACCESS_TYPE_UNICAST,
pup, DDR_PHY_DATA, reg_addr,
(val & (~0xf)) | vref_map[0]));
DEBUG_TRAINING_HW_ALG(
DEBUG_LEVEL_INFO,
("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
if_id, pup,
(val & (~0xf)) | vref_map[0],
__LINE__));
}
}
interface_state[if_id] = 0;
}
/* TODO: Set number of active interfaces */
num_pup = octets_per_if_num * MAX_INTERFACE_NUM;
while ((algo_run_flag <= num_pup) & (while_count < 10)) {
while_count++;
for (rep = 1; rep < 4; rep++) {
ddr3_tip_centr_skip_min_win_check = 1;
ddr3_tip_centralization_rx(dev_num);
ddr3_tip_centr_skip_min_win_check = 0;
/* Read Valid window results only for non converge pups */
for (if_id = 0; if_id < MAX_INTERFACE_NUM; 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 < octets_per_if_num;
pup++) {
VALIDATE_BUS_ACTIVE
(tm->bus_act_mask, pup);
if (pup_st[pup]
[if_id] ==
VREF_CONVERGE)
continue;
current_valid_window[pup]
[if_id] =
(current_valid_window[pup]
[if_id] * (rep - 1) +
1000 * res[pup]) / rep;
}
}
}
}
for (if_id = 0; if_id < MAX_INTERFACE_NUM; 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 < octets_per_if_num; pup++) {
VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE,
("%d ",
current_valid_window
[pup][if_id]));
}
DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE, ("\n"));
}
/* Compare results and respond as function of state */
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);
DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE,
("I/F[ %d ], pup[ %d ] STATE #%d (%d)\n",
if_id, pup,
pup_st[pup]
[if_id], __LINE__));
if (pup_st[pup][if_id] == VREF_CONVERGE)
continue;
DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE,
("I/F[ %d ], pup[ %d ] CHECK progress - Current %d Last %d, limit VREF %d (%d)\n",
if_id, pup,
current_valid_window[pup]
[if_id],
last_valid_window[pup]
[if_id], lim_vref[pup]
[if_id], __LINE__));
/*
* The -1 is for solution resolution +/- 1 tap
* of ADLL
*/
if (current_valid_window[pup][if_id] + 200 >=
(last_valid_window[pup][if_id])) {
if (pup_st[pup][if_id] == VREF_STEP_1) {
/*
* We stay in the same state and
* step just update the window
* size (take the max) and Vref
*/
if (current_vref[pup]
[if_id] == VREF_MAX_INDEX) {
/*
* If we step to the end
* and didn't converge
* to some particular
* better Vref value
* define the pup as
* converge and step
* back to nominal
* Vref.
*/
pup_st[pup]
[if_id] =
VREF_CONVERGE;
algo_run_flag++;
interface_state
[if_id]++;
DEBUG_TRAINING_HW_ALG
(DEBUG_LEVEL_TRACE,
("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
if_id, pup,
current_vref[pup]
[if_id],
__LINE__));
} else {
/* continue to update the Vref index */
current_vref[pup]
[if_id] =
((current_vref[pup]
[if_id] +
initial_step) >
VREF_MAX_INDEX) ?
VREF_MAX_INDEX
: (current_vref[pup]
[if_id] +
initial_step);
if (current_vref[pup]
[if_id] ==
VREF_MAX_INDEX) {
pup_st[pup]
[if_id]
=
VREF_STEP_2;
}
lim_vref[pup]
[if_id] =
last_vref[pup]
[if_id] =
current_vref[pup]
[if_id];
}
last_valid_window[pup]
[if_id] =
GET_MAX(current_valid_window
[pup][if_id],
last_valid_window
[pup]
[if_id]);
/* update the Vref for next stage */
currrent_vref =
current_vref[pup]
[if_id];
CHECK_STATUS
(ddr3_tip_bus_read
(dev_num, if_id,
ACCESS_TYPE_UNICAST, pup,
DDR_PHY_DATA, reg_addr,
&val));
CHECK_STATUS
(ddr3_tip_bus_write
(dev_num,
ACCESS_TYPE_UNICAST,
if_id,
ACCESS_TYPE_UNICAST, pup,
DDR_PHY_DATA, reg_addr,
(val & (~0xf)) |
vref_map[currrent_vref]));
DEBUG_TRAINING_HW_ALG
(DEBUG_LEVEL_TRACE,
("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
if_id, pup,
(val & (~0xf)) |
vref_map[currrent_vref],
__LINE__));
} else if (pup_st[pup][if_id]
== VREF_STEP_2) {
/*
* We keep on search back with
* the same step size.
*/
last_valid_window[pup]
[if_id] =
GET_MAX(current_valid_window
[pup][if_id],
last_valid_window
[pup]
[if_id]);
last_vref[pup][if_id] =
current_vref[pup]
[if_id];
/* we finish all search space */
if ((current_vref[pup]
[if_id] - second_step) == lim_vref[pup][if_id]) {
/*
* If we step to the end
* and didn't converge
* to some particular
* better Vref value
* define the pup as
* converge and step
* back to nominal
* Vref.
*/
pup_st[pup]
[if_id] =
VREF_CONVERGE;
algo_run_flag++;
interface_state
[if_id]++;
current_vref[pup]
[if_id] =
(current_vref[pup]
[if_id] -
second_step);
DEBUG_TRAINING_HW_ALG
(DEBUG_LEVEL_TRACE,
("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
if_id, pup,
current_vref[pup]
[if_id],
__LINE__));
} else
/* we finish all search space */
if (current_vref[pup]
[if_id] ==
lim_vref[pup]
[if_id]) {
/*
* If we step to the end
* and didn't converge
* to some particular
* better Vref value
* define the pup as
* converge and step
* back to nominal
* Vref.
*/
pup_st[pup]
[if_id] =
VREF_CONVERGE;
algo_run_flag++;
interface_state
[if_id]++;
DEBUG_TRAINING_HW_ALG
(DEBUG_LEVEL_TRACE,
("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
if_id, pup,
current_vref[pup]
[if_id],
__LINE__));
} else {
current_vref[pup]
[if_id] =
current_vref[pup]
[if_id] -
second_step;
}
/* Update the Vref for next stage */
currrent_vref =
current_vref[pup]
[if_id];
CHECK_STATUS
(ddr3_tip_bus_read
(dev_num, if_id,
ACCESS_TYPE_UNICAST, pup,
DDR_PHY_DATA, reg_addr,
&val));
CHECK_STATUS
(ddr3_tip_bus_write
(dev_num,
ACCESS_TYPE_UNICAST,
if_id,
ACCESS_TYPE_UNICAST, pup,
DDR_PHY_DATA, reg_addr,
(val & (~0xf)) |
vref_map[currrent_vref]));
DEBUG_TRAINING_HW_ALG
(DEBUG_LEVEL_TRACE,
("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
if_id, pup,
(val & (~0xf)) |
vref_map[currrent_vref],
__LINE__));
}
} else {
/* we change state and change step */
if (pup_st[pup][if_id] == VREF_STEP_1) {
pup_st[pup][if_id] =
VREF_STEP_2;
lim_vref[pup][if_id] =
current_vref[pup]
[if_id] - initial_step;
last_valid_window[pup]
[if_id] =
current_valid_window[pup]
[if_id];
last_vref[pup][if_id] =
current_vref[pup]
[if_id];
current_vref[pup][if_id] =
last_vref[pup][if_id] -
second_step;
/* Update the Vref for next stage */
CHECK_STATUS
(ddr3_tip_bus_read
(dev_num, if_id,
ACCESS_TYPE_UNICAST, pup,
DDR_PHY_DATA, reg_addr,
&val));
CHECK_STATUS
(ddr3_tip_bus_write
(dev_num,
ACCESS_TYPE_UNICAST,
if_id,
ACCESS_TYPE_UNICAST, pup,
DDR_PHY_DATA, reg_addr,
(val & (~0xf)) |
vref_map[current_vref[pup]
[if_id]]));
DEBUG_TRAINING_HW_ALG
(DEBUG_LEVEL_TRACE,
("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
if_id, pup,
(val & (~0xf)) |
vref_map[current_vref[pup]
[if_id]],
__LINE__));
} else if (pup_st[pup][if_id] == VREF_STEP_2) {
/*
* The last search was the max
* point set value and exit
*/
CHECK_STATUS
(ddr3_tip_bus_read
(dev_num, if_id,
ACCESS_TYPE_UNICAST, pup,
DDR_PHY_DATA, reg_addr,
&val));
CHECK_STATUS
(ddr3_tip_bus_write
(dev_num,
ACCESS_TYPE_UNICAST,
if_id,
ACCESS_TYPE_UNICAST, pup,
DDR_PHY_DATA, reg_addr,
(val & (~0xf)) |
vref_map[last_vref[pup]
[if_id]]));
DEBUG_TRAINING_HW_ALG
(DEBUG_LEVEL_TRACE,
("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
if_id, pup,
(val & (~0xf)) |
vref_map[last_vref[pup]
[if_id]],
__LINE__));
pup_st[pup][if_id] =
VREF_CONVERGE;
algo_run_flag++;
interface_state[if_id]++;
DEBUG_TRAINING_HW_ALG
(DEBUG_LEVEL_TRACE,
("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
if_id, pup,
current_vref[pup]
[if_id], __LINE__));
}
}
}
}
}
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);
CHECK_STATUS(ddr3_tip_bus_read
(dev_num, if_id,
ACCESS_TYPE_UNICAST, pup,
DDR_PHY_DATA, reg_addr, &val));
DEBUG_TRAINING_HW_ALG(
DEBUG_LEVEL_INFO,
("FINAL values: I/F[ %d ], pup[ %d ] - Vref = %X (%d)\n",
if_id, pup, val, __LINE__));
}
}
flow_result[if_id] = TEST_SUCCESS;
/* restore start/end pattern */
start_pattern = copy_start_pattern;
end_pattern = copy_end_pattern;
return 0;
}