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