diff options
Diffstat (limited to 'arch/blackfin/kernel/setup.c')
-rw-r--r-- | arch/blackfin/kernel/setup.c | 368 |
1 files changed, 56 insertions, 312 deletions
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 83060f98d15d..f59dcee7bae3 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <asm/cacheflush.h> | 42 | #include <asm/cacheflush.h> |
43 | #include <asm/blackfin.h> | 43 | #include <asm/blackfin.h> |
44 | #include <asm/cplbinit.h> | 44 | #include <asm/cplbinit.h> |
45 | #include <asm/fixed_code.h> | ||
45 | 46 | ||
46 | u16 _bfin_swrst; | 47 | u16 _bfin_swrst; |
47 | 48 | ||
@@ -63,10 +64,6 @@ EXPORT_SYMBOL(mtd_size); | |||
63 | 64 | ||
64 | char __initdata command_line[COMMAND_LINE_SIZE]; | 65 | char __initdata command_line[COMMAND_LINE_SIZE]; |
65 | 66 | ||
66 | #if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE) | ||
67 | static void generate_cpl_tables(void); | ||
68 | #endif | ||
69 | |||
70 | void __init bf53x_cache_init(void) | 67 | void __init bf53x_cache_init(void) |
71 | { | 68 | { |
72 | #if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE) | 69 | #if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE) |
@@ -197,6 +194,17 @@ void __init setup_arch(char **cmdline_p) | |||
197 | /* this give a chance to get printk() working before crash. */ | 194 | /* this give a chance to get printk() working before crash. */ |
198 | #endif | 195 | #endif |
199 | 196 | ||
197 | printk(KERN_INFO "Hardware Trace "); | ||
198 | if (bfin_read_TBUFCTL() & 0x1 ) | ||
199 | printk("Active "); | ||
200 | else | ||
201 | printk("Off "); | ||
202 | if (bfin_read_TBUFCTL() & 0x2) | ||
203 | printk("and Enabled\n"); | ||
204 | else | ||
205 | printk("and Disabled\n"); | ||
206 | |||
207 | |||
200 | #if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH) | 208 | #if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH) |
201 | /* we need to initialize the Flashrom device here since we might | 209 | /* we need to initialize the Flashrom device here since we might |
202 | * do things with flash early on in the boot | 210 | * do things with flash early on in the boot |
@@ -354,15 +362,15 @@ void __init setup_arch(char **cmdline_p) | |||
354 | , _stext, _etext, | 362 | , _stext, _etext, |
355 | __start_rodata, __end_rodata, | 363 | __start_rodata, __end_rodata, |
356 | _sdata, _edata, | 364 | _sdata, _edata, |
357 | (void*)&init_thread_union, (void*)((int)(&init_thread_union) + 0x2000), | 365 | (void *)&init_thread_union, (void *)((int)(&init_thread_union) + 0x2000), |
358 | __init_begin, __init_end, | 366 | __init_begin, __init_end, |
359 | __bss_start, __bss_stop, | 367 | __bss_start, __bss_stop, |
360 | (void*)_ramstart, (void*)memory_end | 368 | (void *)_ramstart, (void *)memory_end |
361 | #ifdef CONFIG_MTD_UCLINUX | 369 | #ifdef CONFIG_MTD_UCLINUX |
362 | , (void*)memory_mtd_start, (void*)(memory_mtd_start + mtd_size) | 370 | , (void *)memory_mtd_start, (void *)(memory_mtd_start + mtd_size) |
363 | #endif | 371 | #endif |
364 | #if DMA_UNCACHED_REGION > 0 | 372 | #if DMA_UNCACHED_REGION > 0 |
365 | , (void*)(_ramend - DMA_UNCACHED_REGION), (void*)(_ramend) | 373 | , (void *)(_ramend - DMA_UNCACHED_REGION), (void *)(_ramend) |
366 | #endif | 374 | #endif |
367 | ); | 375 | ); |
368 | 376 | ||
@@ -388,11 +396,11 @@ void __init setup_arch(char **cmdline_p) | |||
388 | /* check the size of the l1 area */ | 396 | /* check the size of the l1 area */ |
389 | l1_length = _etext_l1 - _stext_l1; | 397 | l1_length = _etext_l1 - _stext_l1; |
390 | if (l1_length > L1_CODE_LENGTH) | 398 | if (l1_length > L1_CODE_LENGTH) |
391 | panic("L1 memory overflow\n"); | 399 | panic("L1 code memory overflow\n"); |
392 | 400 | ||
393 | l1_length = _ebss_l1 - _sdata_l1; | 401 | l1_length = _ebss_l1 - _sdata_l1; |
394 | if (l1_length > L1_DATA_A_LENGTH) | 402 | if (l1_length > L1_DATA_A_LENGTH) |
395 | panic("L1 memory overflow\n"); | 403 | panic("L1 data memory overflow\n"); |
396 | 404 | ||
397 | #ifdef BF561_FAMILY | 405 | #ifdef BF561_FAMILY |
398 | _bfin_swrst = bfin_read_SICA_SWRST(); | 406 | _bfin_swrst = bfin_read_SICA_SWRST(); |
@@ -400,10 +408,28 @@ void __init setup_arch(char **cmdline_p) | |||
400 | _bfin_swrst = bfin_read_SWRST(); | 408 | _bfin_swrst = bfin_read_SWRST(); |
401 | #endif | 409 | #endif |
402 | 410 | ||
403 | bf53x_cache_init(); | 411 | /* Copy atomic sequences to their fixed location, and sanity check that |
412 | these locations are the ones that we advertise to userspace. */ | ||
413 | memcpy((void *)FIXED_CODE_START, &fixed_code_start, | ||
414 | FIXED_CODE_END - FIXED_CODE_START); | ||
415 | BUG_ON((char *)&sigreturn_stub - (char *)&fixed_code_start | ||
416 | != SIGRETURN_STUB - FIXED_CODE_START); | ||
417 | BUG_ON((char *)&atomic_xchg32 - (char *)&fixed_code_start | ||
418 | != ATOMIC_XCHG32 - FIXED_CODE_START); | ||
419 | BUG_ON((char *)&atomic_cas32 - (char *)&fixed_code_start | ||
420 | != ATOMIC_CAS32 - FIXED_CODE_START); | ||
421 | BUG_ON((char *)&atomic_add32 - (char *)&fixed_code_start | ||
422 | != ATOMIC_ADD32 - FIXED_CODE_START); | ||
423 | BUG_ON((char *)&atomic_sub32 - (char *)&fixed_code_start | ||
424 | != ATOMIC_SUB32 - FIXED_CODE_START); | ||
425 | BUG_ON((char *)&atomic_ior32 - (char *)&fixed_code_start | ||
426 | != ATOMIC_IOR32 - FIXED_CODE_START); | ||
427 | BUG_ON((char *)&atomic_and32 - (char *)&fixed_code_start | ||
428 | != ATOMIC_AND32 - FIXED_CODE_START); | ||
429 | BUG_ON((char *)&atomic_xor32 - (char *)&fixed_code_start | ||
430 | != ATOMIC_XOR32 - FIXED_CODE_START); | ||
404 | 431 | ||
405 | printk(KERN_INFO "Hardware Trace Enabled\n"); | 432 | bf53x_cache_init(); |
406 | bfin_write_TBUFCTL(0x03); | ||
407 | } | 433 | } |
408 | 434 | ||
409 | static int __init topology_init(void) | 435 | static int __init topology_init(void) |
@@ -421,286 +447,6 @@ static int __init topology_init(void) | |||
421 | 447 | ||
422 | subsys_initcall(topology_init); | 448 | subsys_initcall(topology_init); |
423 | 449 | ||
424 | #if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE) | ||
425 | static u16 __init lock_kernel_check(u32 start, u32 end) | ||
426 | { | ||
427 | if ((start <= (u32) _stext && end >= (u32) _end) | ||
428 | || (start >= (u32) _stext && end <= (u32) _end)) | ||
429 | return IN_KERNEL; | ||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | static unsigned short __init | ||
434 | fill_cplbtab(struct cplb_tab *table, | ||
435 | unsigned long start, unsigned long end, | ||
436 | unsigned long block_size, unsigned long cplb_data) | ||
437 | { | ||
438 | int i; | ||
439 | |||
440 | switch (block_size) { | ||
441 | case SIZE_4M: | ||
442 | i = 3; | ||
443 | break; | ||
444 | case SIZE_1M: | ||
445 | i = 2; | ||
446 | break; | ||
447 | case SIZE_4K: | ||
448 | i = 1; | ||
449 | break; | ||
450 | case SIZE_1K: | ||
451 | default: | ||
452 | i = 0; | ||
453 | break; | ||
454 | } | ||
455 | |||
456 | cplb_data = (cplb_data & ~(3 << 16)) | (i << 16); | ||
457 | |||
458 | while ((start < end) && (table->pos < table->size)) { | ||
459 | |||
460 | table->tab[table->pos++] = start; | ||
461 | |||
462 | if (lock_kernel_check(start, start + block_size) == IN_KERNEL) | ||
463 | table->tab[table->pos++] = | ||
464 | cplb_data | CPLB_LOCK | CPLB_DIRTY; | ||
465 | else | ||
466 | table->tab[table->pos++] = cplb_data; | ||
467 | |||
468 | start += block_size; | ||
469 | } | ||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static unsigned short __init | ||
474 | close_cplbtab(struct cplb_tab *table) | ||
475 | { | ||
476 | |||
477 | while (table->pos < table->size) { | ||
478 | |||
479 | table->tab[table->pos++] = 0; | ||
480 | table->tab[table->pos++] = 0; /* !CPLB_VALID */ | ||
481 | } | ||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | /* helper function */ | ||
486 | static void __fill_code_cplbtab(struct cplb_tab *t, int i, | ||
487 | u32 a_start, u32 a_end) | ||
488 | { | ||
489 | if (cplb_data[i].psize) { | ||
490 | fill_cplbtab(t, | ||
491 | cplb_data[i].start, | ||
492 | cplb_data[i].end, | ||
493 | cplb_data[i].psize, | ||
494 | cplb_data[i].i_conf); | ||
495 | } else { | ||
496 | #if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263)) | ||
497 | if (i == SDRAM_KERN) { | ||
498 | fill_cplbtab(t, | ||
499 | cplb_data[i].start, | ||
500 | cplb_data[i].end, | ||
501 | SIZE_4M, | ||
502 | cplb_data[i].i_conf); | ||
503 | } else { | ||
504 | #endif | ||
505 | fill_cplbtab(t, | ||
506 | cplb_data[i].start, | ||
507 | a_start, | ||
508 | SIZE_1M, | ||
509 | cplb_data[i].i_conf); | ||
510 | fill_cplbtab(t, | ||
511 | a_start, | ||
512 | a_end, | ||
513 | SIZE_4M, | ||
514 | cplb_data[i].i_conf); | ||
515 | fill_cplbtab(t, a_end, | ||
516 | cplb_data[i].end, | ||
517 | SIZE_1M, | ||
518 | cplb_data[i].i_conf); | ||
519 | } | ||
520 | } | ||
521 | } | ||
522 | |||
523 | static void __fill_data_cplbtab(struct cplb_tab *t, int i, | ||
524 | u32 a_start, u32 a_end) | ||
525 | { | ||
526 | if (cplb_data[i].psize) { | ||
527 | fill_cplbtab(t, | ||
528 | cplb_data[i].start, | ||
529 | cplb_data[i].end, | ||
530 | cplb_data[i].psize, | ||
531 | cplb_data[i].d_conf); | ||
532 | } else { | ||
533 | fill_cplbtab(t, | ||
534 | cplb_data[i].start, | ||
535 | a_start, SIZE_1M, | ||
536 | cplb_data[i].d_conf); | ||
537 | fill_cplbtab(t, a_start, | ||
538 | a_end, SIZE_4M, | ||
539 | cplb_data[i].d_conf); | ||
540 | fill_cplbtab(t, a_end, | ||
541 | cplb_data[i].end, | ||
542 | SIZE_1M, | ||
543 | cplb_data[i].d_conf); | ||
544 | } | ||
545 | } | ||
546 | static void __init generate_cpl_tables(void) | ||
547 | { | ||
548 | |||
549 | u16 i, j, process; | ||
550 | u32 a_start, a_end, as, ae, as_1m; | ||
551 | |||
552 | struct cplb_tab *t_i = NULL; | ||
553 | struct cplb_tab *t_d = NULL; | ||
554 | struct s_cplb cplb; | ||
555 | |||
556 | cplb.init_i.size = MAX_CPLBS; | ||
557 | cplb.init_d.size = MAX_CPLBS; | ||
558 | cplb.switch_i.size = MAX_SWITCH_I_CPLBS; | ||
559 | cplb.switch_d.size = MAX_SWITCH_D_CPLBS; | ||
560 | |||
561 | cplb.init_i.pos = 0; | ||
562 | cplb.init_d.pos = 0; | ||
563 | cplb.switch_i.pos = 0; | ||
564 | cplb.switch_d.pos = 0; | ||
565 | |||
566 | cplb.init_i.tab = icplb_table; | ||
567 | cplb.init_d.tab = dcplb_table; | ||
568 | cplb.switch_i.tab = ipdt_table; | ||
569 | cplb.switch_d.tab = dpdt_table; | ||
570 | |||
571 | cplb_data[SDRAM_KERN].end = memory_end; | ||
572 | |||
573 | #ifdef CONFIG_MTD_UCLINUX | ||
574 | cplb_data[SDRAM_RAM_MTD].start = memory_mtd_start; | ||
575 | cplb_data[SDRAM_RAM_MTD].end = memory_mtd_start + mtd_size; | ||
576 | cplb_data[SDRAM_RAM_MTD].valid = mtd_size > 0; | ||
577 | # if defined(CONFIG_ROMFS_FS) | ||
578 | cplb_data[SDRAM_RAM_MTD].attr |= I_CPLB; | ||
579 | |||
580 | /* | ||
581 | * The ROMFS_FS size is often not multiple of 1MB. | ||
582 | * This can cause multiple CPLB sets covering the same memory area. | ||
583 | * This will then cause multiple CPLB hit exceptions. | ||
584 | * Workaround: We ensure a contiguous memory area by extending the kernel | ||
585 | * memory section over the mtd section. | ||
586 | * For ROMFS_FS memory must be covered with ICPLBs anyways. | ||
587 | * So there is no difference between kernel and mtd memory setup. | ||
588 | */ | ||
589 | |||
590 | cplb_data[SDRAM_KERN].end = memory_mtd_start + mtd_size;; | ||
591 | cplb_data[SDRAM_RAM_MTD].valid = 0; | ||
592 | |||
593 | # endif | ||
594 | #else | ||
595 | cplb_data[SDRAM_RAM_MTD].valid = 0; | ||
596 | #endif | ||
597 | |||
598 | cplb_data[SDRAM_DMAZ].start = _ramend - DMA_UNCACHED_REGION; | ||
599 | cplb_data[SDRAM_DMAZ].end = _ramend; | ||
600 | |||
601 | cplb_data[RES_MEM].start = _ramend; | ||
602 | cplb_data[RES_MEM].end = physical_mem_end; | ||
603 | |||
604 | if (reserved_mem_dcache_on) | ||
605 | cplb_data[RES_MEM].d_conf = SDRAM_DGENERIC; | ||
606 | else | ||
607 | cplb_data[RES_MEM].d_conf = SDRAM_DNON_CHBL; | ||
608 | |||
609 | if (reserved_mem_icache_on) | ||
610 | cplb_data[RES_MEM].i_conf = SDRAM_IGENERIC; | ||
611 | else | ||
612 | cplb_data[RES_MEM].i_conf = SDRAM_INON_CHBL; | ||
613 | |||
614 | for (i = ZERO_P; i <= L2_MEM; i++) { | ||
615 | if (!cplb_data[i].valid) | ||
616 | continue; | ||
617 | |||
618 | as_1m = cplb_data[i].start % SIZE_1M; | ||
619 | |||
620 | /* | ||
621 | * We need to make sure all sections are properly 1M aligned | ||
622 | * However between Kernel Memory and the Kernel mtd section, | ||
623 | * depending on the rootfs size, there can be overlapping | ||
624 | * memory areas. | ||
625 | */ | ||
626 | |||
627 | if (as_1m && i != L1I_MEM && i != L1D_MEM) { | ||
628 | #ifdef CONFIG_MTD_UCLINUX | ||
629 | if (i == SDRAM_RAM_MTD) { | ||
630 | if ((cplb_data[SDRAM_KERN].end + 1) > | ||
631 | cplb_data[SDRAM_RAM_MTD].start) | ||
632 | cplb_data[SDRAM_RAM_MTD].start = | ||
633 | (cplb_data[i].start & | ||
634 | (-2*SIZE_1M)) + SIZE_1M; | ||
635 | else | ||
636 | cplb_data[SDRAM_RAM_MTD].start = | ||
637 | (cplb_data[i].start & | ||
638 | (-2*SIZE_1M)); | ||
639 | } else | ||
640 | #endif | ||
641 | printk(KERN_WARNING | ||
642 | "Unaligned Start of %s at 0x%X\n", | ||
643 | cplb_data[i].name, cplb_data[i].start); | ||
644 | } | ||
645 | |||
646 | as = cplb_data[i].start % SIZE_4M; | ||
647 | ae = cplb_data[i].end % SIZE_4M; | ||
648 | |||
649 | if (as) | ||
650 | a_start = cplb_data[i].start + (SIZE_4M - (as)); | ||
651 | else | ||
652 | a_start = cplb_data[i].start; | ||
653 | |||
654 | a_end = cplb_data[i].end - ae; | ||
655 | |||
656 | for (j = INITIAL_T; j <= SWITCH_T; j++) { | ||
657 | |||
658 | switch (j) { | ||
659 | case INITIAL_T: | ||
660 | if (cplb_data[i].attr & INITIAL_T) { | ||
661 | t_i = &cplb.init_i; | ||
662 | t_d = &cplb.init_d; | ||
663 | process = 1; | ||
664 | } else | ||
665 | process = 0; | ||
666 | break; | ||
667 | case SWITCH_T: | ||
668 | if (cplb_data[i].attr & SWITCH_T) { | ||
669 | t_i = &cplb.switch_i; | ||
670 | t_d = &cplb.switch_d; | ||
671 | process = 1; | ||
672 | } else | ||
673 | process = 0; | ||
674 | break; | ||
675 | default: | ||
676 | process = 0; | ||
677 | break; | ||
678 | } | ||
679 | |||
680 | if (!process) | ||
681 | continue; | ||
682 | if (cplb_data[i].attr & I_CPLB) | ||
683 | __fill_code_cplbtab(t_i, i, a_start, a_end); | ||
684 | |||
685 | if (cplb_data[i].attr & D_CPLB) | ||
686 | __fill_data_cplbtab(t_d, i, a_start, a_end); | ||
687 | } | ||
688 | } | ||
689 | |||
690 | /* close tables */ | ||
691 | |||
692 | close_cplbtab(&cplb.init_i); | ||
693 | close_cplbtab(&cplb.init_d); | ||
694 | |||
695 | cplb.init_i.tab[cplb.init_i.pos] = -1; | ||
696 | cplb.init_d.tab[cplb.init_d.pos] = -1; | ||
697 | cplb.switch_i.tab[cplb.switch_i.pos] = -1; | ||
698 | cplb.switch_d.tab[cplb.switch_d.pos] = -1; | ||
699 | |||
700 | } | ||
701 | |||
702 | #endif | ||
703 | |||
704 | static u_long get_vco(void) | 450 | static u_long get_vco(void) |
705 | { | 451 | { |
706 | u_long msel; | 452 | u_long msel; |
@@ -730,7 +476,6 @@ u_long get_cclk(void) | |||
730 | return get_vco() / ssel; | 476 | return get_vco() / ssel; |
731 | return get_vco() >> csel; | 477 | return get_vco() >> csel; |
732 | } | 478 | } |
733 | |||
734 | EXPORT_SYMBOL(get_cclk); | 479 | EXPORT_SYMBOL(get_cclk); |
735 | 480 | ||
736 | /* Get the System clock */ | 481 | /* Get the System clock */ |
@@ -749,7 +494,6 @@ u_long get_sclk(void) | |||
749 | 494 | ||
750 | return get_vco() / ssel; | 495 | return get_vco() / ssel; |
751 | } | 496 | } |
752 | |||
753 | EXPORT_SYMBOL(get_sclk); | 497 | EXPORT_SYMBOL(get_sclk); |
754 | 498 | ||
755 | /* | 499 | /* |
@@ -804,23 +548,23 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
804 | seq_printf(m, "D-CACHE:\tOFF\n"); | 548 | seq_printf(m, "D-CACHE:\tOFF\n"); |
805 | 549 | ||
806 | 550 | ||
807 | switch(bfin_read_DMEM_CONTROL() & (1 << DMC0_P | 1 << DMC1_P)) { | 551 | switch (bfin_read_DMEM_CONTROL() & (1 << DMC0_P | 1 << DMC1_P)) { |
808 | case ACACHE_BSRAM: | 552 | case ACACHE_BSRAM: |
809 | seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tSRAM\n"); | 553 | seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tSRAM\n"); |
810 | dcache_size = 16; | 554 | dcache_size = 16; |
811 | dsup_banks = 1; | 555 | dsup_banks = 1; |
812 | break; | 556 | break; |
813 | case ACACHE_BCACHE: | 557 | case ACACHE_BCACHE: |
814 | seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tCACHE\n"); | 558 | seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tCACHE\n"); |
815 | dcache_size = 32; | 559 | dcache_size = 32; |
816 | dsup_banks = 2; | 560 | dsup_banks = 2; |
817 | break; | 561 | break; |
818 | case ASRAM_BSRAM: | 562 | case ASRAM_BSRAM: |
819 | seq_printf(m, "DBANK-A:\tSRAM\n" "DBANK-B:\tSRAM\n"); | 563 | seq_printf(m, "DBANK-A:\tSRAM\n" "DBANK-B:\tSRAM\n"); |
820 | dcache_size = 0; | 564 | dcache_size = 0; |
821 | dsup_banks = 0; | 565 | dsup_banks = 0; |
822 | break; | 566 | break; |
823 | default: | 567 | default: |
824 | break; | 568 | break; |
825 | } | 569 | } |
826 | 570 | ||