PERFORCE change 158521 for review
Ulf Lilleengen
lulf at FreeBSD.org
Sun Mar 1 01:57:33 PST 2009
http://perforce.freebsd.org/chv.cgi?CH=158521
Change 158521 by lulf at lulf_carrot on 2009/03/01 09:57:00
- Implement cache handling used by busdma.
Affected files ...
.. //depot/projects/avr32/src/sys/avr32/avr32/cache.c#2 edit
Differences ...
==== //depot/projects/avr32/src/sys/avr32/avr32/cache.c#2 (text+ko) ====
@@ -41,9 +41,24 @@
#include <machine/reg_usart.h>
#include <machine/at32ap700x.h>
-/* TODO:
- - Implement l1 cache handling.
-*/
+/* Valid cache op codes. */
+#define ICACHE_INVALIDATE 0x01
+#define DCACHE_INVALIDATE 0x0b
+#define DCACHE_WRITEBACK 0x0c
+#define DCACHE_WRITEBACK_INVALIDATE 0x0d
+
+/* Next line boundary. */
+#define round_line(va, size) (((va) + ((size) - 1)) & ~((size) - 1))
+/* Previous line boundary. */
+#define trunc_line(va, size) ((va) & ~((size) - 1))
+
+/* Perform operation on cache line. */
+#define cache_line_op(va, op) \
+ __asm__ __volatile( \
+ "cache %0[0], %1" \
+ : \
+ : "r" (va), "n" (op) \
+ : "memory")
struct avr32_cache_ops avr32_cache_ops;
@@ -58,14 +73,14 @@
void avr32_nocache_wb_range(vm_offset_t, vm_size_t);
/* For l1 cache. */
-void avr32_l1cache_sync_all(void);
-void avr32_l1cache_sync_range(vm_offset_t, vm_size_t);
-void avr32_l1cache_sync_range_index(vm_offset_t, vm_size_t);
-void avr32_l1cache_wbinv_all(void);
-void avr32_l1cache_wbinv_range(vm_offset_t, vm_size_t);
-void avr32_l1cache_wbinv_range_index(vm_offset_t, vm_size_t);
-void avr32_l1cache_inv_range(vm_offset_t, vm_size_t);
-void avr32_l1cache_wb_range(vm_offset_t, vm_size_t);
+void avr32_l1icache_sync_all(void);
+void avr32_l1icache_sync_range(vm_offset_t, vm_size_t);
+void avr32_l1icache_sync_range_index(vm_offset_t, vm_size_t);
+void avr32_l1dcache_wbinv_all(void);
+void avr32_l1dcache_wbinv_range(vm_offset_t, vm_size_t);
+void avr32_l1dcache_wbinv_range_index(vm_offset_t, vm_size_t);
+void avr32_l1dcache_inv_range(vm_offset_t, vm_size_t);
+void avr32_l1dcache_wb_range(vm_offset_t, vm_size_t);
u_int avr32_icache_size;
u_int avr32_icache_line_size;
@@ -116,11 +131,11 @@
avr32_cache_ops.mco_icache_sync_range_index =
avr32_nocache_sync_range_index;
} else {
- avr32_cache_ops.mco_icache_sync_all = avr32_l1cache_sync_all;
+ avr32_cache_ops.mco_icache_sync_all = avr32_l1icache_sync_all;
avr32_cache_ops.mco_icache_sync_range =
- avr32_l1cache_sync_range;
+ avr32_l1icache_sync_range;
avr32_cache_ops.mco_icache_sync_range_index =
- avr32_l1cache_sync_range_index;
+ avr32_l1icache_sync_range_index;
}
if (avr32_dcache_line_size == 1) {
@@ -132,13 +147,13 @@
avr32_cache_ops.mco_dcache_inv_range = avr32_nocache_inv_range;
avr32_cache_ops.mco_dcache_wb_range = avr32_nocache_wb_range;
} else {
- avr32_cache_ops.mco_dcache_wbinv_all = avr32_l1cache_wbinv_all;
+ avr32_cache_ops.mco_dcache_wbinv_all = avr32_l1dcache_wbinv_all;
avr32_cache_ops.mco_dcache_wbinv_range =
- avr32_l1cache_wbinv_range;
+ avr32_l1dcache_wbinv_range;
avr32_cache_ops.mco_dcache_wbinv_range_index =
- avr32_l1cache_wbinv_range_index;
- avr32_cache_ops.mco_dcache_inv_range = avr32_l1cache_inv_range;
- avr32_cache_ops.mco_dcache_wb_range = avr32_l1cache_wb_range;
+ avr32_l1dcache_wbinv_range_index;
+ avr32_cache_ops.mco_dcache_inv_range = avr32_l1dcache_inv_range;
+ avr32_cache_ops.mco_dcache_wb_range = avr32_l1dcache_wb_range;
}
}
@@ -155,35 +170,77 @@
/* Operations for l1 cache. */
void
-avr32_l1cache_sync_all(void)
+avr32_l1icache_sync_all(void)
{
+ avr32_impl();
}
void
-avr32_l1cache_sync_range(vm_offset_t from, vm_size_t size)
+avr32_l1icache_sync_range(vm_offset_t from, vm_size_t size)
{
+ avr32_impl();
}
void
-avr32_l1cache_sync_range_index(vm_offset_t from, vm_size_t size)
-{}
+avr32_l1icache_sync_range_index(vm_offset_t from, vm_size_t size)
+{
+ avr32_impl();
+}
void
-avr32_l1cache_wbinv_all(void)
-{}
+avr32_l1dcache_wbinv_all(void)
+{
+ avr32_impl();
+}
void
-avr32_l1cache_wbinv_range(vm_offset_t from, vm_size_t size)
-{}
+avr32_l1dcache_wbinv_range_index(vm_offset_t from, vm_size_t size)
+{
+ avr32_impl();
+}
void
-avr32_l1cache_wbinv_range_index(vm_offset_t from, vm_size_t size)
-{}
+avr32_l1dcache_wbinv_range(vm_offset_t from, vm_size_t size)
+{
+ vm_offset_t va, va_end;
+
+ /* Put address at a cache line boundary. */
+ va = trunc_line(from, avr32_dcache_line_size);
+ va_end = round_line(from + size, avr32_dcache_line_size);
+
+ while (va < va_end) {
+ cache_line_op(va, DCACHE_WRITEBACK_INVALIDATE);
+ va += avr32_dcache_line_size;
+ }
+}
+
void
-avr32_l1cache_inv_range(vm_offset_t from, vm_size_t size)
-{}
+avr32_l1dcache_inv_range(vm_offset_t from, vm_size_t size)
+{
+ vm_offset_t va, va_end;
+
+ /* Put address at a cache line boundary. */
+ va = trunc_line(from, avr32_dcache_line_size);
+ va_end = round_line(from + size, avr32_dcache_line_size);
+
+ while (va < va_end) {
+ cache_line_op(va, DCACHE_INVALIDATE);
+ va += avr32_dcache_line_size;
+ }
+}
void
-avr32_l1cache_wb_range(vm_offset_t from, vm_size_t size)
-{}
+avr32_l1dcache_wb_range(vm_offset_t from, vm_size_t size)
+{
+ vm_offset_t va, va_end;
+
+ /* Put address at a cache line boundary. */
+ va = trunc_line(from, avr32_dcache_line_size);
+ va_end = round_line(from + size, avr32_dcache_line_size);
+
+ while (va < va_end) {
+ cache_line_op(va, DCACHE_WRITEBACK);
+ va += avr32_dcache_line_size;
+ }
+}
More information about the p4-projects
mailing list