Re: [Qemu-devel] [PATCH v3 2/4] m25p80: initial verion
On 20 April 2012 03:12, Peter A. G. Crosthwaite peter.crosthwa...@petalogix.com wrote: Subject: [PATCH v3 2/4] m25p80: initial verion Added device model for m25p80 SPI flash This commit message could be improved; I'd suggest a summary line of m25p80: Initial implementation of SPI flash device Signed-off-by: Peter A. G. Crosthwaite peter.crosthwa...@petalogix.com --- changed from v2: updated for SSI slave interface used async io (suggested - Stefan Hajnoczi) changed from v1: converted spi api to modified txrx style factored out lots of common code and inlined overly short single call functions. undated for txrx style spi interface Makefile.target | 1 + hw/m25p80.c | 378 +++ 2 files changed, 379 insertions(+), 0 deletions(-) create mode 100644 hw/m25p80.c diff --git a/Makefile.target b/Makefile.target index 84951a0..3f7c38e 100644 --- a/Makefile.target +++ b/Makefile.target @@ -326,6 +326,7 @@ obj-mips-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o obj-microblaze-y = petalogix_s3adsp1800_mmu.o obj-microblaze-y += petalogix_ml605_mmu.o obj-microblaze-y += microblaze_boot.o +obj-microblaze-y += m25p80.o obj-microblaze-y += microblaze_pic_cpu.o obj-microblaze-y += xilinx_intc.o diff --git a/hw/m25p80.c b/hw/m25p80.c new file mode 100644 index 000..e6c1f3b --- /dev/null +++ b/hw/m25p80.c @@ -0,0 +1,378 @@ +/* + * ST M25P80 emulator. ST M25P80 SPI Flash device. -- don't force readers to go and google for the part number to find out what it is :-) + * + * Copyright (C) 2011 Edgar E. Iglesias edgar.igles...@gmail.com + * Copyright (C) 2012 Peter A. G. Crosthwaite peter.crosthwa...@petalogix.com + * Copyright (C) 2012 PetaLogix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. Do we really want GPL 2 or 3, rather than 2 or later ? + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see http://www.gnu.org/licenses/. + */ + +#include hw.h +#include blockdev.h +#include ssi.h +#include devices.h + +#ifdef M25P80_ERR_DEBUG +#define DB_PRINT(...) do { \ + fprintf(stderr, : %s: , __func__); \ + fprintf(stderr, ## __VA_ARGS__); \ + } while (0); +#else + #define DB_PRINT(...) +#endif + +enum FlashCMD { + NOP = 0, + PP = 0x2, + READ = 0x3, + WRDI = 0x4, + RDSR = 0x5, + WREN = 0x6, + FAST_READ = 0xb, + SECTOR_ERASE = 0x20, + BLOCK_ERASE32 = 0x52, + JEDEC_READ = 0x9f, + CHIP_ERASE = 0xc7, +}; + +enum CMDState { + STATE_IDLE, + STATE_PAGE_PROGRAM, + STATE_READ, + STATE_COLLECTING_DATA, + STATE_READING_DATA, +}; + +struct flash { + SSISlave ssidev; + uint32_t r; + + BlockDriverState *bdrv; + enum CMDState state; + + uint8_t *storage; + uint64_t size; + int pagesize; + int sectorsize; + int blocksize; + + uint8_t data[16]; + int len; + int pos; + int wrap_read; + int needed_bytes; + enum FlashCMD cmd_in_progress; + + int64_t dirty_page; + + uint64_t waddr; + int write_enable; +}; Missing save/load support (which will cause you to want to turn a lot of those 'int's into either 'bool' or known-width types). + +static void bdrv_sync_complete(void *opaque, int ret) +{ + +} Is there really nothing to do here? If so, perhaps a comment explaining why... + +static void flash_sync_page(struct flash *s, int page) +{ + if (s-bdrv) { + int bdrv_sector, nb_sectors; + QEMUIOVector iov; + + bdrv_sector = (page * s-pagesize) / 512; + nb_sectors = (s-pagesize + 511) / 512; There's a DIV_ROUND_UP macro, if you like: nb_sectors = DIV_ROUND_UP(s-pagesize, BDRV_SECTOR_SIZE); (though it isn't really used much in qemu currently.) + qemu_iovec_init(iov, 1); + qemu_iovec_add(iov, s-storage + bdrv_sector * 512, + nb_sectors * 512); Lots of hardcoded 512 here and elsewhere, you probably mean BDRV_SECTOR_SIZE. + bdrv_aio_writev(s-bdrv, bdrv_sector, iov, nb_sectors, + bdrv_sync_complete, NULL); + } +} + +static inline void flash_sync_area(struct flash *s, int64_t off, int64_t len) +{ + int64_t start, end; + + if (!s-bdrv) { + return; + } + + start = off / 512; + end = (off + len) / 512; This rounds down so you
Re: [Qemu-devel] [PATCH v3 2/4] m25p80: initial verion
On Fri, Apr 20, 2012 at 3:12 AM, Peter A. G. Crosthwaite peter.crosthwa...@petalogix.com wrote: +static inline void flash_sync_area(struct flash *s, int64_t off, int64_t len) +{ + int64_t start, end; + + if (!s-bdrv) { + return; + } + + start = off / 512; + end = (off + len) / 512; + bdrv_write(s-bdrv, start, s-storage + (start * 512), end - start); Is it possible to use bdrv_aio_write() like in flash_sync_page()? Stefan
[Qemu-devel] [PATCH v3 2/4] m25p80: initial verion
Added device model for m25p80 SPI flash Signed-off-by: Peter A. G. Crosthwaite peter.crosthwa...@petalogix.com --- changed from v2: updated for SSI slave interface used async io (suggested - Stefan Hajnoczi) changed from v1: converted spi api to modified txrx style factored out lots of common code and inlined overly short single call functions. undated for txrx style spi interface Makefile.target |1 + hw/m25p80.c | 378 +++ 2 files changed, 379 insertions(+), 0 deletions(-) create mode 100644 hw/m25p80.c diff --git a/Makefile.target b/Makefile.target index 84951a0..3f7c38e 100644 --- a/Makefile.target +++ b/Makefile.target @@ -326,6 +326,7 @@ obj-mips-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o obj-microblaze-y = petalogix_s3adsp1800_mmu.o obj-microblaze-y += petalogix_ml605_mmu.o obj-microblaze-y += microblaze_boot.o +obj-microblaze-y += m25p80.o obj-microblaze-y += microblaze_pic_cpu.o obj-microblaze-y += xilinx_intc.o diff --git a/hw/m25p80.c b/hw/m25p80.c new file mode 100644 index 000..e6c1f3b --- /dev/null +++ b/hw/m25p80.c @@ -0,0 +1,378 @@ +/* + * ST M25P80 emulator. + * + * Copyright (C) 2011 Edgar E. Iglesias edgar.igles...@gmail.com + * Copyright (C) 2012 Peter A. G. Crosthwaite peter.crosthwa...@petalogix.com + * Copyright (C) 2012 PetaLogix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see http://www.gnu.org/licenses/. + */ + +#include hw.h +#include blockdev.h +#include ssi.h +#include devices.h + +#ifdef M25P80_ERR_DEBUG +#define DB_PRINT(...) do { \ +fprintf(stderr, : %s: , __func__); \ +fprintf(stderr, ## __VA_ARGS__); \ +} while (0); +#else +#define DB_PRINT(...) +#endif + +enum FlashCMD { +NOP = 0, +PP = 0x2, +READ = 0x3, +WRDI = 0x4, +RDSR = 0x5, +WREN = 0x6, +FAST_READ = 0xb, +SECTOR_ERASE = 0x20, +BLOCK_ERASE32 = 0x52, +JEDEC_READ = 0x9f, +CHIP_ERASE = 0xc7, +}; + +enum CMDState { +STATE_IDLE, +STATE_PAGE_PROGRAM, +STATE_READ, +STATE_COLLECTING_DATA, +STATE_READING_DATA, +}; + +struct flash { +SSISlave ssidev; +uint32_t r; + +BlockDriverState *bdrv; +enum CMDState state; + +uint8_t *storage; +uint64_t size; +int pagesize; +int sectorsize; +int blocksize; + +uint8_t data[16]; +int len; +int pos; +int wrap_read; +int needed_bytes; +enum FlashCMD cmd_in_progress; + +int64_t dirty_page; + +uint64_t waddr; +int write_enable; +}; + +static void bdrv_sync_complete(void *opaque, int ret) +{ + +} + +static void flash_sync_page(struct flash *s, int page) +{ +if (s-bdrv) { +int bdrv_sector, nb_sectors; +QEMUIOVector iov; + +bdrv_sector = (page * s-pagesize) / 512; +nb_sectors = (s-pagesize + 511) / 512; +qemu_iovec_init(iov, 1); +qemu_iovec_add(iov, s-storage + bdrv_sector * 512, +nb_sectors * 512); +bdrv_aio_writev(s-bdrv, bdrv_sector, iov, nb_sectors, +bdrv_sync_complete, NULL); +} +} + +static inline void flash_sync_area(struct flash *s, int64_t off, int64_t len) +{ +int64_t start, end; + +if (!s-bdrv) { +return; +} + +start = off / 512; +end = (off + len) / 512; +bdrv_write(s-bdrv, start, s-storage + (start * 512), end - start); +} + +static void flash_sector_erase(struct flash *s, int sector) +{ +if (!s-write_enable) { +DB_PRINT(write with write protect!\n); +} +memset(s-storage + sector, 0xff, s-sectorsize); +flash_sync_area(s, sector, s-sectorsize); +} + +static void flash_block_erase32k(struct flash *s, int addr) +{ +if (!s-write_enable) { +DB_PRINT(write with write protect!\n); +} +memset(s-storage + addr, 0xff, 32 * 1024); +flash_sync_area(s, addr, 32 * 1024); +} + +static void flash_chip_erase(struct flash *s) +{ +if (!s-write_enable) { +DB_PRINT(write with write protect!\n); +} +memset(s-storage, 0xff, s-size); +flash_sync_area(s, 0, s-size); +} + +static inline void flash_sync_dirty(struct flash *s, int64_t newpage) +{ +if (s-dirty_page = 0 s-dirty_page != newpage) { +flash_sync_page(s, s-dirty_page); +s-dirty_page = newpage; +} +} + +static inline +void flash_write8(struct flash *s, uint64_t