12c451f78SAneesh V /* 22c451f78SAneesh V * (C) Copyright 2010 32c451f78SAneesh V * Texas Instruments, <www.ti.com> 42c451f78SAneesh V * Aneesh V <aneesh@ti.com> 52c451f78SAneesh V * 61a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 72c451f78SAneesh V */ 82c451f78SAneesh V #include <linux/types.h> 92c451f78SAneesh V #include <common.h> 102c451f78SAneesh V #include <asm/armv7.h> 112c451f78SAneesh V #include <asm/utils.h> 122c451f78SAneesh V 13*df120142SHans de Goede #define ARMV7_DCACHE_INVAL_RANGE 1 14*df120142SHans de Goede #define ARMV7_DCACHE_CLEAN_INVAL_RANGE 2 152c451f78SAneesh V 162c451f78SAneesh V #ifndef CONFIG_SYS_DCACHE_OFF 17c09d2905SHans de Goede 18c09d2905SHans de Goede /* Asm functions from cache_v7_asm.S */ 19c09d2905SHans de Goede void v7_flush_dcache_all(void); 20*df120142SHans de Goede void v7_invalidate_dcache_all(void); 21c09d2905SHans de Goede 2211aa6a32SMarek Vasut static int check_cache_range(unsigned long start, unsigned long stop) 2311aa6a32SMarek Vasut { 2411aa6a32SMarek Vasut int ok = 1; 2511aa6a32SMarek Vasut 2611aa6a32SMarek Vasut if (start & (CONFIG_SYS_CACHELINE_SIZE - 1)) 2711aa6a32SMarek Vasut ok = 0; 2811aa6a32SMarek Vasut 2911aa6a32SMarek Vasut if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1)) 3011aa6a32SMarek Vasut ok = 0; 3111aa6a32SMarek Vasut 3211aa6a32SMarek Vasut if (!ok) 3311aa6a32SMarek Vasut debug("CACHE: Misaligned operation at range [%08lx, %08lx]\n", 3411aa6a32SMarek Vasut start, stop); 3511aa6a32SMarek Vasut 3611aa6a32SMarek Vasut return ok; 3711aa6a32SMarek Vasut } 3811aa6a32SMarek Vasut 392c451f78SAneesh V static u32 get_ccsidr(void) 402c451f78SAneesh V { 412c451f78SAneesh V u32 ccsidr; 422c451f78SAneesh V 432c451f78SAneesh V /* Read current CP15 Cache Size ID Register */ 442c451f78SAneesh V asm volatile ("mrc p15, 1, %0, c0, c0, 0" : "=r" (ccsidr)); 452c451f78SAneesh V return ccsidr; 462c451f78SAneesh V } 472c451f78SAneesh V 48b9297c22SThierry Reding static void v7_dcache_clean_inval_range(u32 start, u32 stop, u32 line_len) 492c451f78SAneesh V { 502c451f78SAneesh V u32 mva; 512c451f78SAneesh V 522c451f78SAneesh V /* Align start to cache line boundary */ 532c451f78SAneesh V start &= ~(line_len - 1); 542c451f78SAneesh V for (mva = start; mva < stop; mva = mva + line_len) { 552c451f78SAneesh V /* DCCIMVAC - Clean & Invalidate data cache by MVA to PoC */ 562c451f78SAneesh V asm volatile ("mcr p15, 0, %0, c7, c14, 1" : : "r" (mva)); 572c451f78SAneesh V } 582c451f78SAneesh V } 592c451f78SAneesh V 602c451f78SAneesh V static void v7_dcache_inval_range(u32 start, u32 stop, u32 line_len) 612c451f78SAneesh V { 622c451f78SAneesh V u32 mva; 632c451f78SAneesh V 642c451f78SAneesh V /* 65cabe2878SAneesh V * If start address is not aligned to cache-line do not 66cabe2878SAneesh V * invalidate the first cache-line 672c451f78SAneesh V */ 682c451f78SAneesh V if (start & (line_len - 1)) { 69cabe2878SAneesh V printf("ERROR: %s - start address is not aligned - 0x%08x\n", 70cabe2878SAneesh V __func__, start); 712c451f78SAneesh V /* move to next cache line */ 722c451f78SAneesh V start = (start + line_len - 1) & ~(line_len - 1); 732c451f78SAneesh V } 742c451f78SAneesh V 752c451f78SAneesh V /* 76cabe2878SAneesh V * If stop address is not aligned to cache-line do not 77cabe2878SAneesh V * invalidate the last cache-line 782c451f78SAneesh V */ 792c451f78SAneesh V if (stop & (line_len - 1)) { 80cabe2878SAneesh V printf("ERROR: %s - stop address is not aligned - 0x%08x\n", 81cabe2878SAneesh V __func__, stop); 822c451f78SAneesh V /* align to the beginning of this cache line */ 832c451f78SAneesh V stop &= ~(line_len - 1); 842c451f78SAneesh V } 852c451f78SAneesh V 862c451f78SAneesh V for (mva = start; mva < stop; mva = mva + line_len) { 872c451f78SAneesh V /* DCIMVAC - Invalidate data cache by MVA to PoC */ 882c451f78SAneesh V asm volatile ("mcr p15, 0, %0, c7, c6, 1" : : "r" (mva)); 892c451f78SAneesh V } 902c451f78SAneesh V } 912c451f78SAneesh V 922c451f78SAneesh V static void v7_dcache_maint_range(u32 start, u32 stop, u32 range_op) 932c451f78SAneesh V { 942c451f78SAneesh V u32 line_len, ccsidr; 952c451f78SAneesh V 962c451f78SAneesh V ccsidr = get_ccsidr(); 972c451f78SAneesh V line_len = ((ccsidr & CCSIDR_LINE_SIZE_MASK) >> 982c451f78SAneesh V CCSIDR_LINE_SIZE_OFFSET) + 2; 992c451f78SAneesh V /* Converting from words to bytes */ 1002c451f78SAneesh V line_len += 2; 1012c451f78SAneesh V /* converting from log2(linelen) to linelen */ 1022c451f78SAneesh V line_len = 1 << line_len; 1032c451f78SAneesh V 1042c451f78SAneesh V switch (range_op) { 1052c451f78SAneesh V case ARMV7_DCACHE_CLEAN_INVAL_RANGE: 1062c451f78SAneesh V v7_dcache_clean_inval_range(start, stop, line_len); 1072c451f78SAneesh V break; 1082c451f78SAneesh V case ARMV7_DCACHE_INVAL_RANGE: 1092c451f78SAneesh V v7_dcache_inval_range(start, stop, line_len); 1102c451f78SAneesh V break; 1112c451f78SAneesh V } 1122c451f78SAneesh V 113882f80b9SAneesh V /* DSB to make sure the operation is complete */ 1149ba379adSValentine Barshak DSB; 1152c451f78SAneesh V } 1162c451f78SAneesh V 1172c451f78SAneesh V /* Invalidate TLB */ 1182c451f78SAneesh V static void v7_inval_tlb(void) 1192c451f78SAneesh V { 1202c451f78SAneesh V /* Invalidate entire unified TLB */ 1212c451f78SAneesh V asm volatile ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0)); 1222c451f78SAneesh V /* Invalidate entire data TLB */ 1232c451f78SAneesh V asm volatile ("mcr p15, 0, %0, c8, c6, 0" : : "r" (0)); 1242c451f78SAneesh V /* Invalidate entire instruction TLB */ 1252c451f78SAneesh V asm volatile ("mcr p15, 0, %0, c8, c5, 0" : : "r" (0)); 1262c451f78SAneesh V /* Full system DSB - make sure that the invalidation is complete */ 1279ba379adSValentine Barshak DSB; 1282c451f78SAneesh V /* Full system ISB - make sure the instruction stream sees it */ 1299ba379adSValentine Barshak ISB; 1302c451f78SAneesh V } 1312c451f78SAneesh V 1322c451f78SAneesh V void invalidate_dcache_all(void) 1332c451f78SAneesh V { 134*df120142SHans de Goede v7_invalidate_dcache_all(); 1352c451f78SAneesh V 1362c451f78SAneesh V v7_outer_cache_inval_all(); 1372c451f78SAneesh V } 1382c451f78SAneesh V 1392c451f78SAneesh V /* 1402c451f78SAneesh V * Performs a clean & invalidation of the entire data cache 1412c451f78SAneesh V * at all levels 1422c451f78SAneesh V */ 1432c451f78SAneesh V void flush_dcache_all(void) 1442c451f78SAneesh V { 145c09d2905SHans de Goede v7_flush_dcache_all(); 1462c451f78SAneesh V 1472c451f78SAneesh V v7_outer_cache_flush_all(); 1482c451f78SAneesh V } 1492c451f78SAneesh V 1502c451f78SAneesh V /* 1512c451f78SAneesh V * Invalidates range in all levels of D-cache/unified cache used: 1522c451f78SAneesh V * Affects the range [start, stop - 1] 1532c451f78SAneesh V */ 1542c451f78SAneesh V void invalidate_dcache_range(unsigned long start, unsigned long stop) 1552c451f78SAneesh V { 15611aa6a32SMarek Vasut check_cache_range(start, stop); 15711aa6a32SMarek Vasut 1582c451f78SAneesh V v7_dcache_maint_range(start, stop, ARMV7_DCACHE_INVAL_RANGE); 1592c451f78SAneesh V 1602c451f78SAneesh V v7_outer_cache_inval_range(start, stop); 1612c451f78SAneesh V } 1622c451f78SAneesh V 1632c451f78SAneesh V /* 1642c451f78SAneesh V * Flush range(clean & invalidate) from all levels of D-cache/unified 1652c451f78SAneesh V * cache used: 1662c451f78SAneesh V * Affects the range [start, stop - 1] 1672c451f78SAneesh V */ 1682c451f78SAneesh V void flush_dcache_range(unsigned long start, unsigned long stop) 1692c451f78SAneesh V { 17011aa6a32SMarek Vasut check_cache_range(start, stop); 17111aa6a32SMarek Vasut 1722c451f78SAneesh V v7_dcache_maint_range(start, stop, ARMV7_DCACHE_CLEAN_INVAL_RANGE); 1732c451f78SAneesh V 1742c451f78SAneesh V v7_outer_cache_flush_range(start, stop); 1752c451f78SAneesh V } 1762c451f78SAneesh V 1772c451f78SAneesh V void arm_init_before_mmu(void) 1782c451f78SAneesh V { 1792c451f78SAneesh V v7_outer_cache_enable(); 1802c451f78SAneesh V invalidate_dcache_all(); 1812c451f78SAneesh V v7_inval_tlb(); 1822c451f78SAneesh V } 1832c451f78SAneesh V 1840dde7f53SSimon Glass void mmu_page_table_flush(unsigned long start, unsigned long stop) 1850dde7f53SSimon Glass { 1860dde7f53SSimon Glass flush_dcache_range(start, stop); 1870dde7f53SSimon Glass v7_inval_tlb(); 1880dde7f53SSimon Glass } 1892c451f78SAneesh V #else /* #ifndef CONFIG_SYS_DCACHE_OFF */ 1902c451f78SAneesh V void invalidate_dcache_all(void) 1912c451f78SAneesh V { 1922c451f78SAneesh V } 1932c451f78SAneesh V 1942c451f78SAneesh V void flush_dcache_all(void) 1952c451f78SAneesh V { 1962c451f78SAneesh V } 1972c451f78SAneesh V 1982c451f78SAneesh V void arm_init_before_mmu(void) 1992c451f78SAneesh V { 2002c451f78SAneesh V } 2012c451f78SAneesh V 2020dde7f53SSimon Glass void mmu_page_table_flush(unsigned long start, unsigned long stop) 2030dde7f53SSimon Glass { 2040dde7f53SSimon Glass } 2050dde7f53SSimon Glass 206de63ac27SR Sricharan void arm_init_domains(void) 207de63ac27SR Sricharan { 208de63ac27SR Sricharan } 2092c451f78SAneesh V #endif /* #ifndef CONFIG_SYS_DCACHE_OFF */ 2102c451f78SAneesh V 2112c451f78SAneesh V #ifndef CONFIG_SYS_ICACHE_OFF 2122c451f78SAneesh V /* Invalidate entire I-cache and branch predictor array */ 2132c451f78SAneesh V void invalidate_icache_all(void) 2142c451f78SAneesh V { 2152c451f78SAneesh V /* 2162c451f78SAneesh V * Invalidate all instruction caches to PoU. 2172c451f78SAneesh V * Also flushes branch target cache. 2182c451f78SAneesh V */ 2192c451f78SAneesh V asm volatile ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0)); 2202c451f78SAneesh V 2212c451f78SAneesh V /* Invalidate entire branch predictor array */ 2222c451f78SAneesh V asm volatile ("mcr p15, 0, %0, c7, c5, 6" : : "r" (0)); 2232c451f78SAneesh V 2242c451f78SAneesh V /* Full system DSB - make sure that the invalidation is complete */ 2259ba379adSValentine Barshak DSB; 2262c451f78SAneesh V 2272c451f78SAneesh V /* ISB - make sure the instruction stream sees it */ 2289ba379adSValentine Barshak ISB; 2292c451f78SAneesh V } 2302c451f78SAneesh V #else 2312c451f78SAneesh V void invalidate_icache_all(void) 2322c451f78SAneesh V { 2332c451f78SAneesh V } 2342c451f78SAneesh V #endif 2352c451f78SAneesh V 236fcfddfd5SJeroen Hofstee /* Stub implementations for outer cache operations */ 237fcfddfd5SJeroen Hofstee __weak void v7_outer_cache_enable(void) {} 238fcfddfd5SJeroen Hofstee __weak void v7_outer_cache_disable(void) {} 239fcfddfd5SJeroen Hofstee __weak void v7_outer_cache_flush_all(void) {} 240fcfddfd5SJeroen Hofstee __weak void v7_outer_cache_inval_all(void) {} 241fcfddfd5SJeroen Hofstee __weak void v7_outer_cache_flush_range(u32 start, u32 end) {} 242fcfddfd5SJeroen Hofstee __weak void v7_outer_cache_inval_range(u32 start, u32 end) {} 243