Merge branch 'topic/fix/hda' into for-linus
[linux-2.6] / arch / mn10300 / mm / cache-flush-mn10300.S
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
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
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
27
28 ###############################################################################
29 #
30 # void mn10300_dcache_flush(void)
31 # Flush the entire data cache back to RAM
32 #
33 ###############################################################################
34         ALIGN
35 mn10300_dcache_flush:
36         movhu   (CHCTR),d0
37         btst    CHCTR_DCEN,d0
38         beq     mn10300_dcache_flush_end
39
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
46
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
53
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
59
60 mn10300_dcache_flush_end:
61         ret     [],0
62
63 ###############################################################################
64 #
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
69 #
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)
78
79         movhu   (CHCTR),d2
80         btst    CHCTR_DCEN,d2
81         beq     mn10300_dcache_flush_range_end
82
83         # round start addr down
84         and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
85         mov     d0,a1
86
87         add     L1_CACHE_BYTES,d1                       # round end addr up
88         and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
89
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
96
97         sub     a1,d1
98         lsr     L1_CACHE_SHIFT,d1               # total number of entries to
99                                                 # examine
100
101         or      L1_CACHE_TAG_VALID,a1           # retain valid entries in the
102                                                 # cache
103
104 mn10300_dcache_flush_range_loop:
105         mov     a1,(L1_CACHE_WAYDISP*0,a0)      # conditionally purge this line
106                                                 # all ways
107
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
113
114 mn10300_dcache_flush_range_end:
115         ret     [d2,d3],8
116
117 ###############################################################################
118 #
119 # void mn10300_dcache_flush_inv(void)
120 # Flush the entire data cache and invalidate all entries
121 #
122 ###############################################################################
123         ALIGN
124 mn10300_dcache_flush_inv:
125         movhu   (CHCTR),d0
126         btst    CHCTR_DCEN,d0
127         beq     mn10300_dcache_flush_inv_end
128
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
132
133 mn10300_dcache_flush_inv_loop:
134         mov     (a1),d0                         # unconditional purge
135
136         add     L1_CACHE_BYTES,a1
137         add     -1,d1
138         bne     mn10300_dcache_flush_inv_loop
139
140 mn10300_dcache_flush_inv_end:
141         ret     [],0
142
143 ###############################################################################
144 #
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
149 #
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
161
162         and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0      # round start
163                                                                 # addr down
164         mov     d0,a1
165
166         add     L1_CACHE_BYTES,d1                       # round end addr up
167         and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
168
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
176
177         sub     a1,d1
178         lsr     L1_CACHE_SHIFT,d1               # total number of entries to
179                                                 # examine
180
181 mn10300_dcache_flush_inv_range_loop:
182         mov     a1,(L1_CACHE_WAYDISP*0,a0)      # conditionally purge this line
183                                                 # in all ways
184
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
190
191 mn10300_dcache_flush_inv_range_end:
192         ret     [d2,d3],8