diff options
author | Murali Palnati <palnatim@qualcomm.com> | 2010-01-15 19:50:19 +0530 |
---|---|---|
committer | Murali Palnati <palnatim@qualcomm.com> | 2010-01-15 20:58:26 +0530 |
commit | c54d13aa2f6ac2f74b452d1d310c45936a0afaf9 (patch) | |
tree | 7f4a05e81c2c6984d6e85a81751299d6c5fa9a73 | |
parent | 0ec5bb772a349bd1faa911a88c9a15400d696778 (diff) | |
download | lk-c54d13aa2f6ac2f74b452d1d310c45936a0afaf9.tar.gz |
[msm] Clear relevant status registers after write and erase.
If a Program or Erase operation fails with an OP_ERR (for example when
erasing a bad block or when programming a page in bad block), then an
immediate read operation on a page from good block too fails with the
same OP_ERR. This is because the device status register (in the NAND
flash device) still has the FAIL flag set. This flag gets updated only
when a program or erase operation happens successfully.
To prevent this, clear NANDC_FLASH_STATUS and NANDC_FLASH_READ_STATUS
registers after every nand write and erase operation.
-rwxr-xr-x | platform/msm_shared/nand.c | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/platform/msm_shared/nand.c b/platform/msm_shared/nand.c index 49bec329..30dd3b97 100755 --- a/platform/msm_shared/nand.c +++ b/platform/msm_shared/nand.c @@ -323,6 +323,8 @@ static int flash_nand_erase_block(dmov_s *cmdlist, unsigned *ptrlist, data[5] = 0xeeeeeeee; data[6] = CFG0 & (~(7 << 6)); /* CW_PER_PAGE = 0 */ data[7] = CFG1; + data[8] = 0x00000020; + data[9] = 0x000000C0; cmd[0].cmd = DST_CRCI_NAND_CMD | CMD_OCB; cmd[0].src = paddr(&data[0]); @@ -339,11 +341,21 @@ static int flash_nand_erase_block(dmov_s *cmdlist, unsigned *ptrlist, cmd[2].dst = NAND_EXEC_CMD; cmd[2].len = 4; - cmd[3].cmd = SRC_CRCI_NAND_DATA | CMD_OCU | CMD_LC; + cmd[3].cmd = SRC_CRCI_NAND_DATA; cmd[3].src = NAND_FLASH_STATUS; cmd[3].dst = paddr(&data[5]); cmd[3].len = 4; + cmd[4].cmd = 0; + cmd[4].src = paddr(&data[8]); + cmd[4].dst = NAND_FLASH_STATUS; + cmd[4].len = 4; + + cmd[5].cmd = CMD_OCU | CMD_LC; + cmd[5].src = paddr(&data[9]); + cmd[5].dst = NAND_READ_STATUS; + cmd[5].len = 4; + ptr[0] = (paddr(cmd) >> 3) | CMD_PTR_LP; dmov_exec_cmdptr(DMOV_NAND_CHAN, ptr); @@ -371,6 +383,8 @@ struct data_flash_io { unsigned exec; unsigned ecc_cfg; unsigned ecc_cfg_save; + unsigned clrfstatus; + unsigned clrrstatus; struct { unsigned flash_status; unsigned buffer_status; @@ -516,6 +530,8 @@ static int _flash_nand_write_page(dmov_s *cmdlist, unsigned *ptrlist, unsigned p data->addr0 = page << 16; data->addr1 = (page >> 16) & 0xff; data->chipsel = 0 | 4; /* flash0 + undoc bit */ + data->clrfstatus = 0x00000020; + data->clrrstatus = 0x000000C0; if (!raw_mode){ data->cfg0 = CFG0; @@ -595,6 +611,18 @@ static int _flash_nand_write_page(dmov_s *cmdlist, unsigned *ptrlist, unsigned p cmd->dst = paddr(&data->result[n]); cmd->len = 8; cmd++; + + cmd->cmd = 0; + cmd->src = paddr(&data->clrfstatus); + cmd->dst = NAND_FLASH_STATUS; + cmd->len = 4; + cmd++; + + cmd->cmd = 0; + cmd->src = paddr(&data->clrrstatus); + cmd->dst = NAND_READ_STATUS; + cmd->len = 4; + cmd++; } /* restore saved ecc config */ @@ -676,7 +704,7 @@ static int flash_nand_read_config(dmov_s *cmdlist, unsigned *ptrlist) | (516 << 9) /* 516 user data bytes */ | (10 << 19) /* 10 parity bytes */ | (5 << 27) /* 5 address cycles */ - | (1 << 30) /* Read status before data */ + | (0 << 30) /* Do not read status before data */ | (1 << 31) /* Send read cmd */ /* 0 spare bytes for 16 bit nand or 1 spare bytes for 8 bit */ | ((nand_cfg1 & CFG1_WIDE_FLASH) ? (0 << 23) : (1 << 23)); |