xref: /openbmc/u-boot/arch/arm/cpu/armv8/cpu.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
20ae76531SDavid Feng /*
30ae76531SDavid Feng  * (C) Copyright 2008 Texas Insturments
40ae76531SDavid Feng  *
50ae76531SDavid Feng  * (C) Copyright 2002
60ae76531SDavid Feng  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
70ae76531SDavid Feng  * Marius Groeger <mgroeger@sysgo.de>
80ae76531SDavid Feng  *
90ae76531SDavid Feng  * (C) Copyright 2002
100ae76531SDavid Feng  * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de>
110ae76531SDavid Feng  */
120ae76531SDavid Feng 
130ae76531SDavid Feng #include <common.h>
140ae76531SDavid Feng #include <command.h>
150ae76531SDavid Feng #include <asm/system.h>
169a561753Smacro.wave.z@gmail.com #include <asm/secure.h>
170ae76531SDavid Feng #include <linux/compiler.h>
180ae76531SDavid Feng 
198ed02bc2SAndre Przywara /*
208ed02bc2SAndre Przywara  * sdelay() - simple spin loop.
218ed02bc2SAndre Przywara  *
228ed02bc2SAndre Przywara  * Will delay execution by roughly (@loops * 2) cycles.
238ed02bc2SAndre Przywara  * This is necessary to be used before timers are accessible.
248ed02bc2SAndre Przywara  *
258ed02bc2SAndre Przywara  * A value of "0" will results in 2^64 loops.
268ed02bc2SAndre Przywara  */
sdelay(unsigned long loops)278ed02bc2SAndre Przywara void sdelay(unsigned long loops)
288ed02bc2SAndre Przywara {
298ed02bc2SAndre Przywara 	__asm__ volatile ("1:\n" "subs %0, %0, #1\n"
308ed02bc2SAndre Przywara 			  "b.ne 1b" : "=r" (loops) : "0"(loops) : "cc");
318ed02bc2SAndre Przywara }
328ed02bc2SAndre Przywara 
cleanup_before_linux(void)330ae76531SDavid Feng int cleanup_before_linux(void)
340ae76531SDavid Feng {
350ae76531SDavid Feng 	/*
360ae76531SDavid Feng 	 * this function is called just before we call linux
370ae76531SDavid Feng 	 * it prepares the processor for linux
380ae76531SDavid Feng 	 *
390ae76531SDavid Feng 	 * disable interrupt and turn off caches etc ...
400ae76531SDavid Feng 	 */
410ae76531SDavid Feng 	disable_interrupts();
420ae76531SDavid Feng 
430ae76531SDavid Feng 	/*
440ae76531SDavid Feng 	 * Turn off I-cache and invalidate it
450ae76531SDavid Feng 	 */
460ae76531SDavid Feng 	icache_disable();
470ae76531SDavid Feng 	invalidate_icache_all();
480ae76531SDavid Feng 
490ae76531SDavid Feng 	/*
500ae76531SDavid Feng 	 * turn off D-cache
510ae76531SDavid Feng 	 * dcache_disable() in turn flushes the d-cache and disables MMU
520ae76531SDavid Feng 	 */
530ae76531SDavid Feng 	dcache_disable();
540ae76531SDavid Feng 	invalidate_dcache_all();
550ae76531SDavid Feng 
560ae76531SDavid Feng 	return 0;
570ae76531SDavid Feng }
589a561753Smacro.wave.z@gmail.com 
599a561753Smacro.wave.z@gmail.com #ifdef CONFIG_ARMV8_PSCI
relocate_secure_section(void)609a561753Smacro.wave.z@gmail.com static void relocate_secure_section(void)
619a561753Smacro.wave.z@gmail.com {
629a561753Smacro.wave.z@gmail.com #ifdef CONFIG_ARMV8_SECURE_BASE
639a561753Smacro.wave.z@gmail.com 	size_t sz = __secure_end - __secure_start;
649a561753Smacro.wave.z@gmail.com 
659a561753Smacro.wave.z@gmail.com 	memcpy((void *)CONFIG_ARMV8_SECURE_BASE, __secure_start, sz);
669a561753Smacro.wave.z@gmail.com 	flush_dcache_range(CONFIG_ARMV8_SECURE_BASE,
679a561753Smacro.wave.z@gmail.com 			   CONFIG_ARMV8_SECURE_BASE + sz + 1);
689a561753Smacro.wave.z@gmail.com 	invalidate_icache_all();
699a561753Smacro.wave.z@gmail.com #endif
709a561753Smacro.wave.z@gmail.com }
719a561753Smacro.wave.z@gmail.com 
armv8_setup_psci(void)729a561753Smacro.wave.z@gmail.com void armv8_setup_psci(void)
739a561753Smacro.wave.z@gmail.com {
749a561753Smacro.wave.z@gmail.com 	relocate_secure_section();
759a561753Smacro.wave.z@gmail.com 	secure_ram_addr(psci_setup_vectors)();
769a561753Smacro.wave.z@gmail.com 	secure_ram_addr(psci_arch_init)();
779a561753Smacro.wave.z@gmail.com }
789a561753Smacro.wave.z@gmail.com #endif
79