*/
#include "hw/hw.h"
+#include "sysemu/block-backend.h"
#include "sysemu/blockdev.h"
#include "hw/ssi.h"
{ INFO("at26df161a", 0x1f4601, 0, 64 << 10, 32, ER_4K) },
{ INFO("at26df321", 0x1f4700, 0, 64 << 10, 64, ER_4K) },
+ { INFO("at45db081d", 0x1f2500, 0, 64 << 10, 16, ER_4K) },
+
/* EON -- en25xxx */
{ INFO("en25f32", 0x1c3116, 0, 64 << 10, 64, ER_4K) },
{ INFO("en25p32", 0x1c2016, 0, 64 << 10, 64, 0) },
{ INFO("en25q32b", 0x1c3016, 0, 64 << 10, 64, 0) },
{ INFO("en25p64", 0x1c2017, 0, 64 << 10, 128, 0) },
+ { INFO("en25q64", 0x1c3017, 0, 64 << 10, 128, ER_4K) },
+
+ /* GigaDevice */
+ { INFO("gd25q32", 0xc84016, 0, 64 << 10, 64, ER_4K) },
+ { INFO("gd25q64", 0xc84017, 0, 64 << 10, 128, ER_4K) },
/* Intel/Numonyx -- xxxs33b */
{ INFO("160s33b", 0x898911, 0, 64 << 10, 32, 0) },
{ INFO("320s33b", 0x898912, 0, 64 << 10, 64, 0) },
{ INFO("640s33b", 0x898913, 0, 64 << 10, 128, 0) },
+ { INFO("n25q064", 0x20ba17, 0, 64 << 10, 128, 0) },
/* Macronix */
+ { INFO("mx25l2005a", 0xc22012, 0, 64 << 10, 4, ER_4K) },
{ INFO("mx25l4005a", 0xc22013, 0, 64 << 10, 8, ER_4K) },
{ INFO("mx25l8005", 0xc22014, 0, 64 << 10, 16, 0) },
{ INFO("mx25l1606e", 0xc22015, 0, 64 << 10, 32, ER_4K) },
{ INFO("mx25l25635e", 0xc22019, 0, 64 << 10, 512, 0) },
{ INFO("mx25l25655e", 0xc22619, 0, 64 << 10, 512, 0) },
+ /* Micron */
+ { INFO("n25q032a11", 0x20bb16, 0, 64 << 10, 64, ER_4K) },
+ { INFO("n25q032a13", 0x20ba16, 0, 64 << 10, 64, ER_4K) },
+ { INFO("n25q064a11", 0x20bb17, 0, 64 << 10, 128, ER_4K) },
+ { INFO("n25q064a13", 0x20ba17, 0, 64 << 10, 128, ER_4K) },
+ { INFO("n25q128a11", 0x20bb18, 0, 64 << 10, 256, ER_4K) },
+ { INFO("n25q128a13", 0x20ba18, 0, 64 << 10, 256, ER_4K) },
+ { INFO("n25q256a11", 0x20bb19, 0, 64 << 10, 512, ER_4K) },
+ { INFO("n25q256a13", 0x20ba19, 0, 64 << 10, 512, ER_4K) },
+
/* Spansion -- single (large) sector size only, at least
* for the chips listed here (without boot sectors).
*/
- { INFO("s25sl004a", 0x010212, 0, 64 << 10, 8, 0) },
- { INFO("s25sl008a", 0x010213, 0, 64 << 10, 16, 0) },
- { INFO("s25sl016a", 0x010214, 0, 64 << 10, 32, 0) },
- { INFO("s25sl032a", 0x010215, 0, 64 << 10, 64, 0) },
{ INFO("s25sl032p", 0x010215, 0x4d00, 64 << 10, 64, ER_4K) },
- { INFO("s25sl064a", 0x010216, 0, 64 << 10, 128, 0) },
+ { INFO("s25sl064p", 0x010216, 0x4d00, 64 << 10, 128, ER_4K) },
{ INFO("s25fl256s0", 0x010219, 0x4d00, 256 << 10, 128, 0) },
{ INFO("s25fl256s1", 0x010219, 0x4d01, 64 << 10, 512, 0) },
{ INFO("s25fl512s", 0x010220, 0x4d00, 256 << 10, 256, 0) },
{ INFO("s25sl12801", 0x012018, 0x0301, 64 << 10, 256, 0) },
{ INFO("s25fl129p0", 0x012018, 0x4d00, 256 << 10, 64, 0) },
{ INFO("s25fl129p1", 0x012018, 0x4d01, 64 << 10, 256, 0) },
+ { INFO("s25sl004a", 0x010212, 0, 64 << 10, 8, 0) },
+ { INFO("s25sl008a", 0x010213, 0, 64 << 10, 16, 0) },
+ { INFO("s25sl016a", 0x010214, 0, 64 << 10, 32, 0) },
+ { INFO("s25sl032a", 0x010215, 0, 64 << 10, 64, 0) },
+ { INFO("s25sl064a", 0x010216, 0, 64 << 10, 128, 0) },
{ INFO("s25fl016k", 0xef4015, 0, 64 << 10, 32, ER_4K | ER_32K) },
{ INFO("s25fl064k", 0xef4017, 0, 64 << 10, 128, ER_4K | ER_32K) },
{ INFO("m25p32", 0x202016, 0, 64 << 10, 64, 0) },
{ INFO("m25p64", 0x202017, 0, 64 << 10, 128, 0) },
{ INFO("m25p128", 0x202018, 0, 256 << 10, 64, 0) },
+ { INFO("n25q032", 0x20ba16, 0, 64 << 10, 64, 0) },
{ INFO("m45pe10", 0x204011, 0, 64 << 10, 2, 0) },
{ INFO("m45pe80", 0x204014, 0, 64 << 10, 16, 0) },
{ INFO("m45pe16", 0x204015, 0, 64 << 10, 32, 0) },
+ { INFO("m25pe20", 0x208012, 0, 64 << 10, 4, 0) },
{ INFO("m25pe80", 0x208014, 0, 64 << 10, 16, 0) },
{ INFO("m25pe16", 0x208015, 0, 64 << 10, 32, ER_4K) },
{ INFO("w25x16", 0xef3015, 0, 64 << 10, 32, ER_4K) },
{ INFO("w25x32", 0xef3016, 0, 64 << 10, 64, ER_4K) },
{ INFO("w25q32", 0xef4016, 0, 64 << 10, 64, ER_4K) },
+ { INFO("w25q32dw", 0xef6016, 0, 64 << 10, 64, ER_4K) },
{ INFO("w25x64", 0xef3017, 0, 64 << 10, 128, ER_4K) },
{ INFO("w25q64", 0xef4017, 0, 64 << 10, 128, ER_4K) },
+ { INFO("w25q80", 0xef5014, 0, 64 << 10, 16, ER_4K) },
+ { INFO("w25q80bl", 0xef4014, 0, 64 << 10, 16, ER_4K) },
+ { INFO("w25q256", 0xef4019, 0, 64 << 10, 512, ER_4K) },
/* Numonyx -- n25q128 */
{ INFO("n25q128", 0x20ba18, 0, 64 << 10, 256, 0) },
} CMDState;
typedef struct Flash {
- SSISlave ssidev;
+ SSISlave parent_obj;
+
uint32_t r;
- BlockDriverState *bdrv;
+ BlockBackend *blk;
uint8_t *storage;
uint32_t size;
#define M25P80_GET_CLASS(obj) \
OBJECT_GET_CLASS(M25P80Class, (obj), TYPE_M25P80)
-static void bdrv_sync_complete(void *opaque, int ret)
+static void blk_sync_complete(void *opaque, int ret)
{
/* do nothing. Masters do not directly interact with the backing store,
* only the working copy so no mutexing required.
static void flash_sync_page(Flash *s, int page)
{
- if (s->bdrv) {
- int bdrv_sector, nb_sectors;
- QEMUIOVector iov;
-
- bdrv_sector = (page * s->pi->page_size) / BDRV_SECTOR_SIZE;
- nb_sectors = DIV_ROUND_UP(s->pi->page_size, BDRV_SECTOR_SIZE);
- qemu_iovec_init(&iov, 1);
- qemu_iovec_add(&iov, s->storage + bdrv_sector * BDRV_SECTOR_SIZE,
- nb_sectors * BDRV_SECTOR_SIZE);
- bdrv_aio_writev(s->bdrv, bdrv_sector, &iov, nb_sectors,
- bdrv_sync_complete, NULL);
+ int blk_sector, nb_sectors;
+ QEMUIOVector iov;
+
+ if (!s->blk || blk_is_read_only(s->blk)) {
+ return;
}
+
+ blk_sector = (page * s->pi->page_size) / BDRV_SECTOR_SIZE;
+ nb_sectors = DIV_ROUND_UP(s->pi->page_size, BDRV_SECTOR_SIZE);
+ qemu_iovec_init(&iov, 1);
+ qemu_iovec_add(&iov, s->storage + blk_sector * BDRV_SECTOR_SIZE,
+ nb_sectors * BDRV_SECTOR_SIZE);
+ blk_aio_writev(s->blk, blk_sector, &iov, nb_sectors, blk_sync_complete,
+ NULL);
}
static inline void flash_sync_area(Flash *s, int64_t off, int64_t len)
int64_t start, end, nb_sectors;
QEMUIOVector iov;
- if (!s->bdrv) {
+ if (!s->blk || blk_is_read_only(s->blk)) {
return;
}
qemu_iovec_init(&iov, 1);
qemu_iovec_add(&iov, s->storage + (start * BDRV_SECTOR_SIZE),
nb_sectors * BDRV_SECTOR_SIZE);
- bdrv_aio_writev(s->bdrv, start, &iov, nb_sectors, bdrv_sync_complete, NULL);
+ blk_aio_writev(s->blk, start, &iov, nb_sectors, blk_sync_complete, NULL);
}
static void flash_erase(Flash *s, int offset, FlashCMD cmd)
static int m25p80_cs(SSISlave *ss, bool select)
{
- Flash *s = FROM_SSI_SLAVE(Flash, ss);
+ Flash *s = M25P80(ss);
if (select) {
s->len = 0;
static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx)
{
- Flash *s = FROM_SSI_SLAVE(Flash, ss);
+ Flash *s = M25P80(ss);
uint32_t r = 0;
switch (s->state) {
static int m25p80_init(SSISlave *ss)
{
DriveInfo *dinfo;
- Flash *s = FROM_SSI_SLAVE(Flash, ss);
+ Flash *s = M25P80(ss);
M25P80Class *mc = M25P80_GET_CLASS(s);
s->pi = mc->pi;
s->size = s->pi->sector_size * s->pi->n_sectors;
s->dirty_page = -1;
- s->storage = qemu_blockalign(s->bdrv, s->size);
+ /* FIXME use a qdev drive property instead of drive_get_next() */
dinfo = drive_get_next(IF_MTD);
- if (dinfo && dinfo->bdrv) {
+ if (dinfo) {
DB_PRINT_L(0, "Binding to IF_MTD drive\n");
- s->bdrv = dinfo->bdrv;
+ s->blk = blk_by_legacy_dinfo(dinfo);
+ blk_attach_dev_nofail(s->blk, s);
+
+ s->storage = blk_blockalign(s->blk, s->size);
+
/* FIXME: Move to late init */
- if (bdrv_read(s->bdrv, 0, s->storage, DIV_ROUND_UP(s->size,
- BDRV_SECTOR_SIZE))) {
+ if (blk_read(s->blk, 0, s->storage,
+ DIV_ROUND_UP(s->size, BDRV_SECTOR_SIZE))) {
fprintf(stderr, "Failed to initialize SPI flash!\n");
return 1;
}
} else {
DB_PRINT_L(0, "No BDRV - binding to RAM\n");
+ s->storage = blk_blockalign(NULL, s->size);
memset(s->storage, 0xFF, s->size);
}
.name = "xilinx_spi",
.version_id = 1,
.minimum_version_id = 1,
- .minimum_version_id_old = 1,
.pre_save = m25p80_pre_save,
.fields = (VMStateField[]) {
VMSTATE_UINT8(state, Flash),