diff options
Diffstat (limited to 'post/cpu/cr.c')
| -rw-r--r-- | post/cpu/cr.c | 356 | 
1 files changed, 356 insertions, 0 deletions
| diff --git a/post/cpu/cr.c b/post/cpu/cr.c new file mode 100644 index 000000000..8e38729a4 --- /dev/null +++ b/post/cpu/cr.c @@ -0,0 +1,356 @@ +/* + * (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. + */ + +#ifdef CONFIG_POST + +#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; + +    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)); + +    return ret; +} + +#endif +#endif |