New version with a few bugfixes and better comments:
- Do not use reversible writes for on-the-fly opcode menu reprogramming
- Add reversible PCI MMIO writes

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.

Signed-off-by: Carl-Daniel Hailfinger<[email protected]>

Patch attached because Seamonkey started to mangle patches.

--
http://www.hailfinger.org/

Index: flashrom-mmio_shutdown_restore/hwaccess.c
===================================================================
--- flashrom-mmio_shutdown_restore/hwaccess.c   (Revision 1289)
+++ flashrom-mmio_shutdown_restore/hwaccess.c   (Arbeitskopie)
@@ -184,3 +184,104 @@
 {
        return le_to_cpu32(mmio_readl(addr));
 }
+
+enum mmio_write_type {
+       mmio_write_type_b,
+       mmio_write_type_w,
+       mmio_write_type_l,
+};
+
+struct undo_mmio_write_data {
+       void *addr;
+       int reg;
+       enum mmio_write_type type;
+       union {
+               uint8_t bdata;
+               uint16_t wdata;
+               uint32_t ldata;
+       };
+};
+
+void undo_mmio_write(void *p)
+{
+       struct undo_mmio_write_data *data = p;
+       msg_pdbg("Restoring MMIO space at %p\n", data->addr);
+       switch (data->type) {
+       case mmio_write_type_b:
+               mmio_writeb(data->bdata, data->addr);
+               break;
+       case mmio_write_type_w:
+               mmio_writew(data->wdata, data->addr);
+               break;
+       case mmio_write_type_l:
+               mmio_writel(data->ldata, data->addr);
+               break;
+       }
+       /* p was allocated in register_undo_mmio_write. */
+       free(p);
+}
+
+#define register_undo_mmio_write(a, c)                                 \
+{                                                                      \
+       struct undo_mmio_write_data *undo_mmio_write_data;              \
+       undo_mmio_write_data = malloc(sizeof(struct undo_mmio_write_data)); \
+       undo_mmio_write_data->addr = a;                                 \
+       undo_mmio_write_data->type = mmio_write_type_##c;               \
+       undo_mmio_write_data->c##data = mmio_read##c(a);                \
+       register_shutdown(undo_mmio_write, undo_mmio_write_data);       \
+}
+
+#define register_undo_mmio_writeb(a) register_undo_mmio_write(a, b)
+#define register_undo_mmio_writew(a) register_undo_mmio_write(a, w)
+#define register_undo_mmio_writel(a) register_undo_mmio_write(a, l)
+
+void rmmio_writeb(uint8_t val, void *addr)
+{
+       register_undo_mmio_writeb(addr);
+       mmio_writeb(val, addr);
+}
+
+void rmmio_writew(uint16_t val, void *addr)
+{
+       register_undo_mmio_writew(addr);
+       mmio_writew(val, addr);
+}
+
+void rmmio_writel(uint32_t val, void *addr)
+{
+       register_undo_mmio_writel(addr);
+       mmio_writel(val, addr);
+}
+
+void rmmio_le_writeb(uint8_t val, void *addr)
+{
+       register_undo_mmio_writeb(addr);
+       mmio_le_writeb(val, addr);
+}
+
+void rmmio_le_writew(uint16_t val, void *addr)
+{
+       register_undo_mmio_writew(addr);
+       mmio_le_writew(val, addr);
+}
+
+void rmmio_le_writel(uint32_t val, void *addr)
+{
+       register_undo_mmio_writel(addr);
+       mmio_le_writel(val, addr);
+}
+
+void rmmio_valb(void *addr)
+{
+       register_undo_mmio_writeb(addr);
+}
+
+void rmmio_valw(void *addr)
+{
+       register_undo_mmio_writew(addr);
+}
+
+void rmmio_vall(void *addr)
+{
+       register_undo_mmio_writel(addr);
+}
Index: flashrom-mmio_shutdown_restore/satamv.c
===================================================================
--- flashrom-mmio_shutdown_restore/satamv.c     (Revision 1289)
+++ flashrom-mmio_shutdown_restore/satamv.c     (Arbeitskopie)
@@ -102,8 +102,7 @@
        msg_pspew("BAR2Sz=0x%01x\n", (tmp >> 19) & 0x7);
        tmp &= 0xffffffc0;
        tmp |= 0x0000001f;
-       /* FIXME: This needs to be an auto-reversible write. */
-       pci_mmio_writel(tmp, mv_bar + PCI_BAR2_CONTROL);
+       pci_rmmio_writel(tmp, mv_bar + PCI_BAR2_CONTROL);
 
        /* Enable flash: GPIO Port Control Register 0x104f0 */
        tmp = pci_mmio_readl(mv_bar + GPIO_PORT_CONTROL);
@@ -114,8 +113,7 @@
                          "values!\n");
        tmp &= 0xfffffffc;
        tmp |= 0x2;
-       /* FIXME: This needs to be an auto-reversible write. */
-       pci_mmio_writel(tmp, mv_bar + GPIO_PORT_CONTROL);
+       pci_rmmio_writel(tmp, mv_bar + GPIO_PORT_CONTROL);
 
        /* Get I/O BAR location. */
        tmp = pci_read_long(pcidev_dev, PCI_BASE_ADDRESS_2) &
Index: flashrom-mmio_shutdown_restore/ichspi.c
===================================================================
--- flashrom-mmio_shutdown_restore/ichspi.c     (Revision 1289)
+++ flashrom-mmio_shutdown_restore/ichspi.c     (Arbeitskopie)
@@ -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.
Index: flashrom-mmio_shutdown_restore/nicintel_spi.c
===================================================================
--- flashrom-mmio_shutdown_restore/nicintel_spi.c       (Revision 1289)
+++ flashrom-mmio_shutdown_restore/nicintel_spi.c       (Arbeitskopie)
@@ -148,6 +148,11 @@
 
        nicintel_spibar = physmap("Intel Gigabit NIC w/ SPI flash",
                                  io_base_addr, 4096);
+       /* Automatic restore of EECD on shutdown is not possible because EECD
+        * does not only contain FLASH_WRITES_DISABLED|FLASH_WRITES_ENABLED,
+        * but other bits with side effects as well. Those other bits must be
+        * left untouched.
+        */
        tmp = pci_mmio_readl(nicintel_spibar + EECD);
        tmp &= ~FLASH_WRITES_DISABLED;
        tmp |= FLASH_WRITES_ENABLED;
@@ -167,6 +172,9 @@
 {
        uint32_t tmp;
 
+       /* Disable writes manually. See the comment about EECD in
+        * nicintel_spi_init() for details.
+        */
        tmp = pci_mmio_readl(nicintel_spibar + EECD);
        tmp &= ~FLASH_WRITES_ENABLED;
        tmp |= FLASH_WRITES_DISABLED;
Index: flashrom-mmio_shutdown_restore/programmer.h
===================================================================
--- flashrom-mmio_shutdown_restore/programmer.h (Revision 1289)
+++ flashrom-mmio_shutdown_restore/programmer.h (Arbeitskopie)
@@ -316,6 +316,18 @@
 #define pci_mmio_readb mmio_le_readb
 #define pci_mmio_readw mmio_le_readw
 #define pci_mmio_readl mmio_le_readl
+void rmmio_writeb(uint8_t val, void *addr);
+void rmmio_writew(uint16_t val, void *addr);
+void rmmio_writel(uint32_t val, void *addr);
+void rmmio_le_writeb(uint8_t val, void *addr);
+void rmmio_le_writew(uint16_t val, void *addr);
+void rmmio_le_writel(uint32_t val, void *addr);
+#define pci_rmmio_writeb rmmio_le_writeb
+#define pci_rmmio_writew rmmio_le_writew
+#define pci_rmmio_writel rmmio_le_writel
+void rmmio_valb(void *addr);
+void rmmio_valw(void *addr);
+void rmmio_vall(void *addr);
 
 /* programmer.c */
 int noop_shutdown(void);
_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to