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