mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-19 19:28:36 +00:00
996 lines
30 KiB
C
996 lines
30 KiB
C
|
/*
|
||
|
* Copyright (C) Marvell International Ltd. and its affiliates
|
||
|
*
|
||
|
* SPDX-License-Identifier: GPL-2.0
|
||
|
*/
|
||
|
|
||
|
#include <common.h>
|
||
|
#include <spl.h>
|
||
|
#include <asm/io.h>
|
||
|
#include <asm/arch/cpu.h>
|
||
|
#include <asm/arch/soc.h>
|
||
|
|
||
|
#include "ddr3_init.h"
|
||
|
|
||
|
#define TYPICAL_PBS_VALUE 12
|
||
|
|
||
|
u32 nominal_adll[MAX_INTERFACE_NUM * MAX_BUS_NUM];
|
||
|
enum hws_training_ip_stat train_status[MAX_INTERFACE_NUM];
|
||
|
u8 result_mat[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
|
||
|
u8 result_mat_rx_dqs[MAX_INTERFACE_NUM][MAX_BUS_NUM][MAX_CS_NUM];
|
||
|
/* 4-EEWA, 3-EWA, 2-SWA, 1-Fail, 0-Pass */
|
||
|
u8 result_all_bit[MAX_BUS_NUM * BUS_WIDTH_IN_BITS * MAX_INTERFACE_NUM];
|
||
|
u8 max_pbs_per_pup[MAX_INTERFACE_NUM][MAX_BUS_NUM];
|
||
|
u8 min_pbs_per_pup[MAX_INTERFACE_NUM][MAX_BUS_NUM];
|
||
|
u8 max_adll_per_pup[MAX_INTERFACE_NUM][MAX_BUS_NUM];
|
||
|
u8 min_adll_per_pup[MAX_INTERFACE_NUM][MAX_BUS_NUM];
|
||
|
u32 pbsdelay_per_pup[NUM_OF_PBS_MODES][MAX_INTERFACE_NUM][MAX_BUS_NUM];
|
||
|
u8 adll_shift_lock[MAX_INTERFACE_NUM][MAX_BUS_NUM];
|
||
|
u8 adll_shift_val[MAX_INTERFACE_NUM][MAX_BUS_NUM];
|
||
|
enum hws_pattern pbs_pattern = PATTERN_VREF;
|
||
|
static u8 pup_state[MAX_INTERFACE_NUM][MAX_BUS_NUM];
|
||
|
|
||
|
/*
|
||
|
* Name: ddr3_tip_pbs
|
||
|
* Desc: PBS
|
||
|
* Args: TBD
|
||
|
* Notes:
|
||
|
* Returns: OK if success, other error code if fail.
|
||
|
*/
|
||
|
int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode)
|
||
|
{
|
||
|
u32 res0[MAX_INTERFACE_NUM];
|
||
|
int adll_tap = MEGA / freq_val[medium_freq] / 64;
|
||
|
int pad_num = 0;
|
||
|
enum hws_search_dir search_dir =
|
||
|
(pbs_mode == PBS_RX_MODE) ? HWS_HIGH2LOW : HWS_LOW2HIGH;
|
||
|
enum hws_dir dir = (pbs_mode == PBS_RX_MODE) ? OPER_READ : OPER_WRITE;
|
||
|
int iterations = (pbs_mode == PBS_RX_MODE) ? 31 : 63;
|
||
|
u32 res_valid_mask = (pbs_mode == PBS_RX_MODE) ? 0x1f : 0x3f;
|
||
|
int init_val = (search_dir == HWS_LOW2HIGH) ? 0 : iterations;
|
||
|
enum hws_edge_compare search_edge = EDGE_FP;
|
||
|
u32 pup = 0, bit = 0, if_id = 0, all_lock = 0, cs_num = 0;
|
||
|
int reg_addr = 0;
|
||
|
u32 validation_val = 0;
|
||
|
u32 cs_enable_reg_val[MAX_INTERFACE_NUM];
|
||
|
u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg();
|
||
|
u8 temp = 0;
|
||
|
struct hws_topology_map *tm = ddr3_get_topology_map();
|
||
|
|
||
|
/* save current cs enable reg val */
|
||
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
||
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
||
|
|
||
|
/* save current cs enable reg val */
|
||
|
CHECK_STATUS(ddr3_tip_if_read
|
||
|
(dev_num, ACCESS_TYPE_UNICAST, if_id,
|
||
|
CS_ENABLE_REG, cs_enable_reg_val, MASK_ALL_BITS));
|
||
|
|
||
|
/* enable single cs */
|
||
|
CHECK_STATUS(ddr3_tip_if_write
|
||
|
(dev_num, ACCESS_TYPE_UNICAST, if_id,
|
||
|
CS_ENABLE_REG, (1 << 3), (1 << 3)));
|
||
|
}
|
||
|
|
||
|
reg_addr = (pbs_mode == PBS_RX_MODE) ?
|
||
|
(READ_CENTRALIZATION_PHY_REG +
|
||
|
(effective_cs * CS_REGISTER_ADDR_OFFSET)) :
|
||
|
(WRITE_CENTRALIZATION_PHY_REG +
|
||
|
(effective_cs * CS_REGISTER_ADDR_OFFSET));
|
||
|
read_adll_value(nominal_adll, reg_addr, MASK_ALL_BITS);
|
||
|
|
||
|
/* stage 1 shift ADLL */
|
||
|
ddr3_tip_ip_training(dev_num, ACCESS_TYPE_MULTICAST,
|
||
|
PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
|
||
|
PARAM_NOT_CARE, RESULT_PER_BIT,
|
||
|
HWS_CONTROL_ELEMENT_ADLL, search_dir, dir,
|
||
|
tm->if_act_mask, init_val, iterations,
|
||
|
pbs_pattern, search_edge, CS_SINGLE, cs_num,
|
||
|
train_status);
|
||
|
validation_val = (pbs_mode == PBS_RX_MODE) ? 0x1f : 0;
|
||
|
for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) {
|
||
|
VALIDATE_ACTIVE(tm->bus_act_mask, pup);
|
||
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
||
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
||
|
min_adll_per_pup[if_id][pup] =
|
||
|
(pbs_mode == PBS_RX_MODE) ? 0x1f : 0x3f;
|
||
|
pup_state[if_id][pup] = 0x3;
|
||
|
adll_shift_lock[if_id][pup] = 1;
|
||
|
max_adll_per_pup[if_id][pup] = 0x0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* EBA */
|
||
|
for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) {
|
||
|
VALIDATE_ACTIVE(tm->bus_act_mask, pup);
|
||
|
for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
|
||
|
CHECK_STATUS(ddr3_tip_if_read
|
||
|
(dev_num, ACCESS_TYPE_MULTICAST,
|
||
|
PARAM_NOT_CARE,
|
||
|
mask_results_dq_reg_map[
|
||
|
bit + pup * BUS_WIDTH_IN_BITS],
|
||
|
res0, MASK_ALL_BITS));
|
||
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1;
|
||
|
if_id++) {
|
||
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
||
|
DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
|
||
|
("FP I/F %d, bit:%d, pup:%d res0 0x%x\n",
|
||
|
if_id, bit, pup,
|
||
|
res0[if_id]));
|
||
|
if (pup_state[if_id][pup] != 3)
|
||
|
continue;
|
||
|
/* if not EBA state than move to next pup */
|
||
|
|
||
|
if ((res0[if_id] & 0x2000000) == 0) {
|
||
|
DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
|
||
|
("-- Fail Training IP\n"));
|
||
|
/* training machine failed */
|
||
|
pup_state[if_id][pup] = 1;
|
||
|
adll_shift_lock[if_id][pup] = 0;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
else if ((res0[if_id] & res_valid_mask) ==
|
||
|
validation_val) {
|
||
|
DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
|
||
|
("-- FAIL EBA %d %d %d %d\n",
|
||
|
if_id, bit, pup,
|
||
|
res0[if_id]));
|
||
|
pup_state[if_id][pup] = 4;
|
||
|
/* this pup move to EEBA */
|
||
|
adll_shift_lock[if_id][pup] = 0;
|
||
|
continue;
|
||
|
} else {
|
||
|
/*
|
||
|
* The search ended in Pass we need
|
||
|
* Fail
|
||
|
*/
|
||
|
res0[if_id] =
|
||
|
(pbs_mode == PBS_RX_MODE) ?
|
||
|
((res0[if_id] &
|
||
|
res_valid_mask) + 1) :
|
||
|
((res0[if_id] &
|
||
|
res_valid_mask) - 1);
|
||
|
max_adll_per_pup[if_id][pup] =
|
||
|
(max_adll_per_pup[if_id][pup] <
|
||
|
res0[if_id]) ?
|
||
|
(u8)res0[if_id] :
|
||
|
max_adll_per_pup[if_id][pup];
|
||
|
min_adll_per_pup[if_id][pup] =
|
||
|
(res0[if_id] >
|
||
|
min_adll_per_pup[if_id][pup]) ?
|
||
|
min_adll_per_pup[if_id][pup] :
|
||
|
(u8)
|
||
|
res0[if_id];
|
||
|
/*
|
||
|
* vs the Rx we are searching for the
|
||
|
* smallest value of DQ shift so all
|
||
|
* Bus would fail
|
||
|
*/
|
||
|
adll_shift_val[if_id][pup] =
|
||
|
(pbs_mode == PBS_RX_MODE) ?
|
||
|
max_adll_per_pup[if_id][pup] :
|
||
|
min_adll_per_pup[if_id][pup];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* EEBA */
|
||
|
for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) {
|
||
|
VALIDATE_ACTIVE(tm->bus_act_mask, pup);
|
||
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
||
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
||
|
|
||
|
if (pup_state[if_id][pup] != 4)
|
||
|
continue;
|
||
|
/*
|
||
|
* if pup state different from EEBA than move to
|
||
|
* next pup
|
||
|
*/
|
||
|
reg_addr = (pbs_mode == PBS_RX_MODE) ?
|
||
|
(0x54 + effective_cs * 0x10) :
|
||
|
(0x14 + effective_cs * 0x10);
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num, ACCESS_TYPE_UNICAST, if_id,
|
||
|
ACCESS_TYPE_UNICAST, pup, DDR_PHY_DATA,
|
||
|
reg_addr, 0x1f));
|
||
|
reg_addr = (pbs_mode == PBS_RX_MODE) ?
|
||
|
(0x55 + effective_cs * 0x10) :
|
||
|
(0x15 + effective_cs * 0x10);
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num, ACCESS_TYPE_UNICAST, if_id,
|
||
|
ACCESS_TYPE_UNICAST, pup, DDR_PHY_DATA,
|
||
|
reg_addr, 0x1f));
|
||
|
/* initialize the Edge2 Max. */
|
||
|
adll_shift_val[if_id][pup] = 0;
|
||
|
min_adll_per_pup[if_id][pup] =
|
||
|
(pbs_mode == PBS_RX_MODE) ? 0x1f : 0x3f;
|
||
|
max_adll_per_pup[if_id][pup] = 0x0;
|
||
|
|
||
|
ddr3_tip_ip_training(dev_num, ACCESS_TYPE_MULTICAST,
|
||
|
PARAM_NOT_CARE,
|
||
|
ACCESS_TYPE_MULTICAST,
|
||
|
PARAM_NOT_CARE, RESULT_PER_BIT,
|
||
|
HWS_CONTROL_ELEMENT_ADLL,
|
||
|
search_dir, dir,
|
||
|
tm->if_act_mask, init_val,
|
||
|
iterations, pbs_pattern,
|
||
|
search_edge, CS_SINGLE, cs_num,
|
||
|
train_status);
|
||
|
DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO,
|
||
|
("ADLL shift results:\n"));
|
||
|
|
||
|
for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
|
||
|
CHECK_STATUS(ddr3_tip_if_read
|
||
|
(dev_num, ACCESS_TYPE_MULTICAST,
|
||
|
PARAM_NOT_CARE,
|
||
|
mask_results_dq_reg_map[
|
||
|
bit + pup *
|
||
|
BUS_WIDTH_IN_BITS],
|
||
|
res0, MASK_ALL_BITS));
|
||
|
DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
|
||
|
("FP I/F %d, bit:%d, pup:%d res0 0x%x\n",
|
||
|
if_id, bit, pup,
|
||
|
res0[if_id]));
|
||
|
|
||
|
if ((res0[if_id] & 0x2000000) == 0) {
|
||
|
DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
|
||
|
(" -- EEBA Fail\n"));
|
||
|
bit = BUS_WIDTH_IN_BITS;
|
||
|
/* exit bit loop */
|
||
|
DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
|
||
|
("-- EEBA Fail Training IP\n"));
|
||
|
/*
|
||
|
* training machine failed but pass
|
||
|
* before in the EBA so maybe the DQS
|
||
|
* shift change env.
|
||
|
*/
|
||
|
pup_state[if_id][pup] = 2;
|
||
|
adll_shift_lock[if_id][pup] = 0;
|
||
|
reg_addr = (pbs_mode == PBS_RX_MODE) ?
|
||
|
(0x54 + effective_cs * 0x10) :
|
||
|
(0x14 + effective_cs * 0x10);
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num,
|
||
|
ACCESS_TYPE_UNICAST,
|
||
|
if_id,
|
||
|
ACCESS_TYPE_UNICAST, pup,
|
||
|
DDR_PHY_DATA, reg_addr,
|
||
|
0x0));
|
||
|
reg_addr = (pbs_mode == PBS_RX_MODE) ?
|
||
|
(0x55 + effective_cs * 0x10) :
|
||
|
(0x15 + effective_cs * 0x10);
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num,
|
||
|
ACCESS_TYPE_UNICAST,
|
||
|
if_id,
|
||
|
ACCESS_TYPE_UNICAST, pup,
|
||
|
DDR_PHY_DATA, reg_addr,
|
||
|
0x0));
|
||
|
continue;
|
||
|
} else if ((res0[if_id] & res_valid_mask) ==
|
||
|
validation_val) {
|
||
|
/* exit bit loop */
|
||
|
bit = BUS_WIDTH_IN_BITS;
|
||
|
DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
|
||
|
("-- FAIL EEBA\n"));
|
||
|
/* this pup move to SBA */
|
||
|
pup_state[if_id][pup] = 2;
|
||
|
adll_shift_lock[if_id][pup] = 0;
|
||
|
reg_addr = (pbs_mode == PBS_RX_MODE) ?
|
||
|
(0x54 + effective_cs * 0x10) :
|
||
|
(0x14 + effective_cs * 0x10);
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num,
|
||
|
ACCESS_TYPE_UNICAST,
|
||
|
if_id,
|
||
|
ACCESS_TYPE_UNICAST, pup,
|
||
|
DDR_PHY_DATA, reg_addr,
|
||
|
0x0));
|
||
|
reg_addr = (pbs_mode == PBS_RX_MODE) ?
|
||
|
(0x55 + effective_cs * 0x10) :
|
||
|
(0x15 + effective_cs * 0x10);
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num,
|
||
|
ACCESS_TYPE_UNICAST,
|
||
|
if_id,
|
||
|
ACCESS_TYPE_UNICAST, pup,
|
||
|
DDR_PHY_DATA, reg_addr,
|
||
|
0x0));
|
||
|
continue;
|
||
|
} else {
|
||
|
adll_shift_lock[if_id][pup] = 1;
|
||
|
/*
|
||
|
* The search ended in Pass we need
|
||
|
* Fail
|
||
|
*/
|
||
|
res0[if_id] =
|
||
|
(pbs_mode == PBS_RX_MODE) ?
|
||
|
((res0[if_id] &
|
||
|
res_valid_mask) + 1) :
|
||
|
((res0[if_id] &
|
||
|
res_valid_mask) - 1);
|
||
|
max_adll_per_pup[if_id][pup] =
|
||
|
(max_adll_per_pup[if_id][pup] <
|
||
|
res0[if_id]) ?
|
||
|
(u8)res0[if_id] :
|
||
|
max_adll_per_pup[if_id][pup];
|
||
|
min_adll_per_pup[if_id][pup] =
|
||
|
(res0[if_id] >
|
||
|
min_adll_per_pup[if_id][pup]) ?
|
||
|
min_adll_per_pup[if_id][pup] :
|
||
|
(u8)res0[if_id];
|
||
|
/*
|
||
|
* vs the Rx we are searching for the
|
||
|
* smallest value of DQ shift so all Bus
|
||
|
* would fail
|
||
|
*/
|
||
|
adll_shift_val[if_id][pup] =
|
||
|
(pbs_mode == PBS_RX_MODE) ?
|
||
|
max_adll_per_pup[if_id][pup] :
|
||
|
min_adll_per_pup[if_id][pup];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Print Stage result */
|
||
|
for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) {
|
||
|
VALIDATE_ACTIVE(tm->bus_act_mask, pup);
|
||
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
||
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
||
|
DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
|
||
|
("FP I/F %d, ADLL Shift for EBA: pup[%d] Lock status = %d Lock Val = %d,%d\n",
|
||
|
if_id, pup,
|
||
|
adll_shift_lock[if_id][pup],
|
||
|
max_adll_per_pup[if_id][pup],
|
||
|
min_adll_per_pup[if_id][pup]));
|
||
|
}
|
||
|
}
|
||
|
DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO,
|
||
|
("Update ADLL Shift of all pups:\n"));
|
||
|
|
||
|
for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) {
|
||
|
VALIDATE_ACTIVE(tm->bus_act_mask, pup);
|
||
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
||
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
||
|
if (adll_shift_lock[if_id][pup] != 1)
|
||
|
continue;
|
||
|
/* if pup not locked continue to next pup */
|
||
|
|
||
|
reg_addr = (pbs_mode == PBS_RX_MODE) ?
|
||
|
(0x3 + effective_cs * 4) :
|
||
|
(0x1 + effective_cs * 4);
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num, ACCESS_TYPE_UNICAST, if_id,
|
||
|
ACCESS_TYPE_UNICAST, pup, DDR_PHY_DATA,
|
||
|
reg_addr, adll_shift_val[if_id][pup]));
|
||
|
DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE,
|
||
|
("FP I/F %d, Pup[%d] = %d\n", if_id,
|
||
|
pup, adll_shift_val[if_id][pup]));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* PBS EEBA&EBA */
|
||
|
/* Start the Per Bit Skew search */
|
||
|
for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) {
|
||
|
VALIDATE_ACTIVE(tm->bus_act_mask, pup);
|
||
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
||
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
||
|
max_pbs_per_pup[if_id][pup] = 0x0;
|
||
|
min_pbs_per_pup[if_id][pup] = 0x1f;
|
||
|
for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
|
||
|
/* reset result for PBS */
|
||
|
result_all_bit[bit + pup * BUS_WIDTH_IN_BITS +
|
||
|
if_id * MAX_BUS_NUM *
|
||
|
BUS_WIDTH_IN_BITS] = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
iterations = 31;
|
||
|
search_dir = HWS_LOW2HIGH;
|
||
|
/* !!!!! ran sh (search_dir == HWS_LOW2HIGH)?0:iterations; */
|
||
|
init_val = 0;
|
||
|
|
||
|
ddr3_tip_ip_training(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
|
||
|
ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
|
||
|
RESULT_PER_BIT, HWS_CONTROL_ELEMENT_DQ_SKEW,
|
||
|
search_dir, dir, tm->if_act_mask, init_val,
|
||
|
iterations, pbs_pattern, search_edge,
|
||
|
CS_SINGLE, cs_num, train_status);
|
||
|
|
||
|
for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) {
|
||
|
VALIDATE_ACTIVE(tm->bus_act_mask, pup);
|
||
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
||
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
||
|
if (adll_shift_lock[if_id][pup] != 1) {
|
||
|
/* if pup not lock continue to next pup */
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
|
||
|
CHECK_STATUS(ddr3_tip_if_read
|
||
|
(dev_num, ACCESS_TYPE_MULTICAST,
|
||
|
PARAM_NOT_CARE,
|
||
|
mask_results_dq_reg_map[
|
||
|
bit +
|
||
|
pup * BUS_WIDTH_IN_BITS],
|
||
|
res0, MASK_ALL_BITS));
|
||
|
DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO,
|
||
|
("Per Bit Skew search, FP I/F %d, bit:%d, pup:%d res0 0x%x\n",
|
||
|
if_id, bit, pup,
|
||
|
res0[if_id]));
|
||
|
if ((res0[if_id] & 0x2000000) == 0) {
|
||
|
DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO,
|
||
|
("--EBA PBS Fail - Training IP machine\n"));
|
||
|
/* exit the bit loop */
|
||
|
bit = BUS_WIDTH_IN_BITS;
|
||
|
/*
|
||
|
* ADLL is no long in lock need new
|
||
|
* search
|
||
|
*/
|
||
|
adll_shift_lock[if_id][pup] = 0;
|
||
|
/* Move to SBA */
|
||
|
pup_state[if_id][pup] = 2;
|
||
|
max_pbs_per_pup[if_id][pup] = 0x0;
|
||
|
min_pbs_per_pup[if_id][pup] = 0x1f;
|
||
|
continue;
|
||
|
} else {
|
||
|
temp = (u8)(res0[if_id] &
|
||
|
res_valid_mask);
|
||
|
max_pbs_per_pup[if_id][pup] =
|
||
|
(temp >
|
||
|
max_pbs_per_pup[if_id][pup]) ?
|
||
|
temp :
|
||
|
max_pbs_per_pup[if_id][pup];
|
||
|
min_pbs_per_pup[if_id][pup] =
|
||
|
(temp <
|
||
|
min_pbs_per_pup[if_id][pup]) ?
|
||
|
temp :
|
||
|
min_pbs_per_pup[if_id][pup];
|
||
|
result_all_bit[bit +
|
||
|
pup * BUS_WIDTH_IN_BITS +
|
||
|
if_id * MAX_BUS_NUM *
|
||
|
BUS_WIDTH_IN_BITS] =
|
||
|
temp;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Check all Pup lock */
|
||
|
all_lock = 1;
|
||
|
for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) {
|
||
|
VALIDATE_ACTIVE(tm->bus_act_mask, pup);
|
||
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
||
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
||
|
all_lock = all_lock * adll_shift_lock[if_id][pup];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Only if not all Pups Lock */
|
||
|
if (all_lock == 0) {
|
||
|
DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO,
|
||
|
("##########ADLL shift for SBA###########\n"));
|
||
|
|
||
|
/* ADLL shift for SBA */
|
||
|
search_dir = (pbs_mode == PBS_RX_MODE) ? HWS_LOW2HIGH :
|
||
|
HWS_HIGH2LOW;
|
||
|
init_val = (search_dir == HWS_LOW2HIGH) ? 0 : iterations;
|
||
|
for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) {
|
||
|
VALIDATE_ACTIVE(tm->bus_act_mask, pup);
|
||
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1;
|
||
|
if_id++) {
|
||
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
||
|
if (adll_shift_lock[if_id][pup] == 1) {
|
||
|
/*if pup lock continue to next pup */
|
||
|
continue;
|
||
|
}
|
||
|
/*init the var altogth init before */
|
||
|
adll_shift_lock[if_id][pup] = 0;
|
||
|
reg_addr = (pbs_mode == PBS_RX_MODE) ?
|
||
|
(0x54 + effective_cs * 0x10) :
|
||
|
(0x14 + effective_cs * 0x10);
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num, ACCESS_TYPE_UNICAST,
|
||
|
if_id, ACCESS_TYPE_UNICAST, pup,
|
||
|
DDR_PHY_DATA, reg_addr, 0));
|
||
|
reg_addr = (pbs_mode == PBS_RX_MODE) ?
|
||
|
(0x55 + effective_cs * 0x10) :
|
||
|
(0x15 + effective_cs * 0x10);
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num, ACCESS_TYPE_UNICAST,
|
||
|
if_id, ACCESS_TYPE_UNICAST, pup,
|
||
|
DDR_PHY_DATA, reg_addr, 0));
|
||
|
reg_addr = (pbs_mode == PBS_RX_MODE) ?
|
||
|
(0x5f + effective_cs * 0x10) :
|
||
|
(0x1f + effective_cs * 0x10);
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num, ACCESS_TYPE_UNICAST,
|
||
|
if_id, ACCESS_TYPE_UNICAST, pup,
|
||
|
DDR_PHY_DATA, reg_addr, 0));
|
||
|
/* initilaze the Edge2 Max. */
|
||
|
adll_shift_val[if_id][pup] = 0;
|
||
|
min_adll_per_pup[if_id][pup] = 0x1f;
|
||
|
max_adll_per_pup[if_id][pup] = 0x0;
|
||
|
|
||
|
ddr3_tip_ip_training(dev_num,
|
||
|
ACCESS_TYPE_MULTICAST,
|
||
|
PARAM_NOT_CARE,
|
||
|
ACCESS_TYPE_MULTICAST,
|
||
|
PARAM_NOT_CARE,
|
||
|
RESULT_PER_BIT,
|
||
|
HWS_CONTROL_ELEMENT_ADLL,
|
||
|
search_dir, dir,
|
||
|
tm->if_act_mask,
|
||
|
init_val, iterations,
|
||
|
pbs_pattern,
|
||
|
search_edge, CS_SINGLE,
|
||
|
cs_num, train_status);
|
||
|
|
||
|
for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
|
||
|
CHECK_STATUS(ddr3_tip_if_read
|
||
|
(dev_num,
|
||
|
ACCESS_TYPE_MULTICAST,
|
||
|
PARAM_NOT_CARE,
|
||
|
mask_results_dq_reg_map
|
||
|
[bit +
|
||
|
pup *
|
||
|
BUS_WIDTH_IN_BITS],
|
||
|
res0, MASK_ALL_BITS));
|
||
|
DEBUG_PBS_ENGINE(
|
||
|
DEBUG_LEVEL_INFO,
|
||
|
("FP I/F %d, bit:%d, pup:%d res0 0x%x\n",
|
||
|
if_id, bit, pup, res0[if_id]));
|
||
|
if ((res0[if_id] & 0x2000000) == 0) {
|
||
|
/* exit the bit loop */
|
||
|
bit = BUS_WIDTH_IN_BITS;
|
||
|
/* Fail SBA --> Fail PBS */
|
||
|
pup_state[if_id][pup] = 1;
|
||
|
DEBUG_PBS_ENGINE
|
||
|
(DEBUG_LEVEL_INFO,
|
||
|
(" SBA Fail\n"));
|
||
|
continue;
|
||
|
} else {
|
||
|
/*
|
||
|
* - increment to get all
|
||
|
* 8 bit lock.
|
||
|
*/
|
||
|
adll_shift_lock[if_id][pup]++;
|
||
|
/*
|
||
|
* The search ended in Pass
|
||
|
* we need Fail
|
||
|
*/
|
||
|
res0[if_id] =
|
||
|
(pbs_mode == PBS_RX_MODE) ?
|
||
|
((res0[if_id] & res_valid_mask) + 1) :
|
||
|
((res0[if_id] & res_valid_mask) - 1);
|
||
|
max_adll_per_pup[if_id][pup] =
|
||
|
(max_adll_per_pup[if_id]
|
||
|
[pup] < res0[if_id]) ?
|
||
|
(u8)res0[if_id] :
|
||
|
max_adll_per_pup[if_id][pup];
|
||
|
min_adll_per_pup[if_id][pup] =
|
||
|
(res0[if_id] >
|
||
|
min_adll_per_pup[if_id]
|
||
|
[pup]) ?
|
||
|
min_adll_per_pup[if_id][pup] :
|
||
|
(u8)res0[if_id];
|
||
|
/*
|
||
|
* vs the Rx we are searching for
|
||
|
* the smallest value of DQ shift
|
||
|
* so all Bus would fail
|
||
|
*/
|
||
|
adll_shift_val[if_id][pup] =
|
||
|
(pbs_mode == PBS_RX_MODE) ?
|
||
|
max_adll_per_pup[if_id][pup] :
|
||
|
min_adll_per_pup[if_id][pup];
|
||
|
}
|
||
|
}
|
||
|
/* 1 is lock */
|
||
|
adll_shift_lock[if_id][pup] =
|
||
|
(adll_shift_lock[if_id][pup] == 8) ?
|
||
|
1 : 0;
|
||
|
reg_addr = (pbs_mode == PBS_RX_MODE) ?
|
||
|
(0x3 + effective_cs * 4) :
|
||
|
(0x1 + effective_cs * 4);
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num, ACCESS_TYPE_UNICAST,
|
||
|
if_id, ACCESS_TYPE_UNICAST, pup,
|
||
|
DDR_PHY_DATA, reg_addr,
|
||
|
adll_shift_val[if_id][pup]));
|
||
|
DEBUG_PBS_ENGINE(
|
||
|
DEBUG_LEVEL_INFO,
|
||
|
("adll_shift_lock[%x][%x] = %x\n",
|
||
|
if_id, pup,
|
||
|
adll_shift_lock[if_id][pup]));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* End ADLL Shift for SBA */
|
||
|
/* Start the Per Bit Skew search */
|
||
|
/* The ADLL shift finished with a Pass */
|
||
|
search_edge = (pbs_mode == PBS_RX_MODE) ? EDGE_PF : EDGE_FP;
|
||
|
search_dir = (pbs_mode == PBS_RX_MODE) ?
|
||
|
HWS_LOW2HIGH : HWS_HIGH2LOW;
|
||
|
iterations = 0x1f;
|
||
|
/* - The initial value is different in Rx and Tx mode */
|
||
|
init_val = (pbs_mode == PBS_RX_MODE) ? 0 : iterations;
|
||
|
|
||
|
ddr3_tip_ip_training(dev_num, ACCESS_TYPE_MULTICAST,
|
||
|
PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST,
|
||
|
PARAM_NOT_CARE, RESULT_PER_BIT,
|
||
|
HWS_CONTROL_ELEMENT_DQ_SKEW,
|
||
|
search_dir, dir, tm->if_act_mask,
|
||
|
init_val, iterations, pbs_pattern,
|
||
|
search_edge, CS_SINGLE, cs_num,
|
||
|
train_status);
|
||
|
|
||
|
for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) {
|
||
|
VALIDATE_ACTIVE(tm->bus_act_mask, pup);
|
||
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1;
|
||
|
if_id++) {
|
||
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
||
|
for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
|
||
|
CHECK_STATUS(ddr3_tip_if_read
|
||
|
(dev_num,
|
||
|
ACCESS_TYPE_MULTICAST,
|
||
|
PARAM_NOT_CARE,
|
||
|
mask_results_dq_reg_map
|
||
|
[bit +
|
||
|
pup *
|
||
|
BUS_WIDTH_IN_BITS],
|
||
|
res0, MASK_ALL_BITS));
|
||
|
if (pup_state[if_id][pup] != 2) {
|
||
|
/*
|
||
|
* if pup is not SBA continue
|
||
|
* to next pup
|
||
|
*/
|
||
|
bit = BUS_WIDTH_IN_BITS;
|
||
|
continue;
|
||
|
}
|
||
|
DEBUG_PBS_ENGINE(
|
||
|
DEBUG_LEVEL_INFO,
|
||
|
("Per Bit Skew search, PF I/F %d, bit:%d, pup:%d res0 0x%x\n",
|
||
|
if_id, bit, pup, res0[if_id]));
|
||
|
if ((res0[if_id] & 0x2000000) == 0) {
|
||
|
DEBUG_PBS_ENGINE
|
||
|
(DEBUG_LEVEL_INFO,
|
||
|
("SBA Fail\n"));
|
||
|
|
||
|
max_pbs_per_pup[if_id][pup] =
|
||
|
0x1f;
|
||
|
result_all_bit[
|
||
|
bit + pup *
|
||
|
BUS_WIDTH_IN_BITS +
|
||
|
if_id * MAX_BUS_NUM *
|
||
|
BUS_WIDTH_IN_BITS] =
|
||
|
0x1f;
|
||
|
} else {
|
||
|
temp = (u8)(res0[if_id] &
|
||
|
res_valid_mask);
|
||
|
max_pbs_per_pup[if_id][pup] =
|
||
|
(temp >
|
||
|
max_pbs_per_pup[if_id]
|
||
|
[pup]) ? temp :
|
||
|
max_pbs_per_pup
|
||
|
[if_id][pup];
|
||
|
min_pbs_per_pup[if_id][pup] =
|
||
|
(temp <
|
||
|
min_pbs_per_pup[if_id]
|
||
|
[pup]) ? temp :
|
||
|
min_pbs_per_pup
|
||
|
[if_id][pup];
|
||
|
result_all_bit[
|
||
|
bit + pup *
|
||
|
BUS_WIDTH_IN_BITS +
|
||
|
if_id * MAX_BUS_NUM *
|
||
|
BUS_WIDTH_IN_BITS] =
|
||
|
temp;
|
||
|
adll_shift_lock[if_id][pup] = 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Check all Pup state */
|
||
|
all_lock = 1;
|
||
|
for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) {
|
||
|
/*
|
||
|
* DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO,
|
||
|
* ("pup_state[%d][%d] = %d\n",if_id,pup,pup_state
|
||
|
* [if_id][pup]));
|
||
|
*/
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* END OF SBA */
|
||
|
/* Norm */
|
||
|
for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) {
|
||
|
VALIDATE_ACTIVE(tm->bus_act_mask, pup);
|
||
|
for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
|
||
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1;
|
||
|
if_id++) {
|
||
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
||
|
/* if pup not lock continue to next pup */
|
||
|
if (adll_shift_lock[if_id][pup] != 1) {
|
||
|
DEBUG_PBS_ENGINE(
|
||
|
DEBUG_LEVEL_ERROR,
|
||
|
("PBS failed for IF #%d\n",
|
||
|
if_id));
|
||
|
training_result[training_stage][if_id]
|
||
|
= TEST_FAILED;
|
||
|
|
||
|
result_mat[if_id][pup][bit] = 0;
|
||
|
max_pbs_per_pup[if_id][pup] = 0;
|
||
|
min_pbs_per_pup[if_id][pup] = 0;
|
||
|
} else {
|
||
|
training_result[
|
||
|
training_stage][if_id] =
|
||
|
(training_result[training_stage]
|
||
|
[if_id] == TEST_FAILED) ?
|
||
|
TEST_FAILED : TEST_SUCCESS;
|
||
|
result_mat[if_id][pup][bit] =
|
||
|
result_all_bit[
|
||
|
bit + pup *
|
||
|
BUS_WIDTH_IN_BITS +
|
||
|
if_id * MAX_BUS_NUM *
|
||
|
BUS_WIDTH_IN_BITS] -
|
||
|
min_pbs_per_pup[if_id][pup];
|
||
|
}
|
||
|
DEBUG_PBS_ENGINE(
|
||
|
DEBUG_LEVEL_INFO,
|
||
|
("The abs min_pbs[%d][%d] = %d\n",
|
||
|
if_id, pup,
|
||
|
min_pbs_per_pup[if_id][pup]));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Clean all results */
|
||
|
ddr3_tip_clean_pbs_result(dev_num, pbs_mode);
|
||
|
|
||
|
/* DQ PBS register update with the final result */
|
||
|
for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
|
||
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
||
|
for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) {
|
||
|
VALIDATE_ACTIVE(tm->bus_act_mask, pup);
|
||
|
|
||
|
DEBUG_PBS_ENGINE(
|
||
|
DEBUG_LEVEL_INFO,
|
||
|
("Final Results: if_id %d, pup %d, Pup State: %d\n",
|
||
|
if_id, pup, pup_state[if_id][pup]));
|
||
|
for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
|
||
|
if (dq_map_table == NULL) {
|
||
|
DEBUG_PBS_ENGINE(
|
||
|
DEBUG_LEVEL_ERROR,
|
||
|
("dq_map_table not initialized\n"));
|
||
|
return MV_FAIL;
|
||
|
}
|
||
|
pad_num = dq_map_table[
|
||
|
bit + pup * BUS_WIDTH_IN_BITS +
|
||
|
if_id * BUS_WIDTH_IN_BITS *
|
||
|
tm->num_of_bus_per_interface];
|
||
|
DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO,
|
||
|
("result_mat: %d ",
|
||
|
result_mat[if_id][pup]
|
||
|
[bit]));
|
||
|
reg_addr = (pbs_mode == PBS_RX_MODE) ?
|
||
|
(PBS_RX_PHY_REG + effective_cs * 0x10) :
|
||
|
(PBS_TX_PHY_REG + effective_cs * 0x10);
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num, ACCESS_TYPE_UNICAST,
|
||
|
if_id, ACCESS_TYPE_UNICAST, pup,
|
||
|
DDR_PHY_DATA, reg_addr + pad_num,
|
||
|
result_mat[if_id][pup][bit]));
|
||
|
}
|
||
|
pbsdelay_per_pup[pbs_mode][if_id][pup] =
|
||
|
(max_pbs_per_pup[if_id][pup] ==
|
||
|
min_pbs_per_pup[if_id][pup]) ?
|
||
|
TYPICAL_PBS_VALUE :
|
||
|
((max_adll_per_pup[if_id][pup] -
|
||
|
min_adll_per_pup[if_id][pup]) * adll_tap /
|
||
|
(max_pbs_per_pup[if_id][pup] -
|
||
|
min_pbs_per_pup[if_id][pup]));
|
||
|
|
||
|
/* RX results ready, write RX also */
|
||
|
if (pbs_mode == PBS_TX_MODE) {
|
||
|
/* Write TX results */
|
||
|
reg_addr = (0x14 + effective_cs * 0x10);
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num, ACCESS_TYPE_UNICAST,
|
||
|
if_id, ACCESS_TYPE_UNICAST, pup,
|
||
|
DDR_PHY_DATA, reg_addr,
|
||
|
(max_pbs_per_pup[if_id][pup] -
|
||
|
min_pbs_per_pup[if_id][pup]) /
|
||
|
2));
|
||
|
reg_addr = (0x15 + effective_cs * 0x10);
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num, ACCESS_TYPE_UNICAST,
|
||
|
if_id, ACCESS_TYPE_UNICAST, pup,
|
||
|
DDR_PHY_DATA, reg_addr,
|
||
|
(max_pbs_per_pup[if_id][pup] -
|
||
|
min_pbs_per_pup[if_id][pup]) /
|
||
|
2));
|
||
|
|
||
|
/* Write previously stored RX results */
|
||
|
reg_addr = (0x54 + effective_cs * 0x10);
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num, ACCESS_TYPE_UNICAST,
|
||
|
if_id, ACCESS_TYPE_UNICAST, pup,
|
||
|
DDR_PHY_DATA, reg_addr,
|
||
|
result_mat_rx_dqs[if_id][pup]
|
||
|
[effective_cs]));
|
||
|
reg_addr = (0x55 + effective_cs * 0x10);
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num, ACCESS_TYPE_UNICAST,
|
||
|
if_id, ACCESS_TYPE_UNICAST, pup,
|
||
|
DDR_PHY_DATA, reg_addr,
|
||
|
result_mat_rx_dqs[if_id][pup]
|
||
|
[effective_cs]));
|
||
|
} else {
|
||
|
/*
|
||
|
* RX results may affect RL results correctess,
|
||
|
* so just store the results that will written
|
||
|
* in TX stage
|
||
|
*/
|
||
|
result_mat_rx_dqs[if_id][pup][effective_cs] =
|
||
|
(max_pbs_per_pup[if_id][pup] -
|
||
|
min_pbs_per_pup[if_id][pup]) / 2;
|
||
|
}
|
||
|
DEBUG_PBS_ENGINE(
|
||
|
DEBUG_LEVEL_INFO,
|
||
|
(", PBS tap=%d [psec] ==> skew observed = %d\n",
|
||
|
pbsdelay_per_pup[pbs_mode][if_id][pup],
|
||
|
((max_pbs_per_pup[if_id][pup] -
|
||
|
min_pbs_per_pup[if_id][pup]) *
|
||
|
pbsdelay_per_pup[pbs_mode][if_id][pup])));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Write back to the phy the default values */
|
||
|
reg_addr = (pbs_mode == PBS_RX_MODE) ?
|
||
|
(READ_CENTRALIZATION_PHY_REG + effective_cs * 4) :
|
||
|
(WRITE_CENTRALIZATION_PHY_REG + effective_cs * 4);
|
||
|
write_adll_value(nominal_adll, reg_addr);
|
||
|
|
||
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
||
|
reg_addr = (pbs_mode == PBS_RX_MODE) ?
|
||
|
(0x5a + effective_cs * 0x10) :
|
||
|
(0x1a + effective_cs * 0x10);
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num, ACCESS_TYPE_UNICAST, if_id,
|
||
|
ACCESS_TYPE_UNICAST, pup, DDR_PHY_DATA, reg_addr,
|
||
|
0));
|
||
|
|
||
|
/* restore cs enable value */
|
||
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
||
|
CHECK_STATUS(ddr3_tip_if_write
|
||
|
(dev_num, ACCESS_TYPE_UNICAST, if_id,
|
||
|
CS_ENABLE_REG, cs_enable_reg_val[if_id],
|
||
|
MASK_ALL_BITS));
|
||
|
}
|
||
|
|
||
|
/* exit test mode */
|
||
|
CHECK_STATUS(ddr3_tip_if_write
|
||
|
(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
|
||
|
ODPG_WRITE_READ_MODE_ENABLE_REG, 0xffff, MASK_ALL_BITS));
|
||
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
||
|
/*
|
||
|
* meaning that there is no VW exist at all (No lock at
|
||
|
* the EBA ADLL shift at EBS)
|
||
|
*/
|
||
|
if (pup_state[if_id][pup] == 1)
|
||
|
return MV_FAIL;
|
||
|
}
|
||
|
|
||
|
return MV_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Name: ddr3_tip_pbs_rx.
|
||
|
* Desc: PBS TX
|
||
|
* Args: TBD
|
||
|
* Notes:
|
||
|
* Returns: OK if success, other error code if fail.
|
||
|
*/
|
||
|
int ddr3_tip_pbs_rx(u32 uidev_num)
|
||
|
{
|
||
|
return ddr3_tip_pbs(uidev_num, PBS_RX_MODE);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Name: ddr3_tip_pbs_tx.
|
||
|
* Desc: PBS TX
|
||
|
* Args: TBD
|
||
|
* Notes:
|
||
|
* Returns: OK if success, other error code if fail.
|
||
|
*/
|
||
|
int ddr3_tip_pbs_tx(u32 uidev_num)
|
||
|
{
|
||
|
return ddr3_tip_pbs(uidev_num, PBS_TX_MODE);
|
||
|
}
|
||
|
|
||
|
#ifndef EXCLUDE_SWITCH_DEBUG
|
||
|
/*
|
||
|
* Print PBS Result
|
||
|
*/
|
||
|
int ddr3_tip_print_all_pbs_result(u32 dev_num)
|
||
|
{
|
||
|
u32 curr_cs;
|
||
|
u32 max_cs = hws_ddr3_tip_max_cs_get();
|
||
|
|
||
|
for (curr_cs = 0; curr_cs < max_cs; curr_cs++) {
|
||
|
ddr3_tip_print_pbs_result(dev_num, curr_cs, PBS_RX_MODE);
|
||
|
ddr3_tip_print_pbs_result(dev_num, curr_cs, PBS_TX_MODE);
|
||
|
}
|
||
|
|
||
|
return MV_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Print PBS Result
|
||
|
*/
|
||
|
int ddr3_tip_print_pbs_result(u32 dev_num, u32 cs_num, enum pbs_dir pbs_mode)
|
||
|
{
|
||
|
u32 data_value = 0, bit = 0, if_id = 0, pup = 0;
|
||
|
u32 reg_addr = (pbs_mode == PBS_RX_MODE) ?
|
||
|
(PBS_RX_PHY_REG + cs_num * 0x10) :
|
||
|
(PBS_TX_PHY_REG + cs_num * 0x10);
|
||
|
struct hws_topology_map *tm = ddr3_get_topology_map();
|
||
|
|
||
|
printf("CS%d, %s ,PBS\n", cs_num,
|
||
|
(pbs_mode == PBS_RX_MODE) ? "Rx" : "Tx");
|
||
|
|
||
|
for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) {
|
||
|
printf("%s, DQ", (pbs_mode == PBS_RX_MODE) ? "Rx" : "Tx");
|
||
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
||
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
||
|
printf("%d ,PBS,,, ", bit);
|
||
|
for (pup = 0; pup <= tm->num_of_bus_per_interface;
|
||
|
pup++) {
|
||
|
VALIDATE_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 + bit,
|
||
|
&data_value));
|
||
|
printf("%d , ", data_value);
|
||
|
}
|
||
|
}
|
||
|
printf("\n");
|
||
|
}
|
||
|
printf("\n");
|
||
|
|
||
|
return MV_OK;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
* Fixup PBS Result
|
||
|
*/
|
||
|
int ddr3_tip_clean_pbs_result(u32 dev_num, enum pbs_dir pbs_mode)
|
||
|
{
|
||
|
u32 if_id, pup, bit;
|
||
|
u32 reg_addr = (pbs_mode == PBS_RX_MODE) ?
|
||
|
(PBS_RX_PHY_REG + effective_cs * 0x10) :
|
||
|
(PBS_TX_PHY_REG + effective_cs * 0x10);
|
||
|
struct hws_topology_map *tm = ddr3_get_topology_map();
|
||
|
|
||
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
||
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
||
|
for (pup = 0; pup <= tm->num_of_bus_per_interface; pup++) {
|
||
|
for (bit = 0; bit <= BUS_WIDTH_IN_BITS + 3; bit++) {
|
||
|
CHECK_STATUS(ddr3_tip_bus_write
|
||
|
(dev_num, ACCESS_TYPE_UNICAST,
|
||
|
if_id, ACCESS_TYPE_UNICAST, pup,
|
||
|
DDR_PHY_DATA, reg_addr + bit, 0));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return MV_OK;
|
||
|
}
|