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 */ | ... | ... |