qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Roy Franz <roy.franz@linaro.org>
To: qemu-devel@nongnu.org, peter.maydell@linaro.org,
	kwolf@redhat.com, stefanha@redhat.com
Cc: Roy Franz <roy.franz@linaro.org>, patches@linaro.org
Subject: [Qemu-devel] [PATCH V5 7/7] Fix NOR flash device ID reading
Date: Thu,  5 Dec 2013 13:35:59 -0800	[thread overview]
Message-ID: <1386279359-32286-8-git-send-email-roy.franz@linaro.org> (raw)
In-Reply-To: <1386279359-32286-1-git-send-email-roy.franz@linaro.org>

Fix NOR flash manufacturer and device ID reading.  This now
properly takes into account device widths and device max widths
as required.  The reading of these IDs uses the same max_width
dependent addressing as CFI queries.

The old code remains for chips that don't specify a device width,
as the new code relies on a device width being set in order to
properly operate.  The existing code seems very broken.

Only ident0 and ident1 are used in the new code, as other fields
relate to the lock state of blocks in flash.

The VExpress flash configuration has been updated to match
the new code, as the existing definition was 'wrong' in order
to return the expected results with the broken device ID code.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
---
 hw/arm/vexpress.c       |    6 +--
 hw/block/pflash_cfi01.c |  107 ++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 90 insertions(+), 23 deletions(-)

diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index 939b468..aaa863e 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -499,10 +499,10 @@ static pflash_t *ve_pflash_cfi01_register(hwaddr base, const char *name,
     qdev_prop_set_uint8(dev, "width", 4);
     qdev_prop_set_uint8(dev, "device-width", 2);
     qdev_prop_set_uint8(dev, "big-endian", 0);
-    qdev_prop_set_uint16(dev, "id0", 0x00);
-    qdev_prop_set_uint16(dev, "id1", 0x89);
+    qdev_prop_set_uint16(dev, "id0", 0x89);
+    qdev_prop_set_uint16(dev, "id1", 0x18);
     qdev_prop_set_uint16(dev, "id2", 0x00);
-    qdev_prop_set_uint16(dev, "id3", 0x18);
+    qdev_prop_set_uint16(dev, "id3", 0x00);
     qdev_prop_set_string(dev, "name", name);
     qdev_init_nofail(dev);
 
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 564e6ee..15e4a64 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -179,6 +179,58 @@ static uint32_t pflash_cfi_query(pflash_t *pfl, hwaddr offset)
     return resp;
 }
 
+
+
+/* Perform a device id query based on the bank width of the flash. */
+static uint32_t pflash_devid_query(pflash_t *pfl, hwaddr offset)
+{
+    int i;
+    uint32_t resp;
+    hwaddr boff;
+
+    /* Adjust incoming offset to match expected device-width
+     * addressing. Device ID read addresses are always specified in
+     * terms of the maximum supported width of the device.  This means
+     * that x8 devices and x8/x16 devices in x8 mode behave
+     * differently. For devices that are not used at their max width,
+     * we will be provided with addresses that use higher address bits
+     * than expected (based on the max width), so we will shift them
+     * lower so that they will match the addresses used when
+     * device_width==max_device_width.
+     */
+    boff = offset >> (ctz32(pfl->bank_width) +
+                      ctz32(pfl->max_device_width) - ctz32(pfl->device_width));
+
+    /* Mask off upper bits which may be used in to query block
+     * or sector lock status at other addresses.
+     * Offsets 2/3 are block lock status, is not emulated.
+     */
+    switch (boff & 0xFF) {
+    case 0:
+        resp = pfl->ident0;
+        DPRINTF("%s: Manufacturer Code %04x\n", __func__, ret);
+        break;
+    case 1:
+        resp = pfl->ident1;
+        DPRINTF("%s: Device ID Code %04x\n", __func__, ret);
+        break;
+    default:
+        DPRINTF("%s: Read Device Information offset=%x\n", __func__,
+                (unsigned)offset);
+        return 0;
+        break;
+    }
+    /* Replicate responses for each device in bank. */
+    if (pfl->device_width < pfl->bank_width) {
+        for (i = pfl->device_width;
+              i < pfl->bank_width; i += pfl->device_width) {
+            resp = deposit32(resp, 8 * i, 8 * pfl->device_width, resp);
+        }
+    }
+
+    return resp;
+}
+
 static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
                              int width, int be)
 {
@@ -266,26 +318,41 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
         DPRINTF("%s: status %x\n", __func__, ret);
         break;
     case 0x90:
-        boff = offset & 0xFF;
-        if (pfl->bank_width == 2)
-            boff = boff >> 1;
-        else if (pfl->bank_width == 4)
-            boff = boff >> 2;
-
-        switch (boff) {
-        case 0:
-            ret = pfl->ident0 << 8 | pfl->ident1;
-            DPRINTF("%s: Manufacturer Code %04x\n", __func__, ret);
-            break;
-        case 1:
-            ret = pfl->ident2 << 8 | pfl->ident3;
-            DPRINTF("%s: Device ID Code %04x\n", __func__, ret);
-            break;
-        default:
-            DPRINTF("%s: Read Device Information boff=%x\n", __func__,
-                    (unsigned)boff);
-            ret = 0;
-            break;
+
+        if (!pfl->device_width) {
+            /* Preserve old behavior if device width not specified */
+            boff = offset & 0xFF;
+            if (pfl->bank_width == 2) {
+                boff = boff >> 1;
+            } else if (pfl->bank_width == 4) {
+                boff = boff >> 2;
+            }
+
+            switch (boff) {
+            case 0:
+                ret = pfl->ident0 << 8 | pfl->ident1;
+                DPRINTF("%s: Manufacturer Code %04x\n", __func__, ret);
+                break;
+            case 1:
+                ret = pfl->ident2 << 8 | pfl->ident3;
+                DPRINTF("%s: Device ID Code %04x\n", __func__, ret);
+                break;
+            default:
+                DPRINTF("%s: Read Device Information boff=%x\n", __func__,
+                        (unsigned)boff);
+                ret = 0;
+                break;
+            }
+        } else {
+            /* If we have a read larger than the bank_width, combine multiple
+             * manufacturer/device ID queries into a single response.
+             */
+            int i;
+            for (i = 0; i < width; i += pfl->bank_width) {
+                ret = deposit32(ret, i * 8, pfl->bank_width * 8,
+                                pflash_devid_query(pfl,
+                                                 offset + i * pfl->bank_width));
+            }
         }
         break;
     case 0x98: /* Query mode */
-- 
1.7.10.4

  parent reply	other threads:[~2013-12-05 21:36 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-05 21:35 [Qemu-devel] [PATCH V5 0/7] block, arm: Fix buffered flash writes on VExpress Roy Franz
2013-12-05 21:35 ` [Qemu-devel] [PATCH V5 1/7] rename pflash_t member width to bank_width Roy Franz
2013-12-05 21:35 ` [Qemu-devel] [PATCH V5 2/7] Add device-width property to pflash_cfi01 Roy Franz
2013-12-12 17:31   ` Peter Maydell
2013-12-05 21:35 ` [Qemu-devel] [PATCH V5 3/7] return status for each NOR flash device Roy Franz
2013-12-12 17:31   ` Peter Maydell
2013-12-05 21:35 ` [Qemu-devel] [PATCH V5 4/7] Set proper device-width for vexpress flash Roy Franz
2013-12-12 17:32   ` Peter Maydell
2013-12-05 21:35 ` [Qemu-devel] [PATCH V5 5/7] Add max device width parameter for NOR devices Roy Franz
2013-12-12 17:26   ` Peter Maydell
2013-12-12 17:37     ` Peter Maydell
2013-12-12 20:08       ` Roy Franz
2013-12-05 21:35 ` [Qemu-devel] [PATCH V5 6/7] Fix CFI query responses for NOR flash Roy Franz
2013-12-12 17:33   ` Peter Maydell
2013-12-05 21:35 ` Roy Franz [this message]
2013-12-12 17:35   ` [Qemu-devel] [PATCH V5 7/7] Fix NOR flash device ID reading Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1386279359-32286-8-git-send-email-roy.franz@linaro.org \
    --to=roy.franz@linaro.org \
    --cc=kwolf@redhat.com \
    --cc=patches@linaro.org \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).