1 /* 2 * (C) Copyright 2002 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 10 /* 11 * CPU test 12 * Store instructions: stb(x)(u), sth(x)(u), stw(x)(u) 13 * 14 * All operations are performed on a 16-byte array. The array 15 * is 4-byte aligned. The base register points to offset 8. 16 * The immediate offset (index register) ranges in [-8 ... +7]. 17 * The test cases are composed so that they do not 18 * cause alignment exceptions. 19 * The test contains a pre-built table describing all test cases. 20 * The table entry contains: 21 * the instruction opcode, the value of the index register and 22 * the value of the source register. After executing the 23 * instruction, the test verifies the contents of the array 24 * and the value of the base register (it must change for "store 25 * with update" instructions). 26 */ 27 28 #include <post.h> 29 #include "cpu_asm.h" 30 31 #if CONFIG_POST & CONFIG_SYS_POST_CPU 32 33 extern void cpu_post_exec_12w (ulong *code, ulong *op1, ulong op2, ulong op3); 34 extern void cpu_post_exec_11w (ulong *code, ulong *op1, ulong op2); 35 36 static struct cpu_post_store_s 37 { 38 ulong cmd; 39 uint width; 40 int update; 41 int index; 42 ulong offset; 43 ulong value; 44 } cpu_post_store_table[] = 45 { 46 { 47 OP_STW, 48 4, 49 0, 50 0, 51 -4, 52 0xff00ff00 53 }, 54 { 55 OP_STH, 56 2, 57 0, 58 0, 59 -2, 60 0xff00 61 }, 62 { 63 OP_STB, 64 1, 65 0, 66 0, 67 -1, 68 0xff 69 }, 70 { 71 OP_STWU, 72 4, 73 1, 74 0, 75 -4, 76 0xff00ff00 77 }, 78 { 79 OP_STHU, 80 2, 81 1, 82 0, 83 -2, 84 0xff00 85 }, 86 { 87 OP_STBU, 88 1, 89 1, 90 0, 91 -1, 92 0xff 93 }, 94 { 95 OP_STWX, 96 4, 97 0, 98 1, 99 -4, 100 0xff00ff00 101 }, 102 { 103 OP_STHX, 104 2, 105 0, 106 1, 107 -2, 108 0xff00 109 }, 110 { 111 OP_STBX, 112 1, 113 0, 114 1, 115 -1, 116 0xff 117 }, 118 { 119 OP_STWUX, 120 4, 121 1, 122 1, 123 -4, 124 0xff00ff00 125 }, 126 { 127 OP_STHUX, 128 2, 129 1, 130 1, 131 -2, 132 0xff00 133 }, 134 { 135 OP_STBUX, 136 1, 137 1, 138 1, 139 -1, 140 0xff 141 }, 142 }; 143 static unsigned int cpu_post_store_size = ARRAY_SIZE(cpu_post_store_table); 144 145 int cpu_post_test_store (void) 146 { 147 int ret = 0; 148 unsigned int i; 149 int flag = disable_interrupts(); 150 151 for (i = 0; i < cpu_post_store_size && ret == 0; i++) 152 { 153 struct cpu_post_store_s *test = cpu_post_store_table + i; 154 uchar data[16] = 155 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; 156 ulong base0 = (ulong) (data + 8); 157 ulong base = base0; 158 159 if (test->index) 160 { 161 ulong code[] = 162 { 163 ASM_12(test->cmd, 5, 3, 4), 164 ASM_BLR, 165 }; 166 167 cpu_post_exec_12w (code, &base, test->offset, test->value); 168 } 169 else 170 { 171 ulong code[] = 172 { 173 ASM_11I(test->cmd, 4, 3, test->offset), 174 ASM_BLR, 175 }; 176 177 cpu_post_exec_11w (code, &base, test->value); 178 } 179 180 if (ret == 0) 181 { 182 if (test->update) 183 ret = base == base0 + test->offset ? 0 : -1; 184 else 185 ret = base == base0 ? 0 : -1; 186 } 187 188 if (ret == 0) 189 { 190 switch (test->width) 191 { 192 case 1: 193 ret = *(uchar *)(base0 + test->offset) == test->value ? 194 0 : -1; 195 break; 196 case 2: 197 ret = *(ushort *)(base0 + test->offset) == test->value ? 198 0 : -1; 199 break; 200 case 4: 201 ret = *(ulong *)(base0 + test->offset) == test->value ? 202 0 : -1; 203 break; 204 } 205 } 206 207 if (ret != 0) 208 { 209 post_log ("Error at store test %d !\n", i); 210 } 211 } 212 213 if (flag) 214 enable_interrupts(); 215 216 return ret; 217 } 218 219 #endif 220