[1/2,v3] block: Add device-width property to pflash_cfi01

Message ID 1382202274-8190-2-git-send-email-roy.franz@linaro.org
State New
Headers show

Commit Message

Roy Franz Oct. 19, 2013, 5:04 p.m.
The width of the devices that make up the flash interface
is required to mask certain commands, in particular the
write length for buffered writes.  This length will be presented
to each device on the interface by the program writing the flash,
and the flash emulation code needs to be able to determine
the length of the write as recieved by each flash device.
The device-width defaults to the bank width which should
maintain existing behavior for platforms that don't need
this change.
This change is required to support buffered writes on the
vexpress platform that has a 32 bit flash interface with 2
16 bit devices on it.

Signed-off-by: Roy Franz <roy.franz@linaro.org>
---
 hw/block/pflash_cfi01.c |   21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

Comments

Peter Maydell Oct. 19, 2013, 8:59 p.m. | #1
On 19 October 2013 18:04, Roy Franz <roy.franz@linaro.org> wrote:
> The width of the devices that make up the flash interface
> is required to mask certain commands, in particular the
> write length for buffered writes.  This length will be presented
> to each device on the interface by the program writing the flash,
> and the flash emulation code needs to be able to determine
> the length of the write as recieved by each flash device.
> The device-width defaults to the bank width which should
> maintain existing behavior for platforms that don't need
> this change.
> This change is required to support buffered writes on the
> vexpress platform that has a 32 bit flash interface with 2
> 16 bit devices on it.
>
> Signed-off-by: Roy Franz <roy.franz@linaro.org>
> ---
>  hw/block/pflash_cfi01.c |   21 +++++++++++++--------
>  1 file changed, 13 insertions(+), 8 deletions(-)
>
> diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
> index 018a967..cda8289 100644
> --- a/hw/block/pflash_cfi01.c
> +++ b/hw/block/pflash_cfi01.c
> @@ -71,7 +71,8 @@ struct pflash_t {
>      BlockDriverState *bs;
>      uint32_t nb_blocs;
>      uint64_t sector_len;
> -    uint8_t width;
> +    uint8_t bank_width;

If you want to rename this struct field can you put that in its own patch,
please? Otherwise it's hard to see the actual functional changes.

> +    uint8_t device_width;
>      uint8_t be;
>      uint8_t wcycle; /* if 0, the flash is read normally */
>      int ro;
> @@ -126,9 +127,9 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
>      ret = -1;
>      boff = offset & 0xFF; /* why this here ?? */
>
> -    if (pfl->width == 2)
> +    if (pfl->bank_width == 2)
>          boff = boff >> 1;
> -    else if (pfl->width == 4)
> +    else if (pfl->bank_width == 4)
>          boff = boff >> 2;
>
>  #if 0
> @@ -378,6 +379,8 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
>
>              break;
>          case 0xe8:
> +            /* Mask writeblock size based on device width */
> +            value &= (1ULL << (pfl->device_width * 8)) - 1;

Is this really the only guest visible difference for banked flash devices?

>              DPRINTF("%s: block write of %x bytes\n", __func__, value);
>              pfl->counter = value;
>              pfl->wcycle++;

thanks
-- PMM

Patch

diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index 018a967..cda8289 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -71,7 +71,8 @@  struct pflash_t {
     BlockDriverState *bs;
     uint32_t nb_blocs;
     uint64_t sector_len;
-    uint8_t width;
+    uint8_t bank_width;
+    uint8_t device_width;
     uint8_t be;
     uint8_t wcycle; /* if 0, the flash is read normally */
     int ro;
@@ -126,9 +127,9 @@  static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
     ret = -1;
     boff = offset & 0xFF; /* why this here ?? */
 
-    if (pfl->width == 2)
+    if (pfl->bank_width == 2)
         boff = boff >> 1;
-    else if (pfl->width == 4)
+    else if (pfl->bank_width == 4)
         boff = boff >> 2;
 
 #if 0
@@ -378,6 +379,8 @@  static void pflash_write(pflash_t *pfl, hwaddr offset,
 
             break;
         case 0xe8:
+            /* Mask writeblock size based on device width */
+            value &= (1ULL << (pfl->device_width * 8)) - 1;
             DPRINTF("%s: block write of %x bytes\n", __func__, value);
             pfl->counter = value;
             pfl->wcycle++;
@@ -665,7 +668,7 @@  static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
     pfl->cfi_table[0x28] = 0x02;
     pfl->cfi_table[0x29] = 0x00;
     /* Max number of bytes in multi-bytes write */
-    if (pfl->width == 1) {
+    if (pfl->bank_width == 1) {
         pfl->cfi_table[0x2A] = 0x08;
     } else {
         pfl->cfi_table[0x2A] = 0x0B;
@@ -706,7 +709,8 @@  static Property pflash_cfi01_properties[] = {
     DEFINE_PROP_DRIVE("drive", struct pflash_t, bs),
     DEFINE_PROP_UINT32("num-blocks", struct pflash_t, nb_blocs, 0),
     DEFINE_PROP_UINT64("sector-length", struct pflash_t, sector_len, 0),
-    DEFINE_PROP_UINT8("width", struct pflash_t, width, 0),
+    DEFINE_PROP_UINT8("width", struct pflash_t, bank_width, 0),
+    DEFINE_PROP_UINT8("device-width", struct pflash_t, device_width, 0),
     DEFINE_PROP_UINT8("big-endian", struct pflash_t, be, 0),
     DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0),
     DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0),
@@ -745,8 +749,8 @@  pflash_t *pflash_cfi01_register(hwaddr base,
                                 DeviceState *qdev, const char *name,
                                 hwaddr size,
                                 BlockDriverState *bs,
-                                uint32_t sector_len, int nb_blocs, int width,
-                                uint16_t id0, uint16_t id1,
+                                uint32_t sector_len, int nb_blocs,
+                                int bank_width, uint16_t id0, uint16_t id1,
                                 uint16_t id2, uint16_t id3, int be)
 {
     DeviceState *dev = qdev_create(NULL, TYPE_CFI_PFLASH01);
@@ -756,7 +760,8 @@  pflash_t *pflash_cfi01_register(hwaddr base,
     }
     qdev_prop_set_uint32(dev, "num-blocks", nb_blocs);
     qdev_prop_set_uint64(dev, "sector-length", sector_len);
-    qdev_prop_set_uint8(dev, "width", width);
+    qdev_prop_set_uint8(dev, "width", bank_width);
+    qdev_prop_set_uint8(dev, "device-width", bank_width);
     qdev_prop_set_uint8(dev, "big-endian", !!be);
     qdev_prop_set_uint16(dev, "id0", id0);
     qdev_prop_set_uint16(dev, "id1", id1);