1ea0364f1SPeter Tyser /* 2ea0364f1SPeter Tyser * (C) Copyright 2002 3ea0364f1SPeter Tyser * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4ea0364f1SPeter Tyser * 51a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 6ea0364f1SPeter Tyser */ 7ea0364f1SPeter Tyser 8ea0364f1SPeter Tyser /* for now: just dummy functions to satisfy the linker */ 9ea0364f1SPeter Tyser 10ea0364f1SPeter Tyser #include <common.h> 111dfdd9baSThierry Reding #include <malloc.h> 12ea0364f1SPeter Tyser 13397b5697SSimon Glass #ifndef CONFIG_SYS_CACHELINE_SIZE 14397b5697SSimon Glass #define CONFIG_SYS_CACHELINE_SIZE 32 15397b5697SSimon Glass #endif 16397b5697SSimon Glass 17633b6cceSWu, Josh /* 18633b6cceSWu, Josh * Flush range from all levels of d-cache/unified-cache. 19633b6cceSWu, Josh * Affects the range [start, start + size - 1]. 20633b6cceSWu, Josh */ 21fcfddfd5SJeroen Hofstee __weak void flush_cache(unsigned long start, unsigned long size) 22ea0364f1SPeter Tyser { 23633b6cceSWu, Josh flush_dcache_range(start, start + size); 24ea0364f1SPeter Tyser } 25e05f0079SAneesh V 26e05f0079SAneesh V /* 27e05f0079SAneesh V * Default implementation: 28e05f0079SAneesh V * do a range flush for the entire range 29e05f0079SAneesh V */ 30fcfddfd5SJeroen Hofstee __weak void flush_dcache_all(void) 31e05f0079SAneesh V { 32e05f0079SAneesh V flush_cache(0, ~0); 33e05f0079SAneesh V } 34cba4b180SAneesh V 35cba4b180SAneesh V /* 36cba4b180SAneesh V * Default implementation of enable_caches() 37cba4b180SAneesh V * Real implementation should be in platform code 38cba4b180SAneesh V */ 39fcfddfd5SJeroen Hofstee __weak void enable_caches(void) 40cba4b180SAneesh V { 41cba4b180SAneesh V puts("WARNING: Caches not enabled\n"); 42cba4b180SAneesh V } 431dfdd9baSThierry Reding 44387871a1SWu, Josh __weak void invalidate_dcache_range(unsigned long start, unsigned long stop) 45387871a1SWu, Josh { 46387871a1SWu, Josh /* An empty stub, real implementation should be in platform code */ 47387871a1SWu, Josh } 48387871a1SWu, Josh __weak void flush_dcache_range(unsigned long start, unsigned long stop) 49387871a1SWu, Josh { 50387871a1SWu, Josh /* An empty stub, real implementation should be in platform code */ 51387871a1SWu, Josh } 52387871a1SWu, Josh 53397b5697SSimon Glass int check_cache_range(unsigned long start, unsigned long stop) 54397b5697SSimon Glass { 55397b5697SSimon Glass int ok = 1; 56397b5697SSimon Glass 57397b5697SSimon Glass if (start & (CONFIG_SYS_CACHELINE_SIZE - 1)) 58397b5697SSimon Glass ok = 0; 59397b5697SSimon Glass 60397b5697SSimon Glass if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1)) 61397b5697SSimon Glass ok = 0; 62397b5697SSimon Glass 63397b5697SSimon Glass if (!ok) { 64*bcc53bf0SSimon Glass warn_non_spl("CACHE: Misaligned operation at range [%08lx, %08lx]\n", 65397b5697SSimon Glass start, stop); 66397b5697SSimon Glass } 67397b5697SSimon Glass 68397b5697SSimon Glass return ok; 69397b5697SSimon Glass } 70397b5697SSimon Glass 711dfdd9baSThierry Reding #ifdef CONFIG_SYS_NONCACHED_MEMORY 721dfdd9baSThierry Reding /* 731dfdd9baSThierry Reding * Reserve one MMU section worth of address space below the malloc() area that 741dfdd9baSThierry Reding * will be mapped uncached. 751dfdd9baSThierry Reding */ 761dfdd9baSThierry Reding static unsigned long noncached_start; 771dfdd9baSThierry Reding static unsigned long noncached_end; 781dfdd9baSThierry Reding static unsigned long noncached_next; 791dfdd9baSThierry Reding 801dfdd9baSThierry Reding void noncached_init(void) 811dfdd9baSThierry Reding { 821dfdd9baSThierry Reding phys_addr_t start, end; 831dfdd9baSThierry Reding size_t size; 841dfdd9baSThierry Reding 851dfdd9baSThierry Reding end = ALIGN(mem_malloc_start, MMU_SECTION_SIZE) - MMU_SECTION_SIZE; 861dfdd9baSThierry Reding size = ALIGN(CONFIG_SYS_NONCACHED_MEMORY, MMU_SECTION_SIZE); 871dfdd9baSThierry Reding start = end - size; 881dfdd9baSThierry Reding 891dfdd9baSThierry Reding debug("mapping memory %pa-%pa non-cached\n", &start, &end); 901dfdd9baSThierry Reding 911dfdd9baSThierry Reding noncached_start = start; 921dfdd9baSThierry Reding noncached_end = end; 931dfdd9baSThierry Reding noncached_next = start; 941dfdd9baSThierry Reding 951dfdd9baSThierry Reding #ifndef CONFIG_SYS_DCACHE_OFF 961dfdd9baSThierry Reding mmu_set_region_dcache_behaviour(noncached_start, size, DCACHE_OFF); 971dfdd9baSThierry Reding #endif 981dfdd9baSThierry Reding } 991dfdd9baSThierry Reding 1001dfdd9baSThierry Reding phys_addr_t noncached_alloc(size_t size, size_t align) 1011dfdd9baSThierry Reding { 1021dfdd9baSThierry Reding phys_addr_t next = ALIGN(noncached_next, align); 1031dfdd9baSThierry Reding 1041dfdd9baSThierry Reding if (next >= noncached_end || (noncached_end - next) < size) 1051dfdd9baSThierry Reding return 0; 1061dfdd9baSThierry Reding 1071dfdd9baSThierry Reding debug("allocated %zu bytes of uncached memory @%pa\n", size, &next); 1081dfdd9baSThierry Reding noncached_next = next + size; 1091dfdd9baSThierry Reding 1101dfdd9baSThierry Reding return next; 1111dfdd9baSThierry Reding } 1121dfdd9baSThierry Reding #endif /* CONFIG_SYS_NONCACHED_MEMORY */ 11362e92077SAlbert ARIBAUD 11462e92077SAlbert ARIBAUD #if defined(CONFIG_SYS_THUMB_BUILD) 11562e92077SAlbert ARIBAUD void invalidate_l2_cache(void) 11662e92077SAlbert ARIBAUD { 11762e92077SAlbert ARIBAUD unsigned int val = 0; 11862e92077SAlbert ARIBAUD 11962e92077SAlbert ARIBAUD asm volatile("mcr p15, 1, %0, c15, c11, 0 @ invl l2 cache" 12062e92077SAlbert ARIBAUD : : "r" (val) : "cc"); 12162e92077SAlbert ARIBAUD isb(); 12262e92077SAlbert ARIBAUD } 12362e92077SAlbert ARIBAUD #endif 124