blob: 7d6a64731281e57bf1a1fca89e4bd3ca22bedafd [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>
Simon Glass52f24232020-05-10 11:40:00 -06008#include <bootstage.h>
Simon Glass3a7d5572019-08-01 09:46:42 -06009#include <env.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060010#include <log.h>
Simon Glass336d4612020-02-03 07:36:16 -070011#include <malloc.h>
Jean-Christophe PLAGNIOL-VILLARD52cb4d42009-05-16 12:14:54 +020012#include <stdio_dev.h>
Simon Glass10453152019-11-14 12:57:30 -070013#include <time.h>
wdenka042ac82002-09-12 22:36:57 +000014#include <watchdog.h>
Christian Rieschc90a4dd2011-12-09 16:54:02 +010015#include <div64.h>
wdenka042ac82002-09-12 22:36:57 +000016#include <post.h>
17
Mike Frysinger9146d132011-05-10 07:01:21 +000018#ifdef CONFIG_SYS_POST_HOTKEYS_GPIO
19#include <asm/gpio.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 */
Ovidiu Panait7addd3c2020-11-28 10:43:10 +0200131int 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 }
Ovidiu Panait7addd3c2020-11-28 10:43:10 +0200146
147 return 0;
wdenk228f29a2002-12-08 09:53:23 +0000148}
149
Heiko Schochere92372c2011-10-12 01:18:05 +0000150static void post_bootmode_test_on(unsigned int last_test)
wdenka042ac82002-09-12 22:36:57 +0000151{
Heiko Schochere92372c2011-10-12 01:18:05 +0000152 unsigned long word = post_word_load();
wdenka042ac82002-09-12 22:36:57 +0000153
154 word |= POST_POWERTEST;
155
156 word |= (last_test & 0xFF) << 8;
157
Heiko Schochere92372c2011-10-12 01:18:05 +0000158 post_word_store(word);
wdenka042ac82002-09-12 22:36:57 +0000159}
160
Heiko Schochere92372c2011-10-12 01:18:05 +0000161static void post_bootmode_test_off(void)
wdenka042ac82002-09-12 22:36:57 +0000162{
Heiko Schochere92372c2011-10-12 01:18:05 +0000163 unsigned long word = post_word_load();
wdenka042ac82002-09-12 22:36:57 +0000164
165 word &= ~POST_POWERTEST;
166
Heiko Schochere92372c2011-10-12 01:18:05 +0000167 post_word_store(word);
wdenka042ac82002-09-12 22:36:57 +0000168}
169
Valentin Longchamp212a0ca2011-08-03 02:37:02 +0000170#ifndef CONFIG_POST_SKIP_ENV_FLAGS
171static void post_get_env_flags(int *test_flags)
wdenka042ac82002-09-12 22:36:57 +0000172{
Yuri Tikhonove262efe2008-02-04 14:11:03 +0100173 int flag[] = { POST_POWERON, POST_NORMAL, POST_SLOWTEST,
174 POST_CRITICAL };
175 char *var[] = { "post_poweron", "post_normal", "post_slowtest",
176 "post_critical" };
Mike Frysingerd2397812011-05-10 07:28:35 +0000177 int varnum = ARRAY_SIZE(var);
wdenka042ac82002-09-12 22:36:57 +0000178 char list[128]; /* long enough for POST list */
179 char *name;
180 char *s;
181 int last;
182 int i, j;
183
wdenka042ac82002-09-12 22:36:57 +0000184 for (i = 0; i < varnum; i++) {
Simon Glass00caae62017-08-03 12:22:12 -0600185 if (env_get_f(var[i], list, sizeof(list)) <= 0)
wdenka042ac82002-09-12 22:36:57 +0000186 continue;
187
Wolfgang Denk50da8372011-10-29 09:42:22 +0000188 for (j = 0; j < post_list_size; j++)
wdenka042ac82002-09-12 22:36:57 +0000189 test_flags[j] &= ~flag[i];
wdenka042ac82002-09-12 22:36:57 +0000190
191 last = 0;
192 name = list;
193 while (!last) {
Heinrich Schuchardt86eeac72020-08-03 22:12:13 +0200194 while (*name == ' ')
wdenka042ac82002-09-12 22:36:57 +0000195 name++;
196 if (*name == 0)
197 break;
198 s = name + 1;
199 while (*s && *s != ' ')
200 s++;
201 if (*s == 0)
202 last = 1;
203 else
204 *s = 0;
205
206 for (j = 0; j < post_list_size; j++) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000207 if (strcmp(post_list[j].cmd, name) == 0) {
wdenka042ac82002-09-12 22:36:57 +0000208 test_flags[j] |= flag[i];
209 break;
210 }
211 }
212
Heiko Schochere92372c2011-10-12 01:18:05 +0000213 if (j == post_list_size)
Wolfgang Denk50da8372011-10-29 09:42:22 +0000214 printf("No such test: %s\n", name);
wdenka042ac82002-09-12 22:36:57 +0000215
216 name = s + 1;
217 }
218 }
Valentin Longchamp212a0ca2011-08-03 02:37:02 +0000219}
220#endif
221
222static void post_get_flags(int *test_flags)
223{
224 int j;
225
226 for (j = 0; j < post_list_size; j++)
227 test_flags[j] = post_list[j].flags;
228
229#ifndef CONFIG_POST_SKIP_ENV_FLAGS
230 post_get_env_flags(test_flags);
231#endif
wdenk6dff5522003-07-15 07:45:49 +0000232
Heiko Schochere92372c2011-10-12 01:18:05 +0000233 for (j = 0; j < post_list_size; j++)
234 if (test_flags[j] & POST_POWERON)
wdenk6dff5522003-07-15 07:45:49 +0000235 test_flags[j] |= POST_SLOWTEST;
wdenka042ac82002-09-12 22:36:57 +0000236}
237
Jeroen Hofstee002ad7b2014-10-08 22:57:25 +0200238__weak void show_post_progress(unsigned int test_num, int before, int result)
Michael Zaidmane070a562010-03-01 11:47:36 +0200239{
240}
Michael Zaidmane070a562010-03-01 11:47:36 +0200241
Heiko Schochere92372c2011-10-12 01:18:05 +0000242static int post_run_single(struct post_test *test,
wdenka042ac82002-09-12 22:36:57 +0000243 int test_flags, int flags, unsigned int i)
244{
245 if ((flags & test_flags & POST_ALWAYS) &&
246 (flags & test_flags & POST_MEM)) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000247 WATCHDOG_RESET();
wdenka042ac82002-09-12 22:36:57 +0000248
249 if (!(flags & POST_REBOOT)) {
Heiko Schochere92372c2011-10-12 01:18:05 +0000250 if ((test_flags & POST_REBOOT) &&
251 !(flags & POST_MANUAL)) {
252 post_bootmode_test_on(
Yuri Tikhonove262efe2008-02-04 14:11:03 +0100253 (gd->flags & GD_FLG_POSTFAIL) ?
254 POST_FAIL_SAVE | i : i);
wdenka042ac82002-09-12 22:36:57 +0000255 }
256
wdenk228f29a2002-12-08 09:53:23 +0000257 if (test_flags & POST_PREREL)
Heiko Schochere92372c2011-10-12 01:18:05 +0000258 post_log_mark_start(test->testid);
wdenk228f29a2002-12-08 09:53:23 +0000259 else
Heiko Schochere92372c2011-10-12 01:18:05 +0000260 post_log("POST %s ", test->cmd);
wdenka042ac82002-09-12 22:36:57 +0000261 }
262
Michael Zaidmane070a562010-03-01 11:47:36 +0200263 show_post_progress(i, POST_BEFORE, POST_FAILED);
264
wdenk228f29a2002-12-08 09:53:23 +0000265 if (test_flags & POST_PREREL) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000266 if ((*test->test)(flags) == 0) {
Heiko Schochere92372c2011-10-12 01:18:05 +0000267 post_log_mark_succ(test->testid);
Michael Zaidmane070a562010-03-01 11:47:36 +0200268 show_post_progress(i, POST_AFTER, POST_PASSED);
Wolfgang Denk50da8372011-10-29 09:42:22 +0000269 } else {
Michael Zaidmane070a562010-03-01 11:47:36 +0200270 show_post_progress(i, POST_AFTER, POST_FAILED);
Yuri Tikhonov28a38502008-05-08 15:45:26 +0200271 if (test_flags & POST_CRITICAL)
272 gd->flags |= GD_FLG_POSTFAIL;
273 if (test_flags & POST_STOP)
274 gd->flags |= GD_FLG_POSTSTOP;
275 }
wdenk228f29a2002-12-08 09:53:23 +0000276 } else {
James Kosin975afc32011-07-14 08:15:06 +0000277 if ((*test->test)(flags) != 0) {
278 post_log("FAILED\n");
Simon Glass770605e2012-02-13 13:51:18 +0000279 bootstage_error(BOOTSTAGE_ID_POST_FAIL_R);
James Kosin975afc32011-07-14 08:15:06 +0000280 show_post_progress(i, POST_AFTER, POST_FAILED);
281 if (test_flags & POST_CRITICAL)
282 gd->flags |= GD_FLG_POSTFAIL;
283 if (test_flags & POST_STOP)
284 gd->flags |= GD_FLG_POSTSTOP;
285 } else {
286 post_log("PASSED\n");
287 show_post_progress(i, POST_AFTER, POST_PASSED);
288 }
wdenk228f29a2002-12-08 09:53:23 +0000289 }
wdenka042ac82002-09-12 22:36:57 +0000290
Wolfgang Denk50da8372011-10-29 09:42:22 +0000291 if ((test_flags & POST_REBOOT) && !(flags & POST_MANUAL))
Heiko Schochere92372c2011-10-12 01:18:05 +0000292 post_bootmode_test_off();
wdenka042ac82002-09-12 22:36:57 +0000293
294 return 0;
295 } else {
296 return -1;
297 }
298}
299
Wolfgang Denk50da8372011-10-29 09:42:22 +0000300int post_run(char *name, int flags)
wdenka042ac82002-09-12 22:36:57 +0000301{
302 unsigned int i;
303 int test_flags[POST_MAX_NUMBER];
304
Heiko Schochere92372c2011-10-12 01:18:05 +0000305 post_get_flags(test_flags);
wdenka042ac82002-09-12 22:36:57 +0000306
307 if (name == NULL) {
308 unsigned int last;
309
Yuri Tikhonov28a38502008-05-08 15:45:26 +0200310 if (gd->flags & GD_FLG_POSTSTOP)
311 return 0;
312
Heiko Schochere92372c2011-10-12 01:18:05 +0000313 if (post_bootmode_get(&last) & POST_POWERTEST) {
Yuri Tikhonove262efe2008-02-04 14:11:03 +0100314 if (last & POST_FAIL_SAVE) {
315 last &= ~POST_FAIL_SAVE;
316 gd->flags |= GD_FLG_POSTFAIL;
317 }
wdenka042ac82002-09-12 22:36:57 +0000318 if (last < post_list_size &&
319 (flags & test_flags[last] & POST_ALWAYS) &&
320 (flags & test_flags[last] & POST_MEM)) {
321
Heiko Schochere92372c2011-10-12 01:18:05 +0000322 post_run_single(post_list + last,
wdenkea909b72002-11-21 23:11:29 +0000323 test_flags[last],
324 flags | POST_REBOOT, last);
wdenka042ac82002-09-12 22:36:57 +0000325
326 for (i = last + 1; i < post_list_size; i++) {
Yuri Tikhonov28a38502008-05-08 15:45:26 +0200327 if (gd->flags & GD_FLG_POSTSTOP)
328 break;
Heiko Schochere92372c2011-10-12 01:18:05 +0000329 post_run_single(post_list + i,
wdenkea909b72002-11-21 23:11:29 +0000330 test_flags[i],
331 flags, i);
wdenka042ac82002-09-12 22:36:57 +0000332 }
333 }
334 } else {
335 for (i = 0; i < post_list_size; i++) {
Yuri Tikhonov28a38502008-05-08 15:45:26 +0200336 if (gd->flags & GD_FLG_POSTSTOP)
337 break;
Heiko Schochere92372c2011-10-12 01:18:05 +0000338 post_run_single(post_list + i,
wdenkea909b72002-11-21 23:11:29 +0000339 test_flags[i],
340 flags, i);
wdenka042ac82002-09-12 22:36:57 +0000341 }
342 }
343
344 return 0;
345 } else {
346 for (i = 0; i < post_list_size; i++) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000347 if (strcmp(post_list[i].cmd, name) == 0)
wdenka042ac82002-09-12 22:36:57 +0000348 break;
349 }
350
351 if (i < post_list_size) {
Sascha Laue5744ddc2008-05-30 09:48:14 +0200352 WATCHDOG_RESET();
Heiko Schochere92372c2011-10-12 01:18:05 +0000353 return post_run_single(post_list + i,
wdenka042ac82002-09-12 22:36:57 +0000354 test_flags[i],
355 flags, i);
356 } else {
357 return -1;
358 }
359 }
360}
361
Heiko Schochere92372c2011-10-12 01:18:05 +0000362static int post_info_single(struct post_test *test, int full)
wdenka042ac82002-09-12 22:36:57 +0000363{
364 if (test->flags & POST_MANUAL) {
365 if (full)
Heiko Schochere92372c2011-10-12 01:18:05 +0000366 printf("%s - %s\n"
wdenka042ac82002-09-12 22:36:57 +0000367 " %s\n", test->cmd, test->name, test->desc);
368 else
Heiko Schochere92372c2011-10-12 01:18:05 +0000369 printf(" %-15s - %s\n", test->cmd, test->name);
wdenka042ac82002-09-12 22:36:57 +0000370
371 return 0;
372 } else {
373 return -1;
374 }
375}
376
Wolfgang Denk50da8372011-10-29 09:42:22 +0000377int post_info(char *name)
wdenka042ac82002-09-12 22:36:57 +0000378{
379 unsigned int i;
380
381 if (name == NULL) {
Heiko Schochere92372c2011-10-12 01:18:05 +0000382 for (i = 0; i < post_list_size; i++)
383 post_info_single(post_list + i, 0);
wdenka042ac82002-09-12 22:36:57 +0000384
385 return 0;
386 } else {
387 for (i = 0; i < post_list_size; i++) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000388 if (strcmp(post_list[i].cmd, name) == 0)
wdenka042ac82002-09-12 22:36:57 +0000389 break;
390 }
391
Wolfgang Denk50da8372011-10-29 09:42:22 +0000392 if (i < post_list_size)
Heiko Schochere92372c2011-10-12 01:18:05 +0000393 return post_info_single(post_list + i, 1);
Wolfgang Denk50da8372011-10-29 09:42:22 +0000394 else
wdenka042ac82002-09-12 22:36:57 +0000395 return -1;
wdenka042ac82002-09-12 22:36:57 +0000396 }
397}
398
Heiko Schochere92372c2011-10-12 01:18:05 +0000399int post_log(char *format, ...)
wdenka042ac82002-09-12 22:36:57 +0000400{
401 va_list args;
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200402 char printbuffer[CONFIG_SYS_PBSIZE];
wdenka042ac82002-09-12 22:36:57 +0000403
Wolfgang Denk50da8372011-10-29 09:42:22 +0000404 va_start(args, format);
wdenka042ac82002-09-12 22:36:57 +0000405
406 /* For this to work, printbuffer must be larger than
407 * anything we ever want to print.
408 */
Wolfgang Denk4d6402b2011-10-29 09:42:23 +0000409 vsprintf(printbuffer, format, args);
Wolfgang Denk50da8372011-10-29 09:42:22 +0000410 va_end(args);
wdenka042ac82002-09-12 22:36:57 +0000411
412 /* Send to the stdout file */
Heiko Schochere92372c2011-10-12 01:18:05 +0000413 puts(printbuffer);
wdenka042ac82002-09-12 22:36:57 +0000414
415 return 0;
416}
417
Wolfgang Denk2e5167c2010-10-28 20:00:11 +0200418#ifdef CONFIG_NEEDS_MANUAL_RELOC
Heiko Schochere92372c2011-10-12 01:18:05 +0000419void post_reloc(void)
wdenka042ac82002-09-12 22:36:57 +0000420{
wdenka042ac82002-09-12 22:36:57 +0000421 unsigned int i;
422
423 /*
424 * We have to relocate the test table manually
425 */
426 for (i = 0; i < post_list_size; i++) {
427 ulong addr;
428 struct post_test *test = post_list + i;
429
430 if (test->name) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000431 addr = (ulong)(test->name) + gd->reloc_off;
Heiko Schochere92372c2011-10-12 01:18:05 +0000432 test->name = (char *)addr;
wdenka042ac82002-09-12 22:36:57 +0000433 }
434
435 if (test->cmd) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000436 addr = (ulong)(test->cmd) + gd->reloc_off;
Heiko Schochere92372c2011-10-12 01:18:05 +0000437 test->cmd = (char *)addr;
wdenka042ac82002-09-12 22:36:57 +0000438 }
439
440 if (test->desc) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000441 addr = (ulong)(test->desc) + gd->reloc_off;
Heiko Schochere92372c2011-10-12 01:18:05 +0000442 test->desc = (char *)addr;
wdenka042ac82002-09-12 22:36:57 +0000443 }
444
445 if (test->test) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000446 addr = (ulong)(test->test) + gd->reloc_off;
wdenka042ac82002-09-12 22:36:57 +0000447 test->test = (int (*)(int flags)) addr;
448 }
wdenk4532cb62003-04-27 22:52:51 +0000449
450 if (test->init_f) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000451 addr = (ulong)(test->init_f) + gd->reloc_off;
wdenk4532cb62003-04-27 22:52:51 +0000452 test->init_f = (int (*)(void)) addr;
453 }
454
455 if (test->reloc) {
Wolfgang Denk50da8372011-10-29 09:42:22 +0000456 addr = (ulong)(test->reloc) + gd->reloc_off;
wdenk4532cb62003-04-27 22:52:51 +0000457 test->reloc = (void (*)(void)) addr;
wdenk8bde7f72003-06-27 21:31:46 +0000458
wdenk4532cb62003-04-27 22:52:51 +0000459 test->reloc();
460 }
wdenka042ac82002-09-12 22:36:57 +0000461 }
462}
Peter Tyser521af042009-09-21 11:20:36 -0500463#endif
wdenka042ac82002-09-12 22:36:57 +0000464
wdenk4532cb62003-04-27 22:52:51 +0000465
466/*
467 * Some tests (e.g. SYSMON) need the time when post_init_f started,
468 * but we cannot use get_timer() at this point.
469 *
470 * On PowerPC we implement it using the timebase register.
471 */
Heiko Schochere92372c2011-10-12 01:18:05 +0000472unsigned long post_time_ms(unsigned long base)
wdenk4532cb62003-04-27 22:52:51 +0000473{
Tom Riniea3310e2017-03-14 11:08:10 -0400474#if defined(CONFIG_PPC) || defined(CONFIG_ARM)
Christian Rieschc90a4dd2011-12-09 16:54:02 +0100475 return (unsigned long)lldiv(get_ticks(), get_tbclk() / CONFIG_SYS_HZ)
Heiko Schochere92372c2011-10-12 01:18:05 +0000476 - base;
wdenk4532cb62003-04-27 22:52:51 +0000477#else
Wolfgang Denkad5bb452007-03-06 18:08:43 +0100478#warning "Not implemented yet"
wdenk4532cb62003-04-27 22:52:51 +0000479 return 0; /* Not implemented yet */
480#endif
481}