From 54ce73a1f5c7ddecc7579c136dbac9c2c201b621 Mon Sep 17 00:00:00 2001 From: Carl-Daniel Hailfinger Date: Tue, 3 May 2011 21:49:41 +0000 Subject: 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 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 --- ichspi.c | 50 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 16 deletions(-) (limited to 'ichspi.c') diff --git a/ichspi.c b/ichspi.c index 78c54227..f2814d1b 100644 --- a/ichspi.c +++ b/ichspi.c @@ -163,7 +163,7 @@ static uint16_t REGREAD8(int X) 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 @@ static int reprogram_opcode_on_the_fly(uint8_t opcode, unsigned int writecnt, un 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 @@ static int generate_opcodes(OPCODES * op) 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 @@ int program_opcodes(OPCODES * op) 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 @@ void ich_set_bbar(uint32_t minaddr) 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 @@ void ich_set_bbar(uint32_t minaddr) 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 @@ static int ich_init_opcodes(void) } 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. -- cgit v1.2.3