]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/blackfin/lib/cache.c
Merge branch 'karo-tx-uboot' into kc-merge
[karo-tx-uboot.git] / arch / blackfin / lib / cache.c
1 /*
2  * U-boot - cache.c
3  *
4  * Copyright (c) 2005-2008 Analog Devices Inc.
5  *
6  * (C) Copyright 2000-2004
7  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
8  *
9  * Licensed under the GPL-2 or later.
10  */
11
12 #include <common.h>
13 #include <asm/blackfin.h>
14 #include <asm/mach-common/bits/mpu.h>
15
16 void flush_cache(unsigned long addr, unsigned long size)
17 {
18         void *start_addr, *end_addr;
19         int istatus, dstatus;
20
21         /* no need to flush stuff in on chip memory (L1/L2/etc...) */
22         if (addr >= 0xE0000000)
23                 return;
24
25         start_addr = (void *)addr;
26         end_addr = (void *)(addr + size);
27         istatus = icache_status();
28         dstatus = dcache_status();
29
30         if (istatus) {
31                 if (dstatus)
32                         blackfin_icache_dcache_flush_range(start_addr, end_addr);
33                 else
34                         blackfin_icache_flush_range(start_addr, end_addr);
35         } else if (dstatus)
36                 blackfin_dcache_flush_range(start_addr, end_addr);
37 }
38
39 #ifdef CONFIG_DCACHE_WB
40 static void flushinv_all_dcache(void)
41 {
42         u32 way, bank, subbank, set;
43         u32 status, addr;
44         u32 dmem_ctl = bfin_read_DMEM_CONTROL();
45
46         for (bank = 0; bank < 2; ++bank) {
47                 if (!(dmem_ctl & (1 << (DMC1_P - bank))))
48                         continue;
49
50                 for (way = 0; way < 2; ++way)
51                         for (subbank = 0; subbank < 4; ++subbank)
52                                 for (set = 0; set < 64; ++set) {
53
54                                         bfin_write_DTEST_COMMAND(
55                                                 way << 26 |
56                                                 bank << 23 |
57                                                 subbank << 16 |
58                                                 set << 5
59                                         );
60                                         CSYNC();
61                                         status = bfin_read_DTEST_DATA0();
62
63                                         /* only worry about valid/dirty entries */
64                                         if ((status & 0x3) != 0x3)
65                                                 continue;
66
67                                         /* construct the address using the tag */
68                                         addr = (status & 0xFFFFC800) | (subbank << 12) | (set << 5);
69
70                                         /* flush it */
71                                         __asm__ __volatile__("FLUSHINV[%0];" : : "a"(addr));
72                                 }
73         }
74 }
75 #endif
76
77 void icache_enable(void)
78 {
79         bfin_write_IMEM_CONTROL(IMC | ENICPLB);
80         SSYNC();
81 }
82
83 void icache_disable(void)
84 {
85         bfin_write_IMEM_CONTROL(0);
86         SSYNC();
87 }
88
89 int icache_status(void)
90 {
91         return bfin_read_IMEM_CONTROL() & IMC;
92 }
93
94 void dcache_enable(void)
95 {
96         bfin_write_DMEM_CONTROL(ACACHE_BCACHE | ENDCPLB | PORT_PREF0);
97         SSYNC();
98 }
99
100 void dcache_disable(void)
101 {
102 #ifdef CONFIG_DCACHE_WB
103         bfin_write_DMEM_CONTROL(bfin_read_DMEM_CONTROL() & ~(ENDCPLB));
104         flushinv_all_dcache();
105 #endif
106         bfin_write_DMEM_CONTROL(0);
107         SSYNC();
108 }
109
110 int dcache_status(void)
111 {
112         return bfin_read_DMEM_CONTROL() & ACACHE_BCACHE;
113 }
114
115 void invalidate_dcache_range(unsigned long start, unsigned long stop)
116 {
117         blackfin_dcache_flush_invalidate_range((const void *)start, (const void *)stop);
118 }
119
120 void flush_dcache_range(unsigned long start, unsigned long stop)
121 {
122         blackfin_dcache_flush_range((const void *)start, (const void *)stop);
123 }