summaryrefslogtreecommitdiff
path: root/firmware/target/arm
diff options
context:
space:
mode:
authorMichael Sparmann <theseven@rockbox.org>2010-03-13 21:44:39 +0000
committerMichael Sparmann <theseven@rockbox.org>2010-03-13 21:44:39 +0000
commit382b6dca08254e815a39db5fefbc2bf98142c812 (patch)
treed665d8f283e1e96a67aceb02c310fc61d5ae8599 /firmware/target/arm
parentcb41b2f2457015a3594eb63e917c5742564fc801 (diff)
Nano2G NAND interleaved write support
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25154 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm')
-rw-r--r--firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c63
1 files changed, 54 insertions, 9 deletions
diff --git a/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c
index 7e455f044c..e9eab73df9 100644
--- a/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c
+++ b/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c
@@ -440,8 +440,8 @@ uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer,
return nand_unlock(rc);
}
-uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer,
- void* sparebuffer, uint32_t doecc)
+uint32_t nand_write_page_int(uint32_t bank, uint32_t page, void* databuffer,
+ void* sparebuffer, uint32_t doecc, uint32_t wait)
{
uint8_t* data = nand_data;
uint8_t* spare = nand_spare;
@@ -458,9 +458,14 @@ uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer,
if (spare != sparebuffer) memcpy(spare, sparebuffer, 0x40);
}
else memset(spare, 0xFF, 0x40);
+ nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
+ if (nand_send_cmd(NAND_CMD_PROGRAM)) return nand_unlock(1);
+ if (nand_send_address(page, databuffer ? 0 : 0x800))
+ return nand_unlock(1);
+ if (databuffer && data != databuffer) memcpy(data, databuffer, 0x800);
+ if (databuffer) nand_transfer_data_start(bank, 1, data, 0x800);
if (doecc)
{
- if (databuffer && data != databuffer) memcpy(data, databuffer, 0x800);
if (ecc_encode(3, data, nand_ecc)) return nand_unlock(1);
memcpy(&spare[0xC], nand_ecc, 0x28);
memset(nand_ctrl, 0xFF, 0x200);
@@ -468,18 +473,15 @@ uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer,
if (ecc_encode(0, nand_ctrl, nand_ecc)) return nand_unlock(1);
memcpy(&spare[0x34], nand_ecc, 0xC);
}
- nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
- if (nand_send_cmd(NAND_CMD_PROGRAM)) return nand_unlock(1);
- if (nand_send_address(page, databuffer ? 0 : 0x800))
- return nand_unlock(1);
if (databuffer)
- if (nand_transfer_data(bank, 1, data, 0x800))
+ if (nand_transfer_data_collect(1))
return nand_unlock(1);
if (sparebuffer || doecc)
if (nand_transfer_data(bank, 1, spare, 0x40))
return nand_unlock(1);
if (nand_send_cmd(NAND_CMD_PROGCNFRM)) return nand_unlock(1);
- return nand_unlock(nand_wait_status_ready(bank));
+ if (wait) if (nand_wait_status_ready(bank)) return nand_unlock(1);
+ return nand_unlock(0);
}
uint32_t nand_block_erase(uint32_t bank, uint32_t page)
@@ -631,6 +633,49 @@ uint32_t nand_read_page_fast(uint32_t page, void* databuffer,
return nand_unlock(rc);
}
+uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer,
+ void* sparebuffer, uint32_t doecc)
+{
+ return nand_write_page_int(bank, page, databuffer, sparebuffer, doecc, 1);
+}
+
+uint32_t nand_write_page_start(uint32_t bank, uint32_t page, void* databuffer,
+ void* sparebuffer, uint32_t doecc)
+{
+ if (((uint32_t)databuffer & 0xf) || ((uint32_t)sparebuffer & 0xf)
+ || !databuffer || !sparebuffer || !doecc)
+ return nand_write_page_int(bank, page, databuffer, sparebuffer, doecc, 0);
+
+ mutex_lock(&nand_mtx);
+ nand_last_activity_value = current_tick;
+ led(true);
+ if (!nand_powered) nand_power_up();
+ nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
+ if (nand_send_cmd(NAND_CMD_PROGRAM))
+ return nand_unlock(1);
+ if (nand_send_address(page, 0))
+ return nand_unlock(1);
+ nand_transfer_data_start(bank, 1, databuffer, 0x800);
+ if (ecc_encode(3, databuffer, nand_ecc))
+ return nand_unlock(1);
+ memcpy((void*)((uint32_t)sparebuffer + 0xC), nand_ecc, 0x28);
+ memset(nand_ctrl, 0xFF, 0x200);
+ memcpy(nand_ctrl, sparebuffer, 0xC);
+ if (ecc_encode(0, nand_ctrl, nand_ecc))
+ return nand_unlock(1);
+ memcpy((void*)((uint32_t)sparebuffer + 0x34), nand_ecc, 0xC);
+ if (nand_transfer_data_collect(0))
+ return nand_unlock(1);
+ if (nand_transfer_data(bank, 1, sparebuffer, 0x40))
+ return nand_unlock(1);
+ return nand_unlock(nand_send_cmd(NAND_CMD_PROGCNFRM));
+}
+
+uint32_t nand_write_page_collect(uint32_t bank)
+{
+ return nand_wait_status_ready(bank);
+}
+
const struct nand_device_info_type* nand_get_device_type(uint32_t bank)
{
if (nand_type[bank] == 0xFFFFFFFF)