From patchwork Tue Feb 26 09:14:02 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [v4,11/23] hw/nand.c: bug fix to BUSY/READY status bit Date: Mon, 25 Feb 2013 23:14:02 -0000 From: Kuo-Jung Su X-Patchwork-Id: 223177 Message-Id: <1361870054-18564-12-git-send-email-dantesu@gmail.com> To: qemu-devel@nongnu.org Cc: Peter Maydell , i.mitsyanko@samsung.com, Blue Swirl , Paul Brook , Kuo-Jung Su , Andreas , fred.konrad@greensocs.com From: Kuo-Jung Su Status Register(SR): SR[6] behaves the same as R/B# pin SR[6] = 0 indicates the device is busy; SR[6] = 1 means the device is ready Some NAND flash controller (i.e. ftnandc021) relies on the SR[6] to determine if the NAND flash erase/program is success, and then report the status code to the host driver. Signed-off-by: Kuo-Jung Su --- hw/nand.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/hw/nand.c b/hw/nand.c index 4a71265..7f40ebf 100644 --- a/hw/nand.c +++ b/hw/nand.c @@ -46,7 +46,7 @@ # define NAND_IOSTATUS_PLANE1 (1 << 2) # define NAND_IOSTATUS_PLANE2 (1 << 3) # define NAND_IOSTATUS_PLANE3 (1 << 4) -# define NAND_IOSTATUS_BUSY (1 << 6) +# define NAND_IOSTATUS_READY (1 << 6) # define NAND_IOSTATUS_UNPROTCT (1 << 7) # define MAX_PAGE 0x800 @@ -231,6 +231,7 @@ static void nand_reset(DeviceState *dev) s->iolen = 0; s->offset = 0; s->status &= NAND_IOSTATUS_UNPROTCT; + s->status |= NAND_IOSTATUS_READY; } static inline void nand_pushio_byte(NANDFlashState *s, uint8_t value) @@ -647,6 +648,8 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s) if (PAGE(s->addr) >= s->pages) return; + s->status &= ~NAND_IOSTATUS_READY; + if (!s->bdrv) { mem_and(s->storage + PAGE_START(s->addr) + (s->addr & PAGE_MASK) + s->offset, s->io, s->iolen); @@ -656,7 +659,7 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s) soff = SECTOR_OFFSET(s->addr); if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, sector); - return; + goto blkw_out; } mem_and(iobuf + (soff | off), s->io, MIN(s->iolen, PAGE_SIZE - off)); @@ -675,7 +678,7 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s) soff = off & 0x1ff; if (bdrv_read(s->bdrv, sector, iobuf, PAGE_SECTORS + 2) < 0) { printf("%s: read error in sector %" PRIu64 "\n", __func__, sector); - return; + goto blkw_out; } mem_and(iobuf + soff, s->io, s->iolen); @@ -685,6 +688,9 @@ static void glue(nand_blk_write_, PAGE_SIZE)(NANDFlashState *s) } } s->offset = 0; + +blkw_out: + s->status |= NAND_IOSTATUS_READY; } /* Erase a single block */ @@ -697,6 +703,8 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s) if (PAGE(addr) >= s->pages) return; + s->status &= ~NAND_IOSTATUS_READY; + if (!s->bdrv) { memset(s->storage + PAGE_START(addr), 0xff, (PAGE_SIZE + OOB_SIZE) << s->erase_shift); @@ -738,6 +746,8 @@ static void glue(nand_blk_erase_, PAGE_SIZE)(NANDFlashState *s) printf("%s: write error in sector %" PRIu64 "\n", __func__, page); } } + + s->status |= NAND_IOSTATUS_READY; } static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s, @@ -746,6 +756,8 @@ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s, if (PAGE(addr) >= s->pages) return; + s->status &= ~NAND_IOSTATUS_READY; + if (s->bdrv) { if (s->mem_oob) { if (bdrv_read(s->bdrv, SECTOR(addr), s->io, PAGE_SECTORS) < 0) { @@ -769,6 +781,8 @@ static void glue(nand_blk_load_, PAGE_SIZE)(NANDFlashState *s, offset, PAGE_SIZE + OOB_SIZE - offset); s->ioaddr = s->io; } + + s->status |= NAND_IOSTATUS_READY; } static void glue(nand_init_, PAGE_SIZE)(NANDFlashState *s)