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