Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 218717
b: refs/heads/master
c: 9731d23
h: refs/heads/master
i:
  218715: 3f28fa1
v: v3
  • Loading branch information
Akira Takeuchi authored and David Howells committed Oct 27, 2010
1 parent 39f8ebe commit 91ae0da
Show file tree
Hide file tree
Showing 5 changed files with 679 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0bd3eb6ca772775da6125ea5b044d4257473d18d
refs/heads/master: 9731d23710736b96786d68c2e63148ff3f22e6eb
13 changes: 12 additions & 1 deletion trunk/arch/mn10300/mm/Kconfig.cache
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ config MN10300_CACHE_ENABLED

choice
prompt "CPU cache flush/invalidate method"
default MN10300_CACHE_MANAGE_BY_TAG
default MN10300_CACHE_MANAGE_BY_TAG if !AM34_2
default MN10300_CACHE_MANAGE_BY_REG if AM34_2
depends on MN10300_CACHE_ENABLED
help
This determines the method by which CPU cache flushing and
Expand All @@ -46,10 +47,20 @@ choice
config MN10300_CACHE_MANAGE_BY_TAG
bool "Use the cache tag registers directly"

config MN10300_CACHE_MANAGE_BY_REG
bool "Flush areas by way of automatic purge registers (AM34 only)"
depends on AM34_2

endchoice

config MN10300_CACHE_INV_BY_TAG
def_bool y if MN10300_CACHE_MANAGE_BY_TAG && MN10300_CACHE_ENABLED

config MN10300_CACHE_INV_BY_REG
def_bool y if MN10300_CACHE_MANAGE_BY_REG && MN10300_CACHE_ENABLED

config MN10300_CACHE_FLUSH_BY_TAG
def_bool y if MN10300_CACHE_MANAGE_BY_TAG && MN10300_CACHE_WBACK

config MN10300_CACHE_FLUSH_BY_REG
def_bool y if MN10300_CACHE_MANAGE_BY_REG && MN10300_CACHE_WBACK
2 changes: 2 additions & 0 deletions trunk/arch/mn10300/mm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

cacheflush-y := cache.o
cacheflush-$(CONFIG_MN10300_CACHE_INV_BY_TAG) += cache-inv-by-tag.o
cacheflush-$(CONFIG_MN10300_CACHE_INV_BY_REG) += cache-inv-by-reg.o
cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_TAG) += cache-flush-by-tag.o
cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_REG) += cache-flush-by-reg.o

cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o

Expand Down
308 changes: 308 additions & 0 deletions trunk/arch/mn10300/mm/cache-flush-by-reg.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,308 @@
/* 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
Loading

0 comments on commit 91ae0da

Please sign in to comment.