1 /* Copyright 2023 The ChromiumOS Authors
2  * SPDX-License-Identifier: Apache-2.0
3  */
4 
5 #include <zephyr/devicetree.h>
6 #include <zephyr/sys/libc-hooks.h>
7 #include <string.h>
8 #include <kernel_internal.h>
9 
10 extern char _mtk_adsp_sram_end[];
11 
12 #define SRAM_START DT_REG_ADDR(DT_NODELABEL(sram0))
13 #define SRAM_SIZE  DT_REG_SIZE(DT_NODELABEL(sram0))
14 #define SRAM_END   (SRAM_START + SRAM_SIZE)
15 
16 extern char _mtk_adsp_dram_end[];
17 
18 #define DRAM_START DT_REG_ADDR(DT_NODELABEL(dram0))
19 #define DRAM_SIZE  DT_REG_SIZE(DT_NODELABEL(dram0))
20 #define DRAM_END   (DRAM_START + DRAM_SIZE)
21 
22 #define DMA_START DT_REG_ADDR(DT_NODELABEL(dram1))
23 #define DMA_SIZE  DT_REG_SIZE(DT_NODELABEL(dram1))
24 #define DMA_END   (DMA_START + DMA_SIZE)
25 
26 
27 #ifdef CONFIG_SOC_MT8196
28 #define INIT_STACK "0x90400000"
29 #define LOG_BASE   0x90580000
30 #define LOG_LEN    0x80000
31 #else
32 #define INIT_STACK "0x60e00000"
33 #define LOG_BASE   0x60700000
34 #define LOG_LEN    0x100000
35 #endif
36 
37 /* The MT8196 interrupt controller is very simple at runtime, with
38  * just an enable and status register needed, like its
39  * predecessors. But it has routing control which resets to "nothing
40  * enabled", so needs a driver.
41  *
42  * There are 64 interrupt inputs to the controller, controlled by
43  * pairs of words (the "intc64" type below).  Each interrupt is
44  * associated with one[1] of 16 "groups", each of which directs to a
45  * different Xtensa architectural interrupt.  So each Xtensa interrupt
46  * can be configured to handle any subset of interrupt inputs.
47  *
48  * The mapping of groups to Xtensa interrupts is given below.  Note
49  * particularly that the final two groups are NMIs directed to an
50  * interrupt level higher than EXCM_LEVEL, so cannot be safely used
51  * for OS code (they'll interrupt spinlocks), but an app might exploit
52  * them for e.g. debug or watchdog hooks.
53  *
54  * GroupNum  XtensaIRQ  XtensaLevel
55  *     0-5        0-5       1  (L1 is shared w/exceptions, poor choice)
56  *     6-7        7-8       1
57  *    8-10       9-11       2
58  *   11-13      16-18       3
59  *   14,15      20,21       4  (Unmaskable! Do not use w/Zephyr code!)
60  *
61  * Naming of the inputs looks like this, though obviously only a small
62  * fraction have been validated (or are even useful for an audio DSP):
63  *
64  *  0: CCU              20: USB1             40: WDT
65  *  1: SCP              21: SCPVOW           41: CONNSYS1
66  *  2: SPM              22: CCIF3_C0         42: CONNSYS3
67  *  3: PCIE             23: CCIF3_C1         43: CONNSYS4
68  *  4: INFRA_HANG       24: PWR_CTRL         44: CONNSYS2
69  *  5: PERI_TIMEOUT     25: DMA_C0           45: IPIC
70  *  6: MBOX_C0          26: DMA_C1           46: AXI_DMA2
71  *  7: MBOX_C1          27: AXI_DMA0         47: AXI_DMA3
72  *  8: TIMER0           28: AXI_DMA1         48: APSRC_DDREN
73  *  9: TIMER1           29: AUDIO_C0         49: LAT_MON_EMI
74  * 10: IPC_C0           30: AUDIO_C1         50: LAT_MON_INFRA
75  * 11: IPC_C1           31: HIFI5_WDT_C0     51: DEVAPC_VIO
76  * 12: IPC1_RSV         32: HIFI5_WDT_C1     52: AO_INFRA_HANG
77  * 13: C2C_SW_C0        33: APU_MBOX_C0      53: BUS_TRA_EMI
78  * 14: C2C_SW_C1        34: APU_MBOX_C1      54: BUS_TRA_INFRA
79  * 15: UART             35: TIMER2           55: L2SRAM_VIO
80  * 16: UART_BT          36: PWR_ON_C0_IRQ    56: L2SRAM_SETERR
81  * 17: LATENCY_MON      37: PWR_ON_C1_IRQ    57: PCIERC_GRP2
82  * 18: BUS_TRACKER      38: WAKEUP_SRC_C0    58: PCIERC_GRP3
83  * 19: USB0             39: WAKEUP_SRC_C1    59: IRQ_MAX_CHANNEL
84  *
85  * [1] It is legal and works as expected for an interrupt to be part
86  *     of more than one group (more than one interrupt fires to handle
87  *     it), though I don't understand why an application would want to
88  *     do that.
89  */
90 
91 struct intc64 { uint32_t lo, hi; };
92 
93 struct intc_8196 {
94 	struct intc64 input;        /* Raw (?) input signal, normally high */
95 	struct intc64 status;       /* Latched input, inverted (active == 1) */
96 	struct intc64 enable;       /* Interrupt enable */
97 	struct intc64 polarity;     /* 1 == active low */
98 	struct intc64 wake_enable;
99 	struct intc64 _unused;
100 	struct intc64 stage1_enable;
101 	struct intc64 sw_trigger;
102 	struct intc64 groups[16];       /* set bit == "member of group" */
103 	struct intc64 group_status[16]; /* status, but masked by group */
104 };
105 
106 #define INTC (*(volatile struct intc_8196 *)0x1a014000)
107 
set_group_bit(volatile struct intc64 * g,uint32_t bit,bool val)108 static void set_group_bit(volatile struct intc64 *g, uint32_t bit, bool val)
109 {
110 	volatile uint32_t *p  = bit < 32 ? &g->lo : &g->hi;
111 	volatile uint32_t mask = BIT(bit & 0x1f);
112 
113 	*p = val ? (*p | mask) : (*p & ~mask);
114 }
115 
mt8196_intc_set_irq_group(uint32_t irq,uint32_t group)116 static void mt8196_intc_set_irq_group(uint32_t irq, uint32_t group)
117 {
118 	for (int i = 0; i < 16; i++) {
119 		set_group_bit(&INTC.groups[i], irq, i == group);
120 	}
121 }
122 
mt8196_intc_init(void)123 void mt8196_intc_init(void)
124 {
125 	struct intc64 zero = { 0, 0 };
126 
127 	INTC.enable = zero;
128 	INTC.polarity.lo = 0xffffffff;
129 	INTC.polarity.hi = 0xffffffff;
130 	INTC.wake_enable = zero;
131 	INTC.stage1_enable = zero;
132 	for (int i = 0; i < ARRAY_SIZE(INTC.groups); i++) {
133 		INTC.groups[i] = zero;
134 	}
135 
136 	/* Now wire up known interrupts for existing drivers to their
137 	 * legacy settings
138 	 */
139 	mt8196_intc_set_irq_group(6, 2); /* mbox0 in group 2 */
140 	mt8196_intc_set_irq_group(7, 2); /* mbox1 in group 2 */
141 	mt8196_intc_set_irq_group(8, 1); /* ostimer in group 1 */
142 }
143 
144 /* This is the true boot vector.  This device allows for direct
145  * setting of the alternate reset vector, so we let it link wherever
146  * it lands and extract its address in the loader.  This represents
147  * the minimum amount of effort required to successfully call a C
148  * function (and duplicates a few versions elsewhere in the tree:
149  * really this should move to the arch layer).  The initial stack
150  * really should be the end of _interrupt_stacks[0]
151  */
152 __asm__(".align 4\n\t"
153 	".global mtk_adsp_boot_entry\n\t"
154 	"mtk_adsp_boot_entry:\n\t"
155 	"  movi  a0, 0x4002f\n\t" /* WOE|EXCM|INTLVL=15 */
156 	"  wsr   a0, PS\n\t"
157 	"  movi  a0, 0\n\t"
158 	"  wsr   a0, WINDOWBASE\n\t"
159 	"  movi  a0, 1\n\t"
160 	"  wsr   a0, WINDOWSTART\n\t"
161 	"  rsync\n\t"
162 	"  movi  a1, " INIT_STACK "\n\t"
163 	"  call4 c_boot\n\t");
164 
165 /* Unfortunately the SOF kernel loader doesn't understand the boot
166  * vector in the ELF/rimage file yet, so we still need a stub to get
167  * actual audio firmware to load.  Leave a stub in place that jumps to
168  * our "real" vector.  Note that this is frustratingly pessimal: the
169  * kernel wants the entry point to be at the start of the SRAM region,
170  * but (1) Xtensa can only load an immediate from addresses LOWER than
171  * a L32R instruction, which we can't do and so need to jump across a
172  * region to put one, and (2) the vector table that gets displaced has
173  * a 1024 byte alignment requirement, forcing us to waste ~1011 bytes
174  * needlessly.
175  */
176 __asm__(".pushsection .sof_entry.text\n\t"
177 	"  j 2f\n"
178 	".align 4\n\t"
179 	"1:\n\t"
180 	"  .word mtk_adsp_boot_entry\n"
181 	"2:\n\t"
182 	"  l32r a0, 1b\n\t"
183 	"  jx a0\n\t"
184 	".popsection");
185 
186 /* Initial MPU configuration, needed to enable caching */
enable_mpu(void)187 static void enable_mpu(void)
188 {
189 	/* Note: we set the linked/in-use-by-zephyr regions of both
190 	 * SRAM and DRAM cached for performance.  The remainder is
191 	 * left uncached, as it's likely to be shared with the host
192 	 * and/or DMA.  This seems like a good default choice pending
193 	 * proper MPU integration
194 	 */
195 	static const uint32_t mpu[][2] = {
196 		{ 0x00000000, 0x06000 },          /* inaccessible null region */
197 		{ 0x10000000, 0x06f00 },          /* MMIO registers */
198 		{ 0x1d000000, 0x06000 },          /* inaccessible */
199 		{ SRAM_START, 0xf7f00 },          /* cached SRAM */
200 		{ SRAM_END,   0x06000 },          /* inaccessible */
201 		{ DRAM_START, 0xf7f00 },          /* cached DRAM */
202 		{ (uint32_t)&_mtk_adsp_dram_end, 0x06f00 }, /* uncached DRAM */
203 		{ DRAM_END,   0x06000 },          /* inaccessible top of mem */
204 		{ DMA_START,  0x06f00 },          /* uncached host "DMA" area */
205 		{ DMA_END,    0x06000 },          /* inaccessible top of mem */
206 	};
207 
208 	/* Must write BACKWARDS FROM THE END to avoid introducing a
209 	 * non-monotonic segment at the current instruction fetch.  The
210 	 * exception triggers even if all the segments involved are
211 	 * disabled!
212 	 */
213 	int32_t nseg = ARRAY_SIZE(mpu);
214 
215 	for (int32_t i = 31; i >= 32 - nseg; i--) {
216 		int32_t mpuidx = i - (32 - nseg);
217 		uint32_t addren = mpu[mpuidx][0] | 1;
218 		uint32_t segprot = (mpu[mpuidx][1]) | i;
219 
220 		/* If an active pipelined instruction fetch is in the
221 		 * same segment, wptlb must be preceded by a memw in
222 		 * the same cache line.  Jumping to an aligned-by-8
223 		 * address ensures that the following two (3-byte)
224 		 * instructions are in the same 8 byte-aligned region.
225 		 */
226 		__asm__ volatile("  j 1f\n"
227 				 ".align 8\n"
228 				 "1:\n"
229 				 "  memw\n"
230 				 "  wptlb %1, %0"
231 				 :: "r"(addren), "r"(segprot));
232 	}
233 }
234 
235 /* Temporary console output, pending integration of a winstream
236  * backend.  This simply appends a null-terminated string to an
237  * otherwise unused 1M region of shared DRAM (it's a hole in the SOF
238  * memory map before the DMA memory, so untouched by existing audio
239  * firmware), making early debugging much easier: it can be read
240  * directly out of /dev/mem (with e.g. dd | hexdump) and survives
241  * device resets/panics/etc.  But it doesn't handle more than 1M of
242  * output, there's no way to detect a reset of the stream, and in fact
243  * it's actually racy with device startup as if you read too early
244  * you'll see the old run and not the new one.  And it's wasteful,
245  * even if this device has a ton of usably-mapped DRAM
246  *
247  * Also note that the storage for the buffer and length value get
248  * reset by the DRAM clear near the end of c_boot().  If you want to
249  * use this for extremely early logging you'll need to stub out the
250  * dram clear and also set buf[0] to 0 manually (as it isn't affected
251  * by device reset).
252  */
253 #ifndef CONFIG_WINSTREAM_CONSOLE
arch_printk_char_out(int c)254 int arch_printk_char_out(int c)
255 {
256 	char volatile * const buf = (void *)LOG_BASE;
257 	const size_t max = LOG_LEN - 4;
258 	int volatile * const len = (int *)&buf[max];
259 
260 	if (*len < max) {
261 		buf[*len + 1] = 0;
262 		buf[(*len)++] = c;
263 	}
264 	return 0;
265 }
266 #endif
267 
268 /* Define this here as a simple uncached array, no special linkage requirements */
269 __nocache char _winstream_console_buf[CONFIG_WINSTREAM_CONSOLE_STATIC_SIZE];
270 
c_boot(void)271 void c_boot(void)
272 {
273 	extern char _bss_start, _bss_end, z_xtensa_vecbase; /* Linker-emitted */
274 	uint32_t memctl = 0xffffff00; /* enable all caches */
275 
276 	/* Clear bss before doing anything else, device memory is
277 	 * persistent across resets (!) and we'd like our static
278 	 * variables to be actually zero.  Do this without using
279 	 * memset() out of pedantry (because we don't know which libc is
280 	 * in use or whether it requires statics).
281 	 */
282 	for (char *p = &_bss_start; p < &_bss_end; p++) {
283 		*p = 0;
284 	}
285 
286 	/* Set up MPU memory regions, both for protection and to
287 	 * enable caching (the hardware defaults is "uncached rwx
288 	 * memory everywhere").
289 	 */
290 	enable_mpu();
291 
292 	/* But the CPU core won't actually use the cache without MEMCTL... */
293 	__asm__ volatile("wsr %0, MEMCTL; rsync" :: "r"(memctl));
294 
295 	/* Need the vector base set to receive exceptions and
296 	 * interrupts (including register window exceptions, meaning
297 	 * we can't make C function calls until this is done!)
298 	 */
299 	__asm__ volatile("wsr %0, VECBASE; rsync" :: "r"(&z_xtensa_vecbase));
300 
301 #ifdef CONFIG_SOC_SERIES_MT8195
302 	mtk_adsp_cpu_freq_init();
303 #endif
304 
305 	/* Likewise, memory power is external to the device, and the
306 	 * kernel SOF loader doesn't zero it, so zero our unlinked
307 	 * memory to prevent possible pollution from previous runs.
308 	 * This region is uncached, no need to flush.
309 	 */
310 	memset(_mtk_adsp_sram_end, 0, SRAM_END - (uint32_t)&_mtk_adsp_sram_end);
311 	memset(_mtk_adsp_dram_end, 0, DRAM_END - (uint32_t)&_mtk_adsp_dram_end);
312 
313 	/* Clear pending interrupts.  Note that this hardware has a
314 	 * habit of starting with all its timer interrupts flagged.
315 	 * These have to be cleared by writing to the equivalent
316 	 * CCOMPAREn register.  Assumes XCHAL_NUM_TIMERS == 3...
317 	 */
318 	uint32_t val = 0;
319 
320 	__asm__ volatile("wsr %0, CCOMPARE0" :: "r"(val));
321 	__asm__ volatile("wsr %0, CCOMPARE1" :: "r"(val));
322 	__asm__ volatile("wsr %0, CCOMPARE2" :: "r"(val));
323 	__ASSERT_NO_MSG(XCHAL_NUM_TIMERS == 3);
324 	val = 0xffffffff;
325 	__asm__ volatile("wsr %0, INTCLEAR" :: "r"(val));
326 
327 	/* Default console, a driver can override this later */
328 	__stdout_hook_install(arch_printk_char_out);
329 
330 #ifdef CONFIG_SOC_MT8196
331 	mt8196_intc_init();
332 #endif
333 
334 	void z_prep_c(void);
335 	z_prep_c();
336 }
337