blob: f9ce4a79f5dbe85e530b7ba48335c050c4e8b437 [file] [log] [blame]
Kyösti Mälkki90a54b02015-05-24 09:06:03 +03001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2012 Advanced Micro Devices, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc.
18 */
19
20#include <spi-generic.h>
21#include <spi_flash.h>
22#include <string.h>
Kyösti Mälkkif7284082015-05-26 10:12:45 +030023#include <cbmem.h>
Kyösti Mälkki90a54b02015-05-24 09:06:03 +030024#include <cpu/amd/agesa/s3_resume.h>
Kyösti Mälkki300cace2014-12-16 19:50:47 +020025#include <northbridge/amd/agesa/agesawrapper.h>
26#include <AGESA.h>
27
28typedef enum {
29 S3DataTypeNonVolatile=0, ///< NonVolatile Data Type
Kyösti Mälkki300cace2014-12-16 19:50:47 +020030 S3DataTypeMTRR ///< MTRR storage
31} S3_DATA_TYPE;
Kyösti Mälkki90a54b02015-05-24 09:06:03 +030032
33/* The size needs to be 4k aligned, which is the sector size of most flashes. */
Kyösti Mälkki90a54b02015-05-24 09:06:03 +030034#define S3_DATA_MTRR_SIZE 0x1000
35#define S3_DATA_NONVOLATILE_SIZE 0x1000
36
37#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME) && \
Kyösti Mälkkic74b53f2015-05-26 15:38:58 +030038 (S3_DATA_MTRR_SIZE + S3_DATA_NONVOLATILE_SIZE) > CONFIG_S3_DATA_SIZE
Kyösti Mälkki90a54b02015-05-24 09:06:03 +030039#error "Please increase the value of S3_DATA_SIZE"
40#endif
41
Stefan Reinauer29e65482015-06-18 01:18:09 -070042static void get_s3nv_data(S3_DATA_TYPE S3DataType, uintptr_t *pos, uintptr_t *len)
Kyösti Mälkki90a54b02015-05-24 09:06:03 +030043{
44 /* FIXME: Find file from CBFS. */
45 u32 s3_data = CONFIG_S3_DATA_POS;
46
47 switch (S3DataType) {
Kyösti Mälkki90a54b02015-05-24 09:06:03 +030048 case S3DataTypeMTRR:
Kyösti Mälkkic74b53f2015-05-26 15:38:58 +030049 *pos = s3_data;
Kyösti Mälkki90a54b02015-05-24 09:06:03 +030050 *len = S3_DATA_MTRR_SIZE;
51 break;
52 case S3DataTypeNonVolatile:
Kyösti Mälkkic74b53f2015-05-26 15:38:58 +030053 *pos = s3_data + S3_DATA_MTRR_SIZE;
Kyösti Mälkki90a54b02015-05-24 09:06:03 +030054 *len = S3_DATA_NONVOLATILE_SIZE;
55 break;
56 default:
57 *pos = 0;
58 *len = 0;
59 break;
60 }
61}
62
Kyösti Mälkki300cace2014-12-16 19:50:47 +020063#if defined(__PRE_RAM__)
64
65AGESA_STATUS OemInitResume(AMD_RESUME_PARAMS *ResumeParams)
66{
67 AMD_S3_PARAMS *dataBlock = &ResumeParams->S3DataBlock;
Stefan Reinauer29e65482015-06-18 01:18:09 -070068 uintptr_t pos, size;
Kyösti Mälkki300cace2014-12-16 19:50:47 +020069
70 get_s3nv_data(S3DataTypeNonVolatile, &pos, &size);
71
72 /* TODO: Our NvStorage is really const. */
73 dataBlock->NvStorageSize = *(UINT32 *) pos;
74 dataBlock->NvStorage = (void *) (pos + sizeof(UINT32));
75 return AGESA_SUCCESS;
76}
77
78AGESA_STATUS OemS3LateRestore(AMD_S3LATE_PARAMS *S3LateParams)
79{
80 AMD_S3_PARAMS *dataBlock = &S3LateParams->S3DataBlock;
Kyösti Mälkkib1fcbf32015-05-26 11:25:13 +030081 void *dst;
82 size_t len;
Kyösti Mälkki300cace2014-12-16 19:50:47 +020083
Kyösti Mälkkib1fcbf32015-05-26 11:25:13 +030084 ResumeHeap(&dst, &len);
Kyösti Mälkki300cace2014-12-16 19:50:47 +020085 dataBlock->VolatileStorageSize = len;
86 dataBlock->VolatileStorage = dst;
Kyösti Mälkkib1fcbf32015-05-26 11:25:13 +030087
Kyösti Mälkki300cace2014-12-16 19:50:47 +020088 return AGESA_SUCCESS;
89}
90
91#else
92
93static int spi_SaveS3info(u32 pos, u32 size, u8 *buf, u32 len)
Kyösti Mälkki90a54b02015-05-24 09:06:03 +030094{
95#if IS_ENABLED(CONFIG_SPI_FLASH)
96 struct spi_flash *flash;
97
98 spi_init();
99 flash = spi_flash_probe(0, 0);
100 if (!flash)
101 return -1;
102
103 flash->spi->rw = SPI_WRITE_FLAG;
104 spi_claim_bus(flash->spi);
105
106 flash->erase(flash, pos, size);
107 flash->write(flash, pos, sizeof(len), &len);
108 flash->write(flash, pos + sizeof(len), len, buf);
109
110 flash->spi->rw = SPI_WRITE_FLAG;
111 spi_release_bus(flash->spi);
112 return 0;
113#else
114 return -1;
115#endif
116}
Kyösti Mälkki300cace2014-12-16 19:50:47 +0200117
Kyösti Mälkki98e0ac02015-09-12 00:20:25 +0300118static u8 MTRRStorage[S3_DATA_MTRR_SIZE];
119
WANG Siyuand3deecd2015-06-12 16:41:50 +0800120AGESA_STATUS OemS3Save(void *vS3SaveParams)
Kyösti Mälkki300cace2014-12-16 19:50:47 +0200121{
WANG Siyuand3deecd2015-06-12 16:41:50 +0800122#if IS_ENABLED(CONFIG_CPU_AMD_PI_00660F01)
123 AMD_RTB_PARAMS *S3SaveParams = (AMD_RTB_PARAMS *)vS3SaveParams;
124 S3_DATA_BLOCK *dataBlock = &S3SaveParams->S3DataBlock;
125#else
126 AMD_S3SAVE_PARAMS *S3SaveParams = (AMD_S3SAVE_PARAMS *)vS3SaveParams;
Kyösti Mälkki300cace2014-12-16 19:50:47 +0200127 AMD_S3_PARAMS *dataBlock = &S3SaveParams->S3DataBlock;
WANG Siyuand3deecd2015-06-12 16:41:50 +0800128#endif
Kyösti Mälkki300cace2014-12-16 19:50:47 +0200129 u32 MTRRStorageSize = 0;
Stefan Reinauer29e65482015-06-18 01:18:09 -0700130 uintptr_t pos, size;
Kyösti Mälkki300cace2014-12-16 19:50:47 +0200131
Kyösti Mälkkif7284082015-05-26 10:12:45 +0300132 if (HIGH_ROMSTAGE_STACK_SIZE)
133 cbmem_add(CBMEM_ID_ROMSTAGE_RAM_STACK, HIGH_ROMSTAGE_STACK_SIZE);
134
Kyösti Mälkki300cace2014-12-16 19:50:47 +0200135 /* To be consumed in AmdInitResume. */
136 get_s3nv_data(S3DataTypeNonVolatile, &pos, &size);
137 if (size && dataBlock->NvStorageSize)
138 spi_SaveS3info(pos, size, dataBlock->NvStorage,
139 dataBlock->NvStorageSize);
140
141 /* To be consumed in AmdS3LateRestore. */
Kyösti Mälkkic74b53f2015-05-26 15:38:58 +0300142 char *heap = cbmem_add(CBMEM_ID_RESUME_SCRATCH, HIGH_MEMORY_SCRATCH);
143 if (heap) {
144 memset(heap, 0, HIGH_MEMORY_SCRATCH);
145 memcpy(heap, dataBlock->VolatileStorage, dataBlock->VolatileStorageSize);
146 }
Kyösti Mälkki300cace2014-12-16 19:50:47 +0200147
148 /* Collect MTRR setup. */
149 backup_mtrr(MTRRStorage, &MTRRStorageSize);
150
151 /* To be consumed in restore_mtrr, CPU enumeration in ramstage. */
152 get_s3nv_data(S3DataTypeMTRR, &pos, &size);
153 if (size && MTRRStorageSize)
154 spi_SaveS3info(pos, size, MTRRStorage, MTRRStorageSize);
155
156 return AGESA_SUCCESS;
157}
158
159const void *OemS3Saved_MTRR_Storage(void)
160{
Stefan Reinauer29e65482015-06-18 01:18:09 -0700161 uintptr_t pos, size;
Kyösti Mälkki300cace2014-12-16 19:50:47 +0200162 get_s3nv_data(S3DataTypeMTRR, &pos, &size);
163 if (!size)
164 return NULL;
165
166 return (void*)(pos + sizeof(UINT32));
167}
168
169#endif