blob: 4194edb89e86fe2db008767dd33bd7faf4e32b79 [file] [log] [blame]
wdenka042ac82002-09-12 22:36:57 +00001/*
2 * (C) Copyright 2002
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
wdenka042ac82002-09-12 22:36:57 +00006 */
7
8#include <common.h>
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +02009#include <stdio_dev.h>
wdenka042ac82002-09-12 22:36:57 +000010#include <watchdog.h>
Christian Rieschc90a4dd2011-12-09 16:54:02 +010011#include <div64.h>
wdenka042ac82002-09-12 22:36:57 +000012#include <post.h>
13
Mike Frysinger9146d132011-05-10 07:01:21 +000014#ifdef CONFIG_SYS_POST_HOTKEYS_GPIO
15#include <asm/gpio.h>
16#endif
17
wdenk56f94be2002-11-05 16:35:14 +000018#ifdef CONFIG_LOGBUFFER
19#include <logbuff.h>
20#endif
21
Wolfgang Denkd87080b2006-03-31 18:32:53 +020022DECLARE_GLOBAL_DATA_PTR;
23
wdenka042ac82002-09-12 22:36:57 +000024#define POST_MAX_NUMBER 32
25
26#define BOOTMODE_MAGIC 0xDEAD0000
27
Heiko Schochere92372c2011-10-12 01:18:05 +000028int post_init_f(void)
wdenk4532cb62003-04-27 22:52:51 +000029{
wdenk4532cb62003-04-27 22:52:51 +000030 int res = 0;
31 unsigned int i;
32
33 for (i = 0; i < post_list_size; i++) {
34 struct post_test *test = post_list + i;
35
Wolfgang Denk50da8372011-10-29 09:42:22 +000036 if (test->init_f && test->init_f())
wdenk4532cb62003-04-27 22:52:51 +000037 res = -1;
wdenk4532cb62003-04-27 22:52:51 +000038 }
wdenk8bde7f72003-06-27 21:31:46 +000039
wdenk4532cb62003-04-27 22:52:51 +000040 gd->post_init_f_time = post_time_ms(0);
41 if (!gd->post_init_f_time)
Heiko Schochere92372c2011-10-12 01:18:05 +000042 printf("%s: post_time_ms not implemented\n", __FILE__);
wdenk4532cb62003-04-27 22:52:51 +000043
44 return res;
45}
46
Stefan Roese39ff7d52009-12-03 06:24:30 +010047/*
48 * Supply a default implementation for post_hotkeys_pressed() for boards
49 * without hotkey support. We always return 0 here, so that the
50 * long-running tests won't be started.
51 *
52 * Boards with hotkey support can override this weak default function
53 * by defining one in their board specific code.
54 */
Jeroen Hofstee002ad7b2014-10-08 22:57:25 +020055__weak int post_hotkeys_pressed(void)
Stefan Roese39ff7d52009-12-03 06:24:30 +010056{
Mike Frysinger9146d132011-05-10 07:01:21 +000057#ifdef CONFIG_SYS_POST_HOTKEYS_GPIO
58 int ret;
59 unsigned gpio = CONFIG_SYS_POST_HOTKEYS_GPIO;
60
61 ret = gpio_request(gpio, "hotkeys");
62 if (ret) {
63 printf("POST: gpio hotkey request failed\n");
64 return 0;
65 }
66
67 gpio_direction_input(gpio);
68 ret = gpio_get_value(gpio);
69 gpio_free(gpio);
70
71 return ret;
72#endif
73
Stefan Roese39ff7d52009-12-03 06:24:30 +010074 return 0; /* No hotkeys supported */
75}
Stefan Roese39ff7d52009-12-03 06:24:30 +010076
Heiko Schochere92372c2011-10-12 01:18:05 +000077void post_bootmode_init(void)
wdenka042ac82002-09-12 22:36:57 +000078{
Heiko Schochere92372c2011-10-12 01:18:05 +000079 int bootmode = post_bootmode_get(0);
wdenk27b207f2003-07-24 23:38:38 +000080 int newword;
wdenk42d1f032003-10-15 23:53:47 +000081
Heiko Schochere92372c2011-10-12 01:18:05 +000082 if (post_hotkeys_pressed() && !(bootmode & POST_POWERTEST))
wdenk27b207f2003-07-24 23:38:38 +000083 newword = BOOTMODE_MAGIC | POST_SLOWTEST;
Heiko Schochere92372c2011-10-12 01:18:05 +000084 else if (bootmode == 0)
wdenk27b207f2003-07-24 23:38:38 +000085 newword = BOOTMODE_MAGIC | POST_POWERON;
Heiko Schochere92372c2011-10-12 01:18:05 +000086 else if (bootmode == POST_POWERON || bootmode == POST_SLOWTEST)
wdenk27b207f2003-07-24 23:38:38 +000087 newword = BOOTMODE_MAGIC | POST_NORMAL;
Heiko Schochere92372c2011-10-12 01:18:05 +000088 else
wdenk27b207f2003-07-24 23:38:38 +000089 /* Use old value */
Wolfgang Denk50da8372011-10-29 09:42:22 +000090 newword = post_word_load() & ~POST_COLDBOOT;
wdenka042ac82002-09-12 22:36:57 +000091
wdenk27b207f2003-07-24 23:38:38 +000092 if (bootmode == 0)
wdenk27b207f2003-07-24 23:38:38 +000093 /* We are booting after power-on */
94 newword |= POST_COLDBOOT;
wdenk27b207f2003-07-24 23:38:38 +000095
Heiko Schochere92372c2011-10-12 01:18:05 +000096 post_word_store(newword);
wdenk27b207f2003-07-24 23:38:38 +000097
wdenk228f29a2002-12-08 09:53:23 +000098 /* Reset activity record */
99 gd->post_log_word = 0;
Valentin Longchamp79843952011-08-03 02:37:01 +0000100 gd->post_log_res = 0;
wdenka042ac82002-09-12 22:36:57 +0000101}
102
Heiko Schochere92372c2011-10-12 01:18:05 +0000103int post_bootmode_get(unsigned int *last_test)
wdenka042ac82002-09-12 22:36:57 +0000104{
Heiko Schochere92372c2011-10-12 01:18:05 +0000105 unsigned long word = post_word_load();
wdenka042ac82002-09-12 22:36:57 +0000106 int bootmode;
107
Heiko Schochere92372c2011-10-12 01:18:05 +0000108 if ((word & 0xFFFF0000) != BOOTMODE_MAGIC)
wdenka042ac82002-09-12 22:36:57 +0000109 return 0;
wdenka042ac82002-09-12 22:36:57 +0000110
wdenk27b207f2003-07-24 23:38:38 +0000111 bootmode = word & 0x7F;
wdenka042ac82002-09-12 22:36:57 +0000112
Heiko Schochere92372c2011-10-12 01:18:05 +0000113 if (last_test && (bootmode & POST_POWERTEST))
wdenka042ac82002-09-12 22:36:57 +0000114 *last_test = (word >> 8) & 0xFF;
wdenka042ac82002-09-12 22:36:57 +0000115
116 return bootmode;
117}
118
wdenk228f29a2002-12-08 09:53:23 +0000119/* POST tests run before relocation only mark status bits .... */
Heiko Schochere92372c2011-10-12 01:18:05 +0000120static void post_log_mark_start(unsigned long testid)
wdenk228f29a2002-12-08 09:53:23 +0000121{
Valentin Longchamp79843952011-08-03 02:37:01 +0000122 gd->post_log_word |= testid;
wdenk228f29a2002-12-08 09:53:23 +0000123}
124
Heiko Schochere92372c2011-10-12 01:18:05 +0000125static void post_log_mark_succ(unsigned long testid)
wdenk228f29a2002-12-08 09:53:23 +0000126{
Valentin Longchamp79843952011-08-03 02:37:01 +0000127 gd->post_log_res |= testid;
wdenk228f29a2002-12-08 09:53:23 +0000128}
129
130/* ... and the messages are output once we are relocated */
Heiko Schochere92372c2011-10-12 01:18:05 +0000131void post_output_backlog(void)
wdenk228f29a2002-12-08 09:53:23 +0000132{
wdenk228f29a2002-12-08 09:53:23 +0000133 int j;
134
135 for (j = 0; j < post_list_size; j++) {
Valentin Longchamp79843952011-08-03 02:37:01 +0000136 if (gd->post_log_word & (post_list[j].testid)) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000137 post_log("POST %s ", post_list[j].cmd);
Valentin Longchamp79843952011-08-03 02:37:01 +0000138 if (gd->post_log_res & post_list[j].testid)
Wolfgang Denk50da8372011-10-29 09:42:22 +0000139 post_log("PASSED\n");
wdenk63e73c92004-02-23 22:22:28 +0000140 else {
Heiko Schochere92372c2011-10-12 01:18:05 +0000141 post_log("FAILED\n");
Simon Glass770605e2012-02-13 13:51:18 +0000142 bootstage_error(BOOTSTAGE_ID_POST_FAIL_R);
wdenk63e73c92004-02-23 22:22:28 +0000143 }
wdenk228f29a2002-12-08 09:53:23 +0000144 }
145 }
146}
147
Heiko Schochere92372c2011-10-12 01:18:05 +0000148static void post_bootmode_test_on(unsigned int last_test)
wdenka042ac82002-09-12 22:36:57 +0000149{
Heiko Schochere92372c2011-10-12 01:18:05 +0000150 unsigned long word = post_word_load();
wdenka042ac82002-09-12 22:36:57 +0000151
152 word |= POST_POWERTEST;
153
154 word |= (last_test & 0xFF) << 8;
155
Heiko Schochere92372c2011-10-12 01:18:05 +0000156 post_word_store(word);
wdenka042ac82002-09-12 22:36:57 +0000157}
158
Heiko Schochere92372c2011-10-12 01:18:05 +0000159static void post_bootmode_test_off(void)
wdenka042ac82002-09-12 22:36:57 +0000160{
Heiko Schochere92372c2011-10-12 01:18:05 +0000161 unsigned long word = post_word_load();
wdenka042ac82002-09-12 22:36:57 +0000162
163 word &= ~POST_POWERTEST;
164
Heiko Schochere92372c2011-10-12 01:18:05 +0000165 post_word_store(word);
wdenka042ac82002-09-12 22:36:57 +0000166}
167
Valentin Longchamp212a0ca2011-08-03 02:37:02 +0000168#ifndef CONFIG_POST_SKIP_ENV_FLAGS
169static void post_get_env_flags(int *test_flags)
wdenka042ac82002-09-12 22:36:57 +0000170{
Yuri Tikhonove262efe2008-02-04 14:11:03 +0100171 int flag[] = { POST_POWERON, POST_NORMAL, POST_SLOWTEST,
172 POST_CRITICAL };
173 char *var[] = { "post_poweron", "post_normal", "post_slowtest",
174 "post_critical" };
Mike Frysingerd2397812011-05-10 07:28:35 +0000175 int varnum = ARRAY_SIZE(var);
wdenka042ac82002-09-12 22:36:57 +0000176 char list[128]; /* long enough for POST list */
177 char *name;
178 char *s;
179 int last;
180 int i, j;
181
wdenka042ac82002-09-12 22:36:57 +0000182 for (i = 0; i < varnum; i++) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000183 if (getenv_f(var[i], list, sizeof(list)) <= 0)
wdenka042ac82002-09-12 22:36:57 +0000184 continue;
185
Wolfgang Denk50da8372011-10-29 09:42:22 +0000186 for (j = 0; j < post_list_size; j++)
wdenka042ac82002-09-12 22:36:57 +0000187 test_flags[j] &= ~flag[i];
wdenka042ac82002-09-12 22:36:57 +0000188
189 last = 0;
190 name = list;
191 while (!last) {
192 while (*name && *name == ' ')
193 name++;
194 if (*name == 0)
195 break;
196 s = name + 1;
197 while (*s && *s != ' ')
198 s++;
199 if (*s == 0)
200 last = 1;
201 else
202 *s = 0;
203
204 for (j = 0; j < post_list_size; j++) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000205 if (strcmp(post_list[j].cmd, name) == 0) {
wdenka042ac82002-09-12 22:36:57 +0000206 test_flags[j] |= flag[i];
207 break;
208 }
209 }
210
Heiko Schochere92372c2011-10-12 01:18:05 +0000211 if (j == post_list_size)
Wolfgang Denk50da8372011-10-29 09:42:22 +0000212 printf("No such test: %s\n", name);
wdenka042ac82002-09-12 22:36:57 +0000213
214 name = s + 1;
215 }
216 }
Valentin Longchamp212a0ca2011-08-03 02:37:02 +0000217}
218#endif
219
220static void post_get_flags(int *test_flags)
221{
222 int j;
223
224 for (j = 0; j < post_list_size; j++)
225 test_flags[j] = post_list[j].flags;
226
227#ifndef CONFIG_POST_SKIP_ENV_FLAGS
228 post_get_env_flags(test_flags);
229#endif
wdenk6dff5522003-07-15 07:45:49 +0000230
Heiko Schochere92372c2011-10-12 01:18:05 +0000231 for (j = 0; j < post_list_size; j++)
232 if (test_flags[j] & POST_POWERON)
wdenk6dff5522003-07-15 07:45:49 +0000233 test_flags[j] |= POST_SLOWTEST;
wdenka042ac82002-09-12 22:36:57 +0000234}
235
Jeroen Hofstee002ad7b2014-10-08 22:57:25 +0200236__weak void show_post_progress(unsigned int test_num, int before, int result)
Michael Zaidmane070a562010-03-01 11:47:36 +0200237{
238}
Michael Zaidmane070a562010-03-01 11:47:36 +0200239
Heiko Schochere92372c2011-10-12 01:18:05 +0000240static int post_run_single(struct post_test *test,
wdenka042ac82002-09-12 22:36:57 +0000241 int test_flags, int flags, unsigned int i)
242{
243 if ((flags & test_flags & POST_ALWAYS) &&
244 (flags & test_flags & POST_MEM)) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000245 WATCHDOG_RESET();
wdenka042ac82002-09-12 22:36:57 +0000246
247 if (!(flags & POST_REBOOT)) {
Heiko Schochere92372c2011-10-12 01:18:05 +0000248 if ((test_flags & POST_REBOOT) &&
249 !(flags & POST_MANUAL)) {
250 post_bootmode_test_on(
Yuri Tikhonove262efe2008-02-04 14:11:03 +0100251 (gd->flags & GD_FLG_POSTFAIL) ?
252 POST_FAIL_SAVE | i : i);
wdenka042ac82002-09-12 22:36:57 +0000253 }
254
wdenk228f29a2002-12-08 09:53:23 +0000255 if (test_flags & POST_PREREL)
Heiko Schochere92372c2011-10-12 01:18:05 +0000256 post_log_mark_start(test->testid);
wdenk228f29a2002-12-08 09:53:23 +0000257 else
Heiko Schochere92372c2011-10-12 01:18:05 +0000258 post_log("POST %s ", test->cmd);
wdenka042ac82002-09-12 22:36:57 +0000259 }
260
Michael Zaidmane070a562010-03-01 11:47:36 +0200261 show_post_progress(i, POST_BEFORE, POST_FAILED);
262
wdenk228f29a2002-12-08 09:53:23 +0000263 if (test_flags & POST_PREREL) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000264 if ((*test->test)(flags) == 0) {
Heiko Schochere92372c2011-10-12 01:18:05 +0000265 post_log_mark_succ(test->testid);
Michael Zaidmane070a562010-03-01 11:47:36 +0200266 show_post_progress(i, POST_AFTER, POST_PASSED);
Wolfgang Denk50da8372011-10-29 09:42:22 +0000267 } else {
Michael Zaidmane070a562010-03-01 11:47:36 +0200268 show_post_progress(i, POST_AFTER, POST_FAILED);
Yuri Tikhonov28a38502008-05-08 15:45:26 +0200269 if (test_flags & POST_CRITICAL)
270 gd->flags |= GD_FLG_POSTFAIL;
271 if (test_flags & POST_STOP)
272 gd->flags |= GD_FLG_POSTSTOP;
273 }
wdenk228f29a2002-12-08 09:53:23 +0000274 } else {
James Kosin975afc32011-07-14 08:15:06 +0000275 if ((*test->test)(flags) != 0) {
276 post_log("FAILED\n");
Simon Glass770605e2012-02-13 13:51:18 +0000277 bootstage_error(BOOTSTAGE_ID_POST_FAIL_R);
James Kosin975afc32011-07-14 08:15:06 +0000278 show_post_progress(i, POST_AFTER, POST_FAILED);
279 if (test_flags & POST_CRITICAL)
280 gd->flags |= GD_FLG_POSTFAIL;
281 if (test_flags & POST_STOP)
282 gd->flags |= GD_FLG_POSTSTOP;
283 } else {
284 post_log("PASSED\n");
285 show_post_progress(i, POST_AFTER, POST_PASSED);
286 }
wdenk228f29a2002-12-08 09:53:23 +0000287 }
wdenka042ac82002-09-12 22:36:57 +0000288
Wolfgang Denk50da8372011-10-29 09:42:22 +0000289 if ((test_flags & POST_REBOOT) && !(flags & POST_MANUAL))
Heiko Schochere92372c2011-10-12 01:18:05 +0000290 post_bootmode_test_off();
wdenka042ac82002-09-12 22:36:57 +0000291
292 return 0;
293 } else {
294 return -1;
295 }
296}
297
Wolfgang Denk50da8372011-10-29 09:42:22 +0000298int post_run(char *name, int flags)
wdenka042ac82002-09-12 22:36:57 +0000299{
300 unsigned int i;
301 int test_flags[POST_MAX_NUMBER];
302
Heiko Schochere92372c2011-10-12 01:18:05 +0000303 post_get_flags(test_flags);
wdenka042ac82002-09-12 22:36:57 +0000304
305 if (name == NULL) {
306 unsigned int last;
307
Yuri Tikhonov28a38502008-05-08 15:45:26 +0200308 if (gd->flags & GD_FLG_POSTSTOP)
309 return 0;
310
Heiko Schochere92372c2011-10-12 01:18:05 +0000311 if (post_bootmode_get(&last) & POST_POWERTEST) {
Yuri Tikhonove262efe2008-02-04 14:11:03 +0100312 if (last & POST_FAIL_SAVE) {
313 last &= ~POST_FAIL_SAVE;
314 gd->flags |= GD_FLG_POSTFAIL;
315 }
wdenka042ac82002-09-12 22:36:57 +0000316 if (last < post_list_size &&
317 (flags & test_flags[last] & POST_ALWAYS) &&
318 (flags & test_flags[last] & POST_MEM)) {
319
Heiko Schochere92372c2011-10-12 01:18:05 +0000320 post_run_single(post_list + last,
wdenkea909b72002-11-21 23:11:29 +0000321 test_flags[last],
322 flags | POST_REBOOT, last);
wdenka042ac82002-09-12 22:36:57 +0000323
324 for (i = last + 1; i < post_list_size; i++) {
Yuri Tikhonov28a38502008-05-08 15:45:26 +0200325 if (gd->flags & GD_FLG_POSTSTOP)
326 break;
Heiko Schochere92372c2011-10-12 01:18:05 +0000327 post_run_single(post_list + i,
wdenkea909b72002-11-21 23:11:29 +0000328 test_flags[i],
329 flags, i);
wdenka042ac82002-09-12 22:36:57 +0000330 }
331 }
332 } else {
333 for (i = 0; i < post_list_size; i++) {
Yuri Tikhonov28a38502008-05-08 15:45:26 +0200334 if (gd->flags & GD_FLG_POSTSTOP)
335 break;
Heiko Schochere92372c2011-10-12 01:18:05 +0000336 post_run_single(post_list + i,
wdenkea909b72002-11-21 23:11:29 +0000337 test_flags[i],
338 flags, i);
wdenka042ac82002-09-12 22:36:57 +0000339 }
340 }
341
342 return 0;
343 } else {
344 for (i = 0; i < post_list_size; i++) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000345 if (strcmp(post_list[i].cmd, name) == 0)
wdenka042ac82002-09-12 22:36:57 +0000346 break;
347 }
348
349 if (i < post_list_size) {
Sascha Laue5744ddc2008-05-30 09:48:14 +0200350 WATCHDOG_RESET();
Heiko Schochere92372c2011-10-12 01:18:05 +0000351 return post_run_single(post_list + i,
wdenka042ac82002-09-12 22:36:57 +0000352 test_flags[i],
353 flags, i);
354 } else {
355 return -1;
356 }
357 }
358}
359
Heiko Schochere92372c2011-10-12 01:18:05 +0000360static int post_info_single(struct post_test *test, int full)
wdenka042ac82002-09-12 22:36:57 +0000361{
362 if (test->flags & POST_MANUAL) {
363 if (full)
Heiko Schochere92372c2011-10-12 01:18:05 +0000364 printf("%s - %s\n"
wdenka042ac82002-09-12 22:36:57 +0000365 " %s\n", test->cmd, test->name, test->desc);
366 else
Heiko Schochere92372c2011-10-12 01:18:05 +0000367 printf(" %-15s - %s\n", test->cmd, test->name);
wdenka042ac82002-09-12 22:36:57 +0000368
369 return 0;
370 } else {
371 return -1;
372 }
373}
374
Wolfgang Denk50da8372011-10-29 09:42:22 +0000375int post_info(char *name)
wdenka042ac82002-09-12 22:36:57 +0000376{
377 unsigned int i;
378
379 if (name == NULL) {
Heiko Schochere92372c2011-10-12 01:18:05 +0000380 for (i = 0; i < post_list_size; i++)
381 post_info_single(post_list + i, 0);
wdenka042ac82002-09-12 22:36:57 +0000382
383 return 0;
384 } else {
385 for (i = 0; i < post_list_size; i++) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000386 if (strcmp(post_list[i].cmd, name) == 0)
wdenka042ac82002-09-12 22:36:57 +0000387 break;
388 }
389
Wolfgang Denk50da8372011-10-29 09:42:22 +0000390 if (i < post_list_size)
Heiko Schochere92372c2011-10-12 01:18:05 +0000391 return post_info_single(post_list + i, 1);
Wolfgang Denk50da8372011-10-29 09:42:22 +0000392 else
wdenka042ac82002-09-12 22:36:57 +0000393 return -1;
wdenka042ac82002-09-12 22:36:57 +0000394 }
395}
396
Heiko Schochere92372c2011-10-12 01:18:05 +0000397int post_log(char *format, ...)
wdenka042ac82002-09-12 22:36:57 +0000398{
399 va_list args;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200400 char printbuffer[CONFIG_SYS_PBSIZE];
wdenka042ac82002-09-12 22:36:57 +0000401
Wolfgang Denk50da8372011-10-29 09:42:22 +0000402 va_start(args, format);
wdenka042ac82002-09-12 22:36:57 +0000403
404 /* For this to work, printbuffer must be larger than
405 * anything we ever want to print.
406 */
Wolfgang Denk4d6402b2011-10-29 09:42:23 +0000407 vsprintf(printbuffer, format, args);
Wolfgang Denk50da8372011-10-29 09:42:22 +0000408 va_end(args);
wdenka042ac82002-09-12 22:36:57 +0000409
wdenk56f94be2002-11-05 16:35:14 +0000410#ifdef CONFIG_LOGBUFFER
wdenk228f29a2002-12-08 09:53:23 +0000411 /* Send to the logbuffer */
Heiko Schochere92372c2011-10-12 01:18:05 +0000412 logbuff_log(printbuffer);
wdenk56f94be2002-11-05 16:35:14 +0000413#else
wdenka042ac82002-09-12 22:36:57 +0000414 /* Send to the stdout file */
Heiko Schochere92372c2011-10-12 01:18:05 +0000415 puts(printbuffer);
wdenk56f94be2002-11-05 16:35:14 +0000416#endif
wdenka042ac82002-09-12 22:36:57 +0000417
418 return 0;
419}
420
Wolfgang Denk2e5167c2010-10-28 20:00:11 +0200421#ifdef CONFIG_NEEDS_MANUAL_RELOC
Heiko Schochere92372c2011-10-12 01:18:05 +0000422void post_reloc(void)
wdenka042ac82002-09-12 22:36:57 +0000423{
wdenka042ac82002-09-12 22:36:57 +0000424 unsigned int i;
425
426 /*
427 * We have to relocate the test table manually
428 */
429 for (i = 0; i < post_list_size; i++) {
430 ulong addr;
431 struct post_test *test = post_list + i;
432
433 if (test->name) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000434 addr = (ulong)(test->name) + gd->reloc_off;
Heiko Schochere92372c2011-10-12 01:18:05 +0000435 test->name = (char *)addr;
wdenka042ac82002-09-12 22:36:57 +0000436 }
437
438 if (test->cmd) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000439 addr = (ulong)(test->cmd) + gd->reloc_off;
Heiko Schochere92372c2011-10-12 01:18:05 +0000440 test->cmd = (char *)addr;
wdenka042ac82002-09-12 22:36:57 +0000441 }
442
443 if (test->desc) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000444 addr = (ulong)(test->desc) + gd->reloc_off;
Heiko Schochere92372c2011-10-12 01:18:05 +0000445 test->desc = (char *)addr;
wdenka042ac82002-09-12 22:36:57 +0000446 }
447
448 if (test->test) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000449 addr = (ulong)(test->test) + gd->reloc_off;
wdenka042ac82002-09-12 22:36:57 +0000450 test->test = (int (*)(int flags)) addr;
451 }
wdenk4532cb62003-04-27 22:52:51 +0000452
453 if (test->init_f) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000454 addr = (ulong)(test->init_f) + gd->reloc_off;
wdenk4532cb62003-04-27 22:52:51 +0000455 test->init_f = (int (*)(void)) addr;
456 }
457
458 if (test->reloc) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000459 addr = (ulong)(test->reloc) + gd->reloc_off;
wdenk4532cb62003-04-27 22:52:51 +0000460 test->reloc = (void (*)(void)) addr;
wdenk8bde7f72003-06-27 21:31:46 +0000461
wdenk4532cb62003-04-27 22:52:51 +0000462 test->reloc();
463 }
wdenka042ac82002-09-12 22:36:57 +0000464 }
465}
Peter Tyser521af042009-09-21 11:20:36 -0500466#endif
wdenka042ac82002-09-12 22:36:57 +0000467
wdenk4532cb62003-04-27 22:52:51 +0000468
469/*
470 * Some tests (e.g. SYSMON) need the time when post_init_f started,
471 * but we cannot use get_timer() at this point.
472 *
473 * On PowerPC we implement it using the timebase register.
474 */
Heiko Schochere92372c2011-10-12 01:18:05 +0000475unsigned long post_time_ms(unsigned long base)
wdenk4532cb62003-04-27 22:52:51 +0000476{
Valentin Longchamp4e518b82012-03-30 03:29:28 +0000477#if defined(CONFIG_PPC) || defined(CONFIG_BLACKFIN) || defined(CONFIG_ARM)
Christian Rieschc90a4dd2011-12-09 16:54:02 +0100478 return (unsigned long)lldiv(get_ticks(), get_tbclk() / CONFIG_SYS_HZ)
Heiko Schochere92372c2011-10-12 01:18:05 +0000479 - base;
wdenk4532cb62003-04-27 22:52:51 +0000480#else
Wolfgang Denkad5bb452007-03-06 18:08:43 +0100481#warning "Not implemented yet"
wdenk4532cb62003-04-27 22:52:51 +0000482 return 0; /* Not implemented yet */
483#endif
484}