summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/export/pp5020.h6
-rw-r--r--firmware/target/arm/pp/system-pp502x.c81
2 files changed, 60 insertions, 27 deletions
diff --git a/firmware/export/pp5020.h b/firmware/export/pp5020.h
index 073d33e494..0d2ffc4d94 100644
--- a/firmware/export/pp5020.h
+++ b/firmware/export/pp5020.h
@@ -584,8 +584,10 @@
584#define CACHE_DATA_BASE (*(volatile unsigned long*)(0xf0000000)) 584#define CACHE_DATA_BASE (*(volatile unsigned long*)(0xf0000000))
585/* 0xf0002000-0xf0003fff */ 585/* 0xf0002000-0xf0003fff */
586#define CACHE_DATA_MIRROR_BASE (*(volatile unsigned long*)(0xf0002000)) 586#define CACHE_DATA_MIRROR_BASE (*(volatile unsigned long*)(0xf0002000))
587/* 0xf0004000-0xf0007fff */ 587/* 0xf0004000-0xf0005fff */
588#define CACHE_STATUS_BASE (*(volatile unsigned long*)(0xf0004000)) 588#define CACHE_STATUS_BASE_CPU (*(volatile unsigned long*)(0xf0004000))
589/* 0xf0006000-0xf0007fff */
590#define CACHE_STATUS_BASE_COP (*(volatile unsigned long*)(0xf0006000))
589#define CACHE_FLUSH_BASE (*(volatile unsigned long*)(0xf0008000)) 591#define CACHE_FLUSH_BASE (*(volatile unsigned long*)(0xf0008000))
590#define CACHE_INVALID_BASE (*(volatile unsigned long*)(0xf000c000)) 592#define CACHE_INVALID_BASE (*(volatile unsigned long*)(0xf000c000))
591#define MMAP_PHYS_READ_MASK 0x0100 593#define MMAP_PHYS_READ_MASK 0x0100
diff --git a/firmware/target/arm/pp/system-pp502x.c b/firmware/target/arm/pp/system-pp502x.c
index ad0577c38f..686e2ac3bd 100644
--- a/firmware/target/arm/pp/system-pp502x.c
+++ b/firmware/target/arm/pp/system-pp502x.c
@@ -29,6 +29,21 @@
29#include "button-target.h" 29#include "button-target.h"
30#include "usb_drv.h" 30#include "usb_drv.h"
31 31
32/* Bit 0 - 20: Cached Address */
33#define CACHE_ADDRESS_MASK ((1<<21)-1)
34/* Bit 22: Cache line dirty */
35#define CACHE_LINE_DIRTY (1<<22)
36/* Bit 23: Cache line valid */
37#define CACHE_LINE_VALID (1<<23)
38/* Cache Size - 8K*/
39#define CACHE_SIZE 0x2000
40
41/*Initial memory address used to prime cache
42 * could be targeted to a more 'important' address
43 * Note: Don't start at 0x0, as the compiler thinks it's a
44 * null pointer dereference and will helpfully blow up the code. */
45#define CACHED_INIT_ADDR CACHEALIGN_UP(0x2000)
46
32#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE) 47#if !defined(BOOTLOADER) || defined(HAVE_BOOTLOADER_USB_MODE)
33extern void TIMER1(void); 48extern void TIMER1(void);
34extern void TIMER2(void); 49extern void TIMER2(void);
@@ -44,7 +59,7 @@ unsigned char probed_ramsize;
44 59
45void __attribute__((interrupt("IRQ"))) irq_handler(void) 60void __attribute__((interrupt("IRQ"))) irq_handler(void)
46{ 61{
47 if(CURRENT_CORE == CPU) 62 if(IF_COP_CORE(CPU) == CPU)
48 { 63 {
49 if (CPU_INT_STAT & TIMER1_MASK) { 64 if (CPU_INT_STAT & TIMER1_MASK) {
50 TIMER1(); 65 TIMER1();
@@ -218,6 +233,39 @@ void ICODE_ATTR commit_dcache(void)
218 } 233 }
219} 234}
220 235
236static void ICODE_ATTR cache_invalidate_special(void)
237{
238 /* Cache lines which are not marked as valid can cause memory
239 * corruption when there are many writes to and code fetches from
240 * cached memory. This workaround points all cache status to the
241 * maximum line address and marked valid but not dirty. Since that area
242 * is never accessed, the cache lines don't affect anything, and
243 * they're effectively discarded. Interrupts must be disabled here
244 * because any change they make to cached memory could be discarded.
245 * A status word is 32 bits and is mirrored four times for each cache line
246 bit 0-20 line_address >> 11
247 bit 21 unused?
248 bit 22 line_dirty
249 bit 23 line_valid
250 bit 24-31 unused?
251 */
252 register volatile unsigned long *p;
253 if (IF_COP_CORE(CPU) == CPU)
254 {
255 for (p = &CACHE_STATUS_BASE_CPU;
256 p < (&CACHE_STATUS_BASE_CPU) + CACHE_SIZE;
257 p += CACHEALIGN_BITS) /* sizeof(p) * CACHEALIGN_BITS */
258 *p = CACHE_LINE_VALID | CACHE_ADDRESS_MASK;
259 }
260 else
261 {
262 for (p = &CACHE_STATUS_BASE_COP;
263 p < (&CACHE_STATUS_BASE_COP) + CACHE_SIZE;
264 p += CACHEALIGN_BITS)
265 *p = CACHE_LINE_VALID | CACHE_ADDRESS_MASK;
266 }
267}
268
221void ICODE_ATTR commit_discard_idcache(void) 269void ICODE_ATTR commit_discard_idcache(void)
222{ 270{
223 if (CACHE_CTL & CACHE_CTL_ENABLE) 271 if (CACHE_CTL & CACHE_CTL_ENABLE)
@@ -225,21 +273,7 @@ void ICODE_ATTR commit_discard_idcache(void)
225 register int istat = disable_interrupt_save(IRQ_FIQ_STATUS); 273 register int istat = disable_interrupt_save(IRQ_FIQ_STATUS);
226 274
227 commit_dcache(); 275 commit_dcache();
228 276 cache_invalidate_special();
229 /* Cache lines which are not marked as valid can cause memory
230 * corruption when there are many writes to and code fetches from
231 * cached memory. This workaround points all cache status words past
232 * end of RAM and marks them as valid, but not dirty. Since that area
233 * is never accessed, the cache lines don't affect anything, and
234 * they're effectively discarded. Interrupts must be disabled here
235 * because any change they make to cached memory could be discarded.
236 */
237
238 register volatile unsigned long *p;
239 for (p = &CACHE_STATUS_BASE;
240 p < (&CACHE_STATUS_BASE) + 512*16/sizeof(*p);
241 p += 16/sizeof(*p))
242 *p = ((MEMORYSIZE*0x100000) >> 11) | 0x800000;
243 277
244 restore_interrupt(istat); 278 restore_interrupt(istat);
245 } 279 }
@@ -258,7 +292,7 @@ static void init_cache(void)
258 292
259#ifndef BOOTLOADER 293#ifndef BOOTLOADER
260 /* what's this do? */ 294 /* what's this do? */
261 CACHE_PRIORITY |= CURRENT_CORE == CPU ? 0x10 : 0x20; 295 CACHE_PRIORITY |= IF_COP_CORE(CPU) == CPU ? 0x10 : 0x20;
262#endif 296#endif
263 297
264 /* Cache if (addr & mask) >> 16 == (mask & match) >> 16: 298 /* Cache if (addr & mask) >> 16 == (mask & match) >> 16:
@@ -278,11 +312,8 @@ static void init_cache(void)
278 * can run from cached RAM, rewriting of cache status words may not 312 * can run from cached RAM, rewriting of cache status words may not
279 * be safe and the cache is filled instead by reading. */ 313 * be safe and the cache is filled instead by reading. */
280 314
281 /* Note: Don't start at 0x0, as the compiler thinks it's a 315 register volatile char *p = (volatile char *)CACHED_INIT_ADDR;
282 null pointer dereference and will helpfully blow up the code. */ 316 for (;p < (volatile char *)CACHED_INIT_ADDR + CACHE_SIZE; p += CACHEALIGN_SIZE)
283
284 register volatile char *p;
285 for (p = (volatile char *)0x1000; p < (volatile char *)0x3000; p += 0x10)
286 (void)*p; 317 (void)*p;
287} 318}
288#endif /* BOOTLOADER || HAVE_BOOTLOADER_USB_MODE */ 319#endif /* BOOTLOADER || HAVE_BOOTLOADER_USB_MODE */
@@ -293,7 +324,7 @@ static void init_cache(void)
293void scale_suspend_core(bool suspend) ICODE_ATTR; 324void scale_suspend_core(bool suspend) ICODE_ATTR;
294void scale_suspend_core(bool suspend) 325void scale_suspend_core(bool suspend)
295{ 326{
296 unsigned int core = CURRENT_CORE; 327 unsigned int core = IF_COP_CORE(CPU);
297 IF_COP( unsigned int othercore = 1 - core; ) 328 IF_COP( unsigned int othercore = 1 - core; )
298 static int oldstatus IBSS_ATTR; 329 static int oldstatus IBSS_ATTR;
299 330
@@ -442,7 +473,7 @@ static void pp_set_cpu_frequency(long frequency)
442#ifndef BOOTLOADER 473#ifndef BOOTLOADER
443void system_init(void) 474void system_init(void)
444{ 475{
445 if (CURRENT_CORE == CPU) 476 if (IF_COP_CORE(CPU) == CPU)
446 { 477 {
447#if defined (IRIVER_H10) || defined(IRIVER_H10_5GB) || defined(IPOD_COLOR) 478#if defined (IRIVER_H10) || defined(IRIVER_H10_5GB) || defined(IPOD_COLOR)
448 /* set minimum startup configuration */ 479 /* set minimum startup configuration */
@@ -628,7 +659,7 @@ void system_exception_wait(void)
628 COP_INT_DIS = -1; 659 COP_INT_DIS = -1;
629 660
630 /* Halt */ 661 /* Halt */
631 PROC_CTL(CURRENT_CORE) = 0x40000000; 662 PROC_CTL(IF_COP_CORE(CPU)) = 0x40000000;
632 while (1); 663 while (1);
633} 664}
634 665