Delay between probe and subsequent operations.
Some flash chips need time to exit ID mode, and while we take care of
correct timing for the matching probe, subsequent probes may have
totally different timing, and that can lead to garbage responses from
the flash chip during the first accesses after the probe sequence is done.
Delay 100 ms between the last probe and any subsequent operation.
To ensure maximum correctness, we would have to reset the chip first in
case the last probe function left the chip in an undefined (non-read)
state. That will be possible once struct flashchip has a .reset function.
This fixes unstable erase/read/write for some flahs chips on nic3com and
possible other use cases as well.
Thanks to Maciej Pijanka for reporting the issue and testing patches.
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006(a)gmx.net>
Index: flashrom-delay_after_probes/cli_classic.c
===================================================================
--- flashrom-delay_after_probes/cli_classic.c (Revision 1171)
+++ flashrom-delay_after_probes/cli_classic.c (Arbeitskopie)
@@ -456,5 +456,10 @@
if (write_it && !dont_verify_it)
verify_it = 1;
+ /* FIXME: We should issue an unconditional chip reset here. This can be
+ * done once we have a .reset function in struct flashchip.
+ * Give the chip time to settle.
+ */
+ programmer_delay(100000);
return doit(flash, force, filename, read_it, write_it, erase_it, verify_it);
}
--
http://www.hailfinger.org/
Author: hailfinger
Date: Wed Sep 15 12:20:16 2010
New Revision: 1172
URL: http://flashrom.org/trac/flashrom/changeset/1172
Log:
Delay between probe and subsequent operations.
Some flash chips need time to exit ID mode, and while we take care of
correct timing for the matching probe, subsequent probes may have
totally different timing, and that can lead to garbage responses from
the flash chip during the first accesses after the probe sequence is
done.
Delay 100 ms between the last probe and any subsequent operation.
To ensure maximum correctness, we would have to reset the chip first in
case the last probe function left the chip in an undefined (non-read)
state. That will be possible once struct flashchip has a .reset
function.
This fixes unstable erase/read/write for some flahs chips on nic3com and
possible other use cases as well.
Thanks to Maciej Pijanka for reporting the issue and testing patches.
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006(a)gmx.net>
Acked-by: Michael Karcher <flashrom(a)mkarcher.dialup.fu-berlin.de>
Modified:
trunk/cli_classic.c
Modified: trunk/cli_classic.c
==============================================================================
--- trunk/cli_classic.c Wed Sep 15 02:17:37 2010 (r1171)
+++ trunk/cli_classic.c Wed Sep 15 12:20:16 2010 (r1172)
@@ -456,5 +456,10 @@
if (write_it && !dont_verify_it)
verify_it = 1;
+ /* FIXME: We should issue an unconditional chip reset here. This can be
+ * done once we have a .reset function in struct flashchip.
+ * Give the chip time to settle.
+ */
+ programmer_delay(100000);
return doit(flash, force, filename, read_it, write_it, erase_it, verify_it);
}
---------- Forwarded message ----------
From: Shahar Or <mightyiampresence(a)gmail.com>
Date: Wed, 15 Sep 2010 08:59:02 +0200
Subject: Re: flashrom test on MSI PM8M3-V 4.1
To: Uwe Hermann <uwe(a)hermann-uwe.de>
Dear ones,
It is the V H, actually. Thanks for noticing.
Blessings,
Shahar
On 9/15/10, Uwe Hermann <uwe(a)hermann-uwe.de> wrote:
> On Sat, Sep 04, 2010 at 11:39:58AM +0000, Shahar Or wrote:
>> DMI string system-product-name: "MS-7211"
> [...]
>> SUCCESS.
>> COMPLETE.
>> Verifying flash... VERIFIED.
>
> Look good, thanks, we marked the "MSI MS-7211 (PM8M3-V)" as tested.
> Just to make sure, you have the "PM8M3-V", not the "PM8M3-V H", right?
>
>
> Thanks, Uwe.
> --
> http://hermann-uwe.de | http://sigrok.org
> http://randomprojects.org | http://unmaintained-free-software.org
>
--
Sent from my mobile device
--
Sent from my mobile device
SPI bitbanging on devices which speak SPI natively has a dual-use
problem: We need to shut down normal SPI operations to do the bitbanging
ourselves. Once we're done, it makes a lot of sense to reenable "normal"
SPI operations again. Add request_bus/release_bus functions to struct
bitbang_spi_master.
Add a bitbang shutdown function (not used yet).
Change MCP SPI and Intel NIC SPI to use the new request/release bus
infrastructure.
There are multiple possible strategies for bus request/release:
- Request at the start of a SPI command, release immediately afterwards.
- Request at the start of a SPI multicommand, release once all commands
of the multicommand are done.
- Request on programmer init, release on shutdown.
Each strategy has its own advantages. For now, we will stay with the
first strategy which worked fine so far.
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006(a)gmx.net>
Index: flashrom-bitbang_spi_init_errorcheck_request_release_bus/bitbang_spi.c
===================================================================
--- flashrom-bitbang_spi_init_errorcheck_request_release_bus/bitbang_spi.c (Revision 1164)
+++ flashrom-bitbang_spi_init_errorcheck_request_release_bus/bitbang_spi.c (Arbeitskopie)
@@ -53,6 +53,18 @@
return bitbang_spi_master->get_miso();
}
+static void bitbang_spi_request_bus(void)
+{
+ if (bitbang_spi_master->request_bus)
+ bitbang_spi_master->request_bus();
+}
+
+static void bitbang_spi_release_bus(void)
+{
+ if (bitbang_spi_master->release_bus)
+ bitbang_spi_master->release_bus();
+}
+
int bitbang_spi_init(const struct bitbang_spi_master *master, int halfperiod)
{
/* BITBANG_SPI_INVALID is 0, so if someone forgot to initialize ->type,
@@ -61,19 +73,44 @@
*/
if (!master || master->type == BITBANG_SPI_INVALID || !master->set_cs ||
!master->set_sck || !master->set_mosi || !master->get_miso) {
- msg_perr("Incomplete bitbanging SPI master setting! Please "
- "report a bug at flashrom(a)flashrom.org\n");
+ msg_perr("Incomplete SPI bitbang master setting! "
+ "Please report a bug at flashrom(a)flashrom.org\n");
return 1;
}
+ if (bitbang_spi_master) {
+ msg_perr("SPI bitbang master already initialized! "
+ "Please report a bug at flashrom(a)flashrom.org\n");
+ return 1;
+ }
+
bitbang_spi_master = master;
bitbang_spi_half_period = halfperiod;
+ /* FIXME: Run bitbang_spi_request_bus here or in programmer init? */
bitbang_spi_set_cs(1);
bitbang_spi_set_sck(0);
bitbang_spi_set_mosi(0);
return 0;
}
+int bitbang_spi_shutdown(const struct bitbang_spi_master *master)
+{
+ if (!bitbang_spi_master) {
+ msg_perr("Shutting down an uninitialized SPI bitbang master! "
+ "Please report a bug at flashrom(a)flashrom.org\n");
+ return 1;
+ }
+ if (master != bitbang_spi_master) {
+ msg_perr("Shutting down a mismatched SPI bitbang master! "
+ "Please report a bug at flashrom(a)flashrom.org\n");
+ return 1;
+ }
+
+ /* FIXME: Run bitbang_spi_release_bus here or per command? */
+ bitbang_spi_master = NULL;
+ return 0;
+}
+
static uint8_t bitbang_spi_readwrite_byte(uint8_t val)
{
uint8_t ret = 0;
@@ -96,6 +133,11 @@
{
int i;
+ /* FIXME: Run bitbang_spi_request_bus here or in programmer init?
+ * Requesting and releasing the SPI bus is handled in here to allow the
+ * programmer to use its own SPI engine for native accesses.
+ */
+ bitbang_spi_request_bus();
bitbang_spi_set_cs(0);
for (i = 0; i < writecnt; i++)
bitbang_spi_readwrite_byte(writearr[i]);
@@ -105,6 +147,8 @@
programmer_delay(bitbang_spi_half_period);
bitbang_spi_set_cs(1);
programmer_delay(bitbang_spi_half_period);
+ /* FIXME: Run bitbang_spi_release_bus here or in programmer init? */
+ bitbang_spi_release_bus();
return 0;
}
Index: flashrom-bitbang_spi_init_errorcheck_request_release_bus/nicintel_spi.c
===================================================================
--- flashrom-bitbang_spi_init_errorcheck_request_release_bus/nicintel_spi.c (Revision 1164)
+++ flashrom-bitbang_spi_init_errorcheck_request_release_bus/nicintel_spi.c (Arbeitskopie)
@@ -91,20 +91,10 @@
{
uint32_t tmp;
- /*
- * Requesting and releasing the SPI bus is handled in here to allow
- * the chipset to use its own SPI engine for native reads.
- */
- if (val == 0)
- nicintel_request_spibus();
-
tmp = pci_mmio_readl(nicintel_spibar + FLA);
tmp &= ~(1 << FL_CS);
tmp |= (val << FL_CS);
pci_mmio_writel(tmp, nicintel_spibar + FLA);
-
- if (val == 1)
- nicintel_release_spibus();
}
static void nicintel_bitbang_set_sck(int val)
@@ -142,6 +132,8 @@
.set_sck = nicintel_bitbang_set_sck,
.set_mosi = nicintel_bitbang_set_mosi,
.get_miso = nicintel_bitbang_get_miso,
+ .request_bus = nicintel_request_spibus,
+ .release_bus = nicintel_release_spibus,
};
int nicintel_spi_init(void)
Index: flashrom-bitbang_spi_init_errorcheck_request_release_bus/mcp6x_spi.c
===================================================================
--- flashrom-bitbang_spi_init_errorcheck_request_release_bus/mcp6x_spi.c (Revision 1164)
+++ flashrom-bitbang_spi_init_errorcheck_request_release_bus/mcp6x_spi.c (Arbeitskopie)
@@ -66,18 +66,9 @@
static void mcp6x_bitbang_set_cs(int val)
{
- /* Requesting and releasing the SPI bus is handled in here to allow the
- * chipset to use its own SPI engine for native reads.
- */
- if (val == 0)
- mcp6x_request_spibus();
-
mcp_gpiostate &= ~(1 << MCP6X_SPI_CS);
mcp_gpiostate |= (val << MCP6X_SPI_CS);
mmio_writeb(mcp_gpiostate, mcp6x_spibar + 0x530);
-
- if (val == 1)
- mcp6x_release_spibus();
}
static void mcp6x_bitbang_set_sck(int val)
@@ -106,6 +97,8 @@
.set_sck = mcp6x_bitbang_set_sck,
.set_mosi = mcp6x_bitbang_set_mosi,
.get_miso = mcp6x_bitbang_get_miso,
+ .request_bus = mcp6x_request_spibus,
+ .release_bus = mcp6x_release_spibus,
};
int mcp6x_spi_init(int want_spi)
Index: flashrom-bitbang_spi_init_errorcheck_request_release_bus/programmer.h
===================================================================
--- flashrom-bitbang_spi_init_errorcheck_request_release_bus/programmer.h (Revision 1164)
+++ flashrom-bitbang_spi_init_errorcheck_request_release_bus/programmer.h (Arbeitskopie)
@@ -131,6 +131,8 @@
void (*set_sck) (int val);
void (*set_mosi) (int val);
int (*get_miso) (void);
+ void (*request_bus) (void);
+ void (*release_bus) (void);
};
#if CONFIG_INTERNAL == 1
@@ -443,6 +445,7 @@
/* bitbang_spi.c */
int bitbang_spi_init(const struct bitbang_spi_master *master, int halfperiod);
+int bitbang_spi_shutdown(const struct bitbang_spi_master *master);
int bitbang_spi_send_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr);
int bitbang_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len);
int bitbang_spi_write_256(struct flashchip *flash, uint8_t *buf, int start, int len);
--
http://www.hailfinger.org/
Author: hailfinger
Date: Wed Sep 15 02:17:37 2010
New Revision: 1171
URL: http://flashrom.org/trac/flashrom/changeset/1171
Log:
SPI bitbanging: request/release bus.
SPI bitbanging on devices which speak SPI natively has a dual-use
problem: We need to shut down normal SPI operations to do the bitbanging
ourselves. Once we're done, it makes a lot of sense to reenable "normal"
SPI operations again. Add request_bus/release_bus functions to struct
bitbang_spi_master.
Add a bitbang shutdown function (not used yet).
Change MCP SPI and Intel NIC SPI to use the new request/release bus
infrastructure.
Cosmetic changes to a few error messages (80 column limit).
There are multiple possible strategies for bus request/release:
- Request at the start of a SPI command, release immediately afterwards.
- Request at the start of a SPI multicommand, release once all commands
of the multicommand are done.
- Request on programmer init, release on shutdown.
Each strategy has its own advantages. For now, we will stay with the
first strategy which worked fine so far.
Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006(a)gmx.net>
Acked-by: Uwe Hermann <uwe(a)hermann-uwe.de>
Modified:
trunk/bitbang_spi.c
trunk/mcp6x_spi.c
trunk/nicintel_spi.c
trunk/programmer.h
Modified: trunk/bitbang_spi.c
==============================================================================
--- trunk/bitbang_spi.c Wed Sep 15 02:13:02 2010 (r1170)
+++ trunk/bitbang_spi.c Wed Sep 15 02:17:37 2010 (r1171)
@@ -53,6 +53,18 @@
return bitbang_spi_master->get_miso();
}
+static void bitbang_spi_request_bus(void)
+{
+ if (bitbang_spi_master->request_bus)
+ bitbang_spi_master->request_bus();
+}
+
+static void bitbang_spi_release_bus(void)
+{
+ if (bitbang_spi_master->release_bus)
+ bitbang_spi_master->release_bus();
+}
+
int bitbang_spi_init(const struct bitbang_spi_master *master, int halfperiod)
{
/* BITBANG_SPI_INVALID is 0, so if someone forgot to initialize ->type,
@@ -61,19 +73,44 @@
*/
if (!master || master->type == BITBANG_SPI_INVALID || !master->set_cs ||
!master->set_sck || !master->set_mosi || !master->get_miso) {
- msg_perr("Incomplete bitbanging SPI master setting! Please "
- "report a bug at flashrom(a)flashrom.org\n");
+ msg_perr("Incomplete SPI bitbang master setting!\n"
+ "Please report a bug at flashrom(a)flashrom.org\n");
+ return 1;
+ }
+ if (bitbang_spi_master) {
+ msg_perr("SPI bitbang master already initialized!\n"
+ "Please report a bug at flashrom(a)flashrom.org\n");
return 1;
}
+
bitbang_spi_master = master;
bitbang_spi_half_period = halfperiod;
+ /* FIXME: Run bitbang_spi_request_bus here or in programmer init? */
bitbang_spi_set_cs(1);
bitbang_spi_set_sck(0);
bitbang_spi_set_mosi(0);
return 0;
}
+int bitbang_spi_shutdown(const struct bitbang_spi_master *master)
+{
+ if (!bitbang_spi_master) {
+ msg_perr("Shutting down an uninitialized SPI bitbang master!\n"
+ "Please report a bug at flashrom(a)flashrom.org\n");
+ return 1;
+ }
+ if (master != bitbang_spi_master) {
+ msg_perr("Shutting down a mismatched SPI bitbang master!\n"
+ "Please report a bug at flashrom(a)flashrom.org\n");
+ return 1;
+ }
+
+ /* FIXME: Run bitbang_spi_release_bus here or per command? */
+ bitbang_spi_master = NULL;
+ return 0;
+}
+
static uint8_t bitbang_spi_readwrite_byte(uint8_t val)
{
uint8_t ret = 0;
@@ -96,6 +133,11 @@
{
int i;
+ /* FIXME: Run bitbang_spi_request_bus here or in programmer init?
+ * Requesting and releasing the SPI bus is handled in here to allow the
+ * programmer to use its own SPI engine for native accesses.
+ */
+ bitbang_spi_request_bus();
bitbang_spi_set_cs(0);
for (i = 0; i < writecnt; i++)
bitbang_spi_readwrite_byte(writearr[i]);
@@ -105,6 +147,8 @@
programmer_delay(bitbang_spi_half_period);
bitbang_spi_set_cs(1);
programmer_delay(bitbang_spi_half_period);
+ /* FIXME: Run bitbang_spi_release_bus here or in programmer init? */
+ bitbang_spi_release_bus();
return 0;
}
Modified: trunk/mcp6x_spi.c
==============================================================================
--- trunk/mcp6x_spi.c Wed Sep 15 02:13:02 2010 (r1170)
+++ trunk/mcp6x_spi.c Wed Sep 15 02:17:37 2010 (r1171)
@@ -66,18 +66,9 @@
static void mcp6x_bitbang_set_cs(int val)
{
- /* Requesting and releasing the SPI bus is handled in here to allow the
- * chipset to use its own SPI engine for native reads.
- */
- if (val == 0)
- mcp6x_request_spibus();
-
mcp_gpiostate &= ~(1 << MCP6X_SPI_CS);
mcp_gpiostate |= (val << MCP6X_SPI_CS);
mmio_writeb(mcp_gpiostate, mcp6x_spibar + 0x530);
-
- if (val == 1)
- mcp6x_release_spibus();
}
static void mcp6x_bitbang_set_sck(int val)
@@ -106,6 +97,8 @@
.set_sck = mcp6x_bitbang_set_sck,
.set_mosi = mcp6x_bitbang_set_mosi,
.get_miso = mcp6x_bitbang_get_miso,
+ .request_bus = mcp6x_request_spibus,
+ .release_bus = mcp6x_release_spibus,
};
int mcp6x_spi_init(int want_spi)
Modified: trunk/nicintel_spi.c
==============================================================================
--- trunk/nicintel_spi.c Wed Sep 15 02:13:02 2010 (r1170)
+++ trunk/nicintel_spi.c Wed Sep 15 02:17:37 2010 (r1171)
@@ -91,20 +91,10 @@
{
uint32_t tmp;
- /*
- * Requesting and releasing the SPI bus is handled in here to allow
- * the chipset to use its own SPI engine for native reads.
- */
- if (val == 0)
- nicintel_request_spibus();
-
tmp = pci_mmio_readl(nicintel_spibar + FLA);
tmp &= ~(1 << FL_CS);
tmp |= (val << FL_CS);
pci_mmio_writel(tmp, nicintel_spibar + FLA);
-
- if (val == 1)
- nicintel_release_spibus();
}
static void nicintel_bitbang_set_sck(int val)
@@ -142,6 +132,8 @@
.set_sck = nicintel_bitbang_set_sck,
.set_mosi = nicintel_bitbang_set_mosi,
.get_miso = nicintel_bitbang_get_miso,
+ .request_bus = nicintel_request_spibus,
+ .release_bus = nicintel_release_spibus,
};
int nicintel_spi_init(void)
Modified: trunk/programmer.h
==============================================================================
--- trunk/programmer.h Wed Sep 15 02:13:02 2010 (r1170)
+++ trunk/programmer.h Wed Sep 15 02:17:37 2010 (r1171)
@@ -131,6 +131,8 @@
void (*set_sck) (int val);
void (*set_mosi) (int val);
int (*get_miso) (void);
+ void (*request_bus) (void);
+ void (*release_bus) (void);
};
#if CONFIG_INTERNAL == 1
@@ -443,6 +445,7 @@
/* bitbang_spi.c */
int bitbang_spi_init(const struct bitbang_spi_master *master, int halfperiod);
+int bitbang_spi_shutdown(const struct bitbang_spi_master *master);
int bitbang_spi_send_command(unsigned int writecnt, unsigned int readcnt, const unsigned char *writearr, unsigned char *readarr);
int bitbang_spi_read(struct flashchip *flash, uint8_t *buf, int start, int len);
int bitbang_spi_write_256(struct flashchip *flash, uint8_t *buf, int start, int len);
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(a)gmx.net>
Index: flashrom-ichspi_read_use_min_addr/spi.c
===================================================================
--- flashrom-ichspi_read_use_min_addr/spi.c (Revision 1165)
+++ flashrom-ichspi_read_use_min_addr/spi.c (Arbeitskopie)
@@ -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 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 @@
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);
}
/*
--
http://www.hailfinger.org/
Author: hailfinger
Date: Wed Sep 15 02:13:02 2010
New Revision: 1170
URL: http://flashrom.org/trac/flashrom/changeset/1170
Log:
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(a)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(a)google.com>
Modified:
trunk/spi.c
Modified: trunk/spi.c
==============================================================================
--- trunk/spi.c Wed Sep 15 02:03:53 2010 (r1169)
+++ trunk/spi.c Wed Sep 15 02:13:02 2010 (r1170)
@@ -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 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 @@
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);
}
/*
Same as version 3, but do not rearrange order of chip definitions in
flashchips.c for easier review.
List all chip variants in the .name strings in flashchips.c
Also have two identical entries for Winbond
W29C010(M)/W29C011A/W29EE011/W29EE012 with different probe functions
in flashchips.c as sometimes (for newer revisions of these chips?) the
standard jedec probe seems to work. Eg see test report here:
http://patchwork.coreboot.org/patch/1476/
Rename constants
W_nnnn -> WINBOND_Wnnnn
W_25nnn -> WINBOND_NEX_W25nnn
Kill incorrect ASD chip and vendor id.
Group Winbond SPI and Parallell chips separately (they have different
vendor ids).
Change constant names to the "canonical" chip name for the following
ids:
W_29C020C (0x45)
-> WINBOND_W29C020 (Same as W29C020C, W29C022 and ASD AE29F2008)
W_29C040P (0x46)
-> WINBOND_W29C040 ("P" is for package type [32-pin PLCC], irrelevant)
W_29C011 + W_29EE011 (0xC1)
-> WINBOND_W29C010M (Same as W29C011A, W29EE011, W29EE012, and ASD AE29F1008)
Also add ids for the following Winbond chips:
W25Q40
W25Q128
W19B160BB
W19B160BT
W19B320SB/W19L320SB
W19B320ST/W19L320ST
W19B322MB
W19B322MT
W19B323MB
W19B323MT
W19B324MB
W19B324MT
W29C512A/W29EE512
W39L010
W39L040A
W39L512
W49F002/W49F002B
Signed-off-by: Mattias Mattsson <vitplister(a)gmail.com>