qemu-devel
[Top][All Lists]
Advanced

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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]