spi: fix erase in SMM while SPIBAR is locked

The handling of write enable was not entirely correct,
the opcode needs to be skipped when the controller is
locked down.

Addresses were not getting set properly for erase commands
which seemed to mostly work when the previous command had
set an address.

Tested by adding events to the event log at runtime on a
freslhy flashed device (with locked down SPI controller)
until the log log shrink happens to ensure it does not hang:

hexdump -C elog.event.kernel_clean
00000000  01 00 00 00 ad de 00 00  00 00

for x in $(seq 1 232); do
 cat elog.event.kernel_clean > /sys/firmware/gsmi/append_to_eventlog
done

mosys eventlog list | tail -6
154 | 2012-09-01 13:54:43 | Kernel Event | Clean Shutdown
155 | 2012-09-01 13:54:43 | Kernel Event | Clean Shutdown
156 | 2012-09-01 13:54:43 | Kernel Event | Clean Shutdown
157 | 2012-09-01 13:54:43 | Kernel Event | Clean Shutdown
158 | 2012-09-01 13:54:43 | Log area cleared | 1030
159 | 2012-09-01 13:54:43 | Kernel Event | Clean Shutdown

Change-Id: I3a50dae54422a9ff37daefce3632f8bcbe4eb89f
Signed-off-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: http://review.coreboot.org/1717
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
Duncan Laurie 2012-09-01 13:44:17 -07:00 committed by Stefan Reinauer
parent 00ba25decb
commit 3beb6db6dd
1 changed files with 7 additions and 2 deletions

View File

@ -627,13 +627,14 @@ int spi_xfer(struct spi_slave *slave, const void *dout,
if ((with_address = spi_setup_offset(&trans)) < 0)
return -1;
if (!ichspi_lock && trans.opcode == SPI_OPCODE_WREN) {
if (trans.opcode == SPI_OPCODE_WREN) {
/*
* Treat Write Enable as Atomic Pre-Op if possible
* in order to prevent the Management Engine from
* issuing a transaction between WREN and DATA.
*/
writew_(trans.opcode, cntlr.preop);
if (!ichspi_lock)
writew_(trans.opcode, cntlr.preop);
return 0;
}
@ -645,6 +646,10 @@ int spi_xfer(struct spi_slave *slave, const void *dout,
control |= SPIC_ACS;
if (!trans.bytesout && !trans.bytesin) {
/* SPI addresses are 24 bit only */
if (with_address)
writel_(trans.offset & 0x00FFFFFF, cntlr.addr);
/*
* This is a 'no data' command (like Write Enable), its
* bitesout size was 1, decremented to zero while executing