cache-flush-by-tag.S revision 518d4bb7464dd3c04aeb23874dc360b54058c01e
1/* MN10300 CPU core caching routines
2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#include <linux/sys.h>
13#include <linux/linkage.h>
14#include <asm/smp.h>
15#include <asm/page.h>
16#include <asm/cache.h>
17
18	.am33_2
19	.globl mn10300_dcache_flush
20	.globl mn10300_dcache_flush_page
21	.globl mn10300_dcache_flush_range
22	.globl mn10300_dcache_flush_range2
23	.globl mn10300_dcache_flush_inv
24	.globl mn10300_dcache_flush_inv_page
25	.globl mn10300_dcache_flush_inv_range
26	.globl mn10300_dcache_flush_inv_range2
27
28###############################################################################
29#
30# void mn10300_dcache_flush(void)
31# Flush the entire data cache back to RAM
32#
33###############################################################################
34	ALIGN
35mn10300_dcache_flush:
36	movhu	(CHCTR),d0
37	btst	CHCTR_DCEN,d0
38	beq	mn10300_dcache_flush_end
39
40	# read the addresses tagged in the cache's tag RAM and attempt to flush
41	# those addresses specifically
42	# - we rely on the hardware to filter out invalid tag entry addresses
43	mov	DCACHE_TAG(0,0),a0		# dcache tag RAM access address
44	mov	DCACHE_PURGE(0,0),a1		# dcache purge request address
45	mov	L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1  # total number of entries
46
47mn10300_dcache_flush_loop:
48	mov	(a0),d0
49	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
50	or	L1_CACHE_TAG_VALID,d0		# retain valid entries in the
51						# cache
52	mov	d0,(a1)				# conditional purge
53
54mn10300_dcache_flush_skip:
55	add	L1_CACHE_BYTES,a0
56	add	L1_CACHE_BYTES,a1
57	add	-1,d1
58	bne	mn10300_dcache_flush_loop
59
60mn10300_dcache_flush_end:
61	ret	[],0
62
63###############################################################################
64#
65# void mn10300_dcache_flush_page(unsigned start)
66# void mn10300_dcache_flush_range(unsigned start, unsigned end)
67# void mn10300_dcache_flush_range2(unsigned start, unsigned size)
68# Flush a range of addresses on a page in the dcache
69#
70###############################################################################
71	ALIGN
72mn10300_dcache_flush_page:
73	mov	PAGE_SIZE,d1
74mn10300_dcache_flush_range2:
75	add	d0,d1
76mn10300_dcache_flush_range:
77	movm	[d2,d3],(sp)
78
79	movhu	(CHCTR),d2
80	btst	CHCTR_DCEN,d2
81	beq	mn10300_dcache_flush_range_end
82
83	# round start addr down
84	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
85	mov	d0,a1
86
87	add	L1_CACHE_BYTES,d1			# round end addr up
88	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
89
90	# write a request to flush all instances of an address from the cache
91	mov	DCACHE_PURGE(0,0),a0
92	mov	a1,d0
93	and	L1_CACHE_TAG_ENTRY,d0
94	add	d0,a0				# starting dcache purge control
95						# reg address
96
97	sub	a1,d1
98	lsr	L1_CACHE_SHIFT,d1		# total number of entries to
99						# examine
100
101	or	L1_CACHE_TAG_VALID,a1		# retain valid entries in the
102						# cache
103
104mn10300_dcache_flush_range_loop:
105	mov	a1,(L1_CACHE_WAYDISP*0,a0)	# conditionally purge this line
106						# all ways
107
108	add	L1_CACHE_BYTES,a0
109	add	L1_CACHE_BYTES,a1
110	and	~L1_CACHE_WAYDISP,a0		# make sure way stay on way 0
111	add	-1,d1
112	bne	mn10300_dcache_flush_range_loop
113
114mn10300_dcache_flush_range_end:
115	ret	[d2,d3],8
116
117###############################################################################
118#
119# void mn10300_dcache_flush_inv(void)
120# Flush the entire data cache and invalidate all entries
121#
122###############################################################################
123	ALIGN
124mn10300_dcache_flush_inv:
125	movhu	(CHCTR),d0
126	btst	CHCTR_DCEN,d0
127	beq	mn10300_dcache_flush_inv_end
128
129	# hit each line in the dcache with an unconditional purge
130	mov	DCACHE_PURGE(0,0),a1		# dcache purge request address
131	mov	L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1  # total number of entries
132
133mn10300_dcache_flush_inv_loop:
134	mov	(a1),d0				# unconditional purge
135
136	add	L1_CACHE_BYTES,a1
137	add	-1,d1
138	bne	mn10300_dcache_flush_inv_loop
139
140mn10300_dcache_flush_inv_end:
141	ret	[],0
142
143###############################################################################
144#
145# void mn10300_dcache_flush_inv_page(unsigned start)
146# void mn10300_dcache_flush_inv_range(unsigned start, unsigned end)
147# void mn10300_dcache_flush_inv_range2(unsigned start, unsigned size)
148# Flush and invalidate a range of addresses on a page in the dcache
149#
150###############################################################################
151	ALIGN
152mn10300_dcache_flush_inv_page:
153	mov	PAGE_SIZE,d1
154mn10300_dcache_flush_inv_range2:
155	add	d0,d1
156mn10300_dcache_flush_inv_range:
157	movm	[d2,d3],(sp)
158	movhu	(CHCTR),d2
159	btst	CHCTR_DCEN,d2
160	beq	mn10300_dcache_flush_inv_range_end
161
162	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0	# round start
163								# addr down
164	mov	d0,a1
165
166	add	L1_CACHE_BYTES,d1			# round end addr up
167	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
168
169	# write a request to flush and invalidate all instances of an address
170	# from the cache
171	mov	DCACHE_PURGE(0,0),a0
172	mov	a1,d0
173	and	L1_CACHE_TAG_ENTRY,d0
174	add	d0,a0				# starting dcache purge control
175						# reg address
176
177	sub	a1,d1
178	lsr	L1_CACHE_SHIFT,d1		# total number of entries to
179						# examine
180
181mn10300_dcache_flush_inv_range_loop:
182	mov	a1,(L1_CACHE_WAYDISP*0,a0)	# conditionally purge this line
183						# in all ways
184
185	add	L1_CACHE_BYTES,a0
186	add	L1_CACHE_BYTES,a1
187	and	~L1_CACHE_WAYDISP,a0		# make sure way stay on way 0
188	add	-1,d1
189	bne	mn10300_dcache_flush_inv_range_loop
190
191mn10300_dcache_flush_inv_range_end:
192	ret	[d2,d3],8
193