1*21ff7344SThomas Chou /* 2*21ff7344SThomas Chou * Copyright (C) 2015 Thomas Chou <thomas@wytron.com.tw> 3*21ff7344SThomas Chou * Copyright (C) 2009, Wind River Systems Inc 4*21ff7344SThomas Chou * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com 5*21ff7344SThomas Chou * 6*21ff7344SThomas Chou * SPDX-License-Identifier: GPL-2.0+ 7*21ff7344SThomas Chou */ 8*21ff7344SThomas Chou 9*21ff7344SThomas Chou #include <common.h> 10*21ff7344SThomas Chou #include <asm/cache.h> 11*21ff7344SThomas Chou 12*21ff7344SThomas Chou DECLARE_GLOBAL_DATA_PTR; 13*21ff7344SThomas Chou 14*21ff7344SThomas Chou static void __flush_dcache(unsigned long start, unsigned long end) 15*21ff7344SThomas Chou { 16*21ff7344SThomas Chou unsigned long addr; 17*21ff7344SThomas Chou 18*21ff7344SThomas Chou start &= ~(gd->arch.dcache_line_size - 1); 19*21ff7344SThomas Chou end += (gd->arch.dcache_line_size - 1); 20*21ff7344SThomas Chou end &= ~(gd->arch.dcache_line_size - 1); 21*21ff7344SThomas Chou 22*21ff7344SThomas Chou for (addr = start; addr < end; addr += gd->arch.dcache_line_size) { 23*21ff7344SThomas Chou __asm__ __volatile__ (" flushda 0(%0)\n" 24*21ff7344SThomas Chou : /* Outputs */ 25*21ff7344SThomas Chou : /* Inputs */ "r"(addr) 26*21ff7344SThomas Chou /* : No clobber */); 27*21ff7344SThomas Chou } 28*21ff7344SThomas Chou } 29*21ff7344SThomas Chou 30*21ff7344SThomas Chou static void __flush_dcache_all(unsigned long start, unsigned long end) 31*21ff7344SThomas Chou { 32*21ff7344SThomas Chou unsigned long addr; 33*21ff7344SThomas Chou 34*21ff7344SThomas Chou start &= ~(gd->arch.dcache_line_size - 1); 35*21ff7344SThomas Chou end += (gd->arch.dcache_line_size - 1); 36*21ff7344SThomas Chou end &= ~(gd->arch.dcache_line_size - 1); 37*21ff7344SThomas Chou 38*21ff7344SThomas Chou if (end > start + gd->arch.dcache_size) 39*21ff7344SThomas Chou end = start + gd->arch.dcache_size; 40*21ff7344SThomas Chou 41*21ff7344SThomas Chou for (addr = start; addr < end; addr += gd->arch.dcache_line_size) { 42*21ff7344SThomas Chou __asm__ __volatile__ (" flushd 0(%0)\n" 43*21ff7344SThomas Chou : /* Outputs */ 44*21ff7344SThomas Chou : /* Inputs */ "r"(addr) 45*21ff7344SThomas Chou /* : No clobber */); 46*21ff7344SThomas Chou } 47*21ff7344SThomas Chou } 48*21ff7344SThomas Chou 49*21ff7344SThomas Chou static void __invalidate_dcache(unsigned long start, unsigned long end) 50*21ff7344SThomas Chou { 51*21ff7344SThomas Chou unsigned long addr; 52*21ff7344SThomas Chou 53*21ff7344SThomas Chou start &= ~(gd->arch.dcache_line_size - 1); 54*21ff7344SThomas Chou end += (gd->arch.dcache_line_size - 1); 55*21ff7344SThomas Chou end &= ~(gd->arch.dcache_line_size - 1); 56*21ff7344SThomas Chou 57*21ff7344SThomas Chou for (addr = start; addr < end; addr += gd->arch.dcache_line_size) { 58*21ff7344SThomas Chou __asm__ __volatile__ (" initda 0(%0)\n" 59*21ff7344SThomas Chou : /* Outputs */ 60*21ff7344SThomas Chou : /* Inputs */ "r"(addr) 61*21ff7344SThomas Chou /* : No clobber */); 62*21ff7344SThomas Chou } 63*21ff7344SThomas Chou } 64*21ff7344SThomas Chou 65*21ff7344SThomas Chou static void __flush_icache(unsigned long start, unsigned long end) 66*21ff7344SThomas Chou { 67*21ff7344SThomas Chou unsigned long addr; 68*21ff7344SThomas Chou 69*21ff7344SThomas Chou start &= ~(gd->arch.icache_line_size - 1); 70*21ff7344SThomas Chou end += (gd->arch.icache_line_size - 1); 71*21ff7344SThomas Chou end &= ~(gd->arch.icache_line_size - 1); 72*21ff7344SThomas Chou 73*21ff7344SThomas Chou if (end > start + gd->arch.icache_size) 74*21ff7344SThomas Chou end = start + gd->arch.icache_size; 75*21ff7344SThomas Chou 76*21ff7344SThomas Chou for (addr = start; addr < end; addr += gd->arch.icache_line_size) { 77*21ff7344SThomas Chou __asm__ __volatile__ (" flushi %0\n" 78*21ff7344SThomas Chou : /* Outputs */ 79*21ff7344SThomas Chou : /* Inputs */ "r"(addr) 80*21ff7344SThomas Chou /* : No clobber */); 81*21ff7344SThomas Chou } 82*21ff7344SThomas Chou __asm__ __volatile(" flushp\n"); 83*21ff7344SThomas Chou } 84*21ff7344SThomas Chou 85*21ff7344SThomas Chou void flush_dcache_all(void) 86*21ff7344SThomas Chou { 87*21ff7344SThomas Chou __flush_dcache_all(0, gd->arch.dcache_size); 88*21ff7344SThomas Chou __flush_icache(0, gd->arch.icache_size); 89*21ff7344SThomas Chou } 90*21ff7344SThomas Chou 91*21ff7344SThomas Chou void flush_dcache_range(unsigned long start, unsigned long end) 92*21ff7344SThomas Chou { 93*21ff7344SThomas Chou if (gd->arch.has_initda) 94*21ff7344SThomas Chou __flush_dcache(start, end); 95*21ff7344SThomas Chou else 96*21ff7344SThomas Chou __flush_dcache_all(start, end); 97*21ff7344SThomas Chou } 98*21ff7344SThomas Chou 99*21ff7344SThomas Chou void flush_cache(unsigned long start, unsigned long size) 100*21ff7344SThomas Chou { 101*21ff7344SThomas Chou if (gd->arch.has_initda) 102*21ff7344SThomas Chou __flush_dcache(start, start + size); 103*21ff7344SThomas Chou else 104*21ff7344SThomas Chou __flush_dcache_all(start, start + size); 105*21ff7344SThomas Chou __flush_icache(start, start + size); 106*21ff7344SThomas Chou } 107*21ff7344SThomas Chou 108*21ff7344SThomas Chou void invalidate_dcache_range(unsigned long start, unsigned long end) 109*21ff7344SThomas Chou { 110*21ff7344SThomas Chou if (gd->arch.has_initda) 111*21ff7344SThomas Chou __invalidate_dcache(start, end); 112*21ff7344SThomas Chou else 113*21ff7344SThomas Chou __flush_dcache_all(start, end); 114*21ff7344SThomas Chou } 115*21ff7344SThomas Chou 116*21ff7344SThomas Chou int dcache_status(void) 117*21ff7344SThomas Chou { 118*21ff7344SThomas Chou return 1; 119*21ff7344SThomas Chou } 120*21ff7344SThomas Chou 121*21ff7344SThomas Chou void dcache_enable(void) 122*21ff7344SThomas Chou { 123*21ff7344SThomas Chou flush_dcache_all(); 124*21ff7344SThomas Chou } 125*21ff7344SThomas Chou 126*21ff7344SThomas Chou void dcache_disable(void) 127*21ff7344SThomas Chou { 128*21ff7344SThomas Chou flush_dcache_all(); 129*21ff7344SThomas Chou } 130