]>
Commit | Line | Data |
---|---|---|
1 | /** | |
2 | * Copyright (c) 2017 Google, Inc | |
3 | * | |
4 | * SPDX-License-Identifier: GPL-2.0+ | |
5 | */ | |
6 | ||
7 | #include <common.h> | |
8 | #include <asm/arch/bootrom.h> | |
9 | #include <asm/arch/boot_mode.h> | |
10 | #include <asm/io.h> | |
11 | #include <asm/setjmp.h> | |
12 | #include <asm/system.h> | |
13 | ||
14 | /* | |
15 | * Force the jmp_buf to the data-section, as .bss will not be valid | |
16 | * when save_boot_params is invoked. | |
17 | */ | |
18 | static jmp_buf brom_ctx __section(".data"); | |
19 | ||
20 | static void _back_to_bootrom(enum rockchip_bootrom_cmd brom_cmd) | |
21 | { | |
22 | longjmp(brom_ctx, brom_cmd); | |
23 | } | |
24 | ||
25 | void back_to_bootrom(enum rockchip_bootrom_cmd brom_cmd) | |
26 | { | |
27 | #if CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT) | |
28 | puts("Returning to boot ROM...\n"); | |
29 | #endif | |
30 | _back_to_bootrom(brom_cmd); | |
31 | } | |
32 | ||
33 | /* | |
34 | * we back to bootrom download mode if get a | |
35 | * BOOT_BROM_DOWNLOAD flag in boot mode register | |
36 | * | |
37 | * note: the boot mode register is configured by | |
38 | * application(next stage bootloader, kernel, etc), | |
39 | * and the bootrom never check this register, so we need | |
40 | * to check it and back to bootrom at very early bootstage(before | |
41 | * some basic configurations(such as interrupts) been | |
42 | * changed by TPL/SPL, as the bootrom download operation | |
43 | * relys on many default settings(such as interrupts) by | |
44 | * it's self. | |
45 | */ | |
46 | static bool check_back_to_brom_dnl_flag(void) | |
47 | { | |
48 | u32 boot_mode; | |
49 | ||
50 | if (CONFIG_ROCKCHIP_BOOT_MODE_REG) { | |
51 | boot_mode = readl(CONFIG_ROCKCHIP_BOOT_MODE_REG); | |
52 | if (boot_mode == BOOT_BROM_DOWNLOAD) { | |
53 | writel(0, CONFIG_ROCKCHIP_BOOT_MODE_REG); | |
54 | return true; | |
55 | } | |
56 | } | |
57 | ||
58 | return false; | |
59 | } | |
60 | ||
61 | /* | |
62 | * All Rockchip BROM implementations enter with a valid stack-pointer, | |
63 | * so this can safely be implemented in C (providing a single | |
64 | * implementation both for ARMv7 and AArch64). | |
65 | */ | |
66 | int save_boot_params(void) | |
67 | { | |
68 | int ret = setjmp(brom_ctx); | |
69 | ||
70 | switch (ret) { | |
71 | case 0: | |
72 | if (check_back_to_brom_dnl_flag()) | |
73 | _back_to_bootrom(BROM_BOOT_ENTER_DNL); | |
74 | /* | |
75 | * This is the initial pass through this function | |
76 | * (i.e. saving the context), setjmp just setup up the | |
77 | * brom_ctx: transfer back into the startup-code at | |
78 | * 'save_boot_params_ret' and let the compiler know | |
79 | * that this will not return. | |
80 | */ | |
81 | save_boot_params_ret(); | |
82 | while (true) | |
83 | /* does not return */; | |
84 | break; | |
85 | ||
86 | case BROM_BOOT_NEXTSTAGE: | |
87 | /* | |
88 | * To instruct the BROM to boot the next stage, we | |
89 | * need to return 0 to it: i.e. we need to rewrite | |
90 | * the return code once more. | |
91 | */ | |
92 | ret = 0; | |
93 | break; | |
94 | case BROM_BOOT_ENTER_DNL: | |
95 | /* | |
96 | * A non-zero return value will instruct the BROM enter | |
97 | * download mode. | |
98 | */ | |
99 | ret = 1; | |
100 | break; | |
101 | default: | |
102 | #if CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT) | |
103 | puts("FATAL: unexpected command to back_to_bootrom()\n"); | |
104 | #endif | |
105 | hang(); | |
106 | }; | |
107 | ||
108 | return ret; | |
109 | } |