1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2002 4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 5 */ 6 7 #include <common.h> 8 9 /* 10 * CPU test 11 * Condition register istructions: mtcr, mfcr, mcrxr, 12 * crand, crandc, cror, crorc, crxor, 13 * crnand, crnor, creqv, mcrf 14 * 15 * The mtcrf/mfcr instructions is tested by loading different 16 * values into the condition register (mtcrf), moving its value 17 * to a general-purpose register (mfcr) and comparing this value 18 * with the expected one. 19 * The mcrxr instruction is tested by loading a fixed value 20 * into the XER register (mtspr), moving XER value to the 21 * condition register (mcrxr), moving it to a general-purpose 22 * register (mfcr) and comparing the value of this register with 23 * the expected one. 24 * The rest of instructions is tested by loading a fixed 25 * value into the condition register (mtcrf), executing each 26 * instruction several times to modify all 4-bit condition 27 * fields, moving the value of the conditional register to a 28 * general-purpose register (mfcr) and comparing it with the 29 * expected one. 30 */ 31 32 #include <post.h> 33 #include "cpu_asm.h" 34 35 #if CONFIG_POST & CONFIG_SYS_POST_CPU 36 37 extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); 38 extern void cpu_post_exec_21x (ulong *code, ulong *op1, ulong *op2, ulong op3); 39 40 static ulong cpu_post_cr_table1[] = 41 { 42 0xaaaaaaaa, 43 0x55555555, 44 }; 45 static unsigned int cpu_post_cr_size1 = ARRAY_SIZE(cpu_post_cr_table1); 46 47 static struct cpu_post_cr_s2 { 48 ulong xer; 49 ulong cr; 50 } cpu_post_cr_table2[] = 51 { 52 { 53 0xa0000000, 54 1 55 }, 56 { 57 0x40000000, 58 5 59 }, 60 }; 61 static unsigned int cpu_post_cr_size2 = ARRAY_SIZE(cpu_post_cr_table2); 62 63 static struct cpu_post_cr_s3 { 64 ulong cr; 65 ulong cs; 66 ulong cd; 67 ulong res; 68 } cpu_post_cr_table3[] = 69 { 70 { 71 0x01234567, 72 0, 73 4, 74 0x01230567 75 }, 76 { 77 0x01234567, 78 7, 79 0, 80 0x71234567 81 }, 82 }; 83 static unsigned int cpu_post_cr_size3 = ARRAY_SIZE(cpu_post_cr_table3); 84 85 static struct cpu_post_cr_s4 { 86 ulong cmd; 87 ulong cr; 88 ulong op1; 89 ulong op2; 90 ulong op3; 91 ulong res; 92 } cpu_post_cr_table4[] = 93 { 94 { 95 OP_CRAND, 96 0x0000ffff, 97 0, 98 16, 99 0, 100 0x0000ffff 101 }, 102 { 103 OP_CRAND, 104 0x0000ffff, 105 16, 106 17, 107 0, 108 0x8000ffff 109 }, 110 { 111 OP_CRANDC, 112 0x0000ffff, 113 0, 114 16, 115 0, 116 0x0000ffff 117 }, 118 { 119 OP_CRANDC, 120 0x0000ffff, 121 16, 122 0, 123 0, 124 0x8000ffff 125 }, 126 { 127 OP_CROR, 128 0x0000ffff, 129 0, 130 16, 131 0, 132 0x8000ffff 133 }, 134 { 135 OP_CROR, 136 0x0000ffff, 137 0, 138 1, 139 0, 140 0x0000ffff 141 }, 142 { 143 OP_CRORC, 144 0x0000ffff, 145 0, 146 16, 147 0, 148 0x0000ffff 149 }, 150 { 151 OP_CRORC, 152 0x0000ffff, 153 0, 154 0, 155 0, 156 0x8000ffff 157 }, 158 { 159 OP_CRXOR, 160 0x0000ffff, 161 0, 162 0, 163 0, 164 0x0000ffff 165 }, 166 { 167 OP_CRXOR, 168 0x0000ffff, 169 0, 170 16, 171 0, 172 0x8000ffff 173 }, 174 { 175 OP_CRNAND, 176 0x0000ffff, 177 0, 178 16, 179 0, 180 0x8000ffff 181 }, 182 { 183 OP_CRNAND, 184 0x0000ffff, 185 16, 186 17, 187 0, 188 0x0000ffff 189 }, 190 { 191 OP_CRNOR, 192 0x0000ffff, 193 0, 194 16, 195 0, 196 0x0000ffff 197 }, 198 { 199 OP_CRNOR, 200 0x0000ffff, 201 0, 202 1, 203 0, 204 0x8000ffff 205 }, 206 { 207 OP_CREQV, 208 0x0000ffff, 209 0, 210 0, 211 0, 212 0x8000ffff 213 }, 214 { 215 OP_CREQV, 216 0x0000ffff, 217 0, 218 16, 219 0, 220 0x0000ffff 221 }, 222 }; 223 static unsigned int cpu_post_cr_size4 = ARRAY_SIZE(cpu_post_cr_table4); 224 225 int cpu_post_test_cr (void) 226 { 227 int ret = 0; 228 unsigned int i; 229 unsigned long cr_sav; 230 int flag = disable_interrupts(); 231 232 asm ( "mfcr %0" : "=r" (cr_sav) : ); 233 234 for (i = 0; i < cpu_post_cr_size1 && ret == 0; i++) 235 { 236 ulong cr = cpu_post_cr_table1[i]; 237 ulong res; 238 239 unsigned long code[] = 240 { 241 ASM_MTCR(3), 242 ASM_MFCR(3), 243 ASM_BLR, 244 }; 245 246 cpu_post_exec_11 (code, &res, cr); 247 248 ret = res == cr ? 0 : -1; 249 250 if (ret != 0) 251 { 252 post_log ("Error at cr1 test %d !\n", i); 253 } 254 } 255 256 for (i = 0; i < cpu_post_cr_size2 && ret == 0; i++) 257 { 258 struct cpu_post_cr_s2 *test = cpu_post_cr_table2 + i; 259 ulong res; 260 ulong xer; 261 262 unsigned long code[] = 263 { 264 ASM_MTXER(3), 265 ASM_MCRXR(test->cr), 266 ASM_MFCR(3), 267 ASM_MFXER(4), 268 ASM_BLR, 269 }; 270 271 cpu_post_exec_21x (code, &res, &xer, test->xer); 272 273 ret = xer == 0 && ((res << (4 * test->cr)) & 0xe0000000) == test->xer ? 274 0 : -1; 275 276 if (ret != 0) 277 { 278 post_log ("Error at cr2 test %d !\n", i); 279 } 280 } 281 282 for (i = 0; i < cpu_post_cr_size3 && ret == 0; i++) 283 { 284 struct cpu_post_cr_s3 *test = cpu_post_cr_table3 + i; 285 ulong res; 286 287 unsigned long code[] = 288 { 289 ASM_MTCR(3), 290 ASM_MCRF(test->cd, test->cs), 291 ASM_MFCR(3), 292 ASM_BLR, 293 }; 294 295 cpu_post_exec_11 (code, &res, test->cr); 296 297 ret = res == test->res ? 0 : -1; 298 299 if (ret != 0) 300 { 301 post_log ("Error at cr3 test %d !\n", i); 302 } 303 } 304 305 for (i = 0; i < cpu_post_cr_size4 && ret == 0; i++) 306 { 307 struct cpu_post_cr_s4 *test = cpu_post_cr_table4 + i; 308 ulong res; 309 310 unsigned long code[] = 311 { 312 ASM_MTCR(3), 313 ASM_12F(test->cmd, test->op3, test->op1, test->op2), 314 ASM_MFCR(3), 315 ASM_BLR, 316 }; 317 318 cpu_post_exec_11 (code, &res, test->cr); 319 320 ret = res == test->res ? 0 : -1; 321 322 if (ret != 0) 323 { 324 post_log ("Error at cr4 test %d !\n", i); 325 } 326 } 327 328 asm ( "mtcr %0" : : "r" (cr_sav)); 329 330 if (flag) 331 enable_interrupts(); 332 333 return ret; 334 } 335 336 #endif 337