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