[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC][PATCH 2/4] cfi02: Optionally remap chips multiple tim
From: |
Jan Kiszka |
Subject: |
[Qemu-devel] [RFC][PATCH 2/4] cfi02: Optionally remap chips multiple times |
Date: |
Sun, 13 Apr 2008 12:11:14 +0200 |
User-agent: |
Thunderbird 2.0.0.12 (X11/20080226) |
On some boards the flash chip might be mapped several times into the
address space. At least this happens on the MusicPal board (8 MB flash
-> 4 times into a 32 MB window), and the cleanest way I found to deal
with this is extending cfi02 with support for remapping the chip.
Again, if this is considered to be useful for cfi01 as well, I'm willing
to extend the patch.
Signed-off-by: Jan Kiszka <address@hidden>
---
hw/flash.h | 2 +-
hw/pflash_cfi02.c | 50 ++++++++++++++++++++++++++++++++------------------
hw/ppc405_boards.c | 12 ++++++------
3 files changed, 39 insertions(+), 25 deletions(-)
Index: b/hw/flash.h
===================================================================
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -11,7 +11,7 @@ pflash_t *pflash_cfi01_register(target_p
/* pflash_cfi02.c */
pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
BlockDriverState *bs, uint32_t sector_len,
- int nb_blocs, int width,
+ int nb_blocs, int nb_mappings, int width,
uint16_t id0, uint16_t id1,
uint16_t id2, uint16_t id3,
uint16_t unlock_addr0, uint16_t unlock_addr1);
Index: b/hw/pflash_cfi02.c
===================================================================
--- a/hw/pflash_cfi02.c
+++ b/hw/pflash_cfi02.c
@@ -55,7 +55,8 @@ struct pflash_t {
BlockDriverState *bs;
target_phys_addr_t base;
uint32_t sector_len;
- uint32_t total_len;
+ uint32_t chip_len;
+ int mappings;
int width;
int wcycle; /* if 0, the flash is read normally */
int bypass;
@@ -72,6 +73,19 @@ struct pflash_t {
void *storage;
};
+static void pflash_register_memory(pflash_t *pfl, int rom_mode)
+{
+ unsigned long phys_offset = pfl->fl_mem;
+ int i;
+
+ if (rom_mode)
+ phys_offset |= pfl->off | IO_MEM_ROMD;
+
+ for (i = 0; i < pfl->mappings; i++)
+ cpu_register_physical_memory(pfl->base + i * pfl->chip_len,
+ pfl->chip_len, phys_offset);
+}
+
static void pflash_timer (void *opaque)
{
pflash_t *pfl = opaque;
@@ -82,8 +96,7 @@ static void pflash_timer (void *opaque)
if (pfl->bypass) {
pfl->wcycle = 2;
} else {
- cpu_register_physical_memory(pfl->base, pfl->total_len,
- pfl->off | IO_MEM_ROMD | pfl->fl_mem);
+ pflash_register_memory(pfl, 1);
pfl->wcycle = 0;
}
pfl->cmd = 0;
@@ -98,6 +111,7 @@ static uint32_t pflash_read (pflash_t *p
DPRINTF("%s: offset " TARGET_FMT_lx "\n", __func__, offset);
ret = -1;
offset -= pfl->base;
+ offset &= pfl->chip_len - 1;
boff = offset & 0xFF;
if (pfl->width == 2)
boff = boff >> 1;
@@ -226,11 +240,10 @@ static void pflash_write (pflash_t *pfl,
offset -= (uint32_t)(long)pfl->storage;
else
offset -= pfl->base;
+ offset &= pfl->chip_len - 1;
DPRINTF("%s: offset " TARGET_FMT_lx " %08x %d\n", __func__,
offset, value, width);
- /* Set the device in I/O access mode */
- cpu_register_physical_memory(pfl->base, pfl->total_len, pfl->fl_mem);
boff = offset & (pfl->sector_len - 1);
if (pfl->width == 2)
boff = boff >> 1;
@@ -238,6 +251,8 @@ static void pflash_write (pflash_t *pfl,
boff = boff >> 2;
switch (pfl->wcycle) {
case 0:
+ /* Set the device in I/O access mode */
+ pflash_register_memory(pfl, 0);
/* We're in read mode */
check_unlock0:
if (boff == 0x55 && cmd == 0x98) {
@@ -369,9 +384,9 @@ static void pflash_write (pflash_t *pfl,
}
/* Chip erase */
DPRINTF("%s: start chip erase\n", __func__);
- memset(pfl->storage, 0xFF, pfl->total_len);
+ memset(pfl->storage, 0xFF, pfl->chip_len);
pfl->status = 0x00;
- pflash_update(pfl, 0, pfl->total_len);
+ pflash_update(pfl, 0, pfl->chip_len);
/* Let's wait 5 seconds before chip erase is done */
qemu_mod_timer(pfl->timer,
qemu_get_clock(vm_clock) + (ticks_per_sec * 5));
@@ -424,8 +439,7 @@ static void pflash_write (pflash_t *pfl,
/* Reset flash */
reset_flash:
- cpu_register_physical_memory(pfl->base, pfl->total_len,
- pfl->off | IO_MEM_ROMD | pfl->fl_mem);
+ pflash_register_memory(pfl, 1);
pfl->bypass = 0;
pfl->wcycle = 0;
pfl->cmd = 0;
@@ -527,15 +541,15 @@ static int ctz32 (uint32_t n)
pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
BlockDriverState *bs, uint32_t sector_len,
- int nb_blocs, int width,
+ int nb_blocs, int nb_mappings, int width,
uint16_t id0, uint16_t id1,
uint16_t id2, uint16_t id3,
uint16_t unlock_addr0, uint16_t unlock_addr1)
{
pflash_t *pfl;
- int32_t total_len;
+ int32_t chip_len;
- total_len = sector_len * nb_blocs;
+ chip_len = sector_len * nb_blocs;
/* XXX: to be fixed */
#if 0
if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) &&
@@ -549,12 +563,14 @@ pflash_t *pflash_cfi02_register(target_p
pfl->fl_mem = cpu_register_io_memory(0, pflash_read_ops, pflash_write_ops,
pfl);
pfl->off = off;
- cpu_register_physical_memory(base, total_len,
- off | pfl->fl_mem | IO_MEM_ROMD);
+ pfl->base = base;
+ pfl->chip_len = chip_len;
+ pfl->mappings = nb_mappings;
+ pflash_register_memory(pfl, 1);
pfl->bs = bs;
if (pfl->bs) {
/* read the initial flash content */
- bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9);
+ bdrv_read(pfl->bs, 0, pfl->storage, chip_len >> 9);
}
#if 0 /* XXX: there should be a bit to set up read-only,
* the same way the hardware does (with WP pin).
@@ -564,9 +580,7 @@ pflash_t *pflash_cfi02_register(target_p
pfl->ro = 0;
#endif
pfl->timer = qemu_new_timer(vm_clock, pflash_timer, pfl);
- pfl->base = base;
pfl->sector_len = sector_len;
- pfl->total_len = total_len;
pfl->width = width;
pfl->wcycle = 0;
pfl->cmd = 0;
@@ -620,7 +634,7 @@ pflash_t *pflash_cfi02_register(target_p
/* Max timeout for chip erase */
pfl->cfi_table[0x26] = 0x0D;
/* Device size */
- pfl->cfi_table[0x27] = ctz32(total_len) + 1;
+ pfl->cfi_table[0x27] = ctz32(chip_len) + 1;
/* Flash device interface (8 & 16 bits) */
pfl->cfi_table[0x28] = 0x02;
pfl->cfi_table[0x29] = 0x00;
Index: b/hw/ppc405_boards.c
===================================================================
--- a/hw/ppc405_boards.c
+++ b/hw/ppc405_boards.c
@@ -235,8 +235,8 @@ static void ref405ep_init (int ram_size,
bdrv_get_device_name(drives_table[index].bdrv), fl_sectors);
#endif
pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
- drives_table[index].bdrv, 65536, fl_sectors, 2,
- 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
+ drives_table[index].bdrv, 65536, fl_sectors, 1,
+ 2, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
fl_idx++;
} else
#endif
@@ -552,8 +552,8 @@ static void taihu_405ep_init(int ram_siz
bdrv_get_device_name(drives_table[index].bdrv), fl_sectors);
#endif
pflash_cfi02_register((uint32_t)(-bios_size), bios_offset,
- drives_table[index].bdrv, 65536, fl_sectors, 4,
- 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
+ drives_table[index].bdrv, 65536, fl_sectors, 1,
+ 4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
fl_idx++;
} else
#endif
@@ -588,8 +588,8 @@ static void taihu_405ep_init(int ram_siz
bdrv_get_device_name(drives_table[index].bdrv));
#endif
pflash_cfi02_register(0xfc000000, bios_offset,
- drives_table[index].bdrv, 65536, fl_sectors, 4,
- 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
+ drives_table[index].bdrv, 65536, fl_sectors, 1,
+ 4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA);
fl_idx++;
}
/* Register CLPD & LCD display */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [RFC][PATCH 2/4] cfi02: Optionally remap chips multiple times,
Jan Kiszka <=