summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCástor Muñoz <cmvidal@gmail.com>2012-03-21 00:02:25 +0100
committerCástor Muñoz <cmvidal@gmail.com>2012-03-31 01:18:15 +0200
commita85780bacc11aa002c4cdde1ca0c57e09518d13d (patch)
tree9040125ef23335589be7d2410e89ad0567c0c2e5
parenta75b5b83d4df1c9295e78d67af24c70c01837456 (diff)
downloadrockbox-a85780bacc11aa002c4cdde1ca0c57e09518d13d.zip
rockbox-a85780bacc11aa002c4cdde1ca0c57e09518d13d.tar.gz
rockbox-a85780bacc11aa002c4cdde1ca0c57e09518d13d.tar.bz2
rockbox-a85780bacc11aa002c4cdde1ca0c57e09518d13d.tar.xz
Classic/6G: CPU frequency/voltage scaling
This patch implements HAVE_ADJUSTABLE_CPU_FREQ, it modifies the following parameters when CPU is unboosted: - s5l8702 voltage is decreased: 1.200V -> 1.050V - CPU frequency is divided by 4: 216MHz -> 54MHz - AHB frequency is divided by 2: 108MHz -> 54MHz Change-Id: I2285b83efb7e1567864ac288f2d4ba55f058f7c5
-rw-r--r--firmware/export/config/ipod6g.h2
-rw-r--r--firmware/target/arm/s5l8702/debug-s5l8702.c2
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/power-ipod6g.c3
-rw-r--r--firmware/target/arm/s5l8702/kernel-s5l8702.c5
-rw-r--r--firmware/target/arm/s5l8702/system-s5l8702.c38
-rw-r--r--firmware/target/arm/s5l8702/system-target.h4
6 files changed, 48 insertions, 6 deletions
diff --git a/firmware/export/config/ipod6g.h b/firmware/export/config/ipod6g.h
index 1941074..7e6faf8 100644
--- a/firmware/export/config/ipod6g.h
+++ b/firmware/export/config/ipod6g.h
@@ -207,7 +207,7 @@
#define HAVE_HARDWARE_CLICK
/* Define this if you have adjustable CPU frequency */
-//#define HAVE_ADJUSTABLE_CPU_FREQ
+#define HAVE_ADJUSTABLE_CPU_FREQ
#define BOOTFILE_EXT "ipod"
#define BOOTFILE "rockbox." BOOTFILE_EXT
diff --git a/firmware/target/arm/s5l8702/debug-s5l8702.c b/firmware/target/arm/s5l8702/debug-s5l8702.c
index 0697e92..27d1ccb 100644
--- a/firmware/target/arm/s5l8702/debug-s5l8702.c
+++ b/firmware/target/arm/s5l8702/debug-s5l8702.c
@@ -58,6 +58,8 @@ bool dbg_hw_info(void)
if(state == 0)
{
_DEBUG_PRINTF("CPU:");
+ _DEBUG_PRINTF("speed: %d MHz", ((CLKCON0 & 1) ?
+ CPUFREQ_NORMAL : CPUFREQ_MAX) / 1000000);
_DEBUG_PRINTF("current_tick: %d", (unsigned int)current_tick);
line++;
diff --git a/firmware/target/arm/s5l8702/ipod6g/power-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/power-ipod6g.c
index 973e269..12948f5 100644
--- a/firmware/target/arm/s5l8702/ipod6g/power-ipod6g.c
+++ b/firmware/target/arm/s5l8702/ipod6g/power-ipod6g.c
@@ -40,6 +40,9 @@ void power_off(void)
void power_init(void)
{
idepowered = false;
+
+ /* DOWN1CTL: CPU DVM step time = 30us (default: no DVM) */
+ pmu_write(0x20, 2);
}
void ide_power_enable(bool on)
diff --git a/firmware/target/arm/s5l8702/kernel-s5l8702.c b/firmware/target/arm/s5l8702/kernel-s5l8702.c
index af54e4d..b39b384 100644
--- a/firmware/target/arm/s5l8702/kernel-s5l8702.c
+++ b/firmware/target/arm/s5l8702/kernel-s5l8702.c
@@ -39,13 +39,14 @@ void tick_start(unsigned int interval_in_ms)
{
int cycles = 10 * interval_in_ms;
- /* configure timer for 10 kHz */
+ /* configure timer for 10 kHz (external source) */
TBCMD = (1 << 1); /* TB_CLR */
- TBPRE = 337 - 1; /* prescaler */
+ TBPRE = 75 - 1; /* prescaler */ /* 12 MHz / 16 / 75 = 10 KHz */
TBCON = (0 << 13) | /* TB_INT1_EN */
(1 << 12) | /* TB_INT0_EN */
(0 << 11) | /* TB_START */
(2 << 8) | /* TB_CS = PCLK / 16 */
+ (1 << 6) | /* UNKNOWN bit */ /* external 12 MHz clock (?) */
(0 << 4); /* TB_MODE_SEL = interval mode */
TBDATA0 = cycles; /* set interval period */
TBCMD = (1 << 0); /* TB_EN */
diff --git a/firmware/target/arm/s5l8702/system-s5l8702.c b/firmware/target/arm/s5l8702/system-s5l8702.c
index 124f016..c3f20c5 100644
--- a/firmware/target/arm/s5l8702/system-s5l8702.c
+++ b/firmware/target/arm/s5l8702/system-s5l8702.c
@@ -255,16 +255,52 @@ void set_cpu_frequency(long frequency)
if (cpu_frequency == frequency)
return;
- //TODO: Need to understand this better
+ /*
+ * CPU scaling parameters:
+ * CPUFREQ_MAX: CPU = 216MHz, AHB = 108MHz, Vcore = 1.200V
+ * CPUFREQ_NORMAL: CPU = 54MHz, AHB = 54MHz, Vcore = 1.050V
+ *
+ * CLKCON0 sets PLL2->FCLK divider (CPU clock)
+ * CLKCON1 sets FCLK->HCLK divider (AHB clock)
+ *
+ * HCLK is derived from FCLK, the system goes unstable if HCLK
+ * is out of the range 54-108 MHz, so two stages are required to
+ * switch FCLK (216 MHz <-> 54 MHz), adjusting HCLK in between
+ * to ensure system stability.
+ */
if (frequency == CPUFREQ_MAX)
{
+ /* Vcore = 1.200V */
+ pmu_write(0x1e, 0x17);
+
+ /* FCLK = PLL2 / 2 (FCLK = 108MHz, HCLK = 108MHz) */
+ CLKCON0 = 0x3011;
+ udelay(50);
+
+ /* HCLK = FCLK / 2 (HCLK = 54MHz) */
CLKCON1 = 0x404101;
+ udelay(50);
+
+ /* FCLK = PLL2 (FCLK = 216MHz, HCLK = 108MHz) */
CLKCON0 = 0x3000;
+ udelay(100);
}
else
{
+ /* FCLK = PLL2 / 2 (FCLK = 108MHz, HCLK = 54MHz) */
CLKCON0 = 0x3011;
+ udelay(50);
+
+ /* HCLK = FCLK (HCLK = 108MHz) */
CLKCON1 = 0x4001;
+ udelay(50);
+
+ /* FCLK = PLL2 / 4 (FCLK = 54MHz, HCLK = 54MHz) */
+ CLKCON0 = 0x3013;
+ udelay(100);
+
+ /* Vcore = 1.050V */
+ pmu_write(0x1e, 0x11);
}
cpu_frequency = frequency;
diff --git a/firmware/target/arm/s5l8702/system-target.h b/firmware/target/arm/s5l8702/system-target.h
index 799efb7..ba05c2f 100644
--- a/firmware/target/arm/s5l8702/system-target.h
+++ b/firmware/target/arm/s5l8702/system-target.h
@@ -26,8 +26,8 @@
#define CPUFREQ_SLEEP 32768
#define CPUFREQ_MAX 216000000
-#define CPUFREQ_DEFAULT 108000000
-#define CPUFREQ_NORMAL 108000000
+#define CPUFREQ_DEFAULT 54000000
+#define CPUFREQ_NORMAL 54000000
#define STORAGE_WANTS_ALIGN