1 /* 2 * CFI parallel flash with AMD command set emulation 3 * 4 * Copyright (c) 2005 Jocelyn Mayer 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 /* 21 * For now, this code can emulate flashes of 1, 2 or 4 bytes width. 22 * Supported commands/modes are: 23 * - flash read 24 * - flash write 25 * - flash ID read 26 * - sector erase 27 * - chip erase 28 * - unlock bypass command 29 * - CFI queries 30 * 31 * It does not support flash interleaving. 32 * It does not implement boot blocs with reduced size 33 * It does not implement software data protection as found in many real chips 34 * It does not implement erase suspend/resume commands 35 * It does not implement multiple sectors erase 36 */ 37 38 #include "qemu/osdep.h" 39 #include "hw/hw.h" 40 #include "hw/block/block.h" 41 #include "hw/block/flash.h" 42 #include "qapi/error.h" 43 #include "qemu/timer.h" 44 #include "sysemu/block-backend.h" 45 #include "qemu/host-utils.h" 46 #include "hw/sysbus.h" 47 #include "trace.h" 48 49 //#define PFLASH_DEBUG 50 #ifdef PFLASH_DEBUG 51 #define DPRINTF(fmt, ...) \ 52 do { \ 53 fprintf(stderr, "PFLASH: " fmt , ## __VA_ARGS__); \ 54 } while (0) 55 #else 56 #define DPRINTF(fmt, ...) do { } while (0) 57 #endif 58 59 #define PFLASH_LAZY_ROMD_THRESHOLD 42 60 61 struct PFlashCFI02 { 62 /*< private >*/ 63 SysBusDevice parent_obj; 64 /*< public >*/ 65 66 BlockBackend *blk; 67 uint32_t sector_len; 68 uint32_t nb_blocs; 69 uint32_t chip_len; 70 uint8_t mappings; 71 uint8_t width; 72 uint8_t be; 73 int wcycle; /* if 0, the flash is read normally */ 74 int bypass; 75 int ro; 76 uint8_t cmd; 77 uint8_t status; 78 /* FIXME: implement array device properties */ 79 uint16_t ident0; 80 uint16_t ident1; 81 uint16_t ident2; 82 uint16_t ident3; 83 uint16_t unlock_addr0; 84 uint16_t unlock_addr1; 85 uint8_t cfi_table[0x52]; 86 QEMUTimer timer; 87 /* The device replicates the flash memory across its memory space. Emulate 88 * that by having a container (.mem) filled with an array of aliases 89 * (.mem_mappings) pointing to the flash memory (.orig_mem). 90 */ 91 MemoryRegion mem; 92 MemoryRegion *mem_mappings; /* array; one per mapping */ 93 MemoryRegion orig_mem; 94 int rom_mode; 95 int read_counter; /* used for lazy switch-back to rom mode */ 96 char *name; 97 void *storage; 98 }; 99 100 /* 101 * Set up replicated mappings of the same region. 102 */ 103 static void pflash_setup_mappings(PFlashCFI02 *pfl) 104 { 105 unsigned i; 106 hwaddr size = memory_region_size(&pfl->orig_mem); 107 108 memory_region_init(&pfl->mem, OBJECT(pfl), "pflash", pfl->mappings * size); 109 pfl->mem_mappings = g_new(MemoryRegion, pfl->mappings); 110 for (i = 0; i < pfl->mappings; ++i) { 111 memory_region_init_alias(&pfl->mem_mappings[i], OBJECT(pfl), 112 "pflash-alias", &pfl->orig_mem, 0, size); 113 memory_region_add_subregion(&pfl->mem, i * size, &pfl->mem_mappings[i]); 114 } 115 } 116 117 static void pflash_register_memory(PFlashCFI02 *pfl, int rom_mode) 118 { 119 memory_region_rom_device_set_romd(&pfl->orig_mem, rom_mode); 120 pfl->rom_mode = rom_mode; 121 } 122 123 static void pflash_timer (void *opaque) 124 { 125 PFlashCFI02 *pfl = opaque; 126 127 trace_pflash_timer_expired(pfl->cmd); 128 /* Reset flash */ 129 pfl->status ^= 0x80; 130 if (pfl->bypass) { 131 pfl->wcycle = 2; 132 } else { 133 pflash_register_memory(pfl, 1); 134 pfl->wcycle = 0; 135 } 136 pfl->cmd = 0; 137 } 138 139 static uint32_t pflash_read(PFlashCFI02 *pfl, hwaddr offset, 140 int width, int be) 141 { 142 hwaddr boff; 143 uint32_t ret; 144 uint8_t *p; 145 146 ret = -1; 147 trace_pflash_read(offset, pfl->cmd, width, pfl->wcycle); 148 /* Lazy reset to ROMD mode after a certain amount of read accesses */ 149 if (!pfl->rom_mode && pfl->wcycle == 0 && 150 ++pfl->read_counter > PFLASH_LAZY_ROMD_THRESHOLD) { 151 pflash_register_memory(pfl, 1); 152 } 153 offset &= pfl->chip_len - 1; 154 boff = offset & 0xFF; 155 if (pfl->width == 2) 156 boff = boff >> 1; 157 else if (pfl->width == 4) 158 boff = boff >> 2; 159 switch (pfl->cmd) { 160 default: 161 /* This should never happen : reset state & treat it as a read*/ 162 DPRINTF("%s: unknown command state: %x\n", __func__, pfl->cmd); 163 pfl->wcycle = 0; 164 pfl->cmd = 0; 165 /* fall through to the read code */ 166 case 0x80: 167 /* We accept reads during second unlock sequence... */ 168 case 0x00: 169 flash_read: 170 /* Flash area read */ 171 p = pfl->storage; 172 switch (width) { 173 case 1: 174 ret = p[offset]; 175 trace_pflash_data_read8(offset, ret); 176 break; 177 case 2: 178 if (be) { 179 ret = p[offset] << 8; 180 ret |= p[offset + 1]; 181 } else { 182 ret = p[offset]; 183 ret |= p[offset + 1] << 8; 184 } 185 trace_pflash_data_read16(offset, ret); 186 break; 187 case 4: 188 if (be) { 189 ret = p[offset] << 24; 190 ret |= p[offset + 1] << 16; 191 ret |= p[offset + 2] << 8; 192 ret |= p[offset + 3]; 193 } else { 194 ret = p[offset]; 195 ret |= p[offset + 1] << 8; 196 ret |= p[offset + 2] << 16; 197 ret |= p[offset + 3] << 24; 198 } 199 trace_pflash_data_read32(offset, ret); 200 break; 201 } 202 break; 203 case 0x90: 204 /* flash ID read */ 205 switch (boff) { 206 case 0x00: 207 case 0x01: 208 ret = boff & 0x01 ? pfl->ident1 : pfl->ident0; 209 break; 210 case 0x02: 211 ret = 0x00; /* Pretend all sectors are unprotected */ 212 break; 213 case 0x0E: 214 case 0x0F: 215 ret = boff & 0x01 ? pfl->ident3 : pfl->ident2; 216 if (ret == (uint8_t)-1) { 217 goto flash_read; 218 } 219 break; 220 default: 221 goto flash_read; 222 } 223 DPRINTF("%s: ID " TARGET_FMT_plx " %x\n", __func__, boff, ret); 224 break; 225 case 0xA0: 226 case 0x10: 227 case 0x30: 228 /* Status register read */ 229 ret = pfl->status; 230 DPRINTF("%s: status %x\n", __func__, ret); 231 /* Toggle bit 6 */ 232 pfl->status ^= 0x40; 233 break; 234 case 0x98: 235 /* CFI query mode */ 236 if (boff < sizeof(pfl->cfi_table)) { 237 ret = pfl->cfi_table[boff]; 238 } else { 239 ret = 0; 240 } 241 break; 242 } 243 244 return ret; 245 } 246 247 /* update flash content on disk */ 248 static void pflash_update(PFlashCFI02 *pfl, int offset, 249 int size) 250 { 251 int offset_end; 252 if (pfl->blk) { 253 offset_end = offset + size; 254 /* widen to sector boundaries */ 255 offset = QEMU_ALIGN_DOWN(offset, BDRV_SECTOR_SIZE); 256 offset_end = QEMU_ALIGN_UP(offset_end, BDRV_SECTOR_SIZE); 257 blk_pwrite(pfl->blk, offset, pfl->storage + offset, 258 offset_end - offset, 0); 259 } 260 } 261 262 static void pflash_write(PFlashCFI02 *pfl, hwaddr offset, 263 uint32_t value, int width, int be) 264 { 265 hwaddr boff; 266 uint8_t *p; 267 uint8_t cmd; 268 269 cmd = value; 270 if (pfl->cmd != 0xA0 && cmd == 0xF0) { 271 #if 0 272 DPRINTF("%s: flash reset asked (%02x %02x)\n", 273 __func__, pfl->cmd, cmd); 274 #endif 275 goto reset_flash; 276 } 277 trace_pflash_write(offset, value, width, pfl->wcycle); 278 offset &= pfl->chip_len - 1; 279 280 DPRINTF("%s: offset " TARGET_FMT_plx " %08x %d\n", __func__, 281 offset, value, width); 282 boff = offset & (pfl->sector_len - 1); 283 if (pfl->width == 2) 284 boff = boff >> 1; 285 else if (pfl->width == 4) 286 boff = boff >> 2; 287 switch (pfl->wcycle) { 288 case 0: 289 /* Set the device in I/O access mode if required */ 290 if (pfl->rom_mode) 291 pflash_register_memory(pfl, 0); 292 pfl->read_counter = 0; 293 /* We're in read mode */ 294 check_unlock0: 295 if (boff == 0x55 && cmd == 0x98) { 296 enter_CFI_mode: 297 /* Enter CFI query mode */ 298 pfl->wcycle = 7; 299 pfl->cmd = 0x98; 300 return; 301 } 302 if (boff != pfl->unlock_addr0 || cmd != 0xAA) { 303 DPRINTF("%s: unlock0 failed " TARGET_FMT_plx " %02x %04x\n", 304 __func__, boff, cmd, pfl->unlock_addr0); 305 goto reset_flash; 306 } 307 DPRINTF("%s: unlock sequence started\n", __func__); 308 break; 309 case 1: 310 /* We started an unlock sequence */ 311 check_unlock1: 312 if (boff != pfl->unlock_addr1 || cmd != 0x55) { 313 DPRINTF("%s: unlock1 failed " TARGET_FMT_plx " %02x\n", __func__, 314 boff, cmd); 315 goto reset_flash; 316 } 317 DPRINTF("%s: unlock sequence done\n", __func__); 318 break; 319 case 2: 320 /* We finished an unlock sequence */ 321 if (!pfl->bypass && boff != pfl->unlock_addr0) { 322 DPRINTF("%s: command failed " TARGET_FMT_plx " %02x\n", __func__, 323 boff, cmd); 324 goto reset_flash; 325 } 326 switch (cmd) { 327 case 0x20: 328 pfl->bypass = 1; 329 goto do_bypass; 330 case 0x80: 331 case 0x90: 332 case 0xA0: 333 pfl->cmd = cmd; 334 DPRINTF("%s: starting command %02x\n", __func__, cmd); 335 break; 336 default: 337 DPRINTF("%s: unknown command %02x\n", __func__, cmd); 338 goto reset_flash; 339 } 340 break; 341 case 3: 342 switch (pfl->cmd) { 343 case 0x80: 344 /* We need another unlock sequence */ 345 goto check_unlock0; 346 case 0xA0: 347 trace_pflash_data_write(offset, value, width, 0); 348 p = pfl->storage; 349 if (!pfl->ro) { 350 switch (width) { 351 case 1: 352 p[offset] &= value; 353 pflash_update(pfl, offset, 1); 354 break; 355 case 2: 356 if (be) { 357 p[offset] &= value >> 8; 358 p[offset + 1] &= value; 359 } else { 360 p[offset] &= value; 361 p[offset + 1] &= value >> 8; 362 } 363 pflash_update(pfl, offset, 2); 364 break; 365 case 4: 366 if (be) { 367 p[offset] &= value >> 24; 368 p[offset + 1] &= value >> 16; 369 p[offset + 2] &= value >> 8; 370 p[offset + 3] &= value; 371 } else { 372 p[offset] &= value; 373 p[offset + 1] &= value >> 8; 374 p[offset + 2] &= value >> 16; 375 p[offset + 3] &= value >> 24; 376 } 377 pflash_update(pfl, offset, 4); 378 break; 379 } 380 } 381 pfl->status = 0x00 | ~(value & 0x80); 382 /* Let's pretend write is immediate */ 383 if (pfl->bypass) 384 goto do_bypass; 385 goto reset_flash; 386 case 0x90: 387 if (pfl->bypass && cmd == 0x00) { 388 /* Unlock bypass reset */ 389 goto reset_flash; 390 } 391 /* We can enter CFI query mode from autoselect mode */ 392 if (boff == 0x55 && cmd == 0x98) 393 goto enter_CFI_mode; 394 /* No break here */ 395 default: 396 DPRINTF("%s: invalid write for command %02x\n", 397 __func__, pfl->cmd); 398 goto reset_flash; 399 } 400 case 4: 401 switch (pfl->cmd) { 402 case 0xA0: 403 /* Ignore writes while flash data write is occurring */ 404 /* As we suppose write is immediate, this should never happen */ 405 return; 406 case 0x80: 407 goto check_unlock1; 408 default: 409 /* Should never happen */ 410 DPRINTF("%s: invalid command state %02x (wc 4)\n", 411 __func__, pfl->cmd); 412 goto reset_flash; 413 } 414 break; 415 case 5: 416 switch (cmd) { 417 case 0x10: 418 if (boff != pfl->unlock_addr0) { 419 DPRINTF("%s: chip erase: invalid address " TARGET_FMT_plx "\n", 420 __func__, offset); 421 goto reset_flash; 422 } 423 /* Chip erase */ 424 DPRINTF("%s: start chip erase\n", __func__); 425 if (!pfl->ro) { 426 memset(pfl->storage, 0xFF, pfl->chip_len); 427 pflash_update(pfl, 0, pfl->chip_len); 428 } 429 pfl->status = 0x00; 430 /* Let's wait 5 seconds before chip erase is done */ 431 timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 432 (NANOSECONDS_PER_SECOND * 5)); 433 break; 434 case 0x30: 435 /* Sector erase */ 436 p = pfl->storage; 437 offset &= ~(pfl->sector_len - 1); 438 DPRINTF("%s: start sector erase at " TARGET_FMT_plx "\n", __func__, 439 offset); 440 if (!pfl->ro) { 441 memset(p + offset, 0xFF, pfl->sector_len); 442 pflash_update(pfl, offset, pfl->sector_len); 443 } 444 pfl->status = 0x00; 445 /* Let's wait 1/2 second before sector erase is done */ 446 timer_mod(&pfl->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 447 (NANOSECONDS_PER_SECOND / 2)); 448 break; 449 default: 450 DPRINTF("%s: invalid command %02x (wc 5)\n", __func__, cmd); 451 goto reset_flash; 452 } 453 pfl->cmd = cmd; 454 break; 455 case 6: 456 switch (pfl->cmd) { 457 case 0x10: 458 /* Ignore writes during chip erase */ 459 return; 460 case 0x30: 461 /* Ignore writes during sector erase */ 462 return; 463 default: 464 /* Should never happen */ 465 DPRINTF("%s: invalid command state %02x (wc 6)\n", 466 __func__, pfl->cmd); 467 goto reset_flash; 468 } 469 break; 470 case 7: /* Special value for CFI queries */ 471 DPRINTF("%s: invalid write in CFI query mode\n", __func__); 472 goto reset_flash; 473 default: 474 /* Should never happen */ 475 DPRINTF("%s: invalid write state (wc 7)\n", __func__); 476 goto reset_flash; 477 } 478 pfl->wcycle++; 479 480 return; 481 482 /* Reset flash */ 483 reset_flash: 484 trace_pflash_reset(); 485 pfl->bypass = 0; 486 pfl->wcycle = 0; 487 pfl->cmd = 0; 488 return; 489 490 do_bypass: 491 pfl->wcycle = 2; 492 pfl->cmd = 0; 493 } 494 495 static uint64_t pflash_be_readfn(void *opaque, hwaddr addr, unsigned size) 496 { 497 return pflash_read(opaque, addr, size, 1); 498 } 499 500 static void pflash_be_writefn(void *opaque, hwaddr addr, 501 uint64_t value, unsigned size) 502 { 503 pflash_write(opaque, addr, value, size, 1); 504 } 505 506 static uint64_t pflash_le_readfn(void *opaque, hwaddr addr, unsigned size) 507 { 508 return pflash_read(opaque, addr, size, 0); 509 } 510 511 static void pflash_le_writefn(void *opaque, hwaddr addr, 512 uint64_t value, unsigned size) 513 { 514 pflash_write(opaque, addr, value, size, 0); 515 } 516 517 static const MemoryRegionOps pflash_cfi02_ops_be = { 518 .read = pflash_be_readfn, 519 .write = pflash_be_writefn, 520 .valid.min_access_size = 1, 521 .valid.max_access_size = 4, 522 .endianness = DEVICE_NATIVE_ENDIAN, 523 }; 524 525 static const MemoryRegionOps pflash_cfi02_ops_le = { 526 .read = pflash_le_readfn, 527 .write = pflash_le_writefn, 528 .valid.min_access_size = 1, 529 .valid.max_access_size = 4, 530 .endianness = DEVICE_NATIVE_ENDIAN, 531 }; 532 533 static void pflash_cfi02_realize(DeviceState *dev, Error **errp) 534 { 535 PFlashCFI02 *pfl = PFLASH_CFI02(dev); 536 uint32_t chip_len; 537 int ret; 538 Error *local_err = NULL; 539 540 if (pfl->sector_len == 0) { 541 error_setg(errp, "attribute \"sector-length\" not specified or zero."); 542 return; 543 } 544 if (pfl->nb_blocs == 0) { 545 error_setg(errp, "attribute \"num-blocks\" not specified or zero."); 546 return; 547 } 548 if (pfl->name == NULL) { 549 error_setg(errp, "attribute \"name\" not specified."); 550 return; 551 } 552 553 chip_len = pfl->sector_len * pfl->nb_blocs; 554 555 memory_region_init_rom_device(&pfl->orig_mem, OBJECT(pfl), pfl->be ? 556 &pflash_cfi02_ops_be : &pflash_cfi02_ops_le, 557 pfl, pfl->name, chip_len, &local_err); 558 if (local_err) { 559 error_propagate(errp, local_err); 560 return; 561 } 562 563 pfl->storage = memory_region_get_ram_ptr(&pfl->orig_mem); 564 pfl->chip_len = chip_len; 565 566 if (pfl->blk) { 567 uint64_t perm; 568 pfl->ro = blk_is_read_only(pfl->blk); 569 perm = BLK_PERM_CONSISTENT_READ | (pfl->ro ? 0 : BLK_PERM_WRITE); 570 ret = blk_set_perm(pfl->blk, perm, BLK_PERM_ALL, errp); 571 if (ret < 0) { 572 return; 573 } 574 } else { 575 pfl->ro = 0; 576 } 577 578 if (pfl->blk) { 579 if (!blk_check_size_and_read_all(pfl->blk, pfl->storage, chip_len, 580 errp)) { 581 vmstate_unregister_ram(&pfl->orig_mem, DEVICE(pfl)); 582 return; 583 } 584 } 585 586 pflash_setup_mappings(pfl); 587 pfl->rom_mode = 1; 588 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem); 589 590 timer_init_ns(&pfl->timer, QEMU_CLOCK_VIRTUAL, pflash_timer, pfl); 591 pfl->wcycle = 0; 592 pfl->cmd = 0; 593 pfl->status = 0; 594 /* Hardcoded CFI table (mostly from SG29 Spansion flash) */ 595 /* Standard "QRY" string */ 596 pfl->cfi_table[0x10] = 'Q'; 597 pfl->cfi_table[0x11] = 'R'; 598 pfl->cfi_table[0x12] = 'Y'; 599 /* Command set (AMD/Fujitsu) */ 600 pfl->cfi_table[0x13] = 0x02; 601 pfl->cfi_table[0x14] = 0x00; 602 /* Primary extended table address */ 603 pfl->cfi_table[0x15] = 0x31; 604 pfl->cfi_table[0x16] = 0x00; 605 /* Alternate command set (none) */ 606 pfl->cfi_table[0x17] = 0x00; 607 pfl->cfi_table[0x18] = 0x00; 608 /* Alternate extended table (none) */ 609 pfl->cfi_table[0x19] = 0x00; 610 pfl->cfi_table[0x1A] = 0x00; 611 /* Vcc min */ 612 pfl->cfi_table[0x1B] = 0x27; 613 /* Vcc max */ 614 pfl->cfi_table[0x1C] = 0x36; 615 /* Vpp min (no Vpp pin) */ 616 pfl->cfi_table[0x1D] = 0x00; 617 /* Vpp max (no Vpp pin) */ 618 pfl->cfi_table[0x1E] = 0x00; 619 /* Reserved */ 620 pfl->cfi_table[0x1F] = 0x07; 621 /* Timeout for min size buffer write (NA) */ 622 pfl->cfi_table[0x20] = 0x00; 623 /* Typical timeout for block erase (512 ms) */ 624 pfl->cfi_table[0x21] = 0x09; 625 /* Typical timeout for full chip erase (4096 ms) */ 626 pfl->cfi_table[0x22] = 0x0C; 627 /* Reserved */ 628 pfl->cfi_table[0x23] = 0x01; 629 /* Max timeout for buffer write (NA) */ 630 pfl->cfi_table[0x24] = 0x00; 631 /* Max timeout for block erase */ 632 pfl->cfi_table[0x25] = 0x0A; 633 /* Max timeout for chip erase */ 634 pfl->cfi_table[0x26] = 0x0D; 635 /* Device size */ 636 pfl->cfi_table[0x27] = ctz32(chip_len); 637 /* Flash device interface (8 & 16 bits) */ 638 pfl->cfi_table[0x28] = 0x02; 639 pfl->cfi_table[0x29] = 0x00; 640 /* Max number of bytes in multi-bytes write */ 641 /* XXX: disable buffered write as it's not supported */ 642 // pfl->cfi_table[0x2A] = 0x05; 643 pfl->cfi_table[0x2A] = 0x00; 644 pfl->cfi_table[0x2B] = 0x00; 645 /* Number of erase block regions (uniform) */ 646 pfl->cfi_table[0x2C] = 0x01; 647 /* Erase block region 1 */ 648 pfl->cfi_table[0x2D] = pfl->nb_blocs - 1; 649 pfl->cfi_table[0x2E] = (pfl->nb_blocs - 1) >> 8; 650 pfl->cfi_table[0x2F] = pfl->sector_len >> 8; 651 pfl->cfi_table[0x30] = pfl->sector_len >> 16; 652 653 /* Extended */ 654 pfl->cfi_table[0x31] = 'P'; 655 pfl->cfi_table[0x32] = 'R'; 656 pfl->cfi_table[0x33] = 'I'; 657 658 pfl->cfi_table[0x34] = '1'; 659 pfl->cfi_table[0x35] = '0'; 660 661 pfl->cfi_table[0x36] = 0x00; 662 pfl->cfi_table[0x37] = 0x00; 663 pfl->cfi_table[0x38] = 0x00; 664 pfl->cfi_table[0x39] = 0x00; 665 666 pfl->cfi_table[0x3a] = 0x00; 667 668 pfl->cfi_table[0x3b] = 0x00; 669 pfl->cfi_table[0x3c] = 0x00; 670 } 671 672 static Property pflash_cfi02_properties[] = { 673 DEFINE_PROP_DRIVE("drive", PFlashCFI02, blk), 674 DEFINE_PROP_UINT32("num-blocks", PFlashCFI02, nb_blocs, 0), 675 DEFINE_PROP_UINT32("sector-length", PFlashCFI02, sector_len, 0), 676 DEFINE_PROP_UINT8("width", PFlashCFI02, width, 0), 677 DEFINE_PROP_UINT8("mappings", PFlashCFI02, mappings, 0), 678 DEFINE_PROP_UINT8("big-endian", PFlashCFI02, be, 0), 679 DEFINE_PROP_UINT16("id0", PFlashCFI02, ident0, 0), 680 DEFINE_PROP_UINT16("id1", PFlashCFI02, ident1, 0), 681 DEFINE_PROP_UINT16("id2", PFlashCFI02, ident2, 0), 682 DEFINE_PROP_UINT16("id3", PFlashCFI02, ident3, 0), 683 DEFINE_PROP_UINT16("unlock-addr0", PFlashCFI02, unlock_addr0, 0), 684 DEFINE_PROP_UINT16("unlock-addr1", PFlashCFI02, unlock_addr1, 0), 685 DEFINE_PROP_STRING("name", PFlashCFI02, name), 686 DEFINE_PROP_END_OF_LIST(), 687 }; 688 689 static void pflash_cfi02_unrealize(DeviceState *dev, Error **errp) 690 { 691 PFlashCFI02 *pfl = PFLASH_CFI02(dev); 692 timer_del(&pfl->timer); 693 } 694 695 static void pflash_cfi02_class_init(ObjectClass *klass, void *data) 696 { 697 DeviceClass *dc = DEVICE_CLASS(klass); 698 699 dc->realize = pflash_cfi02_realize; 700 dc->unrealize = pflash_cfi02_unrealize; 701 dc->props = pflash_cfi02_properties; 702 set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 703 } 704 705 static const TypeInfo pflash_cfi02_info = { 706 .name = TYPE_PFLASH_CFI02, 707 .parent = TYPE_SYS_BUS_DEVICE, 708 .instance_size = sizeof(PFlashCFI02), 709 .class_init = pflash_cfi02_class_init, 710 }; 711 712 static void pflash_cfi02_register_types(void) 713 { 714 type_register_static(&pflash_cfi02_info); 715 } 716 717 type_init(pflash_cfi02_register_types) 718 719 PFlashCFI02 *pflash_cfi02_register(hwaddr base, 720 const char *name, 721 hwaddr size, 722 BlockBackend *blk, 723 uint32_t sector_len, 724 int nb_mappings, int width, 725 uint16_t id0, uint16_t id1, 726 uint16_t id2, uint16_t id3, 727 uint16_t unlock_addr0, 728 uint16_t unlock_addr1, 729 int be) 730 { 731 DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI02); 732 733 if (blk) { 734 qdev_prop_set_drive(dev, "drive", blk, &error_abort); 735 } 736 assert(size % sector_len == 0); 737 qdev_prop_set_uint32(dev, "num-blocks", size / sector_len); 738 qdev_prop_set_uint32(dev, "sector-length", sector_len); 739 qdev_prop_set_uint8(dev, "width", width); 740 qdev_prop_set_uint8(dev, "mappings", nb_mappings); 741 qdev_prop_set_uint8(dev, "big-endian", !!be); 742 qdev_prop_set_uint16(dev, "id0", id0); 743 qdev_prop_set_uint16(dev, "id1", id1); 744 qdev_prop_set_uint16(dev, "id2", id2); 745 qdev_prop_set_uint16(dev, "id3", id3); 746 qdev_prop_set_uint16(dev, "unlock-addr0", unlock_addr0); 747 qdev_prop_set_uint16(dev, "unlock-addr1", unlock_addr1); 748 qdev_prop_set_string(dev, "name", name); 749 qdev_init_nofail(dev); 750 751 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); 752 return PFLASH_CFI02(dev); 753 } 754