summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2020-08-07 00:44:55 -0400
committerSolomon Peachy <pizza@shaftnet.org>2020-08-07 11:42:45 -0400
commiteb0e41c1ccb0dcf35efa7e1434bb0e35c9df1543 (patch)
tree8989f4d1bfe2c24d67d72026f97ec8e0cc11f949
parent62146ed73513ec62b57163d229c6719b9349c640 (diff)
downloadrockbox-eb0e41c1ccb0dcf35efa7e1434bb0e35c9df1543.tar.gz
rockbox-eb0e41c1ccb0dcf35efa7e1434bb0e35c9df1543.zip
jz4760: Support dynamic reclocking!
default/low speed is 192 MHz, Max is 576 Downclock PCLK/MCLK/etc to 96MHz to save a bit of juice Honestly the high speed could be dialed down to, eg 384 as this thing is so bloody fast.. Change-Id: Ie65597c74290f1603e65f69dae8e75b59c8ba0b4
-rw-r--r--firmware/export/config/xduoox3.h14
-rw-r--r--firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c16
-rw-r--r--firmware/target/mips/ingenic_jz47xx/system-jz4760.c61
3 files changed, 66 insertions, 25 deletions
diff --git a/firmware/export/config/xduoox3.h b/firmware/export/config/xduoox3.h
index f510495bd9..999b6b9912 100644
--- a/firmware/export/config/xduoox3.h
+++ b/firmware/export/config/xduoox3.h
@@ -148,8 +148,18 @@
148/* Define this if you have a Ingenic JZ4760B */ 148/* Define this if you have a Ingenic JZ4760B */
149#define CONFIG_CPU JZ4760B 149#define CONFIG_CPU JZ4760B
150 150
151/* Define this to the CPU frequency */ 151/* We have adjustable frequency */
152#define CPU_FREQ 480000000 /* CPU clock: 480 MHz -- Keep a multiple of 48MHz! */ 152#define CPUFREQ_MAX 576000000 // datasheet sez 600MHz max. Must be multiple of 48!
153#define CPUFREQ_MIN 192000000
154#define CPUFREQ_DEFAULT CPUFREQ_MIN
155
156#define HAVE_ADJUSTABLE_CPU_FREQ
157#ifdef HAVE_ADJUSTABLE_CPU_FREQ
158//#define HAVE_GUI_BOOST
159#define CPUFREQ_NORMAL CPUFREQ_MIN
160#else
161#define CPU_FREQ CPUFREQ_MAX
162#endif
153 163
154/* Define this if you want to use the JZ47XX i2c interface */ 164/* Define this if you want to use the JZ47XX i2c interface */
155#define CONFIG_I2C I2C_JZ47XX 165#define CONFIG_I2C I2C_JZ47XX
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c
index 0135c1ced9..6862262045 100644
--- a/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c
+++ b/firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c
@@ -633,14 +633,23 @@ static inline unsigned int jz_sd_calc_clkrt(const int drive, unsigned int rate)
633 return clkrt; 633 return clkrt;
634} 634}
635 635
636static inline void cpm_select_msc_clk(unsigned int rate) 636#ifndef HAVE_ADJUSTABLE_CPU_FREQ
637#define cpu_frequency __cpm_get_pllout2()
638#endif
639
640void cpm_select_msc_clk(void)
637{ 641{
638 unsigned int div = __cpm_get_pllout2() / rate; 642 unsigned int div = cpu_frequency / SD_CLOCK_FAST;
643
639 if (div == 0) 644 if (div == 0)
640 div = 1; 645 div = 1;
641 646
647 if (div == __cpm_get_mscdiv())
648 return;
649
642 REG_CPM_MSCCDR = MSCCDR_MCS | (div - 1); 650 REG_CPM_MSCCDR = MSCCDR_MCS | (div - 1);
643 DEBUG("MSCCLK == %x\n", REG_CPM_MSCCDR); 651 DEBUG("MSCCLK == %x\n", REG_CPM_MSCCDR);
652 __cpm_enable_pll_change();
644} 653}
645 654
646/* Set the MMC clock frequency */ 655/* Set the MMC clock frequency */
@@ -651,9 +660,8 @@ static void jz_sd_set_clock(const int drive, unsigned int rate)
651 jz_sd_stop_clock(drive); 660 jz_sd_stop_clock(drive);
652 661
653 /* select clock source from CPM */ 662 /* select clock source from CPM */
654 cpm_select_msc_clk(rate); 663 cpm_select_msc_clk();
655 664
656 __cpm_enable_pll_change();
657 clkrt = jz_sd_calc_clkrt(drive, rate); 665 clkrt = jz_sd_calc_clkrt(drive, rate);
658 REG_MSC_CLKRT(MSC_CHN(drive)) = clkrt; 666 REG_MSC_CLKRT(MSC_CHN(drive)) = clkrt;
659 667
diff --git a/firmware/target/mips/ingenic_jz47xx/system-jz4760.c b/firmware/target/mips/ingenic_jz47xx/system-jz4760.c
index 73e9ab7749..c28aa8f967 100644
--- a/firmware/target/mips/ingenic_jz47xx/system-jz4760.c
+++ b/firmware/target/mips/ingenic_jz47xx/system-jz4760.c
@@ -417,38 +417,44 @@ static inline unsigned int pll_calc_m_n_od(unsigned int speed, unsigned int xtal
417static void pll0_init(unsigned int freq) 417static void pll0_init(unsigned int freq)
418{ 418{
419 register unsigned int cfcr, plcr1; 419 register unsigned int cfcr, plcr1;
420 int usbdiv; 420 int usbdiv, offset;
421 421
422 /** divisors, 422 /** divisors,
423 * for jz4760b,I:H:H2:P:M:S. 423 * for jz4760b,I:H:H2:P:M:S.
424 * DIV should be one of [1, 2, 3, 4, 6, 8] 424 * DIV should be one of [1, 2, 3, 4, 6, 8]
425 */ 425 */
426 const int div[6] = {1, 4, 4, 4, 4, 4}; 426 const int div[2][6] = { { 1, 2, 2, 2, 2, 2 },
427 { 1, 6, 6, 6, 6, 6 } };
427 const int n2FR[9] = { 428 const int n2FR[9] = {
428 0, 0, 1, 2, 3, 0, 4, 0, 5 429 0, 0, 1, 2, 3, 0, 4, 0, 5
429 }; 430 };
430 431
431 /* @ CPU_FREQ of 492MHZ, this means: 432 /* @ CPU_FREQ of 576/192MHz, this means:
432 492MHz CCLK 433 CCLK (= HCLK*n, H2CLK*n, PCLK*o)
433 123MHz HCLK 434 96MHz HCLK (= MCLK or 2x MCLK, PCLK*n)
434 123MHz H2CLK 435 96MHz H2CLK (= HCLK or HCLK/2, PCLK*n)
435 123MHz PCLK 436 96MHz PCLK
436 123MHz MCLK 437 96MHz MCLK (= PCLK*n)
437 123MHZ SCLK ( must equal H2CLK or HCLK/2) 438 96MHZ SCLK (= H2CLK or HCLK/2)
438 */ 439 */
439 440
441 if (freq > CPUFREQ_NORMAL)
442 offset = 1;
443 else
444 offset = 0;
445
440 /* set ahb **/ 446 /* set ahb **/
441 REG32(HARB0_BASE) = 0x00300000; 447 REG32(HARB0_BASE) = 0x00300000;
442 REG32(0xb3070048) = 0x00000000; 448 REG32(0xb3070048) = 0x00000000;
443 REG32(HARB2_BASE) = 0x00FFFFFF; 449 REG32(HARB2_BASE) = 0x00FFFFFF;
444 450
445 cfcr = CPCCR_PCS | // no divisor on PLL for peripherals 451 cfcr = CPCCR_PCS | // no divisor on PLL for peripherals
446 (n2FR[div[0]] << CPCCR_CDIV_LSB) | 452 (n2FR[div[offset][0]] << CPCCR_CDIV_LSB) |
447 (n2FR[div[1]] << CPCCR_HDIV_LSB) | 453 (n2FR[div[offset][1]] << CPCCR_HDIV_LSB) |
448 (n2FR[div[2]] << CPCCR_H2DIV_LSB) | 454 (n2FR[div[offset][2]] << CPCCR_H2DIV_LSB) |
449 (n2FR[div[3]] << CPCCR_PDIV_LSB) | 455 (n2FR[div[offset][3]] << CPCCR_PDIV_LSB) |
450 (n2FR[div[4]] << CPCCR_MDIV_LSB) | 456 (n2FR[div[offset][4]] << CPCCR_MDIV_LSB) |
451 (n2FR[div[5]] << CPCCR_SDIV_LSB); 457 (n2FR[div[offset][5]] << CPCCR_SDIV_LSB);
452 458
453 // write REG_DDRC_CTRL 8 times to clear ddr fifo 459 // write REG_DDRC_CTRL 8 times to clear ddr fifo
454 REG_DDRC_CTRL = 0; 460 REG_DDRC_CTRL = 0;
@@ -569,6 +575,10 @@ int serial_preinit(void)
569 return 0; 575 return 0;
570} 576}
571 577
578#ifndef HAVE_ADJUSTABLE_CPU_FREQ
579#define cpu_frequency CPU_FREQ
580#endif
581
572void usb_preinit(void) 582void usb_preinit(void)
573{ 583{
574 /* Clear ECS bit of CPCCR, 0:clock source is EXCLK, 1:clock source is EXCLK/2 */ 584 /* Clear ECS bit of CPCCR, 0:clock source is EXCLK, 1:clock source is EXCLK/2 */
@@ -589,7 +599,7 @@ void usb_preinit(void)
589 REG_CPM_USBVBFIL = 0x80; 599 REG_CPM_USBVBFIL = 0x80;
590 600
591 /* rdt */ 601 /* rdt */
592 REG_CPM_USBRDT = (600 * (CPU_FREQ / 1000000)) / 1000; 602 REG_CPM_USBRDT = (600 * (CPUFREQ_DEFAULT / 1000000)) / 1000;
593 603
594 /* rdt - filload_en */ 604 /* rdt - filload_en */
595 REG_CPM_USBRDT |= (1 << 25); 605 REG_CPM_USBRDT |= (1 << 25);
@@ -649,8 +659,8 @@ void ICODE_ATTR system_main(void)
649 659
650 mmu_init(); 660 mmu_init();
651 661
652 pll0_init(CPU_FREQ); // PLL0 drives everything but audio 662 pll0_init(CPUFREQ_DEFAULT); // PLL0 drives everything but audio
653 pll1_disable(); // Leave PLL1 disabled until audio needs it 663 pll1_disable(); // Leave PLL1 disabled until audio needs it
654 664
655 serial_preinit(); 665 serial_preinit();
656 usb_preinit(); 666 usb_preinit();
@@ -713,9 +723,22 @@ int system_memory_guard(int newmode)
713 return 0; 723 return 0;
714} 724}
715 725
726
716#ifdef HAVE_ADJUSTABLE_CPU_FREQ 727#ifdef HAVE_ADJUSTABLE_CPU_FREQ
728void cpm_select_msc_clk(void);
729
717void set_cpu_frequency(long frequency) 730void set_cpu_frequency(long frequency)
718{ 731{
719 serial_putsf("set_cpu_frequency: %d\n", frequency); 732 if (frequency == cpu_frequency)
733 return;
734 else if (frequency < CPUFREQ_MIN)
735 frequency = CPUFREQ_MIN;
736 else if (frequency > CPUFREQ_MAX)
737 frequency = CPUFREQ_MAX;
738
739 pll0_init(frequency);
740 // FIX PCLK (ie i2c)?
741 cpu_frequency = __cpm_get_pllout2();
742 cpm_select_msc_clk();
720} 743}
721#endif 744#endif