diff --git a/firmware/export/config/sansaclipplus.h b/firmware/export/config/sansaclipplus.h index ab4408a..12151a7 100644 --- a/firmware/export/config/sansaclipplus.h +++ b/firmware/export/config/sansaclipplus.h @@ -188,7 +188,7 @@ #define CONFIG_LED LED_VIRTUAL /* Define this if you have adjustable CPU frequency */ -//#define HAVE_ADJUSTABLE_CPU_FREQ +#define HAVE_ADJUSTABLE_CPU_FREQ #define BOOTFILE_EXT "sansa" #define BOOTFILE "rockbox." BOOTFILE_EXT diff --git a/firmware/export/config/sansaclipv2.h b/firmware/export/config/sansaclipv2.h index 262ed36..4b83b32 100644 --- a/firmware/export/config/sansaclipv2.h +++ b/firmware/export/config/sansaclipv2.h @@ -181,7 +181,7 @@ #define CONFIG_LED LED_VIRTUAL /* Define this if you have adjustable CPU frequency */ -//#define HAVE_ADJUSTABLE_CPU_FREQ +#define HAVE_ADJUSTABLE_CPU_FREQ #define BOOTFILE_EXT "sansa" #define BOOTFILE "rockbox." BOOTFILE_EXT diff --git a/firmware/export/config/sansafuzev2.h b/firmware/export/config/sansafuzev2.h index a21eb34..bc22215 100644 --- a/firmware/export/config/sansafuzev2.h +++ b/firmware/export/config/sansafuzev2.h @@ -196,7 +196,7 @@ #endif /* !BOOTLOADER */ /* Define this if you have adjustable CPU frequency */ -//#define HAVE_ADJUSTABLE_CPU_FREQ +#define HAVE_ADJUSTABLE_CPU_FREQ #define BOOTFILE_EXT "sansa" #define BOOTFILE "rockbox." BOOTFILE_EXT diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c index 44e210a..e880337 100644 --- a/firmware/target/arm/as3525/system-as3525.c +++ b/firmware/target/arm/as3525/system-as3525.c @@ -459,32 +459,87 @@ void set_cpu_frequency(long frequency) } } #else /* as3525v2 */ -/* FIXME : disabled for now, seems to cause buggy memory accesses - * Disabling MMU or putting the function in uncached memory seems to help? */ void set_cpu_frequency(long frequency) { int oldstatus = disable_irq_save(); +#if AS3525_PLLA_FREQ != 240000000 +# error only suited for PLLA_FREQ == CPUFREQ_MAX == 240MHz +#endif + +#if AS3525_PCLK_FREQ == 24000000 /* Clipv2 / Clip+ */ + /* fclk 24MHz -> 240MHz */ + static const uint8_t boosting_div[][2] = { + /* -> change fclk -> tmp pclk -> change pclk -> new pclk */ + /* fclk div pclk div fclk tmp pclk new pclk */ + { 10-1, 1-1 }, // 24 24 24 + { 5-1, 2-1 }, // 48 48 24 + { 3-1, 3-1 }, // 80 40 26.66 + { 2-1, 5-1 }, // 120 40 24 + { 1-1, 10-1 }, // 240 48 24 + }; + + /* fclk 240MHz -> 24MHz */ + static const uint8_t unboosting_div[][2] = { + /* -> change fclk -> tmp pclk -> change pclk -> new pclk */ + /* fclk div pclk div fclk tmp pclk new pclk */ + { 1-1, 10-1 }, // 240 24 24 + { 2-1, 5-1 }, // 120 48 24 + { 3-1, 2-1 }, // 80 20 40 + { 5-1, 1-1 }, // 48 24 48 + { 10-1, 1-1 }, // 24 24 24 + }; +#elif AS3525_PCLK_FREQ == 40000000 /* Fuzev2 */ + /* fclk 40MHz -> 240MHz */ + static const uint8_t boosting_div[][2] = { + /* -> change fclk -> tmp pclk -> change pclk -> new pclk */ + /* fclk div pclk div fclk tmp pclk new pclk */ + { 6-1, 1-1 }, // 40 40 40 + { 6-1, 2-1 }, // 40 40 20 + { 3-1, 4-1 }, // 80 40 20 + { 2-1, 5-1 }, // 120 30 24 + { 1-1, 6-1 }, // 240 48 40 + }; + + /* fclk 240MHz -> 40MHz */ + static const uint8_t unboosting_div[][2] = { + /* -> change fclk -> tmp pclk -> change pclk -> new pclk */ + /* fclk div pclk div fclk tmp pclk new pclk */ + { 1-1, 6-1 }, // 240 40 40 + { 2-1, 3-1 }, // 120 20 40 + { 4-1, 2-1 }, // 60 20 30 + { 6-1, 1-1 }, // 40 20 40 + }; +#endif + /* We only have 2 settings */ cpu_frequency = (frequency == CPUFREQ_MAX) ? frequency : CPUFREQ_NORMAL; if(frequency == CPUFREQ_MAX) { - /* Change PCLK while FCLK is low, so it doesn't go too high */ - CGU_PERI = (CGU_PERI & ~(0xF << 2)) | (AS3525_PCLK_DIV0 << 2); - - CGU_PROC = ((AS3525_FCLK_POSTDIV << 4) | - (AS3525_FCLK_PREDIV << 2) | - AS3525_FCLK_SEL); + const size_t max = sizeof(boosting_div)/sizeof(boosting_div[0]); + unsigned i = 1; /* skip 1st entry */ + for(; i