1 /*
2  * Copyright (c) 2015 Travis Geiselbrecht
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 #include <lk/debug.h>
9 #include <arch.h>
10 #include <arch/ops.h>
11 #include <arch/arm.h>
12 #include <kernel/thread.h>
13 #include <kernel/debug.h>
14 #include <platform.h>
15 #include <arch/arm/cm.h>
16 
17 #if ARM_WITH_CACHE
18 
19 /* cache flushing routines for cortex-m cores that support it */
20 
arch_disable_cache(uint flags)21 void arch_disable_cache(uint flags) {
22     if (flags & DCACHE)
23         SCB_DisableDCache();
24 
25     if (flags & ICACHE)
26         SCB_DisableICache();
27 }
28 
arch_enable_cache(uint flags)29 void arch_enable_cache(uint flags) {
30     if (flags & DCACHE)
31         SCB_EnableDCache();
32 
33     if (flags & ICACHE)
34         SCB_EnableICache();
35 }
36 
37 /* clean (writeback) data in the data cache on the range */
arch_clean_cache_range(addr_t start,size_t len)38 void arch_clean_cache_range(addr_t start, size_t len) {
39     addr_t end = start + len;
40 
41     /* align the start address on CACHE_LINE boundary */
42     start &= ~(CACHE_LINE - 1);
43 
44     SCB_CleanDCache_by_Addr((uint32_t *)start, end - start);
45 }
46 
47 /* clean (writeback) and then evict data from the data cache on the range */
arch_clean_invalidate_cache_range(addr_t start,size_t len)48 void arch_clean_invalidate_cache_range(addr_t start, size_t len) {
49     addr_t end = start + len;
50 
51     /* align the start address on CACHE_LINE boundary */
52     start &= ~(CACHE_LINE - 1);
53 
54     SCB_CleanInvalidateDCache_by_Addr((uint32_t *)start, end - start);
55 }
56 
57 /* evict data from the data cache on the range */
arch_invalidate_cache_range(addr_t start,size_t len)58 void arch_invalidate_cache_range(addr_t start, size_t len) {
59     addr_t end = start + len;
60 
61     /* align the start address on CACHE_LINE boundary */
62     start &= ~(CACHE_LINE - 1);
63 
64     SCB_InvalidateDCache_by_Addr((uint32_t *)start, end - start);
65 }
66 
67 /*
68  * clean (writeback) data on the range and then throw away the instruction cache,
69  * ensuring that new instructions fetched from the range are not stale.
70  */
arch_sync_cache_range(addr_t start,size_t len)71 void arch_sync_cache_range(addr_t start, size_t len) {
72     /* flush the dcache and invalidate the icache, ensuring fresh instructions */
73     arch_clean_cache_range(start, len);
74     SCB_InvalidateICache();
75 }
76 
77 #else
78 
79 /* doesn't support cache flush, just nop */
80 
arch_disable_cache(uint flags)81 void arch_disable_cache(uint flags) {
82 }
83 
arch_enable_cache(uint flags)84 void arch_enable_cache(uint flags) {
85 }
86 
87 /* clean (writeback) data in the data cache on the range */
arch_clean_cache_range(addr_t start,size_t len)88 void arch_clean_cache_range(addr_t start, size_t len) {
89 }
90 
91 /* clean (writeback) and then evict data from the data cache on the range */
arch_clean_invalidate_cache_range(addr_t start,size_t len)92 void arch_clean_invalidate_cache_range(addr_t start, size_t len) {
93 }
94 
95 /* evict data from the data cache on the range */
arch_invalidate_cache_range(addr_t start,size_t len)96 void arch_invalidate_cache_range(addr_t start, size_t len) {
97 }
98 
99 /*
100  * clean (writeback) data on the range and then throw away the instruction cache,
101  * ensuring that new instructions fetched from the range are not stale.
102  */
arch_sync_cache_range(addr_t start,size_t len)103 void arch_sync_cache_range(addr_t start, size_t len) {
104 }
105 
106 #endif // !ARM_WITH_CACHE
107 
108