1*0ae76531SDavid Feng /* 2*0ae76531SDavid Feng * (C) Copyright 2013 3*0ae76531SDavid Feng * David Feng <fenghua@phytium.com.cn> 4*0ae76531SDavid Feng * 5*0ae76531SDavid Feng * SPDX-License-Identifier: GPL-2.0+ 6*0ae76531SDavid Feng */ 7*0ae76531SDavid Feng 8*0ae76531SDavid Feng #include <common.h> 9*0ae76531SDavid Feng #include <asm/system.h> 10*0ae76531SDavid Feng #include <asm/armv8/mmu.h> 11*0ae76531SDavid Feng 12*0ae76531SDavid Feng DECLARE_GLOBAL_DATA_PTR; 13*0ae76531SDavid Feng 14*0ae76531SDavid Feng #ifndef CONFIG_SYS_DCACHE_OFF 15*0ae76531SDavid Feng 16*0ae76531SDavid Feng static void set_pgtable_section(u64 section, u64 memory_type) 17*0ae76531SDavid Feng { 18*0ae76531SDavid Feng u64 *page_table = (u64 *)gd->arch.tlb_addr; 19*0ae76531SDavid Feng u64 value; 20*0ae76531SDavid Feng 21*0ae76531SDavid Feng value = (section << SECTION_SHIFT) | PMD_TYPE_SECT | PMD_SECT_AF; 22*0ae76531SDavid Feng value |= PMD_ATTRINDX(memory_type); 23*0ae76531SDavid Feng page_table[section] = value; 24*0ae76531SDavid Feng } 25*0ae76531SDavid Feng 26*0ae76531SDavid Feng /* to activate the MMU we need to set up virtual memory */ 27*0ae76531SDavid Feng static void mmu_setup(void) 28*0ae76531SDavid Feng { 29*0ae76531SDavid Feng int i, j, el; 30*0ae76531SDavid Feng bd_t *bd = gd->bd; 31*0ae76531SDavid Feng 32*0ae76531SDavid Feng /* Setup an identity-mapping for all spaces */ 33*0ae76531SDavid Feng for (i = 0; i < (PGTABLE_SIZE >> 3); i++) 34*0ae76531SDavid Feng set_pgtable_section(i, MT_DEVICE_NGNRNE); 35*0ae76531SDavid Feng 36*0ae76531SDavid Feng /* Setup an identity-mapping for all RAM space */ 37*0ae76531SDavid Feng for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 38*0ae76531SDavid Feng ulong start = bd->bi_dram[i].start; 39*0ae76531SDavid Feng ulong end = bd->bi_dram[i].start + bd->bi_dram[i].size; 40*0ae76531SDavid Feng for (j = start >> SECTION_SHIFT; 41*0ae76531SDavid Feng j < end >> SECTION_SHIFT; j++) { 42*0ae76531SDavid Feng set_pgtable_section(j, MT_NORMAL); 43*0ae76531SDavid Feng } 44*0ae76531SDavid Feng } 45*0ae76531SDavid Feng 46*0ae76531SDavid Feng /* load TTBR0 */ 47*0ae76531SDavid Feng el = current_el(); 48*0ae76531SDavid Feng if (el == 1) 49*0ae76531SDavid Feng asm volatile("msr ttbr0_el1, %0" 50*0ae76531SDavid Feng : : "r" (gd->arch.tlb_addr) : "memory"); 51*0ae76531SDavid Feng else if (el == 2) 52*0ae76531SDavid Feng asm volatile("msr ttbr0_el2, %0" 53*0ae76531SDavid Feng : : "r" (gd->arch.tlb_addr) : "memory"); 54*0ae76531SDavid Feng else 55*0ae76531SDavid Feng asm volatile("msr ttbr0_el3, %0" 56*0ae76531SDavid Feng : : "r" (gd->arch.tlb_addr) : "memory"); 57*0ae76531SDavid Feng 58*0ae76531SDavid Feng /* enable the mmu */ 59*0ae76531SDavid Feng set_sctlr(get_sctlr() | CR_M); 60*0ae76531SDavid Feng } 61*0ae76531SDavid Feng 62*0ae76531SDavid Feng /* 63*0ae76531SDavid Feng * Performs a invalidation of the entire data cache at all levels 64*0ae76531SDavid Feng */ 65*0ae76531SDavid Feng void invalidate_dcache_all(void) 66*0ae76531SDavid Feng { 67*0ae76531SDavid Feng __asm_flush_dcache_all(); 68*0ae76531SDavid Feng } 69*0ae76531SDavid Feng 70*0ae76531SDavid Feng /* 71*0ae76531SDavid Feng * Performs a clean & invalidation of the entire data cache at all levels 72*0ae76531SDavid Feng */ 73*0ae76531SDavid Feng void flush_dcache_all(void) 74*0ae76531SDavid Feng { 75*0ae76531SDavid Feng __asm_flush_dcache_all(); 76*0ae76531SDavid Feng } 77*0ae76531SDavid Feng 78*0ae76531SDavid Feng /* 79*0ae76531SDavid Feng * Invalidates range in all levels of D-cache/unified cache 80*0ae76531SDavid Feng */ 81*0ae76531SDavid Feng void invalidate_dcache_range(unsigned long start, unsigned long stop) 82*0ae76531SDavid Feng { 83*0ae76531SDavid Feng __asm_flush_dcache_range(start, stop); 84*0ae76531SDavid Feng } 85*0ae76531SDavid Feng 86*0ae76531SDavid Feng /* 87*0ae76531SDavid Feng * Flush range(clean & invalidate) from all levels of D-cache/unified cache 88*0ae76531SDavid Feng */ 89*0ae76531SDavid Feng void flush_dcache_range(unsigned long start, unsigned long stop) 90*0ae76531SDavid Feng { 91*0ae76531SDavid Feng __asm_flush_dcache_range(start, stop); 92*0ae76531SDavid Feng } 93*0ae76531SDavid Feng 94*0ae76531SDavid Feng void dcache_enable(void) 95*0ae76531SDavid Feng { 96*0ae76531SDavid Feng /* The data cache is not active unless the mmu is enabled */ 97*0ae76531SDavid Feng if (!(get_sctlr() & CR_M)) { 98*0ae76531SDavid Feng invalidate_dcache_all(); 99*0ae76531SDavid Feng __asm_invalidate_tlb_all(); 100*0ae76531SDavid Feng mmu_setup(); 101*0ae76531SDavid Feng } 102*0ae76531SDavid Feng 103*0ae76531SDavid Feng set_sctlr(get_sctlr() | CR_C); 104*0ae76531SDavid Feng } 105*0ae76531SDavid Feng 106*0ae76531SDavid Feng void dcache_disable(void) 107*0ae76531SDavid Feng { 108*0ae76531SDavid Feng uint32_t sctlr; 109*0ae76531SDavid Feng 110*0ae76531SDavid Feng sctlr = get_sctlr(); 111*0ae76531SDavid Feng 112*0ae76531SDavid Feng /* if cache isn't enabled no need to disable */ 113*0ae76531SDavid Feng if (!(sctlr & CR_C)) 114*0ae76531SDavid Feng return; 115*0ae76531SDavid Feng 116*0ae76531SDavid Feng set_sctlr(sctlr & ~(CR_C|CR_M)); 117*0ae76531SDavid Feng 118*0ae76531SDavid Feng flush_dcache_all(); 119*0ae76531SDavid Feng __asm_invalidate_tlb_all(); 120*0ae76531SDavid Feng } 121*0ae76531SDavid Feng 122*0ae76531SDavid Feng int dcache_status(void) 123*0ae76531SDavid Feng { 124*0ae76531SDavid Feng return (get_sctlr() & CR_C) != 0; 125*0ae76531SDavid Feng } 126*0ae76531SDavid Feng 127*0ae76531SDavid Feng #else /* CONFIG_SYS_DCACHE_OFF */ 128*0ae76531SDavid Feng 129*0ae76531SDavid Feng void invalidate_dcache_all(void) 130*0ae76531SDavid Feng { 131*0ae76531SDavid Feng } 132*0ae76531SDavid Feng 133*0ae76531SDavid Feng void flush_dcache_all(void) 134*0ae76531SDavid Feng { 135*0ae76531SDavid Feng } 136*0ae76531SDavid Feng 137*0ae76531SDavid Feng void invalidate_dcache_range(unsigned long start, unsigned long stop) 138*0ae76531SDavid Feng { 139*0ae76531SDavid Feng } 140*0ae76531SDavid Feng 141*0ae76531SDavid Feng void flush_dcache_range(unsigned long start, unsigned long stop) 142*0ae76531SDavid Feng { 143*0ae76531SDavid Feng } 144*0ae76531SDavid Feng 145*0ae76531SDavid Feng void dcache_enable(void) 146*0ae76531SDavid Feng { 147*0ae76531SDavid Feng } 148*0ae76531SDavid Feng 149*0ae76531SDavid Feng void dcache_disable(void) 150*0ae76531SDavid Feng { 151*0ae76531SDavid Feng } 152*0ae76531SDavid Feng 153*0ae76531SDavid Feng int dcache_status(void) 154*0ae76531SDavid Feng { 155*0ae76531SDavid Feng return 0; 156*0ae76531SDavid Feng } 157*0ae76531SDavid Feng 158*0ae76531SDavid Feng #endif /* CONFIG_SYS_DCACHE_OFF */ 159*0ae76531SDavid Feng 160*0ae76531SDavid Feng #ifndef CONFIG_SYS_ICACHE_OFF 161*0ae76531SDavid Feng 162*0ae76531SDavid Feng void icache_enable(void) 163*0ae76531SDavid Feng { 164*0ae76531SDavid Feng set_sctlr(get_sctlr() | CR_I); 165*0ae76531SDavid Feng } 166*0ae76531SDavid Feng 167*0ae76531SDavid Feng void icache_disable(void) 168*0ae76531SDavid Feng { 169*0ae76531SDavid Feng set_sctlr(get_sctlr() & ~CR_I); 170*0ae76531SDavid Feng } 171*0ae76531SDavid Feng 172*0ae76531SDavid Feng int icache_status(void) 173*0ae76531SDavid Feng { 174*0ae76531SDavid Feng return (get_sctlr() & CR_I) != 0; 175*0ae76531SDavid Feng } 176*0ae76531SDavid Feng 177*0ae76531SDavid Feng void invalidate_icache_all(void) 178*0ae76531SDavid Feng { 179*0ae76531SDavid Feng __asm_invalidate_icache_all(); 180*0ae76531SDavid Feng } 181*0ae76531SDavid Feng 182*0ae76531SDavid Feng #else /* CONFIG_SYS_ICACHE_OFF */ 183*0ae76531SDavid Feng 184*0ae76531SDavid Feng void icache_enable(void) 185*0ae76531SDavid Feng { 186*0ae76531SDavid Feng } 187*0ae76531SDavid Feng 188*0ae76531SDavid Feng void icache_disable(void) 189*0ae76531SDavid Feng { 190*0ae76531SDavid Feng } 191*0ae76531SDavid Feng 192*0ae76531SDavid Feng int icache_status(void) 193*0ae76531SDavid Feng { 194*0ae76531SDavid Feng return 0; 195*0ae76531SDavid Feng } 196*0ae76531SDavid Feng 197*0ae76531SDavid Feng void invalidate_icache_all(void) 198*0ae76531SDavid Feng { 199*0ae76531SDavid Feng } 200*0ae76531SDavid Feng 201*0ae76531SDavid Feng #endif /* CONFIG_SYS_ICACHE_OFF */ 202*0ae76531SDavid Feng 203*0ae76531SDavid Feng /* 204*0ae76531SDavid Feng * Enable dCache & iCache, whether cache is actually enabled 205*0ae76531SDavid Feng * depend on CONFIG_SYS_DCACHE_OFF and CONFIG_SYS_ICACHE_OFF 206*0ae76531SDavid Feng */ 207*0ae76531SDavid Feng void enable_caches(void) 208*0ae76531SDavid Feng { 209*0ae76531SDavid Feng icache_enable(); 210*0ae76531SDavid Feng dcache_enable(); 211*0ae76531SDavid Feng } 212*0ae76531SDavid Feng 213*0ae76531SDavid Feng /* 214*0ae76531SDavid Feng * Flush range from all levels of d-cache/unified-cache 215*0ae76531SDavid Feng */ 216*0ae76531SDavid Feng void flush_cache(unsigned long start, unsigned long size) 217*0ae76531SDavid Feng { 218*0ae76531SDavid Feng flush_dcache_range(start, start + size); 219*0ae76531SDavid Feng } 220