1 /* 2 * (C) Copyright 2007 3 * Nobuhiro Iwamatsu <iwamatsu@nigauri.org> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <command.h> 10 #include <asm/processor.h> 11 #include <asm/io.h> 12 13 /* 14 * Jump to P2 area. 15 * When handling TLB or caches, we need to do it from P2 area. 16 */ 17 #define jump_to_P2() \ 18 do { \ 19 unsigned long __dummy; \ 20 __asm__ __volatile__( \ 21 "mov.l 1f, %0\n\t" \ 22 "or %1, %0\n\t" \ 23 "jmp @%0\n\t" \ 24 " nop\n\t" \ 25 ".balign 4\n" \ 26 "1: .long 2f\n" \ 27 "2:" \ 28 : "=&r" (__dummy) \ 29 : "r" (0x20000000)); \ 30 } while (0) 31 32 /* 33 * Back to P1 area. 34 */ 35 #define back_to_P1() \ 36 do { \ 37 unsigned long __dummy; \ 38 __asm__ __volatile__( \ 39 "nop;nop;nop;nop;nop;nop;nop\n\t" \ 40 "mov.l 1f, %0\n\t" \ 41 "jmp @%0\n\t" \ 42 " nop\n\t" \ 43 ".balign 4\n" \ 44 "1: .long 2f\n" \ 45 "2:" \ 46 : "=&r" (__dummy)); \ 47 } while (0) 48 49 #define CACHE_VALID 1 50 #define CACHE_UPDATED 2 51 52 static inline void cache_wback_all(void) 53 { 54 unsigned long addr, data, i, j; 55 56 jump_to_P2(); 57 for (i = 0; i < CACHE_OC_NUM_ENTRIES; i++){ 58 for (j = 0; j < CACHE_OC_NUM_WAYS; j++) { 59 addr = CACHE_OC_ADDRESS_ARRAY | (j << CACHE_OC_WAY_SHIFT) 60 | (i << CACHE_OC_ENTRY_SHIFT); 61 data = inl(addr); 62 if (data & CACHE_UPDATED) { 63 data &= ~CACHE_UPDATED; 64 outl(data, addr); 65 } 66 } 67 } 68 back_to_P1(); 69 } 70 71 72 #define CACHE_ENABLE 0 73 #define CACHE_DISABLE 1 74 75 int cache_control(unsigned int cmd) 76 { 77 unsigned long ccr; 78 79 jump_to_P2(); 80 ccr = inl(CCR); 81 82 if (ccr & CCR_CACHE_ENABLE) 83 cache_wback_all(); 84 85 if (cmd == CACHE_DISABLE) 86 outl(CCR_CACHE_STOP, CCR); 87 else 88 outl(CCR_CACHE_INIT, CCR); 89 back_to_P1(); 90 91 return 0; 92 } 93 94 void flush_dcache_range(unsigned long start, unsigned long end) 95 { 96 u32 v; 97 98 start &= ~(L1_CACHE_BYTES - 1); 99 for (v = start; v < end; v += L1_CACHE_BYTES) { 100 asm volatile ("ocbwb %0" : /* no output */ 101 : "m" (__m(v))); 102 } 103 } 104 105 void invalidate_dcache_range(unsigned long start, unsigned long end) 106 { 107 u32 v; 108 109 start &= ~(L1_CACHE_BYTES - 1); 110 for (v = start; v < end; v += L1_CACHE_BYTES) { 111 asm volatile ("ocbi %0" : /* no output */ 112 : "m" (__m(v))); 113 } 114 } 115