Linux 2.6.25-rc4
[linux-2.6/next.git] / arch / mn10300 / mm / cache-flush-mn10300.S
blobc8ed1cbac10782eddaa5be2c74e13b486949169c
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  */
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>
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
28 ###############################################################################
30 # void mn10300_dcache_flush(void)
31 # Flush the entire data cache back to RAM
33 ###############################################################################
34         ALIGN
35 mn10300_dcache_flush:
36         movhu   (CHCTR),d0
37         btst    CHCTR_DCEN,d0
38         beq     mn10300_dcache_flush_end
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
47 mn10300_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
54 mn10300_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
60 mn10300_dcache_flush_end:
61         ret     [],0
63 ###############################################################################
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
70 ###############################################################################
71         ALIGN
72 mn10300_dcache_flush_page:
73         mov     PAGE_SIZE,d1
74 mn10300_dcache_flush_range2:
75         add     d0,d1
76 mn10300_dcache_flush_range:
77         movm    [d2,d3],(sp)
79         movhu   (CHCTR),d2
80         btst    CHCTR_DCEN,d2
81         beq     mn10300_dcache_flush_range_end
83         # round start addr down
84         and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
85         mov     d0,a1
87         add     L1_CACHE_BYTES,d1                       # round end addr up
88         and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
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
97         sub     a1,d1
98         lsr     L1_CACHE_SHIFT,d1               # total number of entries to
99                                                 # examine
101         or      L1_CACHE_TAG_VALID,a1           # retain valid entries in the
102                                                 # cache
104 mn10300_dcache_flush_range_loop:
105         mov     a1,(L1_CACHE_WAYDISP*0,a0)      # conditionally purge this line
106                                                 # all ways
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
114 mn10300_dcache_flush_range_end:
115         ret     [d2,d3],8
117 ###############################################################################
119 # void mn10300_dcache_flush_inv(void)
120 # Flush the entire data cache and invalidate all entries
122 ###############################################################################
123         ALIGN
124 mn10300_dcache_flush_inv:
125         movhu   (CHCTR),d0
126         btst    CHCTR_DCEN,d0
127         beq     mn10300_dcache_flush_inv_end
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
133 mn10300_dcache_flush_inv_loop:
134         mov     (a1),d0                         # unconditional purge
136         add     L1_CACHE_BYTES,a1
137         add     -1,d1
138         bne     mn10300_dcache_flush_inv_loop
140 mn10300_dcache_flush_inv_end:
141         ret     [],0
143 ###############################################################################
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
150 ###############################################################################
151         ALIGN
152 mn10300_dcache_flush_inv_page:
153         mov     PAGE_SIZE,d1
154 mn10300_dcache_flush_inv_range2:
155         add     d0,d1
156 mn10300_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
162         and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0      # round start
163                                                                 # addr down
164         mov     d0,a1
166         add     L1_CACHE_BYTES,d1                       # round end addr up
167         and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
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
177         sub     a1,d1
178         lsr     L1_CACHE_SHIFT,d1               # total number of entries to
179                                                 # examine
181 mn10300_dcache_flush_inv_range_loop:
182         mov     a1,(L1_CACHE_WAYDISP*0,a0)      # conditionally purge this line
183                                                 # in all ways
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
191 mn10300_dcache_flush_inv_range_end:
192         ret     [d2,d3],8