forked from len0rd/rockbox
iPod Nano 2G storage performance improved by not copying around buffers unneccessarily if they are aligned anyways and using cache coherency functions instead of bypassing the caches altogether.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23243 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
8f6f19ac00
commit
b424b852e5
2 changed files with 95 additions and 84 deletions
|
@ -368,10 +368,10 @@ struct ftl_vfl_cxt_type ftl_vfl_cxt[4];
|
||||||
struct ftl_cxt_type ftl_cxt;
|
struct ftl_cxt_type ftl_cxt;
|
||||||
|
|
||||||
/* Temporary data buffer for internal use by the FTL */
|
/* Temporary data buffer for internal use by the FTL */
|
||||||
uint8_t ftl_buffer[0x800];
|
uint8_t ftl_buffer[0x800] __attribute__((aligned(16)));
|
||||||
|
|
||||||
/* Temporary spare byte buffer for internal use by the FTL */
|
/* Temporary spare byte buffer for internal use by the FTL */
|
||||||
union ftl_spare_data_type ftl_sparebuffer;
|
union ftl_spare_data_type ftl_sparebuffer __attribute__((aligned(16)));
|
||||||
|
|
||||||
|
|
||||||
#ifndef FTL_READONLY
|
#ifndef FTL_READONLY
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "inttypes.h"
|
#include "inttypes.h"
|
||||||
#include "nand-target.h"
|
#include "nand-target.h"
|
||||||
#include <pmu-target.h>
|
#include <pmu-target.h>
|
||||||
|
#include <mmu-target.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,18 +93,10 @@ static struct wakeup nand_wakeup;
|
||||||
static struct mutex ecc_mtx;
|
static struct mutex ecc_mtx;
|
||||||
static struct wakeup ecc_wakeup;
|
static struct wakeup ecc_wakeup;
|
||||||
|
|
||||||
static uint8_t nand_aligned_data[0x800] __attribute__((aligned(32)));
|
static uint8_t nand_data[0x800] __attribute__((aligned(16)));
|
||||||
static uint8_t nand_aligned_ctrl[0x200] __attribute__((aligned(32)));
|
static uint8_t nand_ctrl[0x200] __attribute__((aligned(16)));
|
||||||
static uint8_t nand_aligned_spare[0x40] __attribute__((aligned(32)));
|
static uint8_t nand_spare[0x40] __attribute__((aligned(16)));
|
||||||
static uint8_t nand_aligned_ecc[0x28] __attribute__((aligned(32)));
|
static uint8_t nand_ecc[0x30] __attribute__((aligned(16)));
|
||||||
#define nand_uncached_data \
|
|
||||||
((uint8_t*)(((uint32_t)nand_aligned_data) | 0x40000000))
|
|
||||||
#define nand_uncached_ctrl \
|
|
||||||
((uint8_t*)(((uint32_t)nand_aligned_ctrl) | 0x40000000))
|
|
||||||
#define nand_uncached_spare \
|
|
||||||
((uint8_t*)(((uint32_t)nand_aligned_spare) | 0x40000000))
|
|
||||||
#define nand_uncached_ecc \
|
|
||||||
((uint8_t*)(((uint32_t)nand_aligned_ecc) | 0x40000000))
|
|
||||||
|
|
||||||
|
|
||||||
uint32_t nand_unlock(uint32_t rc)
|
uint32_t nand_unlock(uint32_t rc)
|
||||||
|
@ -131,7 +124,7 @@ uint32_t nand_timeout(long timeout)
|
||||||
uint32_t nand_wait_rbbdone(void)
|
uint32_t nand_wait_rbbdone(void)
|
||||||
{
|
{
|
||||||
long timeout = current_tick + HZ / 50;
|
long timeout = current_tick + HZ / 50;
|
||||||
while ((FMCSTAT & FMCSTAT_RBBDONE) == 0)
|
while (!(FMCSTAT & FMCSTAT_RBBDONE))
|
||||||
if (nand_timeout(timeout)) return 1;
|
if (nand_timeout(timeout)) return 1;
|
||||||
FMCSTAT = FMCSTAT_RBBDONE;
|
FMCSTAT = FMCSTAT_RBBDONE;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -140,7 +133,7 @@ uint32_t nand_wait_rbbdone(void)
|
||||||
uint32_t nand_wait_cmddone(void)
|
uint32_t nand_wait_cmddone(void)
|
||||||
{
|
{
|
||||||
long timeout = current_tick + HZ / 50;
|
long timeout = current_tick + HZ / 50;
|
||||||
while ((FMCSTAT & FMCSTAT_CMDDONE) == 0)
|
while (!(FMCSTAT & FMCSTAT_CMDDONE))
|
||||||
if (nand_timeout(timeout)) return 1;
|
if (nand_timeout(timeout)) return 1;
|
||||||
FMCSTAT = FMCSTAT_CMDDONE;
|
FMCSTAT = FMCSTAT_CMDDONE;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -149,7 +142,7 @@ uint32_t nand_wait_cmddone(void)
|
||||||
uint32_t nand_wait_addrdone(void)
|
uint32_t nand_wait_addrdone(void)
|
||||||
{
|
{
|
||||||
long timeout = current_tick + HZ / 50;
|
long timeout = current_tick + HZ / 50;
|
||||||
while ((FMCSTAT & FMCSTAT_ADDRDONE) == 0)
|
while (!(FMCSTAT & FMCSTAT_ADDRDONE))
|
||||||
if (nand_timeout(timeout)) return 1;
|
if (nand_timeout(timeout)) return 1;
|
||||||
FMCSTAT = FMCSTAT_ADDRDONE;
|
FMCSTAT = FMCSTAT_ADDRDONE;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -158,7 +151,7 @@ uint32_t nand_wait_addrdone(void)
|
||||||
uint32_t nand_wait_chip_ready(uint32_t bank)
|
uint32_t nand_wait_chip_ready(uint32_t bank)
|
||||||
{
|
{
|
||||||
long timeout = current_tick + HZ / 50;
|
long timeout = current_tick + HZ / 50;
|
||||||
while ((FMCSTAT & (FMCSTAT_BANK0READY << bank)) == 0)
|
while (!(FMCSTAT & (FMCSTAT_BANK0READY << bank)))
|
||||||
if (nand_timeout(timeout)) return 1;
|
if (nand_timeout(timeout)) return 1;
|
||||||
FMCSTAT = (FMCSTAT_BANK0READY << bank);
|
FMCSTAT = (FMCSTAT_BANK0READY << bank);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -188,8 +181,8 @@ uint32_t nand_send_address(uint32_t page, uint32_t offset)
|
||||||
uint32_t nand_reset(uint32_t bank)
|
uint32_t nand_reset(uint32_t bank)
|
||||||
{
|
{
|
||||||
nand_set_fmctrl0(bank, 0);
|
nand_set_fmctrl0(bank, 0);
|
||||||
if (nand_send_cmd(NAND_CMD_RESET) != 0) return 1;
|
if (nand_send_cmd(NAND_CMD_RESET)) return 1;
|
||||||
if (nand_wait_chip_ready(bank) != 0) return 1;
|
if (nand_wait_chip_ready(bank)) return 1;
|
||||||
FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
|
FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -198,17 +191,17 @@ uint32_t nand_wait_status_ready(uint32_t bank)
|
||||||
{
|
{
|
||||||
long timeout = current_tick + HZ / 50;
|
long timeout = current_tick + HZ / 50;
|
||||||
nand_set_fmctrl0(bank, 0);
|
nand_set_fmctrl0(bank, 0);
|
||||||
if ((FMCSTAT & (FMCSTAT_BANK0READY << bank)) != 0)
|
if ((FMCSTAT & (FMCSTAT_BANK0READY << bank)))
|
||||||
FMCSTAT = (FMCSTAT_BANK0READY << bank);
|
FMCSTAT = (FMCSTAT_BANK0READY << bank);
|
||||||
FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
|
FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
|
||||||
if (nand_send_cmd(NAND_CMD_GET_STATUS) != 0) return 1;
|
if (nand_send_cmd(NAND_CMD_GET_STATUS)) return 1;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (nand_timeout(timeout)) return 1;
|
if (nand_timeout(timeout)) return 1;
|
||||||
FMDNUM = 0;
|
FMDNUM = 0;
|
||||||
FMCTRL1 = FMCTRL1_DOREADDATA;
|
FMCTRL1 = FMCTRL1_DOREADDATA;
|
||||||
if (nand_wait_addrdone() != 0) return 1;
|
if (nand_wait_addrdone()) return 1;
|
||||||
if ((FMFIFO & NAND_STATUS_READY) != 0) break;
|
if ((FMFIFO & NAND_STATUS_READY)) break;
|
||||||
FMCTRL1 = FMCTRL1_CLEARRFIFO;
|
FMCTRL1 = FMCTRL1_CLEARRFIFO;
|
||||||
}
|
}
|
||||||
FMCTRL1 = FMCTRL1_CLEARRFIFO;
|
FMCTRL1 = FMCTRL1_CLEARRFIFO;
|
||||||
|
@ -226,15 +219,17 @@ uint32_t nand_transfer_data(uint32_t bank, uint32_t direction,
|
||||||
| (direction << DMACON_DIRECTION_SHIFT)
|
| (direction << DMACON_DIRECTION_SHIFT)
|
||||||
| (2 << DMACON_DATA_SIZE_SHIFT)
|
| (2 << DMACON_DATA_SIZE_SHIFT)
|
||||||
| (3 << DMACON_BURST_LEN_SHIFT);
|
| (3 << DMACON_BURST_LEN_SHIFT);
|
||||||
while ((DMAALLST & DMAALLST_CHAN3_MASK) != 0)
|
while ((DMAALLST & DMAALLST_CHAN3_MASK))
|
||||||
DMACOM3 = DMACOM_CLEARBOTHDONE;
|
DMACOM3 = DMACOM_CLEARBOTHDONE;
|
||||||
DMABASE3 = (uint32_t)buffer;
|
DMABASE3 = (uint32_t)buffer;
|
||||||
DMATCNT3 = (size >> 4) - 1;
|
DMATCNT3 = (size >> 4) - 1;
|
||||||
|
clean_dcache();
|
||||||
DMACOM3 = 4;
|
DMACOM3 = 4;
|
||||||
while ((DMAALLST & DMAALLST_DMABUSY3) != 0)
|
while ((DMAALLST & DMAALLST_DMABUSY3))
|
||||||
if (nand_timeout(timeout)) return 1;
|
if (nand_timeout(timeout)) return 1;
|
||||||
if (nand_wait_addrdone() != 0) return 1;
|
if (!direction) invalidate_dcache();
|
||||||
if (direction == 0) FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
|
if (nand_wait_addrdone()) return 1;
|
||||||
|
if (!direction) FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,9 +242,11 @@ uint32_t ecc_decode(uint32_t size, void* databuffer, void* sparebuffer)
|
||||||
ECC_UNK1 = size;
|
ECC_UNK1 = size;
|
||||||
ECC_DATA_PTR = (uint32_t)databuffer;
|
ECC_DATA_PTR = (uint32_t)databuffer;
|
||||||
ECC_SPARE_PTR = (uint32_t)sparebuffer;
|
ECC_SPARE_PTR = (uint32_t)sparebuffer;
|
||||||
|
clean_dcache();
|
||||||
ECC_CTRL = ECCCTRL_STARTDECODING;
|
ECC_CTRL = ECCCTRL_STARTDECODING;
|
||||||
while ((SRCPND & INTMSK_ECC) == 0)
|
while (!(SRCPND & INTMSK_ECC))
|
||||||
if (nand_timeout(timeout)) return ecc_unlock(1);
|
if (nand_timeout(timeout)) return ecc_unlock(1);
|
||||||
|
invalidate_dcache();
|
||||||
ECC_INT_CLR = 1;
|
ECC_INT_CLR = 1;
|
||||||
SRCPND = INTMSK_ECC;
|
SRCPND = INTMSK_ECC;
|
||||||
return ecc_unlock(ECC_RESULT);
|
return ecc_unlock(ECC_RESULT);
|
||||||
|
@ -264,9 +261,11 @@ uint32_t ecc_encode(uint32_t size, void* databuffer, void* sparebuffer)
|
||||||
ECC_UNK1 = size;
|
ECC_UNK1 = size;
|
||||||
ECC_DATA_PTR = (uint32_t)databuffer;
|
ECC_DATA_PTR = (uint32_t)databuffer;
|
||||||
ECC_SPARE_PTR = (uint32_t)sparebuffer;
|
ECC_SPARE_PTR = (uint32_t)sparebuffer;
|
||||||
|
clean_dcache();
|
||||||
ECC_CTRL = ECCCTRL_STARTENCODING;
|
ECC_CTRL = ECCCTRL_STARTENCODING;
|
||||||
while ((SRCPND & INTMSK_ECC) == 0)
|
while (!(SRCPND & INTMSK_ECC))
|
||||||
if (nand_timeout(timeout)) return ecc_unlock(1);
|
if (nand_timeout(timeout)) return ecc_unlock(1);
|
||||||
|
invalidate_dcache();
|
||||||
ECC_INT_CLR = 1;
|
ECC_INT_CLR = 1;
|
||||||
SRCPND = INTMSK_ECC;
|
SRCPND = INTMSK_ECC;
|
||||||
return ecc_unlock(0);
|
return ecc_unlock(0);
|
||||||
|
@ -285,15 +284,15 @@ uint32_t nand_get_chip_type(uint32_t bank)
|
||||||
{
|
{
|
||||||
mutex_lock(&nand_mtx);
|
mutex_lock(&nand_mtx);
|
||||||
uint32_t result;
|
uint32_t result;
|
||||||
if (nand_reset(bank) != 0) return nand_unlock(0xFFFFFFFF);
|
if (nand_reset(bank)) return nand_unlock(0xFFFFFFFF);
|
||||||
if (nand_send_cmd(0x90) != 0) return nand_unlock(0xFFFFFFFF);
|
if (nand_send_cmd(0x90)) return nand_unlock(0xFFFFFFFF);
|
||||||
FMANUM = 0;
|
FMANUM = 0;
|
||||||
FMADDR0 = 0;
|
FMADDR0 = 0;
|
||||||
FMCTRL1 = FMCTRL1_DOTRANSADDR;
|
FMCTRL1 = FMCTRL1_DOTRANSADDR;
|
||||||
if (nand_wait_cmddone() != 0) return nand_unlock(0xFFFFFFFF);
|
if (nand_wait_cmddone()) return nand_unlock(0xFFFFFFFF);
|
||||||
FMDNUM = 4;
|
FMDNUM = 4;
|
||||||
FMCTRL1 = FMCTRL1_DOREADDATA;
|
FMCTRL1 = FMCTRL1_DOREADDATA;
|
||||||
if (nand_wait_addrdone() != 0) return nand_unlock(0xFFFFFFFF);
|
if (nand_wait_addrdone()) return nand_unlock(0xFFFFFFFF);
|
||||||
result = FMFIFO;
|
result = FMFIFO;
|
||||||
FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
|
FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
|
||||||
return nand_unlock(result);
|
return nand_unlock(result);
|
||||||
|
@ -343,49 +342,55 @@ uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer,
|
||||||
void* sparebuffer, uint32_t doecc,
|
void* sparebuffer, uint32_t doecc,
|
||||||
uint32_t checkempty)
|
uint32_t checkempty)
|
||||||
{
|
{
|
||||||
|
uint8_t* data = nand_data;
|
||||||
|
uint8_t* spare = nand_spare;
|
||||||
|
if (databuffer && !((uint32_t)databuffer & 0xf))
|
||||||
|
data = (uint8_t*)databuffer;
|
||||||
|
if (sparebuffer && !((uint32_t)sparebuffer & 0xf))
|
||||||
|
spare = (uint8_t*)sparebuffer;
|
||||||
mutex_lock(&nand_mtx);
|
mutex_lock(&nand_mtx);
|
||||||
if (!nand_powered) nand_power_up();
|
if (!nand_powered) nand_power_up();
|
||||||
uint32_t rc, eccresult;
|
uint32_t rc, eccresult;
|
||||||
nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
|
nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
|
||||||
if (nand_send_cmd(NAND_CMD_READ) != 0) return nand_unlock(1);
|
if (nand_send_cmd(NAND_CMD_READ)) return nand_unlock(1);
|
||||||
if (nand_send_address(page, (databuffer == 0) ? 0x800 : 0) != 0)
|
if (nand_send_address(page, databuffer ? 0 : 0x800))
|
||||||
return nand_unlock(1);
|
return nand_unlock(1);
|
||||||
if (nand_send_cmd(NAND_CMD_READ2) != 0) return nand_unlock(1);
|
if (nand_send_cmd(NAND_CMD_READ2)) return nand_unlock(1);
|
||||||
if (nand_wait_status_ready(bank) != 0) return nand_unlock(1);
|
if (nand_wait_status_ready(bank)) return nand_unlock(1);
|
||||||
if (databuffer != 0)
|
if (databuffer)
|
||||||
if (nand_transfer_data(bank, 0, nand_uncached_data, 0x800) != 0)
|
if (nand_transfer_data(bank, 0, data, 0x800))
|
||||||
return nand_unlock(1);
|
return nand_unlock(1);
|
||||||
rc = 0;
|
rc = 0;
|
||||||
if (doecc == 0)
|
if (!doecc)
|
||||||
{
|
{
|
||||||
memcpy(databuffer, nand_uncached_data, 0x800);
|
if (databuffer && data != databuffer) memcpy(databuffer, data, 0x800);
|
||||||
if (sparebuffer != 0)
|
if (sparebuffer)
|
||||||
{
|
{
|
||||||
if (nand_transfer_data(bank, 0, nand_uncached_spare, 0x40) != 0)
|
if (nand_transfer_data(bank, 0, spare, 0x40))
|
||||||
return nand_unlock(1);
|
return nand_unlock(1);
|
||||||
memcpy(sparebuffer, nand_uncached_spare, 0x800);
|
if (sparebuffer && spare != sparebuffer)
|
||||||
if (checkempty != 0)
|
memcpy(sparebuffer, spare, 0x800);
|
||||||
|
if (checkempty)
|
||||||
rc = nand_check_empty((uint8_t*)sparebuffer) << 1;
|
rc = nand_check_empty((uint8_t*)sparebuffer) << 1;
|
||||||
}
|
}
|
||||||
return nand_unlock(rc);
|
return nand_unlock(rc);
|
||||||
}
|
}
|
||||||
if (nand_transfer_data(bank, 0, nand_uncached_spare, 0x40) != 0)
|
if (nand_transfer_data(bank, 0, spare, 0x40)) return nand_unlock(1);
|
||||||
return nand_unlock(1);
|
memcpy(nand_ecc, &spare[0xC], 0x28);
|
||||||
memcpy(nand_uncached_ecc, &nand_uncached_spare[0xC], 0x28);
|
rc |= (ecc_decode(3, data, nand_ecc) & 0xF) << 4;
|
||||||
rc |= (ecc_decode(3, nand_uncached_data, nand_uncached_ecc) & 0xF) << 4;
|
if (databuffer && data != databuffer) memcpy(databuffer, data, 0x800);
|
||||||
if (databuffer != 0) memcpy(databuffer, nand_uncached_data, 0x800);
|
memset(nand_ctrl, 0xFF, 0x200);
|
||||||
memset(nand_uncached_ctrl, 0xFF, 0x200);
|
memcpy(nand_ctrl, spare, 0xC);
|
||||||
memcpy(nand_uncached_ctrl, nand_uncached_spare, 0xC);
|
memcpy(nand_ecc, &spare[0x34], 0xC);
|
||||||
memcpy(nand_uncached_ecc, &nand_uncached_spare[0x34], 0xC);
|
eccresult = ecc_decode(0, nand_ctrl, nand_ecc);
|
||||||
eccresult = ecc_decode(0, nand_uncached_ctrl, nand_uncached_ecc);
|
|
||||||
rc |= (eccresult & 0xF) << 8;
|
rc |= (eccresult & 0xF) << 8;
|
||||||
if (sparebuffer != 0)
|
if (sparebuffer)
|
||||||
{
|
{
|
||||||
memcpy(sparebuffer, nand_uncached_spare, 0x40);
|
if (spare != sparebuffer) memcpy(sparebuffer, spare, 0x40);
|
||||||
if ((eccresult & 1) != 0) memset(sparebuffer, 0xFF, 0xC);
|
if (eccresult & 1) memset(sparebuffer, 0xFF, 0xC);
|
||||||
else memcpy(sparebuffer, nand_uncached_ctrl, 0xC);
|
else memcpy(sparebuffer, nand_ctrl, 0xC);
|
||||||
}
|
}
|
||||||
if (checkempty != 0) rc |= nand_check_empty(nand_uncached_spare) << 1;
|
if (checkempty) rc |= nand_check_empty(spare) << 1;
|
||||||
|
|
||||||
return nand_unlock(rc);
|
return nand_unlock(rc);
|
||||||
}
|
}
|
||||||
|
@ -393,34 +398,40 @@ uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer,
|
||||||
uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer,
|
uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer,
|
||||||
void* sparebuffer, uint32_t doecc)
|
void* sparebuffer, uint32_t doecc)
|
||||||
{
|
{
|
||||||
|
uint8_t* data = nand_data;
|
||||||
|
uint8_t* spare = nand_spare;
|
||||||
|
if (databuffer && !((uint32_t)databuffer & 0xf))
|
||||||
|
data = (uint8_t*)databuffer;
|
||||||
|
if (sparebuffer && !((uint32_t)sparebuffer & 0xf))
|
||||||
|
spare = (uint8_t*)sparebuffer;
|
||||||
mutex_lock(&nand_mtx);
|
mutex_lock(&nand_mtx);
|
||||||
if (!nand_powered) nand_power_up();
|
if (!nand_powered) nand_power_up();
|
||||||
if (sparebuffer != 0) memcpy(nand_uncached_spare, sparebuffer, 0x40);
|
if (sparebuffer)
|
||||||
else memset(nand_uncached_spare, 0xFF, 0x40);
|
{
|
||||||
if (doecc != 0)
|
if (spare != sparebuffer) memcpy(spare, sparebuffer, 0x40);
|
||||||
|
}
|
||||||
|
else memset(spare, 0xFF, 0x40);
|
||||||
|
if (doecc)
|
||||||
{
|
{
|
||||||
memcpy(nand_uncached_data, databuffer, 0x800);
|
if (databuffer && data != databuffer) memcpy(data, databuffer, 0x800);
|
||||||
if (ecc_encode(3, nand_uncached_data, nand_uncached_ecc) != 0)
|
if (ecc_encode(3, data, nand_ecc)) return nand_unlock(1);
|
||||||
return nand_unlock(1);
|
memcpy(&spare[0xC], nand_ecc, 0x28);
|
||||||
memcpy(&nand_uncached_spare[0xC], nand_uncached_ecc, 0x28);
|
memset(nand_ctrl, 0xFF, 0x200);
|
||||||
memset(nand_uncached_ctrl, 0xFF, 0x200);
|
memcpy(nand_ctrl, spare, 0xC);
|
||||||
memcpy(nand_uncached_ctrl, nand_uncached_spare, 0xC);
|
if (ecc_encode(0, nand_ctrl, nand_ecc)) return nand_unlock(1);
|
||||||
if (ecc_encode(0, nand_uncached_ctrl, nand_uncached_ecc) != 0)
|
memcpy(&spare[0x34], nand_ecc, 0xC);
|
||||||
return nand_unlock(1);
|
|
||||||
memcpy(&nand_uncached_spare[0x34], nand_uncached_ecc, 0xC);
|
|
||||||
}
|
}
|
||||||
nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
|
nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
|
||||||
if (nand_send_cmd(NAND_CMD_PROGRAM) != 0)
|
if (nand_send_cmd(NAND_CMD_PROGRAM)) return nand_unlock(1);
|
||||||
|
if (nand_send_address(page, databuffer ? 0 : 0x800))
|
||||||
return nand_unlock(1);
|
return nand_unlock(1);
|
||||||
if (nand_send_address(page, (databuffer == 0) ? 0x800 : 0) != 0)
|
if (databuffer)
|
||||||
return nand_unlock(1);
|
if (nand_transfer_data(bank, 1, data, 0x800))
|
||||||
if (databuffer != 0)
|
|
||||||
if (nand_transfer_data(bank, 1, nand_uncached_data, 0x800) != 0)
|
|
||||||
return nand_unlock(1);
|
return nand_unlock(1);
|
||||||
if (sparebuffer != 0 || doecc != 0)
|
if (sparebuffer || doecc)
|
||||||
if (nand_transfer_data(bank, 1, nand_uncached_spare, 0x40) != 0)
|
if (nand_transfer_data(bank, 1, spare, 0x40))
|
||||||
return nand_unlock(1);
|
return nand_unlock(1);
|
||||||
if (nand_send_cmd(NAND_CMD_PROGCNFRM) != 0) return nand_unlock(1);
|
if (nand_send_cmd(NAND_CMD_PROGCNFRM)) return nand_unlock(1);
|
||||||
return nand_unlock(nand_wait_status_ready(bank));
|
return nand_unlock(nand_wait_status_ready(bank));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,13 +440,13 @@ uint32_t nand_block_erase(uint32_t bank, uint32_t page)
|
||||||
mutex_lock(&nand_mtx);
|
mutex_lock(&nand_mtx);
|
||||||
if (!nand_powered) nand_power_up();
|
if (!nand_powered) nand_power_up();
|
||||||
nand_set_fmctrl0(bank, 0);
|
nand_set_fmctrl0(bank, 0);
|
||||||
if (nand_send_cmd(NAND_CMD_BLOCKERASE) != 0) return nand_unlock(1);
|
if (nand_send_cmd(NAND_CMD_BLOCKERASE)) return nand_unlock(1);
|
||||||
FMANUM = 2;
|
FMANUM = 2;
|
||||||
FMADDR0 = page;
|
FMADDR0 = page;
|
||||||
FMCTRL1 = FMCTRL1_DOTRANSADDR;
|
FMCTRL1 = FMCTRL1_DOTRANSADDR;
|
||||||
if (nand_wait_cmddone() != 0) return nand_unlock(1);
|
if (nand_wait_cmddone()) return nand_unlock(1);
|
||||||
if (nand_send_cmd(NAND_CMD_ERASECNFRM) != 0) return nand_unlock(1);
|
if (nand_send_cmd(NAND_CMD_ERASECNFRM)) return nand_unlock(1);
|
||||||
if (nand_wait_status_ready(bank) != 0) return nand_unlock(1);
|
if (nand_wait_status_ready(bank)) return nand_unlock(1);
|
||||||
return nand_unlock(0);
|
return nand_unlock(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue