Linux Audio

Check our new training course

Loading...
  1/* MN10300 CPU core caching routines, using direct tag flushing
  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#include <asm/irqflags.h>
 18
 19	.am33_2
 20
 21#ifndef CONFIG_SMP
 22	.globl mn10300_dcache_flush
 23	.globl mn10300_dcache_flush_page
 24	.globl mn10300_dcache_flush_range
 25	.globl mn10300_dcache_flush_range2
 26	.globl mn10300_dcache_flush_inv
 27	.globl mn10300_dcache_flush_inv_page
 28	.globl mn10300_dcache_flush_inv_range
 29	.globl mn10300_dcache_flush_inv_range2
 30
 31mn10300_dcache_flush		= mn10300_local_dcache_flush
 32mn10300_dcache_flush_page	= mn10300_local_dcache_flush_page
 33mn10300_dcache_flush_range	= mn10300_local_dcache_flush_range
 34mn10300_dcache_flush_range2	= mn10300_local_dcache_flush_range2
 35mn10300_dcache_flush_inv	= mn10300_local_dcache_flush_inv
 36mn10300_dcache_flush_inv_page	= mn10300_local_dcache_flush_inv_page
 37mn10300_dcache_flush_inv_range	= mn10300_local_dcache_flush_inv_range
 38mn10300_dcache_flush_inv_range2	= mn10300_local_dcache_flush_inv_range2
 39
 40#endif /* !CONFIG_SMP */
 41
 42###############################################################################
 43#
 44# void mn10300_local_dcache_flush(void)
 45# Flush the entire data cache back to RAM
 46#
 47###############################################################################
 48	ALIGN
 49	.globl	mn10300_local_dcache_flush
 50        .type	mn10300_local_dcache_flush,@function
 51mn10300_local_dcache_flush:
 52	movhu	(CHCTR),d0
 53	btst	CHCTR_DCEN,d0
 54	beq	mn10300_local_dcache_flush_end
 55
 56	# read the addresses tagged in the cache's tag RAM and attempt to flush
 57	# those addresses specifically
 58	# - we rely on the hardware to filter out invalid tag entry addresses
 59	mov	DCACHE_TAG(0,0),a0		# dcache tag RAM access address
 60	mov	DCACHE_PURGE(0,0),a1		# dcache purge request address
 61	mov	L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1  # total number of entries
 62
 63mn10300_local_dcache_flush_loop:
 64	mov	(a0),d0
 65	and	L1_CACHE_TAG_MASK,d0
 66	or	L1_CACHE_TAG_VALID,d0		# retain valid entries in the
 67						# cache
 68	mov	d0,(a1)				# conditional purge
 69
 70	add	L1_CACHE_BYTES,a0
 71	add	L1_CACHE_BYTES,a1
 72	add	-1,d1
 73	bne	mn10300_local_dcache_flush_loop
 74
 75mn10300_local_dcache_flush_end:
 76	ret	[],0
 77	.size	mn10300_local_dcache_flush,.-mn10300_local_dcache_flush
 78
 79###############################################################################
 80#
 81# void mn10300_local_dcache_flush_page(unsigned long start)
 82# void mn10300_local_dcache_flush_range(unsigned long start, unsigned long end)
 83# void mn10300_local_dcache_flush_range2(unsigned long start, unsigned long size)
 84# Flush a range of addresses on a page in the dcache
 85#
 86###############################################################################
 87	ALIGN
 88	.globl	mn10300_local_dcache_flush_page
 89	.globl	mn10300_local_dcache_flush_range
 90	.globl	mn10300_local_dcache_flush_range2
 91	.type	mn10300_local_dcache_flush_page,@function
 92	.type	mn10300_local_dcache_flush_range,@function
 93	.type	mn10300_local_dcache_flush_range2,@function
 94mn10300_local_dcache_flush_page:
 95	and	~(PAGE_SIZE-1),d0
 96	mov	PAGE_SIZE,d1
 97mn10300_local_dcache_flush_range2:
 98	add	d0,d1
 99mn10300_local_dcache_flush_range:
100	movm	[d2],(sp)
101
102	movhu	(CHCTR),d2
103	btst	CHCTR_DCEN,d2
104	beq	mn10300_local_dcache_flush_range_end
105
106	sub	d0,d1,a0
107	cmp	MN10300_DCACHE_FLUSH_BORDER,a0
108	ble	1f
109
110	movm	(sp),[d2]
111	bra	mn10300_local_dcache_flush
1121:
113
114	# round start addr down
115	and	L1_CACHE_TAG_MASK,d0
116	mov	d0,a1
117
118	add	L1_CACHE_BYTES,d1			# round end addr up
119	and	L1_CACHE_TAG_MASK,d1
120
121	# write a request to flush all instances of an address from the cache
122	mov	DCACHE_PURGE(0,0),a0
123	mov	a1,d0
124	and	L1_CACHE_TAG_ENTRY,d0
125	add	d0,a0				# starting dcache purge control
126						# reg address
127
128	sub	a1,d1
129	lsr	L1_CACHE_SHIFT,d1		# total number of entries to
130						# examine
131
132	or	L1_CACHE_TAG_VALID,a1		# retain valid entries in the
133						# cache
134
135mn10300_local_dcache_flush_range_loop:
136	mov	a1,(L1_CACHE_WAYDISP*0,a0)	# conditionally purge this line
137						# all ways
138
139	add	L1_CACHE_BYTES,a0
140	add	L1_CACHE_BYTES,a1
141	and	~L1_CACHE_WAYDISP,a0		# make sure way stay on way 0
142	add	-1,d1
143	bne	mn10300_local_dcache_flush_range_loop
144
145mn10300_local_dcache_flush_range_end:
146	ret	[d2],4
147
148	.size	mn10300_local_dcache_flush_page,.-mn10300_local_dcache_flush_page
149	.size	mn10300_local_dcache_flush_range,.-mn10300_local_dcache_flush_range
150	.size	mn10300_local_dcache_flush_range2,.-mn10300_local_dcache_flush_range2
151
152###############################################################################
153#
154# void mn10300_local_dcache_flush_inv(void)
155# Flush the entire data cache and invalidate all entries
156#
157###############################################################################
158	ALIGN
159	.globl	mn10300_local_dcache_flush_inv
160	.type	mn10300_local_dcache_flush_inv,@function
161mn10300_local_dcache_flush_inv:
162	movhu	(CHCTR),d0
163	btst	CHCTR_DCEN,d0
164	beq	mn10300_local_dcache_flush_inv_end
165
166	mov	L1_CACHE_NENTRIES,d1
167	clr	a1
168
169mn10300_local_dcache_flush_inv_loop:
170	mov	(DCACHE_PURGE_WAY0(0),a1),d0	# unconditional purge
171	mov	(DCACHE_PURGE_WAY1(0),a1),d0	# unconditional purge
172	mov	(DCACHE_PURGE_WAY2(0),a1),d0	# unconditional purge
173	mov	(DCACHE_PURGE_WAY3(0),a1),d0	# unconditional purge
174
175	add	L1_CACHE_BYTES,a1
176	add	-1,d1
177	bne	mn10300_local_dcache_flush_inv_loop
178
179mn10300_local_dcache_flush_inv_end:
180	ret	[],0
181	.size	mn10300_local_dcache_flush_inv,.-mn10300_local_dcache_flush_inv
182
183###############################################################################
184#
185# void mn10300_local_dcache_flush_inv_page(unsigned long start)
186# void mn10300_local_dcache_flush_inv_range(unsigned long start, unsigned long end)
187# void mn10300_local_dcache_flush_inv_range2(unsigned long start, unsigned long size)
188# Flush and invalidate a range of addresses on a page in the dcache
189#
190###############################################################################
191	ALIGN
192	.globl	mn10300_local_dcache_flush_inv_page
193	.globl	mn10300_local_dcache_flush_inv_range
194	.globl	mn10300_local_dcache_flush_inv_range2
195	.type	mn10300_local_dcache_flush_inv_page,@function
196	.type	mn10300_local_dcache_flush_inv_range,@function
197	.type	mn10300_local_dcache_flush_inv_range2,@function
198mn10300_local_dcache_flush_inv_page:
199	and	~(PAGE_SIZE-1),d0
200	mov	PAGE_SIZE,d1
201mn10300_local_dcache_flush_inv_range2:
202	add	d0,d1
203mn10300_local_dcache_flush_inv_range:
204	movm	[d2],(sp)
205
206	movhu	(CHCTR),d2
207	btst	CHCTR_DCEN,d2
208	beq	mn10300_local_dcache_flush_inv_range_end
209
210	sub	d0,d1,a0
211	cmp	MN10300_DCACHE_FLUSH_INV_BORDER,a0
212	ble	1f
213
214	movm	(sp),[d2]
215	bra	mn10300_local_dcache_flush_inv
2161:
217
218	and	L1_CACHE_TAG_MASK,d0		# round start addr down
219	mov	d0,a1
220
221	add	L1_CACHE_BYTES,d1		# round end addr up
222	and	L1_CACHE_TAG_MASK,d1
223
224	# write a request to flush and invalidate all instances of an address
225	# from the cache
226	mov	DCACHE_PURGE(0,0),a0
227	mov	a1,d0
228	and	L1_CACHE_TAG_ENTRY,d0
229	add	d0,a0				# starting dcache purge control
230						# reg address
231
232	sub	a1,d1
233	lsr	L1_CACHE_SHIFT,d1		# total number of entries to
234						# examine
235
236mn10300_local_dcache_flush_inv_range_loop:
237	mov	a1,(L1_CACHE_WAYDISP*0,a0)	# conditionally purge this line
238						# in all ways
239
240	add	L1_CACHE_BYTES,a0
241	add	L1_CACHE_BYTES,a1
242	and	~L1_CACHE_WAYDISP,a0		# make sure way stay on way 0
243	add	-1,d1
244	bne	mn10300_local_dcache_flush_inv_range_loop
245
246mn10300_local_dcache_flush_inv_range_end:
247	ret	[d2],4
248	.size	mn10300_local_dcache_flush_inv_page,.-mn10300_local_dcache_flush_inv_page
249	.size	mn10300_local_dcache_flush_inv_range,.-mn10300_local_dcache_flush_inv_range
250	.size	mn10300_local_dcache_flush_inv_range2,.-mn10300_local_dcache_flush_inv_range2