Revert MMIO space writes on shutdown as needed

Reversible MMIO space writes now use rmmio_write*().
Reversible PCI MMIO space writes now use pci_rmmio_write*().
If a MMIO value needs to be queued for restore without writing it,
use rmmio_val*().
MMIO space writes which are one-shot (e.g. communication with some chip)
should continue to use the permanent mmio_write* variants.

Corresponding to flashrom svn r1292.

Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>

David tested it successfully on some NM10/ICH7 platforms which switch
between SPI and LPC targets (x86 BIOS ROM vs. EC firmware ROM).

Acked-by: David Hendricks <dhendrix@google.com>
diff --git a/ichspi.c b/ichspi.c
index 78c5422..f2814d1 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -163,7 +163,7 @@
 static int find_opcode(OPCODES *op, uint8_t opcode);
 static int find_preop(OPCODES *op, uint8_t preop);
 static int generate_opcodes(OPCODES * op);
-static int program_opcodes(OPCODES * op);
+static int program_opcodes(OPCODES *op, int enable_undo);
 static int run_opcode(OPCODE op, uint32_t offset,
 		      uint8_t datalength, uint8_t * data);
 
@@ -269,7 +269,7 @@
 		int oppos=2;	// use original JEDEC_BE_D8 offset
 		curopcodes->opcode[oppos].opcode = opcode;
 		curopcodes->opcode[oppos].spi_type = spi_type;
-		program_opcodes(curopcodes);
+		program_opcodes(curopcodes, 0);
 		oppos = find_opcode(curopcodes, opcode);
 		msg_pdbg ("on-the-fly OPCODE (0x%02X) re-programmed, op-pos=%d\n", opcode, oppos);
 		return oppos;
@@ -357,7 +357,7 @@
 	return 0;
 }
 
-int program_opcodes(OPCODES * op)
+static int program_opcodes(OPCODES *op, int enable_undo)
 {
 	uint8_t a;
 	uint16_t preop, optype;
@@ -391,16 +391,30 @@
 	switch (spi_controller) {
 	case SPI_CONTROLLER_ICH7:
 	case SPI_CONTROLLER_VIA:
-		REGWRITE16(ICH7_REG_PREOP, preop);
-		REGWRITE16(ICH7_REG_OPTYPE, optype);
-		REGWRITE32(ICH7_REG_OPMENU, opmenu[0]);
-		REGWRITE32(ICH7_REG_OPMENU + 4, opmenu[1]);
+		/* Register undo only for enable_undo=1, i.e. first call. */
+		if (enable_undo) {
+			rmmio_valw(ich_spibar + ICH7_REG_PREOP);
+			rmmio_valw(ich_spibar + ICH7_REG_OPTYPE);
+			rmmio_vall(ich_spibar + ICH7_REG_OPMENU);
+			rmmio_vall(ich_spibar + ICH7_REG_OPMENU + 4);
+		}
+		mmio_writew(preop, ich_spibar + ICH7_REG_PREOP);
+		mmio_writew(optype, ich_spibar + ICH7_REG_OPTYPE);
+		mmio_writel(opmenu[0], ich_spibar + ICH7_REG_OPMENU);
+		mmio_writel(opmenu[1], ich_spibar + ICH7_REG_OPMENU + 4);
 		break;
 	case SPI_CONTROLLER_ICH9:
-		REGWRITE16(ICH9_REG_PREOP, preop);
-		REGWRITE16(ICH9_REG_OPTYPE, optype);
-		REGWRITE32(ICH9_REG_OPMENU, opmenu[0]);
-		REGWRITE32(ICH9_REG_OPMENU + 4, opmenu[1]);
+		/* Register undo only for enable_undo=1, i.e. first call. */
+		if (enable_undo) {
+			rmmio_valw(ich_spibar + ICH9_REG_PREOP);
+			rmmio_valw(ich_spibar + ICH9_REG_OPTYPE);
+			rmmio_vall(ich_spibar + ICH9_REG_OPMENU);
+			rmmio_vall(ich_spibar + ICH9_REG_OPMENU + 4);
+		}
+		mmio_writew(preop, ich_spibar + ICH9_REG_PREOP);
+		mmio_writew(optype, ich_spibar + ICH9_REG_OPTYPE);
+		mmio_writel(opmenu[0], ich_spibar + ICH9_REG_OPMENU);
+		mmio_writel(opmenu[1], ich_spibar + ICH9_REG_OPMENU + 4);
 		break;
 	default:
 		msg_perr("%s: unsupported chipset\n", __func__);
@@ -426,9 +440,11 @@
 			msg_pdbg("Reserved bits in BBAR not zero: 0x%04x",
 				 ichspi_bbar);
 		ichspi_bbar |= minaddr;
-		mmio_writel(ichspi_bbar, ich_spibar + 0x50);
+		rmmio_writel(ichspi_bbar, ich_spibar + 0x50);
 		ichspi_bbar = mmio_readl(ich_spibar + 0x50);
-		/* We don't have any option except complaining. */
+		/* We don't have any option except complaining. And if the write
+		 * failed, the restore will fail as well, so no problem there.
+		 */
 		if (ichspi_bbar != minaddr)
 			msg_perr("Setting BBAR failed!\n");
 		break;
@@ -438,9 +454,11 @@
 			msg_pdbg("Reserved bits in BBAR not zero: 0x%04x",
 				 ichspi_bbar);
 		ichspi_bbar |= minaddr;
-		mmio_writel(ichspi_bbar, ich_spibar + 0xA0);
+		rmmio_writel(ichspi_bbar, ich_spibar + 0xA0);
 		ichspi_bbar = mmio_readl(ich_spibar + 0xA0);
-		/* We don't have any option except complaining. */
+		/* We don't have any option except complaining. And if the write
+		 * failed, the restore will fail as well, so no problem there.
+		 */
 		if (ichspi_bbar != minaddr)
 			msg_perr("Setting BBAR failed!\n");
 		break;
@@ -470,7 +488,7 @@
 	} else {
 		msg_pdbg("Programming OPCODES... ");
 		curopcodes_done = &O_ST_M25P;
-		rc = program_opcodes(curopcodes_done);
+		rc = program_opcodes(curopcodes_done, 1);
 		/* Technically not part of opcode init, but it allows opcodes
 		 * to run without transaction errors by setting the lowest
 		 * allowed address to zero.