1 /* Copyright(c) 2021 Intel Corporation. All rights reserved.
2 * SPDX-License-Identifier: Apache-2.0
3 */
4
5
6 #include <stddef.h>
7 #include <stdint.h>
8
9 #include <zephyr/devicetree.h>
10 #include <zephyr/kernel.h>
11 #include <zephyr/init.h>
12 #include <soc_util.h>
13 #include <zephyr/cache.h>
14 #include <adsp_shim.h>
15 #include <adsp_memory.h>
16 #include <cpu_init.h>
17 #include "manifest.h"
18
19 /* Important note about linkage:
20 *
21 * The C code here, starting from boot_core0(), is running entirely in
22 * IMR memory. The sram banks are not initialized yet and the Zephyr
23 * code is not yet copied there. No use of this memory is legal until
24 * after parse_manifest() returns. This means that all symbols in
25 * this file must be flagged "__imr" or "__imrdata" (or be guaranteed
26 * to inline via ALWAYS_INLINE, normal gcc "inline" is only a hint)!
27 *
28 * There's a similar note with Xtensa register windows: the Zephyr
29 * exception handles for window overflow are not present in IMR.
30 * While on existing systems, we start running with a VECBASE pointing
31 * to ROM handlers (that seem to work), it seems unsafe to rely on
32 * that. It's not possible to hit an overflow until at least four
33 * nested function calls, so this is mostly theoretical. Nonetheless
34 * care should be taken here to make sure the function tree remains
35 * shallow until SRAM initialization is finished.
36 */
37
38 /* Various cAVS platform dependencies needed by the bootloader code.
39 * These probably want to migrate to devicetree.
40 */
41
42
43 #define HOST_PAGE_SIZE 4096
44 #define MANIFEST_SEGMENT_COUNT 3
45
46 /* FIXME: Use Kconfig or some other means */
47 #if !defined(CONFIG_SOC_SERIES_INTEL_ACE)
48 #define RESET_MEMORY_HOLE
49 #endif
50
51 /* Initial/true entry point. Does nothing but jump to
52 * z_boot_asm_entry (which cannot be here, because it needs to be able
53 * to reference immediates which must link before it)
54 */
55 __asm__(".pushsection .boot_entry.text, \"ax\" \n\t"
56 ".global rom_entry \n\t"
57 "rom_entry: \n\t"
58 " j z_boot_asm_entry \n\t"
59 ".popsection \n\t");
60
61 /* Entry stub. Sets up register windows and stack such that we can
62 * enter C code successfully, and calls boot_core0()
63 */
64 #define STRINGIFY_MACRO(x) Z_STRINGIFY(x)
65 #define IMRSTACK STRINGIFY_MACRO(IMR_BOOT_LDR_MANIFEST_BASE)
66 __asm__(".section .imr.z_boot_asm_entry, \"x\" \n\t"
67 ".align 4 \n\t"
68 "z_boot_asm_entry: \n\t"
69 " movi a0, 0x4002f \n\t"
70 " wsr a0, PS \n\t"
71 " movi a0, 0 \n\t"
72 " wsr a0, WINDOWBASE \n\t"
73 " movi a0, 1 \n\t"
74 " wsr a0, WINDOWSTART \n\t"
75 " rsync \n\t"
76 " movi a1, " IMRSTACK "\n\t"
77 " call4 boot_core0 \n\t");
78
parse_module(struct sof_man_fw_header * hdr,struct sof_man_module * mod)79 static __imr void parse_module(struct sof_man_fw_header *hdr,
80 struct sof_man_module *mod)
81 {
82 int i;
83 uint32_t bias;
84
85 /* each module has 3 segments */
86 for (i = 0; i < MANIFEST_SEGMENT_COUNT; i++) {
87
88 switch (mod->segment[i].flags.r.type) {
89 case SOF_MAN_SEGMENT_TEXT:
90 case SOF_MAN_SEGMENT_DATA:
91 if (mod->segment[i].flags.r.load == 0) {
92 continue;
93 }
94
95 bias = mod->segment[i].file_offset -
96 SOF_MAN_ELF_TEXT_OFFSET;
97
98 /* copy from IMR to SRAM */
99 bmemcpy((void *)mod->segment[i].v_base_addr,
100 (uint8_t *)hdr + bias,
101 mod->segment[i].flags.r.length *
102 HOST_PAGE_SIZE);
103 break;
104 case SOF_MAN_SEGMENT_BSS:
105 /* already bbzero'd by sram init */
106 break;
107 default:
108 /* ignore */
109 break;
110 }
111 }
112 }
113
114 #define MAN_SKIP_ENTRIES 1
115
116 /* parse FW manifest and copy modules */
parse_manifest(void)117 __imr void parse_manifest(void)
118 {
119 struct sof_man_fw_desc *desc =
120 (struct sof_man_fw_desc *)IMR_BOOT_LDR_MANIFEST_BASE;
121 struct sof_man_fw_header *hdr = &desc->header;
122 struct sof_man_module *mod;
123 int i;
124
125 sys_cache_data_invd_range(hdr, sizeof(*hdr));
126
127 /* copy module to SRAM - skip bootloader module */
128 for (i = MAN_SKIP_ENTRIES; i < hdr->num_module_entries; i++) {
129 mod = desc->man_module + i;
130
131 sys_cache_data_invd_range(mod, sizeof(*mod));
132 parse_module(hdr, mod);
133 }
134 }
135
136 extern void hp_sram_init(uint32_t memory_size);
137 extern void lp_sram_init(void);
138
boot_core0(void)139 __imr void boot_core0(void)
140 {
141 cpu_early_init();
142
143 #ifdef CONFIG_ADSP_DISABLE_L2CACHE_AT_BOOT
144 ADSP_L2PCFG_REG = 0;
145 #endif
146
147 #ifdef RESET_MEMORY_HOLE
148 /* reset memory hole */
149 CAVS_SHIM.l2mecs = 0;
150 #endif
151
152 hp_sram_init(L2_SRAM_SIZE);
153 lp_sram_init();
154 parse_manifest();
155 sys_cache_data_flush_all();
156
157 xtensa_vecbase_lock();
158
159 /* Zephyr! */
160 extern FUNC_NORETURN void z_cstart(void);
161 z_cstart();
162 }
163