Commit 4fbd24ba35ce80b23253002116d5a90df6d25b2c
1 parent
6725070d
Emulate address wrap in CFI02 chips mapping (Jan Kiszka).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4219 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
39 additions
and
25 deletions
hw/flash.h
| ... | ... | @@ -11,7 +11,7 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base, ram_addr_t off, |
| 11 | 11 | /* pflash_cfi02.c */ |
| 12 | 12 | pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off, |
| 13 | 13 | BlockDriverState *bs, uint32_t sector_len, |
| 14 | - int nb_blocs, int width, | |
| 14 | + int nb_blocs, int nb_mappings, int width, | |
| 15 | 15 | uint16_t id0, uint16_t id1, |
| 16 | 16 | uint16_t id2, uint16_t id3, |
| 17 | 17 | uint16_t unlock_addr0, uint16_t unlock_addr1); | ... | ... |
hw/pflash_cfi02.c
| ... | ... | @@ -55,7 +55,8 @@ struct pflash_t { |
| 55 | 55 | BlockDriverState *bs; |
| 56 | 56 | target_phys_addr_t base; |
| 57 | 57 | uint32_t sector_len; |
| 58 | - uint32_t total_len; | |
| 58 | + uint32_t chip_len; | |
| 59 | + int mappings; | |
| 59 | 60 | int width; |
| 60 | 61 | int wcycle; /* if 0, the flash is read normally */ |
| 61 | 62 | int bypass; |
| ... | ... | @@ -72,6 +73,19 @@ struct pflash_t { |
| 72 | 73 | void *storage; |
| 73 | 74 | }; |
| 74 | 75 | |
| 76 | +static void pflash_register_memory(pflash_t *pfl, int rom_mode) | |
| 77 | +{ | |
| 78 | + unsigned long phys_offset = pfl->fl_mem; | |
| 79 | + int i; | |
| 80 | + | |
| 81 | + if (rom_mode) | |
| 82 | + phys_offset |= pfl->off | IO_MEM_ROMD; | |
| 83 | + | |
| 84 | + for (i = 0; i < pfl->mappings; i++) | |
| 85 | + cpu_register_physical_memory(pfl->base + i * pfl->chip_len, | |
| 86 | + pfl->chip_len, phys_offset); | |
| 87 | +} | |
| 88 | + | |
| 75 | 89 | static void pflash_timer (void *opaque) |
| 76 | 90 | { |
| 77 | 91 | pflash_t *pfl = opaque; |
| ... | ... | @@ -82,8 +96,7 @@ static void pflash_timer (void *opaque) |
| 82 | 96 | if (pfl->bypass) { |
| 83 | 97 | pfl->wcycle = 2; |
| 84 | 98 | } else { |
| 85 | - cpu_register_physical_memory(pfl->base, pfl->total_len, | |
| 86 | - pfl->off | IO_MEM_ROMD | pfl->fl_mem); | |
| 99 | + pflash_register_memory(pfl, 1); | |
| 87 | 100 | pfl->wcycle = 0; |
| 88 | 101 | } |
| 89 | 102 | pfl->cmd = 0; |
| ... | ... | @@ -98,6 +111,7 @@ static uint32_t pflash_read (pflash_t *pfl, uint32_t offset, int width) |
| 98 | 111 | DPRINTF("%s: offset " TARGET_FMT_lx "\n", __func__, offset); |
| 99 | 112 | ret = -1; |
| 100 | 113 | offset -= pfl->base; |
| 114 | + offset &= pfl->chip_len - 1; | |
| 101 | 115 | boff = offset & 0xFF; |
| 102 | 116 | if (pfl->width == 2) |
| 103 | 117 | boff = boff >> 1; |
| ... | ... | @@ -226,11 +240,10 @@ static void pflash_write (pflash_t *pfl, uint32_t offset, uint32_t value, |
| 226 | 240 | offset -= (uint32_t)(long)pfl->storage; |
| 227 | 241 | else |
| 228 | 242 | offset -= pfl->base; |
| 243 | + offset &= pfl->chip_len - 1; | |
| 229 | 244 | |
| 230 | 245 | DPRINTF("%s: offset " TARGET_FMT_lx " %08x %d\n", __func__, |
| 231 | 246 | offset, value, width); |
| 232 | - /* Set the device in I/O access mode */ | |
| 233 | - cpu_register_physical_memory(pfl->base, pfl->total_len, pfl->fl_mem); | |
| 234 | 247 | boff = offset & (pfl->sector_len - 1); |
| 235 | 248 | if (pfl->width == 2) |
| 236 | 249 | boff = boff >> 1; |
| ... | ... | @@ -238,6 +251,8 @@ static void pflash_write (pflash_t *pfl, uint32_t offset, uint32_t value, |
| 238 | 251 | boff = boff >> 2; |
| 239 | 252 | switch (pfl->wcycle) { |
| 240 | 253 | case 0: |
| 254 | + /* Set the device in I/O access mode */ | |
| 255 | + pflash_register_memory(pfl, 0); | |
| 241 | 256 | /* We're in read mode */ |
| 242 | 257 | check_unlock0: |
| 243 | 258 | if (boff == 0x55 && cmd == 0x98) { |
| ... | ... | @@ -369,9 +384,9 @@ static void pflash_write (pflash_t *pfl, uint32_t offset, uint32_t value, |
| 369 | 384 | } |
| 370 | 385 | /* Chip erase */ |
| 371 | 386 | DPRINTF("%s: start chip erase\n", __func__); |
| 372 | - memset(pfl->storage, 0xFF, pfl->total_len); | |
| 387 | + memset(pfl->storage, 0xFF, pfl->chip_len); | |
| 373 | 388 | pfl->status = 0x00; |
| 374 | - pflash_update(pfl, 0, pfl->total_len); | |
| 389 | + pflash_update(pfl, 0, pfl->chip_len); | |
| 375 | 390 | /* Let's wait 5 seconds before chip erase is done */ |
| 376 | 391 | qemu_mod_timer(pfl->timer, |
| 377 | 392 | qemu_get_clock(vm_clock) + (ticks_per_sec * 5)); |
| ... | ... | @@ -424,8 +439,7 @@ static void pflash_write (pflash_t *pfl, uint32_t offset, uint32_t value, |
| 424 | 439 | |
| 425 | 440 | /* Reset flash */ |
| 426 | 441 | reset_flash: |
| 427 | - cpu_register_physical_memory(pfl->base, pfl->total_len, | |
| 428 | - pfl->off | IO_MEM_ROMD | pfl->fl_mem); | |
| 442 | + pflash_register_memory(pfl, 1); | |
| 429 | 443 | pfl->bypass = 0; |
| 430 | 444 | pfl->wcycle = 0; |
| 431 | 445 | pfl->cmd = 0; |
| ... | ... | @@ -527,15 +541,15 @@ static int ctz32 (uint32_t n) |
| 527 | 541 | |
| 528 | 542 | pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off, |
| 529 | 543 | BlockDriverState *bs, uint32_t sector_len, |
| 530 | - int nb_blocs, int width, | |
| 544 | + int nb_blocs, int nb_mappings, int width, | |
| 531 | 545 | uint16_t id0, uint16_t id1, |
| 532 | 546 | uint16_t id2, uint16_t id3, |
| 533 | 547 | uint16_t unlock_addr0, uint16_t unlock_addr1) |
| 534 | 548 | { |
| 535 | 549 | pflash_t *pfl; |
| 536 | - int32_t total_len; | |
| 550 | + int32_t chip_len; | |
| 537 | 551 | |
| 538 | - total_len = sector_len * nb_blocs; | |
| 552 | + chip_len = sector_len * nb_blocs; | |
| 539 | 553 | /* XXX: to be fixed */ |
| 540 | 554 | #if 0 |
| 541 | 555 | if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) && |
| ... | ... | @@ -549,12 +563,14 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off, |
| 549 | 563 | pfl->fl_mem = cpu_register_io_memory(0, pflash_read_ops, pflash_write_ops, |
| 550 | 564 | pfl); |
| 551 | 565 | pfl->off = off; |
| 552 | - cpu_register_physical_memory(base, total_len, | |
| 553 | - off | pfl->fl_mem | IO_MEM_ROMD); | |
| 566 | + pfl->base = base; | |
| 567 | + pfl->chip_len = chip_len; | |
| 568 | + pfl->mappings = nb_mappings; | |
| 569 | + pflash_register_memory(pfl, 1); | |
| 554 | 570 | pfl->bs = bs; |
| 555 | 571 | if (pfl->bs) { |
| 556 | 572 | /* read the initial flash content */ |
| 557 | - bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9); | |
| 573 | + bdrv_read(pfl->bs, 0, pfl->storage, chip_len >> 9); | |
| 558 | 574 | } |
| 559 | 575 | #if 0 /* XXX: there should be a bit to set up read-only, |
| 560 | 576 | * the same way the hardware does (with WP pin). |
| ... | ... | @@ -564,9 +580,7 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off, |
| 564 | 580 | pfl->ro = 0; |
| 565 | 581 | #endif |
| 566 | 582 | pfl->timer = qemu_new_timer(vm_clock, pflash_timer, pfl); |
| 567 | - pfl->base = base; | |
| 568 | 583 | pfl->sector_len = sector_len; |
| 569 | - pfl->total_len = total_len; | |
| 570 | 584 | pfl->width = width; |
| 571 | 585 | pfl->wcycle = 0; |
| 572 | 586 | pfl->cmd = 0; |
| ... | ... | @@ -620,7 +634,7 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off, |
| 620 | 634 | /* Max timeout for chip erase */ |
| 621 | 635 | pfl->cfi_table[0x26] = 0x0D; |
| 622 | 636 | /* Device size */ |
| 623 | - pfl->cfi_table[0x27] = ctz32(total_len) + 1; | |
| 637 | + pfl->cfi_table[0x27] = ctz32(chip_len) + 1; | |
| 624 | 638 | /* Flash device interface (8 & 16 bits) */ |
| 625 | 639 | pfl->cfi_table[0x28] = 0x02; |
| 626 | 640 | pfl->cfi_table[0x29] = 0x00; | ... | ... |
hw/ppc405_boards.c
| ... | ... | @@ -235,8 +235,8 @@ static void ref405ep_init (int ram_size, int vga_ram_size, |
| 235 | 235 | bdrv_get_device_name(drives_table[index].bdrv), fl_sectors); |
| 236 | 236 | #endif |
| 237 | 237 | pflash_cfi02_register((uint32_t)(-bios_size), bios_offset, |
| 238 | - drives_table[index].bdrv, 65536, fl_sectors, 2, | |
| 239 | - 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA); | |
| 238 | + drives_table[index].bdrv, 65536, fl_sectors, 1, | |
| 239 | + 2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA); | |
| 240 | 240 | fl_idx++; |
| 241 | 241 | } else |
| 242 | 242 | #endif |
| ... | ... | @@ -552,8 +552,8 @@ static void taihu_405ep_init(int ram_size, int vga_ram_size, |
| 552 | 552 | bdrv_get_device_name(drives_table[index].bdrv), fl_sectors); |
| 553 | 553 | #endif |
| 554 | 554 | pflash_cfi02_register((uint32_t)(-bios_size), bios_offset, |
| 555 | - drives_table[index].bdrv, 65536, fl_sectors, 4, | |
| 556 | - 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA); | |
| 555 | + drives_table[index].bdrv, 65536, fl_sectors, 1, | |
| 556 | + 4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA); | |
| 557 | 557 | fl_idx++; |
| 558 | 558 | } else |
| 559 | 559 | #endif |
| ... | ... | @@ -588,8 +588,8 @@ static void taihu_405ep_init(int ram_size, int vga_ram_size, |
| 588 | 588 | bdrv_get_device_name(drives_table[index].bdrv)); |
| 589 | 589 | #endif |
| 590 | 590 | pflash_cfi02_register(0xfc000000, bios_offset, |
| 591 | - drives_table[index].bdrv, 65536, fl_sectors, 4, | |
| 592 | - 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA); | |
| 591 | + drives_table[index].bdrv, 65536, fl_sectors, 1, | |
| 592 | + 4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA); | |
| 593 | 593 | fl_idx++; |
| 594 | 594 | } |
| 595 | 595 | /* Register CLPD & LCD display */ | ... | ... |