From fe23dc8f15e9d01ea634d10b334984f1d8760007 Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Mon, 2 Jul 2007 05:16:40 +0000 Subject: Improved CPU clock setup for PP502x. PP5020 and PP5022 are not register compatible here, so define the PP5022 targets properly, and introduce a CPU_PP502x macro for easier family check. Improves stability on PP5020 (less freezing, tested with Mini G1) and reduces clock change penalty (500us on PP5020; uses the relock bit on PP5022). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13763 a1c6a512-1295-4272-9138-f99709370657 --- apps/debug_menu.c | 49 ++++++++++++++++++++++++++++++++++--- firmware/export/config-ipodmini2g.h | 4 +-- firmware/export/config-ipodnano.h | 6 ++--- firmware/export/config-ipodvideo.h | 6 ++--- firmware/export/config.h | 8 ++++-- firmware/export/cpu.h | 2 +- firmware/rolo.c | 4 +-- firmware/target/arm/ata-as-arm.S | 4 +-- firmware/target/arm/ata-target.h | 4 +-- firmware/target/arm/ipod/lcd-gray.c | 2 +- firmware/target/arm/pcm-pp.c | 34 ++++++++++++------------- firmware/target/arm/system-pp502x.c | 41 ++++++++++++------------------- firmware/target/arm/system-target.h | 2 +- firmware/target/arm/wmcodec-pp.c | 2 +- 14 files changed, 100 insertions(+), 68 deletions(-) diff --git a/apps/debug_menu.c b/apps/debug_menu.c index fe7d5b584b..086ca9e3a7 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -405,6 +405,34 @@ static bool dbg_flash_id(unsigned* p_manufacturer, unsigned* p_device, #endif /* (CONFIG_CPU == SH7034 || CPU_COLDFIRE) */ #ifndef SIMULATOR +#ifdef CPU_PP502x +static int perfcheck(void) +{ + int result; + int old_level = set_irq_level(HIGHEST_IRQ_LEVEL); + + asm ( + "mov %[res], #0 \n" + "ldr r0, [%[timr]] \n" + "add r0, r0, %[tmo] \n" + "1: \n" + "add %[res], %[res], #1 \n" + "ldr r1, [%[timr]] \n" + "cmp r1, r0 \n" + "bmi 1b \n" + : + [res]"=&r"(result) + : + [timr]"r"(&USEC_TIMER), + [tmo]"r"(10226) + : + "r0", "r1" + ); + set_irq_level(old_level); + return result; +} +#endif + #ifdef HAVE_LCD_BITMAP static bool dbg_hw_info(void) { @@ -535,7 +563,7 @@ static bool dbg_hw_info(void) if (action_userabort(TIMEOUT_BLOCK)) return false; } -#elif CONFIG_CPU == PP5020 +#elif defined(CPU_PP502x) char buf[32]; char pp_version[] = { (PP_VER2 >> 24) & 0xff, (PP_VER2 >> 16) & 0xff, (PP_VER2 >> 8) & 0xff, (PP_VER2) & 0xff, @@ -553,6 +581,10 @@ static bool dbg_hw_info(void) snprintf(buf, sizeof(buf), "PP version: %s", pp_version); lcd_puts(0, 2, buf); + + snprintf(buf, sizeof(buf), "Est. clock (kHz): %d", perfcheck()); + lcd_puts(0, 3, buf); + lcd_update(); while(1) @@ -1020,7 +1052,7 @@ bool dbg_ports(void) return false; } -#elif CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 +#elif defined(CPU_PP502x) unsigned int gpio_a, gpio_b, gpio_c, gpio_d; unsigned int gpio_e, gpio_f, gpio_g, gpio_h; @@ -1066,6 +1098,17 @@ bool dbg_ports(void) lcd_puts(0, line++, buf); snprintf(buf, sizeof(buf), "GPIO_F: %02x GPIO_L: %02x", gpio_f, gpio_l); lcd_puts(0, line++, buf); + line++; + + snprintf(buf, sizeof(buf), "CLOCK_SRC: %08lx", inl(0x60006020)); + lcd_puts(0, line++, buf); + snprintf(buf, sizeof(buf), "PLL_CONTROL: %08lx", inl(0x60006034)); + lcd_puts(0, line++, buf); + snprintf(buf, sizeof(buf), "PLL_STATUS: %08lx", inl(0x6000603c)); + lcd_puts(0, line++, buf); + snprintf(buf, sizeof(buf), "DEV_PLL: %08lx", inl(0x70000020)); + lcd_puts(0, line++, buf); + #if defined(IRIVER_H10) || defined(IRIVER_H10_5GB) line++; snprintf(buf, sizeof(buf), "ADC_BATTERY: %02x", adc_read(ADC_BATTERY)); @@ -1297,7 +1340,7 @@ static bool dbg_cpufreq(void) snprintf(buf, sizeof(buf), "boost_counter: %d", get_cpu_boost_counter()); lcd_puts(0, line++, buf); - + lcd_update(); button = get_action(CONTEXT_STD,HZ/10); diff --git a/firmware/export/config-ipodmini2g.h b/firmware/export/config-ipodmini2g.h index 55831c4cb3..032d32ad4c 100644 --- a/firmware/export/config-ipodmini2g.h +++ b/firmware/export/config-ipodmini2g.h @@ -76,8 +76,8 @@ #ifndef SIMULATOR -/* Define this if you have a PortalPlayer PP5020 */ -#define CONFIG_CPU PP5020 +/* Define this if you have a PortalPlayer PP5022 */ +#define CONFIG_CPU PP5022 /* Define this if you want to use the PP5020 i2c interface */ #define CONFIG_I2C I2C_PP5020 diff --git a/firmware/export/config-ipodnano.h b/firmware/export/config-ipodnano.h index 1d024d8565..37935786b7 100644 --- a/firmware/export/config-ipodnano.h +++ b/firmware/export/config-ipodnano.h @@ -74,10 +74,8 @@ #ifndef SIMULATOR -/* The Nano actually has a PP5021 - but it's register compatible with - the 5020 so Rockbox doesn't care. */ -/* Define this if you have a PortalPlayer PP5020 */ -#define CONFIG_CPU PP5020 +/* Define this if you have a PortalPlayer PP5022 */ +#define CONFIG_CPU PP5022 /* Define this if you want to use the PP5020 i2c interface */ #define CONFIG_I2C I2C_PP5020 diff --git a/firmware/export/config-ipodvideo.h b/firmware/export/config-ipodvideo.h index 46411a7784..e954859eb0 100644 --- a/firmware/export/config-ipodvideo.h +++ b/firmware/export/config-ipodvideo.h @@ -74,10 +74,8 @@ #ifndef SIMULATOR -/* The Nano actually has a PP5021 - but it's register compatible with - the 5020 so Rockbox doesn't care. */ -/* Define this if you have a PortalPlayer PP5020 */ -#define CONFIG_CPU PP5020 +/* Define this if you have a PortalPlayer PP5022 */ +#define CONFIG_CPU PP5022 /* Define this if you want to use the PP5020 i2c interface */ #define CONFIG_I2C I2C_PP5020 diff --git a/firmware/export/config.h b/firmware/export/config.h index ffcbf688ea..86e27d0031 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -43,9 +43,10 @@ #define MCF5250 5250 #define PP5002 5002 #define PP5020 5020 +#define PP5022 5022 +#define PP5024 5024 #define PNX0101 101 #define S3C2440 2440 -#define PP5024 5024 #define TMS320DSC25 25 /* CONFIG_KEYPAD */ @@ -279,8 +280,11 @@ #endif /* define for all cpus from PP family */ -#if (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) || (CONFIG_CPU == PP5024) +#if (CONFIG_CPU == PP5002) +#define CPU_PP +#elif (CONFIG_CPU == PP5020) || (CONFIG_CPU == PP5022) || (CONFIG_CPU == PP5024) #define CPU_PP +#define CPU_PP502x #endif /* define for all cpus from ARM family */ diff --git a/firmware/export/cpu.h b/firmware/export/cpu.h index 6adf52ba5e..eb1c57b646 100644 --- a/firmware/export/cpu.h +++ b/firmware/export/cpu.h @@ -27,7 +27,7 @@ #if CONFIG_CPU == MCF5250 #include "mcf5250.h" #endif -#if CONFIG_CPU == PP5020 +#if (CONFIG_CPU == PP5020) || (CONFIG_CPU == PP5022) #include "pp5020.h" #endif #if CONFIG_CPU == PP5002 diff --git a/firmware/rolo.c b/firmware/rolo.c index 0b8a4f28ba..1ad59e216b 100644 --- a/firmware/rolo.c +++ b/firmware/rolo.c @@ -105,7 +105,7 @@ void rolo_restart(const unsigned char* source, unsigned char* dest, { long i; unsigned char* localdest = dest; -#if (CONFIG_CPU==PP5020) || (CONFIG_CPU==PP5024) +#ifdef CPU_PP502x unsigned long* memmapregs = (unsigned long*)0xf000f000; #endif @@ -120,7 +120,7 @@ void rolo_restart(const unsigned char* source, unsigned char* dest, "jmp (%0) \n" : : "a"(dest) ); -#elif (CONFIG_CPU==PP5020) || (CONFIG_CPU==PP5024) +#elif defined(CPU_PP502x) /* Tell the COP that we've finished loading and started rebooting */ cpu_message = 0; diff --git a/firmware/target/arm/ata-as-arm.S b/firmware/target/arm/ata-as-arm.S index 32fc28c4e0..5c0a1f9660 100644 --- a/firmware/target/arm/ata-as-arm.S +++ b/firmware/target/arm/ata-as-arm.S @@ -25,8 +25,8 @@ * setup. Needs investigation. */ .section .icode,"ax",%progbits .equ .ata_port, 0xc00031e0 -#elif CONFIG_CPU == PP5020 - /* Verified working on (PP5020, PP5021, PP5022) targets */ +#elif defined CPU_PP502x + /* Verified working on (PP5020, PP5022) targets */ .section .icode,"ax",%progbits .equ .ata_port, 0xc30001e0 #elif CONFIG_CPU == S3C2440 diff --git a/firmware/target/arm/ata-target.h b/firmware/target/arm/ata-target.h index d6c5f512e6..d65a7b2822 100644 --- a/firmware/target/arm/ata-target.h +++ b/firmware/target/arm/ata-target.h @@ -17,7 +17,7 @@ * ****************************************************************************/ -#if (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020) +#ifdef CPU_PP #if (CONFIG_CPU == PP5002) @@ -26,7 +26,7 @@ #define ATA_IOBASE 0xc00031e0 #define ATA_CONTROL (*((volatile unsigned char*)(0xc00033f8))) -#elif (CONFIG_CPU == PP5020) +#elif defined CPU_PP502x /* asm optimized reading and writing */ #define ATA_OPTIMIZED_READING diff --git a/firmware/target/arm/ipod/lcd-gray.c b/firmware/target/arm/ipod/lcd-gray.c index 1493751c3b..0a3a4ae797 100644 --- a/firmware/target/arm/ipod/lcd-gray.c +++ b/firmware/target/arm/ipod/lcd-gray.c @@ -41,7 +41,7 @@ static inline bool timer_check(int clock_start, int usecs) #if CONFIG_CPU == PP5002 #define IPOD_LCD_BASE 0xc0001000 #define IPOD_LCD_BUSY_MASK 0x80000000 -#else /* PP5020 */ +#else /* PP502x */ #define IPOD_LCD_BASE 0x70003000 #define IPOD_LCD_BUSY_MASK 0x00008000 #endif diff --git a/firmware/target/arm/pcm-pp.c b/firmware/target/arm/pcm-pp.c index 0608c208eb..35bcd343cb 100644 --- a/firmware/target/arm/pcm-pp.c +++ b/firmware/target/arm/pcm-pp.c @@ -30,7 +30,7 @@ static int rec_peak_left, rec_peak_right; #endif /** DMA **/ -#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 +#ifdef CPU_PP502x #define FIFO_FREE_COUNT ((IISFIFO_CFG & 0x3f000000) >> 24) #elif CONFIG_CPU == PP5002 #define FIFO_FREE_COUNT ((IISFIFO_CFG & 0x7800000) >> 23) @@ -52,7 +52,7 @@ size_t p_size IBSS_ATTR; actually needs to do so when calling pcm_callback_for_more. C version is still included below for reference. */ -#ifdef CPU_PP +#if 1 void fiq(void) ICODE_ATTR __attribute__((naked)); void fiq(void) { @@ -154,12 +154,12 @@ void fiq(void) "b .exit \n\t" ); } -#else /* !(CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002) */ +#else /* C version for reference */ void fiq(void) ICODE_ATTR __attribute__ ((interrupt ("FIQ"))); void fiq(void) { /* Clear interrupt */ -#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 +#ifdef CPU_PP502x IISCONFIG &= ~(1 << 1); #elif CONFIG_CPU == PP5002 inl(0xcf001040); @@ -170,7 +170,7 @@ void fiq(void) while (p_size) { if (FIFO_FREE_COUNT < 2) { /* Enable interrupt */ -#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 +#ifdef CPU_PP502x IISCONFIG |= (1 << 1); #elif CONFIG_CPU == PP5002 IISFIFO_CFG |= (1<<9); @@ -197,7 +197,7 @@ void fiq(void) /* No more data, so disable the FIFO/FIQ */ pcm_play_dma_stop(); } -#endif /* CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002 */ +#endif /* ASM / C selection */ void pcm_play_dma_start(const void *addr, size_t size) { @@ -206,7 +206,7 @@ void pcm_play_dma_start(const void *addr, size_t size) pcm_playing = true; -#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 +#ifdef CPU_PP502x CPU_INT_PRIORITY |= I2S_MASK; /* FIQ priority for I2S */ CPU_INT_EN = I2S_MASK; /* Enable I2S interrupt */ #else @@ -220,7 +220,7 @@ void pcm_play_dma_start(const void *addr, size_t size) enable_fiq(); /* Enable playback FIFO */ -#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 +#ifdef CPU_PP502x IISCONFIG |= (1 << 29); #elif CONFIG_CPU == PP5002 IISCONFIG |= 0x4; @@ -231,7 +231,7 @@ void pcm_play_dma_start(const void *addr, size_t size) while (p_size > 0) { if (FIFO_FREE_COUNT < 2) { /* Enable interrupt */ -#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 +#ifdef CPU_PP502x IISCONFIG |= (1 << 1); #elif CONFIG_CPU == PP5002 IISFIFO_CFG |= (1<<9); @@ -256,7 +256,7 @@ void pcm_play_dma_stop(void) pcm_playing = false; pcm_paused = false; -#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 +#ifdef CPU_PP502x /* Disable playback FIFO and interrupt */ IISCONFIG &= ~((1 << 29) | (1 << 1)); #elif CONFIG_CPU == PP5002 @@ -273,7 +273,7 @@ void pcm_play_dma_stop(void) void pcm_play_pause_pause(void) { -#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 +#ifdef CPU_PP502x /* Disable playback FIFO and interrupt */ IISCONFIG &= ~((1 << 29) | (1 << 1)); #elif CONFIG_CPU == PP5002 @@ -293,7 +293,7 @@ void pcm_play_pause_unpause(void) enable_fiq(); /* Enable playback FIFO */ -#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 +#ifdef CPU_PP502x IISCONFIG |= (1 << 29); #elif CONFIG_CPU == PP5002 IISCONFIG |= 0x4; @@ -304,7 +304,7 @@ void pcm_play_pause_unpause(void) while (p_size > 0) { if (FIFO_FREE_COUNT < 2) { /* Enable interrupt */ -#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 +#ifdef CPU_PP502x IISCONFIG |= (1 << 1); #elif CONFIG_CPU == PP5002 IISFIFO_CFG |= (1<<9); @@ -445,7 +445,7 @@ void fiq_record(void) int status = 0; /* Clear interrupt */ -#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 +#ifdef CPU_PP502x IISCONFIG &= ~(1 << 0); #elif CONFIG_CPU == PP5002 /* TODO */ @@ -454,7 +454,7 @@ void fiq_record(void) while (p_size > 0) { if (FIFO_FREE_COUNT < 2) { /* enable interrupt */ -#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 +#ifdef CPU_PP502x IISCONFIG |= (1 << 0); #elif CONFIG_CPU == PP5002 /* TODO */ @@ -499,7 +499,7 @@ void pcm_record_more(void *start, size_t size) rec_peak_addr = start; /* Start peaking at dest */ p = start; /* Start of RX buffer */ p_size = size; /* Bytes to transfer */ -#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 +#ifdef CPU_PP502x IISCONFIG |= (1 << 0); #elif CONFIG_CPU == PP5002 /* TODO */ @@ -558,7 +558,7 @@ void pcm_init_recording(void) pcm_recording = false; pcm_callback_more_ready = NULL; -#if (CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024) +#ifdef CPU_PP502x #if defined(IPOD_COLOR) || defined (IPOD_4G) /* The usual magic from IPL - I'm guessing this configures the headphone socket to be input or output - in this case, input. */ diff --git a/firmware/target/arm/system-pp502x.c b/firmware/target/arm/system-pp502x.c index 49ffdd300b..658ea0eeb3 100644 --- a/firmware/target/arm/system-pp502x.c +++ b/firmware/target/arm/system-pp502x.c @@ -151,7 +151,7 @@ static void ipod_init_cache(void) #ifdef HAVE_ADJUSTABLE_CPU_FREQ void set_cpu_frequency(long frequency) { - unsigned long postmult; + unsigned long postmult, pll_control; # if NUM_CORES > 1 /* Using mutex or spinlock isn't safe here. */ @@ -168,35 +168,24 @@ void set_cpu_frequency(long frequency) /* Enable PLL? */ outl(inl(0x70000020) | (1<<30), 0x70000020); - + /* Select 24MHz crystal as clock source? */ - outl((inl(0x60006020) & 0x0fffff0f) | 0x20000020, 0x60006020); - + outl((inl(0x60006020) & 0x0ffffff0) | 0x10000002, 0x60006020); + /* Clock frequency = (24/8)*postmult */ - outl(0xaa020000 | 8 | (postmult << 8), 0x60006034); - - /* Wait for PLL relock? */ - udelay(2000); + pll_control = 0x8a020000 | 8 | (postmult << 8); + outl(pll_control, 0x60006034); +# if CONFIG_CPU == PP5020 + outl(0xd198, 0x6000603c); /* magic sequence */ + outl(pll_control, 0x60006034); + udelay(500); /* wait for relock */ +# else /* PP5022, PP5024 */ + while (!(inl(0x6000603c) & 0x80000000)); /* wait for relock */ +# endif /* Select PLL as clock source? */ outl((inl(0x60006020) & 0x0fffff0f) | 0x20000070, 0x60006020); -# if defined(IPOD_COLOR) || defined(IPOD_4G) || defined(IPOD_MINI) || defined(IRIVER_H10) || defined(IRIVER_H10_5GB) - /* We don't know why the timer interrupt gets disabled on the PP5020 - based ipods, but without the following line, the 4Gs will freeze - when CPU frequency changing is enabled. - - Note also that a simple "CPU_INT_EN = TIMER1_MASK;" (as used - elsewhere to enable interrupts) doesn't work, we need "|=". - - It's not needed on the PP5021 and PP5022 ipods. - */ - - /* unmask interrupt source */ - CPU_INT_EN |= TIMER1_MASK; - COP_INT_EN |= TIMER1_MASK; -# endif - # if NUM_CORES > 1 boostctrl_mtx.locked = 0; # endif @@ -213,9 +202,9 @@ void ipod_set_cpu_frequency(void) outl((inl(0x60006020) & 0x0fffff0f) | 0x20000020, 0x60006020); /* Clock frequency = (24/8)*25 = 75MHz */ - outl(0xaa020000 | 8 | (25 << 8), 0x60006034); + outl(0x8a020000 | 8 | (25 << 8), 0x60006034); /* Wait for PLL relock? */ - udelay(2000); + udelay(500); /* Select PLL as clock source? */ outl((inl(0x60006020) & 0x0fffff0f) | 0x20000070, 0x60006020); diff --git a/firmware/target/arm/system-target.h b/firmware/target/arm/system-target.h index 7a4c8b603c..afb1ce7314 100644 --- a/firmware/target/arm/system-target.h +++ b/firmware/target/arm/system-target.h @@ -36,7 +36,7 @@ static inline void udelay(unsigned usecs) while (TIME_BEFORE(USEC_TIMER, stop)); } -#if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5024 +#ifdef CPU_PP502x static inline unsigned int current_core(void) { /* diff --git a/firmware/target/arm/wmcodec-pp.c b/firmware/target/arm/wmcodec-pp.c index 505a31deb4..7d00369bf0 100644 --- a/firmware/target/arm/wmcodec-pp.c +++ b/firmware/target/arm/wmcodec-pp.c @@ -43,7 +43,7 @@ int audiohw_init(void) { /* reset I2C */ i2c_init(); -#if CONFIG_CPU == PP5020 +#ifdef CPU_PP502x /* normal outputs for CDI and I2S pin groups */ DEV_INIT &= ~0x300; -- cgit v1.2.3