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