Luc Verhaegen has uploaded this change for review. ( https://review.coreboot.org/29087
Change subject: ati: add save/restore ......................................................................
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; }