u-boot/post/lib_ppc/cr.c
Stefan Roese 86446d3a5d POST: Add disable interrupts in some of the missing CPU POST tests
Some CPU POST tests did not disable the interrupts while running. This
seems to be necessary to protect this self modifying code.

Signed-off-by: Stefan Roese <sr@denx.de>
2008-07-20 23:00:22 +02:00

357 lines
5.8 KiB
C

/*
* (C) Copyright 2002
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* 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>
/*
* CPU test
* Condition register istructions: mtcr, mfcr, mcrxr,
* crand, crandc, cror, crorc, crxor,
* crnand, crnor, creqv, mcrf
*
* The mtcrf/mfcr instructions is tested by loading different
* values into the condition register (mtcrf), moving its value
* to a general-purpose register (mfcr) and comparing this value
* with the expected one.
* The mcrxr instruction is tested by loading a fixed value
* into the XER register (mtspr), moving XER value to the
* condition register (mcrxr), moving it to a general-purpose
* register (mfcr) and comparing the value of this register with
* the expected one.
* The rest of instructions is tested by loading a fixed
* value into the condition register (mtcrf), executing each
* instruction several times to modify all 4-bit condition
* fields, moving the value of the conditional register to a
* general-purpose register (mfcr) and comparing it with the
* expected one.
*/
#include <post.h>
#include "cpu_asm.h"
#if CONFIG_POST & CFG_POST_CPU
extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1);
extern void cpu_post_exec_21x (ulong *code, ulong *op1, ulong *op2, ulong op3);
static ulong cpu_post_cr_table1[] =
{
0xaaaaaaaa,
0x55555555,
};
static unsigned int cpu_post_cr_size1 =
sizeof (cpu_post_cr_table1) / sizeof (ulong);
static struct cpu_post_cr_s2 {
ulong xer;
ulong cr;
} cpu_post_cr_table2[] =
{
{
0xa0000000,
1
},
{
0x40000000,
5
},
};
static unsigned int cpu_post_cr_size2 =
sizeof (cpu_post_cr_table2) / sizeof (struct cpu_post_cr_s2);
static struct cpu_post_cr_s3 {
ulong cr;
ulong cs;
ulong cd;
ulong res;
} cpu_post_cr_table3[] =
{
{
0x01234567,
0,
4,
0x01230567
},
{
0x01234567,
7,
0,
0x71234567
},
};
static unsigned int cpu_post_cr_size3 =
sizeof (cpu_post_cr_table3) / sizeof (struct cpu_post_cr_s3);
static struct cpu_post_cr_s4 {
ulong cmd;
ulong cr;
ulong op1;
ulong op2;
ulong op3;
ulong res;
} cpu_post_cr_table4[] =
{
{
OP_CRAND,
0x0000ffff,
0,
16,
0,
0x0000ffff
},
{
OP_CRAND,
0x0000ffff,
16,
17,
0,
0x8000ffff
},
{
OP_CRANDC,
0x0000ffff,
0,
16,
0,
0x0000ffff
},
{
OP_CRANDC,
0x0000ffff,
16,
0,
0,
0x8000ffff
},
{
OP_CROR,
0x0000ffff,
0,
16,
0,
0x8000ffff
},
{
OP_CROR,
0x0000ffff,
0,
1,
0,
0x0000ffff
},
{
OP_CRORC,
0x0000ffff,
0,
16,
0,
0x0000ffff
},
{
OP_CRORC,
0x0000ffff,
0,
0,
0,
0x8000ffff
},
{
OP_CRXOR,
0x0000ffff,
0,
0,
0,
0x0000ffff
},
{
OP_CRXOR,
0x0000ffff,
0,
16,
0,
0x8000ffff
},
{
OP_CRNAND,
0x0000ffff,
0,
16,
0,
0x8000ffff
},
{
OP_CRNAND,
0x0000ffff,
16,
17,
0,
0x0000ffff
},
{
OP_CRNOR,
0x0000ffff,
0,
16,
0,
0x0000ffff
},
{
OP_CRNOR,
0x0000ffff,
0,
1,
0,
0x8000ffff
},
{
OP_CREQV,
0x0000ffff,
0,
0,
0,
0x8000ffff
},
{
OP_CREQV,
0x0000ffff,
0,
16,
0,
0x0000ffff
},
};
static unsigned int cpu_post_cr_size4 =
sizeof (cpu_post_cr_table4) / sizeof (struct cpu_post_cr_s4);
int cpu_post_test_cr (void)
{
int ret = 0;
unsigned int i;
unsigned long cr_sav;
int flag = disable_interrupts();
asm ( "mfcr %0" : "=r" (cr_sav) : );
for (i = 0; i < cpu_post_cr_size1 && ret == 0; i++)
{
ulong cr = cpu_post_cr_table1[i];
ulong res;
unsigned long code[] =
{
ASM_MTCR(3),
ASM_MFCR(3),
ASM_BLR,
};
cpu_post_exec_11 (code, &res, cr);
ret = res == cr ? 0 : -1;
if (ret != 0)
{
post_log ("Error at cr1 test %d !\n", i);
}
}
for (i = 0; i < cpu_post_cr_size2 && ret == 0; i++)
{
struct cpu_post_cr_s2 *test = cpu_post_cr_table2 + i;
ulong res;
ulong xer;
unsigned long code[] =
{
ASM_MTXER(3),
ASM_MCRXR(test->cr),
ASM_MFCR(3),
ASM_MFXER(4),
ASM_BLR,
};
cpu_post_exec_21x (code, &res, &xer, test->xer);
ret = xer == 0 && ((res << (4 * test->cr)) & 0xe0000000) == test->xer ?
0 : -1;
if (ret != 0)
{
post_log ("Error at cr2 test %d !\n", i);
}
}
for (i = 0; i < cpu_post_cr_size3 && ret == 0; i++)
{
struct cpu_post_cr_s3 *test = cpu_post_cr_table3 + i;
ulong res;
unsigned long code[] =
{
ASM_MTCR(3),
ASM_MCRF(test->cd, test->cs),
ASM_MFCR(3),
ASM_BLR,
};
cpu_post_exec_11 (code, &res, test->cr);
ret = res == test->res ? 0 : -1;
if (ret != 0)
{
post_log ("Error at cr3 test %d !\n", i);
}
}
for (i = 0; i < cpu_post_cr_size4 && ret == 0; i++)
{
struct cpu_post_cr_s4 *test = cpu_post_cr_table4 + i;
ulong res;
unsigned long code[] =
{
ASM_MTCR(3),
ASM_12F(test->cmd, test->op3, test->op1, test->op2),
ASM_MFCR(3),
ASM_BLR,
};
cpu_post_exec_11 (code, &res, test->cr);
ret = res == test->res ? 0 : -1;
if (ret != 0)
{
post_log ("Error at cr4 test %d !\n", i);
}
}
asm ( "mtcr %0" : : "r" (cr_sav));
if (flag)
enable_interrupts();
return ret;
}
#endif