pflash: Buffer block writes
Buffer block writes to avoid flushing every word access onto backing storage device. This significantly speeds up flash emulation for flashes connected through an 8 or 16-bit bus combined with backing storage (-pflash). Signed-off-by: Edgar E. Iglesias <edgar.iglesias@petalogix.com>
This commit is contained in:
parent
625a5befc2
commit
b4bf0a9a69
@ -72,6 +72,7 @@ struct pflash_t {
|
|||||||
uint8_t cfi_len;
|
uint8_t cfi_len;
|
||||||
uint8_t cfi_table[0x52];
|
uint8_t cfi_table[0x52];
|
||||||
target_phys_addr_t counter;
|
target_phys_addr_t counter;
|
||||||
|
unsigned int writeblock_size;
|
||||||
QEMUTimer *timer;
|
QEMUTimer *timer;
|
||||||
ram_addr_t off;
|
ram_addr_t off;
|
||||||
int fl_mem;
|
int fl_mem;
|
||||||
@ -206,7 +207,6 @@ static inline void pflash_data_write(pflash_t *pfl, target_phys_addr_t offset,
|
|||||||
switch (width) {
|
switch (width) {
|
||||||
case 1:
|
case 1:
|
||||||
p[offset] = value;
|
p[offset] = value;
|
||||||
pflash_update(pfl, offset, 1);
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||||
@ -216,7 +216,6 @@ static inline void pflash_data_write(pflash_t *pfl, target_phys_addr_t offset,
|
|||||||
p[offset] = value;
|
p[offset] = value;
|
||||||
p[offset + 1] = value >> 8;
|
p[offset + 1] = value >> 8;
|
||||||
#endif
|
#endif
|
||||||
pflash_update(pfl, offset, 2);
|
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||||
@ -230,7 +229,6 @@ static inline void pflash_data_write(pflash_t *pfl, target_phys_addr_t offset,
|
|||||||
p[offset + 2] = value >> 16;
|
p[offset + 2] = value >> 16;
|
||||||
p[offset + 3] = value >> 24;
|
p[offset + 3] = value >> 24;
|
||||||
#endif
|
#endif
|
||||||
pflash_update(pfl, offset, 4);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,6 +305,7 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset,
|
|||||||
case 0x40: /* Single Byte Program */
|
case 0x40: /* Single Byte Program */
|
||||||
DPRINTF("%s: Single Byte Program\n", __func__);
|
DPRINTF("%s: Single Byte Program\n", __func__);
|
||||||
pflash_data_write(pfl, offset, value, width);
|
pflash_data_write(pfl, offset, value, width);
|
||||||
|
pflash_update(pfl, offset, width);
|
||||||
pfl->status |= 0x80; /* Ready! */
|
pfl->status |= 0x80; /* Ready! */
|
||||||
pfl->wcycle = 0;
|
pfl->wcycle = 0;
|
||||||
break;
|
break;
|
||||||
@ -359,8 +358,13 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset,
|
|||||||
pfl->status |= 0x80;
|
pfl->status |= 0x80;
|
||||||
|
|
||||||
if (!pfl->counter) {
|
if (!pfl->counter) {
|
||||||
|
target_phys_addr_t mask = pfl->writeblock_size - 1;
|
||||||
|
mask = ~mask;
|
||||||
|
|
||||||
DPRINTF("%s: block write finished\n", __func__);
|
DPRINTF("%s: block write finished\n", __func__);
|
||||||
pfl->wcycle++;
|
pfl->wcycle++;
|
||||||
|
/* Flush the entire write buffer onto backing storage. */
|
||||||
|
pflash_update(pfl, offset & mask, pfl->writeblock_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
pfl->counter--;
|
pfl->counter--;
|
||||||
@ -606,6 +610,8 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off,
|
|||||||
} else {
|
} else {
|
||||||
pfl->cfi_table[0x2A] = 0x0B;
|
pfl->cfi_table[0x2A] = 0x0B;
|
||||||
}
|
}
|
||||||
|
pfl->writeblock_size = 1 << pfl->cfi_table[0x2A];
|
||||||
|
|
||||||
pfl->cfi_table[0x2B] = 0x00;
|
pfl->cfi_table[0x2B] = 0x00;
|
||||||
/* Number of erase block regions (uniform) */
|
/* Number of erase block regions (uniform) */
|
||||||
pfl->cfi_table[0x2C] = 0x01;
|
pfl->cfi_table[0x2C] = 0x01;
|
||||||
|
Loading…
Reference in New Issue
Block a user