1/*
2 * Copyright 2022 Haiku, Inc. All rights reserved.
3 * Released under the terms of the MIT License.
4 */
5
6#include <asm_defs.h>
7
8
9	// the following code is based on ARM ARM
10	// section B2.2.4, Cache maintenance functionality
11
12FUNCTION(clean_dcache_all):
13	dmb
14	stmfd	sp!, {r4-r11, lr}
15
16	// Query the number of cache levels to be cleaned
17	// this is encoded in LoC which is bits 26..24 of CLIDR
18	mrc		p15, 1, r0, c0, c0, 1
19	mov		r3, r0, lsr #23
20	ands	r3, r3, #7 << 1
21	beq		cleaning_done
22
23	// Start cleaning at cache level 0
24	mov		r10, #0
25clean_levels_loop:
26	// Get type of current cache level
27	add		r2, r10, r10, lsr #1
28	mov		r1, r0, lsr r2
29	and		r1, r1, #7
30
31	// Skip this level if cache type is less than 2 i.e. no cache or only i-cache
32	cmp		r1, #2
33	blt		clean_next_level
34
35	// Select current level in Cache Size selection register
36	mcr		p15, 2, r10, c0, c0, 0
37	isb
38
39	// Read Cache Size ID for the current level
40	mrc		p15, 1, r1, c0, c0, 0
41
42	// Decode LineSize from bits[2:0]
43	and		r2, r1, #7
44	add		r2, r2, #4
45
46	// Decode Associativity from bits[12:3]
47	movw	r4, #0x3ff
48	ands	r4, r4, r1, lsr #3
49	clz		r5, r4
50
51	// Decode NumSets from bits[27:13]
52	movw	r7, #0x7fff
53	ands	r7, r7, r1, lsr #13
54
55clean_way_loop:
56	mov		r9, r7
57clean_index_loop:
58	orr		r11, r10, r4, lsl r5
59	orr		r11, r11, r9, lsl r2
60
61	// Clean and Invalidate by set/way
62	mcr		p15, 0, r11, c7, c14, 2
63
64	subs	r9, r9, #1
65	bge		clean_index_loop
66
67	subs	r4, r4, #1
68	bge		clean_way_loop
69clean_next_level:
70	add		r10, r10, #2
71	cmp		r3, r10
72	bgt		clean_levels_loop
73cleaning_done:
74	dsb
75	isb
76	ldmfd	sp!, {r4-r11, lr}
77	bx		lr
78FUNCTION_END(clean_dcache_all)
79
80
81FUNCTION(invalidate_icache_all):
82	mov		r0, #0
83	mcr		p15, 0, r0, c7, c5, 0
84	dsb
85	isb
86	bx		lr
87FUNCTION_END(invalidate_icache_all)
88