summaryrefslogtreecommitdiffstats
path: root/hwaccess.c
diff options
context:
space:
mode:
authorCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>2011-05-03 21:49:41 +0000
committerCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>2011-05-03 21:49:41 +0000
commit20c9ed251c13ab15014c75a0e313cc6935e4bf55 (patch)
treef24b7ce88dfdedbb3388cb3f6e4e44ee4e9f15f0 /hwaccess.c
parente34778ab8b00f25d152a9b7d5beb3e5fc9f2d012 (diff)
downloadflashrom-20c9ed251c13ab15014c75a0e313cc6935e4bf55.zip
flashrom-20c9ed251c13ab15014c75a0e313cc6935e4bf55.tar.gz
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. David tested it successfully on some NM10/ICH7 platforms which switch between SPI and LPC targets (x86 BIOS ROM vs. EC firmware ROM). Corresponding to flashrom svn r1292. Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> Acked-by: David Hendricks <dhendrix@google.com>
Diffstat (limited to 'hwaccess.c')
-rw-r--r--hwaccess.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/hwaccess.c b/hwaccess.c
index bbb91a6..3c4f07a 100644
--- a/hwaccess.c
+++ b/hwaccess.c
@@ -184,3 +184,104 @@ uint32_t mmio_le_readl(void *addr)
{
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);
+}
OpenPOWER on IntegriCloud