309 lines
		
	
	
	
		
			7.6 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
		
		
			
		
	
	
			309 lines
		
	
	
	
		
			7.6 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| 
								 | 
							
								/* MN10300 CPU core caching routines, using indirect regs on cache controller
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
							 | 
						||
| 
								 | 
							
								 * Written by David Howells (dhowells@redhat.com)
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This program is free software; you can redistribute it and/or
							 | 
						||
| 
								 | 
							
								 * modify it under the terms of the GNU General Public Licence
							 | 
						||
| 
								 | 
							
								 * as published by the Free Software Foundation; either version
							 | 
						||
| 
								 | 
							
								 * 2 of the Licence, or (at your option) any later version.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <linux/sys.h>
							 | 
						||
| 
								 | 
							
								#include <linux/linkage.h>
							 | 
						||
| 
								 | 
							
								#include <asm/smp.h>
							 | 
						||
| 
								 | 
							
								#include <asm/page.h>
							 | 
						||
| 
								 | 
							
								#include <asm/cache.h>
							 | 
						||
| 
								 | 
							
								#include <asm/irqflags.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									.am33_2
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef CONFIG_SMP
							 | 
						||
| 
								 | 
							
									.globl mn10300_dcache_flush
							 | 
						||
| 
								 | 
							
									.globl mn10300_dcache_flush_page
							 | 
						||
| 
								 | 
							
									.globl mn10300_dcache_flush_range
							 | 
						||
| 
								 | 
							
									.globl mn10300_dcache_flush_range2
							 | 
						||
| 
								 | 
							
									.globl mn10300_dcache_flush_inv
							 | 
						||
| 
								 | 
							
									.globl mn10300_dcache_flush_inv_page
							 | 
						||
| 
								 | 
							
									.globl mn10300_dcache_flush_inv_range
							 | 
						||
| 
								 | 
							
									.globl mn10300_dcache_flush_inv_range2
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mn10300_dcache_flush		= mn10300_local_dcache_flush
							 | 
						||
| 
								 | 
							
								mn10300_dcache_flush_page	= mn10300_local_dcache_flush_page
							 | 
						||
| 
								 | 
							
								mn10300_dcache_flush_range	= mn10300_local_dcache_flush_range
							 | 
						||
| 
								 | 
							
								mn10300_dcache_flush_range2	= mn10300_local_dcache_flush_range2
							 | 
						||
| 
								 | 
							
								mn10300_dcache_flush_inv	= mn10300_local_dcache_flush_inv
							 | 
						||
| 
								 | 
							
								mn10300_dcache_flush_inv_page	= mn10300_local_dcache_flush_inv_page
							 | 
						||
| 
								 | 
							
								mn10300_dcache_flush_inv_range	= mn10300_local_dcache_flush_inv_range
							 | 
						||
| 
								 | 
							
								mn10300_dcache_flush_inv_range2	= mn10300_local_dcache_flush_inv_range2
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /* !CONFIG_SMP */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								###############################################################################
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								# void mn10300_local_dcache_flush(void)
							 | 
						||
| 
								 | 
							
								# Flush the entire data cache back to RAM
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								###############################################################################
							 | 
						||
| 
								 | 
							
									ALIGN
							 | 
						||
| 
								 | 
							
									.globl	mn10300_local_dcache_flush
							 | 
						||
| 
								 | 
							
								        .type	mn10300_local_dcache_flush,@function
							 | 
						||
| 
								 | 
							
								mn10300_local_dcache_flush:
							 | 
						||
| 
								 | 
							
									movhu	(CHCTR),d0
							 | 
						||
| 
								 | 
							
									btst	CHCTR_DCEN,d0
							 | 
						||
| 
								 | 
							
									beq	mn10300_local_dcache_flush_end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									mov	DCPGCR,a0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									LOCAL_CLI_SAVE(d1)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# wait for busy bit of area purge
							 | 
						||
| 
								 | 
							
									setlb
							 | 
						||
| 
								 | 
							
									mov	(a0),d0
							 | 
						||
| 
								 | 
							
									btst	DCPGCR_DCPGBSY,d0
							 | 
						||
| 
								 | 
							
									lne
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# set mask
							 | 
						||
| 
								 | 
							
									clr	d0
							 | 
						||
| 
								 | 
							
									mov	d0,(DCPGMR)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# area purge
							 | 
						||
| 
								 | 
							
									#
							 | 
						||
| 
								 | 
							
									# DCPGCR = DCPGCR_DCP
							 | 
						||
| 
								 | 
							
									#
							 | 
						||
| 
								 | 
							
									mov	DCPGCR_DCP,d0
							 | 
						||
| 
								 | 
							
									mov	d0,(a0)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# wait for busy bit of area purge
							 | 
						||
| 
								 | 
							
									setlb
							 | 
						||
| 
								 | 
							
									mov	(a0),d0
							 | 
						||
| 
								 | 
							
									btst	DCPGCR_DCPGBSY,d0
							 | 
						||
| 
								 | 
							
									lne
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									LOCAL_IRQ_RESTORE(d1)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mn10300_local_dcache_flush_end:
							 | 
						||
| 
								 | 
							
									ret	[],0
							 | 
						||
| 
								 | 
							
									.size	mn10300_local_dcache_flush,.-mn10300_local_dcache_flush
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								###############################################################################
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								# void mn10300_local_dcache_flush_page(unsigned long start)
							 | 
						||
| 
								 | 
							
								# void mn10300_local_dcache_flush_range(unsigned long start, unsigned long end)
							 | 
						||
| 
								 | 
							
								# void mn10300_local_dcache_flush_range2(unsigned long start, unsigned long size)
							 | 
						||
| 
								 | 
							
								# Flush a range of addresses on a page in the dcache
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								###############################################################################
							 | 
						||
| 
								 | 
							
									ALIGN
							 | 
						||
| 
								 | 
							
									.globl	mn10300_local_dcache_flush_page
							 | 
						||
| 
								 | 
							
									.globl	mn10300_local_dcache_flush_range
							 | 
						||
| 
								 | 
							
									.globl	mn10300_local_dcache_flush_range2
							 | 
						||
| 
								 | 
							
									.type	mn10300_local_dcache_flush_page,@function
							 | 
						||
| 
								 | 
							
									.type	mn10300_local_dcache_flush_range,@function
							 | 
						||
| 
								 | 
							
									.type	mn10300_local_dcache_flush_range2,@function
							 | 
						||
| 
								 | 
							
								mn10300_local_dcache_flush_page:
							 | 
						||
| 
								 | 
							
									and	~(PAGE_SIZE-1),d0
							 | 
						||
| 
								 | 
							
									mov	PAGE_SIZE,d1
							 | 
						||
| 
								 | 
							
								mn10300_local_dcache_flush_range2:
							 | 
						||
| 
								 | 
							
									add	d0,d1
							 | 
						||
| 
								 | 
							
								mn10300_local_dcache_flush_range:
							 | 
						||
| 
								 | 
							
									movm	[d2,d3,a2],(sp)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									movhu	(CHCTR),d2
							 | 
						||
| 
								 | 
							
									btst	CHCTR_DCEN,d2
							 | 
						||
| 
								 | 
							
									beq	mn10300_local_dcache_flush_range_end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# calculate alignsize
							 | 
						||
| 
								 | 
							
									#
							 | 
						||
| 
								 | 
							
									# alignsize = L1_CACHE_BYTES;
							 | 
						||
| 
								 | 
							
									# for (i = (end - start - 1) / L1_CACHE_BYTES ;  i > 0; i >>= 1)
							 | 
						||
| 
								 | 
							
									#     alignsize <<= 1;
							 | 
						||
| 
								 | 
							
									# d2 = alignsize;
							 | 
						||
| 
								 | 
							
									#
							 | 
						||
| 
								 | 
							
									mov	L1_CACHE_BYTES,d2
							 | 
						||
| 
								 | 
							
									sub	d0,d1,d3
							 | 
						||
| 
								 | 
							
									add	-1,d3
							 | 
						||
| 
								 | 
							
									lsr	L1_CACHE_SHIFT,d3
							 | 
						||
| 
								 | 
							
									beq	2f
							 | 
						||
| 
								 | 
							
								1:
							 | 
						||
| 
								 | 
							
									add     d2,d2
							 | 
						||
| 
								 | 
							
									lsr     1,d3
							 | 
						||
| 
								 | 
							
									bne     1b
							 | 
						||
| 
								 | 
							
								2:
							 | 
						||
| 
								 | 
							
									mov	d1,a1		# a1 = end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									LOCAL_CLI_SAVE(d3)
							 | 
						||
| 
								 | 
							
									mov	DCPGCR,a0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# wait for busy bit of area purge
							 | 
						||
| 
								 | 
							
									setlb
							 | 
						||
| 
								 | 
							
									mov	(a0),d1
							 | 
						||
| 
								 | 
							
									btst	DCPGCR_DCPGBSY,d1
							 | 
						||
| 
								 | 
							
									lne
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# determine the mask
							 | 
						||
| 
								 | 
							
									mov	d2,d1
							 | 
						||
| 
								 | 
							
									add	-1,d1
							 | 
						||
| 
								 | 
							
									not	d1		# d1 = mask = ~(alignsize-1)
							 | 
						||
| 
								 | 
							
									mov	d1,(DCPGMR)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									and	d1,d0,a2	# a2 = mask & start
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								dcpgloop:
							 | 
						||
| 
								 | 
							
									# area purge
							 | 
						||
| 
								 | 
							
									mov	a2,d0
							 | 
						||
| 
								 | 
							
									or	DCPGCR_DCP,d0
							 | 
						||
| 
								 | 
							
									mov	d0,(a0)		# DCPGCR = (mask & start) | DCPGCR_DCP
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# wait for busy bit of area purge
							 | 
						||
| 
								 | 
							
									setlb
							 | 
						||
| 
								 | 
							
									mov	(a0),d1
							 | 
						||
| 
								 | 
							
									btst	DCPGCR_DCPGBSY,d1
							 | 
						||
| 
								 | 
							
									lne
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# check purge of end address
							 | 
						||
| 
								 | 
							
									add	d2,a2		# a2 += alignsize
							 | 
						||
| 
								 | 
							
									cmp	a1,a2		# if (a2 < end) goto dcpgloop
							 | 
						||
| 
								 | 
							
									bns	dcpgloop
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									LOCAL_IRQ_RESTORE(d3)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mn10300_local_dcache_flush_range_end:
							 | 
						||
| 
								 | 
							
									ret	[d2,d3,a2],12
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									.size	mn10300_local_dcache_flush_page,.-mn10300_local_dcache_flush_page
							 | 
						||
| 
								 | 
							
									.size	mn10300_local_dcache_flush_range,.-mn10300_local_dcache_flush_range
							 | 
						||
| 
								 | 
							
									.size	mn10300_local_dcache_flush_range2,.-mn10300_local_dcache_flush_range2
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								###############################################################################
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								# void mn10300_local_dcache_flush_inv(void)
							 | 
						||
| 
								 | 
							
								# Flush the entire data cache and invalidate all entries
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								###############################################################################
							 | 
						||
| 
								 | 
							
									ALIGN
							 | 
						||
| 
								 | 
							
									.globl	mn10300_local_dcache_flush_inv
							 | 
						||
| 
								 | 
							
									.type	mn10300_local_dcache_flush_inv,@function
							 | 
						||
| 
								 | 
							
								mn10300_local_dcache_flush_inv:
							 | 
						||
| 
								 | 
							
									movhu	(CHCTR),d0
							 | 
						||
| 
								 | 
							
									btst	CHCTR_DCEN,d0
							 | 
						||
| 
								 | 
							
									beq	mn10300_local_dcache_flush_inv_end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									mov	DCPGCR,a0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									LOCAL_CLI_SAVE(d1)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# wait for busy bit of area purge & invalidate
							 | 
						||
| 
								 | 
							
									setlb
							 | 
						||
| 
								 | 
							
									mov	(a0),d0
							 | 
						||
| 
								 | 
							
									btst	DCPGCR_DCPGBSY,d0
							 | 
						||
| 
								 | 
							
									lne
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# set the mask to cover everything
							 | 
						||
| 
								 | 
							
									clr	d0
							 | 
						||
| 
								 | 
							
									mov	d0,(DCPGMR)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# area purge & invalidate
							 | 
						||
| 
								 | 
							
									mov	DCPGCR_DCP|DCPGCR_DCI,d0
							 | 
						||
| 
								 | 
							
									mov	d0,(a0)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# wait for busy bit of area purge & invalidate
							 | 
						||
| 
								 | 
							
									setlb
							 | 
						||
| 
								 | 
							
									mov	(a0),d0
							 | 
						||
| 
								 | 
							
									btst	DCPGCR_DCPGBSY,d0
							 | 
						||
| 
								 | 
							
									lne
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									LOCAL_IRQ_RESTORE(d1)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mn10300_local_dcache_flush_inv_end:
							 | 
						||
| 
								 | 
							
									ret	[],0
							 | 
						||
| 
								 | 
							
									.size	mn10300_local_dcache_flush_inv,.-mn10300_local_dcache_flush_inv
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								###############################################################################
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								# void mn10300_local_dcache_flush_inv_page(unsigned long start)
							 | 
						||
| 
								 | 
							
								# void mn10300_local_dcache_flush_inv_range(unsigned long start, unsigned long end)
							 | 
						||
| 
								 | 
							
								# void mn10300_local_dcache_flush_inv_range2(unsigned long start, unsigned long size)
							 | 
						||
| 
								 | 
							
								# Flush and invalidate a range of addresses on a page in the dcache
							 | 
						||
| 
								 | 
							
								#
							 | 
						||
| 
								 | 
							
								###############################################################################
							 | 
						||
| 
								 | 
							
									ALIGN
							 | 
						||
| 
								 | 
							
									.globl	mn10300_local_dcache_flush_inv_page
							 | 
						||
| 
								 | 
							
									.globl	mn10300_local_dcache_flush_inv_range
							 | 
						||
| 
								 | 
							
									.globl	mn10300_local_dcache_flush_inv_range2
							 | 
						||
| 
								 | 
							
									.type	mn10300_local_dcache_flush_inv_page,@function
							 | 
						||
| 
								 | 
							
									.type	mn10300_local_dcache_flush_inv_range,@function
							 | 
						||
| 
								 | 
							
									.type	mn10300_local_dcache_flush_inv_range2,@function
							 | 
						||
| 
								 | 
							
								mn10300_local_dcache_flush_inv_page:
							 | 
						||
| 
								 | 
							
									and	~(PAGE_SIZE-1),d0
							 | 
						||
| 
								 | 
							
									mov	PAGE_SIZE,d1
							 | 
						||
| 
								 | 
							
								mn10300_local_dcache_flush_inv_range2:
							 | 
						||
| 
								 | 
							
									add	d0,d1
							 | 
						||
| 
								 | 
							
								mn10300_local_dcache_flush_inv_range:
							 | 
						||
| 
								 | 
							
									movm	[d2,d3,a2],(sp)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									movhu	(CHCTR),d2
							 | 
						||
| 
								 | 
							
									btst	CHCTR_DCEN,d2
							 | 
						||
| 
								 | 
							
									beq	mn10300_local_dcache_flush_inv_range_end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# calculate alignsize
							 | 
						||
| 
								 | 
							
									#
							 | 
						||
| 
								 | 
							
									# alignsize = L1_CACHE_BYTES;
							 | 
						||
| 
								 | 
							
									# for (i = (end - start - 1) / L1_CACHE_BYTES; i > 0; i >>= 1)
							 | 
						||
| 
								 | 
							
									#     alignsize <<= 1;
							 | 
						||
| 
								 | 
							
									# d2 = alignsize
							 | 
						||
| 
								 | 
							
									#
							 | 
						||
| 
								 | 
							
									mov	L1_CACHE_BYTES,d2
							 | 
						||
| 
								 | 
							
									sub	d0,d1,d3
							 | 
						||
| 
								 | 
							
									add	-1,d3
							 | 
						||
| 
								 | 
							
									lsr	L1_CACHE_SHIFT,d3
							 | 
						||
| 
								 | 
							
									beq	2f
							 | 
						||
| 
								 | 
							
								1:
							 | 
						||
| 
								 | 
							
									add     d2,d2
							 | 
						||
| 
								 | 
							
									lsr     1,d3
							 | 
						||
| 
								 | 
							
									bne     1b
							 | 
						||
| 
								 | 
							
								2:
							 | 
						||
| 
								 | 
							
									mov	d1,a1		# a1 = end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									LOCAL_CLI_SAVE(d3)
							 | 
						||
| 
								 | 
							
									mov	DCPGCR,a0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# wait for busy bit of area purge & invalidate
							 | 
						||
| 
								 | 
							
									setlb
							 | 
						||
| 
								 | 
							
									mov	(a0),d1
							 | 
						||
| 
								 | 
							
									btst	DCPGCR_DCPGBSY,d1
							 | 
						||
| 
								 | 
							
									lne
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# set the mask
							 | 
						||
| 
								 | 
							
									mov	d2,d1
							 | 
						||
| 
								 | 
							
									add	-1,d1
							 | 
						||
| 
								 | 
							
									not	d1		# d1 = mask = ~(alignsize-1)
							 | 
						||
| 
								 | 
							
									mov	d1,(DCPGMR)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									and	d1,d0,a2	# a2 = mask & start
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								dcpgivloop:
							 | 
						||
| 
								 | 
							
									# area purge & invalidate
							 | 
						||
| 
								 | 
							
									mov	a2,d0
							 | 
						||
| 
								 | 
							
									or	DCPGCR_DCP|DCPGCR_DCI,d0
							 | 
						||
| 
								 | 
							
									mov	d0,(a0)		# DCPGCR = (mask & start)|DCPGCR_DCP|DCPGCR_DCI
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# wait for busy bit of area purge & invalidate
							 | 
						||
| 
								 | 
							
									setlb
							 | 
						||
| 
								 | 
							
									mov	(a0),d1
							 | 
						||
| 
								 | 
							
									btst	DCPGCR_DCPGBSY,d1
							 | 
						||
| 
								 | 
							
									lne
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									# check purge & invalidate of end address
							 | 
						||
| 
								 | 
							
									add	d2,a2		# a2 += alignsize
							 | 
						||
| 
								 | 
							
									cmp	a1,a2		# if (a2 < end) goto dcpgivloop
							 | 
						||
| 
								 | 
							
									bns	dcpgivloop
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									LOCAL_IRQ_RESTORE(d3)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mn10300_local_dcache_flush_inv_range_end:
							 | 
						||
| 
								 | 
							
									ret	[d2,d3,a2],12
							 | 
						||
| 
								 | 
							
									.size	mn10300_local_dcache_flush_inv_page,.-mn10300_local_dcache_flush_inv_page
							 | 
						||
| 
								 | 
							
									.size	mn10300_local_dcache_flush_inv_range,.-mn10300_local_dcache_flush_inv_range
							 | 
						||
| 
								 | 
							
									.size	mn10300_local_dcache_flush_inv_range2,.-mn10300_local_dcache_flush_inv_range2
							 |