blob: ac7e4043e2448a575d90a57a5cfe5a71fad8c66f [file] [log] [blame]
/*
* (C) Copyright Mindspeed Technologies Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <asm/hardware.h>
extern u32* __training_data_start;
typedef struct {
unsigned char rd0;
unsigned char rd1;
unsigned char rd2;
unsigned char rd3;
} dll_rd;
u32 wr_loop(u8 dqs_index, u32 find_median);
dll_rd DLL_check(u8 dqs_index, u8 wr_index, u32 find_median);
u32 wr_rd_transaction(u32 transaction_size, u32 i, u8 dqs_index, u8 wr_index,u8 rd_index, u32 mask);
u32 actual_transaction(u32 transaction_size, u32 i, u32 mask, u32 ddr_addr, u32 dll_num);
u32 get_dll(u32 i);
u32 get_max_addr_space_bit(void);
void training_gbl_init(void);
u32 find_best(void);
u32 ddr_addr_offset;
u32 max_addr_space_bit;
u8 byte_list[16];
u16 half_word_list[16];
u32 word_list[16];
u64 dword_list[16];
u32 byte_mask[4];
u32 max_addr_bit_list[15];
#define SZ_1K 0x400
#define SZ_1M 0x100000
#define SZ_4K SZ_1K * 4
#define SZ_8K SZ_1K * 8
#define SZ_16K SZ_1K * 16
#define SZ_32K SZ_1K * 32
#define SZ_64K SZ_1K * 64
#define SZ_128K SZ_1K * 128
#define SZ_8M SZ_1M * 8
#define SZ_16M SZ_1M * 16
#define SZ_32M SZ_1M * 32
#define SZ_64M SZ_1M * 64
#define ADDR_JUMP_SIZE SZ_128K
void start_training(void)
{
//initialize global data
training_gbl_init();
//start DDR training
find_best();
}
void training_gbl_init(void)
{
u8 i = 0;
u8 __byte_list[16] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x19, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x7f};
u16 __half_word_list[16] = {0x0000, 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666, 0x7777, 0x0888, 0x1999, 0x2aaa, 0x3bbb, 0x4ccc, 0x5ddd, 0x6eee, 0x7fff};
u32 __word_list[16] = {0x00000000, 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x08888888, 0x19999999, 0x2aaaaaaa, 0x3bbbbbbb, 0x4ccccccc, 0x5ddddddd, 0x6eeeeeee, 0x7fffffff};
u64 __dword_list[16] = {0x0000000000000000LL, 0x1111111111111111LL, 0x2222222222222222LL, 0x3333333333333333LL, 0x4444444444444444LL, 0x5555555555555555LL, 0x6666666666666666LL, 0x7777777777777777LL, 0x0888888888888888LL, 0x1999999999999999LL, 0x2aaaaaaaaaaaaaaaLL, 0x3bbbbbbbbbbbbbbbLL, 0x4cccccccccccccccLL, 0x5dddddddddddddddLL, 0x6eeeeeeeeeeeeeeeLL, 0x7fffffffffffffffLL};
u32 __byte_mask[4] = {0xff,0xff00,0xff0000,0xff000000};
u32 __max_addr_bit_list[15] = {0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000};
u32 __ddr_addr_offset = 0;
u32 __max_addr_space_bit = 0;
// remap global data to internal memory
ddr_addr_offset = (u32)&__training_data_start;
max_addr_space_bit = (u32)(&__training_data_start + sizeof(ddr_addr_offset));
byte_list[i] = (u8)(&__training_data_start + sizeof(max_addr_space_bit));
half_word_list[i] = (u16)(&__training_data_start + sizeof(byte_list));
word_list[i] = (u32)(&__training_data_start + sizeof(half_word_list));
dword_list[i] = (u64)(&__training_data_start + sizeof(word_list));
ddr_addr_offset = __ddr_addr_offset;
max_addr_space_bit = __max_addr_space_bit;
for (i = 0; i < 16; i++)
{
byte_list[i] = __byte_list[i];
half_word_list[i] = __half_word_list[i];
word_list[i] = __word_list[i];
dword_list[i] = __dword_list[i];
}
for (i = 0; i < 4; i++)
byte_mask[i] = __byte_mask[i];
for (i = 0; i < 15; i++)
max_addr_bit_list[i] = __max_addr_bit_list[i];
}
u32 find_best(void)
{
u8 dqs_ind = FAILURE; // dqs indication initialize to failure
u8 dqs_min_val = UNSET, dqs_max_val = UNSET, dqs_median = UNSET;
u8 dqs_index;
u8 wr_median_val, rd_median, rslt= FAILURE;
u32 i;
u32 wr_rslt = FAILURE;
u32 dll_num;
register int reg_0 __asm__ ("r3");
register int reg_1 __asm__ ("r4");
u32 max_mem_reg;
u64 *dst, *src;
dll_rd rd;
ddr_addr_offset = 0; // init
if ((__le64_to_cpu(*(&CS_MAP)) & 0x3) == 3) {
max_addr_space_bit = get_max_addr_space_bit();
}
for(dqs_index = LOW_DQS_OUT; dqs_index <= HIGH_DQS_OUT; dqs_index++) {// DQS loop
wr_rslt = wr_loop(dqs_index, 0);
// set min/max values;
if (wr_rslt == FAILURE) {
if ((dqs_min_val != UNSET) && (dqs_min_val==(dqs_index-1))) {
dqs_min_val = UNSET;
}
if ((dqs_min_val!=UNSET) && (dqs_max_val==UNSET)){
dqs_max_val = dqs_index-1;
break;
}
} else { // SUCCESS
if (dqs_min_val==UNSET) {
dqs_min_val = dqs_index;
dqs_ind = SUCCESS;
}
}
}
if (dqs_ind == FAILURE) {
wr_median_val = HIGH_DQS_OUT;
dqs_median = HIGH_WR_DQS;
rd.rd0 = HIGH_RD0;
rd.rd1 = HIGH_RD1;
rd.rd2 = HIGH_RD2;
rd.rd3 = HIGH_RD3;
DENALI_WR_DQS = wr_median_val;
DENALI_DQS_OUT = dqs_median;
DENALI_DQS_DELAY0 = rd.rd0;
DENALI_DQS_DELAY1 = rd.rd1;
DENALI_DQS_DELAY2 = rd.rd2;
DENALI_DQS_DELAY3 = rd.rd3;
return 0xffff;
} else { //SUCCESS
if ((dqs_min_val!=UNSET) && (dqs_max_val==UNSET)){
dqs_max_val = dqs_index-1;
}
dqs_median = (dqs_min_val + dqs_max_val)/2;
}
// end procedure
wr_median_val = wr_loop(dqs_median,1);
rd = DLL_check(dqs_median,wr_median_val,1);
if ((rd.rd0==0) || (rd.rd1==0) || (rd.rd2==0) || (rd.rd3==0)) {
wr_median_val = HIGH_DQS_OUT;
dqs_median = HIGH_WR_DQS;
rd.rd0 = HIGH_RD0;
rd.rd1 = HIGH_RD1;
rd.rd2 = HIGH_RD2;
rd.rd3 = HIGH_RD3;
DENALI_WR_DQS = wr_median_val;
DENALI_DQS_OUT = dqs_median;
DENALI_DQS_DELAY0 = rd.rd0;
DENALI_DQS_DELAY1 = rd.rd1;
DENALI_DQS_DELAY2 = rd.rd2;
DENALI_DQS_DELAY3 = rd.rd3;
return 0xffff; // failure
}
//configure median values
DENALI_WR_DQS = wr_median_val;
DENALI_DQS_OUT = dqs_median;
DENALI_DQS_DELAY0 = rd.rd0;
DENALI_DQS_DELAY1 = rd.rd1;
DENALI_DQS_DELAY2 = rd.rd2;
DENALI_DQS_DELAY3 = rd.rd3;
max_mem_reg = __le64_to_cpu(*(&AHB_MAX_MEM_REG)) & (0x80000000 - ADDR_JUMP_SIZE);
i=0;
while (ddr_addr_offset<max_mem_reg) {
i+=1;
if ((i&0xc)==0) {
rd_median = rd.rd0;
dll_num=0;
} else if ((i&0xc)==1) {
rd_median = rd.rd1;
dll_num=1;
} else if ((i&0xc)==2) {
rd_median = rd.rd2;
dll_num=2;
} else {
rd_median = rd.rd3;
dll_num=3;
}
if ((__le64_to_cpu(*(&REDUC)&0x1)==1) && ((dll_num==2) || (dll_num==3))) {
//REDUC
//half datapath mode in which DLL2 and 3 are not used.
continue;
}
switch (i & 0x3) {
case 0:
rslt = wr_rd_transaction(BYTE_SZ, dll_num, dqs_median, wr_median_val, rd_median,0);
break;
case 1:
rslt = wr_rd_transaction(HALF_WORD, dll_num, dqs_median, wr_median_val, rd_median,0);
break;
case 2:
rslt = wr_rd_transaction(WORD, dll_num, dqs_median, wr_median_val, rd_median,0);
break;
case 3:
rslt = wr_rd_transaction(DOUBLE_WORD, dll_num, dqs_median, wr_median_val, rd_median,0);
break;
};
if (rslt == FAILURE) {
wr_median_val = HIGH_DQS_OUT;
dqs_median = HIGH_WR_DQS;
rd.rd0 = HIGH_RD0;
rd.rd1 = HIGH_RD1;
rd.rd2 = HIGH_RD2;
rd.rd3 = HIGH_RD3;
DENALI_WR_DQS = wr_median_val;
DENALI_DQS_OUT = dqs_median;
DENALI_DQS_DELAY0 = rd.rd0;
DENALI_DQS_DELAY1 = rd.rd1;
DENALI_DQS_DELAY2 = rd.rd2;
DENALI_DQS_DELAY3 = rd.rd3;
return 0xffff;
}
};
//*** burst ***
for (i=0;i<16;i++) {
src = &dword_list[i];
dst = 0;
__asm__ __volatile__ ("ldmia %0, {%1,%2}" \
: "+r" (src), "=r" (reg_0), "=r" (reg_1) \
);
__asm__ __volatile__ ("stmia %0, {%1,%2}" \
: "+r" (dst), "=r" (reg_0), "=r" (reg_1) \
);
if (*src!=*dst) {
wr_median_val = HIGH_DQS_OUT;
dqs_median = HIGH_WR_DQS;
rd.rd0 = HIGH_RD0;
rd.rd1 = HIGH_RD1;
rd.rd2 = HIGH_RD2;
rd.rd3 = HIGH_RD3;
DENALI_WR_DQS = wr_median_val;
DENALI_DQS_OUT = dqs_median;
DENALI_DQS_DELAY0 = rd.rd0;
DENALI_DQS_DELAY1 = rd.rd1;
DENALI_DQS_DELAY2 = rd.rd2;
DENALI_DQS_DELAY3 = rd.rd3;
return 0xffff; //failure
}
}
return SUCCESS;
}
u32 get_max_addr_space_bit(void) {
u32 max_mem_reg;
max_mem_reg = __le32_to_cpu(*(&AHB_MAX_MEM_REG));
if ((max_mem_reg & 0x40000000) != 0) {
return 31;
} else if ((max_mem_reg & 0x20000000) != 0) {
return 30;
} else if ((max_mem_reg & 0x10000000) != 0) {
return 29;
} else if ((max_mem_reg & 0x08000000) != 0) {
return 28;
} else if ((max_mem_reg & 0x04000000) != 0) {
return 27;
} else if ((max_mem_reg & 0x02000000) != 0) {
return 26;
} else if ((max_mem_reg & 0x01000000) != 0) {
return 25;
} else if ((max_mem_reg & 0x00800000) != 0) {
return 24;
} else if ((max_mem_reg & 0x00400000) != 0) {
return 23;
} else if ((max_mem_reg & 0x00200000) != 0) {
return 22;
} else if ((max_mem_reg & 0x00100000) != 0) {
return 21;
};
return 0;
}
u32 wr_loop(u8 dqs_index, u32 find_median) {
u8 wr_index;
u32 rd_rslt = FAILURE; // rd indication initialize to failure: Failure or Success
u8 wr_min_val = UNSET , wr_max_val = UNSET;
u8 wr_median_val = FAILURE;
dll_rd rd;
for(wr_index = LOW_WR_DQS; wr_index <= HIGH_WR_DQS; wr_index++) { /* WR loop */
rd = DLL_check(dqs_index, wr_index,find_median);
rd_rslt = ((rd.rd0>0) && (rd.rd1>0) && (rd.rd2>0) && (rd.rd3>0)) ? SUCCESS : FAILURE;
if (rd_rslt == FAILURE) {
if (find_median == 1) {
if ((wr_min_val != UNSET) && (wr_min_val==(wr_index-1))) {
wr_min_val = UNSET;
}
if ((wr_min_val!=UNSET) && (wr_max_val==UNSET)) {
wr_max_val = wr_index-1;
}
if ((wr_min_val!=UNSET) && (wr_max_val!=UNSET)) {
wr_median_val = (wr_min_val+wr_max_val)/2;
return wr_median_val;
}
}
} else { // SUCCESS
if (find_median == 1) {
if (wr_min_val==UNSET) {
wr_min_val = wr_index;
}
} else {
return SUCCESS;
}
}
}
if (find_median == 1) {
if ((wr_min_val!=UNSET) && (wr_max_val==UNSET)) {
wr_max_val = wr_index-1;
wr_median_val = (wr_min_val+wr_max_val)/2;
}
};
return wr_median_val;
}
dll_rd DLL_check(u8 dqs_index, u8 wr_index, u32 find_median) {
u32 transaction_size;
u32 rslt = FAILURE, dll0_rslt = FAILURE, dll1_rslt = FAILURE, dll2_rslt = FAILURE, dll3_rslt = FAILURE;
u8 rd_index;
u32 i;
dll_rd rd;
u8 rd0_min_val=UNSET, rd1_min_val=UNSET, rd2_min_val=UNSET, rd3_min_val=UNSET;
u8 rd0_max_val=UNSET, rd1_max_val=UNSET, rd2_max_val=UNSET, rd3_max_val=UNSET;
u8 rd0_median=UNSET, rd1_median=UNSET, rd2_median=UNSET, rd3_median=UNSET;
// byte order per DLL
///////////////////////
// 0 1 2 3
// 4 5 6 7
// DLL0 DLL1 DLL2 DLL4
/////////// DLL0 //////////////
for (rd_index = LOW_RD0; rd_index <= HIGH_RD0; rd_index++) {
transaction_size = BYTE_SZ; // byte (8 bits)
for(i = 0; i <= 15; i=i+4){
rslt = wr_rd_transaction(transaction_size, i, dqs_index,wr_index,rd_index,1);
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;
}
if (rslt == SUCCESS) { // only for SUCCESS continue checking for the next transaction width
transaction_size = DOUBLE_WORD; // double-word (64 bits)
for(i = 0; i <= 15; i=i+16){
rslt = wr_rd_transaction(transaction_size, i, dqs_index,wr_index,rd_index,1);
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;
}// end of transaction_size DOUBLE_WORD
} // end of transaction_size BYTE_SZ
// find results of dll run
if (find_median == 1) {
if (rslt == FAILURE) {
if ((rd0_min_val != UNSET) && (rd0_min_val==(rd_index-1))) {
rd0_min_val = UNSET;
}
if ((rd0_min_val != UNSET) && (rd0_max_val == UNSET)) {
rd0_max_val = rd_index-1;
dll0_rslt = SUCCESS;
break;
}
} else if (rslt == SUCCESS) {
if (rd0_min_val == UNSET) {
rd0_min_val = rd_index;
}
}
} else {
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;// one SUCCESS is enough when no median calculation is needed
} // dll0 median
} // DLL0
if (rslt == SUCCESS) dll0_rslt = SUCCESS;
if (find_median == 1) {
if ((rd0_min_val != UNSET) && (rd0_max_val == UNSET)) {
rd0_max_val = rd_index-1;
}
rd0_median = (rd0_min_val + rd0_max_val)/2;
}
/////////// DLL1 //////////////
for (rd_index = LOW_RD1; rd_index <= HIGH_RD1; rd_index++) {
transaction_size = BYTE_SZ; // byte (8 bits)
for(i = 1; i <= 15; i=i+4){
rslt = wr_rd_transaction(transaction_size, i, dqs_index,wr_index,rd_index,1);
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;
}
if (rslt == SUCCESS) { // only for SUCCESS continue checking for the next transaction width
transaction_size = DOUBLE_WORD; // double-word (64 bits)
for(i = 1; i <= 15; i=i+16){
rslt = wr_rd_transaction(transaction_size, i, dqs_index,wr_index,rd_index,1);
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;
}// end of transaction_size DOUBLE_WORD
} // end of transaction_size BYTE_SZ
// find results of dll run
if (find_median == 1) {
if (rslt == FAILURE) {
if ((rd1_min_val != UNSET) && (rd1_min_val==(rd_index-1))) {
rd1_min_val = UNSET;
}
if ((rd1_min_val != UNSET) && (rd1_max_val == UNSET)) {
rd1_max_val = rd_index-1;
dll1_rslt = SUCCESS;
break;
}
} else if (rslt == SUCCESS) {
if (rd1_min_val == UNSET) {
rd1_min_val = rd_index;
}
}
} else {
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;// one SUCCESS is enough when no median calculation is needed
} // dll1 median
} // DLL1
if (rslt == SUCCESS) dll1_rslt = SUCCESS;
if (find_median == 1) {
if ((rd1_min_val != UNSET) && (rd1_max_val == UNSET)) {
rd1_max_val = rd_index-1;
}
rd1_median = (rd1_min_val + rd1_max_val)/2;
}
if ((__le64_to_cpu(*(&REDUC))&0x1)==1) {
dll2_rslt = SUCCESS;
dll3_rslt = SUCCESS;
} else {
/////////// DLL2 //////////////
for (rd_index = LOW_RD2; rd_index <= HIGH_RD2; rd_index++) {
transaction_size = BYTE_SZ; // byte (8 bits)
for(i = 2; i <= 15; i=i+4){
rslt = wr_rd_transaction(transaction_size, i, dqs_index,wr_index,rd_index,1);
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;
}
if (rslt == SUCCESS) { // only for SUCCESS continue checking for the next transaction width
transaction_size = DOUBLE_WORD; // double-word (64 bits)
for(i = 2; i <= 15; i=i+16){
rslt = wr_rd_transaction(transaction_size, i, dqs_index,wr_index,rd_index,1);
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;
}// end of transaction_size DOUBLE_WORD
} // end of transaction_size BYTE_SZ
// find results of dll run
if (find_median == 1) {
if (rslt == FAILURE) {
if ((rd2_min_val != UNSET) && (rd2_min_val==(rd_index-1))) {
rd2_min_val = UNSET;
}
if ((rd2_min_val != UNSET) && (rd2_max_val == UNSET)) {
rd2_max_val = rd_index-1;
dll2_rslt = SUCCESS;
break;
}
} else if (rslt == SUCCESS) {
if (rd2_min_val == UNSET) {
rd2_min_val = rd_index;
}
}
} else {
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;// one SUCCESS is enough when no median calculation is needed
} // dll2 median
} // DLL2
if (rslt == SUCCESS) dll2_rslt = SUCCESS;
if (find_median == 1) {
if ((rd2_min_val != UNSET) && (rd2_max_val == UNSET)) {
rd2_max_val = rd_index-1;
}
rd2_median = (rd2_min_val + rd2_max_val)/2;
}
/////////// DLL3 //////////////
for (rd_index = LOW_RD3; rd_index <= HIGH_RD3; rd_index++) {
transaction_size = BYTE_SZ; // byte (8 bits)
for(i = 3; i <= 15; i=i+4){
rslt = wr_rd_transaction(transaction_size, i, dqs_index,wr_index,rd_index,1);
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;
}
if (rslt == SUCCESS) { // only for SUCCESS continue checking for the next transaction width
transaction_size = DOUBLE_WORD; // double-word (64 bits)
for(i = 3; i <= 15; i=i+16){
rslt = wr_rd_transaction(transaction_size, i, dqs_index,wr_index,rd_index,1);
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;
}// end of transaction_size DOUBLE_WORD
} // end of transaction_size BYTE_SZ
// find results of dll run
if (find_median == 1) {
if (rslt == FAILURE) {
if ((rd3_min_val != UNSET) && (rd3_min_val==(rd_index-1))) {
rd3_min_val = UNSET;
}
if ((rd3_min_val != UNSET) && (rd3_max_val == UNSET)) {
rd3_max_val = rd_index-1;
dll3_rslt = SUCCESS;
break;
}
} else if (rslt == SUCCESS) {
if (rd3_min_val == UNSET) {
rd3_min_val = rd_index;
}
}
} else {
if (rslt == FAILURE) continue;
else if (rslt == SUCCESS) break;// one SUCCESS is enough when no median calculation is needed
} // dll3 median
} // DLL3
if (rslt == SUCCESS) dll3_rslt = SUCCESS;
if (find_median == 1) {
if ((rd3_min_val != UNSET) && (rd3_max_val == UNSET)) {
rd3_max_val = rd_index-1;
}
rd3_median = (rd3_min_val + rd3_max_val)/2;
}
}; // REDUC
// all dll found a success values for current dqs and wr values.
// For initialization: 0s indicates Failure
rd.rd0 = 0;
rd.rd1 = 0;
rd.rd2 = 0;
rd.rd3 = 0;
if ((dll0_rslt & dll1_rslt & dll2_rslt & dll3_rslt & 0x1) == 1) {//return SUCCESS;
if (find_median == 1) {
rd.rd0 = rd0_median;
rd.rd1 = rd1_median;
rd.rd2 = rd2_median;
rd.rd3 = rd3_median;
} else {
// 1s indicates Success
rd.rd0 = 1;
rd.rd1 = 1;
rd.rd2 = 1;
rd.rd3 = 1;
}
}
return rd; // 0s indicate Failure
}
u32 wr_rd_transaction(u32 transaction_size, u32 i, u8 dqs_index, u8 wr_index, u8 rd_index, u32 mask) {
u32 dll_num;
u32 ddr_addr, limit_addr;
// set values for current transaction
DENALI_WR_DQS = wr_index;
DENALI_DQS_OUT = dqs_index;
dll_num = get_dll(i);
switch (dll_num) {
case 0:DENALI_DQS_DELAY0 = rd_index;break;
case 1:DENALI_DQS_DELAY1 = rd_index;break;
case 2:DENALI_DQS_DELAY2 = rd_index;break;
case 3:DENALI_DQS_DELAY3 = rd_index;break;
};
limit_addr = __le64_to_cpu(*(&AHB_MAX_MEM_REG)) & 0x7fffffff;
ddr_addr_offset = (ddr_addr_offset + ADDR_JUMP_SIZE) & limit_addr; // limit the address space to ahb configured value.
// the address is shifted by 8 to ensure 64 byte transaction in region.
// 0x80000000 + dll_num + offset *2^ (0 for byte, 1 for half word , 2 for word, 3 for double word.)
if ((__le64_to_cpu(*(&CS_MAP)) & 0x3) == 3) {
ddr_addr = ddr_addr_offset;
// default cs#0
ddr_addr &= (~(max_addr_bit_list[max_addr_space_bit-21]));
if (actual_transaction(transaction_size, i, mask, ddr_addr, dll_num) == SUCCESS) {
// set cs#1
ddr_addr |= max_addr_bit_list[max_addr_space_bit-21];
return actual_transaction(transaction_size, i, mask, ddr_addr, dll_num);
} else {
return FAILURE;
}
} else {
return actual_transaction(transaction_size, i, mask, ddr_addr_offset, dll_num);
}
}
u32 get_dll(u32 i) {
u32 rslt=0;
switch (i) {
case 0: case 4: case 8: case 12 : rslt = 0;break;
case 1: case 5: case 9: case 13 : rslt = 1;break;
case 2: case 6: case 10: case 14: rslt = 2;break;
case 3: case 7: case 11: case 15: rslt = 3;break;
};
return rslt;
}
u32 actual_transaction(u32 transaction_size, u32 i, u32 mask, u32 ddr_addr, u32 dll_num) {
u32 rslt = FAILURE;
// per transaction width, write and read transaction.
switch (transaction_size) {
case BYTE_SZ:
if (mask == 1) {
*(&WRITE_VAL_U8+i+ddr_addr) = 0x00;
*(&WRITE_VAL_U8+i+0x10+ddr_addr) = 0xaa;
*(&WRITE_VAL_U8+i+0x20+ddr_addr) = 0x55;
if (((*(&WRITE_VAL_U8+i+ddr_addr)) & 0xff)==0x00) {
if (((*(&WRITE_VAL_U8+i+0x10+ddr_addr)) & 0xff)==0xaa) {
if (((*(&WRITE_VAL_U8+i+0x20+ddr_addr)) & 0xff)==0x55) {
rslt = SUCCESS; // per dll
}
}
}
*(&WRITE_VAL_U8+i+ddr_addr) = 0;//clear
*(&WRITE_VAL_U8+i+0x10+ddr_addr) = 0;//clear
*(&WRITE_VAL_U8+i+0x20+ddr_addr) = 0;//clear
} else {
*(&WRITE_VAL_U8+ddr_addr) = 0x00;
*(&WRITE_VAL_U8+0x10+ddr_addr) = 0xaa;
*(&WRITE_VAL_U8+0x20+ddr_addr) = 0x55;
if (*(&WRITE_VAL_U8+ddr_addr) == 0x00) {
if (*(&WRITE_VAL_U8+0x10+ddr_addr) == 0xaa) {
if (*(&WRITE_VAL_U8+0x20+ddr_addr) == 0x55) {
rslt = SUCCESS;
}
}
}
*(&WRITE_VAL_U8+ddr_addr) = 0; //clear
*(&WRITE_VAL_U8+i+0x10+ddr_addr) = 0;//clear
*(&WRITE_VAL_U8+i+0x20+ddr_addr) = 0;//clear
}
break;
case HALF_WORD: // no masking option
*(&WRITE_VAL_U16+ddr_addr) = __cpu_to_le16(0x0000);
*(&WRITE_VAL_U16+0x10+ddr_addr) = __cpu_to_le16(0xaaaa);
*(&WRITE_VAL_U16+0x20+ddr_addr) = __cpu_to_le16(0x5555);
if (__le16_to_cpu(*(&WRITE_VAL_U16+ddr_addr)) == 0x0000) {
if (__le16_to_cpu(*(&WRITE_VAL_U16+0x10+ddr_addr)) == 0xaaaa) {
if (__le16_to_cpu(*(&WRITE_VAL_U16+0x20+ddr_addr)) == 0x5555) {
rslt = SUCCESS;
}
}
}
*(&WRITE_VAL_U16+ddr_addr) = __cpu_to_le16(0); //clear
*(&WRITE_VAL_U16+i+0x10+ddr_addr) = __cpu_to_le16(0);//clear
*(&WRITE_VAL_U16+i+0x20+ddr_addr) = __cpu_to_le16(0);//clear
break;
case WORD:// no masking option
*(&WRITE_VAL_U32+ddr_addr) = __cpu_to_le32(0x00000000);
*(&WRITE_VAL_U32+0x10+ddr_addr) = __cpu_to_le32(0xaaaaaaaa);
*(&WRITE_VAL_U32+0x20+ddr_addr) = __cpu_to_le32(0x55555555);
if (__le32_to_cpu(*(&WRITE_VAL_U32+ddr_addr)) == 0x00000000) {
if (__le32_to_cpu(*(&WRITE_VAL_U32+0x10+ddr_addr)) == 0xaaaaaaaa) {
if (__le32_to_cpu(*(&WRITE_VAL_U32+0x20+ddr_addr)) == 0x55555555) {
rslt = SUCCESS;
}
}
}
*(&WRITE_VAL_U32+ddr_addr) = __cpu_to_le32(0); //clear
*(&WRITE_VAL_U32+0x10+ddr_addr) = __cpu_to_le32(0); //clear
*(&WRITE_VAL_U32+0x20+ddr_addr) = __cpu_to_le32(0); //clear
break;
case DOUBLE_WORD: // no masking : full 64 bits
*(&WRITE_VAL_U64+ddr_addr) = __cpu_to_le64(0x0000000000000000LL);
*(&WRITE_VAL_U64+0x10+ddr_addr) = __cpu_to_le64(0x2aaaaaaaaaaaaaaaLL);
*(&WRITE_VAL_U64+0x20+ddr_addr) = __cpu_to_le64(0x5555555555555555LL);
if (__le64_to_cpu(*(&WRITE_VAL_U64+ddr_addr)) == 0x0000000000000000LL) {
if (__le64_to_cpu(*(&WRITE_VAL_U64+0x10+ddr_addr)) == 0x2aaaaaaaaaaaaaaaLL) {
if (__le64_to_cpu(*(&WRITE_VAL_U64+0x20+ddr_addr)) == 0x5555555555555555LL) {
rslt = SUCCESS;
}
}
}
*(&WRITE_VAL_U64+ddr_addr) = __cpu_to_le64(0); //clear
*(&WRITE_VAL_U64+0x10+ddr_addr) = __cpu_to_le64(0); //clear
*(&WRITE_VAL_U64+0x20+ddr_addr) = __cpu_to_le64(0); //clear
break;
}; // switch transaction_size
return rslt;
}