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 * Branch instructions: b, bl, bc 13 * 14 * The first 2 instructions (b, bl) are verified by jumping 15 * to a fixed address and checking whether control was transferred 16 * to that very point. For the bl instruction the value of the 17 * link register is checked as well (using mfspr). 18 * To verify the bc instruction various combinations of the BI/BO 19 * fields, the CTR and the condition register values are 20 * checked. The list of such combinations is pre-built and 21 * linked in U-Boot at build time. 22 */ 23 24 #include <post.h> 25 #include "cpu_asm.h" 26 27 #if CONFIG_POST & CONFIG_SYS_POST_CPU 28 29 extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); 30 extern void cpu_post_exec_31 (ulong *code, ulong *ctr, ulong *lr, ulong *jump, 31 ulong cr); 32 33 static int cpu_post_test_bc (ulong cmd, ulong bo, ulong bi, 34 int pjump, int decr, int link, ulong pctr, ulong cr) 35 { 36 int ret = 0; 37 ulong lr = 0; 38 ulong ctr = pctr; 39 ulong jump; 40 41 unsigned long code[] = 42 { 43 ASM_MTCR(6), 44 ASM_MFLR(6), 45 ASM_MTCTR(3), 46 ASM_MTLR(4), 47 ASM_LI(5, 1), 48 ASM_3O(cmd, bo, bi, 8), 49 ASM_LI(5, 0), 50 ASM_MFCTR(3), 51 ASM_MFLR(4), 52 ASM_MTLR(6), 53 ASM_BLR, 54 }; 55 56 cpu_post_exec_31 (code, &ctr, &lr, &jump, cr); 57 58 if (ret == 0) 59 ret = pjump == jump ? 0 : -1; 60 if (ret == 0) 61 { 62 if (decr) 63 ret = pctr == ctr + 1 ? 0 : -1; 64 else 65 ret = pctr == ctr ? 0 : -1; 66 } 67 if (ret == 0) 68 { 69 if (link) 70 ret = lr == (ulong) code + 24 ? 0 : -1; 71 else 72 ret = lr == 0 ? 0 : -1; 73 } 74 75 return ret; 76 } 77 78 int cpu_post_test_b (void) 79 { 80 int ret = 0; 81 unsigned int i; 82 int flag = disable_interrupts(); 83 84 if (ret == 0) 85 { 86 ulong code[] = 87 { 88 ASM_MFLR(4), 89 ASM_MTLR(3), 90 ASM_B(4), 91 ASM_MFLR(3), 92 ASM_MTLR(4), 93 ASM_BLR, 94 }; 95 ulong res; 96 97 cpu_post_exec_11 (code, &res, 0); 98 99 ret = res == 0 ? 0 : -1; 100 101 if (ret != 0) 102 { 103 post_log ("Error at b1 test !\n"); 104 } 105 } 106 107 if (ret == 0) 108 { 109 ulong code[] = 110 { 111 ASM_MFLR(4), 112 ASM_MTLR(3), 113 ASM_BL(4), 114 ASM_MFLR(3), 115 ASM_MTLR(4), 116 ASM_BLR, 117 }; 118 ulong res; 119 120 cpu_post_exec_11 (code, &res, 0); 121 122 ret = res == (ulong)code + 12 ? 0 : -1; 123 124 if (ret != 0) 125 { 126 post_log ("Error at b2 test !\n"); 127 } 128 } 129 130 if (ret == 0) 131 { 132 ulong cc, cd; 133 int cond; 134 ulong ctr; 135 int link; 136 137 i = 0; 138 139 for (cc = 0; cc < 4 && ret == 0; cc++) 140 { 141 for (cd = 0; cd < 4 && ret == 0; cd++) 142 { 143 for (link = 0; link <= 1 && ret == 0; link++) 144 { 145 for (cond = 0; cond <= 1 && ret == 0; cond++) 146 { 147 for (ctr = 1; ctr <= 2 && ret == 0; ctr++) 148 { 149 int decr = cd < 2; 150 int cr = cond ? 0x80000000 : 0x00000000; 151 int jumpc = cc >= 2 || 152 (cc == 0 && !cond) || 153 (cc == 1 && cond); 154 int jumpd = cd >= 2 || 155 (cd == 0 && ctr != 1) || 156 (cd == 1 && ctr == 1); 157 int jump = jumpc && jumpd; 158 159 ret = cpu_post_test_bc (link ? OP_BCL : OP_BC, 160 (cc << 3) + (cd << 1), 0, jump, decr, link, 161 ctr, cr); 162 163 if (ret != 0) 164 { 165 post_log ("Error at b3 test %d !\n", i); 166 } 167 168 i++; 169 } 170 } 171 } 172 } 173 } 174 } 175 176 if (flag) 177 enable_interrupts(); 178 179 return ret; 180 } 181 182 #endif 183