62f603bdb0f5dea2ad6b10f6db56390070f334a5
[oweals/u-boot.git] / cpu / bf537 / cpu.c
1 /*
2  * U-boot - cpu.c CPU specific functions
3  *
4  * Copyright (c) 2005-2007 Analog Devices Inc.
5  *
6  * (C) Copyright 2000-2004
7  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
8  *
9  * See file CREDITS for list of people who contributed to this
10  * project.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License as
14  * published by the Free Software Foundation; either version 2 of
15  * the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
25  * MA 02110-1301 USA
26  */
27
28 #include <common.h>
29 #include <asm/blackfin.h>
30 #include <command.h>
31 #include <asm/entry.h>
32 #include <asm/cplb.h>
33 #include <asm/io.h>
34
35 #define CACHE_ON 1
36 #define CACHE_OFF 0
37
38 extern unsigned int icplb_table[page_descriptor_table_size][2];
39 extern unsigned int dcplb_table[page_descriptor_table_size][2];
40
41 int do_reset(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
42 {
43         __asm__ __volatile__("cli r3;" "P0 = %0;" "JUMP (P0);"::"r"(L1_ISRAM)
44             );
45
46         return 0;
47 }
48
49 /* These functions are just used to satisfy the linker */
50 int cpu_init(void)
51 {
52         return 0;
53 }
54
55 int cleanup_before_linux(void)
56 {
57         return 0;
58 }
59
60 void icache_enable(void)
61 {
62         unsigned int *I0, *I1;
63         int i, j = 0;
64
65         if ((*pCHIPID >> 28) < 2)
66                 return;
67
68         /* Before enable icache, disable it first */
69         icache_disable();
70         I0 = (unsigned int *)ICPLB_ADDR0;
71         I1 = (unsigned int *)ICPLB_DATA0;
72
73         /* make sure the locked ones go in first */
74         for (i = 0; i < page_descriptor_table_size; i++) {
75                 if (CPLB_LOCK & icplb_table[i][1]) {
76                         debug("adding %02i %02i 0x%08x 0x%08x\n", i, j,
77                                  icplb_table[i][0], icplb_table[i][1]);
78                         *I0++ = icplb_table[i][0];
79                         *I1++ = icplb_table[i][1];
80                         j++;
81                 }
82         }
83
84         for (i = 0; i < page_descriptor_table_size; i++) {
85                 if (!(CPLB_LOCK & icplb_table[i][1])) {
86                         debug("adding %02i %02i 0x%08x 0x%08x\n", i, j,
87                                  icplb_table[i][0], icplb_table[i][1]);
88                         *I0++ = icplb_table[i][0];
89                         *I1++ = icplb_table[i][1];
90                         j++;
91                         if (j == 16) {
92                                 break;
93                         }
94                 }
95         }
96
97         /* Fill the rest with invalid entry */
98         if (j <= 15) {
99                 for (; j < 16; j++) {
100                         debug("filling %i with 0", j);
101                         *I1++ = 0x0;
102                 }
103
104         }
105
106         cli();
107         sync();
108         asm(" .align 8; ");
109         *(unsigned int *)IMEM_CONTROL = IMC | ENICPLB;
110         sync();
111         sti();
112 }
113
114 void icache_disable(void)
115 {
116         if ((*pCHIPID >> 28) < 2)
117                 return;
118         cli();
119         sync();
120         asm(" .align 8; ");
121         *(unsigned int *)IMEM_CONTROL &= ~(IMC | ENICPLB);
122         sync();
123         sti();
124 }
125
126 int icache_status(void)
127 {
128         unsigned int value;
129         value = *(unsigned int *)IMEM_CONTROL;
130
131         if (value & (IMC | ENICPLB))
132                 return CACHE_ON;
133         else
134                 return CACHE_OFF;
135 }
136
137 void dcache_enable(void)
138 {
139         unsigned int *I0, *I1;
140         unsigned int temp;
141         int i, j = 0;
142
143         /* Before enable dcache, disable it first */
144         dcache_disable();
145         I0 = (unsigned int *)DCPLB_ADDR0;
146         I1 = (unsigned int *)DCPLB_DATA0;
147
148         /* make sure the locked ones go in first */
149         for (i = 0; i < page_descriptor_table_size; i++) {
150                 if (CPLB_LOCK & dcplb_table[i][1]) {
151                         debug("adding %02i %02i 0x%08x 0x%08x\n", i, j,
152                                  dcplb_table[i][0], dcplb_table[i][1]);
153                         *I0++ = dcplb_table[i][0];
154                         *I1++ = dcplb_table[i][1];
155                         j++;
156                 } else {
157                         debug("skip   %02i %02i 0x%08x 0x%08x\n", i, j,
158                                  dcplb_table[i][0], dcplb_table[i][1]);
159                 }
160         }
161
162         for (i = 0; i < page_descriptor_table_size; i++) {
163                 if (!(CPLB_LOCK & dcplb_table[i][1])) {
164                         debug("adding %02i %02i 0x%08x 0x%08x\n", i, j,
165                                  dcplb_table[i][0], dcplb_table[i][1]);
166                         *I0++ = dcplb_table[i][0];
167                         *I1++ = dcplb_table[i][1];
168                         j++;
169                         if (j == 16) {
170                                 break;
171                         }
172                 }
173         }
174
175         /* Fill the rest with invalid entry */
176         if (j <= 15) {
177                 for (; j < 16; j++) {
178                         debug("filling %i with 0", j);
179                         *I1++ = 0x0;
180                 }
181         }
182
183         cli();
184         temp = *(unsigned int *)DMEM_CONTROL;
185         sync();
186         asm(" .align 8; ");
187         *(unsigned int *)DMEM_CONTROL =
188             ACACHE_BCACHE | ENDCPLB | PORT_PREF0 | temp;
189         sync();
190         sti();
191 }
192
193 void dcache_disable(void)
194 {
195         unsigned int *I0, *I1;
196         int i;
197
198         cli();
199         sync();
200         asm(" .align 8; ");
201         *(unsigned int *)DMEM_CONTROL &=
202             ~(ACACHE_BCACHE | ENDCPLB | PORT_PREF0);
203         sync();
204         sti();
205
206         /* after disable dcache,
207          * clear it so we don't confuse the next application
208          */
209         I0 = (unsigned int *)DCPLB_ADDR0;
210         I1 = (unsigned int *)DCPLB_DATA0;
211
212         for (i = 0; i < 16; i++) {
213                 *I0++ = 0x0;
214                 *I1++ = 0x0;
215         }
216 }
217
218 int dcache_status(void)
219 {
220         unsigned int value;
221         value = *(unsigned int *)DMEM_CONTROL;
222
223         if (value & (ENDCPLB))
224                 return CACHE_ON;
225         else
226                 return CACHE_OFF;
227 }