1 /*
2 * Copyright (c) 2015 Stefan Kristiansson
3 *
4 * Use of this source code is governed by a MIT-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/MIT
7 */
8
9 #include <arch/ops.h>
10 #include <arch/or1k.h>
11
dc_block_size(void)12 static inline uint32_t dc_block_size(void) {
13 uint32_t dccfgr = mfspr(OR1K_SPR_SYS_DCCFGR_ADDR);
14
15 return dccfgr & OR1K_SPR_SYS_DCCFGR_CBS_MASK ? 32 : 16;
16 }
17
dc_sets(void)18 static inline uint32_t dc_sets(void) {
19 uint32_t dccfgr = mfspr(OR1K_SPR_SYS_DCCFGR_ADDR);
20
21 return 1 << OR1K_SPR_SYS_DCCFGR_NCS_GET(dccfgr);
22 }
23
ic_block_size(void)24 static inline uint32_t ic_block_size(void) {
25 uint32_t iccfgr = mfspr(OR1K_SPR_SYS_ICCFGR_ADDR);
26
27 return iccfgr & OR1K_SPR_SYS_ICCFGR_CBS_MASK ? 32 : 16;
28 }
29
ic_sets(void)30 static inline uint32_t ic_sets(void) {
31 uint32_t iccfgr = mfspr(OR1K_SPR_SYS_ICCFGR_ADDR);
32
33 return 1 << OR1K_SPR_SYS_ICCFGR_NCS_GET(iccfgr);
34 }
35
arch_invalidate_cache_all(void)36 void arch_invalidate_cache_all(void) {
37 uint32_t i;
38 uint32_t cache_size;
39 uint32_t block_size;
40
41 block_size = ic_block_size();
42 cache_size = block_size * ic_sets();
43 for (i = 0; i < cache_size; i += block_size)
44 mtspr(OR1K_SPR_ICACHE_ICBIR_ADDR, i);
45
46 block_size = dc_block_size();
47 cache_size = block_size * dc_sets();
48 for (i = 0; i < cache_size; i += block_size)
49 mtspr(OR1K_SPR_DCACHE_DCBIR_ADDR, i);
50 }
51
arch_disable_cache(uint flags)52 void arch_disable_cache(uint flags) {
53 uint32_t sr = mfspr(OR1K_SPR_SYS_SR_ADDR);
54
55 if (flags & ICACHE)
56 sr &= ~OR1K_SPR_SYS_SR_ICE_MASK;
57 if (flags & DCACHE)
58 sr &= ~OR1K_SPR_SYS_SR_DCE_MASK;
59
60 mtspr(OR1K_SPR_SYS_SR_ADDR, sr);
61 }
62
arch_enable_cache(uint flags)63 void arch_enable_cache(uint flags) {
64 uint32_t sr = mfspr(OR1K_SPR_SYS_SR_ADDR);
65
66 if (flags & ICACHE)
67 sr |= OR1K_SPR_SYS_SR_ICE_MASK;
68 if (flags & DCACHE)
69 sr |= OR1K_SPR_SYS_SR_DCE_MASK;
70
71 mtspr(OR1K_SPR_SYS_SR_ADDR, sr);
72 }
73
74 /* flush dcache */
arch_clean_cache_range(addr_t start,size_t len)75 void arch_clean_cache_range(addr_t start, size_t len) {
76 addr_t addr;
77 uint32_t block_size = dc_block_size();
78
79 for (addr = start; addr < start + len; addr += block_size)
80 mtspr(OR1K_SPR_DCACHE_DCBFR_ADDR, addr);
81 }
82
83 /* invalidate dcache */
arch_invalidate_cache_range(addr_t start,size_t len)84 void arch_invalidate_cache_range(addr_t start, size_t len) {
85 addr_t addr;
86 uint32_t block_size = dc_block_size();
87
88 for (addr = start; addr < start + len; addr += block_size)
89 mtspr(OR1K_SPR_DCACHE_DCBIR_ADDR, addr);
90 }
91
92 /* flush + invalidate dcache */
arch_clean_invalidate_cache_range(addr_t start,size_t len)93 void arch_clean_invalidate_cache_range(addr_t start, size_t len) {
94 /* invalidate is implied by flush on or1k */
95 arch_clean_cache_range(start, len);
96 }
97
98 /* flush dcache + invalidate icache */
arch_sync_cache_range(addr_t start,size_t len)99 void arch_sync_cache_range(addr_t start, size_t len) {
100 addr_t addr;
101 uint32_t block_size = ic_block_size();
102
103 arch_clean_cache_range(start, len);
104 for (addr = start; addr < start + len; addr += block_size)
105 mtspr(OR1K_SPR_ICACHE_ICBIR_ADDR, addr);
106 }
107