• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/mn10300/mm/
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#include <linux/sys.h>
12#include <linux/linkage.h>
13#include <asm/smp.h>
14#include <asm/page.h>
15#include <asm/cache.h>
16
17#define mn10300_dcache_inv_range_intr_interval \
18	+((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
19
20#if mn10300_dcache_inv_range_intr_interval > 0xff
21#error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
22#endif
23
24	.am33_2
25
26	.globl mn10300_icache_inv
27	.globl mn10300_dcache_inv
28	.globl mn10300_dcache_inv_range
29	.globl mn10300_dcache_inv_range2
30	.globl mn10300_dcache_inv_page
31
32###############################################################################
33#
34# void mn10300_icache_inv(void)
35# Invalidate the entire icache
36#
37###############################################################################
38	ALIGN
39mn10300_icache_inv:
40	mov	CHCTR,a0
41
42	movhu	(a0),d0
43	btst	CHCTR_ICEN,d0
44	beq	mn10300_icache_inv_end
45
46	mov	epsw,d1
47	and	~EPSW_IE,epsw
48	nop
49	nop
50
51	# disable the icache
52	and	~CHCTR_ICEN,d0
53	movhu	d0,(a0)
54
55	# and wait for it to calm down
56	setlb
57	movhu	(a0),d0
58	btst	CHCTR_ICBUSY,d0
59	lne
60
61	# invalidate
62	or	CHCTR_ICINV,d0
63	movhu	d0,(a0)
64
65	# wait for the cache to finish
66	mov	CHCTR,a0
67	setlb
68	movhu	(a0),d0
69	btst	CHCTR_ICBUSY,d0
70	lne
71
72	# and reenable it
73	and	~CHCTR_ICINV,d0
74	or	CHCTR_ICEN,d0
75	movhu	d0,(a0)
76	movhu	(a0),d0
77
78	mov	d1,epsw
79
80mn10300_icache_inv_end:
81	ret	[],0
82
83###############################################################################
84#
85# void mn10300_dcache_inv(void)
86# Invalidate the entire dcache
87#
88###############################################################################
89	ALIGN
90mn10300_dcache_inv:
91	mov	CHCTR,a0
92
93	movhu	(a0),d0
94	btst	CHCTR_DCEN,d0
95	beq	mn10300_dcache_inv_end
96
97	mov	epsw,d1
98	and	~EPSW_IE,epsw
99	nop
100	nop
101
102	# disable the dcache
103	and	~CHCTR_DCEN,d0
104	movhu	d0,(a0)
105
106	# and wait for it to calm down
107	setlb
108	movhu	(a0),d0
109	btst	CHCTR_DCBUSY,d0
110	lne
111
112	# invalidate
113	or	CHCTR_DCINV,d0
114	movhu	d0,(a0)
115
116	# wait for the cache to finish
117	mov	CHCTR,a0
118	setlb
119	movhu	(a0),d0
120	btst	CHCTR_DCBUSY,d0
121	lne
122
123	# and reenable it
124	and	~CHCTR_DCINV,d0
125	or	CHCTR_DCEN,d0
126	movhu	d0,(a0)
127	movhu	(a0),d0
128
129	mov	d1,epsw
130
131mn10300_dcache_inv_end:
132	ret	[],0
133
134###############################################################################
135#
136# void mn10300_dcache_inv_range(unsigned start, unsigned end)
137# void mn10300_dcache_inv_range2(unsigned start, unsigned size)
138# void mn10300_dcache_inv_page(unsigned start)
139# Invalidate a range of addresses on a page in the dcache
140#
141###############################################################################
142	ALIGN
143mn10300_dcache_inv_page:
144	mov	PAGE_SIZE,d1
145mn10300_dcache_inv_range2:
146	add	d0,d1
147mn10300_dcache_inv_range:
148	movm	[d2,d3,a2],(sp)
149	mov	CHCTR,a2
150
151	movhu	(a2),d2
152	btst	CHCTR_DCEN,d2
153	beq	mn10300_dcache_inv_range_end
154
155	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0	# round start
156								# addr down
157	mov	d0,a1
158
159	add	L1_CACHE_BYTES,d1			# round end addr up
160	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
161
162	clr	d2				# we're going to clear tag ram
163						# entries
164
165	# read the tags from the tag RAM, and if they indicate a valid dirty
166	# cache line then invalidate that line
167	mov	DCACHE_TAG(0,0),a0
168	mov	a1,d0
169	and	L1_CACHE_TAG_ENTRY,d0
170	add	d0,a0				# starting dcache tag RAM
171						# access address
172
173	sub	a1,d1
174	lsr	L1_CACHE_SHIFT,d1		# total number of entries to
175						# examine
176
177	and	~(L1_CACHE_DISPARITY-1),a1	# determine comparator base
178
179mn10300_dcache_inv_range_outer_loop:
180	# disable interrupts
181	mov	epsw,d3
182	and	~EPSW_IE,epsw
183	nop					# note that reading CHCTR and
184						# AND'ing D0 occupy two delay
185						# slots after disabling
186						# interrupts
187
188	# disable the dcache
189	movhu	(a2),d0
190	and	~CHCTR_DCEN,d0
191	movhu	d0,(a2)
192
193	# and wait for it to calm down
194	setlb
195	movhu	(a2),d0
196	btst	CHCTR_DCBUSY,d0
197	lne
198
199mn10300_dcache_inv_range_loop:
200
201	# process the way 0 slot
202	mov	(L1_CACHE_WAYDISP*0,a0),d0	# read the tag in the way 0 slot
203	btst	L1_CACHE_TAG_VALID,d0
204	beq	mn10300_dcache_inv_range_skip_0	# jump if this cacheline is not
205						# valid
206
207	xor	a1,d0
208	lsr	12,d0
209	bne	mn10300_dcache_inv_range_skip_0	# jump if not this cacheline
210
211	mov	d2,(a0)				# kill the tag
212
213mn10300_dcache_inv_range_skip_0:
214
215	# process the way 1 slot
216	mov	(L1_CACHE_WAYDISP*1,a0),d0	# read the tag in the way 1 slot
217	btst	L1_CACHE_TAG_VALID,d0
218	beq	mn10300_dcache_inv_range_skip_1	# jump if this cacheline is not
219						# valid
220
221	xor	a1,d0
222	lsr	12,d0
223	bne	mn10300_dcache_inv_range_skip_1	# jump if not this cacheline
224
225	mov	d2,(a0)				# kill the tag
226
227mn10300_dcache_inv_range_skip_1:
228
229	# process the way 2 slot
230	mov	(L1_CACHE_WAYDISP*2,a0),d0	# read the tag in the way 2 slot
231	btst	L1_CACHE_TAG_VALID,d0
232	beq	mn10300_dcache_inv_range_skip_2	# jump if this cacheline is not
233						# valid
234
235	xor	a1,d0
236	lsr	12,d0
237	bne	mn10300_dcache_inv_range_skip_2	# jump if not this cacheline
238
239	mov	d2,(a0)				# kill the tag
240
241mn10300_dcache_inv_range_skip_2:
242
243	# process the way 3 slot
244	mov	(L1_CACHE_WAYDISP*3,a0),d0	# read the tag in the way 3 slot
245	btst	L1_CACHE_TAG_VALID,d0
246	beq	mn10300_dcache_inv_range_skip_3	# jump if this cacheline is not
247						# valid
248
249	xor	a1,d0
250	lsr	12,d0
251	bne	mn10300_dcache_inv_range_skip_3	# jump if not this cacheline
252
253	mov	d2,(a0)				# kill the tag
254
255mn10300_dcache_inv_range_skip_3:
256
257	# approx every N steps we re-enable the cache and see if there are any
258	# interrupts to be processed
259	# we also break out if we've reached the end of the loop
260	# (the bottom nibble of the count is zero in both cases)
261	add	L1_CACHE_BYTES,a0
262	add	L1_CACHE_BYTES,a1
263	add	-1,d1
264	btst	mn10300_dcache_inv_range_intr_interval,d1
265	bne	mn10300_dcache_inv_range_loop
266
267	# wait for the cache to finish what it's doing
268	setlb
269	movhu	(a2),d0
270	btst	CHCTR_DCBUSY,d0
271	lne
272
273	# and reenable it
274	or	CHCTR_DCEN,d0
275	movhu	d0,(a2)
276	movhu	(a2),d0
277
278	# re-enable interrupts
279	# - we don't bother with delay NOPs as we'll have enough instructions
280	#   before we disable interrupts again to give the interrupts a chance
281	#   to happen
282	mov	d3,epsw
283
284	# go around again if the counter hasn't yet reached zero
285	add	0,d1
286	bne	mn10300_dcache_inv_range_outer_loop
287
288mn10300_dcache_inv_range_end:
289	ret	[d2,d3,a2],12
290