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