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