aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel
diff options
context:
space:
mode:
authorBernd Schmidt <bernd.schmidt@analog.com>2007-07-12 04:25:29 -0400
committerBryan Wu <bryan.wu@analog.com>2007-07-12 04:25:29 -0400
commit29440a2b4cd37e32dfe0fa60ef1665775b24dab1 (patch)
tree1b7bd1c1793feba0719f04de2eb68e418498e827 /arch/blackfin/kernel
parent474f1a667d4bd40b6dcacc6870b70f4d2ba4e155 (diff)
Blackfin arch: Start untangling the CPLB handling code.
- Move cache initialization to C from assembly. - Move anomaly workaround for writing [ID]MEM_CONTROL to assembly, so that we don't have to mess around with .align directives in C source. - Fix a bug where bfin_write_DMEM_CONTROL would write to IMEM_CONTROL - Break out CPLB related code from kernel/setup.c into their own file. - Don't define variables in header files, only declare them. Signed-off-by: Bernd Schmidt <bernd.schmidt@analog.com> Signed-off-by: Bryan Wu <bryan.wu@analog.com>
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r--arch/blackfin/kernel/Makefile2
-rw-r--r--arch/blackfin/kernel/cacheinit.c66
-rw-r--r--arch/blackfin/kernel/cplbinit.c433
-rw-r--r--arch/blackfin/kernel/setup.c289
4 files changed, 502 insertions, 288 deletions
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index 6fac57f6ce06..f429ebc3a961 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -7,7 +7,7 @@ extra-y := init_task.o vmlinux.lds
7obj-y := \ 7obj-y := \
8 entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \ 8 entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \
9 sys_bfin.o time.o traps.o irqchip.o dma-mapping.o flat.o \ 9 sys_bfin.o time.o traps.o irqchip.o dma-mapping.o flat.o \
10 fixed_code.o 10 fixed_code.o cplbinit.o cacheinit.o
11 11
12obj-$(CONFIG_BF53x) += bfin_gpio.o 12obj-$(CONFIG_BF53x) += bfin_gpio.o
13obj-$(CONFIG_BF561) += bfin_gpio.o 13obj-$(CONFIG_BF561) += bfin_gpio.o
diff --git a/arch/blackfin/kernel/cacheinit.c b/arch/blackfin/kernel/cacheinit.c
new file mode 100644
index 000000000000..4d41a40e8133
--- /dev/null
+++ b/arch/blackfin/kernel/cacheinit.c
@@ -0,0 +1,66 @@
1/*
2 * Copyright 2004-2007 Analog Devices Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see the file COPYING, or write
16 * to the Free Software Foundation, Inc.,
17 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <linux/cpu.h>
21
22#include <asm/cacheflush.h>
23#include <asm/blackfin.h>
24#include <asm/cplbinit.h>
25
26#if defined(CONFIG_BLKFIN_CACHE)
27void bfin_icache_init(void)
28{
29 unsigned long *table = icplb_table;
30 unsigned long ctrl;
31 int i;
32
33 for (i = 0; i < MAX_CPLBS; i++) {
34 unsigned long addr = *table++;
35 unsigned long data = *table++;
36 if (addr == (unsigned long)-1)
37 break;
38 bfin_write32(ICPLB_ADDR0 + i * 4, addr);
39 bfin_write32(ICPLB_DATA0 + i * 4, data);
40 }
41 ctrl = bfin_read_IMEM_CONTROL();
42 ctrl |= IMC | ENICPLB;
43 bfin_write_IMEM_CONTROL(ctrl);
44}
45#endif
46
47#if defined(CONFIG_BLKFIN_DCACHE)
48void bfin_dcache_init(void)
49{
50 unsigned long *table = dcplb_table;
51 unsigned long ctrl;
52 int i;
53
54 for (i = 0; i < MAX_CPLBS; i++) {
55 unsigned long addr = *table++;
56 unsigned long data = *table++;
57 if (addr == (unsigned long)-1)
58 break;
59 bfin_write32(DCPLB_ADDR0 + i * 4, addr);
60 bfin_write32(DCPLB_DATA0 + i * 4, data);
61 }
62 ctrl = bfin_read_DMEM_CONTROL();
63 ctrl |= DMEM_CNTR;
64 bfin_write_DMEM_CONTROL(ctrl);
65}
66#endif
diff --git a/arch/blackfin/kernel/cplbinit.c b/arch/blackfin/kernel/cplbinit.c
new file mode 100644
index 000000000000..bbdb403fcb55
--- /dev/null
+++ b/arch/blackfin/kernel/cplbinit.c
@@ -0,0 +1,433 @@
1/*
2 * Blackfin CPLB initialization
3 *
4 * Copyright 2004-2007 Analog Devices Inc.
5 *
6 * Bugs: Enter bugs at http://blackfin.uclinux.org/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see the file COPYING, or write
20 * to the Free Software Foundation, Inc.,
21 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23#include <linux/module.h>
24
25#include <asm/blackfin.h>
26#include <asm/cplbinit.h>
27
28u_long icplb_table[MAX_CPLBS+1];
29u_long dcplb_table[MAX_CPLBS+1];
30
31#ifdef CONFIG_CPLB_SWITCH_TAB_L1
32u_long ipdt_table[MAX_SWITCH_I_CPLBS+1]__attribute__((l1_data));
33u_long dpdt_table[MAX_SWITCH_D_CPLBS+1]__attribute__((l1_data));
34
35#ifdef CONFIG_CPLB_INFO
36u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS]__attribute__((l1_data));
37u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS]__attribute__((l1_data));
38#endif /* CONFIG_CPLB_INFO */
39
40#else
41
42u_long ipdt_table[MAX_SWITCH_I_CPLBS+1];
43u_long dpdt_table[MAX_SWITCH_D_CPLBS+1];
44
45#ifdef CONFIG_CPLB_INFO
46u_long ipdt_swapcount_table[MAX_SWITCH_I_CPLBS];
47u_long dpdt_swapcount_table[MAX_SWITCH_D_CPLBS];
48#endif /* CONFIG_CPLB_INFO */
49
50#endif /*CONFIG_CPLB_SWITCH_TAB_L1*/
51
52struct s_cplb {
53 struct cplb_tab init_i;
54 struct cplb_tab init_d;
55 struct cplb_tab switch_i;
56 struct cplb_tab switch_d;
57};
58
59#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
60static struct cplb_desc cplb_data[] = {
61 {
62 .start = 0,
63 .end = SIZE_1K,
64 .psize = SIZE_1K,
65 .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
66 .i_conf = SDRAM_OOPS,
67 .d_conf = SDRAM_OOPS,
68#if defined(CONFIG_DEBUG_HUNT_FOR_ZERO)
69 .valid = 1,
70#else
71 .valid = 0,
72#endif
73 .name = "ZERO Pointer Saveguard",
74 },
75 {
76 .start = L1_CODE_START,
77 .end = L1_CODE_START + L1_CODE_LENGTH,
78 .psize = SIZE_4M,
79 .attr = INITIAL_T | SWITCH_T | I_CPLB,
80 .i_conf = L1_IMEMORY,
81 .d_conf = 0,
82 .valid = 1,
83 .name = "L1 I-Memory",
84 },
85 {
86 .start = L1_DATA_A_START,
87 .end = L1_DATA_B_START + L1_DATA_B_LENGTH,
88 .psize = SIZE_4M,
89 .attr = INITIAL_T | SWITCH_T | D_CPLB,
90 .i_conf = 0,
91 .d_conf = L1_DMEMORY,
92#if ((L1_DATA_A_LENGTH > 0) || (L1_DATA_B_LENGTH > 0))
93 .valid = 1,
94#else
95 .valid = 0,
96#endif
97 .name = "L1 D-Memory",
98 },
99 {
100 .start = 0,
101 .end = 0, /* dynamic */
102 .psize = 0,
103 .attr = INITIAL_T | SWITCH_T | I_CPLB | D_CPLB,
104 .i_conf = SDRAM_IGENERIC,
105 .d_conf = SDRAM_DGENERIC,
106 .valid = 1,
107 .name = "SDRAM Kernel",
108 },
109 {
110 .start = 0, /* dynamic */
111 .end = 0, /* dynamic */
112 .psize = 0,
113 .attr = INITIAL_T | SWITCH_T | D_CPLB,
114 .i_conf = SDRAM_IGENERIC,
115 .d_conf = SDRAM_DNON_CHBL,
116 .valid = 1,
117 .name = "SDRAM RAM MTD",
118 },
119 {
120 .start = 0, /* dynamic */
121 .end = 0, /* dynamic */
122 .psize = SIZE_1M,
123 .attr = INITIAL_T | SWITCH_T | D_CPLB,
124 .d_conf = SDRAM_DNON_CHBL,
125 .valid = 1,
126 .name = "SDRAM Uncached DMA ZONE",
127 },
128 {
129 .start = 0, /* dynamic */
130 .end = 0, /* dynamic */
131 .psize = 0,
132 .attr = SWITCH_T | D_CPLB,
133 .i_conf = 0, /* dynamic */
134 .d_conf = 0, /* dynamic */
135 .valid = 1,
136 .name = "SDRAM Reserved Memory",
137 },
138 {
139 .start = ASYNC_BANK0_BASE,
140 .end = ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE,
141 .psize = 0,
142 .attr = SWITCH_T | D_CPLB,
143 .d_conf = SDRAM_EBIU,
144 .valid = 1,
145 .name = "ASYNC Memory",
146 },
147 {
148#if defined(CONFIG_BF561)
149 .start = L2_SRAM,
150 .end = L2_SRAM_END,
151 .psize = SIZE_1M,
152 .attr = SWITCH_T | D_CPLB,
153 .i_conf = L2_MEMORY,
154 .d_conf = L2_MEMORY,
155 .valid = 1,
156#else
157 .valid = 0,
158#endif
159 .name = "L2 Memory",
160 }
161};
162
163static u16 __init lock_kernel_check(u32 start, u32 end)
164{
165 if ((start <= (u32) _stext && end >= (u32) _end)
166 || (start >= (u32) _stext && end <= (u32) _end))
167 return IN_KERNEL;
168 return 0;
169}
170
171static unsigned short __init
172fill_cplbtab(struct cplb_tab *table,
173 unsigned long start, unsigned long end,
174 unsigned long block_size, unsigned long cplb_data)
175{
176 int i;
177
178 switch (block_size) {
179 case SIZE_4M:
180 i = 3;
181 break;
182 case SIZE_1M:
183 i = 2;
184 break;
185 case SIZE_4K:
186 i = 1;
187 break;
188 case SIZE_1K:
189 default:
190 i = 0;
191 break;
192 }
193
194 cplb_data = (cplb_data & ~(3 << 16)) | (i << 16);
195
196 while ((start < end) && (table->pos < table->size)) {
197
198 table->tab[table->pos++] = start;
199
200 if (lock_kernel_check(start, start + block_size) == IN_KERNEL)
201 table->tab[table->pos++] =
202 cplb_data | CPLB_LOCK | CPLB_DIRTY;
203 else
204 table->tab[table->pos++] = cplb_data;
205
206 start += block_size;
207 }
208 return 0;
209}
210
211static unsigned short __init
212close_cplbtab(struct cplb_tab *table)
213{
214
215 while (table->pos < table->size) {
216
217 table->tab[table->pos++] = 0;
218 table->tab[table->pos++] = 0; /* !CPLB_VALID */
219 }
220 return 0;
221}
222
223/* helper function */
224static void __fill_code_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end)
225{
226 if (cplb_data[i].psize) {
227 fill_cplbtab(t,
228 cplb_data[i].start,
229 cplb_data[i].end,
230 cplb_data[i].psize,
231 cplb_data[i].i_conf);
232 } else {
233#if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263))
234 if (i == SDRAM_KERN) {
235 fill_cplbtab(t,
236 cplb_data[i].start,
237 cplb_data[i].end,
238 SIZE_4M,
239 cplb_data[i].i_conf);
240 } else
241#endif
242 {
243 fill_cplbtab(t,
244 cplb_data[i].start,
245 a_start,
246 SIZE_1M,
247 cplb_data[i].i_conf);
248 fill_cplbtab(t,
249 a_start,
250 a_end,
251 SIZE_4M,
252 cplb_data[i].i_conf);
253 fill_cplbtab(t, a_end,
254 cplb_data[i].end,
255 SIZE_1M,
256 cplb_data[i].i_conf);
257 }
258 }
259}
260
261static void __fill_data_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end)
262{
263 if (cplb_data[i].psize) {
264 fill_cplbtab(t,
265 cplb_data[i].start,
266 cplb_data[i].end,
267 cplb_data[i].psize,
268 cplb_data[i].d_conf);
269 } else {
270 fill_cplbtab(t,
271 cplb_data[i].start,
272 a_start, SIZE_1M,
273 cplb_data[i].d_conf);
274 fill_cplbtab(t, a_start,
275 a_end, SIZE_4M,
276 cplb_data[i].d_conf);
277 fill_cplbtab(t, a_end,
278 cplb_data[i].end,
279 SIZE_1M,
280 cplb_data[i].d_conf);
281 }
282}
283
284void __init generate_cpl_tables(void)
285{
286
287 u16 i, j, process;
288 u32 a_start, a_end, as, ae, as_1m;
289
290 struct cplb_tab *t_i = NULL;
291 struct cplb_tab *t_d = NULL;
292 struct s_cplb cplb;
293
294 cplb.init_i.size = MAX_CPLBS;
295 cplb.init_d.size = MAX_CPLBS;
296 cplb.switch_i.size = MAX_SWITCH_I_CPLBS;
297 cplb.switch_d.size = MAX_SWITCH_D_CPLBS;
298
299 cplb.init_i.pos = 0;
300 cplb.init_d.pos = 0;
301 cplb.switch_i.pos = 0;
302 cplb.switch_d.pos = 0;
303
304 cplb.init_i.tab = icplb_table;
305 cplb.init_d.tab = dcplb_table;
306 cplb.switch_i.tab = ipdt_table;
307 cplb.switch_d.tab = dpdt_table;
308
309 cplb_data[SDRAM_KERN].end = memory_end;
310
311#ifdef CONFIG_MTD_UCLINUX
312 cplb_data[SDRAM_RAM_MTD].start = memory_mtd_start;
313 cplb_data[SDRAM_RAM_MTD].end = memory_mtd_start + mtd_size;
314 cplb_data[SDRAM_RAM_MTD].valid = mtd_size > 0;
315# if defined(CONFIG_ROMFS_FS)
316 cplb_data[SDRAM_RAM_MTD].attr |= I_CPLB;
317
318 /*
319 * The ROMFS_FS size is often not multiple of 1MB.
320 * This can cause multiple CPLB sets covering the same memory area.
321 * This will then cause multiple CPLB hit exceptions.
322 * Workaround: We ensure a contiguous memory area by extending the kernel
323 * memory section over the mtd section.
324 * For ROMFS_FS memory must be covered with ICPLBs anyways.
325 * So there is no difference between kernel and mtd memory setup.
326 */
327
328 cplb_data[SDRAM_KERN].end = memory_mtd_start + mtd_size;;
329 cplb_data[SDRAM_RAM_MTD].valid = 0;
330
331# endif
332#else
333 cplb_data[SDRAM_RAM_MTD].valid = 0;
334#endif
335
336 cplb_data[SDRAM_DMAZ].start = _ramend - DMA_UNCACHED_REGION;
337 cplb_data[SDRAM_DMAZ].end = _ramend;
338
339 cplb_data[RES_MEM].start = _ramend;
340 cplb_data[RES_MEM].end = physical_mem_end;
341
342 if (reserved_mem_dcache_on)
343 cplb_data[RES_MEM].d_conf = SDRAM_DGENERIC;
344 else
345 cplb_data[RES_MEM].d_conf = SDRAM_DNON_CHBL;
346
347 if (reserved_mem_icache_on)
348 cplb_data[RES_MEM].i_conf = SDRAM_IGENERIC;
349 else
350 cplb_data[RES_MEM].i_conf = SDRAM_INON_CHBL;
351
352 for (i = ZERO_P; i <= L2_MEM; i++) {
353 if (!cplb_data[i].valid)
354 continue;
355
356 as_1m = cplb_data[i].start % SIZE_1M;
357
358 /* We need to make sure all sections are properly 1M aligned
359 * However between Kernel Memory and the Kernel mtd section, depending on the
360 * rootfs size, there can be overlapping memory areas.
361 */
362
363 if (as_1m && i != L1I_MEM && i != L1D_MEM) {
364#ifdef CONFIG_MTD_UCLINUX
365 if (i == SDRAM_RAM_MTD) {
366 if ((cplb_data[SDRAM_KERN].end + 1) > cplb_data[SDRAM_RAM_MTD].start)
367 cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M)) + SIZE_1M;
368 else
369 cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M));
370 } else
371#endif
372 printk(KERN_WARNING "Unaligned Start of %s at 0x%X\n",
373 cplb_data[i].name, cplb_data[i].start);
374 }
375
376 as = cplb_data[i].start % SIZE_4M;
377 ae = cplb_data[i].end % SIZE_4M;
378
379 if (as)
380 a_start = cplb_data[i].start + (SIZE_4M - (as));
381 else
382 a_start = cplb_data[i].start;
383
384 a_end = cplb_data[i].end - ae;
385
386 for (j = INITIAL_T; j <= SWITCH_T; j++) {
387
388 switch (j) {
389 case INITIAL_T:
390 if (cplb_data[i].attr & INITIAL_T) {
391 t_i = &cplb.init_i;
392 t_d = &cplb.init_d;
393 process = 1;
394 } else
395 process = 0;
396 break;
397 case SWITCH_T:
398 if (cplb_data[i].attr & SWITCH_T) {
399 t_i = &cplb.switch_i;
400 t_d = &cplb.switch_d;
401 process = 1;
402 } else
403 process = 0;
404 break;
405 default:
406 process = 0;
407 break;
408 }
409
410 if (!process)
411 continue;
412 if (cplb_data[i].attr & I_CPLB)
413 __fill_code_cplbtab(t_i, i, a_start, a_end);
414
415 if (cplb_data[i].attr & D_CPLB)
416 __fill_data_cplbtab(t_d, i, a_start, a_end);
417 }
418 }
419
420/* close tables */
421
422 close_cplbtab(&cplb.init_i);
423 close_cplbtab(&cplb.init_d);
424
425 cplb.init_i.tab[cplb.init_i.pos] = -1;
426 cplb.init_d.tab[cplb.init_d.pos] = -1;
427 cplb.switch_i.tab[cplb.switch_i.pos] = -1;
428 cplb.switch_d.tab[cplb.switch_d.pos] = -1;
429
430}
431
432#endif
433
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index 534227f4da30..07c1cfdc958e 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -64,10 +64,6 @@ EXPORT_SYMBOL(mtd_size);
64 64
65char __initdata command_line[COMMAND_LINE_SIZE]; 65char __initdata command_line[COMMAND_LINE_SIZE];
66 66
67#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
68static void generate_cpl_tables(void);
69#endif
70
71void __init bf53x_cache_init(void) 67void __init bf53x_cache_init(void)
72{ 68{
73#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE) 69#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
@@ -401,8 +397,6 @@ void __init setup_arch(char **cmdline_p)
401 _bfin_swrst = bfin_read_SWRST(); 397 _bfin_swrst = bfin_read_SWRST();
402#endif 398#endif
403 399
404 bf53x_cache_init();
405
406 printk(KERN_INFO "Hardware Trace Enabled\n"); 400 printk(KERN_INFO "Hardware Trace Enabled\n");
407 bfin_write_TBUFCTL(0x03); 401 bfin_write_TBUFCTL(0x03);
408 402
@@ -426,6 +420,8 @@ void __init setup_arch(char **cmdline_p)
426 != ATOMIC_AND32 - FIXED_CODE_START); 420 != ATOMIC_AND32 - FIXED_CODE_START);
427 BUG_ON((char *)&atomic_xor32 - (char *)&fixed_code_start 421 BUG_ON((char *)&atomic_xor32 - (char *)&fixed_code_start
428 != ATOMIC_XOR32 - FIXED_CODE_START); 422 != ATOMIC_XOR32 - FIXED_CODE_START);
423
424 bf53x_cache_init();
429} 425}
430 426
431static int __init topology_init(void) 427static int __init topology_init(void)
@@ -443,287 +439,6 @@ static int __init topology_init(void)
443 439
444subsys_initcall(topology_init); 440subsys_initcall(topology_init);
445 441
446#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
447static u16 __init lock_kernel_check(u32 start, u32 end)
448{
449 if ((start <= (u32) _stext && end >= (u32) _end)
450 || (start >= (u32) _stext && end <= (u32) _end))
451 return IN_KERNEL;
452 return 0;
453}
454
455static unsigned short __init
456fill_cplbtab(struct cplb_tab *table,
457 unsigned long start, unsigned long end,
458 unsigned long block_size, unsigned long cplb_data)
459{
460 int i;
461
462 switch (block_size) {
463 case SIZE_4M:
464 i = 3;
465 break;
466 case SIZE_1M:
467 i = 2;
468 break;
469 case SIZE_4K:
470 i = 1;
471 break;
472 case SIZE_1K:
473 default:
474 i = 0;
475 break;
476 }
477
478 cplb_data = (cplb_data & ~(3 << 16)) | (i << 16);
479
480 while ((start < end) && (table->pos < table->size)) {
481
482 table->tab[table->pos++] = start;
483
484 if (lock_kernel_check(start, start + block_size) == IN_KERNEL)
485 table->tab[table->pos++] =
486 cplb_data | CPLB_LOCK | CPLB_DIRTY;
487 else
488 table->tab[table->pos++] = cplb_data;
489
490 start += block_size;
491 }
492 return 0;
493}
494
495static unsigned short __init
496close_cplbtab(struct cplb_tab *table)
497{
498
499 while (table->pos < table->size) {
500
501 table->tab[table->pos++] = 0;
502 table->tab[table->pos++] = 0; /* !CPLB_VALID */
503 }
504 return 0;
505}
506
507/* helper function */
508static void __fill_code_cplbtab(struct cplb_tab *t, int i,
509 u32 a_start, u32 a_end)
510{
511 if (cplb_data[i].psize) {
512 fill_cplbtab(t,
513 cplb_data[i].start,
514 cplb_data[i].end,
515 cplb_data[i].psize,
516 cplb_data[i].i_conf);
517 } else {
518#if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263))
519 if (i == SDRAM_KERN) {
520 fill_cplbtab(t,
521 cplb_data[i].start,
522 cplb_data[i].end,
523 SIZE_4M,
524 cplb_data[i].i_conf);
525 } else
526#endif
527 {
528 fill_cplbtab(t,
529 cplb_data[i].start,
530 a_start,
531 SIZE_1M,
532 cplb_data[i].i_conf);
533 fill_cplbtab(t,
534 a_start,
535 a_end,
536 SIZE_4M,
537 cplb_data[i].i_conf);
538 fill_cplbtab(t, a_end,
539 cplb_data[i].end,
540 SIZE_1M,
541 cplb_data[i].i_conf);
542 }
543 }
544}
545
546static void __fill_data_cplbtab(struct cplb_tab *t, int i,
547 u32 a_start, u32 a_end)
548{
549 if (cplb_data[i].psize) {
550 fill_cplbtab(t,
551 cplb_data[i].start,
552 cplb_data[i].end,
553 cplb_data[i].psize,
554 cplb_data[i].d_conf);
555 } else {
556 fill_cplbtab(t,
557 cplb_data[i].start,
558 a_start, SIZE_1M,
559 cplb_data[i].d_conf);
560 fill_cplbtab(t, a_start,
561 a_end, SIZE_4M,
562 cplb_data[i].d_conf);
563 fill_cplbtab(t, a_end,
564 cplb_data[i].end,
565 SIZE_1M,
566 cplb_data[i].d_conf);
567 }
568}
569static void __init generate_cpl_tables(void)
570{
571
572 u16 i, j, process;
573 u32 a_start, a_end, as, ae, as_1m;
574
575 struct cplb_tab *t_i = NULL;
576 struct cplb_tab *t_d = NULL;
577 struct s_cplb cplb;
578
579 cplb.init_i.size = MAX_CPLBS;
580 cplb.init_d.size = MAX_CPLBS;
581 cplb.switch_i.size = MAX_SWITCH_I_CPLBS;
582 cplb.switch_d.size = MAX_SWITCH_D_CPLBS;
583
584 cplb.init_i.pos = 0;
585 cplb.init_d.pos = 0;
586 cplb.switch_i.pos = 0;
587 cplb.switch_d.pos = 0;
588
589 cplb.init_i.tab = icplb_table;
590 cplb.init_d.tab = dcplb_table;
591 cplb.switch_i.tab = ipdt_table;
592 cplb.switch_d.tab = dpdt_table;
593
594 cplb_data[SDRAM_KERN].end = memory_end;
595
596#ifdef CONFIG_MTD_UCLINUX
597 cplb_data[SDRAM_RAM_MTD].start = memory_mtd_start;
598 cplb_data[SDRAM_RAM_MTD].end = memory_mtd_start + mtd_size;
599 cplb_data[SDRAM_RAM_MTD].valid = mtd_size > 0;
600# if defined(CONFIG_ROMFS_FS)
601 cplb_data[SDRAM_RAM_MTD].attr |= I_CPLB;
602
603 /*
604 * The ROMFS_FS size is often not multiple of 1MB.
605 * This can cause multiple CPLB sets covering the same memory area.
606 * This will then cause multiple CPLB hit exceptions.
607 * Workaround: We ensure a contiguous memory area by extending the kernel
608 * memory section over the mtd section.
609 * For ROMFS_FS memory must be covered with ICPLBs anyways.
610 * So there is no difference between kernel and mtd memory setup.
611 */
612
613 cplb_data[SDRAM_KERN].end = memory_mtd_start + mtd_size;;
614 cplb_data[SDRAM_RAM_MTD].valid = 0;
615
616# endif
617#else
618 cplb_data[SDRAM_RAM_MTD].valid = 0;
619#endif
620
621 cplb_data[SDRAM_DMAZ].start = _ramend - DMA_UNCACHED_REGION;
622 cplb_data[SDRAM_DMAZ].end = _ramend;
623
624 cplb_data[RES_MEM].start = _ramend;
625 cplb_data[RES_MEM].end = physical_mem_end;
626
627 if (reserved_mem_dcache_on)
628 cplb_data[RES_MEM].d_conf = SDRAM_DGENERIC;
629 else
630 cplb_data[RES_MEM].d_conf = SDRAM_DNON_CHBL;
631
632 if (reserved_mem_icache_on)
633 cplb_data[RES_MEM].i_conf = SDRAM_IGENERIC;
634 else
635 cplb_data[RES_MEM].i_conf = SDRAM_INON_CHBL;
636
637 for (i = ZERO_P; i <= L2_MEM; i++) {
638 if (!cplb_data[i].valid)
639 continue;
640
641 as_1m = cplb_data[i].start % SIZE_1M;
642
643 /*
644 * We need to make sure all sections are properly 1M aligned
645 * However between Kernel Memory and the Kernel mtd section,
646 * depending on the rootfs size, there can be overlapping
647 * memory areas.
648 */
649
650 if (as_1m && i != L1I_MEM && i != L1D_MEM) {
651#ifdef CONFIG_MTD_UCLINUX
652 if (i == SDRAM_RAM_MTD) {
653 if ((cplb_data[SDRAM_KERN].end + 1) >
654 cplb_data[SDRAM_RAM_MTD].start)
655 cplb_data[SDRAM_RAM_MTD].start =
656 (cplb_data[i].start &
657 (-2*SIZE_1M)) + SIZE_1M;
658 else
659 cplb_data[SDRAM_RAM_MTD].start =
660 (cplb_data[i].start &
661 (-2*SIZE_1M));
662 } else
663#endif
664 printk(KERN_WARNING
665 "Unaligned Start of %s at 0x%X\n",
666 cplb_data[i].name, cplb_data[i].start);
667 }
668
669 as = cplb_data[i].start % SIZE_4M;
670 ae = cplb_data[i].end % SIZE_4M;
671
672 if (as)
673 a_start = cplb_data[i].start + (SIZE_4M - (as));
674 else
675 a_start = cplb_data[i].start;
676
677 a_end = cplb_data[i].end - ae;
678
679 for (j = INITIAL_T; j <= SWITCH_T; j++) {
680
681 switch (j) {
682 case INITIAL_T:
683 if (cplb_data[i].attr & INITIAL_T) {
684 t_i = &cplb.init_i;
685 t_d = &cplb.init_d;
686 process = 1;
687 } else
688 process = 0;
689 break;
690 case SWITCH_T:
691 if (cplb_data[i].attr & SWITCH_T) {
692 t_i = &cplb.switch_i;
693 t_d = &cplb.switch_d;
694 process = 1;
695 } else
696 process = 0;
697 break;
698 default:
699 process = 0;
700 break;
701 }
702
703 if (!process)
704 continue;
705 if (cplb_data[i].attr & I_CPLB)
706 __fill_code_cplbtab(t_i, i, a_start, a_end);
707
708 if (cplb_data[i].attr & D_CPLB)
709 __fill_data_cplbtab(t_d, i, a_start, a_end);
710 }
711 }
712
713/* close tables */
714
715 close_cplbtab(&cplb.init_i);
716 close_cplbtab(&cplb.init_d);
717
718 cplb.init_i.tab[cplb.init_i.pos] = -1;
719 cplb.init_d.tab[cplb.init_d.pos] = -1;
720 cplb.switch_i.tab[cplb.switch_i.pos] = -1;
721 cplb.switch_d.tab[cplb.switch_d.pos] = -1;
722
723}
724
725#endif
726
727static u_long get_vco(void) 442static u_long get_vco(void)
728{ 443{
729 u_long msel; 444 u_long msel;