hw/block/pflash_cfi02: Add helpers to manipulate the status bits
Pull out all of the code to modify the status into simple helper functions. Status handling becomes more complex once multiple chips are interleaved to produce a single device. No change in functionality is intended with this commit. Signed-off-by: Stephen Checkoway <stephen.checkoway@oberlin.edu> Message-Id: <20190426162624.55977-3-stephen.checkoway@oberlin.edu> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com> [PMD: Extracted from bigger patch] Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
This commit is contained in:
parent
aeaf6c20db
commit
1d311e738b
@ -101,6 +101,31 @@ struct PFlashCFI02 {
|
|||||||
void *storage;
|
void *storage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Toggle status bit DQ7.
|
||||||
|
*/
|
||||||
|
static inline void toggle_dq7(PFlashCFI02 *pfl)
|
||||||
|
{
|
||||||
|
pfl->status ^= 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set status bit DQ7 to bit 7 of value.
|
||||||
|
*/
|
||||||
|
static inline void set_dq7(PFlashCFI02 *pfl, uint8_t value)
|
||||||
|
{
|
||||||
|
pfl->status &= 0x7F;
|
||||||
|
pfl->status |= value & 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Toggle status bit DQ6.
|
||||||
|
*/
|
||||||
|
static inline void toggle_dq6(PFlashCFI02 *pfl)
|
||||||
|
{
|
||||||
|
pfl->status ^= 0x40;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up replicated mappings of the same region.
|
* Set up replicated mappings of the same region.
|
||||||
*/
|
*/
|
||||||
@ -130,7 +155,7 @@ static void pflash_timer (void *opaque)
|
|||||||
|
|
||||||
trace_pflash_timer_expired(pfl->cmd);
|
trace_pflash_timer_expired(pfl->cmd);
|
||||||
/* Reset flash */
|
/* Reset flash */
|
||||||
pfl->status ^= 0x80;
|
toggle_dq7(pfl);
|
||||||
if (pfl->bypass) {
|
if (pfl->bypass) {
|
||||||
pfl->wcycle = 2;
|
pfl->wcycle = 2;
|
||||||
} else {
|
} else {
|
||||||
@ -229,8 +254,7 @@ static uint32_t pflash_read(PFlashCFI02 *pfl, hwaddr offset,
|
|||||||
/* Status register read */
|
/* Status register read */
|
||||||
ret = pfl->status;
|
ret = pfl->status;
|
||||||
DPRINTF("%s: status %" PRIx32 "\n", __func__, ret);
|
DPRINTF("%s: status %" PRIx32 "\n", __func__, ret);
|
||||||
/* Toggle bit 6 */
|
toggle_dq6(pfl);
|
||||||
pfl->status ^= 0x40;
|
|
||||||
break;
|
break;
|
||||||
case 0x98:
|
case 0x98:
|
||||||
/* CFI query mode */
|
/* CFI query mode */
|
||||||
@ -374,7 +398,11 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pfl->status = 0x00 | ~(value & 0x80);
|
/*
|
||||||
|
* While programming, status bit DQ7 should hold the opposite
|
||||||
|
* value from how it was programmed.
|
||||||
|
*/
|
||||||
|
set_dq7(pfl, ~value);
|
||||||
/* Let's pretend write is immediate */
|
/* Let's pretend write is immediate */
|
||||||
if (pfl->bypass)
|
if (pfl->bypass)
|
||||||
goto do_bypass;
|
goto do_bypass;
|
||||||
@ -422,7 +450,7 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset,
|
|||||||
memset(pfl->storage, 0xFF, pfl->chip_len);
|
memset(pfl->storage, 0xFF, pfl->chip_len);
|
||||||
pflash_update(pfl, 0, pfl->chip_len);
|
pflash_update(pfl, 0, pfl->chip_len);
|
||||||
}
|
}
|
||||||
pfl->status = 0x00;
|
set_dq7(pfl, 0x00);
|
||||||
/* Let's wait 5 seconds before chip erase is done */
|
/* Let's wait 5 seconds before chip erase is done */
|
||||||
timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
|
timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
|
||||||
(NANOSECONDS_PER_SECOND * 5));
|
(NANOSECONDS_PER_SECOND * 5));
|
||||||
@ -437,7 +465,7 @@ static void pflash_write(PFlashCFI02 *pfl, hwaddr offset,
|
|||||||
memset(p + offset, 0xFF, pfl->sector_len);
|
memset(p + offset, 0xFF, pfl->sector_len);
|
||||||
pflash_update(pfl, offset, pfl->sector_len);
|
pflash_update(pfl, offset, pfl->sector_len);
|
||||||
}
|
}
|
||||||
pfl->status = 0x00;
|
set_dq7(pfl, 0x00);
|
||||||
/* Let's wait 1/2 second before sector erase is done */
|
/* Let's wait 1/2 second before sector erase is done */
|
||||||
timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
|
timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
|
||||||
(NANOSECONDS_PER_SECOND / 2));
|
(NANOSECONDS_PER_SECOND / 2));
|
||||||
|
Loading…
Reference in New Issue
Block a user