Hi.

I'm currently struggling to understand what the write granularity is for and how it
interacts with the page size?
I'm also a little confused by flashrom's use of page size?

I am mainly interested in SPI flash chips.  For most SPI chips the "page size" is 256 bytes.
I have a chip where the page size is 512 bytes.

The "page size" is the amount that writes using the PP command have to be chunked by.
So "spi_nbyte_program" must be used to write no more than "page size" bytes and must
not cross a "page size" boundary.

So far this all makes sense, apart from the "spi_chip_write_256" function, which should
be named "spi_chip_write_page"?  (as all chips currently have a page size of 256 this is
correct at the moment, but I'm about to add one that doesn't).

I think that the "chunksize" parameter in spi_write_chunked is to do with possible restrictions
of some programmer hardware?  This also makes sense, apart from all of the comments which
are very out of date?

According to the manuals of the SPI Flash chips I've looked at, when using the PP command
you can program any part of a page, and the correct thing will happen (1's can only be written
to 0's).  So I don't see how this matches up with "write granularity", which claims that the other
bytes in the granularity region will be "undefined"?

Is write granularity for something else?
Is there a post somewhere that I missed that explains all of this?

Thanks for any help,

Mark M.



On 14 March 2013 12:13, Stefan Tauner <stefan.tauner@student.tuwien.ac.at> wrote:
This adds a number of new granularities in a rather inelegant way.
Until we figure out how to better handle various granularities this has
to be accepted.

It also refactors the handling of n-byte granularities by extracting the
checking code into a helper function which reduces the pain of the above
significantly.

Signed-off-by: Stefan Tauner <stefan.tauner@student.tuwien.ac.at>
---
This is one possibility to solve the granularity issue and i think the
most likely to get the patch series in fastest...

 flash.h    |   24 +++++++++++++----------
 flashrom.c |   64 ++++++++++++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 63 insertions(+), 25 deletions(-)

diff --git a/flash.h b/flash.h
index 9c4b0ac..845d898 100644
--- a/flash.h
+++ b/flash.h
@@ -59,18 +59,22 @@ enum chipbustype {
 };

 /*
- * The following write granularities are known:
- * - 1 bit: Each bit can be cleared individually.
- * - 1 byte: A byte can be written once. Further writes to an already written byte cause its contents to be
- *   either undefined or to stay unchanged.
- * - 128 bytes: If less than 128 bytes are written, the rest will be erased. Each write to a 128-byte region
- *   will trigger an automatic erase before anything is written. Very uncommon behaviour.
- * - 256 bytes: If less than 256 bytes are written, the contents of the unwritten bytes are undefined.
+ * The following enum defines possible write granularities of flash chips. These tend to reflect the properties
+ * of the actual hardware not necesserily the write function(s) defined by the respective struct flashchip.
+ * The latter might (and should) be more precisely specified, e.g. they might bail out early if their execution
+ * would result in undefined chip contents.
  */
 enum write_granularity {
-       write_gran_256bytes = 0, /* We assume 256 byte granularity by default. */
-       write_gran_1bit,
-       write_gran_1byte,
+       /* We assume 256 byte granularity by default. */
+       write_gran_256bytes = 0,/* If less than 256 bytes are written, the unwritten bytes are undefined. */
+       write_gran_1bit,        /* Each bit can be cleared individually. */
+       write_gran_1byte,       /* A byte can be written once. Further writes to an already written byte cause
+                                * its contents to be either undefined or to stay unchanged. */
+       write_gran_264bytes,    /* If less than 264 bytes are written, the unwritten bytes are undefined. */
+       write_gran_512bytes,    /* If less than 512 bytes are written, the unwritten bytes are undefined. */
+       write_gran_528bytes,    /* If less than 528 bytes are written, the unwritten bytes are undefined. */
+       write_gran_1024bytes,   /* If less than 1024 bytes are written, the unwritten bytes are undefined. */
+       write_gran_1056bytes,   /* If less than 1056 bytes are written, the unwritten bytes are undefined. */
 };

 /*
diff --git a/flashrom.c b/flashrom.c
index 225b6f0..4e5f484 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -676,6 +676,23 @@ out_free:
        return ret;
 }

+/* Helper function for need_erase() that focuses on granularities of n bytes. */
+static int need_erase_n_bytes(uint8_t *have, uint8_t *want, unsigned int len, unsigned int n)
+{
+       unsigned int i, j, limit;
+       for (j = 0; j < len / n; j++) {
+               limit = min (n, len - j * n);
+               /* Are 'have' and 'want' identical? */
+               if (!memcmp(have + j * n, want + j * n, limit))
+                       continue;
+               /* have needs to be in erased state. */
+               for (i = 0; i < limit; i++)
+                       if (have[j * n + i] != 0xff)
+                               return 1;
+       }
+       return 0;
+}
+
 /*
  * Check if the buffer @have can be programmed to the content of @want without
  * erasing. This is only possible if all chunks of size @gran are either kept
@@ -693,7 +710,7 @@ out_free:
 int need_erase(uint8_t *have, uint8_t *want, unsigned int len, enum write_granularity gran)
 {
        int result = 0;
-       unsigned int i, j, limit;
+       unsigned int i;

        switch (gran) {
        case write_gran_1bit:
@@ -711,20 +728,22 @@ int need_erase(uint8_t *have, uint8_t *want, unsigned int len, enum write_granul
                        }
                break;
        case write_gran_256bytes:
-               for (j = 0; j < len / 256; j++) {
-                       limit = min (256, len - j * 256);
-                       /* Are 'have' and 'want' identical? */
-                       if (!memcmp(have + j * 256, want + j * 256, limit))
-                               continue;
-                       /* have needs to be in erased state. */
-                       for (i = 0; i < limit; i++)
-                               if (have[j * 256 + i] != 0xff) {
-                                       result = 1;
-                                       break;
-                               }
-                       if (result)
-                               break;
-               }
+               result = need_erase_n_bytes(have, want, len, 256);
+               break;
+       case write_gran_264bytes:
+               result = need_erase_n_bytes(have, want, len, 264);
+               break;
+       case write_gran_512bytes:
+               result = need_erase_n_bytes(have, want, len, 512);
+               break;
+       case write_gran_528bytes:
+               result = need_erase_n_bytes(have, want, len, 528);
+               break;
+       case write_gran_1024bytes:
+               result = need_erase_n_bytes(have, want, len, 1024);
+               break;
+       case write_gran_1056bytes:
+               result = need_erase_n_bytes(have, want, len, 1056);
                break;
        default:
                msg_cerr("%s: Unsupported granularity! Please report a bug at "
@@ -772,6 +791,21 @@ static unsigned int get_next_write(uint8_t *have, uint8_t *want, unsigned int le
        case write_gran_256bytes:
                stride = 256;
                break;
+       case write_gran_264bytes:
+               stride = 264;
+               break;
+       case write_gran_512bytes:
+               stride = 512;
+               break;
+       case write_gran_528bytes:
+               stride = 528;
+               break;
+       case write_gran_1024bytes:
+               stride = 1024;
+               break;
+       case write_gran_1056bytes:
+               stride = 1056;
+               break;
        default:
                msg_cerr("%s: Unsupported granularity! Please report a bug at "
                         "flashrom@flashrom.org\n", __func__);
--
Kind regards, Stefan Tauner


_______________________________________________
flashrom mailing list
flashrom@flashrom.org
http://www.flashrom.org/mailman/listinfo/flashrom