Author: hailfinger
Date: Sat May 22 01:09:42 2010
New Revision: 1005
URL: http://flashrom.org/trac/coreboot/changeset/1005

Log:
Every SPI programmer driver had its own completely different chip write
implementation, and all of them were insufficiently commented.
Create spi_write_chunked as a copy of spi_read_chunked and convert all
SPI programmers to use it.
No functional changes except:
- Bus Pirate uses 12 Byte writes instead of 8 Byte writes
- SB600 uses 5 Byte writes instead of 1 Byte writes

Signed-off-by: Carl-Daniel Hailfinger <[email protected]>
Acked-by: Michael Karcher <[email protected]>
Acked-by: David Hendricks <[email protected]>

Modified:
   trunk/bitbang_spi.c
   trunk/buspirate_spi.c
   trunk/chipdrivers.h
   trunk/ft2232_spi.c
   trunk/ichspi.c
   trunk/sb600spi.c
   trunk/spi25.c

Modified: trunk/bitbang_spi.c
==============================================================================
--- trunk/bitbang_spi.c Sat May 22 01:00:56 2010        (r1004)
+++ trunk/bitbang_spi.c Sat May 22 01:09:42 2010        (r1005)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the flashrom project.
  *
- * Copyright (C) 2009 Carl-Daniel Hailfinger
+ * Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -142,24 +142,7 @@
 int bitbang_spi_write_256(struct flashchip *flash, uint8_t *buf)
 {
        int total_size = 1024 * flash->total_size;
-       int i;
 
        msg_pdbg("total_size is %d\n", total_size);
-       for (i = 0; i < total_size; i += 256) {
-               int l, r;
-               if (i + 256 <= total_size)
-                       l = 256;
-               else
-                       l = total_size - i;
-
-               if ((r = spi_nbyte_program(i, &buf[i], l))) {
-                       msg_perr("%s: write fail %d\n", __func__, r);
-                       return 1;
-               }
-               
-               while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
-                       /* loop */;
-       }
-
-       return 0;
+       return spi_write_chunked(flash, buf, 0, total_size, 256);
 }

Modified: trunk/buspirate_spi.c
==============================================================================
--- trunk/buspirate_spi.c       Sat May 22 01:00:56 2010        (r1004)
+++ trunk/buspirate_spi.c       Sat May 22 01:09:42 2010        (r1005)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the flashrom project.
  *
- * Copyright (C) 2009 Carl-Daniel Hailfinger
+ * Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -319,7 +319,6 @@
 int buspirate_spi_write_256(struct flashchip *flash, uint8_t *buf)
 {
        int total_size = 1024 * flash->total_size;
-       int i;
 
        spi_disable_blockprotect();
        /* Erase first. */
@@ -330,25 +329,5 @@
        }
        msg_pinfo("done.\n");
 
-       /* FIXME: We could do 12 byte writes, but then we'd have to make sure
-        * not to cross a 256 byte page boundary. This problem only applies to
-        * writes, reads can cross page boundaries just fine.
-        */
-       for (i = 0; i < total_size; i += 8) {
-               int l, r;
-               if (i + 8 <= total_size)
-                       l = 8;
-               else
-                       l = total_size - i;
-
-               if ((r = spi_nbyte_program(i, &buf[i], l))) {
-                       msg_perr("%s: write fail %d\n", __func__, r);
-                       return 1;
-               }
-
-               while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
-                       /* loop */;
-       }
-
-       return 0;
+       return spi_write_chunked(flash, buf, 0, total_size, 12);
 }

Modified: trunk/chipdrivers.h
==============================================================================
--- trunk/chipdrivers.h Sat May 22 01:00:56 2010        (r1004)
+++ trunk/chipdrivers.h Sat May 22 01:09:42 2010        (r1005)
@@ -51,6 +51,7 @@
 int spi_nbyte_program(int addr, uint8_t *bytes, int len);
 int spi_nbyte_read(int addr, uint8_t *bytes, int len);
 int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int start, int 
len, int chunksize);
+int spi_write_chunked(struct flashchip *flash, uint8_t *buf, int start, int 
len, int chunksize);
 int spi_aai_write(struct flashchip *flash, uint8_t *buf);
 
 /* 82802ab.c */

Modified: trunk/ft2232_spi.c
==============================================================================
--- trunk/ft2232_spi.c  Sat May 22 01:00:56 2010        (r1004)
+++ trunk/ft2232_spi.c  Sat May 22 01:09:42 2010        (r1005)
@@ -2,7 +2,7 @@
  * This file is part of the flashrom project.
  *
  * Copyright (C) 2009 Paul Fox <[email protected]>
- * Copyright (C) 2009 Carl-Daniel Hailfinger
+ * Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -288,7 +288,6 @@
 int ft2232_spi_write_256(struct flashchip *flash, uint8_t *buf)
 {
        int total_size = 1024 * flash->total_size;
-       int i;
 
        spi_disable_blockprotect();
        /* Erase first. */
@@ -299,23 +298,7 @@
        }
        msg_pinfo("done.\n");
        msg_pdbg("total_size is %d\n", total_size);
-       for (i = 0; i < total_size; i += 256) {
-               int l, r;
-               if (i + 256 <= total_size)
-                       l = 256;
-               else
-                       l = total_size - i;
-
-               if ((r = spi_nbyte_program(i, &buf[i], l))) {
-                       msg_perr("%s: write fail %d\n", __func__, r);
-                       return 1;
-               }
-
-               while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
-                       /* loop */;
-       }
-
-       return 0;
+       return spi_write_chunked(flash, buf, 0, total_size, 256);
 }
 
 #endif

Modified: trunk/ichspi.c
==============================================================================
--- trunk/ichspi.c      Sat May 22 01:00:56 2010        (r1004)
+++ trunk/ichspi.c      Sat May 22 01:09:42 2010        (r1005)
@@ -5,7 +5,7 @@
  * Copyright (C) 2008 Claus Gindhart <[email protected]>
  * Copyright (C) 2008 Dominik Geyer <[email protected]>
  * Copyright (C) 2008 coresystems GmbH <[email protected]>
- * Copyright (C) 2009 Carl-Daniel Hailfinger
+ * Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -149,8 +149,6 @@
 static int program_opcodes(OPCODES * op);
 static int run_opcode(OPCODE op, uint32_t offset,
                      uint8_t datalength, uint8_t * data);
-static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes,
-                             int offset, int maxdata);
 
 /* for pairing opcodes with their required preop */
 struct preop_opcode_pair {
@@ -636,28 +634,6 @@
        return -1;
 }
 
-static int ich_spi_write_page(struct flashchip *flash, uint8_t * bytes,
-                             int offset, int maxdata)
-{
-       int page_size = flash->page_size;
-       uint32_t remaining = page_size;
-       int towrite;
-
-       msg_pspew("ich_spi_write_page: offset=%d, number=%d, buf=%p\n",
-                    offset, page_size, bytes);
-
-       for (; remaining > 0; remaining -= towrite) {
-               towrite = min(remaining, maxdata);
-               if (spi_nbyte_program(offset + (page_size - remaining),
-                                     &bytes[page_size - remaining], towrite)) {
-                       msg_perr("Error writing");
-                       return 1;
-               }
-       }
-
-       return 0;
-}
-
 int ich_spi_read(struct flashchip *flash, uint8_t * buf, int start, int len)
 {
        int maxdata = 64;
@@ -670,12 +646,14 @@
 
 int ich_spi_write_256(struct flashchip *flash, uint8_t * buf)
 {
-       int i, j, rc = 0;
+       int i, ret = 0;
        int total_size = flash->total_size * 1024;
-       int page_size = flash->page_size;
        int erase_size = 64 * 1024;
        int maxdata = 64;
 
+       if (spi_controller == SPI_CONTROLLER_VIA)
+               maxdata = 16;
+
        spi_disable_blockprotect();
        /* Erase first */
        msg_pinfo("Erasing flash before programming... ");
@@ -687,19 +665,15 @@
 
        msg_pinfo("Programming page: \n");
        for (i = 0; i < total_size / erase_size; i++) {
-               if (spi_controller == SPI_CONTROLLER_VIA)
-                       maxdata = 16;
-
-               for (j = 0; j < erase_size / page_size; j++) {
-                       ich_spi_write_page(flash,
-                          (void *)(buf + (i * erase_size) + (j * page_size)),
-                          (i * erase_size) + (j * page_size), maxdata);
-               }
+               ret = spi_write_chunked(flash, buf + (i * erase_size),
+                                       i * erase_size, erase_size, maxdata);
+               if (ret)
+                       break;
        }
 
        msg_pinfo("\n");
 
-       return rc;
+       return ret;
 }
 
 int ich_spi_send_command(unsigned int writecnt, unsigned int readcnt,

Modified: trunk/sb600spi.c
==============================================================================
--- trunk/sb600spi.c    Sat May 22 01:00:56 2010        (r1004)
+++ trunk/sb600spi.c    Sat May 22 01:09:42 2010        (r1005)
@@ -4,6 +4,7 @@
  * Copyright (C) 2008 Wang Qingpei <[email protected]>
  * Copyright (C) 2008 Joe Bao <[email protected]>
  * Copyright (C) 2008 Advanced Micro Devices, Inc.
+ * Copyright (C) 2009, 2010 Carl-Daniel Hailfinger
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -49,7 +50,6 @@
 /* FIXME: SB600 can write 5 bytes per transaction. */
 int sb600_spi_write_1(struct flashchip *flash, uint8_t *buf)
 {
-       int i;
        int total_size = flash->total_size * 1024;
        int result = 0;
 
@@ -63,19 +63,7 @@
        msg_pinfo("done.\n");
 
        msg_pinfo("Programming flash");
-       for (i = 0; i < total_size; i++, buf++) {
-               result = spi_nbyte_program(i, buf, 1);
-               if (result) {
-                       msg_perr("Write error!\n");
-                       return result;
-               }
-
-               /* wait program complete. */
-               if (i % 0x8000 == 0)
-                       msg_pspew(".");
-               while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
-                       ;
-       }
+       result = spi_write_chunked(flash, buf, 0, total_size, 5);
        msg_pinfo(" done.\n");
        return result;
 }

Modified: trunk/spi25.c
==============================================================================
--- trunk/spi25.c       Sat May 22 01:00:56 2010        (r1004)
+++ trunk/spi25.c       Sat May 22 01:09:42 2010        (r1005)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the flashrom project.
  *
- * Copyright (C) 2007, 2008, 2009 Carl-Daniel Hailfinger
+ * Copyright (C) 2007, 2008, 2009, 2010 Carl-Daniel Hailfinger
  * Copyright (C) 2008 coresystems GmbH
  *
  * This program is free software; you can redistribute it and/or modify
@@ -874,7 +874,7 @@
 }
 
 /*
- * Read a complete flash chip.
+ * Read a part of the flash chip.
  * Each page is read separately in chunks with a maximum size of chunksize.
  */
 int spi_read_chunked(struct flashchip *flash, uint8_t *buf, int start, int 
len, int chunksize)
@@ -907,6 +907,52 @@
                }
                if (rc)
                        break;
+       }
+
+       return rc;
+}
+
+/*
+ * Write a part of the flash chip.
+ * Each page is written separately in chunks with a maximum size of chunksize.
+ */
+int spi_write_chunked(struct flashchip *flash, uint8_t *buf, int start, int 
len, int chunksize)
+{
+       int rc = 0;
+       int i, j, starthere, lenhere;
+       /* FIXME: page_size is the wrong variable. We need max_writechunk_size
+        * in struct flashchip to do this properly. All chips using
+        * spi_chip_write_256 have page_size set to max_writechunk_size, so
+        * we're OK for now.
+        */
+       int page_size = flash->page_size;
+       int towrite;
+
+       /* Warning: This loop has a very unusual condition and body.
+        * The loop needs to go through each page with at least one affected
+        * byte. The lowest page number is (start / page_size) since that
+        * division rounds down. The highest page number we want is the page
+        * where the last byte of the range lives. That last byte has the
+        * address (start + len - 1), thus the highest page number is
+        * (start + len - 1) / page_size. Since we want to include that last
+        * page as well, the loop condition uses <=.
+        */
+       for (i = start / page_size; i <= (start + len - 1) / page_size; i++) {
+               /* Byte position of the first byte in the range in this page. */
+               /* starthere is an offset to the base address of the chip. */
+               starthere = max(start, i * page_size);
+               /* Length of bytes in the range in this page. */
+               lenhere = min(start + len, (i + 1) * page_size) - starthere;
+               for (j = 0; j < lenhere; j += chunksize) {
+                       towrite = min(chunksize, lenhere - j);
+                       rc = spi_nbyte_program(starthere + j, buf + starthere - 
start + j, towrite);
+                       if (rc)
+                               break;
+                       while (spi_read_status_register() & JEDEC_RDSR_BIT_WIP)
+                               programmer_delay(10);
+               }
+               if (rc)
+                       break;
        }
 
        return rc;

_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to