1 /* 2 * (C) Copyright 2004 Texas Insturments 3 * 4 * (C) Copyright 2002 5 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> 6 * Marius Groeger <mgroeger@sysgo.de> 7 * 8 * (C) Copyright 2002 9 * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> 10 * 11 * SPDX-License-Identifier: GPL-2.0+ 12 */ 13 14 /* 15 * CPU specific code 16 */ 17 18 #include <common.h> 19 #include <command.h> 20 #include <asm/system.h> 21 22 static void cache_flush(void); 23 24 int cleanup_before_linux (void) 25 { 26 /* 27 * this function is called just before we call linux 28 * it prepares the processor for linux 29 * 30 * we turn off caches etc ... 31 */ 32 33 disable_interrupts (); 34 35 /* turn off I/D-cache */ 36 icache_disable(); 37 dcache_disable(); 38 /* flush I/D-cache */ 39 cache_flush(); 40 41 return 0; 42 } 43 44 static void cache_flush(void) 45 { 46 unsigned long i = 0; 47 /* clean entire data cache */ 48 asm volatile("mcr p15, 0, %0, c7, c10, 0" : : "r" (i)); 49 /* invalidate both caches and flush btb */ 50 asm volatile("mcr p15, 0, %0, c7, c7, 0" : : "r" (i)); 51 /* mem barrier to sync things */ 52 asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (i)); 53 } 54 55 #ifndef CONFIG_SYS_DCACHE_OFF 56 57 #ifndef CONFIG_SYS_CACHELINE_SIZE 58 #define CONFIG_SYS_CACHELINE_SIZE 32 59 #endif 60 61 void invalidate_dcache_all(void) 62 { 63 asm volatile("mcr p15, 0, %0, c7, c6, 0" : : "r" (0)); 64 } 65 66 void flush_dcache_all(void) 67 { 68 asm volatile("mcr p15, 0, %0, c7, c10, 0" : : "r" (0)); 69 asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); 70 } 71 72 static int check_cache_range(unsigned long start, unsigned long stop) 73 { 74 int ok = 1; 75 76 if (start & (CONFIG_SYS_CACHELINE_SIZE - 1)) 77 ok = 0; 78 79 if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1)) 80 ok = 0; 81 82 if (!ok) 83 debug("CACHE: Misaligned operation at range [%08lx, %08lx]\n", 84 start, stop); 85 86 return ok; 87 } 88 89 void invalidate_dcache_range(unsigned long start, unsigned long stop) 90 { 91 if (!check_cache_range(start, stop)) 92 return; 93 94 while (start < stop) { 95 asm volatile("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)); 96 start += CONFIG_SYS_CACHELINE_SIZE; 97 } 98 } 99 100 void flush_dcache_range(unsigned long start, unsigned long stop) 101 { 102 if (!check_cache_range(start, stop)) 103 return; 104 105 while (start < stop) { 106 asm volatile("mcr p15, 0, %0, c7, c14, 1" : : "r" (start)); 107 start += CONFIG_SYS_CACHELINE_SIZE; 108 } 109 110 asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); 111 } 112 113 #else /* #ifndef CONFIG_SYS_DCACHE_OFF */ 114 void invalidate_dcache_all(void) 115 { 116 } 117 118 void flush_dcache_all(void) 119 { 120 } 121 #endif /* #ifndef CONFIG_SYS_DCACHE_OFF */ 122 123 #if !defined(CONFIG_SYS_ICACHE_OFF) || !defined(CONFIG_SYS_DCACHE_OFF) 124 void enable_caches(void) 125 { 126 #ifndef CONFIG_SYS_ICACHE_OFF 127 icache_enable(); 128 #endif 129 #ifndef CONFIG_SYS_DCACHE_OFF 130 dcache_enable(); 131 #endif 132 } 133 #endif 134