diff options
Diffstat (limited to 'firmware/target/mips/ingenic_jz47xx/system-jz4740.c')
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/system-jz4740.c | 353 |
1 files changed, 169 insertions, 184 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c index 052ea64495..c0f39a4933 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c | |||
@@ -397,7 +397,7 @@ void mdelay(unsigned int msec) | |||
397 | } | 397 | } |
398 | 398 | ||
399 | /* Core-level interrupt masking */ | 399 | /* Core-level interrupt masking */ |
400 | void cli(void) | 400 | void clear_interrupts(void) |
401 | { | 401 | { |
402 | register unsigned int t; | 402 | register unsigned int t; |
403 | t = read_c0_status(); | 403 | t = read_c0_status(); |
@@ -410,7 +410,7 @@ unsigned int mips_get_sr(void) | |||
410 | return read_c0_status(); | 410 | return read_c0_status(); |
411 | } | 411 | } |
412 | 412 | ||
413 | void sti(void) | 413 | void store_interrupts(void) |
414 | { | 414 | { |
415 | register unsigned int t; | 415 | register unsigned int t; |
416 | t = read_c0_status(); | 416 | t = read_c0_status(); |
@@ -525,13 +525,6 @@ void tlb_refill_handler(void) | |||
525 | panicf("TLB refill handler at 0x%08lx! [0x%x]", read_c0_epc(), read_c0_badvaddr()); | 525 | panicf("TLB refill handler at 0x%08lx! [0x%x]", read_c0_epc(), read_c0_badvaddr()); |
526 | } | 526 | } |
527 | 527 | ||
528 | static void tlb_call_refill(void) | ||
529 | { | ||
530 | asm("la $8, tlb_refill_handler \n" | ||
531 | "jr $8 \n" | ||
532 | ); | ||
533 | } | ||
534 | |||
535 | static int dma_count = 0; | 528 | static int dma_count = 0; |
536 | void dma_enable(void) | 529 | void dma_enable(void) |
537 | { | 530 | { |
@@ -559,191 +552,178 @@ void dma_disable(void) | |||
559 | } | 552 | } |
560 | } | 553 | } |
561 | 554 | ||
562 | static inline void pll_convert(unsigned int pllin, unsigned int *pll_cfcr, unsigned int *pll_plcr1) | 555 | /* PLL output clock = EXTAL * NF / (NR * NO) |
556 | * | ||
557 | * NF = FD + 2, NR = RD + 2 | ||
558 | * NO = 1 (if OD = 0), NO = 2 (if OD = 1 or 2), NO = 4 (if OD = 3) | ||
559 | */ | ||
560 | static void pll_init(void) ICODE_ATTR; | ||
561 | static void pll_init(void) | ||
563 | { | 562 | { |
564 | register unsigned int cfcr, plcr1; | 563 | register unsigned int cfcr, plcr1; |
564 | int n2FR[33] = { | ||
565 | 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, | ||
566 | 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, | ||
567 | 9 | ||
568 | }; | ||
565 | int div[5] = {1, 3, 3, 3, 3}; /* divisors of I:S:P:L:M */ | 569 | int div[5] = {1, 3, 3, 3, 3}; /* divisors of I:S:P:L:M */ |
566 | int nf; | 570 | int nf, pllout2; |
571 | |||
572 | cfcr = CPM_CPCCR_CLKOEN | | ||
573 | CPM_CPCCR_PCS | | ||
574 | (n2FR[div[0]] << CPM_CPCCR_CDIV_BIT) | | ||
575 | (n2FR[div[1]] << CPM_CPCCR_HDIV_BIT) | | ||
576 | (n2FR[div[2]] << CPM_CPCCR_PDIV_BIT) | | ||
577 | (n2FR[div[3]] << CPM_CPCCR_MDIV_BIT) | | ||
578 | (n2FR[div[4]] << CPM_CPCCR_LDIV_BIT) | | ||
579 | CPM_CPCCR_CE; /* Perform clock divisions immediately */ | ||
567 | 580 | ||
568 | cfcr = CPM_CPCCR_CLKOEN | | 581 | pllout2 = (cfcr & CPM_CPCCR_PCS) ? CPU_FREQ : (CPU_FREQ / 2); |
569 | (div[0] << CPM_CPCCR_CDIV_BIT) | | ||
570 | (div[1] << CPM_CPCCR_HDIV_BIT) | | ||
571 | (div[2] << CPM_CPCCR_PDIV_BIT) | | ||
572 | (div[3] << CPM_CPCCR_MDIV_BIT) | | ||
573 | (div[4] << CPM_CPCCR_LDIV_BIT); | ||
574 | 582 | ||
575 | //nf = pllin * 2 / CFG_EXTAL; | 583 | /* Init USB Host clock, pllout2 must be n*48MHz */ |
576 | nf = pllin * 2 / 375299969; | 584 | REG_CPM_UHCCDR = pllout2 / 48000000 - 1; |
585 | |||
586 | nf = CPU_FREQ * 2 / CFG_EXTAL; | ||
577 | plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */ | 587 | plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */ |
578 | (0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */ | 588 | (0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */ |
579 | (0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */ | 589 | (0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */ |
580 | (0xa << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */ | 590 | (0x20 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */ |
581 | CPM_CPPCR_PLLEN; /* enable PLL */ | 591 | CPM_CPPCR_PLLEN; /* enable PLL */ |
582 | 592 | ||
583 | /* init PLL */ | 593 | /* init PLL */ |
584 | *pll_cfcr = cfcr; | 594 | REG_CPM_CPCCR = cfcr; |
585 | *pll_plcr1 = plcr1; | 595 | REG_CPM_CPPCR = plcr1; |
586 | } | 596 | } |
587 | 597 | ||
588 | static inline void sdram_convert(unsigned int pllin, unsigned int *sdram_freq) | 598 | // SDRAM paramters |
589 | { | 599 | #define CFG_SDRAM_BW16 0 /* Data bus width: 0-32bit, 1-16bit */ |
590 | register unsigned int ns, tmp; | 600 | #define CFG_SDRAM_BANK4 1 /* Banks each chip: 0-2bank, 1-4bank */ |
591 | 601 | #define CFG_SDRAM_ROW 12 /* Row address: 11 to 13 */ | |
592 | ns = 1000000000 / pllin; | 602 | #define CFG_SDRAM_COL 8 /* Column address: 8 to 12 */ |
593 | tmp = 15625 / ns; | 603 | #define CFG_SDRAM_CASL 2 /* CAS latency: 2 or 3 */ |
594 | 604 | ||
595 | /* Set refresh registers */ | 605 | // SDRAM Timings, unit: ns |
606 | #define CFG_SDRAM_TRAS 45 /* RAS# Active Time */ | ||
607 | #define CFG_SDRAM_RCD 20 /* RAS# to CAS# Delay */ | ||
608 | #define CFG_SDRAM_TPC 20 /* RAS# Precharge Time */ | ||
609 | #define CFG_SDRAM_TRWL 7 /* Write Latency Time */ | ||
610 | #define CFG_SDRAM_TREF 7812 /* Refresh period: 8192 refresh cycles/64ms */ | ||
611 | |||
612 | /* | ||
613 | * Init SDRAM memory. | ||
614 | */ | ||
615 | static void sdram_init(void) ICODE_ATTR; | ||
616 | static void sdram_init(void) | ||
617 | { | ||
618 | register unsigned int dmcr0, dmcr, sdmode, tmp, cpu_clk, mem_clk, ns; | ||
619 | |||
620 | unsigned int cas_latency_sdmr[2] = { | ||
621 | EMC_SDMR_CAS_2, | ||
622 | EMC_SDMR_CAS_3, | ||
623 | }; | ||
624 | |||
625 | unsigned int cas_latency_dmcr[2] = { | ||
626 | 1 << EMC_DMCR_TCL_BIT, /* CAS latency is 2 */ | ||
627 | 2 << EMC_DMCR_TCL_BIT /* CAS latency is 3 */ | ||
628 | }; | ||
629 | |||
630 | int div[] = { 1, 2, 3, 4, 6, 8, 12, 16, 24, 32 }; | ||
631 | |||
632 | cpu_clk = CPU_FREQ; | ||
633 | mem_clk = cpu_clk * div[__cpm_get_cdiv()] / div[__cpm_get_mdiv()]; | ||
634 | |||
635 | //REG_EMC_BCR = 0; /* Disable bus release */ | ||
636 | REG_EMC_RTCSR = 0; /* Disable clock for counting */ | ||
637 | REG_EMC_RTCOR = 0; | ||
638 | REG_EMC_RTCNT = 0; | ||
639 | |||
640 | /* Fault DMCR value for mode register setting */ | ||
641 | #define SDRAM_ROW0 11 | ||
642 | #define SDRAM_COL0 8 | ||
643 | #define SDRAM_BANK40 0 | ||
644 | |||
645 | dmcr0 = ((SDRAM_ROW0 - 11) << EMC_DMCR_RA_BIT) | | ||
646 | ((SDRAM_COL0 - 8) << EMC_DMCR_CA_BIT) | | ||
647 | (SDRAM_BANK40 << EMC_DMCR_BA_BIT) | | ||
648 | (CFG_SDRAM_BW16 << EMC_DMCR_BW_BIT) | | ||
649 | EMC_DMCR_EPIN | cas_latency_dmcr[((CFG_SDRAM_CASL == 3) ? 1 : 0)]; | ||
650 | |||
651 | /* Basic DMCR value */ | ||
652 | dmcr = ((CFG_SDRAM_ROW - 11) << EMC_DMCR_RA_BIT) | | ||
653 | ((CFG_SDRAM_COL - 8) << EMC_DMCR_CA_BIT) | | ||
654 | (CFG_SDRAM_BANK4 << EMC_DMCR_BA_BIT) | | ||
655 | (CFG_SDRAM_BW16 << EMC_DMCR_BW_BIT) | | ||
656 | EMC_DMCR_EPIN | cas_latency_dmcr[((CFG_SDRAM_CASL == 3) ? 1 : 0)]; | ||
657 | |||
658 | /* SDRAM timimg */ | ||
659 | ns = 1000000000 / mem_clk; | ||
660 | tmp = CFG_SDRAM_TRAS / ns; | ||
661 | if (tmp < 4) | ||
662 | tmp = 4; | ||
663 | if (tmp > 11) | ||
664 | tmp = 11; | ||
665 | dmcr |= ((tmp - 4) << EMC_DMCR_TRAS_BIT); | ||
666 | tmp = CFG_SDRAM_RCD / ns; | ||
667 | if (tmp > 3) | ||
668 | tmp = 3; | ||
669 | dmcr |= (tmp << EMC_DMCR_RCD_BIT); | ||
670 | tmp = CFG_SDRAM_TPC / ns; | ||
671 | if (tmp > 7) | ||
672 | tmp = 7; | ||
673 | dmcr |= (tmp << EMC_DMCR_TPC_BIT); | ||
674 | tmp = CFG_SDRAM_TRWL / ns; | ||
675 | if (tmp > 3) | ||
676 | tmp = 3; | ||
677 | dmcr |= (tmp << EMC_DMCR_TRWL_BIT); | ||
678 | tmp = (CFG_SDRAM_TRAS + CFG_SDRAM_TPC) / ns; | ||
679 | if (tmp > 14) | ||
680 | tmp = 14; | ||
681 | dmcr |= (((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT); | ||
682 | |||
683 | /* SDRAM mode value */ | ||
684 | sdmode = EMC_SDMR_BT_SEQ | | ||
685 | EMC_SDMR_OM_NORMAL | | ||
686 | EMC_SDMR_BL_4 | cas_latency_sdmr[((CFG_SDRAM_CASL == 3) ? 1 : 0)]; | ||
687 | |||
688 | /* Stage 1. Precharge all banks by writing SDMR with DMCR.MRSET=0 */ | ||
689 | REG_EMC_DMCR = dmcr; | ||
690 | REG8(EMC_SDMR0 | sdmode) = 0; | ||
691 | |||
692 | /* Wait for precharge, > 200us */ | ||
693 | tmp = (cpu_clk / 1000000) * 1000; | ||
694 | while (tmp--); | ||
695 | |||
696 | /* Stage 2. Enable auto-refresh */ | ||
697 | REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH; | ||
698 | |||
699 | tmp = CFG_SDRAM_TREF / ns; | ||
596 | tmp = tmp / 64 + 1; | 700 | tmp = tmp / 64 + 1; |
597 | 701 | if (tmp > 0xff) | |
598 | if(tmp > 0xff) | ||
599 | tmp = 0xff; | 702 | tmp = 0xff; |
600 | 703 | REG_EMC_RTCOR = tmp; | |
601 | *sdram_freq = tmp; | 704 | REG_EMC_RTCNT = 0; |
602 | } | 705 | REG_EMC_RTCSR = EMC_RTCSR_CKS_64; /* Divisor is 64, CKO/64 */ |
603 | 706 | ||
604 | static inline void set_cpu_freq(unsigned int pllin, unsigned int div) | 707 | /* Wait for number of auto-refresh cycles */ |
605 | { | 708 | tmp = (cpu_clk / 1000000) * 1000; |
606 | unsigned int sdram_freq; | 709 | while (tmp--); |
607 | unsigned int pll_cfcr, pll_plcr1; | ||
608 | int div_preq[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; | ||
609 | |||
610 | if(pllin < 25000000 || pllin > 420000000) | ||
611 | panicf("PLL should be >25000000 and <420000000 !"); | ||
612 | |||
613 | unsigned long t = read_c0_status(); | ||
614 | write_c0_status(t & ~1); | ||
615 | |||
616 | pll_convert(pllin, &pll_cfcr, &pll_plcr1); | ||
617 | 710 | ||
618 | sdram_convert(pllin / div_preq[div], &sdram_freq); | 711 | /* Stage 3. Mode Register Set */ |
619 | 712 | REG_EMC_DMCR = dmcr0 | EMC_DMCR_RFSH | EMC_DMCR_MRSET; | |
620 | REG_CPM_CPCCR &= ~CPM_CPCCR_CE; | 713 | REG8(EMC_SDMR0 | sdmode) = 0; |
621 | |||
622 | REG_CPM_CPCCR = pll_cfcr; | ||
623 | REG_CPM_CPPCR = pll_plcr1; | ||
624 | |||
625 | REG_EMC_RTCOR = sdram_freq; | ||
626 | REG_EMC_RTCNT = sdram_freq; | ||
627 | |||
628 | REG_CPM_CPCCR |= CPM_CPCCR_CE; | ||
629 | |||
630 | detect_clock(); | ||
631 | |||
632 | write_c0_status(t); | ||
633 | } | ||
634 | 714 | ||
635 | static void OF_init_clocks(void) | 715 | /* Set back to basic DMCR value */ |
636 | { | 716 | REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET; |
637 | unsigned long t = read_c0_status(); | ||
638 | write_c0_status(t & ~1); | ||
639 | |||
640 | unsigned int prog_entry = ((unsigned int)OF_init_clocks >> 5) << 5; | ||
641 | unsigned int i, prog_size = 1024; | ||
642 | |||
643 | for(i = prog_entry; i < prog_entry + prog_size; i += 32) | ||
644 | __asm__ __volatile__("cache 0x1c, 0x00(%0) \n" | ||
645 | : | ||
646 | : "r" (i) | ||
647 | ); | ||
648 | |||
649 | /* disable PLL clock */ | ||
650 | REG_CPM_CPPCR &= ~CPM_CPPCR_PLLEN; | ||
651 | REG_CPM_CPCCR |= CPM_CPCCR_CE; | ||
652 | |||
653 | unsigned long old_clocks = REG_CPM_CLKGR; | ||
654 | /* | ||
655 | REG_CPM_CLKGR = ~( CPM_CLKGR_UART0 | CPM_CLKGR_TCU | | ||
656 | CPM_CLKGR_RTC | CPM_CLKGR_SADC | | ||
657 | CPM_CLKGR_LCD ); | ||
658 | */ | ||
659 | |||
660 | unsigned long old_scr = REG_CPM_SCR; | ||
661 | REG_CPM_SCR &= ~CPM_SCR_OSC_ENABLE; /* O1SE: 12M oscillator is disabled in Sleep mode */ | ||
662 | |||
663 | REG_EMC_DMCR |= (EMC_DMCR_RMODE | EMC_DMCR_RFSH); /* self refresh + refresh is performed */ | ||
664 | REG_EMC_DMCR = (REG_EMC_DMCR & ~EMC_DMCR_RMODE) | 1; /* -> RMODE = auto refresh | ||
665 | -> CAS mode = 2 cycles */ | ||
666 | __asm__ __volatile__("wait \n"); | ||
667 | |||
668 | REG_CPM_CLKGR = old_clocks; | ||
669 | REG_CPM_SCR = old_scr; | ||
670 | |||
671 | for(i=0; i<90; i++); | ||
672 | |||
673 | set_cpu_freq(336000000, 1); | ||
674 | |||
675 | for(i=0; i<60; i++); | ||
676 | |||
677 | write_c0_status(t); | ||
678 | } | ||
679 | 717 | ||
680 | static void my_init_clocks(void) | 718 | /* everything is ok now */ |
681 | { | ||
682 | unsigned long t = read_c0_status(); | ||
683 | write_c0_status(t & ~1); | ||
684 | |||
685 | unsigned int prog_entry = ((unsigned int)my_init_clocks / 32 - 1) * 32; | ||
686 | unsigned int i, prog_size = 1024; | ||
687 | |||
688 | for(i = prog_entry; i < prog_entry + prog_size; i += 32) | ||
689 | __asm__ __volatile__("cache 0x1c, 0x00(%0) \n" | ||
690 | : | ||
691 | : "r" (i) | ||
692 | ); | ||
693 | |||
694 | unsigned int sdram_freq, plcr1, cfcr; | ||
695 | |||
696 | sdram_convert(336000000/3, &sdram_freq); | ||
697 | |||
698 | cfcr = CPM_CPCCR_CLKOEN | | ||
699 | (6 << CPM_CPCCR_UDIV_BIT) | | ||
700 | CPM_CPCCR_UCS | | ||
701 | CPM_CPCCR_PCS | | ||
702 | (0 << CPM_CPCCR_CDIV_BIT) | | ||
703 | (1 << CPM_CPCCR_HDIV_BIT) | | ||
704 | (1 << CPM_CPCCR_PDIV_BIT) | | ||
705 | (1 << CPM_CPCCR_MDIV_BIT) | | ||
706 | (1 << CPM_CPCCR_LDIV_BIT); | ||
707 | |||
708 | plcr1 = (54 << CPM_CPPCR_PLLM_BIT) | /* FD */ | ||
709 | (0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */ | ||
710 | (0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */ | ||
711 | (0x20 << CPM_CPPCR_PLLST_BIT)| /* PLL stable time */ | ||
712 | CPM_CPPCR_PLLEN; /* enable PLL */ | ||
713 | |||
714 | REG_CPM_CPCCR &= ~CPM_CPCCR_CE; | ||
715 | |||
716 | REG_CPM_CPCCR = cfcr; | ||
717 | REG_CPM_CPPCR = plcr1; | ||
718 | |||
719 | REG_EMC_RTCOR = sdram_freq; | ||
720 | REG_EMC_RTCNT = sdram_freq; | ||
721 | |||
722 | REG_CPM_CPCCR |= CPM_CPCCR_CE; | ||
723 | |||
724 | REG_CPM_LPCDR = (REG_CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | (11 << CPM_LPCDR_PIXDIV_BIT); | ||
725 | |||
726 | write_c0_status(t); | ||
727 | } | 719 | } |
728 | 720 | ||
729 | extern int main(void); | 721 | extern int main(void); |
730 | extern void except_common_entry(void); | 722 | void system_main(void) ICODE_ATTR; |
731 | |||
732 | void system_main(void) | 723 | void system_main(void) |
733 | { | 724 | { |
734 | int i; | 725 | int i; |
735 | 726 | ||
736 | /* | ||
737 | * 0x0 - Simple TLB refill handler | ||
738 | * 0x100 - Cache error handler | ||
739 | * 0x180 - Exception/Interrupt handler | ||
740 | * 0x200 - Special Exception Interrupt handler (when IV is set in CP0_CAUSE) | ||
741 | */ | ||
742 | memcpy((void *)A_K0BASE, (void *)&tlb_call_refill, 0x20); | ||
743 | memcpy((void *)(A_K0BASE + 0x100), (void *)&except_common_entry, 0x20); | ||
744 | memcpy((void *)(A_K0BASE + 0x180), (void *)&except_common_entry, 0x20); | ||
745 | memcpy((void *)(A_K0BASE + 0x200), (void *)&except_common_entry, 0x20); | ||
746 | |||
747 | __dcache_writeback_all(); | 727 | __dcache_writeback_all(); |
748 | __icache_invalidate_all(); | 728 | __icache_invalidate_all(); |
749 | 729 | ||
@@ -755,27 +735,22 @@ void system_main(void) | |||
755 | 735 | ||
756 | tlb_init(); | 736 | tlb_init(); |
757 | 737 | ||
738 | //pll_init(); | ||
739 | //sdram_init(); | ||
740 | |||
758 | detect_clock(); | 741 | detect_clock(); |
759 | 742 | ||
760 | /* Disable unneeded clocks, clocks are enabled when needed */ | 743 | /* Disable unneeded clocks, clocks are enabled when needed */ |
761 | __cpm_stop_all(); | 744 | __cpm_stop_all(); |
762 | __cpm_suspend_usbhost(); | 745 | __cpm_suspend_usbhost(); |
763 | 746 | ||
764 | #if 0 | ||
765 | my_init_clocks(); | ||
766 | //OF_init_clocks(); | ||
767 | /*__cpm_stop_udc(); | ||
768 | REG_CPM_CPCCR |= CPM_CPCCR_UCS; | ||
769 | REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | (3 << CPM_CPCCR_UDIV_BIT); | ||
770 | __cpm_start_udc();*/ | ||
771 | #endif | ||
772 | |||
773 | /* Enable interrupts at core level */ | 747 | /* Enable interrupts at core level */ |
774 | sti(); | 748 | store_interrupts(); |
775 | 749 | ||
776 | main(); /* Shouldn't return */ | 750 | main(); /* Shouldn't return */ |
777 | 751 | ||
778 | while(1); | 752 | while(1) |
753 | core_idle(); | ||
779 | } | 754 | } |
780 | 755 | ||
781 | void system_reboot(void) | 756 | void system_reboot(void) |
@@ -812,3 +787,13 @@ void power_off(void) | |||
812 | 787 | ||
813 | while(1); | 788 | while(1); |
814 | } | 789 | } |
790 | |||
791 | void system_init(void) | ||
792 | { | ||
793 | } | ||
794 | |||
795 | int system_memory_guard(int newmode) | ||
796 | { | ||
797 | (void)newmode; | ||
798 | return 0; | ||
799 | } | ||