summaryrefslogtreecommitdiff
path: root/spi.c
diff options
context:
space:
mode:
authorhailfinger <hailfinger@2b7e53f0-3cfb-0310-b3e9-8179ed1497e1>2010-09-15 00:13:02 +0000
committerhailfinger <hailfinger@2b7e53f0-3cfb-0310-b3e9-8179ed1497e1>2010-09-15 00:13:02 +0000
commit2eb79e9e5022506b6b7478520a6fcc60d9d84454 (patch)
tree096c8eb5101ada5ba8b098baf30060a20f471512 /spi.c
parentf13f8c9136c330d23e6e71a2ebc2581c033dd2d9 (diff)
downloadflashrom-2eb79e9e5022506b6b7478520a6fcc60d9d84454.tar.gz
Honor ICH SPI address window for reads.
ICH SPI has the ability to restrict SPI read/write accesses to a given address range. The low end of the range is configurable by the BIOS (and by flashrom if the BIOS didn't lock down the flash interface), the high end of the range is 0xffffff (2^24-1). This patch checks for an address range restriction and uses the low end of the allowed range as base for SPI reads. A similar workaround for REMS/RES opcodes has been committed in r500. This fixes read on the Intel D945GCLF mainboard where the stock BIOS enforces a restricted address range. Please note that writes need the same fix, but for architectural reasons that fix will be merged once partial write is available. Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> Tested by David Hendricks on the Intel D945GCLF mainboard, results at http://paste.flashrom.org/view.php?id=79 Acked-by: David Hendricks <dhendrix@google.com> git-svn-id: https://code.coreboot.org/svn/flashrom/trunk@1170 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'spi.c')
-rw-r--r--spi.c23
1 files changed, 22 insertions, 1 deletions
diff --git a/spi.c b/spi.c
index e892e74..e52ea7a 100644
--- a/spi.c
+++ b/spi.c
@@ -22,6 +22,7 @@
* Contains the generic SPI framework
*/
+#include <string.h>
#include "flash.h"
#include "flashchips.h"
#include "chipdrivers.h"
@@ -207,6 +208,7 @@ int default_spi_send_multicommand(struct spi_command *cmds)
int spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len)
{
+ int addrbase = 0;
if (!spi_programmer[spi_controller].read) {
msg_perr("%s called, but SPI read is unsupported on this "
"hardware. Please report a bug at "
@@ -214,7 +216,26 @@ int spi_chip_read(struct flashchip *flash, uint8_t *buf, int start, int len)
return 1;
}
- return spi_programmer[spi_controller].read(flash, buf, start, len);
+ /* Check if the chip fits between lowest valid and highest possible
+ * address. Highest possible address with the current SPI implementation
+ * means 0xffffff, the highest unsigned 24bit number.
+ */
+ addrbase = spi_get_valid_read_addr();
+ if (addrbase + flash->total_size * 1024 > (1 << 24)) {
+ msg_perr("Flash chip size exceeds the allowed access window. ");
+ msg_perr("Read will probably fail.\n");
+ /* Try to get the best alignment subject to constraints. */
+ addrbase = (1 << 24) - flash->total_size * 1024;
+ }
+ /* Check if alignment is native (at least the largest power of two which
+ * is a factor of the mapped size of the chip).
+ */
+ if (ffs(flash->total_size * 1024) > (ffs(addrbase) ? : 33)) {
+ msg_perr("Flash chip is not aligned natively in the allowed "
+ "access window.\n");
+ msg_perr("Read will probably return garbage.\n");
+ }
+ return spi_programmer[spi_controller].read(flash, buf, addrbase + start, len);
}
/*