summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafaël Carré <rafael.carre@gmail.com>2010-06-19 04:55:10 +0000
committerRafaël Carré <rafael.carre@gmail.com>2010-06-19 04:55:10 +0000
commitffc7323ec3599d09bd3452658c154ad6cd857230 (patch)
treec65741e699cb7239d11286fc16b18cc026dfe576
parent9e3f473492353852d07ce359c10540c6f1fbd14a (diff)
sd-as3525*: handle aligned transfers without memcpy()
test_disk shows 1MB transfers are up to 3 times faster not much difference for 1 or 8 sectors at a time define STORAGE_WANTS_ALIGN to use the fast path when possible git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26953 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/arm/as3525/sd-as3525.c28
-rw-r--r--firmware/target/arm/as3525/sd-as3525v2.c31
-rw-r--r--firmware/target/arm/as3525/system-target.h2
3 files changed, 49 insertions, 12 deletions
diff --git a/firmware/target/arm/as3525/sd-as3525.c b/firmware/target/arm/as3525/sd-as3525.c
index 9e55c16be6..52bf6932ec 100644
--- a/firmware/target/arm/as3525/sd-as3525.c
+++ b/firmware/target/arm/as3525/sd-as3525.c
@@ -669,6 +669,7 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
#endif
int ret = 0;
unsigned loops = 0;
+ bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1));
mutex_lock(&sd_mtx);
sd_enable(true);
@@ -700,6 +701,14 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
dma_retain();
+ if(aligned)
+ {
+ if(write)
+ clean_dcache_range(buf, count * SECTOR_SIZE);
+ else
+ dump_dcache_range(buf, count * SECTOR_SIZE);
+ }
+
while(count)
{
/* 128 * 512 = 2^16, and doesn't fit in the 16 bits of DATA_LENGTH
@@ -740,12 +749,19 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
if(!(card_info[drive].ocr & (1<<30))) /* not SDHC */
bank_start *= SD_BLOCK_SIZE;
- dma_buf = aligned_buffer;
- if(transfer > UNALIGNED_NUM_SECTORS)
- transfer = UNALIGNED_NUM_SECTORS;
+ if(aligned)
+ {
+ dma_buf = buf;
+ }
+ else
+ {
+ dma_buf = aligned_buffer;
+ if(transfer > UNALIGNED_NUM_SECTORS)
+ transfer = UNALIGNED_NUM_SECTORS;
- if(write)
- memcpy(uncached_buffer, buf, transfer * SD_BLOCK_SIZE);
+ if(write)
+ memcpy(uncached_buffer, buf, transfer * SD_BLOCK_SIZE);
+ }
ret = sd_wait_for_tran_state(drive);
if (ret < 0)
@@ -804,7 +820,7 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
if(!transfer_error[drive])
{
- if(!write)
+ if(!write && !aligned)
memcpy(buf, uncached_buffer, transfer * SD_BLOCK_SIZE);
buf += transfer * SD_BLOCK_SIZE;
start += transfer;
diff --git a/firmware/target/arm/as3525/sd-as3525v2.c b/firmware/target/arm/as3525/sd-as3525v2.c
index 386b76e758..d268bc779c 100644
--- a/firmware/target/arm/as3525/sd-as3525v2.c
+++ b/firmware/target/arm/as3525/sd-as3525v2.c
@@ -789,6 +789,8 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
#ifndef HAVE_MULTIDRIVE
const int drive = 0;
#endif
+ bool aligned = !((uintptr_t)buf & (CACHEALIGN_SIZE - 1));
+
mutex_lock(&sd_mtx);
#ifndef BOOTLOADER
@@ -828,17 +830,34 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
last_disk_activity = current_tick;
dma_retain();
+ if(aligned)
+ {
+ if(write)
+ clean_dcache_range(buf, count * SECTOR_SIZE);
+ else
+ dump_dcache_range(buf, count * SECTOR_SIZE);
+ }
+
const int cmd = write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK;
do
{
- void *dma_buf = aligned_buffer;
+ void *dma_buf;
unsigned int transfer = count;
- if(transfer > UNALIGNED_NUM_SECTORS)
- transfer = UNALIGNED_NUM_SECTORS;
- if(write)
- memcpy(uncached_buffer, buf, transfer * SD_BLOCK_SIZE);
+ if(aligned)
+ {
+ dma_buf = buf;
+ }
+ else
+ {
+ dma_buf = aligned_buffer;
+ if(transfer > UNALIGNED_NUM_SECTORS)
+ transfer = UNALIGNED_NUM_SECTORS;
+
+ if(write)
+ memcpy(uncached_buffer, buf, transfer * SD_BLOCK_SIZE);
+ }
/* Interrupt handler might set this to true during transfer */
retry = false;
@@ -893,7 +912,7 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
if(!retry)
{
- if(!write)
+ if(!write && !aligned)
memcpy(buf, uncached_buffer, transfer * SD_BLOCK_SIZE);
buf += transfer * SD_BLOCK_SIZE;
start += transfer;
diff --git a/firmware/target/arm/as3525/system-target.h b/firmware/target/arm/as3525/system-target.h
index f7dc1ac312..5d11ecb26c 100644
--- a/firmware/target/arm/as3525/system-target.h
+++ b/firmware/target/arm/as3525/system-target.h
@@ -27,6 +27,8 @@
#include "clock-target.h" /* CPUFREQ_* are defined here */
+#define STORAGE_WANTS_ALIGN
+
/* We can use a interrupt-based mechanism on the fuzev2 */
#define INCREASED_SCROLLWHEEL_POLLING \
(defined(HAVE_SCROLLWHEEL) && (CONFIG_CPU == AS3525))