Luc Verhaegen has uploaded this change for review.

View Change

ati: add save/restore

Change-Id: I392c3ecc07facdeb2454ec1702bd277f7ebbf50d
Signed-off-by: Luc Verhaegen <libv@skynet.be>
---
M ati_spi.c
1 file changed, 141 insertions(+), 0 deletions(-)

git pull ssh://review.coreboot.org:29418/flashrom refs/changes/87/29087/1
diff --git a/ati_spi.c b/ati_spi.c
index 2db0681..97c056a 100644
--- a/ati_spi.c
+++ b/ati_spi.c
@@ -17,15 +17,137 @@
* This adds support for the ATI/AMD Radeon SPI interfaces.
*/

+#include <stdlib.h>
+
#include "programmer.h"
#include "spi.h"

+/* improve readability */
+#define mmio_read(reg) flashrom_pci_mmio_long_read(device, (reg))
+#define mmio_write(reg, val) flashrom_pci_mmio_long_write(device, (reg), (val))
+#define mmio_mask(reg, val, mask) flashrom_pci_mmio_long_mask(device, (reg), (val), (mask))
+
struct ati_spi_pci_private {
int io_bar;
+
+ int (*save) (struct flashrom_pci_device *device);
+ int (*restore) (struct flashrom_pci_device *device);
};

+#define R600_GENERAL_PWRMGT 0x0618
+
+#define R600_LOWER_GPIO_ENABLE 0x0710
+#define R600_CTXSW_VID_LOWER_GPIO_CNTL 0x0718
+#define R600_HIGH_VID_LOWER_GPIO_CNTL 0x071c
+#define R600_MEDIUM_VID_LOWER_GPIO_CNTL 0x0720
+#define R600_LOW_VID_LOWER_GPIO_CNTL 0x0724
+
+#define R600_ROM_CNTL 0x1600
+
+#define R600_GPIOPAD_MASK 0x1798
+#define R600_GPIOPAD_A 0x179C
+#define R600_GPIOPAD_EN 0x17A0
+
+struct r600_spi_data {
+ uint32_t reg_general_pwrmgt;
+ uint32_t reg_lower_gpio_enable;
+ uint32_t reg_ctxsw_vid_lower_gpio_cntl;
+ uint32_t reg_high_vid_lower_gpio_cntl;
+ uint32_t reg_medium_vid_lower_gpio_cntl;
+ uint32_t reg_low_vid_lower_gpio_cntl;
+
+ uint32_t reg_rom_cntl;
+ uint32_t reg_gpiopad_mask;
+ uint32_t reg_gpiopad_a;
+ uint32_t reg_gpiopad_en;
+};
+
+/*
+ * Save for later restore.
+ */
+static int
+r600_spi_save(struct flashrom_pci_device *device)
+{
+ struct r600_spi_data *data;
+
+ msg_pdbg("%s();\n", __func__);
+
+ if (device->private_data) {
+ msg_perr("%s: device->private_data is already assigned.\n",
+ __func__);
+ return -1;
+ }
+
+ data = calloc(1, sizeof(struct r600_spi_data));
+
+ data->reg_general_pwrmgt = mmio_read(R600_GENERAL_PWRMGT);
+
+ data->reg_lower_gpio_enable = mmio_read(R600_LOWER_GPIO_ENABLE);
+ data->reg_ctxsw_vid_lower_gpio_cntl =
+ mmio_read(R600_CTXSW_VID_LOWER_GPIO_CNTL);
+ data->reg_high_vid_lower_gpio_cntl =
+ mmio_read(R600_HIGH_VID_LOWER_GPIO_CNTL);
+ data->reg_medium_vid_lower_gpio_cntl =
+ mmio_read(R600_MEDIUM_VID_LOWER_GPIO_CNTL);
+ data->reg_low_vid_lower_gpio_cntl =
+ mmio_read(R600_LOW_VID_LOWER_GPIO_CNTL);
+
+ data->reg_rom_cntl = mmio_read(R600_ROM_CNTL);
+
+ data->reg_gpiopad_mask = mmio_read(R600_GPIOPAD_MASK);
+ data->reg_gpiopad_a = mmio_read(R600_GPIOPAD_A);
+ data->reg_gpiopad_en = mmio_read(R600_GPIOPAD_EN);
+
+ device->private_data = data;
+
+ return 0;
+}
+
+/*
+ * Restore saved registers, in the order of enable writes.
+ */
+static int
+r600_spi_restore(struct flashrom_pci_device *device)
+{
+ struct r600_spi_data *data = device->private_data;
+
+ msg_pdbg("%s();\n", __func__);
+
+ if (!data) {
+ msg_perr("%s: device->private_data is not assigned.\n",
+ __func__);
+ return -1;
+ }
+
+ mmio_write(R600_ROM_CNTL, data->reg_rom_cntl);
+
+ mmio_write(R600_GPIOPAD_A, data->reg_gpiopad_a);
+ mmio_write(R600_GPIOPAD_EN, data->reg_gpiopad_en);
+ mmio_write(R600_GPIOPAD_MASK, data->reg_gpiopad_mask);
+
+ mmio_write(R600_GENERAL_PWRMGT, data->reg_general_pwrmgt);
+
+ mmio_write(R600_CTXSW_VID_LOWER_GPIO_CNTL,
+ data->reg_ctxsw_vid_lower_gpio_cntl);
+ mmio_write(R600_HIGH_VID_LOWER_GPIO_CNTL,
+ data->reg_high_vid_lower_gpio_cntl);
+ mmio_write(R600_MEDIUM_VID_LOWER_GPIO_CNTL,
+ data->reg_medium_vid_lower_gpio_cntl);
+ mmio_write(R600_LOW_VID_LOWER_GPIO_CNTL,
+ data->reg_low_vid_lower_gpio_cntl);
+
+ mmio_write(R600_LOWER_GPIO_ENABLE, data->reg_lower_gpio_enable);
+
+ free(data);
+ device->private_data = NULL;
+
+ return 0;
+}
+
static const struct ati_spi_pci_private r600_spi_pci_private = {
.io_bar = 2,
+ .save = r600_spi_save,
+ .restore = r600_spi_restore,
};

const struct flashrom_pci_match ati_spi_pci_devices[] = {
@@ -33,11 +155,24 @@
{},
};

+/*
+ *
+ */
+static int
+ati_spi_shutdown(void *data)
+{
+ struct flashrom_pci_device *device = data;
+ const struct ati_spi_pci_private *private = device->private;
+
+ return private->restore(device);
+}
+
int
ati_spi_init(void)
{
struct flashrom_pci_device *device;
const struct ati_spi_pci_private *private;
+ int ret;

device = flashrom_pci_init(ati_spi_pci_devices);
if (!device)
@@ -48,5 +183,11 @@
if (flashrom_pci_mmio_map(device, private->io_bar))
return 1;

+ register_shutdown(ati_spi_shutdown, device);
+
+ ret = private->save(device);
+ if (ret)
+ return ret;
+
return 0;
}

To view, visit change 29087. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I392c3ecc07facdeb2454ec1702bd277f7ebbf50d
Gerrit-Change-Number: 29087
Gerrit-PatchSet: 1
Gerrit-Owner: Luc Verhaegen <libv@skynet.be>