summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_jz47xx/system-jz4740.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips/ingenic_jz47xx/system-jz4740.c')
-rw-r--r--firmware/target/mips/ingenic_jz47xx/system-jz4740.c122
1 files changed, 72 insertions, 50 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c
index 8f1c3f5c1a..61be6c60de 100644
--- a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c
@@ -555,21 +555,7 @@ void dma_cache_wback_inv(unsigned long addr, unsigned long size)
555 } 555 }
556} 556}
557 557
558extern int main(void); 558#define BARRIER \
559extern void except_common_entry(void);
560
561#define mtc0_tlbw_hazard() \
562 __asm__ __volatile__( \
563 " .set noreorder \n" \
564 " nop \n" \
565 " nop \n" \
566 " nop \n" \
567 " nop \n" \
568 " nop \n" \
569 " nop \n" \
570 " .set reorder \n");
571
572#define tlbw_use_hazard() \
573 __asm__ __volatile__( \ 559 __asm__ __volatile__( \
574 " .set noreorder \n" \ 560 " .set noreorder \n" \
575 " nop \n" \ 561 " nop \n" \
@@ -580,10 +566,13 @@ extern void except_common_entry(void);
580 " nop \n" \ 566 " nop \n" \
581 " .set reorder \n"); 567 " .set reorder \n");
582 568
583 569#define DEFAULT_PAGE_SHIFT PL_4K
584#define PAGE_SHIFT PL_4K 570#define DEFAULT_PAGE_MASK PM_4K
585#define PM_DEFAULT_MASK PM_4K 571#define UNIQUE_ENTRYHI(idx, ps) (A_K0BASE + ((idx) << (ps + 1)))
586#define UNIQUE_ENTRYHI(idx) (A_K0BASE + ((idx) << (PAGE_SHIFT + 1))) 572#define ASID_MASK M_EntryHiASID
573#define VPN2_SHIFT S_EntryHiVPN2
574#define PFN_SHIFT S_EntryLoPFN
575#define PFN_MASK 0xffffff
587static void local_flush_tlb_all(void) 576static void local_flush_tlb_all(void)
588{ 577{
589 unsigned long old_ctx; 578 unsigned long old_ctx;
@@ -594,59 +583,92 @@ static void local_flush_tlb_all(void)
594 old_ctx = read_c0_entryhi(); 583 old_ctx = read_c0_entryhi();
595 write_c0_entrylo0(0); 584 write_c0_entrylo0(0);
596 write_c0_entrylo1(0); 585 write_c0_entrylo1(0);
586 BARRIER;
597 587
598 /* Blast 'em all away. */ 588 /* Blast 'em all away. */
599 for(entry = read_c0_wired(); entry < 32; entry++) 589 for(entry = 0; entry < 32; entry++)
600 { 590 {
601 /* Make sure all entries differ. */ 591 /* Make sure all entries differ. */
602 write_c0_entryhi(UNIQUE_ENTRYHI(entry)); 592 write_c0_entryhi(UNIQUE_ENTRYHI(entry, DEFAULT_PAGE_SHIFT));
603 write_c0_index(entry); 593 write_c0_index(entry);
604 mtc0_tlbw_hazard(); 594 BARRIER;
605 tlb_write_indexed(); 595 tlb_write_indexed();
606 } 596 }
607 tlbw_use_hazard(); 597 BARRIER;
608 write_c0_entryhi(old_ctx); 598 write_c0_entryhi(old_ctx);
609 599
610 restore_irq(old_irq); 600 restore_irq(old_irq);
611} 601}
612 602
603static void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
604 unsigned long entryhi, unsigned long pagemask)
605{
606 unsigned long wired;
607 unsigned long old_pagemask;
608 unsigned long old_ctx;
609 unsigned int old_irq = disable_irq_save();
610
611 old_ctx = read_c0_entryhi() & ASID_MASK;
612 old_pagemask = read_c0_pagemask();
613 wired = read_c0_wired();
614 write_c0_wired(wired + 1);
615 write_c0_index(wired);
616 BARRIER;
617 write_c0_pagemask(pagemask);
618 write_c0_entryhi(entryhi);
619 write_c0_entrylo0(entrylo0);
620 write_c0_entrylo1(entrylo1);
621 BARRIER;
622 tlb_write_indexed();
623 BARRIER;
624
625 write_c0_entryhi(old_ctx);
626 BARRIER;
627 write_c0_pagemask(old_pagemask);
628 local_flush_tlb_all();
629 restore_irq(old_irq);
630}
631
632static void map_address(unsigned long virtual, unsigned long physical, unsigned long length)
633{
634 unsigned long entry0 = (physical & PFN_MASK) << PFN_SHIFT;
635 unsigned long entry1 = ((physical+length) & PFN_MASK) << PFN_SHIFT;
636 unsigned long entryhi = virtual & ~VPN2_SHIFT;
637
638 entry0 |= (M_EntryLoG | M_EntryLoV | (K_CacheAttrC << S_EntryLoC) );
639 entry1 |= (M_EntryLoG | M_EntryLoV | (K_CacheAttrC << S_EntryLoC) );
640
641 add_wired_entry(entry0, entry1, entryhi, DEFAULT_PAGE_MASK);
642}
643
613 644
614static void tlb_init(void) 645static void tlb_init(void)
615{ 646{
616 write_c0_pagemask(PM_DEFAULT_MASK); 647 write_c0_pagemask(DEFAULT_PAGE_MASK);
617 write_c0_wired(0); 648 write_c0_wired(0);
618 write_c0_framemask(0); 649 write_c0_framemask(0);
619 650
620 local_flush_tlb_all(); 651 local_flush_tlb_all();
652/*
653 map_address(0x80000000, 0x80000000, 0x4000);
654 map_address(0x80004000, 0x80004000, MEM * 0x100000);
655*/
621} 656}
622 657
623static void tlb_refill_handler(void) 658void tlb_refill_handler(void)
624{ 659{
625#if 1 660 panicf("TLB refill handler! [0x%x] [0x%lx]", read_c0_badvaddr(), read_c0_epc());
626 panicf("TLB refill handler! [0x%x] [0x%x]", read_c0_badvaddr(), read_c0_epc());
627#else
628 __asm__ __volatile__(
629 "mfc0 k0, C0_BADVADDR\n"
630 "lui k1, pgdc\n"
631 "lw k1, pgdc>>16(k0)\n"
632 "srl k0, k0, 22\n"
633 "sll k0, k0, 2\n"
634 "addu k1, k1, k0\n"
635 "mfc0 k0, C0_CONTEXT\n"
636 "lw k1, 0(k1)\n"
637 "andi k0, k0, 0xFFC\n"
638 "addu k1, k1, k0\n"
639 "lw k0, 0(k1)\n"
640 "nop\n"
641 "mtc0 k0, C0_ENTRYLO0\n"
642 "mfc0 k1, C0_EPC\n"
643 "tlbwr\n"
644 "jr k1\n"
645 "rfe\n"
646 );
647#endif
648} 661}
649 662
663static void tlb_call_refill(void)
664{
665 asm("la $8, tlb_refill_handler \n"
666 "jr $8 \n");
667}
668
669extern int main(void);
670extern void except_common_entry(void);
671
650void system_main(void) 672void system_main(void)
651{ 673{
652 int i; 674 int i;
@@ -657,7 +679,7 @@ void system_main(void)
657 * 0x180 - Exception/Interrupt handler 679 * 0x180 - Exception/Interrupt handler
658 * 0x200 - Special Exception Interrupt handler (when IV is set in CP0_CAUSE) 680 * 0x200 - Special Exception Interrupt handler (when IV is set in CP0_CAUSE)
659 */ 681 */
660 memcpy((void *)A_K0BASE, (void *)&tlb_refill_handler, 0x20); 682 memcpy((void *)A_K0BASE, (void *)&tlb_call_refill, 0x20);
661 memcpy((void *)(A_K0BASE + 0x100), (void *)&except_common_entry, 0x20); 683 memcpy((void *)(A_K0BASE + 0x100), (void *)&except_common_entry, 0x20);
662 memcpy((void *)(A_K0BASE + 0x180), (void *)&except_common_entry, 0x20); 684 memcpy((void *)(A_K0BASE + 0x180), (void *)&except_common_entry, 0x20);
663 memcpy((void *)(A_K0BASE + 0x200), (void *)&except_common_entry, 0x20); 685 memcpy((void *)(A_K0BASE + 0x200), (void *)&except_common_entry, 0x20);
@@ -671,7 +693,7 @@ void system_main(void)
671 for(i=0; i<IRQ_MAX; i++) 693 for(i=0; i<IRQ_MAX; i++)
672 dis_irq(i); 694 dis_irq(i);
673 695
674 tlb_init(); 696 //tlb_init();
675 697
676 sti(); 698 sti();
677 699