From cd829dbb26067f529f1648d330af0d68b950c222 Mon Sep 17 00:00:00 2001 From: funman Date: Tue, 26 May 2009 18:44:02 +0000 Subject: [PATCH] FS#10245 by Jack Halpin : Adjust Clocking scheme on Sansa AMS git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21088 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/as3525/ascodec-as3525.c | 2 +- firmware/target/arm/as3525/ata_sd_as3525.c | 7 +- firmware/target/arm/as3525/clock-target.h | 117 +++++++++++++++++---- firmware/target/arm/as3525/debug-as3525.c | 22 ++-- .../target/arm/as3525/sansa-c200v2/lcd-c200v2.c | 2 +- .../target/arm/as3525/sansa-clip/lcd-ssd1303.c | 2 +- .../target/arm/as3525/sansa-e200v2/lcd-e200v2.c | 2 +- firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c | 2 +- firmware/target/arm/as3525/system-as3525.c | 72 +++++++------ 9 files changed, 155 insertions(+), 73 deletions(-) diff --git a/firmware/target/arm/as3525/ascodec-as3525.c b/firmware/target/arm/as3525/ascodec-as3525.c index b9790217a..668c001f9 100644 --- a/firmware/target/arm/as3525/ascodec-as3525.c +++ b/firmware/target/arm/as3525/ascodec-as3525.c @@ -78,7 +78,7 @@ void ascodec_init(void) CGU_PERI |= CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE; /* prescaler for i2c clock */ - prescaler = CLK_DIV(AS3525_PCLK_FREQ, AS3525_I2C_FREQ); + prescaler = AS3525_I2C_PRESCALER; I2C2_CPSR0 = prescaler & 0xFF; /* 8 lsb */ I2C2_CPSR1 = (prescaler >> 8) & 0x3; /* 2 msb */ diff --git a/firmware/target/arm/as3525/ata_sd_as3525.c b/firmware/target/arm/as3525/ata_sd_as3525.c index 6d6b275fb..03a6a8bd0 100644 --- a/firmware/target/arm/as3525/ata_sd_as3525.c +++ b/firmware/target/arm/as3525/ata_sd_as3525.c @@ -456,8 +456,7 @@ static void init_pl180_controller(const int drive) MCI_SELECT(drive) = 0; - MCI_CLOCK(drive) = MCI_CLOCK_ENABLE | - (((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SD_IDENT_FREQ)) / 2) - 1); + MCI_CLOCK(drive) = MCI_CLOCK_ENABLE | AS3525_SD_IDENT_DIV; mci_delay(); } @@ -466,8 +465,8 @@ int sd_init(void) int ret; CGU_IDE = (1<<7) /* AHB interface enable */ | (1<<6) /* interface enable */ | - ((CLK_DIV(AS3525_PLLA_FREQ, AS3525_IDE_FREQ) - 1) << 2) | - 1; /* clock source = PLLA */ + (AS3525_IDE_DIV << 2) | + AS3525_CLK_PLLA; /* clock source = PLLA */ CGU_PERI |= CGU_NAF_CLOCK_ENABLE; diff --git a/firmware/target/arm/as3525/clock-target.h b/firmware/target/arm/as3525/clock-target.h index 1928f1fbf..a6e492738 100644 --- a/firmware/target/arm/as3525/clock-target.h +++ b/firmware/target/arm/as3525/clock-target.h @@ -24,47 +24,120 @@ /* returns clock divider, given maximal target frequency and clock reference */ #define CLK_DIV(ref, target) ((ref + target - 1) / target) -/* PLL */ -#define AS3525_PLLA_FREQ 248000000 +/* Frequency and Bus Settings + * These bus settings work on the assumption that unboosted performance will be + * based on fastbus mode(FCLK == PCLK) at a frequency configured with this file. + * Boosted performance defaults to synchronous bus but will be changed to + * asynchronous bus if FCLK is not an integer multiple of PCLK. + * The player starts up in fastbus mode and synchronous or asynchronous mode is + * implemented in the set_cpu_frequency() function in system-as3525.c. There + * are limitations on both frequencies and frequency relationships listed in 7.3.14 + * of the as3525 datasheet that need to be observed. If you are determined to + * use a frequency that is not "legal" you can do that. There are no checks for + * legal frequency values, only some validity checks to make sure the divider + * value fits into the number of bits allotted to it. + * + * The CLOCK_DIV macro does a pretty good job at selecting divider values but + * you can always overide it by choosing your own value and commenting out the + * macro. If you are going to use AS3525_FCLK_PREDIV or AS3525_PCLK_DIV1 you + * will have to do a manual calculation. I have included USB & PLLB for future + * use but commented them out for now. + */ + +/* Clock Sources */ +#define AS3525_CLK_MAIN 0 +#define AS3525_CLK_PLLA 1 +//#define AS3525_CLK_PLLB 2 +#define AS3525_CLK_FCLK 3 /* for synchronous bus only */ + +/* PLL frequencies and settings*/ + +#define AS3525_PLLA_FREQ 248000000 /*124,82.7,62,49.6,41.3,35.4 */ + /* FCLK_PREDIV-> *7/8 = 217MHz 108.5 ,72.3, 54.25, 43.4, 36.17 */ + /* *6/8 = 186MHz 93, 62, 46.5, 37.2 */ + /* *5/8 = 155MHz 77.5, 51.67, 38.75 */ #define AS3525_PLLA_SETTING 0x261F -/* CPU */ +//#define AS3525_PLLA_FREQ 384000000 /*192,128,96,76.8,64,54.9,48,42.7,38.4*/ + /* FCLK_PREDIV-> *7/8 = 336MHz 168, 112, 84, 67.2, 56, 48, 42, 37.3*/ + /* *6/8 = 288MHz 144, 96, 72, 57.6, 48, 41.1, */ + /* *5/8 = 240MHz 120, 80, 60, 48, 40 */ +//#define AS3525_PLLA_SETTING 0x2630 -/* ensure that PLLA_FREQ * prediv == CPUFREQ_MAX */ -#define AS3525_CPU_PREDIV 0 /* div = 1/1 */ +/* PLLB not used at this time! */ +//#define AS3525_PLLB_FREQ +//#define AS3525_PLLB_SETTING -#define CPUFREQ_MAX 248000000 +/** ************ Change these to reconfigure clocking scheme *******************/ -#define CPUFREQ_DEFAULT 24800000 +#define AS3525_FCLK_FREQ 248000000 /* Boosted FCLK frequency */ +#define AS3525_PCLK_FREQ 62000000 /* Initial PCLK frequency */ +#define AS3525_DBOP_FREQ AS3525_PCLK_FREQ /* Initial DBOP frequency */ -#define CPUFREQ_NORMAL 31000000 +/** ****************************************************************************/ -/* peripherals */ +/* Figure out if we need to use asynchronous bus */ +#if (AS3525_FCLK_FREQ % AS3525_PCLK_FREQ) +#define ASYNCHRONOUS_BUS /* Boosted mode asynchronous */ +#endif -#define AS3525_PCLK_FREQ 62000000 -#if (CLK_DIV(AS3525_PLLA_FREQ, AS3525_PCLK_FREQ) - 1) >= (1<<4) /* 4 bits */ -#error PCLK frequency is too low : clock divider will not fit ! +/* Tell the software what frequencies we're running */ +#define CPUFREQ_MAX AS3525_FCLK_FREQ +#define CPUFREQ_DEFAULT AS3525_PCLK_FREQ +#define CPUFREQ_NORMAL AS3525_PCLK_FREQ + +/* FCLK */ +#define AS3525_FCLK_SEL AS3525_CLK_PLLA +#define AS3525_FCLK_PREDIV 0 /* div = (8-n)/8 acts strange when used!*/ +#define AS3525_FCLK_POSTDIV (CLK_DIV(AS3525_PLLA_FREQ, AS3525_FCLK_FREQ) - 1) /*div=1/(n+1)*/ + +/* PCLK */ +#ifdef ASYNCHRONOUS_BUS +#define AS3525_PCLK_SEL AS3525_CLK_PLLA /* PLLA input for asynchronous */ +#define AS3525_PCLK_DIV0 (CLK_DIV(AS3525_PLLA_FREQ, AS3525_PCLK_FREQ) - 1)/*div=1/(n+1)*/ +#else +#define AS3525_PCLK_SEL AS3525_CLK_FCLK /* Fclk input for synchronous */ +#define AS3525_PCLK_DIV0 (CLK_DIV(AS3525_FCLK_FREQ, AS3525_PCLK_FREQ) - 1) /*div=1/(n+1)*/ #endif +#define AS3525_PCLK_DIV1 0 /* div = 1/(n+1) unable to use successfuly so far*/ + + /* PCLK as Source */ + #define AS3525_DBOP_DIV (CLK_DIV(AS3525_PCLK_FREQ, AS3525_DBOP_FREQ) - 1) /*div=1/(n+1)*/ + #define AS3525_I2C_PRESCALER CLK_DIV(AS3525_PCLK_FREQ, AS3525_I2C_FREQ) + #define AS3525_I2C_FREQ 400000 + #define AS3525_SD_IDENT_DIV ((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SD_IDENT_FREQ) / 2) - 1) + #define AS3525_SD_IDENT_FREQ 400000 /* must be between 100 & 400 kHz */ -#define AS3525_IDE_FREQ 90000000 /* The OF uses 66MHz maximal freq +#define AS3525_IDE_SEL AS3525_CLK_PLLA /* Input Source */ +#define AS3525_IDE_DIV (CLK_DIV(AS3525_PLLA_FREQ, AS3525_IDE_FREQ) - 1)/*div=1/(n+1)*/ +#define AS3525_IDE_FREQ 90000000 /* The OF uses 66MHz maximal freq but sd transfers fail on some players with this limit */ + +//#define AS3525_USB_SEL AS3525_CLK_PLLA /* Input Source */ +//#define AS3525_USB_DIV /* div = 1/(n=0?1:2n)*/ + + +/* Validity Checks */ + +/* AS3525_PCLK_FREQ */ +#if (CLK_DIV(AS3525_PLLA_FREQ, AS3525_PCLK_FREQ) - 1) >= (1<<4) /* 4 bits */ +#error PCLK frequency is too low : clock divider will not fit ! +#endif +/* AS3525_DBOP_FREQ */ +#if (CLK_DIV(AS3525_PCLK_FREQ, AS3525_DBOP_FREQ) - 1) >= (1<<3) /* 3 bits */ +#error DBOP frequency is too low : clock divider will not fit ! +#endif +/* AS3525_IDE_FREQ */ #if (CLK_DIV(AS3525_PLLA_FREQ, AS3525_IDE_FREQ) - 1) >= (1<<4) /* 4 bits */ #error IDE frequency is too low : clock divider will not fit ! #endif - -#define AS3525_I2C_FREQ 400000 +/* AS3525_I2C_FREQ */ #if (CLK_DIV(AS3525_PCLK_FREQ, AS3525_I2C_FREQ)) >= (1<<10) /* 2+8 bits */ #error I2C frequency is too low : clock divider will not fit ! #endif - -#define AS3525_DBOP_FREQ 32000000 -#if (CLK_DIV(AS3525_PCLK_FREQ, AS3525_DBOP_FREQ) - 1) >= (1<<3) /* 3 bits */ -#error DBOP frequency is too low : clock divider will not fit ! -#endif - -#define AS3525_SD_IDENT_FREQ 400000 /* must be between 100 & 400 kHz */ +/* AS3525_SD_IDENT_FREQ */ #if ((CLK_DIV(AS3525_PCLK_FREQ, AS3525_SD_IDENT_FREQ) / 2) - 1) >= (1<<8) /* 8 bits */ #error SD IDENTIFICATION frequency is too low : clock divider will not fit ! #endif diff --git a/firmware/target/arm/as3525/debug-as3525.c b/firmware/target/arm/as3525/debug-as3525.c index ac7253d57..ea1bf9c38 100644 --- a/firmware/target/arm/as3525/debug-as3525.c +++ b/firmware/target/arm/as3525/debug-as3525.c @@ -120,39 +120,39 @@ int calc_freq(int clk) switch(CGU_PROC & 3) { case 0: return CLK_MAIN/ - ((8/(8-((CGU_PROC & 0xc)>>2)))*(((CGU_PROC & 0xf0)>>4) + 1)); + ((8/(8-((CGU_PROC>>2)& 0x3)))*(((CGU_PROC>>4)& 0xf) + 1)); case 1: return calc_freq(CLK_PLLA)/ - ((8/(8-((CGU_PROC & 0xc)>>2)))*(((CGU_PROC & 0xf0)>>4) + 1)); + ((8/(8-((CGU_PROC>>2)& 0x3)))*(((CGU_PROC>>4)& 0xf) + 1)); case 2: return calc_freq(CLK_PLLB)/ - ((8/(8-((CGU_PROC & 0xc)>>2)))*(((CGU_PROC & 0xf0)>>4) + 1)); + ((8/(8-((CGU_PROC>>2)& 0x3)))*(((CGU_PROC>>4)& 0xf) + 1)); default: return 0; } case CLK_EXTMEM: switch(CGU_PERI & 3) { case 0: - return CLK_MAIN/(((CGU_PERI & 0x3c)>>2)+1); + return CLK_MAIN/(((CGU_PERI>>2)& 0xf)+1); case 1: - return calc_freq(CLK_PLLA)/(((CGU_PERI & 0x3c)>>2)+1); + return calc_freq(CLK_PLLA)/(((CGU_PERI>>2)& 0xf)+1); case 2: - return calc_freq(CLK_PLLB)/(((CGU_PERI & 0x3c)>>2)+1); + return calc_freq(CLK_PLLB)/(((CGU_PERI>>2)& 0xf)+1); case 3: - return calc_freq(CLK_FCLK)/(((CGU_PERI & 0x3c)>>2)+1); + return calc_freq(CLK_FCLK)/(((CGU_PERI>>2)& 0xf)+1); default: return 0; } case CLK_PCLK: - return calc_freq(CLK_EXTMEM)/(((CGU_PERI & 0x40)>>6)+1); + return calc_freq(CLK_EXTMEM)/(((CGU_PERI>>6)& 0x1)+1); case CLK_IDE: switch(CGU_IDE & 3) { case 0: - return CLK_MAIN/(((CGU_IDE & 0x3c)>>2)+1); + return CLK_MAIN/(((CGU_IDE>>2)& 0xf)+1); case 1: - return calc_freq(CLK_PLLA)/(((CGU_IDE & 0x3c)>>2)+1);; + return calc_freq(CLK_PLLA)/(((CGU_IDE>>2)& 0xf)+1); case 2: - return calc_freq(CLK_PLLB)/(((CGU_IDE & 0x3c)>>2)+1); + return calc_freq(CLK_PLLB)/(((CGU_IDE>>2)& 0xf)+1); default: return 0; } diff --git a/firmware/target/arm/as3525/sansa-c200v2/lcd-c200v2.c b/firmware/target/arm/as3525/sansa-c200v2/lcd-c200v2.c index 0ffe0bdc8..e16b082ce 100644 --- a/firmware/target/arm/as3525/sansa-c200v2/lcd-c200v2.c +++ b/firmware/target/arm/as3525/sansa-c200v2/lcd-c200v2.c @@ -98,7 +98,7 @@ static void lcd_delay(int x) /* DBOP initialisation, do what OF does */ static void ams3525_dbop_init(void) { - CGU_DBOP = (1<<3) | (CLK_DIV(AS3525_PCLK_FREQ, AS3525_DBOP_FREQ) - 1); + CGU_DBOP = (1<<3) | AS3525_DBOP_DIV; DBOP_TIMPOL_01 = 0xe167e167; DBOP_TIMPOL_23 = 0xe167006e; diff --git a/firmware/target/arm/as3525/sansa-clip/lcd-ssd1303.c b/firmware/target/arm/as3525/sansa-clip/lcd-ssd1303.c index 70db6a3f0..c0df1f766 100644 --- a/firmware/target/arm/as3525/sansa-clip/lcd-ssd1303.c +++ b/firmware/target/arm/as3525/sansa-clip/lcd-ssd1303.c @@ -70,7 +70,7 @@ /* DBOP initialisation, do what OF does */ static void ams3525_dbop_init(void) { - CGU_DBOP = (1<<3) | (CLK_DIV(AS3525_PCLK_FREQ, AS3525_DBOP_FREQ) - 1); + CGU_DBOP = (1<<3) | AS3525_DBOP_DIV; GPIOB_AFSEL = 0x08; /* DBOP on pin 3 */ GPIOC_AFSEL = 0x0f; /* DBOP on pins 3:0 */ diff --git a/firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c b/firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c index 9e23dac34..2958298b7 100644 --- a/firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c +++ b/firmware/target/arm/as3525/sansa-e200v2/lcd-e200v2.c @@ -108,7 +108,7 @@ static void lcd_delay(int x) /* DBOP initialisation, do what OF does */ static void ams3525_dbop_init(void) { - CGU_DBOP = (1<<3) | (CLK_DIV(AS3525_PCLK_FREQ, AS3525_DBOP_FREQ) - 1); + CGU_DBOP = (1<<3) | AS3525_DBOP_DIV; DBOP_TIMPOL_01 = 0xe167e167; DBOP_TIMPOL_23 = 0xe167006e; diff --git a/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c b/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c index f0c85f53b..f713425b9 100644 --- a/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c +++ b/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c @@ -50,7 +50,7 @@ static bool lcd_busy = false; static void as3525_dbop_init(void) { - CGU_DBOP = (1<<3) | (CLK_DIV(AS3525_PCLK_FREQ, AS3525_DBOP_FREQ) - 1); + CGU_DBOP = (1<<3) | AS3525_DBOP_DIV; DBOP_TIMPOL_01 = 0xe167e167; DBOP_TIMPOL_23 = 0xe167006e; diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c index a5f34d9b8..2f320e91a 100644 --- a/firmware/target/arm/as3525/system-as3525.c +++ b/firmware/target/arm/as3525/system-as3525.c @@ -229,29 +229,25 @@ void system_init(void) CGU_PROC = 0; /* fclk 24 MHz */ CGU_PERI &= ~0x7f; /* pclk 24 MHz */ - asm volatile( - "mrc p15, 0, r0, c1, c0 \n" - "orr r0, r0, #0xC0000000 \n" /* asynchronous clocking */ - "mcr p15, 0, r0, c1, c0 \n" - : : : "r0" ); - CGU_PLLA = AS3525_PLLA_SETTING; - while(!(CGU_INTCTRL & (1<<0))); /* wait until PLLA is locked */ - - CGU_PROC = (AS3525_CPU_PREDIV << 2) | 1; - - CGU_PERI |= ((CLK_DIV(AS3525_PLLA_FREQ, AS3525_PCLK_FREQ) - 1) << 2) - | 1; /* clk_in = PLLA */ + while(!(CGU_INTCTRL & (1<<0))); /* wait until PLLA is locked */ + + /* Set FCLK frequency */ + CGU_PROC = ((AS3525_FCLK_POSTDIV << 4) | + (AS3525_FCLK_PREDIV << 2) | + AS3525_FCLK_SEL); + /* Set PCLK frequency */ + CGU_PERI = ((CGU_PERI & 0xffffff80) | /* reset divider bits 0:6 */ + (AS3525_PCLK_DIV0 << 2) | + (AS3525_PCLK_DIV1 << 6) | + AS3525_PCLK_SEL); - - /* FIXME: dcache will not be active, since the mmu is not running - * See arm922t datasheet */ asm volatile( "mov r0, #0 \n" - "mcr p15, 0, r0, c7, c7 \n" /* invalidate icache & dcache */ - "mrc p15, 0, r0, c1, c0 \n" /* control register */ - "orr r0, r0, #0x1000 \n" /* enable icache */ - "orr r0, r0, #4 \n" /* enable dcache */ + "mcr p15, 0, r0, c7, c7 \n" /* invalidate icache & dcache */ + "mrc p15, 0, r0, c1, c0 \n" /* control register */ + "bic r0, r0, #3<<30 \n" /* clears bus bits & sets fastbus */ + "orr r0, r0, #1<<12 \n" /* enable icache */ "mcr p15, 0, r0, c1, c0 \n" : : : "r0" ); @@ -281,10 +277,6 @@ void system_init(void) fmradio_i2c_init(); #endif #endif /* !BOOTLOADER */ - -#ifdef HAVE_ADJUSTABLE_CPU_FREQ - set_cpu_frequency(CPUFREQ_DEFAULT); -#endif } void system_reboot(void) @@ -311,16 +303,34 @@ int system_memory_guard(int newmode) #ifdef HAVE_ADJUSTABLE_CPU_FREQ void set_cpu_frequency(long frequency) { - int divider = frequency ? (CPUFREQ_MAX / frequency) : 16 /* minimal */ ; + if(frequency == CPUFREQ_MAX) + { - if(divider > 16) - divider = 16; - else if(divider < 1) - divider = 1; + asm volatile( + "mrc p15, 0, r0, c1, c0 \n" - cpu_frequency = CPUFREQ_MAX / divider; +#ifdef ASYNCHRONOUS_BUS + "orr r0, r0, #3<<30 \n" /* asynchronous bus clocking */ +#else + "bic r0, r0, #3<<30 \n" /* clear bus bits */ + "orr r0, r0, #1<<30 \n" /* synchronous bus clocking */ +#endif - CGU_PROC = (CGU_PROC & 0x0f) | ((divider-1) << 4); + "mcr p15, 0, r0, c1, c0 \n" + : : : "r0" ); + + cpu_frequency = CPUFREQ_MAX; + } + else + { + asm volatile( + "mrc p15, 0, r0, c1, c0 \n" + "bic r0, r0, #3<<30 \n" /* fastbus clocking */ + "mcr p15, 0, r0, c1, c0 \n" + : : : "r0" ); + + cpu_frequency = CPUFREQ_NORMAL; + } } #endif /* HAVE_ADJUSTABLE_CPU_FREQ */ -#endif /* BOOTLOADER */ +#endif /* !BOOTLOADER */ -- 2.11.4.GIT