qemu/hw/block/m25p80.c
<<
>>
Prefs
   1/*
   2 * ST M25P80 emulator. Emulate all SPI flash devices based on the m25p80 command
   3 * set. Known devices table current as of Jun/2012 and taken from linux.
   4 * See drivers/mtd/devices/m25p80.c.
   5 *
   6 * Copyright (C) 2011 Edgar E. Iglesias <edgar.iglesias@gmail.com>
   7 * Copyright (C) 2012 Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
   8 * Copyright (C) 2012 PetaLogix
   9 *
  10 * This program is free software; you can redistribute it and/or
  11 * modify it under the terms of the GNU General Public License as
  12 * published by the Free Software Foundation; either version 2 or
  13 * (at your option) a later version of the License.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 * GNU General Public License for more details.
  19 *
  20 * You should have received a copy of the GNU General Public License along
  21 * with this program; if not, see <http://www.gnu.org/licenses/>.
  22 */
  23
  24#include "hw/hw.h"
  25#include "sysemu/block-backend.h"
  26#include "sysemu/blockdev.h"
  27#include "hw/ssi.h"
  28
  29#ifndef M25P80_ERR_DEBUG
  30#define M25P80_ERR_DEBUG 0
  31#endif
  32
  33#define DB_PRINT_L(level, ...) do { \
  34    if (M25P80_ERR_DEBUG > (level)) { \
  35        fprintf(stderr,  ": %s: ", __func__); \
  36        fprintf(stderr, ## __VA_ARGS__); \
  37    } \
  38} while (0);
  39
  40/* Fields for FlashPartInfo->flags */
  41
  42/* erase capabilities */
  43#define ER_4K 1
  44#define ER_32K 2
  45/* set to allow the page program command to write 0s back to 1. Useful for
  46 * modelling EEPROM with SPI flash command set
  47 */
  48#define WR_1 0x100
  49
  50typedef struct FlashPartInfo {
  51    const char *part_name;
  52    /* jedec code. (jedec >> 16) & 0xff is the 1st byte, >> 8 the 2nd etc */
  53    uint32_t jedec;
  54    /* extended jedec code */
  55    uint16_t ext_jedec;
  56    /* there is confusion between manufacturers as to what a sector is. In this
  57     * device model, a "sector" is the size that is erased by the ERASE_SECTOR
  58     * command (opcode 0xd8).
  59     */
  60    uint32_t sector_size;
  61    uint32_t n_sectors;
  62    uint32_t page_size;
  63    uint8_t flags;
  64} FlashPartInfo;
  65
  66/* adapted from linux */
  67
  68#define INFO(_part_name, _jedec, _ext_jedec, _sector_size, _n_sectors, _flags)\
  69    .part_name = (_part_name),\
  70    .jedec = (_jedec),\
  71    .ext_jedec = (_ext_jedec),\
  72    .sector_size = (_sector_size),\
  73    .n_sectors = (_n_sectors),\
  74    .page_size = 256,\
  75    .flags = (_flags),\
  76
  77#define JEDEC_NUMONYX 0x20
  78#define JEDEC_WINBOND 0xEF
  79#define JEDEC_SPANSION 0x01
  80
  81static const FlashPartInfo known_devices[] = {
  82    /* Atmel -- some are (confusingly) marketed as "DataFlash" */
  83    { INFO("at25fs010",   0x1f6601,      0,  32 << 10,   4, ER_4K) },
  84    { INFO("at25fs040",   0x1f6604,      0,  64 << 10,   8, ER_4K) },
  85
  86    { INFO("at25df041a",  0x1f4401,      0,  64 << 10,   8, ER_4K) },
  87    { INFO("at25df321a",  0x1f4701,      0,  64 << 10,  64, ER_4K) },
  88    { INFO("at25df641",   0x1f4800,      0,  64 << 10, 128, ER_4K) },
  89
  90    { INFO("at26f004",    0x1f0400,      0,  64 << 10,   8, ER_4K) },
  91    { INFO("at26df081a",  0x1f4501,      0,  64 << 10,  16, ER_4K) },
  92    { INFO("at26df161a",  0x1f4601,      0,  64 << 10,  32, ER_4K) },
  93    { INFO("at26df321",   0x1f4700,      0,  64 << 10,  64, ER_4K) },
  94
  95    { INFO("at45db081d",  0x1f2500,      0,  64 << 10,  16, ER_4K) },
  96
  97    /* EON -- en25xxx */
  98    { INFO("en25f32",     0x1c3116,      0,  64 << 10,  64, ER_4K) },
  99    { INFO("en25p32",     0x1c2016,      0,  64 << 10,  64, 0) },
 100    { INFO("en25q32b",    0x1c3016,      0,  64 << 10,  64, 0) },
 101    { INFO("en25p64",     0x1c2017,      0,  64 << 10, 128, 0) },
 102    { INFO("en25q64",     0x1c3017,      0,  64 << 10, 128, ER_4K) },
 103
 104    /* GigaDevice */
 105    { INFO("gd25q32",     0xc84016,      0,  64 << 10,  64, ER_4K) },
 106    { INFO("gd25q64",     0xc84017,      0,  64 << 10, 128, ER_4K) },
 107
 108    /* Intel/Numonyx -- xxxs33b */
 109    { INFO("160s33b",     0x898911,      0,  64 << 10,  32, 0) },
 110    { INFO("320s33b",     0x898912,      0,  64 << 10,  64, 0) },
 111    { INFO("640s33b",     0x898913,      0,  64 << 10, 128, 0) },
 112    { INFO("n25q064",     0x20ba17,      0,  64 << 10, 128, 0) },
 113
 114    /* Macronix */
 115    { INFO("mx25l2005a",  0xc22012,      0,  64 << 10,   4, ER_4K) },
 116    { INFO("mx25l4005a",  0xc22013,      0,  64 << 10,   8, ER_4K) },
 117    { INFO("mx25l8005",   0xc22014,      0,  64 << 10,  16, 0) },
 118    { INFO("mx25l1606e",  0xc22015,      0,  64 << 10,  32, ER_4K) },
 119    { INFO("mx25l3205d",  0xc22016,      0,  64 << 10,  64, 0) },
 120    { INFO("mx25l6405d",  0xc22017,      0,  64 << 10, 128, 0) },
 121    { INFO("mx25l12805d", 0xc22018,      0,  64 << 10, 256, 0) },
 122    { INFO("mx25l12855e", 0xc22618,      0,  64 << 10, 256, 0) },
 123    { INFO("mx25l25635e", 0xc22019,      0,  64 << 10, 512, 0) },
 124    { INFO("mx25l25655e", 0xc22619,      0,  64 << 10, 512, 0) },
 125
 126    /* Micron */
 127    { INFO("n25q032a11",  0x20bb16,      0,  64 << 10,  64, ER_4K) },
 128    { INFO("n25q032a13",  0x20ba16,      0,  64 << 10,  64, ER_4K) },
 129    { INFO("n25q064a11",  0x20bb17,      0,  64 << 10, 128, ER_4K) },
 130    { INFO("n25q064a13",  0x20ba17,      0,  64 << 10, 128, ER_4K) },
 131    { INFO("n25q128a11",  0x20bb18,      0,  64 << 10, 256, ER_4K) },
 132    { INFO("n25q128a13",  0x20ba18,      0,  64 << 10, 256, ER_4K) },
 133    { INFO("n25q256a11",  0x20bb19,      0,  64 << 10, 512, ER_4K) },
 134    { INFO("n25q256a13",  0x20ba19,      0,  64 << 10, 512, ER_4K) },
 135
 136    /* Spansion -- single (large) sector size only, at least
 137     * for the chips listed here (without boot sectors).
 138     */
 139    { INFO("s25sl032p",   0x010215, 0x4d00,  64 << 10,  64, ER_4K) },
 140    { INFO("s25sl064p",   0x010216, 0x4d00,  64 << 10, 128, ER_4K) },
 141    { INFO("s25fl256s0",  0x010219, 0x4d00, 256 << 10, 128, 0) },
 142    { INFO("s25fl256s1",  0x010219, 0x4d01,  64 << 10, 512, 0) },
 143    { INFO("s25fl512s",   0x010220, 0x4d00, 256 << 10, 256, 0) },
 144    { INFO("s70fl01gs",   0x010221, 0x4d00, 256 << 10, 256, 0) },
 145    { INFO("s25sl12800",  0x012018, 0x0300, 256 << 10,  64, 0) },
 146    { INFO("s25sl12801",  0x012018, 0x0301,  64 << 10, 256, 0) },
 147    { INFO("s25fl129p0",  0x012018, 0x4d00, 256 << 10,  64, 0) },
 148    { INFO("s25fl129p1",  0x012018, 0x4d01,  64 << 10, 256, 0) },
 149    { INFO("s25sl004a",   0x010212,      0,  64 << 10,   8, 0) },
 150    { INFO("s25sl008a",   0x010213,      0,  64 << 10,  16, 0) },
 151    { INFO("s25sl016a",   0x010214,      0,  64 << 10,  32, 0) },
 152    { INFO("s25sl032a",   0x010215,      0,  64 << 10,  64, 0) },
 153    { INFO("s25sl064a",   0x010216,      0,  64 << 10, 128, 0) },
 154    { INFO("s25fl016k",   0xef4015,      0,  64 << 10,  32, ER_4K | ER_32K) },
 155    { INFO("s25fl064k",   0xef4017,      0,  64 << 10, 128, ER_4K | ER_32K) },
 156
 157    /* SST -- large erase sizes are "overlays", "sectors" are 4<< 10 */
 158    { INFO("sst25vf040b", 0xbf258d,      0,  64 << 10,   8, ER_4K) },
 159    { INFO("sst25vf080b", 0xbf258e,      0,  64 << 10,  16, ER_4K) },
 160    { INFO("sst25vf016b", 0xbf2541,      0,  64 << 10,  32, ER_4K) },
 161    { INFO("sst25vf032b", 0xbf254a,      0,  64 << 10,  64, ER_4K) },
 162    { INFO("sst25wf512",  0xbf2501,      0,  64 << 10,   1, ER_4K) },
 163    { INFO("sst25wf010",  0xbf2502,      0,  64 << 10,   2, ER_4K) },
 164    { INFO("sst25wf020",  0xbf2503,      0,  64 << 10,   4, ER_4K) },
 165    { INFO("sst25wf040",  0xbf2504,      0,  64 << 10,   8, ER_4K) },
 166
 167    /* ST Microelectronics -- newer production may have feature updates */
 168    { INFO("m25p05",      0x202010,      0,  32 << 10,   2, 0) },
 169    { INFO("m25p10",      0x202011,      0,  32 << 10,   4, 0) },
 170    { INFO("m25p20",      0x202012,      0,  64 << 10,   4, 0) },
 171    { INFO("m25p40",      0x202013,      0,  64 << 10,   8, 0) },
 172    { INFO("m25p80",      0x202014,      0,  64 << 10,  16, 0) },
 173    { INFO("m25p16",      0x202015,      0,  64 << 10,  32, 0) },
 174    { INFO("m25p32",      0x202016,      0,  64 << 10,  64, 0) },
 175    { INFO("m25p64",      0x202017,      0,  64 << 10, 128, 0) },
 176    { INFO("m25p128",     0x202018,      0, 256 << 10,  64, 0) },
 177    { INFO("n25q032",     0x20ba16,      0,  64 << 10,  64, 0) },
 178
 179    { INFO("m45pe10",     0x204011,      0,  64 << 10,   2, 0) },
 180    { INFO("m45pe80",     0x204014,      0,  64 << 10,  16, 0) },
 181    { INFO("m45pe16",     0x204015,      0,  64 << 10,  32, 0) },
 182
 183    { INFO("m25pe20",     0x208012,      0,  64 << 10,   4, 0) },
 184    { INFO("m25pe80",     0x208014,      0,  64 << 10,  16, 0) },
 185    { INFO("m25pe16",     0x208015,      0,  64 << 10,  32, ER_4K) },
 186
 187    { INFO("m25px32",     0x207116,      0,  64 << 10,  64, ER_4K) },
 188    { INFO("m25px32-s0",  0x207316,      0,  64 << 10,  64, ER_4K) },
 189    { INFO("m25px32-s1",  0x206316,      0,  64 << 10,  64, ER_4K) },
 190    { INFO("m25px64",     0x207117,      0,  64 << 10, 128, 0) },
 191
 192    /* Winbond -- w25x "blocks" are 64k, "sectors" are 4KiB */
 193    { INFO("w25x10",      0xef3011,      0,  64 << 10,   2, ER_4K) },
 194    { INFO("w25x20",      0xef3012,      0,  64 << 10,   4, ER_4K) },
 195    { INFO("w25x40",      0xef3013,      0,  64 << 10,   8, ER_4K) },
 196    { INFO("w25x80",      0xef3014,      0,  64 << 10,  16, ER_4K) },
 197    { INFO("w25x16",      0xef3015,      0,  64 << 10,  32, ER_4K) },
 198    { INFO("w25x32",      0xef3016,      0,  64 << 10,  64, ER_4K) },
 199    { INFO("w25q32",      0xef4016,      0,  64 << 10,  64, ER_4K) },
 200    { INFO("w25q32dw",    0xef6016,      0,  64 << 10,  64, ER_4K) },
 201    { INFO("w25x64",      0xef3017,      0,  64 << 10, 128, ER_4K) },
 202    { INFO("w25q64",      0xef4017,      0,  64 << 10, 128, ER_4K) },
 203    { INFO("w25q80",      0xef5014,      0,  64 << 10,  16, ER_4K) },
 204    { INFO("w25q80bl",    0xef4014,      0,  64 << 10,  16, ER_4K) },
 205    { INFO("w25q256",     0xef4019,      0,  64 << 10, 512, ER_4K) },
 206
 207    /* Numonyx -- n25q128 */
 208    { INFO("n25q128",      0x20ba18,      0,  64 << 10, 256, 0) },
 209};
 210
 211typedef enum {
 212    NOP = 0,
 213    WRSR = 0x1,
 214    WRDI = 0x4,
 215    RDSR = 0x5,
 216    WREN = 0x6,
 217    JEDEC_READ = 0x9f,
 218    BULK_ERASE = 0xc7,
 219
 220    READ = 0x3,
 221    FAST_READ = 0xb,
 222    DOR = 0x3b,
 223    QOR = 0x6b,
 224    DIOR = 0xbb,
 225    QIOR = 0xeb,
 226
 227    PP = 0x2,
 228    DPP = 0xa2,
 229    QPP = 0x32,
 230
 231    ERASE_4K = 0x20,
 232    ERASE_32K = 0x52,
 233    ERASE_SECTOR = 0xd8,
 234} FlashCMD;
 235
 236typedef enum {
 237    STATE_IDLE,
 238    STATE_PAGE_PROGRAM,
 239    STATE_READ,
 240    STATE_COLLECTING_DATA,
 241    STATE_READING_DATA,
 242} CMDState;
 243
 244typedef struct Flash {
 245    SSISlave parent_obj;
 246
 247    uint32_t r;
 248
 249    BlockBackend *blk;
 250
 251    uint8_t *storage;
 252    uint32_t size;
 253    int page_size;
 254
 255    uint8_t state;
 256    uint8_t data[16];
 257    uint32_t len;
 258    uint32_t pos;
 259    uint8_t needed_bytes;
 260    uint8_t cmd_in_progress;
 261    uint64_t cur_addr;
 262    bool write_enable;
 263
 264    int64_t dirty_page;
 265
 266    const FlashPartInfo *pi;
 267
 268} Flash;
 269
 270typedef struct M25P80Class {
 271    SSISlaveClass parent_class;
 272    FlashPartInfo *pi;
 273} M25P80Class;
 274
 275#define TYPE_M25P80 "m25p80-generic"
 276#define M25P80(obj) \
 277     OBJECT_CHECK(Flash, (obj), TYPE_M25P80)
 278#define M25P80_CLASS(klass) \
 279     OBJECT_CLASS_CHECK(M25P80Class, (klass), TYPE_M25P80)
 280#define M25P80_GET_CLASS(obj) \
 281     OBJECT_GET_CLASS(M25P80Class, (obj), TYPE_M25P80)
 282
 283static void blk_sync_complete(void *opaque, int ret)
 284{
 285    /* do nothing. Masters do not directly interact with the backing store,
 286     * only the working copy so no mutexing required.
 287     */
 288}
 289
 290static void flash_sync_page(Flash *s, int page)
 291{
 292    int blk_sector, nb_sectors;
 293    QEMUIOVector iov;
 294
 295    if (!s->blk || blk_is_read_only(s->blk)) {
 296        return;
 297    }
 298
 299    blk_sector = (page * s->pi->page_size) / BDRV_SECTOR_SIZE;
 300    nb_sectors = DIV_ROUND_UP(s->pi->page_size, BDRV_SECTOR_SIZE);
 301    qemu_iovec_init(&iov, 1);
 302    qemu_iovec_add(&iov, s->storage + blk_sector * BDRV_SECTOR_SIZE,
 303                   nb_sectors * BDRV_SECTOR_SIZE);
 304    blk_aio_writev(s->blk, blk_sector, &iov, nb_sectors, blk_sync_complete,
 305                   NULL);
 306}
 307
 308static inline void flash_sync_area(Flash *s, int64_t off, int64_t len)
 309{
 310    int64_t start, end, nb_sectors;
 311    QEMUIOVector iov;
 312
 313    if (!s->blk || blk_is_read_only(s->blk)) {
 314        return;
 315    }
 316
 317    assert(!(len % BDRV_SECTOR_SIZE));
 318    start = off / BDRV_SECTOR_SIZE;
 319    end = (off + len) / BDRV_SECTOR_SIZE;
 320    nb_sectors = end - start;
 321    qemu_iovec_init(&iov, 1);
 322    qemu_iovec_add(&iov, s->storage + (start * BDRV_SECTOR_SIZE),
 323                                        nb_sectors * BDRV_SECTOR_SIZE);
 324    blk_aio_writev(s->blk, start, &iov, nb_sectors, blk_sync_complete, NULL);
 325}
 326
 327static void flash_erase(Flash *s, int offset, FlashCMD cmd)
 328{
 329    uint32_t len;
 330    uint8_t capa_to_assert = 0;
 331
 332    switch (cmd) {
 333    case ERASE_4K:
 334        len = 4 << 10;
 335        capa_to_assert = ER_4K;
 336        break;
 337    case ERASE_32K:
 338        len = 32 << 10;
 339        capa_to_assert = ER_32K;
 340        break;
 341    case ERASE_SECTOR:
 342        len = s->pi->sector_size;
 343        break;
 344    case BULK_ERASE:
 345        len = s->size;
 346        break;
 347    default:
 348        abort();
 349    }
 350
 351    DB_PRINT_L(0, "offset = %#x, len = %d\n", offset, len);
 352    if ((s->pi->flags & capa_to_assert) != capa_to_assert) {
 353        qemu_log_mask(LOG_GUEST_ERROR, "M25P80: %d erase size not supported by"
 354                      " device\n", len);
 355    }
 356
 357    if (!s->write_enable) {
 358        qemu_log_mask(LOG_GUEST_ERROR, "M25P80: erase with write protect!\n");
 359        return;
 360    }
 361    memset(s->storage + offset, 0xff, len);
 362    flash_sync_area(s, offset, len);
 363}
 364
 365static inline void flash_sync_dirty(Flash *s, int64_t newpage)
 366{
 367    if (s->dirty_page >= 0 && s->dirty_page != newpage) {
 368        flash_sync_page(s, s->dirty_page);
 369        s->dirty_page = newpage;
 370    }
 371}
 372
 373static inline
 374void flash_write8(Flash *s, uint64_t addr, uint8_t data)
 375{
 376    int64_t page = addr / s->pi->page_size;
 377    uint8_t prev = s->storage[s->cur_addr];
 378
 379    if (!s->write_enable) {
 380        qemu_log_mask(LOG_GUEST_ERROR, "M25P80: write with write protect!\n");
 381    }
 382
 383    if ((prev ^ data) & data) {
 384        DB_PRINT_L(1, "programming zero to one! addr=%" PRIx64 "  %" PRIx8
 385                   " -> %" PRIx8 "\n", addr, prev, data);
 386    }
 387
 388    if (s->pi->flags & WR_1) {
 389        s->storage[s->cur_addr] = data;
 390    } else {
 391        s->storage[s->cur_addr] &= data;
 392    }
 393
 394    flash_sync_dirty(s, page);
 395    s->dirty_page = page;
 396}
 397
 398static void complete_collecting_data(Flash *s)
 399{
 400    s->cur_addr = s->data[0] << 16;
 401    s->cur_addr |= s->data[1] << 8;
 402    s->cur_addr |= s->data[2];
 403
 404    s->state = STATE_IDLE;
 405
 406    switch (s->cmd_in_progress) {
 407    case DPP:
 408    case QPP:
 409    case PP:
 410        s->state = STATE_PAGE_PROGRAM;
 411        break;
 412    case READ:
 413    case FAST_READ:
 414    case DOR:
 415    case QOR:
 416    case DIOR:
 417    case QIOR:
 418        s->state = STATE_READ;
 419        break;
 420    case ERASE_4K:
 421    case ERASE_32K:
 422    case ERASE_SECTOR:
 423        flash_erase(s, s->cur_addr, s->cmd_in_progress);
 424        break;
 425    case WRSR:
 426        if (s->write_enable) {
 427            s->write_enable = false;
 428        }
 429        break;
 430    default:
 431        break;
 432    }
 433}
 434
 435static void decode_new_cmd(Flash *s, uint32_t value)
 436{
 437    s->cmd_in_progress = value;
 438    DB_PRINT_L(0, "decoded new command:%x\n", value);
 439
 440    switch (value) {
 441
 442    case ERASE_4K:
 443    case ERASE_32K:
 444    case ERASE_SECTOR:
 445    case READ:
 446    case DPP:
 447    case QPP:
 448    case PP:
 449        s->needed_bytes = 3;
 450        s->pos = 0;
 451        s->len = 0;
 452        s->state = STATE_COLLECTING_DATA;
 453        break;
 454
 455    case FAST_READ:
 456    case DOR:
 457    case QOR:
 458        s->needed_bytes = 4;
 459        s->pos = 0;
 460        s->len = 0;
 461        s->state = STATE_COLLECTING_DATA;
 462        break;
 463
 464    case DIOR:
 465        switch ((s->pi->jedec >> 16) & 0xFF) {
 466        case JEDEC_WINBOND:
 467        case JEDEC_SPANSION:
 468            s->needed_bytes = 4;
 469            break;
 470        case JEDEC_NUMONYX:
 471        default:
 472            s->needed_bytes = 5;
 473        }
 474        s->pos = 0;
 475        s->len = 0;
 476        s->state = STATE_COLLECTING_DATA;
 477        break;
 478
 479    case QIOR:
 480        switch ((s->pi->jedec >> 16) & 0xFF) {
 481        case JEDEC_WINBOND:
 482        case JEDEC_SPANSION:
 483            s->needed_bytes = 6;
 484            break;
 485        case JEDEC_NUMONYX:
 486        default:
 487            s->needed_bytes = 8;
 488        }
 489        s->pos = 0;
 490        s->len = 0;
 491        s->state = STATE_COLLECTING_DATA;
 492        break;
 493
 494    case WRSR:
 495        if (s->write_enable) {
 496            s->needed_bytes = 1;
 497            s->pos = 0;
 498            s->len = 0;
 499            s->state = STATE_COLLECTING_DATA;
 500        }
 501        break;
 502
 503    case WRDI:
 504        s->write_enable = false;
 505        break;
 506    case WREN:
 507        s->write_enable = true;
 508        break;
 509
 510    case RDSR:
 511        s->data[0] = (!!s->write_enable) << 1;
 512        s->pos = 0;
 513        s->len = 1;
 514        s->state = STATE_READING_DATA;
 515        break;
 516
 517    case JEDEC_READ:
 518        DB_PRINT_L(0, "populated jedec code\n");
 519        s->data[0] = (s->pi->jedec >> 16) & 0xff;
 520        s->data[1] = (s->pi->jedec >> 8) & 0xff;
 521        s->data[2] = s->pi->jedec & 0xff;
 522        if (s->pi->ext_jedec) {
 523            s->data[3] = (s->pi->ext_jedec >> 8) & 0xff;
 524            s->data[4] = s->pi->ext_jedec & 0xff;
 525            s->len = 5;
 526        } else {
 527            s->len = 3;
 528        }
 529        s->pos = 0;
 530        s->state = STATE_READING_DATA;
 531        break;
 532
 533    case BULK_ERASE:
 534        if (s->write_enable) {
 535            DB_PRINT_L(0, "chip erase\n");
 536            flash_erase(s, 0, BULK_ERASE);
 537        } else {
 538            qemu_log_mask(LOG_GUEST_ERROR, "M25P80: chip erase with write "
 539                          "protect!\n");
 540        }
 541        break;
 542    case NOP:
 543        break;
 544    default:
 545        qemu_log_mask(LOG_GUEST_ERROR, "M25P80: Unknown cmd %x\n", value);
 546        break;
 547    }
 548}
 549
 550static int m25p80_cs(SSISlave *ss, bool select)
 551{
 552    Flash *s = M25P80(ss);
 553
 554    if (select) {
 555        s->len = 0;
 556        s->pos = 0;
 557        s->state = STATE_IDLE;
 558        flash_sync_dirty(s, -1);
 559    }
 560
 561    DB_PRINT_L(0, "%sselect\n", select ? "de" : "");
 562
 563    return 0;
 564}
 565
 566static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx)
 567{
 568    Flash *s = M25P80(ss);
 569    uint32_t r = 0;
 570
 571    switch (s->state) {
 572
 573    case STATE_PAGE_PROGRAM:
 574        DB_PRINT_L(1, "page program cur_addr=%#" PRIx64 " data=%" PRIx8 "\n",
 575                   s->cur_addr, (uint8_t)tx);
 576        flash_write8(s, s->cur_addr, (uint8_t)tx);
 577        s->cur_addr++;
 578        break;
 579
 580    case STATE_READ:
 581        r = s->storage[s->cur_addr];
 582        DB_PRINT_L(1, "READ 0x%" PRIx64 "=%" PRIx8 "\n", s->cur_addr,
 583                   (uint8_t)r);
 584        s->cur_addr = (s->cur_addr + 1) % s->size;
 585        break;
 586
 587    case STATE_COLLECTING_DATA:
 588        s->data[s->len] = (uint8_t)tx;
 589        s->len++;
 590
 591        if (s->len == s->needed_bytes) {
 592            complete_collecting_data(s);
 593        }
 594        break;
 595
 596    case STATE_READING_DATA:
 597        r = s->data[s->pos];
 598        s->pos++;
 599        if (s->pos == s->len) {
 600            s->pos = 0;
 601            s->state = STATE_IDLE;
 602        }
 603        break;
 604
 605    default:
 606    case STATE_IDLE:
 607        decode_new_cmd(s, (uint8_t)tx);
 608        break;
 609    }
 610
 611    return r;
 612}
 613
 614static int m25p80_init(SSISlave *ss)
 615{
 616    DriveInfo *dinfo;
 617    Flash *s = M25P80(ss);
 618    M25P80Class *mc = M25P80_GET_CLASS(s);
 619
 620    s->pi = mc->pi;
 621
 622    s->size = s->pi->sector_size * s->pi->n_sectors;
 623    s->dirty_page = -1;
 624
 625    /* FIXME use a qdev drive property instead of drive_get_next() */
 626    dinfo = drive_get_next(IF_MTD);
 627
 628    if (dinfo) {
 629        DB_PRINT_L(0, "Binding to IF_MTD drive\n");
 630        s->blk = blk_by_legacy_dinfo(dinfo);
 631        blk_attach_dev_nofail(s->blk, s);
 632
 633        s->storage = blk_blockalign(s->blk, s->size);
 634
 635        /* FIXME: Move to late init */
 636        if (blk_read(s->blk, 0, s->storage,
 637                     DIV_ROUND_UP(s->size, BDRV_SECTOR_SIZE))) {
 638            fprintf(stderr, "Failed to initialize SPI flash!\n");
 639            return 1;
 640        }
 641    } else {
 642        DB_PRINT_L(0, "No BDRV - binding to RAM\n");
 643        s->storage = blk_blockalign(NULL, s->size);
 644        memset(s->storage, 0xFF, s->size);
 645    }
 646
 647    return 0;
 648}
 649
 650static void m25p80_pre_save(void *opaque)
 651{
 652    flash_sync_dirty((Flash *)opaque, -1);
 653}
 654
 655static const VMStateDescription vmstate_m25p80 = {
 656    .name = "xilinx_spi",
 657    .version_id = 1,
 658    .minimum_version_id = 1,
 659    .pre_save = m25p80_pre_save,
 660    .fields = (VMStateField[]) {
 661        VMSTATE_UINT8(state, Flash),
 662        VMSTATE_UINT8_ARRAY(data, Flash, 16),
 663        VMSTATE_UINT32(len, Flash),
 664        VMSTATE_UINT32(pos, Flash),
 665        VMSTATE_UINT8(needed_bytes, Flash),
 666        VMSTATE_UINT8(cmd_in_progress, Flash),
 667        VMSTATE_UINT64(cur_addr, Flash),
 668        VMSTATE_BOOL(write_enable, Flash),
 669        VMSTATE_END_OF_LIST()
 670    }
 671};
 672
 673static void m25p80_class_init(ObjectClass *klass, void *data)
 674{
 675    DeviceClass *dc = DEVICE_CLASS(klass);
 676    SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
 677    M25P80Class *mc = M25P80_CLASS(klass);
 678
 679    k->init = m25p80_init;
 680    k->transfer = m25p80_transfer8;
 681    k->set_cs = m25p80_cs;
 682    k->cs_polarity = SSI_CS_LOW;
 683    dc->vmsd = &vmstate_m25p80;
 684    mc->pi = data;
 685}
 686
 687static const TypeInfo m25p80_info = {
 688    .name           = TYPE_M25P80,
 689    .parent         = TYPE_SSI_SLAVE,
 690    .instance_size  = sizeof(Flash),
 691    .class_size     = sizeof(M25P80Class),
 692    .abstract       = true,
 693};
 694
 695static void m25p80_register_types(void)
 696{
 697    int i;
 698
 699    type_register_static(&m25p80_info);
 700    for (i = 0; i < ARRAY_SIZE(known_devices); ++i) {
 701        TypeInfo ti = {
 702            .name       = known_devices[i].part_name,
 703            .parent     = TYPE_M25P80,
 704            .class_init = m25p80_class_init,
 705            .class_data = (void *)&known_devices[i],
 706        };
 707        type_register(&ti);
 708    }
 709}
 710
 711type_init(m25p80_register_types)
 712