mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-12 22:33:18 +00:00
f1df936445
This patch adds the DDR3 setup and training code taken from the Marvell U-Boot repository. This code used to be included as a binary (bin_hdr) into the Armada A38x boot image. Not linked with the main U-Boot. With this code addition and the serdes/PHY setup code, the Armada A38x support in mainline U-Boot is finally self-contained. So the complete image for booting can be built from mainline U-Boot. Without any additional external inclusion. Note: This code has undergone many hours (days!) of coding-style cleanup and refactoring. It still is not checkpatch clean though, I'm afraid. As the factoring of the code has so many levels of indentation that many lines are longer than 80 chars. Signed-off-by: Stefan Roese <sr@denx.de>
1551 lines
37 KiB
C
1551 lines
37 KiB
C
/*
|
|
* Copyright (C) Marvell International Ltd. and its affiliates
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <i2c.h>
|
|
#include <spl.h>
|
|
#include <asm/io.h>
|
|
#include <asm/arch/cpu.h>
|
|
#include <asm/arch/soc.h>
|
|
|
|
#include "ddr3_init.h"
|
|
|
|
u8 is_reg_dump = 0;
|
|
u8 debug_pbs = DEBUG_LEVEL_ERROR;
|
|
|
|
/*
|
|
* API to change flags outside of the lib
|
|
*/
|
|
#ifndef SILENT_LIB
|
|
/* Debug flags for other Training modules */
|
|
u8 debug_training_static = DEBUG_LEVEL_ERROR;
|
|
u8 debug_training = DEBUG_LEVEL_ERROR;
|
|
u8 debug_leveling = DEBUG_LEVEL_ERROR;
|
|
u8 debug_centralization = DEBUG_LEVEL_ERROR;
|
|
u8 debug_training_ip = DEBUG_LEVEL_ERROR;
|
|
u8 debug_training_bist = DEBUG_LEVEL_ERROR;
|
|
u8 debug_training_hw_alg = DEBUG_LEVEL_ERROR;
|
|
u8 debug_training_access = DEBUG_LEVEL_ERROR;
|
|
u8 debug_training_a38x = DEBUG_LEVEL_ERROR;
|
|
|
|
void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level)
|
|
{
|
|
switch (block) {
|
|
case DEBUG_BLOCK_STATIC:
|
|
debug_training_static = level;
|
|
break;
|
|
case DEBUG_BLOCK_TRAINING_MAIN:
|
|
debug_training = level;
|
|
break;
|
|
case DEBUG_BLOCK_LEVELING:
|
|
debug_leveling = level;
|
|
break;
|
|
case DEBUG_BLOCK_CENTRALIZATION:
|
|
debug_centralization = level;
|
|
break;
|
|
case DEBUG_BLOCK_PBS:
|
|
debug_pbs = level;
|
|
break;
|
|
case DEBUG_BLOCK_ALG:
|
|
debug_training_hw_alg = level;
|
|
break;
|
|
case DEBUG_BLOCK_DEVICE:
|
|
debug_training_a38x = level;
|
|
break;
|
|
case DEBUG_BLOCK_ACCESS:
|
|
debug_training_access = level;
|
|
break;
|
|
case DEBUG_STAGES_REG_DUMP:
|
|
if (level == DEBUG_LEVEL_TRACE)
|
|
is_reg_dump = 1;
|
|
else
|
|
is_reg_dump = 0;
|
|
break;
|
|
case DEBUG_BLOCK_ALL:
|
|
default:
|
|
debug_training_static = level;
|
|
debug_training = level;
|
|
debug_leveling = level;
|
|
debug_centralization = level;
|
|
debug_pbs = level;
|
|
debug_training_hw_alg = level;
|
|
debug_training_access = level;
|
|
debug_training_a38x = level;
|
|
}
|
|
}
|
|
#else
|
|
void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level)
|
|
{
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
struct hws_tip_config_func_db config_func_info[HWS_MAX_DEVICE_NUM];
|
|
u8 is_default_centralization = 0;
|
|
u8 is_tune_result = 0;
|
|
u8 is_validate_window_per_if = 0;
|
|
u8 is_validate_window_per_pup = 0;
|
|
u8 sweep_cnt = 1;
|
|
u32 is_bist_reset_bit = 1;
|
|
static struct hws_xsb_info xsb_info[HWS_MAX_DEVICE_NUM];
|
|
|
|
/*
|
|
* Dump Dunit & Phy registers
|
|
*/
|
|
int ddr3_tip_reg_dump(u32 dev_num)
|
|
{
|
|
u32 if_id, reg_addr, data_value, bus_id;
|
|
u32 read_data[MAX_INTERFACE_NUM];
|
|
struct hws_topology_map *tm = ddr3_get_topology_map();
|
|
|
|
printf("-- dunit registers --\n");
|
|
for (reg_addr = 0x1400; reg_addr < 0x19f0; reg_addr += 4) {
|
|
printf("0x%x ", reg_addr);
|
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
|
CHECK_STATUS(ddr3_tip_if_read
|
|
(dev_num, ACCESS_TYPE_UNICAST,
|
|
if_id, reg_addr, read_data,
|
|
MASK_ALL_BITS));
|
|
printf("0x%x ", read_data[if_id]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
printf("-- Phy registers --\n");
|
|
for (reg_addr = 0; reg_addr <= 0xff; reg_addr++) {
|
|
printf("0x%x ", reg_addr);
|
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
|
for (bus_id = 0;
|
|
bus_id < tm->num_of_bus_per_interface;
|
|
bus_id++) {
|
|
VALIDATE_ACTIVE(tm->bus_act_mask, bus_id);
|
|
CHECK_STATUS(ddr3_tip_bus_read
|
|
(dev_num, if_id,
|
|
ACCESS_TYPE_UNICAST, bus_id,
|
|
DDR_PHY_DATA, reg_addr,
|
|
&data_value));
|
|
printf("0x%x ", data_value);
|
|
}
|
|
for (bus_id = 0;
|
|
bus_id < tm->num_of_bus_per_interface;
|
|
bus_id++) {
|
|
VALIDATE_ACTIVE(tm->bus_act_mask, bus_id);
|
|
CHECK_STATUS(ddr3_tip_bus_read
|
|
(dev_num, if_id,
|
|
ACCESS_TYPE_UNICAST, bus_id,
|
|
DDR_PHY_CONTROL, reg_addr,
|
|
&data_value));
|
|
printf("0x%x ", data_value);
|
|
}
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
return MV_OK;
|
|
}
|
|
|
|
/*
|
|
* Register access func registration
|
|
*/
|
|
int ddr3_tip_init_config_func(u32 dev_num,
|
|
struct hws_tip_config_func_db *config_func)
|
|
{
|
|
if (config_func == NULL)
|
|
return MV_BAD_PARAM;
|
|
|
|
memcpy(&config_func_info[dev_num], config_func,
|
|
sizeof(struct hws_tip_config_func_db));
|
|
|
|
return MV_OK;
|
|
}
|
|
|
|
/*
|
|
* Read training result table
|
|
*/
|
|
int hws_ddr3_tip_read_training_result(
|
|
u32 dev_num, enum hws_result result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM])
|
|
{
|
|
dev_num = dev_num;
|
|
|
|
if (result == NULL)
|
|
return MV_BAD_PARAM;
|
|
memcpy(result, training_result, sizeof(result));
|
|
|
|
return MV_OK;
|
|
}
|
|
|
|
/*
|
|
* Get training result info pointer
|
|
*/
|
|
enum hws_result *ddr3_tip_get_result_ptr(u32 stage)
|
|
{
|
|
return training_result[stage];
|
|
}
|
|
|
|
/*
|
|
* Device info read
|
|
*/
|
|
int ddr3_tip_get_device_info(u32 dev_num, struct ddr3_device_info *info_ptr)
|
|
{
|
|
if (config_func_info[dev_num].tip_get_device_info_func != NULL) {
|
|
return config_func_info[dev_num].
|
|
tip_get_device_info_func((u8) dev_num, info_ptr);
|
|
}
|
|
|
|
return MV_FAIL;
|
|
}
|
|
|
|
#ifndef EXCLUDE_SWITCH_DEBUG
|
|
/*
|
|
* Convert freq to character string
|
|
*/
|
|
static char *convert_freq(enum hws_ddr_freq freq)
|
|
{
|
|
switch (freq) {
|
|
case DDR_FREQ_LOW_FREQ:
|
|
return "DDR_FREQ_LOW_FREQ";
|
|
case DDR_FREQ_400:
|
|
return "400";
|
|
|
|
case DDR_FREQ_533:
|
|
return "533";
|
|
case DDR_FREQ_667:
|
|
return "667";
|
|
|
|
case DDR_FREQ_800:
|
|
return "800";
|
|
|
|
case DDR_FREQ_933:
|
|
return "933";
|
|
|
|
case DDR_FREQ_1066:
|
|
return "1066";
|
|
case DDR_FREQ_311:
|
|
return "311";
|
|
|
|
case DDR_FREQ_333:
|
|
return "333";
|
|
|
|
case DDR_FREQ_467:
|
|
return "467";
|
|
|
|
case DDR_FREQ_850:
|
|
return "850";
|
|
|
|
case DDR_FREQ_900:
|
|
return "900";
|
|
|
|
case DDR_FREQ_360:
|
|
return "DDR_FREQ_360";
|
|
|
|
case DDR_FREQ_1000:
|
|
return "DDR_FREQ_1000";
|
|
default:
|
|
return "Unknown Frequency";
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Convert device ID to character string
|
|
*/
|
|
static char *convert_dev_id(u32 dev_id)
|
|
{
|
|
switch (dev_id) {
|
|
case 0x6800:
|
|
return "A38xx";
|
|
case 0x6900:
|
|
return "A39XX";
|
|
case 0xf400:
|
|
return "AC3";
|
|
case 0xfc00:
|
|
return "BC2";
|
|
|
|
default:
|
|
return "Unknown Device";
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Convert device ID to character string
|
|
*/
|
|
static char *convert_mem_size(u32 dev_id)
|
|
{
|
|
switch (dev_id) {
|
|
case 0:
|
|
return "512 MB";
|
|
case 1:
|
|
return "1 GB";
|
|
case 2:
|
|
return "2 GB";
|
|
case 3:
|
|
return "4 GB";
|
|
case 4:
|
|
return "8 GB";
|
|
|
|
default:
|
|
return "wrong mem size";
|
|
}
|
|
}
|
|
|
|
int print_device_info(u8 dev_num)
|
|
{
|
|
struct ddr3_device_info info_ptr;
|
|
struct hws_topology_map *tm = ddr3_get_topology_map();
|
|
|
|
CHECK_STATUS(ddr3_tip_get_device_info(dev_num, &info_ptr));
|
|
printf("=== DDR setup START===\n");
|
|
printf("\tDevice ID: %s\n", convert_dev_id(info_ptr.device_id));
|
|
printf("\tDDR3 CK delay: %d\n", info_ptr.ck_delay);
|
|
print_topology(tm);
|
|
printf("=== DDR setup END===\n");
|
|
|
|
return MV_OK;
|
|
}
|
|
|
|
void hws_ddr3_tip_sweep_test(int enable)
|
|
{
|
|
if (enable) {
|
|
is_validate_window_per_if = 1;
|
|
is_validate_window_per_pup = 1;
|
|
debug_training = DEBUG_LEVEL_TRACE;
|
|
} else {
|
|
is_validate_window_per_if = 0;
|
|
is_validate_window_per_pup = 0;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
char *ddr3_tip_convert_tune_result(enum hws_result tune_result)
|
|
{
|
|
switch (tune_result) {
|
|
case TEST_FAILED:
|
|
return "FAILED";
|
|
case TEST_SUCCESS:
|
|
return "PASS";
|
|
case NO_TEST_DONE:
|
|
return "NOT COMPLETED";
|
|
default:
|
|
return "Un-KNOWN";
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Print log info
|
|
*/
|
|
int ddr3_tip_print_log(u32 dev_num, u32 mem_addr)
|
|
{
|
|
u32 if_id = 0;
|
|
struct hws_topology_map *tm = ddr3_get_topology_map();
|
|
|
|
mem_addr = mem_addr;
|
|
|
|
#ifndef EXCLUDE_SWITCH_DEBUG
|
|
if ((is_validate_window_per_if != 0) ||
|
|
(is_validate_window_per_pup != 0)) {
|
|
u32 is_pup_log = 0;
|
|
enum hws_ddr_freq freq;
|
|
|
|
freq = tm->interface_params[first_active_if].memory_freq;
|
|
|
|
is_pup_log = (is_validate_window_per_pup != 0) ? 1 : 0;
|
|
printf("===VALIDATE WINDOW LOG START===\n");
|
|
printf("DDR Frequency: %s ======\n", convert_freq(freq));
|
|
/* print sweep windows */
|
|
ddr3_tip_run_sweep_test(dev_num, sweep_cnt, 1, is_pup_log);
|
|
ddr3_tip_run_sweep_test(dev_num, sweep_cnt, 0, is_pup_log);
|
|
ddr3_tip_print_all_pbs_result(dev_num);
|
|
ddr3_tip_print_wl_supp_result(dev_num);
|
|
printf("===VALIDATE WINDOW LOG END ===\n");
|
|
CHECK_STATUS(ddr3_tip_restore_dunit_regs(dev_num));
|
|
ddr3_tip_reg_dump(dev_num);
|
|
}
|
|
#endif
|
|
|
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
|
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("IF %d Status:\n", if_id));
|
|
|
|
if (mask_tune_func & INIT_CONTROLLER_MASK_BIT) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("\tInit Controller: %s\n",
|
|
ddr3_tip_convert_tune_result
|
|
(training_result[INIT_CONTROLLER]
|
|
[if_id])));
|
|
}
|
|
if (mask_tune_func & SET_LOW_FREQ_MASK_BIT) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("\tLow freq Config: %s\n",
|
|
ddr3_tip_convert_tune_result
|
|
(training_result[SET_LOW_FREQ]
|
|
[if_id])));
|
|
}
|
|
if (mask_tune_func & LOAD_PATTERN_MASK_BIT) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("\tLoad Pattern: %s\n",
|
|
ddr3_tip_convert_tune_result
|
|
(training_result[LOAD_PATTERN]
|
|
[if_id])));
|
|
}
|
|
if (mask_tune_func & SET_MEDIUM_FREQ_MASK_BIT) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("\tMedium freq Config: %s\n",
|
|
ddr3_tip_convert_tune_result
|
|
(training_result[SET_MEDIUM_FREQ]
|
|
[if_id])));
|
|
}
|
|
if (mask_tune_func & WRITE_LEVELING_MASK_BIT) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("\tWL: %s\n",
|
|
ddr3_tip_convert_tune_result
|
|
(training_result[WRITE_LEVELING]
|
|
[if_id])));
|
|
}
|
|
if (mask_tune_func & LOAD_PATTERN_2_MASK_BIT) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("\tLoad Pattern: %s\n",
|
|
ddr3_tip_convert_tune_result
|
|
(training_result[LOAD_PATTERN_2]
|
|
[if_id])));
|
|
}
|
|
if (mask_tune_func & READ_LEVELING_MASK_BIT) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("\tRL: %s\n",
|
|
ddr3_tip_convert_tune_result
|
|
(training_result[READ_LEVELING]
|
|
[if_id])));
|
|
}
|
|
if (mask_tune_func & WRITE_LEVELING_SUPP_MASK_BIT) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("\tWL Supp: %s\n",
|
|
ddr3_tip_convert_tune_result
|
|
(training_result[WRITE_LEVELING_SUPP]
|
|
[if_id])));
|
|
}
|
|
if (mask_tune_func & PBS_RX_MASK_BIT) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("\tPBS RX: %s\n",
|
|
ddr3_tip_convert_tune_result
|
|
(training_result[PBS_RX]
|
|
[if_id])));
|
|
}
|
|
if (mask_tune_func & PBS_TX_MASK_BIT) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("\tPBS TX: %s\n",
|
|
ddr3_tip_convert_tune_result
|
|
(training_result[PBS_TX]
|
|
[if_id])));
|
|
}
|
|
if (mask_tune_func & SET_TARGET_FREQ_MASK_BIT) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("\tTarget freq Config: %s\n",
|
|
ddr3_tip_convert_tune_result
|
|
(training_result[SET_TARGET_FREQ]
|
|
[if_id])));
|
|
}
|
|
if (mask_tune_func & WRITE_LEVELING_TF_MASK_BIT) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("\tWL TF: %s\n",
|
|
ddr3_tip_convert_tune_result
|
|
(training_result[WRITE_LEVELING_TF]
|
|
[if_id])));
|
|
}
|
|
if (mask_tune_func & READ_LEVELING_TF_MASK_BIT) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("\tRL TF: %s\n",
|
|
ddr3_tip_convert_tune_result
|
|
(training_result[READ_LEVELING_TF]
|
|
[if_id])));
|
|
}
|
|
if (mask_tune_func & WRITE_LEVELING_SUPP_TF_MASK_BIT) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("\tWL TF Supp: %s\n",
|
|
ddr3_tip_convert_tune_result
|
|
(training_result
|
|
[WRITE_LEVELING_SUPP_TF]
|
|
[if_id])));
|
|
}
|
|
if (mask_tune_func & CENTRALIZATION_RX_MASK_BIT) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("\tCentr RX: %s\n",
|
|
ddr3_tip_convert_tune_result
|
|
(training_result[CENTRALIZATION_RX]
|
|
[if_id])));
|
|
}
|
|
if (mask_tune_func & VREF_CALIBRATION_MASK_BIT) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("\tVREF_CALIBRATION: %s\n",
|
|
ddr3_tip_convert_tune_result
|
|
(training_result[VREF_CALIBRATION]
|
|
[if_id])));
|
|
}
|
|
if (mask_tune_func & CENTRALIZATION_TX_MASK_BIT) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("\tCentr TX: %s\n",
|
|
ddr3_tip_convert_tune_result
|
|
(training_result[CENTRALIZATION_TX]
|
|
[if_id])));
|
|
}
|
|
}
|
|
|
|
return MV_OK;
|
|
}
|
|
|
|
/*
|
|
* Print stability log info
|
|
*/
|
|
int ddr3_tip_print_stability_log(u32 dev_num)
|
|
{
|
|
u8 if_id = 0, csindex = 0, bus_id = 0, idx = 0;
|
|
u32 reg_data;
|
|
u32 read_data[MAX_INTERFACE_NUM];
|
|
u32 max_cs = hws_ddr3_tip_max_cs_get();
|
|
struct hws_topology_map *tm = ddr3_get_topology_map();
|
|
|
|
/* Title print */
|
|
for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
|
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
|
printf("Title: I/F# , Tj, Calibration_n0, Calibration_p0, Calibration_n1, Calibration_p1, Calibration_n2, Calibration_p2,");
|
|
for (csindex = 0; csindex < max_cs; csindex++) {
|
|
printf("CS%d , ", csindex);
|
|
printf("\n");
|
|
VALIDATE_ACTIVE(tm->bus_act_mask, bus_id);
|
|
printf("VWTx, VWRx, WL_tot, WL_ADLL, WL_PH, RL_Tot, RL_ADLL, RL_PH, RL_Smp, Cen_tx, Cen_rx, Vref, DQVref,");
|
|
printf("\t\t");
|
|
for (idx = 0; idx < 11; idx++)
|
|
printf("PBSTx-Pad%d,", idx);
|
|
printf("\t\t");
|
|
for (idx = 0; idx < 11; idx++)
|
|
printf("PBSRx-Pad%d,", idx);
|
|
}
|
|
}
|
|
printf("\n");
|
|
|
|
/* Data print */
|
|
for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
|
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
|
|
|
printf("Data: %d,%d,", if_id,
|
|
(config_func_info[dev_num].tip_get_temperature != NULL)
|
|
? (config_func_info[dev_num].
|
|
tip_get_temperature(dev_num)) : (0));
|
|
|
|
CHECK_STATUS(ddr3_tip_if_read
|
|
(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x14c8,
|
|
read_data, MASK_ALL_BITS));
|
|
printf("%d,%d,", ((read_data[if_id] & 0x3f0) >> 4),
|
|
((read_data[if_id] & 0xfc00) >> 10));
|
|
CHECK_STATUS(ddr3_tip_if_read
|
|
(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x17c8,
|
|
read_data, MASK_ALL_BITS));
|
|
printf("%d,%d,", ((read_data[if_id] & 0x3f0) >> 4),
|
|
((read_data[if_id] & 0xfc00) >> 10));
|
|
CHECK_STATUS(ddr3_tip_if_read
|
|
(dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1dc8,
|
|
read_data, MASK_ALL_BITS));
|
|
printf("%d,%d,", ((read_data[if_id] & 0x3f0000) >> 16),
|
|
((read_data[if_id] & 0xfc00000) >> 22));
|
|
|
|
for (csindex = 0; csindex < max_cs; csindex++) {
|
|
printf("CS%d , ", csindex);
|
|
for (bus_id = 0; bus_id < MAX_BUS_NUM; bus_id++) {
|
|
printf("\n");
|
|
VALIDATE_ACTIVE(tm->bus_act_mask, bus_id);
|
|
ddr3_tip_bus_read(dev_num, if_id,
|
|
ACCESS_TYPE_UNICAST,
|
|
bus_id, DDR_PHY_DATA,
|
|
RESULT_DB_PHY_REG_ADDR +
|
|
csindex, ®_data);
|
|
printf("%d,%d,", (reg_data & 0x1f),
|
|
((reg_data & 0x3e0) >> 5));
|
|
/* WL */
|
|
ddr3_tip_bus_read(dev_num, if_id,
|
|
ACCESS_TYPE_UNICAST,
|
|
bus_id, DDR_PHY_DATA,
|
|
WL_PHY_REG +
|
|
csindex * 4, ®_data);
|
|
printf("%d,%d,%d,",
|
|
(reg_data & 0x1f) +
|
|
((reg_data & 0x1c0) >> 6) * 32,
|
|
(reg_data & 0x1f),
|
|
(reg_data & 0x1c0) >> 6);
|
|
/* RL */
|
|
CHECK_STATUS(ddr3_tip_if_read
|
|
(dev_num, ACCESS_TYPE_UNICAST,
|
|
if_id,
|
|
READ_DATA_SAMPLE_DELAY,
|
|
read_data, MASK_ALL_BITS));
|
|
read_data[if_id] =
|
|
(read_data[if_id] &
|
|
(0xf << (4 * csindex))) >>
|
|
(4 * csindex);
|
|
ddr3_tip_bus_read(dev_num, if_id,
|
|
ACCESS_TYPE_UNICAST, bus_id,
|
|
DDR_PHY_DATA,
|
|
RL_PHY_REG + csindex * 4,
|
|
®_data);
|
|
printf("%d,%d,%d,%d,",
|
|
(reg_data & 0x1f) +
|
|
((reg_data & 0x1c0) >> 6) * 32 +
|
|
read_data[if_id] * 64,
|
|
(reg_data & 0x1f),
|
|
((reg_data & 0x1c0) >> 6),
|
|
read_data[if_id]);
|
|
/* Centralization */
|
|
ddr3_tip_bus_read(dev_num, if_id,
|
|
ACCESS_TYPE_UNICAST, bus_id,
|
|
DDR_PHY_DATA,
|
|
WRITE_CENTRALIZATION_PHY_REG
|
|
+ csindex * 4, ®_data);
|
|
printf("%d,", (reg_data & 0x3f));
|
|
ddr3_tip_bus_read(dev_num, if_id,
|
|
ACCESS_TYPE_UNICAST, bus_id,
|
|
DDR_PHY_DATA,
|
|
READ_CENTRALIZATION_PHY_REG
|
|
+ csindex * 4, ®_data);
|
|
printf("%d,", (reg_data & 0x1f));
|
|
/* Vref */
|
|
ddr3_tip_bus_read(dev_num, if_id,
|
|
ACCESS_TYPE_UNICAST, bus_id,
|
|
DDR_PHY_DATA,
|
|
PAD_CONFIG_PHY_REG,
|
|
®_data);
|
|
printf("%d,", (reg_data & 0x7));
|
|
/* DQVref */
|
|
/* Need to add the Read Function from device */
|
|
printf("%d,", 0);
|
|
printf("\t\t");
|
|
for (idx = 0; idx < 11; idx++) {
|
|
ddr3_tip_bus_read(dev_num, if_id,
|
|
ACCESS_TYPE_UNICAST,
|
|
bus_id, DDR_PHY_DATA,
|
|
0xd0 +
|
|
12 * csindex +
|
|
idx, ®_data);
|
|
printf("%d,", (reg_data & 0x3f));
|
|
}
|
|
printf("\t\t");
|
|
for (idx = 0; idx < 11; idx++) {
|
|
ddr3_tip_bus_read(dev_num, if_id,
|
|
ACCESS_TYPE_UNICAST,
|
|
bus_id, DDR_PHY_DATA,
|
|
0x10 +
|
|
16 * csindex +
|
|
idx, ®_data);
|
|
printf("%d,", (reg_data & 0x3f));
|
|
}
|
|
printf("\t\t");
|
|
for (idx = 0; idx < 11; idx++) {
|
|
ddr3_tip_bus_read(dev_num, if_id,
|
|
ACCESS_TYPE_UNICAST,
|
|
bus_id, DDR_PHY_DATA,
|
|
0x50 +
|
|
16 * csindex +
|
|
idx, ®_data);
|
|
printf("%d,", (reg_data & 0x3f));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
printf("\n");
|
|
|
|
return MV_OK;
|
|
}
|
|
|
|
/*
|
|
* Register XSB information
|
|
*/
|
|
int ddr3_tip_register_xsb_info(u32 dev_num, struct hws_xsb_info *xsb_info_table)
|
|
{
|
|
memcpy(&xsb_info[dev_num], xsb_info_table, sizeof(struct hws_xsb_info));
|
|
return MV_OK;
|
|
}
|
|
|
|
/*
|
|
* Read ADLL Value
|
|
*/
|
|
int read_adll_value(u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM],
|
|
int reg_addr, u32 mask)
|
|
{
|
|
u32 data_value;
|
|
u32 if_id = 0, bus_id = 0;
|
|
u32 dev_num = 0;
|
|
struct hws_topology_map *tm = ddr3_get_topology_map();
|
|
|
|
/*
|
|
* multi CS support - reg_addr is calucalated in calling function
|
|
* with CS offset
|
|
*/
|
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
|
for (bus_id = 0; bus_id < tm->num_of_bus_per_interface;
|
|
bus_id++) {
|
|
VALIDATE_ACTIVE(tm->bus_act_mask, bus_id);
|
|
CHECK_STATUS(ddr3_tip_bus_read(dev_num, if_id,
|
|
ACCESS_TYPE_UNICAST,
|
|
bus_id,
|
|
DDR_PHY_DATA, reg_addr,
|
|
&data_value));
|
|
pup_values[if_id *
|
|
tm->num_of_bus_per_interface + bus_id] =
|
|
data_value & mask;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Write ADLL Value
|
|
*/
|
|
int write_adll_value(u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM],
|
|
int reg_addr)
|
|
{
|
|
u32 if_id = 0, bus_id = 0;
|
|
u32 dev_num = 0, data;
|
|
struct hws_topology_map *tm = ddr3_get_topology_map();
|
|
|
|
/*
|
|
* multi CS support - reg_addr is calucalated in calling function
|
|
* with CS offset
|
|
*/
|
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
|
for (bus_id = 0; bus_id < tm->num_of_bus_per_interface;
|
|
bus_id++) {
|
|
VALIDATE_ACTIVE(tm->bus_act_mask, bus_id);
|
|
data = pup_values[if_id *
|
|
tm->num_of_bus_per_interface +
|
|
bus_id];
|
|
CHECK_STATUS(ddr3_tip_bus_write(dev_num,
|
|
ACCESS_TYPE_UNICAST,
|
|
if_id,
|
|
ACCESS_TYPE_UNICAST,
|
|
bus_id, DDR_PHY_DATA,
|
|
reg_addr, data));
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifndef EXCLUDE_SWITCH_DEBUG
|
|
u32 rl_version = 1; /* 0 - old RL machine */
|
|
struct hws_tip_config_func_db config_func_info[HWS_MAX_DEVICE_NUM];
|
|
u32 start_xsb_offset = 0;
|
|
u8 is_rl_old = 0;
|
|
u8 is_freq_old = 0;
|
|
u8 is_dfs_disabled = 0;
|
|
u32 default_centrlization_value = 0x12;
|
|
u32 vref = 0x4;
|
|
u32 activate_select_before_run_alg = 1, activate_deselect_after_run_alg = 1,
|
|
rl_test = 0, reset_read_fifo = 0;
|
|
int debug_acc = 0;
|
|
u32 ctrl_sweepres[ADLL_LENGTH][MAX_INTERFACE_NUM][MAX_BUS_NUM];
|
|
u32 ctrl_adll[MAX_CS_NUM * MAX_INTERFACE_NUM * MAX_BUS_NUM];
|
|
u8 cs_mask_reg[] = {
|
|
0, 4, 8, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
};
|
|
|
|
u32 xsb_test_table[][8] = {
|
|
{0x00000000, 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555,
|
|
0x66666666, 0x77777777},
|
|
{0x88888888, 0x99999999, 0xaaaaaaaa, 0xbbbbbbbb, 0xcccccccc, 0xdddddddd,
|
|
0xeeeeeeee, 0xffffffff},
|
|
{0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
|
|
0x00000000, 0xffffffff},
|
|
{0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
|
|
0x00000000, 0xffffffff},
|
|
{0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
|
|
0x00000000, 0xffffffff},
|
|
{0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
|
|
0x00000000, 0xffffffff},
|
|
{0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
|
|
0xffffffff, 0xffffffff},
|
|
{0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0x00000000,
|
|
0x00000000, 0x00000000},
|
|
{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
|
|
0xffffffff, 0xffffffff}
|
|
};
|
|
|
|
static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr);
|
|
|
|
int ddr3_tip_print_adll(void)
|
|
{
|
|
u32 bus_cnt = 0, if_id, data_p1, data_p2, ui_data3, dev_num = 0;
|
|
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 (bus_cnt = 0; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES();
|
|
bus_cnt++) {
|
|
VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt);
|
|
CHECK_STATUS(ddr3_tip_bus_read
|
|
(dev_num, if_id,
|
|
ACCESS_TYPE_UNICAST, bus_cnt,
|
|
DDR_PHY_DATA, 0x1, &data_p1));
|
|
CHECK_STATUS(ddr3_tip_bus_read
|
|
(dev_num, if_id, ACCESS_TYPE_UNICAST,
|
|
bus_cnt, DDR_PHY_DATA, 0x2, &data_p2));
|
|
CHECK_STATUS(ddr3_tip_bus_read
|
|
(dev_num, if_id, ACCESS_TYPE_UNICAST,
|
|
bus_cnt, DDR_PHY_DATA, 0x3, &ui_data3));
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE,
|
|
(" IF %d bus_cnt %d phy_reg_1_data 0x%x phy_reg_2_data 0x%x phy_reg_3_data 0x%x\n",
|
|
if_id, bus_cnt, data_p1, data_p2,
|
|
ui_data3));
|
|
}
|
|
}
|
|
|
|
return MV_OK;
|
|
}
|
|
|
|
/*
|
|
* Set attribute value
|
|
*/
|
|
int ddr3_tip_set_atr(u32 dev_num, u32 flag_id, u32 value)
|
|
{
|
|
int ret;
|
|
u32 *ptr_flag = NULL;
|
|
|
|
ret = ddr3_tip_access_atr(dev_num, flag_id, value, &ptr_flag);
|
|
if (ptr_flag != NULL) {
|
|
printf("ddr3_tip_set_atr Flag ID 0x%x value is set to 0x%x (was 0x%x)\n",
|
|
flag_id, value, *ptr_flag);
|
|
*ptr_flag = value;
|
|
} else {
|
|
printf("ddr3_tip_set_atr Flag ID 0x%x value is set to 0x%x\n",
|
|
flag_id, value);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
* Access attribute
|
|
*/
|
|
static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr)
|
|
{
|
|
u32 tmp_val = 0, if_id = 0, pup_id = 0;
|
|
struct hws_topology_map *tm = ddr3_get_topology_map();
|
|
|
|
dev_num = dev_num;
|
|
*ptr = NULL;
|
|
|
|
switch (flag_id) {
|
|
case 0:
|
|
*ptr = (u32 *)&(tm->if_act_mask);
|
|
break;
|
|
|
|
case 0x1:
|
|
*ptr = (u32 *)&mask_tune_func;
|
|
break;
|
|
|
|
case 0x2:
|
|
*ptr = (u32 *)&low_freq;
|
|
break;
|
|
|
|
case 0x3:
|
|
*ptr = (u32 *)&medium_freq;
|
|
break;
|
|
|
|
case 0x4:
|
|
*ptr = (u32 *)&generic_init_controller;
|
|
break;
|
|
|
|
case 0x5:
|
|
*ptr = (u32 *)&rl_version;
|
|
break;
|
|
|
|
case 0x8:
|
|
*ptr = (u32 *)&start_xsb_offset;
|
|
break;
|
|
|
|
case 0x20:
|
|
*ptr = (u32 *)&is_rl_old;
|
|
break;
|
|
|
|
case 0x21:
|
|
*ptr = (u32 *)&is_freq_old;
|
|
break;
|
|
|
|
case 0x23:
|
|
*ptr = (u32 *)&is_dfs_disabled;
|
|
break;
|
|
|
|
case 0x24:
|
|
*ptr = (u32 *)&is_pll_before_init;
|
|
break;
|
|
|
|
case 0x25:
|
|
*ptr = (u32 *)&is_adll_calib_before_init;
|
|
break;
|
|
#ifdef STATIC_ALGO_SUPPORT
|
|
case 0x26:
|
|
*ptr = (u32 *)&(silicon_delay[0]);
|
|
break;
|
|
|
|
case 0x27:
|
|
*ptr = (u32 *)&wl_debug_delay;
|
|
break;
|
|
#endif
|
|
case 0x28:
|
|
*ptr = (u32 *)&is_tune_result;
|
|
break;
|
|
|
|
case 0x29:
|
|
*ptr = (u32 *)&is_validate_window_per_if;
|
|
break;
|
|
|
|
case 0x2a:
|
|
*ptr = (u32 *)&is_validate_window_per_pup;
|
|
break;
|
|
|
|
case 0x30:
|
|
*ptr = (u32 *)&sweep_cnt;
|
|
break;
|
|
|
|
case 0x31:
|
|
*ptr = (u32 *)&is_bist_reset_bit;
|
|
break;
|
|
|
|
case 0x32:
|
|
*ptr = (u32 *)&is_dfs_in_init;
|
|
break;
|
|
|
|
case 0x33:
|
|
*ptr = (u32 *)&p_finger;
|
|
break;
|
|
|
|
case 0x34:
|
|
*ptr = (u32 *)&n_finger;
|
|
break;
|
|
|
|
case 0x35:
|
|
*ptr = (u32 *)&init_freq;
|
|
break;
|
|
|
|
case 0x36:
|
|
*ptr = (u32 *)&(freq_val[DDR_FREQ_LOW_FREQ]);
|
|
break;
|
|
|
|
case 0x37:
|
|
*ptr = (u32 *)&start_pattern;
|
|
break;
|
|
|
|
case 0x38:
|
|
*ptr = (u32 *)&end_pattern;
|
|
break;
|
|
|
|
case 0x39:
|
|
*ptr = (u32 *)&phy_reg0_val;
|
|
break;
|
|
|
|
case 0x4a:
|
|
*ptr = (u32 *)&phy_reg1_val;
|
|
break;
|
|
|
|
case 0x4b:
|
|
*ptr = (u32 *)&phy_reg2_val;
|
|
break;
|
|
|
|
case 0x4c:
|
|
*ptr = (u32 *)&phy_reg3_val;
|
|
break;
|
|
|
|
case 0x4e:
|
|
*ptr = (u32 *)&sweep_pattern;
|
|
break;
|
|
|
|
case 0x50:
|
|
*ptr = (u32 *)&is_rzq6;
|
|
break;
|
|
|
|
case 0x51:
|
|
*ptr = (u32 *)&znri_data_phy_val;
|
|
break;
|
|
|
|
case 0x52:
|
|
*ptr = (u32 *)&zpri_data_phy_val;
|
|
break;
|
|
|
|
case 0x53:
|
|
*ptr = (u32 *)&finger_test;
|
|
break;
|
|
|
|
case 0x54:
|
|
*ptr = (u32 *)&n_finger_start;
|
|
break;
|
|
|
|
case 0x55:
|
|
*ptr = (u32 *)&n_finger_end;
|
|
break;
|
|
|
|
case 0x56:
|
|
*ptr = (u32 *)&p_finger_start;
|
|
break;
|
|
|
|
case 0x57:
|
|
*ptr = (u32 *)&p_finger_end;
|
|
break;
|
|
|
|
case 0x58:
|
|
*ptr = (u32 *)&p_finger_step;
|
|
break;
|
|
|
|
case 0x59:
|
|
*ptr = (u32 *)&n_finger_step;
|
|
break;
|
|
|
|
case 0x5a:
|
|
*ptr = (u32 *)&znri_ctrl_phy_val;
|
|
break;
|
|
|
|
case 0x5b:
|
|
*ptr = (u32 *)&zpri_ctrl_phy_val;
|
|
break;
|
|
|
|
case 0x5c:
|
|
*ptr = (u32 *)&is_reg_dump;
|
|
break;
|
|
|
|
case 0x5d:
|
|
*ptr = (u32 *)&vref;
|
|
break;
|
|
|
|
case 0x5e:
|
|
*ptr = (u32 *)&mode2_t;
|
|
break;
|
|
|
|
case 0x5f:
|
|
*ptr = (u32 *)&xsb_validate_type;
|
|
break;
|
|
|
|
case 0x60:
|
|
*ptr = (u32 *)&xsb_validation_base_address;
|
|
break;
|
|
|
|
case 0x67:
|
|
*ptr = (u32 *)&activate_select_before_run_alg;
|
|
break;
|
|
|
|
case 0x68:
|
|
*ptr = (u32 *)&activate_deselect_after_run_alg;
|
|
break;
|
|
|
|
case 0x69:
|
|
*ptr = (u32 *)&odt_additional;
|
|
break;
|
|
|
|
case 0x70:
|
|
*ptr = (u32 *)&debug_mode;
|
|
break;
|
|
|
|
case 0x71:
|
|
*ptr = (u32 *)&pbs_pattern;
|
|
break;
|
|
|
|
case 0x72:
|
|
*ptr = (u32 *)&delay_enable;
|
|
break;
|
|
|
|
case 0x73:
|
|
*ptr = (u32 *)&ck_delay;
|
|
break;
|
|
|
|
case 0x74:
|
|
*ptr = (u32 *)&ck_delay_16;
|
|
break;
|
|
|
|
case 0x75:
|
|
*ptr = (u32 *)&ca_delay;
|
|
break;
|
|
|
|
case 0x100:
|
|
*ptr = (u32 *)&debug_dunit;
|
|
break;
|
|
|
|
case 0x101:
|
|
debug_acc = (int)value;
|
|
break;
|
|
|
|
case 0x102:
|
|
debug_training = (u8)value;
|
|
break;
|
|
|
|
case 0x103:
|
|
debug_training_bist = (u8)value;
|
|
break;
|
|
|
|
case 0x104:
|
|
debug_centralization = (u8)value;
|
|
break;
|
|
|
|
case 0x105:
|
|
debug_training_ip = (u8)value;
|
|
break;
|
|
|
|
case 0x106:
|
|
debug_leveling = (u8)value;
|
|
break;
|
|
|
|
case 0x107:
|
|
debug_pbs = (u8)value;
|
|
break;
|
|
|
|
case 0x108:
|
|
debug_training_static = (u8)value;
|
|
break;
|
|
|
|
case 0x109:
|
|
debug_training_access = (u8)value;
|
|
break;
|
|
|
|
case 0x112:
|
|
*ptr = &start_pattern;
|
|
break;
|
|
|
|
case 0x113:
|
|
*ptr = &end_pattern;
|
|
break;
|
|
|
|
default:
|
|
if ((flag_id >= 0x200) && (flag_id < 0x210)) {
|
|
if_id = flag_id - 0x200;
|
|
*ptr = (u32 *)&(tm->interface_params
|
|
[if_id].memory_freq);
|
|
} else if ((flag_id >= 0x210) && (flag_id < 0x220)) {
|
|
if_id = flag_id - 0x210;
|
|
*ptr = (u32 *)&(tm->interface_params
|
|
[if_id].speed_bin_index);
|
|
} else if ((flag_id >= 0x220) && (flag_id < 0x230)) {
|
|
if_id = flag_id - 0x220;
|
|
*ptr = (u32 *)&(tm->interface_params
|
|
[if_id].bus_width);
|
|
} else if ((flag_id >= 0x230) && (flag_id < 0x240)) {
|
|
if_id = flag_id - 0x230;
|
|
*ptr = (u32 *)&(tm->interface_params
|
|
[if_id].memory_size);
|
|
} else if ((flag_id >= 0x240) && (flag_id < 0x250)) {
|
|
if_id = flag_id - 0x240;
|
|
*ptr = (u32 *)&(tm->interface_params
|
|
[if_id].cas_l);
|
|
} else if ((flag_id >= 0x250) && (flag_id < 0x260)) {
|
|
if_id = flag_id - 0x250;
|
|
*ptr = (u32 *)&(tm->interface_params
|
|
[if_id].cas_wl);
|
|
} else if ((flag_id >= 0x270) && (flag_id < 0x2cf)) {
|
|
if_id = (flag_id - 0x270) / MAX_BUS_NUM;
|
|
pup_id = (flag_id - 0x270) % MAX_BUS_NUM;
|
|
*ptr = (u32 *)&(tm->interface_params[if_id].
|
|
as_bus_params[pup_id].is_ck_swap);
|
|
} else if ((flag_id >= 0x2d0) && (flag_id < 0x32f)) {
|
|
if_id = (flag_id - 0x2d0) / MAX_BUS_NUM;
|
|
pup_id = (flag_id - 0x2d0) % MAX_BUS_NUM;
|
|
*ptr = (u32 *)&(tm->interface_params[if_id].
|
|
as_bus_params[pup_id].is_dqs_swap);
|
|
} else if ((flag_id >= 0x330) && (flag_id < 0x38f)) {
|
|
if_id = (flag_id - 0x330) / MAX_BUS_NUM;
|
|
pup_id = (flag_id - 0x330) % MAX_BUS_NUM;
|
|
*ptr = (u32 *)&(tm->interface_params[if_id].
|
|
as_bus_params[pup_id].cs_bitmask);
|
|
} else if ((flag_id >= 0x390) && (flag_id < 0x3ef)) {
|
|
if_id = (flag_id - 0x390) / MAX_BUS_NUM;
|
|
pup_id = (flag_id - 0x390) % MAX_BUS_NUM;
|
|
*ptr = (u32 *)&(tm->interface_params
|
|
[if_id].as_bus_params
|
|
[pup_id].mirror_enable_bitmask);
|
|
} else if ((flag_id >= 0x500) && (flag_id <= 0x50f)) {
|
|
tmp_val = flag_id - 0x320;
|
|
*ptr = (u32 *)&(clamp_tbl[tmp_val]);
|
|
} else {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
|
|
("flag_id out of boundary %d\n",
|
|
flag_id));
|
|
return MV_BAD_PARAM;
|
|
}
|
|
}
|
|
|
|
return MV_OK;
|
|
}
|
|
|
|
#ifndef EXCLUDE_SWITCH_DEBUG
|
|
/*
|
|
* Print ADLL
|
|
*/
|
|
int print_adll(u32 dev_num, u32 adll[MAX_INTERFACE_NUM * MAX_BUS_NUM])
|
|
{
|
|
u32 i, j;
|
|
struct hws_topology_map *tm = ddr3_get_topology_map();
|
|
|
|
dev_num = dev_num;
|
|
|
|
for (j = 0; j < tm->num_of_bus_per_interface; j++) {
|
|
VALIDATE_ACTIVE(tm->bus_act_mask, j);
|
|
for (i = 0; i < MAX_INTERFACE_NUM; i++) {
|
|
printf("%d ,",
|
|
adll[i * tm->num_of_bus_per_interface + j]);
|
|
}
|
|
}
|
|
printf("\n");
|
|
|
|
return MV_OK;
|
|
}
|
|
#endif
|
|
|
|
/* byte_index - only byte 0, 1, 2, or 3, oxff - test all bytes */
|
|
static u32 ddr3_tip_compare(u32 if_id, u32 *p_src, u32 *p_dst,
|
|
u32 byte_index)
|
|
{
|
|
u32 burst_cnt = 0, addr_offset, i_id;
|
|
int b_is_fail = 0;
|
|
|
|
addr_offset =
|
|
(byte_index ==
|
|
0xff) ? (u32) 0xffffffff : (u32) (0xff << (byte_index * 8));
|
|
for (burst_cnt = 0; burst_cnt < EXT_ACCESS_BURST_LENGTH; burst_cnt++) {
|
|
if ((p_src[burst_cnt] & addr_offset) !=
|
|
(p_dst[burst_cnt] & addr_offset))
|
|
b_is_fail = 1;
|
|
}
|
|
|
|
if (b_is_fail == 1) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
|
|
("IF %d exp: ", if_id));
|
|
for (i_id = 0; i_id <= MAX_INTERFACE_NUM - 1; i_id++) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
|
|
("0x%8x ", p_src[i_id]));
|
|
}
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
|
|
("\n_i_f %d rcv: ", if_id));
|
|
for (i_id = 0; i_id <= MAX_INTERFACE_NUM - 1; i_id++) {
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR,
|
|
("(0x%8x ", p_dst[i_id]));
|
|
}
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("\n "));
|
|
}
|
|
|
|
return b_is_fail;
|
|
}
|
|
|
|
/* test_type = 0-tx , 1-rx */
|
|
int ddr3_tip_sweep_test(u32 dev_num, u32 test_type,
|
|
u32 mem_addr, u32 is_modify_adll,
|
|
u32 start_if, u32 end_if, u32 startpup, u32 endpup)
|
|
{
|
|
u32 bus_cnt = 0, adll_val = 0, if_id, ui_prev_adll, ui_mask_bit,
|
|
end_adll, start_adll;
|
|
u32 reg_addr = 0;
|
|
struct hws_topology_map *tm = ddr3_get_topology_map();
|
|
|
|
mem_addr = mem_addr;
|
|
|
|
if (test_type == 0) {
|
|
reg_addr = 1;
|
|
ui_mask_bit = 0x3f;
|
|
start_adll = 0;
|
|
end_adll = ui_mask_bit;
|
|
} else {
|
|
reg_addr = 3;
|
|
ui_mask_bit = 0x1f;
|
|
start_adll = 0;
|
|
end_adll = ui_mask_bit;
|
|
}
|
|
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("==============================\n"));
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO,
|
|
("Test type %d (0-tx, 1-rx)\n", test_type));
|
|
|
|
for (if_id = start_if; if_id <= end_if; if_id++) {
|
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
|
for (bus_cnt = startpup; bus_cnt < endpup; bus_cnt++) {
|
|
CHECK_STATUS(ddr3_tip_bus_read
|
|
(dev_num, if_id, ACCESS_TYPE_UNICAST,
|
|
bus_cnt, DDR_PHY_DATA, reg_addr,
|
|
&ui_prev_adll));
|
|
|
|
for (adll_val = start_adll; adll_val <= end_adll;
|
|
adll_val++) {
|
|
if (is_modify_adll == 1) {
|
|
CHECK_STATUS(ddr3_tip_bus_read_modify_write
|
|
(dev_num,
|
|
ACCESS_TYPE_UNICAST,
|
|
if_id, bus_cnt,
|
|
DDR_PHY_DATA, reg_addr,
|
|
adll_val, ui_mask_bit));
|
|
}
|
|
}
|
|
if (is_modify_adll == 1) {
|
|
CHECK_STATUS(ddr3_tip_bus_write
|
|
(dev_num, ACCESS_TYPE_UNICAST,
|
|
if_id, ACCESS_TYPE_UNICAST,
|
|
bus_cnt, DDR_PHY_DATA, reg_addr,
|
|
ui_prev_adll));
|
|
}
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("\n"));
|
|
}
|
|
DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("\n"));
|
|
}
|
|
|
|
return MV_OK;
|
|
}
|
|
|
|
#ifndef EXCLUDE_SWITCH_DEBUG
|
|
/*
|
|
* Sweep validation
|
|
*/
|
|
int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction,
|
|
u32 mode)
|
|
{
|
|
u32 pup = 0, start_pup = 0, end_pup = 0;
|
|
u32 adll = 0;
|
|
u32 res[MAX_INTERFACE_NUM] = { 0 };
|
|
int if_id = 0;
|
|
u32 adll_value = 0;
|
|
int reg = (direction == 0) ? WRITE_CENTRALIZATION_PHY_REG :
|
|
READ_CENTRALIZATION_PHY_REG;
|
|
enum hws_access_type pup_access;
|
|
u32 cs;
|
|
u32 max_cs = hws_ddr3_tip_max_cs_get();
|
|
struct hws_topology_map *tm = ddr3_get_topology_map();
|
|
|
|
repeat_num = repeat_num;
|
|
|
|
if (mode == 1) {
|
|
/* per pup */
|
|
start_pup = 0;
|
|
end_pup = tm->num_of_bus_per_interface - 1;
|
|
pup_access = ACCESS_TYPE_UNICAST;
|
|
} else {
|
|
start_pup = 0;
|
|
end_pup = 0;
|
|
pup_access = ACCESS_TYPE_MULTICAST;
|
|
}
|
|
|
|
for (cs = 0; cs < max_cs; cs++) {
|
|
for (adll = 0; adll < ADLL_LENGTH; adll++) {
|
|
for (if_id = 0;
|
|
if_id <= MAX_INTERFACE_NUM - 1;
|
|
if_id++) {
|
|
VALIDATE_ACTIVE
|
|
(tm->if_act_mask,
|
|
if_id);
|
|
for (pup = start_pup; pup <= end_pup; pup++) {
|
|
ctrl_sweepres[adll][if_id][pup] =
|
|
0;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (adll = 0; adll < (MAX_INTERFACE_NUM * MAX_BUS_NUM); adll++)
|
|
ctrl_adll[adll] = 0;
|
|
/* Save DQS value(after algorithm run) */
|
|
read_adll_value(ctrl_adll,
|
|
(reg + (cs * CS_REGISTER_ADDR_OFFSET)),
|
|
MASK_ALL_BITS);
|
|
|
|
/*
|
|
* Sweep ADLL from 0:31 on all I/F on all Pup and perform
|
|
* BIST on each stage.
|
|
*/
|
|
for (pup = start_pup; pup <= end_pup; pup++) {
|
|
for (adll = 0; adll < ADLL_LENGTH; adll++) {
|
|
adll_value =
|
|
(direction == 0) ? (adll * 2) : adll;
|
|
CHECK_STATUS(ddr3_tip_bus_write
|
|
(dev_num, ACCESS_TYPE_MULTICAST, 0,
|
|
pup_access, pup, DDR_PHY_DATA,
|
|
reg + CS_REG_VALUE(cs),
|
|
adll_value));
|
|
hws_ddr3_run_bist(dev_num, sweep_pattern, res,
|
|
cs);
|
|
/* ddr3_tip_reset_fifo_ptr(dev_num); */
|
|
for (if_id = 0;
|
|
if_id <= MAX_INTERFACE_NUM - 1;
|
|
if_id++) {
|
|
VALIDATE_ACTIVE
|
|
(tm->if_act_mask,
|
|
if_id);
|
|
ctrl_sweepres[adll][if_id][pup]
|
|
= res[if_id];
|
|
if (mode == 1) {
|
|
CHECK_STATUS
|
|
(ddr3_tip_bus_write
|
|
(dev_num,
|
|
ACCESS_TYPE_UNICAST,
|
|
if_id,
|
|
ACCESS_TYPE_UNICAST,
|
|
pup,
|
|
DDR_PHY_DATA,
|
|
reg + CS_REG_VALUE(cs),
|
|
ctrl_adll[if_id *
|
|
cs *
|
|
tm->num_of_bus_per_interface
|
|
+ pup]));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
printf("Final, CS %d,%s, Sweep, Result, Adll,", cs,
|
|
((direction == 0) ? "TX" : "RX"));
|
|
for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
|
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
|
if (mode == 1) {
|
|
for (pup = start_pup; pup <= end_pup; pup++) {
|
|
VALIDATE_ACTIVE(tm->bus_act_mask, pup);
|
|
printf("I/F%d-PHY%d , ", if_id, pup);
|
|
}
|
|
} else {
|
|
printf("I/F%d , ", if_id);
|
|
}
|
|
}
|
|
printf("\n");
|
|
|
|
for (adll = 0; adll < ADLL_LENGTH; adll++) {
|
|
adll_value = (direction == 0) ? (adll * 2) : adll;
|
|
printf("Final,%s, Sweep, Result, %d ,",
|
|
((direction == 0) ? "TX" : "RX"), adll_value);
|
|
|
|
for (if_id = 0;
|
|
if_id <= MAX_INTERFACE_NUM - 1;
|
|
if_id++) {
|
|
VALIDATE_ACTIVE(tm->if_act_mask, if_id);
|
|
for (pup = start_pup; pup <= end_pup; pup++) {
|
|
printf("%d , ",
|
|
ctrl_sweepres[adll][if_id]
|
|
[pup]);
|
|
}
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
/*
|
|
* Write back to the phy the Rx DQS value, we store in
|
|
* the beginning.
|
|
*/
|
|
write_adll_value(ctrl_adll,
|
|
(reg + cs * CS_REGISTER_ADDR_OFFSET));
|
|
/* print adll results */
|
|
read_adll_value(ctrl_adll, (reg + cs * CS_REGISTER_ADDR_OFFSET),
|
|
MASK_ALL_BITS);
|
|
printf("%s, DQS, ADLL,,,", (direction == 0) ? "Tx" : "Rx");
|
|
print_adll(dev_num, ctrl_adll);
|
|
}
|
|
ddr3_tip_reset_fifo_ptr(dev_num);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void print_topology(struct hws_topology_map *topology_db)
|
|
{
|
|
u32 ui, uj;
|
|
|
|
printf("\tinterface_mask: 0x%x\n", topology_db->if_act_mask);
|
|
printf("\tNum Bus: %d\n", topology_db->num_of_bus_per_interface);
|
|
printf("\tbus_act_mask: 0x%x\n", topology_db->bus_act_mask);
|
|
|
|
for (ui = 0; ui < MAX_INTERFACE_NUM; ui++) {
|
|
VALIDATE_ACTIVE(topology_db->if_act_mask, ui);
|
|
printf("\n\tInterface ID: %d\n", ui);
|
|
printf("\t\tDDR Frequency: %s\n",
|
|
convert_freq(topology_db->
|
|
interface_params[ui].memory_freq));
|
|
printf("\t\tSpeed_bin: %d\n",
|
|
topology_db->interface_params[ui].speed_bin_index);
|
|
printf("\t\tBus_width: %d\n",
|
|
(4 << topology_db->interface_params[ui].bus_width));
|
|
printf("\t\tMem_size: %s\n",
|
|
convert_mem_size(topology_db->
|
|
interface_params[ui].memory_size));
|
|
printf("\t\tCAS-WL: %d\n",
|
|
topology_db->interface_params[ui].cas_wl);
|
|
printf("\t\tCAS-L: %d\n",
|
|
topology_db->interface_params[ui].cas_l);
|
|
printf("\t\tTemperature: %d\n",
|
|
topology_db->interface_params[ui].interface_temp);
|
|
printf("\n");
|
|
for (uj = 0; uj < 4; uj++) {
|
|
printf("\t\tBus %d parameters- CS Mask: 0x%x\t", uj,
|
|
topology_db->interface_params[ui].
|
|
as_bus_params[uj].cs_bitmask);
|
|
printf("Mirror: 0x%x\t",
|
|
topology_db->interface_params[ui].
|
|
as_bus_params[uj].mirror_enable_bitmask);
|
|
printf("DQS Swap is %s \t",
|
|
(topology_db->
|
|
interface_params[ui].as_bus_params[uj].
|
|
is_dqs_swap == 1) ? "enabled" : "disabled");
|
|
printf("Ck Swap:%s\t",
|
|
(topology_db->
|
|
interface_params[ui].as_bus_params[uj].
|
|
is_ck_swap == 1) ? "enabled" : "disabled");
|
|
printf("\n");
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Execute XSB Test transaction (rd/wr/both)
|
|
*/
|
|
int run_xsb_test(u32 dev_num, u32 mem_addr, u32 write_type,
|
|
u32 read_type, u32 burst_length)
|
|
{
|
|
u32 seq = 0, if_id = 0, addr, cnt;
|
|
int ret = MV_OK, ret_tmp;
|
|
u32 data_read[MAX_INTERFACE_NUM];
|
|
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);
|
|
addr = mem_addr;
|
|
for (cnt = 0; cnt <= burst_length; cnt++) {
|
|
seq = (seq + 1) % 8;
|
|
if (write_type != 0) {
|
|
CHECK_STATUS(ddr3_tip_ext_write
|
|
(dev_num, if_id, addr, 1,
|
|
xsb_test_table[seq]));
|
|
}
|
|
if (read_type != 0) {
|
|
CHECK_STATUS(ddr3_tip_ext_read
|
|
(dev_num, if_id, addr, 1,
|
|
data_read));
|
|
}
|
|
if ((read_type != 0) && (write_type != 0)) {
|
|
ret_tmp =
|
|
ddr3_tip_compare(if_id,
|
|
xsb_test_table[seq],
|
|
data_read,
|
|
0xff);
|
|
addr += (EXT_ACCESS_BURST_LENGTH * 4);
|
|
ret = (ret != MV_OK) ? ret : ret_tmp;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
#else /*EXCLUDE_SWITCH_DEBUG */
|
|
|
|
u32 rl_version = 1; /* 0 - old RL machine */
|
|
u32 vref = 0x4;
|
|
u32 start_xsb_offset = 0;
|
|
u8 cs_mask_reg[] = {
|
|
0, 4, 8, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
};
|
|
|
|
int run_xsb_test(u32 dev_num, u32 mem_addr, u32 write_type,
|
|
u32 read_type, u32 burst_length)
|
|
{
|
|
return MV_OK;
|
|
}
|
|
|
|
#endif
|