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