blob: 1950736b63c072803ca11e7f45f6eaab20cac4dc [file] [log] [blame]
#define U32 u32
#define CODE_PROGRESS_MARKER 0x8300FF00
#define PERIPH_BASE 0xFFF00000
#define IC_DIST_BASE 0xFFF01000
#define IC_INT_BASE 0xFFF00100
void set_marker(int val)
{
*(volatile int *)CODE_PROGRESS_MARKER = val;
}
void reg_wr (volatile U32 waddr, volatile U32 data)
{
U32 *wloc;
wloc = (U32 *)waddr;
*wloc = data;
return ;
}
#if 0
U64 reg_wr_64 (U32 REG_ADDR,U64 REG_VAL)
{
volatile U64* WriteLocAddr;
U64 WriteData;
WriteLocAddr = (volatile U64*)REG_ADDR;
//tb_printf("%x\n",WriteLocAddr); // printing the write address
WriteData = REG_VAL;
*WriteLocAddr =WriteData;
return(1);
}
#endif
int reg_rd (volatile U32 raddr)
{
U32 *rloc,r_data;
rloc = (U32 *)raddr;
r_data = *rloc;
return (r_data);
}
// Procedure to test a specific Register by writing a specific Test Data Pattern to it and reading it back
// Input Parameters: reg_waddr - (Write) Address of Register
// testdata - Data to be written to and read back from the Register
// debug - Enables printing of debug information.
// Output: Boolean value if the Register Write/Read-back test passed or not
bool test_reg (volatile U32 reg_waddr, volatile U32 testdata, bool debug)
{
U32 *reg_loc; // Pointer to Register Address
U32 r_data; // 32-bit Unsigned Integer Variable to store the data read from the Register Address
if(debug) {
r_data = reg_rd(reg_waddr); // Read the data in the Register at it's Address
//printf("read_data = %x & testdata = %x\n", r_data, testdata); // Issue if Register read has X's
printf("testdata = %x\n", testdata);
}
reg_wr(reg_waddr, testdata); // Call the method to write the Test Data-Pattern to the specified Register
if(debug) {
printf("Wrote %x to %x\n", testdata, reg_waddr);
}
r_data = reg_rd(reg_waddr); // Read the data in the Register back from it's Address
if(debug) {
printf("testdata = %x data = %x\n", testdata, r_data);
}
return(r_data == testdata); // Return whether the data read-back from the Register was the same as the data written to it
}
// Procedure to test a specific 'Read-Only' Register by writing a specific Test Data Pattern to it, reading it back & making sure that it didn't get written
// Input Parameters: reg_waddr - (Write) Address of Register
// testdata - Data to be written to and read back from the Register
// debug - Enables printing of debug information.
// Output: Boolean value if the Register Write/Read-back test passed or not
bool test_reg_ro (volatile U32 reg_waddr, volatile U32 testdata, bool debug)
{
U32 *reg_loc; // Pointer to Register Address
U32 r_data, r_dataw; // 32-bit Unsigned Integer Variable to store the data read from the Register Address before and after writing to it respectively
r_data = reg_rd(reg_waddr); // Read the data in the Register at it's Address
if(debug) {
printf("Read data = %x & testdata = %x\n", r_data, testdata);
}
reg_wr(reg_waddr, testdata); // Call the method to write the Test Data-Pattern to the specified Register
if(debug) {
printf("Wrote %x to %x\n", testdata, reg_waddr);
}
r_dataw = reg_rd(reg_waddr); // Read the data in the Register back from it's Address after performing the write
if(debug) {
printf("Old read = %x & read = %x\n", r_data, r_dataw);
}
return(r_data == r_dataw); // Return whether the data read-back from the Register was the same as it's original value before the write to it
}
void reg_rmw (volatile U32 waddr, volatile U32 mask, volatile U32 data) {
U32 *rloc;
U32 data_temp, data_mod;
rloc = (U32 *)waddr;
data_temp = *rloc;
data_temp = data_temp & (~mask); // '&&' is logical AND of values, whereas '&' does "bit-wise" ANDing, which is what is required here
data_mod = data_temp | data; // || is logical OR of values, whereas | does "bit-wise" ORing, which is what is what is required here
*rloc = data_mod;
return ;
}
//----------------------------------------------------------------
// These are added by Mohd on 120411
int reg_def_val_check (volatile U32 raddr, volatile U32 rst_val) {
U32 r_data;
U32 err_cnt=0;
r_data = reg_rd(raddr);
if(r_data != rst_val)
{
printf("FAIL@ %x :Exp.DefValue= %x,Act.DefValue=%x\n",raddr,rst_val,r_data);
err_cnt=1;
}
return(err_cnt);
}
int reg_rw_check (volatile U32 addr, volatile U32 wr_data, volatile U32 cmp_val) {
U32 r_data;
U32 err_cnt=0;
reg_wr(addr,wr_data);
r_data = reg_rd(addr);
if(r_data != cmp_val)
{
printf("FAIL@ %x WrD=%x :Exp.Value=%x ,Act.Value=%x\n",addr,wr_data,cmp_val,r_data);
err_cnt=1;
}
return(err_cnt) ;
}
#if 0
//----------------------------------------------------------------
// This is added by Mohd on 140411
// This functions returns the A9-MP Core GIC- Interrupt Controller
// Distribuitors SPI status (IRQs status) can be read by following 2 ways
// [1]
// 0x304 -ICDABR0(Interrupt Controller Distribuitor Acitve Bit Register 0-[31:0]
// 0x308 -ICDABR0(Interrupt Controller Distribuitor Acitve Bit Register 1-[63:32]
// These 2 registers holds the active status of SPI interrupts IRQs[63:0]
// [2]
// 0xD04 -ICD SPI_status Register 0-[31:0]
// 0xD08 -ICD SPI_status Register 1-[63:32]
// These 2 registers holds status of SPI interrupts IRQs[63:0]
//----------------------------------------------------------------
U64 read_a9irqs_status()
{
U32 irqs_31_0_status=0;
U32 irqs_63_32_status=0;
U64 irqs_63_0_status=0;
irqs_31_0_status = reg_rd (IC_DIST_BASE + 0xD04);
//printf("irqs_31_0= %x\n",irqs_31_0_status);
//printf("%x\n",irqs_31_0_status);
irqs_63_32_status = reg_rd (IC_DIST_BASE + 0xD08);
//printf("irqs_63_32= %x\n",irqs_63_32_status);
//printf("%x\n",irqs_63_32_status);
irqs_63_0_status = (((U64)(irqs_63_32_status)<<32) | irqs_31_0_status);
printf("A9-IRQs Status:%016llx\n",irqs_63_0_status);
return(irqs_63_0_status);
}
#endif
//----------------------------------------------------------------
// Specify that the test has failed with the specified number of Errors
// Input Parameter: num_errors - Integer inidicating number of errors seen in the failed test
void fail_ctl(int num_errors) {
U32 sim_ctl_addr = 0x85FF0000; // Simulation Control Address (from sim_control.v)
U32 *sim_ctl_ptr = (U32 *)sim_ctl_addr; // Pointer to the Simulation Control Address
U32 sim_ctl_byte = 0x3; // Lowest byte of Write-data on AXI to Simulation Conrol Address that indicates that the Test passed or failed
U32 fail_msg_wdata = ((U32)num_errors << 8) + sim_ctl_byte; // Append the number of Errors in the upper portion [23:8] of the word alongwith the control byte for test-fail indication
*sim_ctl_ptr = fail_msg_wdata; // Write the Error-information message to the Simulation Control Address through the pointer-value
return;
}
// Specify that the test has passed (owing to no Errors)
void pass_ctl() {
U32 sim_ctl_addr = 0x85FF0000; // Simulation Control Address (from sim_control.v)
U32 *sim_ctl_ptr = (U32 *)sim_ctl_addr; // Pointer to the Simulation Control Address
U32 sim_ctl_byte = 0x3; // Lowest byte of Write-data on AXI to Simulation Conrol Address that indicates that the Test failed
U32 pass_msg_wdata = sim_ctl_byte; // Since there is no error count to append to theupper portiom [23:8] of the word alongwith the control byte, it means the test passed
*sim_ctl_ptr = pass_msg_wdata; // Write the Pass-information message to the Simulation Control Address through the pointer-value
return;
}
void nop (volatile int no_of_nop){
int temp, i;
temp = 0;
for(i = 0; i < no_of_nop; i++){
temp = i;
}
return;
}
interrupt_init (void){
U32 i, temp,read_val;
printf("INIT\n");
temp = reg_rd(IC_DIST_BASE + 0x004); // ICDICTR Interrupt controller Type Register
printf("Type 0x%x \n",temp );
reg_wr((IC_DIST_BASE + 0x000),0x0); // ICDDCR Distributor Control register
for (i = 0; i<= 31; i++) {
reg_wr((IC_DIST_BASE + (0x080 + i*4)),0x0); // Interrupt Security register
}
reg_wr((IC_DIST_BASE + 0x100),0xF000FFFF);
for (i = 0; i<= 6; i++) {
reg_wr((IC_DIST_BASE + (0x104 + i*4)),0xFFFFFFFF); // Interrrupt Set Enable Register ICDISERn
}
for (i = 0; i<= 57; i++) {
reg_wr((IC_DIST_BASE + (0x800 + i*4)),0x01010101); // SPI Target register
}
reg_wr((IC_INT_BASE + 0x004),0xF8); // Priority mask CPU register
temp = reg_rd(IC_INT_BASE + 0x004); // Priority mask CPU Register
printf("Prio 0x%x \n",temp );
reg_wr((IC_INT_BASE + 0x000),0x1); // ICDDCR Distributor Control register
temp = reg_rd(IC_INT_BASE + 0x000); // ICDICTR Interrupt controller Type Register
printf("En 0x%x \n",temp );
reg_wr((IC_DIST_BASE + 0x000),0x1); // ICDDCR Distributor Control register
temp = reg_rd(IC_DIST_BASE + 0x000); // ICDICTR Interrupt controller Type Register
printf("Di 0x%x \n",temp );
return;
}
// Method to write the specified pattern to the specified memory(IRAM/DDR) Start Address for the specified number of locations(size), or to Check that the test pattern is present correctly at the specified memory Start Address for the specified number of locations
// Input Parameters: start_addr - Start Address of the IRAM/DDR Memory location where we have to write the test pattern to/check the test pattern from
// size - Number of sequential (DWORD-aligned) memory addresses to be written/checked including/from the specified start address
// pattern_type - Type of test pattern to be written to/checked from the specified start address for the specified number of locations(size) [0 - Increment from 0x0, 1 - Decrement from 0xFFFF_FFFF, 2 - Rolling counter pattern of DWORD-size (0x03020100, 0x04030201, onwards), 3 - Reverse rolling counter pattern of DWORD-size (0x00010203, 0x01020304, onwards), 4 - Inverted rolling counter pattern of DWORD-size (0xFCFDFEFF, 0xFBFCFDFE, onwards) & 5 - Inverted reverse rolling counter pattern of DWORD-size (0xFFFEFDFC, 0xFEFDFCFB, onwards)]
// isWrite - Specifies if the specified test pattern is to be written to the memory (else it is used to check from memory)
// max_err_cnt - Specifies the number of errors in the Memory Pattern Check tolerates before the method stops further checking and returns [Negative values - Default maximum of 5 errors, 0 - Don't stop on hitting errors & go on until all specified memory locations have been checked]
// debug - Enables the printing of debug messages
// extra_debug - Enables the printing of extra debug messages (Enabling this automatically enables the 'debug' parameter)
void mem_pattern_gen_check(U32 start_addr, int size, int pattern_type, bool isWrite, int max_err_cnt, bool debug, bool extra_debug)
{
int i;
U32 addr, wr_data, rd_data;
int err_cnt = 5; // Count of Maximum number of errors that are allowed during pattern check (Default: 5)
// If extra debug messages are enabled, regular debug messages are also enabled
if(extra_debug)
debug = true;
// Update the maximum error count with the value specified through the parameter
if(max_err_cnt >= 0)
err_cnt = max_err_cnt;
if(debug)
{
if(isWrite) // Check if we are trying to write the test pattern to the memory address
printf("Writing the test pattern type:%d to memory locations:0x%x to 0x%x...\n", pattern_type, start_addr, (start_addr + (size * 4)));
else // Otherwise we are trying to check that a particular test pattern was received correctly at the specified address
printf("Checking the test pattern type:%d at memory locations:0x%x to 0x%x...\n", pattern_type, start_addr, (start_addr + (size * 4)));
}
// Perform the Memory's Pattern-Write/Check for specified range
for(i = 0; i < size; i++)
{
addr = (start_addr + (i * 4));
switch(pattern_type)
{
case 0: wr_data = (i % 256);
break;
case 1: wr_data = (0xFFFFFFFF - (i % 256));
break;
case 2: wr_data = ((((i+3) % 256) << 24) + (((i+2) % 256) << 16) + (((i+1) % 256) << 8) + (i % 256));
break;
case 3: wr_data = (((i % 256) << 24) + (((i+1) % 256) << 16) + (((i+2) % 256) << 8) + ((i+3) % 256));
break;
case 4: wr_data = ((((252 - i) % 256) << 24) + (((253 - i) % 256) << 16) + (((254 - i) % 256) << 8) + ((255 - i) % 256));
break;
case 5: wr_data = ((((255 - i) % 256) << 24) + (((254 - i) % 256) << 16) + (((253 - i) % 256) << 8) + ((252 - i) % 256));
break;
default: printf("Error: mem_pattern_gen_check - Unsupported Test Pattern-type:%d specified for Write!\n", pattern_type);
return;
}
// Check if we are trying to write the test pattern to the memory address
if(isWrite)
{
reg_wr(addr, wr_data);
if(extra_debug)
printf("Wrote 0x%x = 0x%x\n", addr, wr_data);
}
else // Otherwise we are trying to check that a particular test pattern was received correctly at the specified address
{
rd_data = reg_rd(addr);
if(extra_debug)
printf("Read 0x%x = 0x%x\n", addr, rd_data);
// Check if there is a pattern mismatch error
if(rd_data != wr_data)
{
printf("Error: Mem Patt Check - Addr:0x%x, Read:0x%x, Expected: 0x%x!\n", addr, rd_data, wr_data);
if(err_cnt != 0) // Check that we don't have unlimited perrmissible errors
{
if(err_cnt == 1) // Check if this was the last permissible error
{
printf("Max no. of errors hit stopping check!\n");
return;
}
else
err_cnt--; // Decrement the remaining number of errors permitted
}
}
}
}
if(debug)
{
if(isWrite)
printf("Completed test pattern writing to memory!\n");
else
{
if(err_cnt == 0)
printf("Completed memory pattern check!\n");
else
{
if(((max_err_cnt > 0) && (err_cnt == max_err_cnt)) || ((max_err_cnt < 0) && (err_cnt == 5)))
printf("Completed memory pattern check without errors!\n");
else
printf("Completed memory pattern check with %d errors!\n", (max_err_cnt - err_cnt));
}
}
}
}