blob: bd393d597f9c4143eefa184739ea22b284bb1f69 [file] [log] [blame]
Wolfgang Denk6cb142f2006-03-12 02:12:27 +01001/*
2 * U-boot - cpu.c CPU specific functions
3 *
4 * Copyright (c) 2005 blackfin.uclinux.org
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., 59 Temple Place, Suite 330, Boston,
25 * MA 02111-1307 USA
26 */
27
28#include <common.h>
29#include <asm/blackfin.h>
30#include <command.h>
31#include <asm/entry.h>
Aubrey.Li3f0606a2007-03-09 13:38:44 +080032#include <asm/cplb.h>
Wolfgang Denk6cb142f2006-03-12 02:12:27 +010033
Wolfgang Denk6cb142f2006-03-12 02:12:27 +010034#define CACHE_ON 1
35#define CACHE_OFF 0
36
Aubrey.Li3f0606a2007-03-09 13:38:44 +080037extern unsigned int icplb_table[page_descriptor_table_size][2];
38extern unsigned int dcplb_table[page_descriptor_table_size][2];
Wolfgang Denk6cb142f2006-03-12 02:12:27 +010039
Aubrey.Li3f0606a2007-03-09 13:38:44 +080040#ifdef DEBUG
41#define pr_debug(fmt,arg...) printf(fmt,##arg)
42#else
43static inline int
44 __attribute__ ((format(printf, 1, 2))) pr_debug(const char *fmt, ...)
Wolfgang Denk6cb142f2006-03-12 02:12:27 +010045{
Aubrey.Li3f0606a2007-03-09 13:38:44 +080046 return 0;
47}
48#endif
49
50int do_reset(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
51{
52 __asm__ __volatile__("cli r3;" "P0 = %0;" "JUMP (P0);"::"r"(L1_ISRAM)
53 );
Wolfgang Denk6cb142f2006-03-12 02:12:27 +010054
55 return 0;
56}
57
58/* These functions are just used to satisfy the linker */
59int cpu_init(void)
60{
61 return 0;
62}
63
64int cleanup_before_linux(void)
65{
66 return 0;
67}
68
69void icache_enable(void)
70{
Aubrey.Li3f0606a2007-03-09 13:38:44 +080071 unsigned int *I0, *I1;
72 int i, j = 0;
73#ifdef __ADSPBF537__
74 if ((*pCHIPID >> 28) < 2)
75 return;
76#endif
Wolfgang Denk6cb142f2006-03-12 02:12:27 +010077
Aubrey.Li3f0606a2007-03-09 13:38:44 +080078 /* Before enable icache, disable it first */
79 icache_disable();
Wolfgang Denk6cb142f2006-03-12 02:12:27 +010080 I0 = (unsigned int *)ICPLB_ADDR0;
81 I1 = (unsigned int *)ICPLB_DATA0;
Wolfgang Denk8e7b7032006-03-12 02:55:22 +010082
Aubrey.Li3f0606a2007-03-09 13:38:44 +080083 /* make sure the locked ones go in first */
84 for (i = 0; i < page_descriptor_table_size; i++) {
85 if (CPLB_LOCK & icplb_table[i][1]) {
86 pr_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++;
Wolfgang Denk6cb142f2006-03-12 02:12:27 +010091 }
Aubrey.Li3f0606a2007-03-09 13:38:44 +080092 }
93
94 for (i = 0; i < page_descriptor_table_size; i++) {
95 if (!(CPLB_LOCK & icplb_table[i][1])) {
96 pr_debug("adding %02i %02i 0x%08x 0x%08x\n", i, j,
97 icplb_table[i][0], icplb_table[i][1]);
98 *I0++ = icplb_table[i][0];
99 *I1++ = icplb_table[i][1];
100 j++;
101 if (j == 16) {
102 break;
103 }
104 }
105 }
106
107 /* Fill the rest with invalid entry */
108 if (j <= 15) {
109 for (; j <= 16; j++) {
110 pr_debug("filling %i with 0", j);
111 *I1++ = 0x0;
112 }
113
114 }
115
Wolfgang Denk6cb142f2006-03-12 02:12:27 +0100116 cli();
Aubrey.Li3f0606a2007-03-09 13:38:44 +0800117 __builtin_bfin_ssync();
118 asm(" .align 8; ");
Wolfgang Denk6cb142f2006-03-12 02:12:27 +0100119 *(unsigned int *)IMEM_CONTROL = IMC | ENICPLB;
Aubrey.Li3f0606a2007-03-09 13:38:44 +0800120 __builtin_bfin_ssync();
Wolfgang Denk6cb142f2006-03-12 02:12:27 +0100121 sti();
122}
123
124void icache_disable(void)
125{
Aubrey.Li3f0606a2007-03-09 13:38:44 +0800126#ifdef __ADSPBF537__
127 if ((*pCHIPID >> 28) < 2)
128 return;
129#endif
Wolfgang Denk6cb142f2006-03-12 02:12:27 +0100130 cli();
Aubrey.Li3f0606a2007-03-09 13:38:44 +0800131 __builtin_bfin_ssync();
132 asm(" .align 8; ");
Wolfgang Denk6cb142f2006-03-12 02:12:27 +0100133 *(unsigned int *)IMEM_CONTROL &= ~(IMC | ENICPLB);
Aubrey.Li3f0606a2007-03-09 13:38:44 +0800134 __builtin_bfin_ssync();
Wolfgang Denk6cb142f2006-03-12 02:12:27 +0100135 sti();
136}
137
138int icache_status(void)
139{
140 unsigned int value;
141 value = *(unsigned int *)IMEM_CONTROL;
142
Aubrey.Li3f0606a2007-03-09 13:38:44 +0800143 if (value & (IMC | ENICPLB))
Wolfgang Denk6cb142f2006-03-12 02:12:27 +0100144 return CACHE_ON;
145 else
146 return CACHE_OFF;
147}
148
149void dcache_enable(void)
150{
Aubrey.Li3f0606a2007-03-09 13:38:44 +0800151 unsigned int *I0, *I1;
Wolfgang Denk6cb142f2006-03-12 02:12:27 +0100152 unsigned int temp;
Aubrey.Li3f0606a2007-03-09 13:38:44 +0800153 int i, j = 0;
154
155 /* Before enable dcache, disable it first */
156 dcache_disable();
Wolfgang Denk6cb142f2006-03-12 02:12:27 +0100157 I0 = (unsigned int *)DCPLB_ADDR0;
158 I1 = (unsigned int *)DCPLB_DATA0;
159
Aubrey.Li3f0606a2007-03-09 13:38:44 +0800160 /* make sure the locked ones go in first */
161 for (i = 0; i < page_descriptor_table_size; i++) {
162 if (CPLB_LOCK & dcplb_table[i][1]) {
163 pr_debug("adding %02i %02i 0x%08x 0x%08x\n", i, j,
164 dcplb_table[i][0], dcplb_table[i][1]);
165 *I0++ = dcplb_table[i][0];
166 *I1++ = dcplb_table[i][1];
167 j++;
168 } else {
169 pr_debug("skip %02i %02i 0x%08x 0x%08x\n", i, j,
170 dcplb_table[i][0], dcplb_table[i][1]);
Wolfgang Denk6cb142f2006-03-12 02:12:27 +0100171 }
Aubrey.Li3f0606a2007-03-09 13:38:44 +0800172 }
173
174 for (i = 0; i < page_descriptor_table_size; i++) {
175 if (!(CPLB_LOCK & dcplb_table[i][1])) {
176 pr_debug("adding %02i %02i 0x%08x 0x%08x\n", i, j,
177 dcplb_table[i][0], dcplb_table[i][1]);
178 *I0++ = dcplb_table[i][0];
179 *I1++ = dcplb_table[i][1];
180 j++;
181 if (j == 16) {
182 break;
183 }
184 }
185 }
186
187 /* Fill the rest with invalid entry */
188 if (j <= 15) {
189 for (; j <= 16; j++) {
190 pr_debug("filling %i with 0", j);
191 *I1++ = 0x0;
192 }
193 }
194
Wolfgang Denk6cb142f2006-03-12 02:12:27 +0100195 cli();
Wolfgang Denk8e7b7032006-03-12 02:55:22 +0100196 temp = *(unsigned int *)DMEM_CONTROL;
Aubrey.Li3f0606a2007-03-09 13:38:44 +0800197 __builtin_bfin_ssync();
198 asm(" .align 8; ");
199 *(unsigned int *)DMEM_CONTROL =
200 ACACHE_BCACHE | ENDCPLB | PORT_PREF0 | temp;
201 __builtin_bfin_ssync();
Wolfgang Denk6cb142f2006-03-12 02:12:27 +0100202 sti();
203}
Wolfgang Denk6cb142f2006-03-12 02:12:27 +0100204
205void dcache_disable(void)
206{
Aubrey.Li3f0606a2007-03-09 13:38:44 +0800207
208 unsigned int *I0, *I1;
209 int i;
210
Wolfgang Denk6cb142f2006-03-12 02:12:27 +0100211 cli();
Aubrey.Li3f0606a2007-03-09 13:38:44 +0800212 __builtin_bfin_ssync();
213 asm(" .align 8; ");
214 *(unsigned int *)DMEM_CONTROL &=
215 ~(ACACHE_BCACHE | ENDCPLB | PORT_PREF0);
216 __builtin_bfin_ssync();
Wolfgang Denk6cb142f2006-03-12 02:12:27 +0100217 sti();
Aubrey.Li3f0606a2007-03-09 13:38:44 +0800218
219 /* after disable dcache,
220 * clear it so we don't confuse the next application
221 */
222 I0 = (unsigned int *)DCPLB_ADDR0;
223 I1 = (unsigned int *)DCPLB_DATA0;
224
225 for (i = 0; i < 16; i++) {
226 *I0++ = 0x0;
227 *I1++ = 0x0;
228 }
Wolfgang Denk6cb142f2006-03-12 02:12:27 +0100229}
230
231int dcache_status(void)
232{
233 unsigned int value;
234 value = *(unsigned int *)DMEM_CONTROL;
Aubrey.Li3f0606a2007-03-09 13:38:44 +0800235 if (value & (ENDCPLB))
Wolfgang Denk6cb142f2006-03-12 02:12:27 +0100236 return CACHE_ON;
237 else
238 return CACHE_OFF;
239}