diff options
author | Michael Sparmann <theseven@rockbox.org> | 2010-03-13 21:44:39 +0000 |
---|---|---|
committer | Michael Sparmann <theseven@rockbox.org> | 2010-03-13 21:44:39 +0000 |
commit | 382b6dca08254e815a39db5fefbc2bf98142c812 (patch) | |
tree | d665d8f283e1e96a67aceb02c310fc61d5ae8599 | |
parent | cb41b2f2457015a3594eb63e917c5742564fc801 (diff) |
Nano2G NAND interleaved write support
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25154 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c | 63 |
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) |