Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | // SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2008 Texas Insturments * * (C) Copyright 2002 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> * Marius Groeger <mgroeger@sysgo.de> * * (C) Copyright 2002 * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> */ #include <bootm.h> #include <command.h> #include <cpu_func.h> #include <irq_func.h> #include <passage.h> #include <asm/cache.h> #include <asm/system.h> #include <asm/secure.h> #include <linux/compiler.h> /* * sdelay() - simple spin loop. * * Will delay execution by roughly (@loops * 2) cycles. * This is necessary to be used before timers are accessible. * * A value of "0" will results in 2^64 loops. */ void sdelay(unsigned long loops) { __asm__ volatile ("1:\n" "subs %0, %0, #1\n" "b.ne 1b" : "=r" (loops) : "0"(loops) : "cc"); } void __weak board_cleanup_before_linux(void){} int cleanup_before_linux(void) { /* * this function is called just before we call linux * it prepares the processor for linux * * disable interrupt and turn off caches etc ... */ board_cleanup_before_linux(); disable_interrupts(); if (IS_ENABLED(CONFIG_CMO_BY_VA_ONLY)) { /* * Disable D-cache. */ dcache_disable(); } else { /* * Turn off I-cache and invalidate it */ icache_disable(); invalidate_icache_all(); /* * turn off D-cache * dcache_disable() in turn flushes the d-cache and disables * MMU */ dcache_disable(); invalidate_dcache_all(); } return 0; } #ifdef CONFIG_ARMV8_PSCI static void relocate_secure_section(void) { #ifdef CONFIG_ARMV8_SECURE_BASE size_t sz = __secure_end - __secure_start; memcpy((void *)CONFIG_ARMV8_SECURE_BASE, __secure_start, sz); flush_dcache_range(CONFIG_ARMV8_SECURE_BASE, CONFIG_ARMV8_SECURE_BASE + sz + 1); invalidate_icache_all(); #endif } void armv8_setup_psci(void) { if (current_el() != 3) return; relocate_secure_section(); secure_ram_addr(psci_setup_vectors)(); secure_ram_addr(psci_arch_init)(); } #endif void allow_unaligned(void) { set_sctlr(get_sctlr() & ~CR_A); } void __noreturn arch_passage_entry(ulong entry_addr, ulong bloblist, ulong fdt) { typedef void __noreturn (*passage_entry_t)(ulong fdt, ulong abi, ulong zero1, ulong bloblist, ulong zero2); passage_entry_t entry = (passage_entry_t)entry_addr; /* * Register Contents * x0 Address of devicetree * x1 00000001_4a0fb10b (indicates standard passage v1) * x2 0 * x3 Address of bloblist * x30 Return address */ entry(fdt, passage_mach_version(), 0, bloblist, 0); } |