diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index 254a629a3b..c22f7b6a51 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -139,6 +139,37 @@ int dcache_status(void) return (get_sctlr() & CR_C) != 0; } +u64 *__weak arch_get_page_table(void) { + puts("No page table offset defined\n"); + + return NULL; +} + +void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size, + enum dcache_option option) +{ + u64 *page_table = arch_get_page_table(); + u64 upto, end; + + if (page_table == NULL) + return; + + end = ALIGN(start + size, (1 << MMU_SECTION_SHIFT)) >> + MMU_SECTION_SHIFT; + start = start >> MMU_SECTION_SHIFT; + for (upto = start; upto < end; upto++) { + page_table[upto] &= ~PMD_ATTRINDX_MASK; + page_table[upto] |= PMD_ATTRINDX(option); + } + asm volatile("dsb sy"); + __asm_invalidate_tlb_all(); + asm volatile("dsb sy"); + asm volatile("isb"); + start = start << MMU_SECTION_SHIFT; + end = end << MMU_SECTION_SHIFT; + flush_dcache_range(start, end); + asm volatile("dsb sy"); +} #else /* CONFIG_SYS_DCACHE_OFF */ void invalidate_dcache_all(void) @@ -170,6 +201,11 @@ int dcache_status(void) return 0; } +void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size, + enum dcache_option option) +{ +} + #endif /* CONFIG_SYS_DCACHE_OFF */ #ifndef CONFIG_SYS_ICACHE_OFF diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 760e8ab1c8..868ea54b4f 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -15,9 +15,15 @@ #define CR_EE (1 << 25) /* Exception (Big) Endian */ #define PGTABLE_SIZE (0x10000) +/* 2MB granularity */ +#define MMU_SECTION_SHIFT 21 #ifndef __ASSEMBLY__ +enum dcache_option { + DCACHE_OFF = 0x3, +}; + #define isb() \ ({asm volatile( \ "isb" : : : "memory"); \ @@ -264,16 +270,6 @@ enum { #define TTBR0_IRGN_WB (1 << 0 | 1 << 6) #endif -/** - * Change the cache settings for a region. - * - * \param start start address of memory region to change - * \param size size of memory region to change - * \param option dcache option to select - */ -void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size, - enum dcache_option option); - /** * Register an update to the page tables, and flush the TLB * @@ -295,4 +291,17 @@ phys_addr_t noncached_alloc(size_t size, size_t align); #endif /* CONFIG_ARM64 */ +#ifndef __ASSEMBLY__ +/** + * Change the cache settings for a region. + * + * \param start start address of memory region to change + * \param size size of memory region to change + * \param option dcache option to select + */ +void mmu_set_region_dcache_behaviour(phys_addr_t start, size_t size, + enum dcache_option option); + +#endif /* __ASSEMBLY__ */ + #endif