From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1JkzB8-0005Qy-Em for qemu-devel@nongnu.org; Sun, 13 Apr 2008 06:11:18 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1JkzB6-0005Pq-KS for qemu-devel@nongnu.org; Sun, 13 Apr 2008 06:11:17 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JkzB6-0005Pe-FD for qemu-devel@nongnu.org; Sun, 13 Apr 2008 06:11:16 -0400 Received: from fmmailgate03.web.de ([217.72.192.234]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1JkzB5-0003zy-Ue for qemu-devel@nongnu.org; Sun, 13 Apr 2008 06:11:16 -0400 Received: from smtp07.web.de (fmsmtp07.dlan.cinetic.de [172.20.5.215]) by fmmailgate03.web.de (Postfix) with ESMTP id 3A460D6EB8DD for ; Sun, 13 Apr 2008 12:11:15 +0200 (CEST) Received: from [88.65.41.105] (helo=[192.168.1.198]) by smtp07.web.de with asmtp (TLSv1:AES256-SHA:256) (WEB.DE 4.109 #226) id 1JkzB4-0002xV-00 for qemu-devel@nongnu.org; Sun, 13 Apr 2008 12:11:15 +0200 Message-ID: <4801DC42.8010008@web.de> Date: Sun, 13 Apr 2008 12:11:14 +0200 From: Jan Kiszka MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: 7bit Sender: jan.kiszka@web.de Subject: [Qemu-devel] [RFC][PATCH 2/4] cfi02: Optionally remap chips multiple times Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org 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 --- 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 */