forked from len0rd/rockbox
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
This commit is contained in:
parent
62146ed735
commit
eb0e41c1cc
3 changed files with 66 additions and 25 deletions
|
|
@ -148,8 +148,18 @@
|
||||||
/* Define this if you have a Ingenic JZ4760B */
|
/* Define this if you have a Ingenic JZ4760B */
|
||||||
#define CONFIG_CPU JZ4760B
|
#define CONFIG_CPU JZ4760B
|
||||||
|
|
||||||
/* Define this to the CPU frequency */
|
/* We have adjustable frequency */
|
||||||
#define CPU_FREQ 480000000 /* CPU clock: 480 MHz -- Keep a multiple of 48MHz! */
|
#define CPUFREQ_MAX 576000000 // datasheet sez 600MHz max. Must be multiple of 48!
|
||||||
|
#define CPUFREQ_MIN 192000000
|
||||||
|
#define CPUFREQ_DEFAULT CPUFREQ_MIN
|
||||||
|
|
||||||
|
#define HAVE_ADJUSTABLE_CPU_FREQ
|
||||||
|
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||||
|
//#define HAVE_GUI_BOOST
|
||||||
|
#define CPUFREQ_NORMAL CPUFREQ_MIN
|
||||||
|
#else
|
||||||
|
#define CPU_FREQ CPUFREQ_MAX
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Define this if you want to use the JZ47XX i2c interface */
|
/* Define this if you want to use the JZ47XX i2c interface */
|
||||||
#define CONFIG_I2C I2C_JZ47XX
|
#define CONFIG_I2C I2C_JZ47XX
|
||||||
|
|
|
||||||
|
|
@ -633,14 +633,23 @@ static inline unsigned int jz_sd_calc_clkrt(const int drive, unsigned int rate)
|
||||||
return clkrt;
|
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)
|
if (div == 0)
|
||||||
div = 1;
|
div = 1;
|
||||||
|
|
||||||
|
if (div == __cpm_get_mscdiv())
|
||||||
|
return;
|
||||||
|
|
||||||
REG_CPM_MSCCDR = MSCCDR_MCS | (div - 1);
|
REG_CPM_MSCCDR = MSCCDR_MCS | (div - 1);
|
||||||
DEBUG("MSCCLK == %x\n", REG_CPM_MSCCDR);
|
DEBUG("MSCCLK == %x\n", REG_CPM_MSCCDR);
|
||||||
|
__cpm_enable_pll_change();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the MMC clock frequency */
|
/* 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);
|
jz_sd_stop_clock(drive);
|
||||||
|
|
||||||
/* select clock source from CPM */
|
/* 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);
|
clkrt = jz_sd_calc_clkrt(drive, rate);
|
||||||
REG_MSC_CLKRT(MSC_CHN(drive)) = clkrt;
|
REG_MSC_CLKRT(MSC_CHN(drive)) = clkrt;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
static void pll0_init(unsigned int freq)
|
||||||
{
|
{
|
||||||
register unsigned int cfcr, plcr1;
|
register unsigned int cfcr, plcr1;
|
||||||
int usbdiv;
|
int usbdiv, offset;
|
||||||
|
|
||||||
/** divisors,
|
/** divisors,
|
||||||
* for jz4760b,I:H:H2:P:M:S.
|
* for jz4760b,I:H:H2:P:M:S.
|
||||||
* DIV should be one of [1, 2, 3, 4, 6, 8]
|
* 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] = {
|
const int n2FR[9] = {
|
||||||
0, 0, 1, 2, 3, 0, 4, 0, 5
|
0, 0, 1, 2, 3, 0, 4, 0, 5
|
||||||
};
|
};
|
||||||
|
|
||||||
/* @ CPU_FREQ of 492MHZ, this means:
|
/* @ CPU_FREQ of 576/192MHz, this means:
|
||||||
492MHz CCLK
|
CCLK (= HCLK*n, H2CLK*n, PCLK*o)
|
||||||
123MHz HCLK
|
96MHz HCLK (= MCLK or 2x MCLK, PCLK*n)
|
||||||
123MHz H2CLK
|
96MHz H2CLK (= HCLK or HCLK/2, PCLK*n)
|
||||||
123MHz PCLK
|
96MHz PCLK
|
||||||
123MHz MCLK
|
96MHz MCLK (= PCLK*n)
|
||||||
123MHZ SCLK ( must equal H2CLK or HCLK/2)
|
96MHZ SCLK (= H2CLK or HCLK/2)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (freq > CPUFREQ_NORMAL)
|
||||||
|
offset = 1;
|
||||||
|
else
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
/* set ahb **/
|
/* set ahb **/
|
||||||
REG32(HARB0_BASE) = 0x00300000;
|
REG32(HARB0_BASE) = 0x00300000;
|
||||||
REG32(0xb3070048) = 0x00000000;
|
REG32(0xb3070048) = 0x00000000;
|
||||||
REG32(HARB2_BASE) = 0x00FFFFFF;
|
REG32(HARB2_BASE) = 0x00FFFFFF;
|
||||||
|
|
||||||
cfcr = CPCCR_PCS | // no divisor on PLL for peripherals
|
cfcr = CPCCR_PCS | // no divisor on PLL for peripherals
|
||||||
(n2FR[div[0]] << CPCCR_CDIV_LSB) |
|
(n2FR[div[offset][0]] << CPCCR_CDIV_LSB) |
|
||||||
(n2FR[div[1]] << CPCCR_HDIV_LSB) |
|
(n2FR[div[offset][1]] << CPCCR_HDIV_LSB) |
|
||||||
(n2FR[div[2]] << CPCCR_H2DIV_LSB) |
|
(n2FR[div[offset][2]] << CPCCR_H2DIV_LSB) |
|
||||||
(n2FR[div[3]] << CPCCR_PDIV_LSB) |
|
(n2FR[div[offset][3]] << CPCCR_PDIV_LSB) |
|
||||||
(n2FR[div[4]] << CPCCR_MDIV_LSB) |
|
(n2FR[div[offset][4]] << CPCCR_MDIV_LSB) |
|
||||||
(n2FR[div[5]] << CPCCR_SDIV_LSB);
|
(n2FR[div[offset][5]] << CPCCR_SDIV_LSB);
|
||||||
|
|
||||||
// write REG_DDRC_CTRL 8 times to clear ddr fifo
|
// write REG_DDRC_CTRL 8 times to clear ddr fifo
|
||||||
REG_DDRC_CTRL = 0;
|
REG_DDRC_CTRL = 0;
|
||||||
|
|
@ -569,6 +575,10 @@ int serial_preinit(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_ADJUSTABLE_CPU_FREQ
|
||||||
|
#define cpu_frequency CPU_FREQ
|
||||||
|
#endif
|
||||||
|
|
||||||
void usb_preinit(void)
|
void usb_preinit(void)
|
||||||
{
|
{
|
||||||
/* Clear ECS bit of CPCCR, 0:clock source is EXCLK, 1:clock source is EXCLK/2 */
|
/* 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;
|
REG_CPM_USBVBFIL = 0x80;
|
||||||
|
|
||||||
/* rdt */
|
/* rdt */
|
||||||
REG_CPM_USBRDT = (600 * (CPU_FREQ / 1000000)) / 1000;
|
REG_CPM_USBRDT = (600 * (CPUFREQ_DEFAULT / 1000000)) / 1000;
|
||||||
|
|
||||||
/* rdt - filload_en */
|
/* rdt - filload_en */
|
||||||
REG_CPM_USBRDT |= (1 << 25);
|
REG_CPM_USBRDT |= (1 << 25);
|
||||||
|
|
@ -649,8 +659,8 @@ void ICODE_ATTR system_main(void)
|
||||||
|
|
||||||
mmu_init();
|
mmu_init();
|
||||||
|
|
||||||
pll0_init(CPU_FREQ); // PLL0 drives everything but audio
|
pll0_init(CPUFREQ_DEFAULT); // PLL0 drives everything but audio
|
||||||
pll1_disable(); // Leave PLL1 disabled until audio needs it
|
pll1_disable(); // Leave PLL1 disabled until audio needs it
|
||||||
|
|
||||||
serial_preinit();
|
serial_preinit();
|
||||||
usb_preinit();
|
usb_preinit();
|
||||||
|
|
@ -713,9 +723,22 @@ int system_memory_guard(int newmode)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||||
|
void cpm_select_msc_clk(void);
|
||||||
|
|
||||||
void set_cpu_frequency(long frequency)
|
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
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue