1/*
2 * linux/arch/unicore32/mm/cache-ucv2.S
3 *
4 * Code specific to PKUnity SoC and UniCore ISA
5 *
6 * Copyright (C) 2001-2010 GUAN Xue-tao
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 *  This is the "shell" of the UniCore-v2 processor support.
13 */
14#include <linux/linkage.h>
15#include <linux/init.h>
16#include <asm/assembler.h>
17#include <asm/page.h>
18
19#include "proc-macros.S"
20
21/*
22 *	__cpuc_flush_icache_all()
23 *	__cpuc_flush_kern_all()
24 *	__cpuc_flush_user_all()
25 *
26 *	Flush the entire cache.
27 */
28ENTRY(__cpuc_flush_icache_all)
29	/*FALLTHROUGH*/
30ENTRY(__cpuc_flush_kern_all)
31	/*FALLTHROUGH*/
32ENTRY(__cpuc_flush_user_all)
33	mov	r0, #0
34	movc	p0.c5, r0, #14			@ Dcache flush all
35	nop8
36
37	mov	r0, #0
38	movc	p0.c5, r0, #20			@ Icache invalidate all
39	nop8
40
41	mov	pc, lr
42
43/*
44 *	__cpuc_flush_user_range(start, end, flags)
45 *
46 *	Flush a range of TLB entries in the specified address space.
47 *
48 *	- start - start address (may not be aligned)
49 *	- end   - end address (exclusive, may not be aligned)
50 *	- flags	- vm_area_struct flags describing address space
51 */
52ENTRY(__cpuc_flush_user_range)
53	cxor.a	r2, #0
54	beq	__cpuc_dma_flush_range
55
56#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
57	andn	r0, r0, #CACHE_LINESIZE - 1	@ Safety check
58	sub	r1, r1, r0
59	csub.a	r1, #MAX_AREA_SIZE
60	bsg	2f
61
62	andn	r1, r1, #CACHE_LINESIZE - 1
63	add	r1, r1, #CACHE_LINESIZE
64
65101:	dcacheline_flush	r0, r11, r12
66
67	add	r0, r0, #CACHE_LINESIZE
68	sub.a	r1, r1, #CACHE_LINESIZE
69	bns	101b
70	b	3f
71#endif
722:	mov	ip, #0
73	movc	p0.c5, ip, #14			@ Dcache flush all
74	nop8
75
763:	mov	ip, #0
77	movc	p0.c5, ip, #20			@ Icache invalidate all
78	nop8
79
80	mov	pc, lr
81
82/*
83 *	__cpuc_coherent_kern_range(start,end)
84 *	__cpuc_coherent_user_range(start,end)
85 *
86 *	Ensure that the I and D caches are coherent within specified
87 *	region.  This is typically used when code has been written to
88 *	a memory region, and will be executed.
89 *
90 *	- start   - virtual start address of region
91 *	- end     - virtual end address of region
92 */
93ENTRY(__cpuc_coherent_kern_range)
94	/* FALLTHROUGH */
95ENTRY(__cpuc_coherent_user_range)
96#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
97	andn	r0, r0, #CACHE_LINESIZE - 1	@ Safety check
98	sub	r1, r1, r0
99	csub.a	r1, #MAX_AREA_SIZE
100	bsg	2f
101
102	andn	r1, r1, #CACHE_LINESIZE - 1
103	add	r1, r1, #CACHE_LINESIZE
104
105	@ r0 va2pa r10
106	mov	r9, #PAGE_SZ
107	sub	r9, r9, #1			@ PAGE_MASK
108101:	va2pa	r0, r10, r11, r12, r13, 2f	@ r10 is PA
109	b	103f
110102:	cand.a	r0, r9
111	beq	101b
112
113103:	movc	p0.c5, r10, #11			@ Dcache clean line of R10
114	nop8
115
116	add	r0, r0, #CACHE_LINESIZE
117	add	r10, r10, #CACHE_LINESIZE
118	sub.a	r1, r1, #CACHE_LINESIZE
119	bns	102b
120	b	3f
121#endif
1222:	mov	ip, #0
123	movc	p0.c5, ip, #10			@ Dcache clean all
124	nop8
125
1263:	mov	ip, #0
127	movc	p0.c5, ip, #20			@ Icache invalidate all
128	nop8
129
130	mov	pc, lr
131
132/*
133 *	__cpuc_flush_kern_dcache_area(void *addr, size_t size)
134 *
135 *	- addr	- kernel address
136 *	- size	- region size
137 */
138ENTRY(__cpuc_flush_kern_dcache_area)
139	mov	ip, #0
140	movc	p0.c5, ip, #14			@ Dcache flush all
141	nop8
142	mov	pc, lr
143
144/*
145 *	__cpuc_dma_clean_range(start,end)
146 *	- start   - virtual start address of region
147 *	- end     - virtual end address of region
148 */
149ENTRY(__cpuc_dma_clean_range)
150#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
151	andn	r0, r0, #CACHE_LINESIZE - 1
152	sub	r1, r1, r0
153	andn	r1, r1, #CACHE_LINESIZE - 1
154	add	r1, r1, #CACHE_LINESIZE
155
156	csub.a	r1, #MAX_AREA_SIZE
157	bsg	2f
158
159	@ r0 va2pa r10
160	mov	r9, #PAGE_SZ
161	sub	r9, r9, #1			@ PAGE_MASK
162101:	va2pa	r0, r10, r11, r12, r13, 2f	@ r10 is PA
163	b	1f
164102:	cand.a	r0, r9
165	beq	101b
166
1671:	movc	p0.c5, r10, #11			@ Dcache clean line of R10
168	nop8
169	add	r0, r0, #CACHE_LINESIZE
170	add	r10, r10, #CACHE_LINESIZE
171	sub.a	r1, r1, #CACHE_LINESIZE
172	bns	102b
173	mov	pc, lr
174#endif
1752:	mov	ip, #0
176	movc	p0.c5, ip, #10			@ Dcache clean all
177	nop8
178
179	mov	pc, lr
180
181/*
182 *	__cpuc_dma_inv_range(start,end)
183 *	__cpuc_dma_flush_range(start,end)
184 *	- start   - virtual start address of region
185 *	- end     - virtual end address of region
186 */
187__cpuc_dma_inv_range:
188	/* FALLTHROUGH */
189ENTRY(__cpuc_dma_flush_range)
190#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
191	andn	r0, r0, #CACHE_LINESIZE - 1
192	sub	r1, r1, r0
193	andn	r1, r1, #CACHE_LINESIZE - 1
194	add	r1, r1, #CACHE_LINESIZE
195
196	csub.a	r1, #MAX_AREA_SIZE
197	bsg	2f
198
199	@ r0 va2pa r10
200101:	dcacheline_flush	r0, r11, r12
201
202	add	r0, r0, #CACHE_LINESIZE
203	sub.a	r1, r1, #CACHE_LINESIZE
204	bns	101b
205	mov	pc, lr
206#endif
2072:	mov	ip, #0
208	movc	p0.c5, ip, #14			@ Dcache flush all
209	nop8
210
211	mov	pc, lr
212
213