aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin
diff options
context:
space:
mode:
authorMichael Hennerich <michael.hennerich@analog.com>2010-06-16 05:12:10 -0400
committerMike Frysinger <vapier@gentoo.org>2010-08-06 12:55:50 -0400
commitd1401e1dc22606a91f577ad3dfd68ae7e60e0357 (patch)
tree6c59463c60fd4ada2b5d4974afaa30be7059c67f /arch/blackfin
parent502c8a0e07450ff886b80a11150a123bae92f3f7 (diff)
Blackfin: fix DMA/cache bug when resuming from suspend to RAM
The dma_memcpy() function takes care of flushing different caches for us. Normally this is what we want, but when resuming from mem, we don't yet have caches enabled. If these functions happen to be placed into L1 mem (which is what we're trying to relocate), then things aren't going to work. So define a non-cache dma_memcpy() variant to utilize in situations like this. Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin')
-rw-r--r--arch/blackfin/include/asm/dma.h1
-rw-r--r--arch/blackfin/kernel/bfin_dma_5xx.c19
-rw-r--r--arch/blackfin/mach-common/pm.c17
3 files changed, 27 insertions, 10 deletions
diff --git a/arch/blackfin/include/asm/dma.h b/arch/blackfin/include/asm/dma.h
index 2c09b1d50ec9..eedf3ca65ba2 100644
--- a/arch/blackfin/include/asm/dma.h
+++ b/arch/blackfin/include/asm/dma.h
@@ -276,6 +276,7 @@ static inline void clear_dma_irqstat(unsigned int channel)
276} 276}
277 277
278void *dma_memcpy(void *dest, const void *src, size_t count); 278void *dma_memcpy(void *dest, const void *src, size_t count);
279void *dma_memcpy_nocache(void *dest, const void *src, size_t count);
279void *safe_dma_memcpy(void *dest, const void *src, size_t count); 280void *safe_dma_memcpy(void *dest, const void *src, size_t count);
280void blackfin_dma_early_init(void); 281void blackfin_dma_early_init(void);
281void early_dma_memcpy(void *dest, const void *src, size_t count); 282void early_dma_memcpy(void *dest, const void *src, size_t count);
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c
index 26403d1c9e65..1e485dfdc9f2 100644
--- a/arch/blackfin/kernel/bfin_dma_5xx.c
+++ b/arch/blackfin/kernel/bfin_dma_5xx.c
@@ -450,7 +450,6 @@ void *dma_memcpy(void *pdst, const void *psrc, size_t size)
450{ 450{
451 unsigned long dst = (unsigned long)pdst; 451 unsigned long dst = (unsigned long)pdst;
452 unsigned long src = (unsigned long)psrc; 452 unsigned long src = (unsigned long)psrc;
453 size_t bulk, rest;
454 453
455 if (bfin_addr_dcacheable(src)) 454 if (bfin_addr_dcacheable(src))
456 blackfin_dcache_flush_range(src, src + size); 455 blackfin_dcache_flush_range(src, src + size);
@@ -458,6 +457,22 @@ void *dma_memcpy(void *pdst, const void *psrc, size_t size)
458 if (bfin_addr_dcacheable(dst)) 457 if (bfin_addr_dcacheable(dst))
459 blackfin_dcache_invalidate_range(dst, dst + size); 458 blackfin_dcache_invalidate_range(dst, dst + size);
460 459
460 return dma_memcpy_nocache(pdst, psrc, size);
461}
462EXPORT_SYMBOL(dma_memcpy);
463
464/**
465 * dma_memcpy_nocache - DMA memcpy under mutex lock
466 * - No cache flush/invalidate
467 *
468 * Do not check arguments before starting the DMA memcpy. Break the transfer
469 * up into two pieces. The first transfer is in multiples of 64k and the
470 * second transfer is the piece smaller than 64k.
471 */
472void *dma_memcpy_nocache(void *pdst, const void *psrc, size_t size)
473{
474 size_t bulk, rest;
475
461 bulk = size & ~0xffff; 476 bulk = size & ~0xffff;
462 rest = size - bulk; 477 rest = size - bulk;
463 if (bulk) 478 if (bulk)
@@ -465,7 +480,7 @@ void *dma_memcpy(void *pdst, const void *psrc, size_t size)
465 _dma_memcpy(pdst + bulk, psrc + bulk, rest); 480 _dma_memcpy(pdst + bulk, psrc + bulk, rest);
466 return pdst; 481 return pdst;
467} 482}
468EXPORT_SYMBOL(dma_memcpy); 483EXPORT_SYMBOL(dma_memcpy_nocache);
469 484
470/** 485/**
471 * safe_dma_memcpy - DMA memcpy w/argument checking 486 * safe_dma_memcpy - DMA memcpy w/argument checking
diff --git a/arch/blackfin/mach-common/pm.c b/arch/blackfin/mach-common/pm.c
index ea7f95f6bb4c..09c1fb410748 100644
--- a/arch/blackfin/mach-common/pm.c
+++ b/arch/blackfin/mach-common/pm.c
@@ -61,10 +61,11 @@ void bfin_pm_suspend_standby_enter(void)
61 61
62int bf53x_suspend_l1_mem(unsigned char *memptr) 62int bf53x_suspend_l1_mem(unsigned char *memptr)
63{ 63{
64 dma_memcpy(memptr, (const void *) L1_CODE_START, L1_CODE_LENGTH); 64 dma_memcpy_nocache(memptr, (const void *) L1_CODE_START,
65 dma_memcpy(memptr + L1_CODE_LENGTH, (const void *) L1_DATA_A_START, 65 L1_CODE_LENGTH);
66 L1_DATA_A_LENGTH); 66 dma_memcpy_nocache(memptr + L1_CODE_LENGTH,
67 dma_memcpy(memptr + L1_CODE_LENGTH + L1_DATA_A_LENGTH, 67 (const void *) L1_DATA_A_START, L1_DATA_A_LENGTH);
68 dma_memcpy_nocache(memptr + L1_CODE_LENGTH + L1_DATA_A_LENGTH,
68 (const void *) L1_DATA_B_START, L1_DATA_B_LENGTH); 69 (const void *) L1_DATA_B_START, L1_DATA_B_LENGTH);
69 memcpy(memptr + L1_CODE_LENGTH + L1_DATA_A_LENGTH + 70 memcpy(memptr + L1_CODE_LENGTH + L1_DATA_A_LENGTH +
70 L1_DATA_B_LENGTH, (const void *) L1_SCRATCH_START, 71 L1_DATA_B_LENGTH, (const void *) L1_SCRATCH_START,
@@ -75,10 +76,10 @@ int bf53x_suspend_l1_mem(unsigned char *memptr)
75 76
76int bf53x_resume_l1_mem(unsigned char *memptr) 77int bf53x_resume_l1_mem(unsigned char *memptr)
77{ 78{
78 dma_memcpy((void *) L1_CODE_START, memptr, L1_CODE_LENGTH); 79 dma_memcpy_nocache((void *) L1_CODE_START, memptr, L1_CODE_LENGTH);
79 dma_memcpy((void *) L1_DATA_A_START, memptr + L1_CODE_LENGTH, 80 dma_memcpy_nocache((void *) L1_DATA_A_START, memptr + L1_CODE_LENGTH,
80 L1_DATA_A_LENGTH); 81 L1_DATA_A_LENGTH);
81 dma_memcpy((void *) L1_DATA_B_START, memptr + L1_CODE_LENGTH + 82 dma_memcpy_nocache((void *) L1_DATA_B_START, memptr + L1_CODE_LENGTH +
82 L1_DATA_A_LENGTH, L1_DATA_B_LENGTH); 83 L1_DATA_A_LENGTH, L1_DATA_B_LENGTH);
83 memcpy((void *) L1_SCRATCH_START, memptr + L1_CODE_LENGTH + 84 memcpy((void *) L1_SCRATCH_START, memptr + L1_CODE_LENGTH +
84 L1_DATA_A_LENGTH + L1_DATA_B_LENGTH, L1_SCRATCH_LENGTH); 85 L1_DATA_A_LENGTH + L1_DATA_B_LENGTH, L1_SCRATCH_LENGTH);
@@ -167,7 +168,7 @@ int bfin_pm_suspend_mem_enter(void)
167 _disable_icplb(); 168 _disable_icplb();
168 bf53x_suspend_l1_mem(memptr); 169 bf53x_suspend_l1_mem(memptr);
169 170
170 do_hibernate(wakeup | vr_wakeup); /* Goodbye */ 171 do_hibernate(wakeup | vr_wakeup); /* See you later! */
171 172
172 bf53x_resume_l1_mem(memptr); 173 bf53x_resume_l1_mem(memptr);
173 174