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 * Store instructions: stb(x)(u), sth(x)(u), stw(x)(u) 12 * 13 * All operations are performed on a 16-byte array. The array 14 * is 4-byte aligned. The base register points to offset 8. 15 * The immediate offset (index register) ranges in [-8 ... +7]. 16 * The test cases are composed so that they do not 17 * cause alignment exceptions. 18 * The test contains a pre-built table describing all test cases. 19 * The table entry contains: 20 * the instruction opcode, the value of the index register and 21 * the value of the source register. After executing the 22 * instruction, the test verifies the contents of the array 23 * and the value of the base register (it must change for "store 24 * with update" instructions). 25 */ 26 27 #include <post.h> 28 #include "cpu_asm.h" 29 30 #if CONFIG_POST & CONFIG_SYS_POST_CPU 31 32 extern void cpu_post_exec_12w (ulong *code, ulong *op1, ulong op2, ulong op3); 33 extern void cpu_post_exec_11w (ulong *code, ulong *op1, ulong op2); 34 35 static struct cpu_post_store_s 36 { 37 ulong cmd; 38 uint width; 39 int update; 40 int index; 41 ulong offset; 42 ulong value; 43 } cpu_post_store_table[] = 44 { 45 { 46 OP_STW, 47 4, 48 0, 49 0, 50 -4, 51 0xff00ff00 52 }, 53 { 54 OP_STH, 55 2, 56 0, 57 0, 58 -2, 59 0xff00 60 }, 61 { 62 OP_STB, 63 1, 64 0, 65 0, 66 -1, 67 0xff 68 }, 69 { 70 OP_STWU, 71 4, 72 1, 73 0, 74 -4, 75 0xff00ff00 76 }, 77 { 78 OP_STHU, 79 2, 80 1, 81 0, 82 -2, 83 0xff00 84 }, 85 { 86 OP_STBU, 87 1, 88 1, 89 0, 90 -1, 91 0xff 92 }, 93 { 94 OP_STWX, 95 4, 96 0, 97 1, 98 -4, 99 0xff00ff00 100 }, 101 { 102 OP_STHX, 103 2, 104 0, 105 1, 106 -2, 107 0xff00 108 }, 109 { 110 OP_STBX, 111 1, 112 0, 113 1, 114 -1, 115 0xff 116 }, 117 { 118 OP_STWUX, 119 4, 120 1, 121 1, 122 -4, 123 0xff00ff00 124 }, 125 { 126 OP_STHUX, 127 2, 128 1, 129 1, 130 -2, 131 0xff00 132 }, 133 { 134 OP_STBUX, 135 1, 136 1, 137 1, 138 -1, 139 0xff 140 }, 141 }; 142 static unsigned int cpu_post_store_size = ARRAY_SIZE(cpu_post_store_table); 143 144 int cpu_post_test_store (void) 145 { 146 int ret = 0; 147 unsigned int i; 148 int flag = disable_interrupts(); 149 150 for (i = 0; i < cpu_post_store_size && ret == 0; i++) 151 { 152 struct cpu_post_store_s *test = cpu_post_store_table + i; 153 uchar data[16] = 154 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; 155 ulong base0 = (ulong) (data + 8); 156 ulong base = base0; 157 158 if (test->index) 159 { 160 ulong code[] = 161 { 162 ASM_12(test->cmd, 5, 3, 4), 163 ASM_BLR, 164 }; 165 166 cpu_post_exec_12w (code, &base, test->offset, test->value); 167 } 168 else 169 { 170 ulong code[] = 171 { 172 ASM_11I(test->cmd, 4, 3, test->offset), 173 ASM_BLR, 174 }; 175 176 cpu_post_exec_11w (code, &base, test->value); 177 } 178 179 if (ret == 0) 180 { 181 if (test->update) 182 ret = base == base0 + test->offset ? 0 : -1; 183 else 184 ret = base == base0 ? 0 : -1; 185 } 186 187 if (ret == 0) 188 { 189 switch (test->width) 190 { 191 case 1: 192 ret = *(uchar *)(base0 + test->offset) == test->value ? 193 0 : -1; 194 break; 195 case 2: 196 ret = *(ushort *)(base0 + test->offset) == test->value ? 197 0 : -1; 198 break; 199 case 4: 200 ret = *(ulong *)(base0 + test->offset) == test->value ? 201 0 : -1; 202 break; 203 } 204 } 205 206 if (ret != 0) 207 { 208 post_log ("Error at store test %d !\n", i); 209 } 210 } 211 212 if (flag) 213 enable_interrupts(); 214 215 return ret; 216 } 217 218 #endif 219