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