Index: firmware/export/config-ipodnano2g.h =================================================================== --- firmware/export/config-ipodnano2g.h (revision 23323) +++ firmware/export/config-ipodnano2g.h (working copy) @@ -151,7 +151,7 @@ #define FLASH_SIZE 0x400000 /* Define this to the CPU frequency */ -#define CPU_FREQ 192000000 +#define CPU_FREQ 191692800 /* Define this if you have ATA power-off control */ //#define HAVE_ATA_POWER_OFF @@ -169,7 +169,7 @@ #define HAVE_WHEEL_POSITION /* Define this if you have adjustable CPU frequency */ -/* #define HAVE_ADJUSTABLE_CPU_FREQ - not yet */ +#define HAVE_ADJUSTABLE_CPU_FREQ #define BOOTFILE_EXT "ipod" #define BOOTFILE "rockbox." BOOTFILE_EXT Index: firmware/export/s5l8700.h =================================================================== --- firmware/export/s5l8700.h (revision 23323) +++ firmware/export/s5l8700.h (working copy) @@ -25,7 +25,7 @@ #define REG16_PTR_T volatile uint16_t * #define REG32_PTR_T volatile uint32_t * -#define TIMER_FREQ 48000000L +#define TIMER_FREQ 47923200L /* 04. CALMADM2E */ @@ -226,6 +226,12 @@ #define DMACADDR7 (*(REG32_PTR_T)(0x384000EC)) /* Current memory address register for channel 7 */ #define DMACTCNT7 (*(REG32_PTR_T)(0x384000F0)) /* Current transfer count register for channel 7 */ #define DMACOM7 (*(REG32_PTR_T)(0x384000F4)) /* Channel 7 command register */ +#define DMABASE8 (*(REG32_PTR_T)(0x38400100)) /* Base address register for channel 8 */ +#define DMACON8 (*(REG32_PTR_T)(0x38400104)) /* Configuration register for channel 8 */ +#define DMATCNT8 (*(REG32_PTR_T)(0x38400108)) /* Transfer count register for channel 8 */ +#define DMACADDR8 (*(REG32_PTR_T)(0x3840010C)) /* Current memory address register for channel 8 */ +#define DMACTCNT8 (*(REG32_PTR_T)(0x38400110)) /* Current transfer count register for channel 8 */ +#define DMACOM8 (*(REG32_PTR_T)(0x38400114)) /* Channel 8 command register */ #define DMAALLST (*(REG32_PTR_T)(0x38400180)) /* All channel status register */ #else #define DMAALLST (*(REG32_PTR_T)(0x38400100)) /* All channel status register */ @@ -304,9 +310,9 @@ #define TDDATA1 (*(REG32_PTR_T)(0x3C70006C)) /* Data1 Register */ #define TDPRE (*(REG32_PTR_T)(0x3C700070)) /* Pre-scale register */ #define TDCNT (*(REG32_PTR_T)(0x3C700074)) /* Counter register */ -#define FIVE_USEC_TIMER ((*(REG32_PTR_T)(0x3C700080) << 32) \ - | *(REG32_PTR_T)(0x3C700084)) /* 64bit 5usec timer */ -#define USEC_TIMER (*(REG32_PTR_T)(0x3C700084) * 5) /* lower 32 bits of the above as a usec timer */ +#define FIVE_USEC_TIMER (((*(REG32_PTR_T)(0x3C700080)) << 32) \ + | (*(REG32_PTR_T)(0x3C700084))) /* 64bit 5usec timer */ +#define USEC_TIMER ((*(REG32_PTR_T)(0x3C700084)) * 5) /* lower 32 bits of the above as a usec timer */ /* 12. NAND FLASH CONTROLER */ #if CONFIG_CPU==S5L8701 Index: firmware/target/arm/s5l8700/system-s5l8700.c =================================================================== --- firmware/target/arm/s5l8700/system-s5l8700.c (revision 23327) +++ firmware/target/arm/s5l8700/system-s5l8700.c (working copy) @@ -24,6 +24,7 @@ #include "panic.h" #ifdef IPOD_NANO2G #include "storage.h" +#include "pmu-target.h" #endif #define default_interrupt(name) \ @@ -70,6 +71,9 @@ default_interrupt(INT_UNK3); +struct mutex boost_mutex; + + void INT_TIMER(void) { if (TACON & 0x00038000) INT_TIMERA(); @@ -153,6 +157,7 @@ void system_init(void) { + mutex_init(&boost_mutex); } void system_reboot(void) @@ -193,29 +198,59 @@ void set_cpu_frequency(long frequency) { + mutex_lock(&boost_mutex); if (cpu_frequency == frequency) return; - - /* CPU/COP frequencies can be scaled between Fbus (min) and Fsys (max). - Fbus should not be set below ~32Mhz with LCD enabled or the display - will be garbled. */ + +#if 1 if (frequency == CPUFREQ_MAX) { + int i; + pmu_write(0x1e, 15); /* Vcore = 1.000V */ + for (i = 0; i < 65536; i++); /* wait for voltage to stabilize */ + /* FCLK_CPU = PLL0, HCLK = PLL0 / 2 */ + CLKCON = (CLKCON & ~0xFF00FF00) | 0x20003100; + CLKCON2 |= 0x200; /* PCLK = HCLK / 2 */ } - else if (frequency == CPUFREQ_NORMAL) + else { + /* FCLK_CPU = PLL0 / 4, HCLK = PLL0 / 4 */ + CLKCON = (CLKCON & ~0xFF00FF00) | 0x33003300; + CLKCON2 &= ~0x200; /* PCLK = HCLK */ + pmu_write(0x1e, 11); /* Vcore = 0.900V */ } + +#else /* Alternative: Also clock down the PLL. Doesn't seem to save much + current, but results in high switching latency. */ + + if (frequency == CPUFREQ_MAX) + { + pmu_write(0x1e, 15); /* Vcore = 1.000V */ + CLKCON &= ~0xFF00FF00; /* Everything back to the OSC */ + PLLCON &= ~1; /* Power down PLL0 */ + PLL0PMS = 0x021200; /* 192 MHz */ + PLL0LCNT = 8100; + PLLCON |= 1; /* Power up PLL0 */ + while (!(PLLLOCK & 1)); /* Wait for PLL to lock */ + CLKCON2 |= 0x200; /* PCLK = HCLK / 2 */ + CLKCON |= 0x20003100; /* FCLK_CPU = PLL0, PCLK = PLL0 / 2 */ + } else { + CLKCON &= ~0xFF00FF00; /* Everything back to the OSC */ + CLKCON2 &= ~0x200; /* PCLK = HCLK */ + PLLCON &= ~1; /* Power down PLL0 */ + PLL0PMS = 0x000500; /* 48 MHz */ + PLL0LCNT = 8100; + PLLCON |= 1; /* Power up PLL0 */ + while (!(PLLLOCK & 1)); /* Wait for PLL to lock */ + CLKCON |= 0x20002000; /* FCLK_CPU = PLL0, PCLK = PLL0 */ + pmu_write(0x1e, 11); /* Vcore = 0.900V */ } +#endif - asm volatile ( - "nop \n\t" - "nop \n\t" - "nop \n\t" - ); - cpu_frequency = frequency; + mutex_unlock(&boost_mutex); } #endif Index: firmware/target/arm/s5l8700/system-target.h =================================================================== --- firmware/target/arm/s5l8700/system-target.h (revision 23327) +++ firmware/target/arm/s5l8700/system-target.h (working copy) @@ -24,9 +24,10 @@ #include "system-arm.h" #include "mmu-target.h" -#define CPUFREQ_DEFAULT 32000000 -#define CPUFREQ_NORMAL 48000000 -#define CPUFREQ_MAX 192000000 +#define CPUFREQ_SLEEP 32768 +#define CPUFREQ_DEFAULT 47923200 +#define CPUFREQ_NORMAL 47923200 +#define CPUFREQ_MAX 191692800 #define inl(a) (*(volatile unsigned long *) (a)) #define outl(a,b) (*(volatile unsigned long *) (b) = (a))