blob: ebb620590e3f6e3c1502536a5dbd46fa5a38e672 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenka042ac82002-09-12 22:36:57 +00002/*
3 * (C) Copyright 2002
4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
wdenka042ac82002-09-12 22:36:57 +00005 */
6
7#include <common.h>
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +02008#include <stdio_dev.h>
wdenka042ac82002-09-12 22:36:57 +00009#include <watchdog.h>
Christian Rieschc90a4dd2011-12-09 16:54:02 +010010#include <div64.h>
wdenka042ac82002-09-12 22:36:57 +000011#include <post.h>
12
Mike Frysinger9146d132011-05-10 07:01:21 +000013#ifdef CONFIG_SYS_POST_HOTKEYS_GPIO
14#include <asm/gpio.h>
15#endif
16
Wolfgang Denkd87080b2006-03-31 18:32:53 +020017DECLARE_GLOBAL_DATA_PTR;
18
wdenka042ac82002-09-12 22:36:57 +000019#define POST_MAX_NUMBER 32
20
21#define BOOTMODE_MAGIC 0xDEAD0000
22
Heiko Schochere92372c2011-10-12 01:18:05 +000023int post_init_f(void)
wdenk4532cb62003-04-27 22:52:51 +000024{
wdenk4532cb62003-04-27 22:52:51 +000025 int res = 0;
26 unsigned int i;
27
28 for (i = 0; i < post_list_size; i++) {
29 struct post_test *test = post_list + i;
30
Wolfgang Denk50da8372011-10-29 09:42:22 +000031 if (test->init_f && test->init_f())
wdenk4532cb62003-04-27 22:52:51 +000032 res = -1;
wdenk4532cb62003-04-27 22:52:51 +000033 }
wdenk8bde7f72003-06-27 21:31:46 +000034
wdenk4532cb62003-04-27 22:52:51 +000035 gd->post_init_f_time = post_time_ms(0);
36 if (!gd->post_init_f_time)
Heiko Schochere92372c2011-10-12 01:18:05 +000037 printf("%s: post_time_ms not implemented\n", __FILE__);
wdenk4532cb62003-04-27 22:52:51 +000038
39 return res;
40}
41
Stefan Roese39ff7d52009-12-03 06:24:30 +010042/*
43 * Supply a default implementation for post_hotkeys_pressed() for boards
44 * without hotkey support. We always return 0 here, so that the
45 * long-running tests won't be started.
46 *
47 * Boards with hotkey support can override this weak default function
48 * by defining one in their board specific code.
49 */
Jeroen Hofstee002ad7b2014-10-08 22:57:25 +020050__weak int post_hotkeys_pressed(void)
Stefan Roese39ff7d52009-12-03 06:24:30 +010051{
Mike Frysinger9146d132011-05-10 07:01:21 +000052#ifdef CONFIG_SYS_POST_HOTKEYS_GPIO
53 int ret;
54 unsigned gpio = CONFIG_SYS_POST_HOTKEYS_GPIO;
55
56 ret = gpio_request(gpio, "hotkeys");
57 if (ret) {
58 printf("POST: gpio hotkey request failed\n");
59 return 0;
60 }
61
62 gpio_direction_input(gpio);
63 ret = gpio_get_value(gpio);
64 gpio_free(gpio);
65
66 return ret;
67#endif
68
Stefan Roese39ff7d52009-12-03 06:24:30 +010069 return 0; /* No hotkeys supported */
70}
Stefan Roese39ff7d52009-12-03 06:24:30 +010071
Heiko Schochere92372c2011-10-12 01:18:05 +000072void post_bootmode_init(void)
wdenka042ac82002-09-12 22:36:57 +000073{
Heiko Schochere92372c2011-10-12 01:18:05 +000074 int bootmode = post_bootmode_get(0);
wdenk27b207f2003-07-24 23:38:38 +000075 int newword;
wdenk42d1f032003-10-15 23:53:47 +000076
Heiko Schochere92372c2011-10-12 01:18:05 +000077 if (post_hotkeys_pressed() && !(bootmode & POST_POWERTEST))
wdenk27b207f2003-07-24 23:38:38 +000078 newword = BOOTMODE_MAGIC | POST_SLOWTEST;
Heiko Schochere92372c2011-10-12 01:18:05 +000079 else if (bootmode == 0)
wdenk27b207f2003-07-24 23:38:38 +000080 newword = BOOTMODE_MAGIC | POST_POWERON;
Heiko Schochere92372c2011-10-12 01:18:05 +000081 else if (bootmode == POST_POWERON || bootmode == POST_SLOWTEST)
wdenk27b207f2003-07-24 23:38:38 +000082 newword = BOOTMODE_MAGIC | POST_NORMAL;
Heiko Schochere92372c2011-10-12 01:18:05 +000083 else
wdenk27b207f2003-07-24 23:38:38 +000084 /* Use old value */
Wolfgang Denk50da8372011-10-29 09:42:22 +000085 newword = post_word_load() & ~POST_COLDBOOT;
wdenka042ac82002-09-12 22:36:57 +000086
wdenk27b207f2003-07-24 23:38:38 +000087 if (bootmode == 0)
wdenk27b207f2003-07-24 23:38:38 +000088 /* We are booting after power-on */
89 newword |= POST_COLDBOOT;
wdenk27b207f2003-07-24 23:38:38 +000090
Heiko Schochere92372c2011-10-12 01:18:05 +000091 post_word_store(newword);
wdenk27b207f2003-07-24 23:38:38 +000092
wdenk228f29a2002-12-08 09:53:23 +000093 /* Reset activity record */
94 gd->post_log_word = 0;
Valentin Longchamp79843952011-08-03 02:37:01 +000095 gd->post_log_res = 0;
wdenka042ac82002-09-12 22:36:57 +000096}
97
Heiko Schochere92372c2011-10-12 01:18:05 +000098int post_bootmode_get(unsigned int *last_test)
wdenka042ac82002-09-12 22:36:57 +000099{
Heiko Schochere92372c2011-10-12 01:18:05 +0000100 unsigned long word = post_word_load();
wdenka042ac82002-09-12 22:36:57 +0000101 int bootmode;
102
Heiko Schochere92372c2011-10-12 01:18:05 +0000103 if ((word & 0xFFFF0000) != BOOTMODE_MAGIC)
wdenka042ac82002-09-12 22:36:57 +0000104 return 0;
wdenka042ac82002-09-12 22:36:57 +0000105
wdenk27b207f2003-07-24 23:38:38 +0000106 bootmode = word & 0x7F;
wdenka042ac82002-09-12 22:36:57 +0000107
Heiko Schochere92372c2011-10-12 01:18:05 +0000108 if (last_test && (bootmode & POST_POWERTEST))
wdenka042ac82002-09-12 22:36:57 +0000109 *last_test = (word >> 8) & 0xFF;
wdenka042ac82002-09-12 22:36:57 +0000110
111 return bootmode;
112}
113
wdenk228f29a2002-12-08 09:53:23 +0000114/* POST tests run before relocation only mark status bits .... */
Heiko Schochere92372c2011-10-12 01:18:05 +0000115static void post_log_mark_start(unsigned long testid)
wdenk228f29a2002-12-08 09:53:23 +0000116{
Valentin Longchamp79843952011-08-03 02:37:01 +0000117 gd->post_log_word |= testid;
wdenk228f29a2002-12-08 09:53:23 +0000118}
119
Heiko Schochere92372c2011-10-12 01:18:05 +0000120static void post_log_mark_succ(unsigned long testid)
wdenk228f29a2002-12-08 09:53:23 +0000121{
Valentin Longchamp79843952011-08-03 02:37:01 +0000122 gd->post_log_res |= testid;
wdenk228f29a2002-12-08 09:53:23 +0000123}
124
125/* ... and the messages are output once we are relocated */
Heiko Schochere92372c2011-10-12 01:18:05 +0000126void post_output_backlog(void)
wdenk228f29a2002-12-08 09:53:23 +0000127{
wdenk228f29a2002-12-08 09:53:23 +0000128 int j;
129
130 for (j = 0; j < post_list_size; j++) {
Valentin Longchamp79843952011-08-03 02:37:01 +0000131 if (gd->post_log_word & (post_list[j].testid)) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000132 post_log("POST %s ", post_list[j].cmd);
Valentin Longchamp79843952011-08-03 02:37:01 +0000133 if (gd->post_log_res & post_list[j].testid)
Wolfgang Denk50da8372011-10-29 09:42:22 +0000134 post_log("PASSED\n");
wdenk63e73c92004-02-23 22:22:28 +0000135 else {
Heiko Schochere92372c2011-10-12 01:18:05 +0000136 post_log("FAILED\n");
Simon Glass770605e2012-02-13 13:51:18 +0000137 bootstage_error(BOOTSTAGE_ID_POST_FAIL_R);
wdenk63e73c92004-02-23 22:22:28 +0000138 }
wdenk228f29a2002-12-08 09:53:23 +0000139 }
140 }
141}
142
Heiko Schochere92372c2011-10-12 01:18:05 +0000143static void post_bootmode_test_on(unsigned int last_test)
wdenka042ac82002-09-12 22:36:57 +0000144{
Heiko Schochere92372c2011-10-12 01:18:05 +0000145 unsigned long word = post_word_load();
wdenka042ac82002-09-12 22:36:57 +0000146
147 word |= POST_POWERTEST;
148
149 word |= (last_test & 0xFF) << 8;
150
Heiko Schochere92372c2011-10-12 01:18:05 +0000151 post_word_store(word);
wdenka042ac82002-09-12 22:36:57 +0000152}
153
Heiko Schochere92372c2011-10-12 01:18:05 +0000154static void post_bootmode_test_off(void)
wdenka042ac82002-09-12 22:36:57 +0000155{
Heiko Schochere92372c2011-10-12 01:18:05 +0000156 unsigned long word = post_word_load();
wdenka042ac82002-09-12 22:36:57 +0000157
158 word &= ~POST_POWERTEST;
159
Heiko Schochere92372c2011-10-12 01:18:05 +0000160 post_word_store(word);
wdenka042ac82002-09-12 22:36:57 +0000161}
162
Valentin Longchamp212a0ca2011-08-03 02:37:02 +0000163#ifndef CONFIG_POST_SKIP_ENV_FLAGS
164static void post_get_env_flags(int *test_flags)
wdenka042ac82002-09-12 22:36:57 +0000165{
Yuri Tikhonove262efe2008-02-04 14:11:03 +0100166 int flag[] = { POST_POWERON, POST_NORMAL, POST_SLOWTEST,
167 POST_CRITICAL };
168 char *var[] = { "post_poweron", "post_normal", "post_slowtest",
169 "post_critical" };
Mike Frysingerd2397812011-05-10 07:28:35 +0000170 int varnum = ARRAY_SIZE(var);
wdenka042ac82002-09-12 22:36:57 +0000171 char list[128]; /* long enough for POST list */
172 char *name;
173 char *s;
174 int last;
175 int i, j;
176
wdenka042ac82002-09-12 22:36:57 +0000177 for (i = 0; i < varnum; i++) {
Simon Glass00caae62017-08-03 12:22:12 -0600178 if (env_get_f(var[i], list, sizeof(list)) <= 0)
wdenka042ac82002-09-12 22:36:57 +0000179 continue;
180
Wolfgang Denk50da8372011-10-29 09:42:22 +0000181 for (j = 0; j < post_list_size; j++)
wdenka042ac82002-09-12 22:36:57 +0000182 test_flags[j] &= ~flag[i];
wdenka042ac82002-09-12 22:36:57 +0000183
184 last = 0;
185 name = list;
186 while (!last) {
187 while (*name && *name == ' ')
188 name++;
189 if (*name == 0)
190 break;
191 s = name + 1;
192 while (*s && *s != ' ')
193 s++;
194 if (*s == 0)
195 last = 1;
196 else
197 *s = 0;
198
199 for (j = 0; j < post_list_size; j++) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000200 if (strcmp(post_list[j].cmd, name) == 0) {
wdenka042ac82002-09-12 22:36:57 +0000201 test_flags[j] |= flag[i];
202 break;
203 }
204 }
205
Heiko Schochere92372c2011-10-12 01:18:05 +0000206 if (j == post_list_size)
Wolfgang Denk50da8372011-10-29 09:42:22 +0000207 printf("No such test: %s\n", name);
wdenka042ac82002-09-12 22:36:57 +0000208
209 name = s + 1;
210 }
211 }
Valentin Longchamp212a0ca2011-08-03 02:37:02 +0000212}
213#endif
214
215static void post_get_flags(int *test_flags)
216{
217 int j;
218
219 for (j = 0; j < post_list_size; j++)
220 test_flags[j] = post_list[j].flags;
221
222#ifndef CONFIG_POST_SKIP_ENV_FLAGS
223 post_get_env_flags(test_flags);
224#endif
wdenk6dff5522003-07-15 07:45:49 +0000225
Heiko Schochere92372c2011-10-12 01:18:05 +0000226 for (j = 0; j < post_list_size; j++)
227 if (test_flags[j] & POST_POWERON)
wdenk6dff5522003-07-15 07:45:49 +0000228 test_flags[j] |= POST_SLOWTEST;
wdenka042ac82002-09-12 22:36:57 +0000229}
230
Jeroen Hofstee002ad7b2014-10-08 22:57:25 +0200231__weak void show_post_progress(unsigned int test_num, int before, int result)
Michael Zaidmane070a562010-03-01 11:47:36 +0200232{
233}
Michael Zaidmane070a562010-03-01 11:47:36 +0200234
Heiko Schochere92372c2011-10-12 01:18:05 +0000235static int post_run_single(struct post_test *test,
wdenka042ac82002-09-12 22:36:57 +0000236 int test_flags, int flags, unsigned int i)
237{
238 if ((flags & test_flags & POST_ALWAYS) &&
239 (flags & test_flags & POST_MEM)) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000240 WATCHDOG_RESET();
wdenka042ac82002-09-12 22:36:57 +0000241
242 if (!(flags & POST_REBOOT)) {
Heiko Schochere92372c2011-10-12 01:18:05 +0000243 if ((test_flags & POST_REBOOT) &&
244 !(flags & POST_MANUAL)) {
245 post_bootmode_test_on(
Yuri Tikhonove262efe2008-02-04 14:11:03 +0100246 (gd->flags & GD_FLG_POSTFAIL) ?
247 POST_FAIL_SAVE | i : i);
wdenka042ac82002-09-12 22:36:57 +0000248 }
249
wdenk228f29a2002-12-08 09:53:23 +0000250 if (test_flags & POST_PREREL)
Heiko Schochere92372c2011-10-12 01:18:05 +0000251 post_log_mark_start(test->testid);
wdenk228f29a2002-12-08 09:53:23 +0000252 else
Heiko Schochere92372c2011-10-12 01:18:05 +0000253 post_log("POST %s ", test->cmd);
wdenka042ac82002-09-12 22:36:57 +0000254 }
255
Michael Zaidmane070a562010-03-01 11:47:36 +0200256 show_post_progress(i, POST_BEFORE, POST_FAILED);
257
wdenk228f29a2002-12-08 09:53:23 +0000258 if (test_flags & POST_PREREL) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000259 if ((*test->test)(flags) == 0) {
Heiko Schochere92372c2011-10-12 01:18:05 +0000260 post_log_mark_succ(test->testid);
Michael Zaidmane070a562010-03-01 11:47:36 +0200261 show_post_progress(i, POST_AFTER, POST_PASSED);
Wolfgang Denk50da8372011-10-29 09:42:22 +0000262 } else {
Michael Zaidmane070a562010-03-01 11:47:36 +0200263 show_post_progress(i, POST_AFTER, POST_FAILED);
Yuri Tikhonov28a38502008-05-08 15:45:26 +0200264 if (test_flags & POST_CRITICAL)
265 gd->flags |= GD_FLG_POSTFAIL;
266 if (test_flags & POST_STOP)
267 gd->flags |= GD_FLG_POSTSTOP;
268 }
wdenk228f29a2002-12-08 09:53:23 +0000269 } else {
James Kosin975afc32011-07-14 08:15:06 +0000270 if ((*test->test)(flags) != 0) {
271 post_log("FAILED\n");
Simon Glass770605e2012-02-13 13:51:18 +0000272 bootstage_error(BOOTSTAGE_ID_POST_FAIL_R);
James Kosin975afc32011-07-14 08:15:06 +0000273 show_post_progress(i, POST_AFTER, POST_FAILED);
274 if (test_flags & POST_CRITICAL)
275 gd->flags |= GD_FLG_POSTFAIL;
276 if (test_flags & POST_STOP)
277 gd->flags |= GD_FLG_POSTSTOP;
278 } else {
279 post_log("PASSED\n");
280 show_post_progress(i, POST_AFTER, POST_PASSED);
281 }
wdenk228f29a2002-12-08 09:53:23 +0000282 }
wdenka042ac82002-09-12 22:36:57 +0000283
Wolfgang Denk50da8372011-10-29 09:42:22 +0000284 if ((test_flags & POST_REBOOT) && !(flags & POST_MANUAL))
Heiko Schochere92372c2011-10-12 01:18:05 +0000285 post_bootmode_test_off();
wdenka042ac82002-09-12 22:36:57 +0000286
287 return 0;
288 } else {
289 return -1;
290 }
291}
292
Wolfgang Denk50da8372011-10-29 09:42:22 +0000293int post_run(char *name, int flags)
wdenka042ac82002-09-12 22:36:57 +0000294{
295 unsigned int i;
296 int test_flags[POST_MAX_NUMBER];
297
Heiko Schochere92372c2011-10-12 01:18:05 +0000298 post_get_flags(test_flags);
wdenka042ac82002-09-12 22:36:57 +0000299
300 if (name == NULL) {
301 unsigned int last;
302
Yuri Tikhonov28a38502008-05-08 15:45:26 +0200303 if (gd->flags & GD_FLG_POSTSTOP)
304 return 0;
305
Heiko Schochere92372c2011-10-12 01:18:05 +0000306 if (post_bootmode_get(&last) & POST_POWERTEST) {
Yuri Tikhonove262efe2008-02-04 14:11:03 +0100307 if (last & POST_FAIL_SAVE) {
308 last &= ~POST_FAIL_SAVE;
309 gd->flags |= GD_FLG_POSTFAIL;
310 }
wdenka042ac82002-09-12 22:36:57 +0000311 if (last < post_list_size &&
312 (flags & test_flags[last] & POST_ALWAYS) &&
313 (flags & test_flags[last] & POST_MEM)) {
314
Heiko Schochere92372c2011-10-12 01:18:05 +0000315 post_run_single(post_list + last,
wdenkea909b72002-11-21 23:11:29 +0000316 test_flags[last],
317 flags | POST_REBOOT, last);
wdenka042ac82002-09-12 22:36:57 +0000318
319 for (i = last + 1; i < post_list_size; i++) {
Yuri Tikhonov28a38502008-05-08 15:45:26 +0200320 if (gd->flags & GD_FLG_POSTSTOP)
321 break;
Heiko Schochere92372c2011-10-12 01:18:05 +0000322 post_run_single(post_list + i,
wdenkea909b72002-11-21 23:11:29 +0000323 test_flags[i],
324 flags, i);
wdenka042ac82002-09-12 22:36:57 +0000325 }
326 }
327 } else {
328 for (i = 0; i < post_list_size; i++) {
Yuri Tikhonov28a38502008-05-08 15:45:26 +0200329 if (gd->flags & GD_FLG_POSTSTOP)
330 break;
Heiko Schochere92372c2011-10-12 01:18:05 +0000331 post_run_single(post_list + i,
wdenkea909b72002-11-21 23:11:29 +0000332 test_flags[i],
333 flags, i);
wdenka042ac82002-09-12 22:36:57 +0000334 }
335 }
336
337 return 0;
338 } else {
339 for (i = 0; i < post_list_size; i++) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000340 if (strcmp(post_list[i].cmd, name) == 0)
wdenka042ac82002-09-12 22:36:57 +0000341 break;
342 }
343
344 if (i < post_list_size) {
Sascha Laue5744ddc2008-05-30 09:48:14 +0200345 WATCHDOG_RESET();
Heiko Schochere92372c2011-10-12 01:18:05 +0000346 return post_run_single(post_list + i,
wdenka042ac82002-09-12 22:36:57 +0000347 test_flags[i],
348 flags, i);
349 } else {
350 return -1;
351 }
352 }
353}
354
Heiko Schochere92372c2011-10-12 01:18:05 +0000355static int post_info_single(struct post_test *test, int full)
wdenka042ac82002-09-12 22:36:57 +0000356{
357 if (test->flags & POST_MANUAL) {
358 if (full)
Heiko Schochere92372c2011-10-12 01:18:05 +0000359 printf("%s - %s\n"
wdenka042ac82002-09-12 22:36:57 +0000360 " %s\n", test->cmd, test->name, test->desc);
361 else
Heiko Schochere92372c2011-10-12 01:18:05 +0000362 printf(" %-15s - %s\n", test->cmd, test->name);
wdenka042ac82002-09-12 22:36:57 +0000363
364 return 0;
365 } else {
366 return -1;
367 }
368}
369
Wolfgang Denk50da8372011-10-29 09:42:22 +0000370int post_info(char *name)
wdenka042ac82002-09-12 22:36:57 +0000371{
372 unsigned int i;
373
374 if (name == NULL) {
Heiko Schochere92372c2011-10-12 01:18:05 +0000375 for (i = 0; i < post_list_size; i++)
376 post_info_single(post_list + i, 0);
wdenka042ac82002-09-12 22:36:57 +0000377
378 return 0;
379 } else {
380 for (i = 0; i < post_list_size; i++) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000381 if (strcmp(post_list[i].cmd, name) == 0)
wdenka042ac82002-09-12 22:36:57 +0000382 break;
383 }
384
Wolfgang Denk50da8372011-10-29 09:42:22 +0000385 if (i < post_list_size)
Heiko Schochere92372c2011-10-12 01:18:05 +0000386 return post_info_single(post_list + i, 1);
Wolfgang Denk50da8372011-10-29 09:42:22 +0000387 else
wdenka042ac82002-09-12 22:36:57 +0000388 return -1;
wdenka042ac82002-09-12 22:36:57 +0000389 }
390}
391
Heiko Schochere92372c2011-10-12 01:18:05 +0000392int post_log(char *format, ...)
wdenka042ac82002-09-12 22:36:57 +0000393{
394 va_list args;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200395 char printbuffer[CONFIG_SYS_PBSIZE];
wdenka042ac82002-09-12 22:36:57 +0000396
Wolfgang Denk50da8372011-10-29 09:42:22 +0000397 va_start(args, format);
wdenka042ac82002-09-12 22:36:57 +0000398
399 /* For this to work, printbuffer must be larger than
400 * anything we ever want to print.
401 */
Wolfgang Denk4d6402b2011-10-29 09:42:23 +0000402 vsprintf(printbuffer, format, args);
Wolfgang Denk50da8372011-10-29 09:42:22 +0000403 va_end(args);
wdenka042ac82002-09-12 22:36:57 +0000404
405 /* Send to the stdout file */
Heiko Schochere92372c2011-10-12 01:18:05 +0000406 puts(printbuffer);
wdenka042ac82002-09-12 22:36:57 +0000407
408 return 0;
409}
410
Wolfgang Denk2e5167c2010-10-28 20:00:11 +0200411#ifdef CONFIG_NEEDS_MANUAL_RELOC
Heiko Schochere92372c2011-10-12 01:18:05 +0000412void post_reloc(void)
wdenka042ac82002-09-12 22:36:57 +0000413{
wdenka042ac82002-09-12 22:36:57 +0000414 unsigned int i;
415
416 /*
417 * We have to relocate the test table manually
418 */
419 for (i = 0; i < post_list_size; i++) {
420 ulong addr;
421 struct post_test *test = post_list + i;
422
423 if (test->name) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000424 addr = (ulong)(test->name) + gd->reloc_off;
Heiko Schochere92372c2011-10-12 01:18:05 +0000425 test->name = (char *)addr;
wdenka042ac82002-09-12 22:36:57 +0000426 }
427
428 if (test->cmd) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000429 addr = (ulong)(test->cmd) + gd->reloc_off;
Heiko Schochere92372c2011-10-12 01:18:05 +0000430 test->cmd = (char *)addr;
wdenka042ac82002-09-12 22:36:57 +0000431 }
432
433 if (test->desc) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000434 addr = (ulong)(test->desc) + gd->reloc_off;
Heiko Schochere92372c2011-10-12 01:18:05 +0000435 test->desc = (char *)addr;
wdenka042ac82002-09-12 22:36:57 +0000436 }
437
438 if (test->test) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000439 addr = (ulong)(test->test) + gd->reloc_off;
wdenka042ac82002-09-12 22:36:57 +0000440 test->test = (int (*)(int flags)) addr;
441 }
wdenk4532cb62003-04-27 22:52:51 +0000442
443 if (test->init_f) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000444 addr = (ulong)(test->init_f) + gd->reloc_off;
wdenk4532cb62003-04-27 22:52:51 +0000445 test->init_f = (int (*)(void)) addr;
446 }
447
448 if (test->reloc) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000449 addr = (ulong)(test->reloc) + gd->reloc_off;
wdenk4532cb62003-04-27 22:52:51 +0000450 test->reloc = (void (*)(void)) addr;
wdenk8bde7f72003-06-27 21:31:46 +0000451
wdenk4532cb62003-04-27 22:52:51 +0000452 test->reloc();
453 }
wdenka042ac82002-09-12 22:36:57 +0000454 }
455}
Peter Tyser521af042009-09-21 11:20:36 -0500456#endif
wdenka042ac82002-09-12 22:36:57 +0000457
wdenk4532cb62003-04-27 22:52:51 +0000458
459/*
460 * Some tests (e.g. SYSMON) need the time when post_init_f started,
461 * but we cannot use get_timer() at this point.
462 *
463 * On PowerPC we implement it using the timebase register.
464 */
Heiko Schochere92372c2011-10-12 01:18:05 +0000465unsigned long post_time_ms(unsigned long base)
wdenk4532cb62003-04-27 22:52:51 +0000466{
Tom Riniea3310e2017-03-14 11:08:10 -0400467#if defined(CONFIG_PPC) || defined(CONFIG_ARM)
Christian Rieschc90a4dd2011-12-09 16:54:02 +0100468 return (unsigned long)lldiv(get_ticks(), get_tbclk() / CONFIG_SYS_HZ)
Heiko Schochere92372c2011-10-12 01:18:05 +0000469 - base;
wdenk4532cb62003-04-27 22:52:51 +0000470#else
Wolfgang Denkad5bb452007-03-06 18:08:43 +0100471#warning "Not implemented yet"
wdenk4532cb62003-04-27 22:52:51 +0000472 return 0; /* Not implemented yet */
473#endif
474}