summaryrefslogtreecommitdiffstats
path: root/firmware/target/mips
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 /firmware/target/mips
parent62146ed73513ec62b57163d229c6719b9349c640 (diff)
downloadrockbox-eb0e41c1ccb0dcf35efa7e1434bb0e35c9df1543.tar.gz
rockbox-eb0e41c1ccb0dcf35efa7e1434bb0e35c9df1543.tar.bz2
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
Diffstat (limited to 'firmware/target/mips')
-rw-r--r--firmware/target/mips/ingenic_jz47xx/ata-sd-jz4760.c16
-rw-r--r--firmware/target/mips/ingenic_jz47xx/system-jz4760.c61
2 files changed, 54 insertions, 23 deletions
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)
return clkrt;
}
-static inline void cpm_select_msc_clk(unsigned int rate)
+#ifndef HAVE_ADJUSTABLE_CPU_FREQ
+#define cpu_frequency __cpm_get_pllout2()
+#endif
+
+void cpm_select_msc_clk(void)
{
- unsigned int div = __cpm_get_pllout2() / rate;
+ unsigned int div = cpu_frequency / SD_CLOCK_FAST;
+
if (div == 0)
div = 1;
+ if (div == __cpm_get_mscdiv())
+ return;
+
REG_CPM_MSCCDR = MSCCDR_MCS | (div - 1);
DEBUG("MSCCLK == %x\n", REG_CPM_MSCCDR);
+ __cpm_enable_pll_change();
}
/* Set the MMC clock frequency */
@@ -651,9 +660,8 @@ static void jz_sd_set_clock(const int drive, unsigned int rate)
jz_sd_stop_clock(drive);
/* select clock source from CPM */
- cpm_select_msc_clk(rate);
+ cpm_select_msc_clk();
- __cpm_enable_pll_change();
clkrt = jz_sd_calc_clkrt(drive, rate);
REG_MSC_CLKRT(MSC_CHN(drive)) = clkrt;
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
static void pll0_init(unsigned int freq)
{
register unsigned int cfcr, plcr1;
- int usbdiv;
+ int usbdiv, offset;
/** divisors,
* for jz4760b,I:H:H2:P:M:S.
* DIV should be one of [1, 2, 3, 4, 6, 8]
*/
- const int div[6] = {1, 4, 4, 4, 4, 4};
+ const int div[2][6] = { { 1, 2, 2, 2, 2, 2 },
+ { 1, 6, 6, 6, 6, 6 } };
const int n2FR[9] = {
0, 0, 1, 2, 3, 0, 4, 0, 5
};
- /* @ CPU_FREQ of 492MHZ, this means:
- 492MHz CCLK
- 123MHz HCLK
- 123MHz H2CLK
- 123MHz PCLK
- 123MHz MCLK
- 123MHZ SCLK ( must equal H2CLK or HCLK/2)
+ /* @ CPU_FREQ of 576/192MHz, this means:
+ CCLK (= HCLK*n, H2CLK*n, PCLK*o)
+ 96MHz HCLK (= MCLK or 2x MCLK, PCLK*n)
+ 96MHz H2CLK (= HCLK or HCLK/2, PCLK*n)
+ 96MHz PCLK
+ 96MHz MCLK (= PCLK*n)
+ 96MHZ SCLK (= H2CLK or HCLK/2)
*/
+ if (freq > CPUFREQ_NORMAL)
+ offset = 1;
+ else
+ offset = 0;
+
/* set ahb **/
REG32(HARB0_BASE) = 0x00300000;
REG32(0xb3070048) = 0x00000000;
REG32(HARB2_BASE) = 0x00FFFFFF;
cfcr = CPCCR_PCS | // no divisor on PLL for peripherals
- (n2FR[div[0]] << CPCCR_CDIV_LSB) |
- (n2FR[div[1]] << CPCCR_HDIV_LSB) |
- (n2FR[div[2]] << CPCCR_H2DIV_LSB) |
- (n2FR[div[3]] << CPCCR_PDIV_LSB) |
- (n2FR[div[4]] << CPCCR_MDIV_LSB) |
- (n2FR[div[5]] << CPCCR_SDIV_LSB);
+ (n2FR[div[offset][0]] << CPCCR_CDIV_LSB) |
+ (n2FR[div[offset][1]] << CPCCR_HDIV_LSB) |
+ (n2FR[div[offset][2]] << CPCCR_H2DIV_LSB) |
+ (n2FR[div[offset][3]] << CPCCR_PDIV_LSB) |
+ (n2FR[div[offset][4]] << CPCCR_MDIV_LSB) |
+ (n2FR[div[offset][5]] << CPCCR_SDIV_LSB);
// write REG_DDRC_CTRL 8 times to clear ddr fifo
REG_DDRC_CTRL = 0;
@@ -569,6 +575,10 @@ int serial_preinit(void)
return 0;
}
+#ifndef HAVE_ADJUSTABLE_CPU_FREQ
+#define cpu_frequency CPU_FREQ
+#endif
+
void usb_preinit(void)
{
/* Clear ECS bit of CPCCR, 0:clock source is EXCLK, 1:clock source is EXCLK/2 */
@@ -589,7 +599,7 @@ void usb_preinit(void)
REG_CPM_USBVBFIL = 0x80;
/* rdt */
- REG_CPM_USBRDT = (600 * (CPU_FREQ / 1000000)) / 1000;
+ REG_CPM_USBRDT = (600 * (CPUFREQ_DEFAULT / 1000000)) / 1000;
/* rdt - filload_en */
REG_CPM_USBRDT |= (1 << 25);
@@ -649,8 +659,8 @@ void ICODE_ATTR system_main(void)
mmu_init();
- pll0_init(CPU_FREQ); // PLL0 drives everything but audio
- pll1_disable(); // Leave PLL1 disabled until audio needs it
+ pll0_init(CPUFREQ_DEFAULT); // PLL0 drives everything but audio
+ pll1_disable(); // Leave PLL1 disabled until audio needs it
serial_preinit();
usb_preinit();
@@ -713,9 +723,22 @@ int system_memory_guard(int newmode)
return 0;
}
+
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+void cpm_select_msc_clk(void);
+
void set_cpu_frequency(long frequency)
{
- serial_putsf("set_cpu_frequency: %d\n", frequency);
+ if (frequency == cpu_frequency)
+ return;
+ else if (frequency < CPUFREQ_MIN)
+ frequency = CPUFREQ_MIN;
+ else if (frequency > CPUFREQ_MAX)
+ frequency = CPUFREQ_MAX;
+
+ pll0_init(frequency);
+ // FIX PCLK (ie i2c)?
+ cpu_frequency = __cpm_get_pllout2();
+ cpm_select_msc_clk();
}
#endif