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.c353
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 */
400void cli(void) 400void 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
413void sti(void) 413void 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
528static void tlb_call_refill(void)
529{
530 asm("la $8, tlb_refill_handler \n"
531 "jr $8 \n"
532 );
533}
534
535static int dma_count = 0; 528static int dma_count = 0;
536void dma_enable(void) 529void dma_enable(void)
537{ 530{
@@ -559,191 +552,178 @@ void dma_disable(void)
559 } 552 }
560} 553}
561 554
562static 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 */
560static void pll_init(void) ICODE_ATTR;
561static 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
588static 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 */
615static void sdram_init(void) ICODE_ATTR;
616static 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
604static 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
635static 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
680static 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
729extern int main(void); 721extern int main(void);
730extern void except_common_entry(void); 722void system_main(void) ICODE_ATTR;
731
732void system_main(void) 723void 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
781void system_reboot(void) 756void system_reboot(void)
@@ -812,3 +787,13 @@ void power_off(void)
812 787
813 while(1); 788 while(1);
814} 789}
790
791void system_init(void)
792{
793}
794
795int system_memory_guard(int newmode)
796{
797 (void)newmode;
798 return 0;
799}