1 /* 2 * (C) Copyright 2002 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24 #include <common.h> 25 26 /* 27 * CPU test 28 * Branch instructions: b, bl, bc 29 * 30 * The first 2 instructions (b, bl) are verified by jumping 31 * to a fixed address and checking whether control was transfered 32 * to that very point. For the bl instruction the value of the 33 * link register is checked as well (using mfspr). 34 * To verify the bc instruction various combinations of the BI/BO 35 * fields, the CTR and the condition register values are 36 * checked. The list of such combinations is pre-built and 37 * linked in U-Boot at build time. 38 */ 39 40 #include <post.h> 41 #include "cpu_asm.h" 42 43 #if CONFIG_POST & CONFIG_SYS_POST_CPU 44 45 extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); 46 extern void cpu_post_exec_31 (ulong *code, ulong *ctr, ulong *lr, ulong *jump, 47 ulong cr); 48 49 static int cpu_post_test_bc (ulong cmd, ulong bo, ulong bi, 50 int pjump, int decr, int link, ulong pctr, ulong cr) 51 { 52 int ret = 0; 53 ulong lr = 0; 54 ulong ctr = pctr; 55 ulong jump; 56 57 unsigned long code[] = 58 { 59 ASM_MTCR(6), 60 ASM_MFLR(6), 61 ASM_MTCTR(3), 62 ASM_MTLR(4), 63 ASM_LI(5, 1), 64 ASM_3O(cmd, bo, bi, 8), 65 ASM_LI(5, 0), 66 ASM_MFCTR(3), 67 ASM_MFLR(4), 68 ASM_MTLR(6), 69 ASM_BLR, 70 }; 71 72 cpu_post_exec_31 (code, &ctr, &lr, &jump, cr); 73 74 if (ret == 0) 75 ret = pjump == jump ? 0 : -1; 76 if (ret == 0) 77 { 78 if (decr) 79 ret = pctr == ctr + 1 ? 0 : -1; 80 else 81 ret = pctr == ctr ? 0 : -1; 82 } 83 if (ret == 0) 84 { 85 if (link) 86 ret = lr == (ulong) code + 24 ? 0 : -1; 87 else 88 ret = lr == 0 ? 0 : -1; 89 } 90 91 return ret; 92 } 93 94 int cpu_post_test_b (void) 95 { 96 int ret = 0; 97 unsigned int i; 98 int flag = disable_interrupts(); 99 100 if (ret == 0) 101 { 102 ulong code[] = 103 { 104 ASM_MFLR(4), 105 ASM_MTLR(3), 106 ASM_B(4), 107 ASM_MFLR(3), 108 ASM_MTLR(4), 109 ASM_BLR, 110 }; 111 ulong res; 112 113 cpu_post_exec_11 (code, &res, 0); 114 115 ret = res == 0 ? 0 : -1; 116 117 if (ret != 0) 118 { 119 post_log ("Error at b1 test !\n"); 120 } 121 } 122 123 if (ret == 0) 124 { 125 ulong code[] = 126 { 127 ASM_MFLR(4), 128 ASM_MTLR(3), 129 ASM_BL(4), 130 ASM_MFLR(3), 131 ASM_MTLR(4), 132 ASM_BLR, 133 }; 134 ulong res; 135 136 cpu_post_exec_11 (code, &res, 0); 137 138 ret = res == (ulong)code + 12 ? 0 : -1; 139 140 if (ret != 0) 141 { 142 post_log ("Error at b2 test !\n"); 143 } 144 } 145 146 if (ret == 0) 147 { 148 ulong cc, cd; 149 int cond; 150 ulong ctr; 151 int link; 152 153 i = 0; 154 155 for (cc = 0; cc < 4 && ret == 0; cc++) 156 { 157 for (cd = 0; cd < 4 && ret == 0; cd++) 158 { 159 for (link = 0; link <= 1 && ret == 0; link++) 160 { 161 for (cond = 0; cond <= 1 && ret == 0; cond++) 162 { 163 for (ctr = 1; ctr <= 2 && ret == 0; ctr++) 164 { 165 int decr = cd < 2; 166 int cr = cond ? 0x80000000 : 0x00000000; 167 int jumpc = cc >= 2 || 168 (cc == 0 && !cond) || 169 (cc == 1 && cond); 170 int jumpd = cd >= 2 || 171 (cd == 0 && ctr != 1) || 172 (cd == 1 && ctr == 1); 173 int jump = jumpc && jumpd; 174 175 ret = cpu_post_test_bc (link ? OP_BCL : OP_BC, 176 (cc << 3) + (cd << 1), 0, jump, decr, link, 177 ctr, cr); 178 179 if (ret != 0) 180 { 181 post_log ("Error at b3 test %d !\n", i); 182 } 183 184 i++; 185 } 186 } 187 } 188 } 189 } 190 } 191 192 if (flag) 193 enable_interrupts(); 194 195 return ret; 196 } 197 198 #endif 199