2 * arch/ubicom32/mach-common/cachectl.c
3 * Architecture cache control support
5 * (C) Copyright 2009, Ubicom, Inc.
7 * This file is part of the Ubicom32 Linux Kernel Port.
9 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10 * it and/or modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation, either version 2 of the
12 * License, or (at your option) any later version.
14 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with the Ubicom32 Linux Kernel Port. If not,
21 * see <http://www.gnu.org/licenses/>.
23 * Ubicom32 implementation derived from (with many thanks):
29 #include <linux/types.h>
30 #include <linux/module.h>
31 #include <asm/cachectl.h>
34 * The write queue flush procedure in mem_cache_control needs to make
35 * DCACHE_WRITE_QUEUE_LENGTH writes to DDR (not OCM). Here we reserve some
36 * memory for this operation.
37 * Allocate array of cache lines of least DCACHE_WRITE_QUEUE_LENGTH + 1 words in
38 * length rounded up to the nearest cache line.
40 #define CACHE_WRITE_QUEUE_FLUSH_AREA_SIZE \
41 ALIGN(sizeof(int) * (DCACHE_WRITE_QUEUE_LENGTH + 1), CACHE_LINE_SIZE)
43 static char cache_write_queue_flush_area
[CACHE_WRITE_QUEUE_FLUSH_AREA_SIZE
]
44 __attribute__((aligned(CACHE_LINE_SIZE
)));
47 * ONE_CCR_ADDR_OP is a helper macro that executes a single CCR operation.
49 #define ONE_CCR_ADDR_OP(cc, op_addr, op) \
52 " btst "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_VALID)" \n\t" \
54 " move.4 "D(CCR_ADDR)"(%0), %1 \n\t" \
55 " move.1 "D(CCR_CTRL+3)"(%0), %2 \n\t" \
56 " bset "D(CCR_CTRL)"(%0), "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_VALID)" \n\t" \
58 " btst "D(CCR_CTRL)"(%0), #"D(CCR_CTRL_DONE)" \n\t" \
61 : "a"(cc), "r"(op_addr), "r"(op & 0xff) \
68 * Special cache control operation
70 void mem_cache_control(unsigned long cc
, unsigned long begin_addr
,
71 unsigned long end_addr
, unsigned long op
)
73 unsigned long op_addr
;
74 int dccr
= cc
== DCCR_BASE
;
75 if (dccr
&& op
== CCR_CTRL_FLUSH_ADDR
) {
77 * We ensure all previous writes have left the data cache write
78 * queue by sending DCACHE_WRITE_QUEUE_LENGTH writes (to
79 * different words) down the queue. If this is not done it's
80 * possible that the data we are trying to flush hasn't even
81 * entered the data cache.
82 * The +1 ensure that the final 'flush' is actually a flush.
84 int *flush_area
= (int *)cache_write_queue_flush_area
;
86 " .rept "D(DCACHE_WRITE_QUEUE_LENGTH
+ 1)" \n\t"
87 " move.4 (%0)4++, d0 \n\t"
94 UBICOM32_LOCK(DCCR_LOCK_BIT
);
96 UBICOM32_LOCK(ICCR_LOCK_BIT
);
99 * Calculate the cache lines we need to operate on that include
100 * begin_addr though end_addr.
102 begin_addr
= begin_addr
& ~(CACHE_LINE_SIZE
- 1);
103 end_addr
= (end_addr
+ CACHE_LINE_SIZE
- 1) & ~(CACHE_LINE_SIZE
- 1);
104 op_addr
= begin_addr
;
107 ONE_CCR_ADDR_OP(cc
, op_addr
, op
);
108 op_addr
+= CACHE_LINE_SIZE
;
109 } while (likely(op_addr
< end_addr
));
111 if (dccr
&& op
== CCR_CTRL_FLUSH_ADDR
) {
113 * It turns out that when flushing the data cache the last flush
114 * isn't actually complete at this point. This is because there
115 * is another write buffer on the DDR side of the cache that is
116 * arbitrated with the I-Cache.
118 * The only foolproof method that ensures that the last data
119 * cache flush *actually* completed is to do another flush on a
120 * dirty cache line. This flush will block until the DDR write
123 * Rather than creating a another dirty cache line, we use the
124 * flush_area above as we know that it is dirty from previous
127 ONE_CCR_ADDR_OP(cc
, cache_write_queue_flush_area
, op
);
131 UBICOM32_UNLOCK(DCCR_LOCK_BIT
);
133 UBICOM32_UNLOCK(ICCR_LOCK_BIT
);
136 EXPORT_SYMBOL(mem_cache_control
);