diff --git a/firmware/export/config/sansaclipplus.h b/firmware/export/config/sansaclipplus.h
index c52d803..e4c43d9 100644
--- a/firmware/export/config/sansaclipplus.h
+++ b/firmware/export/config/sansaclipplus.h
@@ -187,7 +187,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 eb6fb6c..c308f76 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 b56c8a5..ebee66a 100644
--- a/firmware/export/config/sansafuzev2.h
+++ b/firmware/export/config/sansafuzev2.h
@@ -196,7 +196,7 @@
 #define USB_PRODUCT_ID 0x74c3   /* MSC = 0x74c3, MTP = 0x74c2 */
 
 /* 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/clock-target.h b/firmware/target/arm/as3525/clock-target.h
index 1689c59..e945fd7 100644
--- a/firmware/target/arm/as3525/clock-target.h
+++ b/firmware/target/arm/as3525/clock-target.h
@@ -86,13 +86,7 @@
  * Also note that CGU_PERI is based on fclk, not PLLA
  */
 
-#ifdef SANSA_FUZEV2
-/* display is unbearably slow at 24MHz
- * 34285715 HZ works ok but 40MHz works even better*/
 #define AS3525_DRAM_FREQ        40000000    /* Initial DRAM frequency  */
-#else
-#define AS3525_DRAM_FREQ        24000000    /* Initial DRAM frequency  */
-#endif /* SANSA_FUZEV2 */
 
 #else
 /* AS3525v1 */
diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c
index 2e4747e..e3ec1d7 100644
--- a/firmware/target/arm/as3525/system-as3525.c
+++ b/firmware/target/arm/as3525/system-as3525.c
@@ -403,32 +403,81 @@ 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? */
+
+static inline void clk_wait(void)
+{
+#if 0
+    unsigned i = 40;
+    do {
+        nop;
+    } while(--i);
+#endif
+}
+
 void set_cpu_frequency(long frequency)
 {
     int oldstatus = disable_irq_save();
+    unsigned long cgu_peri = CGU_PERI & ~(0xF << 2);
+
+#if AS3525_PLLA_FREQ != 240000000
+#   error only suited for PLLA_FREQ == CPUFREQ_MAX == 240MHz
+#endif
+
+#if AS3525_PCLK_FREQ == 24000000 /* Clipv2 / Clip+ */
+    /* fclk 240MHz -> 24MHz */
+    static const uint8_t divider[][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 240MHz -> 40MHz */
+    static const uint8_t divider[][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
+
+    const size_t n_divs = sizeof(divider)/sizeof(divider[0]);
 
     /* 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);
+        unsigned i = n_divs - 1;
+        do
+        {
+            CGU_PERI = cgu_peri | (divider[i][1] << 2);
+            clk_wait();
+
+            CGU_PROC =  (divider[i][0]<< 4)
+                      | (AS3525_FCLK_PREDIV  << 2)
+                      | AS3525_FCLK_SEL;
+            clk_wait();
+        } while(i--);
     }
     else
     {
-        CGU_PROC = ((AS3525_FCLK_POSTDIV_UNBOOSTED << 4) |
-                    (AS3525_FCLK_PREDIV  << 2) |
-                    AS3525_FCLK_SEL);
-
-        /* Change PCLK after FCLK is low, so it doesn't go too high */
-        CGU_PERI = (CGU_PERI & ~(0xF << 2)) | (AS3525_PCLK_DIV0_UNBOOSTED << 2);
+        unsigned i = 1;
+        do
+        {
+            CGU_PROC =  (divider[i][0] << 4)
+                      | (AS3525_FCLK_PREDIV  << 2)
+                      | AS3525_FCLK_SEL;
+            clk_wait();
+
+            CGU_PERI = cgu_peri | (divider[i][1] << 2);
+            clk_wait();
+        } while(++i < n_divs);
     }
 
     restore_irq(oldstatus);
