blob: 2ff4d441b70e2fe51583c1f6e98baacfd52b418f [file] [log] [blame]
Angel Pons8a3453f2020-04-02 23:48:19 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +02002
3#include <stdint.h>
4#include <string.h>
Furquan Shaikh76cedd22020-05-02 10:24:23 -07005#include <acpi/acpi.h>
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +02006#include <bootstate.h>
Kyösti Mälkkidbd64952017-07-16 16:08:58 +03007#include <cbfs.h>
Kyösti Mälkki43f6d9d2019-03-14 14:59:31 +02008#include <timestamp.h>
9
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020010#include <northbridge/amd/agesa/state_machine.h>
11#include <northbridge/amd/agesa/agesa_helper.h>
12#include <northbridge/amd/agesa/BiosCallOuts.h>
Elyes HAOUAS19f5ba82018-10-14 14:52:06 +020013#include <amdlib.h>
Kyösti Mälkkic6918f92018-06-11 08:52:22 +030014
Elyes HAOUAS19f5ba82018-10-14 14:52:06 +020015#include <AMD.h>
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020016
Julius Wernercd49cce2019-03-05 16:53:33 -080017#if CONFIG(CPU_AMD_AGESA_OPENSOURCE)
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030018#include "Dispatcher.h"
19#endif
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020020
Kyösti Mälkki11cac782022-04-07 07:16:48 +030021#if ENV_RAMINIT
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020022#include <PlatformMemoryConfiguration.h>
23CONST PSO_ENTRY ROMDATA DefaultPlatformMemoryConfiguration[] = {PSO_END};
24#endif
25
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030026static void agesa_locate_image(AMD_CONFIG_PARAMS *StdHeader)
27{
Julius Wernercd49cce2019-03-05 16:53:33 -080028#if CONFIG(CPU_AMD_AGESA_BINARY_PI)
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030029 const char ModuleIdentifier[] = AGESA_ID;
30 const void *agesa, *image;
31 size_t file_size;
32
Julius Werner834b3ec2020-03-04 16:52:08 -080033 agesa = cbfs_map((const char *)CONFIG_AGESA_CBFS_NAME, &file_size);
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030034 if (agesa == NULL)
35 return;
36
37 image = LibAmdLocateImage(agesa, agesa + file_size, 4096,
38 ModuleIdentifier);
Elyes Haouas76c63232022-07-16 09:47:00 +020039 StdHeader->ImageBasePtr = (void *)image;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030040#endif
41}
42
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020043void agesa_set_interface(struct sysinfo *cb)
44{
45 memset(&cb->StdHeader, 0, sizeof(AMD_CONFIG_PARAMS));
46
47 cb->StdHeader.CalloutPtr = GetBiosCallout;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030048
Julius Wernercd49cce2019-03-05 16:53:33 -080049 if (CONFIG(CPU_AMD_AGESA_BINARY_PI)) {
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030050 agesa_locate_image(&cb->StdHeader);
51 AMD_IMAGE_HEADER *image =
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +020052 (void *)(uintptr_t)cb->StdHeader.ImageBasePtr;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030053 ASSERT(image);
54 AMD_MODULE_HEADER *module =
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +020055 (void *)(uintptr_t)image->ModuleInfoOffset;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030056 ASSERT(module && module->ModuleDispatcher);
57 }
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020058}
59
60AGESA_STATUS module_dispatch(AGESA_STRUCT_NAME func,
61 AMD_CONFIG_PARAMS *StdHeader)
62{
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030063 MODULE_ENTRY dispatcher;
64
Julius Wernercd49cce2019-03-05 16:53:33 -080065#if CONFIG(CPU_AMD_AGESA_OPENSOURCE)
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030066 dispatcher = AmdAgesaDispatcher;
67#endif
Julius Wernercd49cce2019-03-05 16:53:33 -080068#if CONFIG(CPU_AMD_AGESA_BINARY_PI)
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +020069 AMD_IMAGE_HEADER *image = (void *)(uintptr_t)StdHeader->ImageBasePtr;
70 AMD_MODULE_HEADER *module = (void *)(uintptr_t)image->ModuleInfoOffset;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030071 dispatcher = module->ModuleDispatcher;
72#endif
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020073
74 StdHeader->Func = func;
75 return dispatcher(StdHeader);
76}
77
78static AGESA_STATUS amd_create_struct(AMD_INTERFACE_PARAMS *aip,
79 AGESA_STRUCT_NAME func, void *buf, size_t len)
80{
81 aip->AgesaFunctionName = func;
82 aip->AllocationMethod = 0;
83 aip->NewStructPtr = buf;
84 aip->NewStructSize = len;
85 if (buf != NULL && len != 0)
86 aip->AllocationMethod = ByHost;
87
88 return module_dispatch(AMD_CREATE_STRUCT, &aip->StdHeader);
89}
90
91static AGESA_STATUS amd_release_struct(AMD_INTERFACE_PARAMS *aip)
92{
93 /* Cannot release AMD_LATE_PARAMS until ACPI tables are done. */
94 if (aip->AgesaFunctionName == AMD_INIT_LATE)
95 return AGESA_SUCCESS;
96
97 return module_dispatch(AMD_RELEASE_STRUCT, &aip->StdHeader);
98}
99
100/* By design, for each valid AGESA_STRUCT_NAME, AMD_CONFIG_PARAMS
101 * can be evaluated to apply correct typecast based on Func field.
102 */
103
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300104static AGESA_STATUS romstage_dispatch(struct sysinfo *cb,
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200105 AGESA_STRUCT_NAME func, AMD_CONFIG_PARAMS *StdHeader)
106{
107 AGESA_STATUS status = AGESA_UNSUPPORTED;
108
109 switch (func)
110 {
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200111 case AMD_INIT_RESET:
112 {
113 AMD_RESET_PARAMS *param = (void *)StdHeader;
114 platform_BeforeInitReset(cb, param);
115 board_BeforeInitReset(cb, param);
116 status = module_dispatch(func, StdHeader);
117 break;
118 }
119
120 case AMD_INIT_EARLY:
121 {
122 AMD_EARLY_PARAMS *param = (void *)StdHeader;
123 platform_BeforeInitEarly(cb, param);
124 board_BeforeInitEarly(cb, param);
125 status = module_dispatch(func, StdHeader);
126 break;
127 }
128
129 case AMD_INIT_POST:
130 {
131 AMD_POST_PARAMS *param = (void *)StdHeader;
132 platform_BeforeInitPost(cb, param);
133 board_BeforeInitPost(cb, param);
134 status = module_dispatch(func, StdHeader);
Kyösti Mälkki43f6d9d2019-03-14 14:59:31 +0200135
136 /* FIXME: Detect if TSC frequency really
137 * changed during raminit? */
138 timestamp_rescale_table(1, 4);
139
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200140 platform_AfterInitPost(cb, param);
141 break;
142 }
143
144 case AMD_INIT_RESUME:
145 {
146 AMD_RESUME_PARAMS *param = (void *)StdHeader;
147 platform_BeforeInitResume(cb, param);
148 status = module_dispatch(func, StdHeader);
Kyösti Mälkki43f6d9d2019-03-14 14:59:31 +0200149
150 /* FIXME: Detect if TSC frequency really
151 * changed during raminit? */
152 timestamp_rescale_table(1, 4);
153
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200154 platform_AfterInitResume(cb, param);
155 break;
156 }
157
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300158 default:
159 {
160 break;
161 }
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300162 }
163 return status;
164}
165
166static AGESA_STATUS ramstage_dispatch(struct sysinfo *cb,
167 AGESA_STRUCT_NAME func, AMD_CONFIG_PARAMS *StdHeader)
168{
169 AGESA_STATUS status = AGESA_UNSUPPORTED;
170
171 switch (func)
172 {
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200173 case AMD_INIT_ENV:
174 {
175 AMD_ENV_PARAMS *param = (void *)StdHeader;
176 platform_BeforeInitEnv(cb, param);
177 board_BeforeInitEnv(cb, param);
178 status = module_dispatch(func, StdHeader);
179 platform_AfterInitEnv(cb, param);
180 break;
181 }
182
183 case AMD_S3LATE_RESTORE:
184 {
185 AMD_S3LATE_PARAMS *param = (void *)StdHeader;
186 platform_BeforeS3LateRestore(cb, param);
187 status = module_dispatch(func, StdHeader);
188 platform_AfterS3LateRestore(cb, param);
189 break;
190 }
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200191
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200192 case AMD_INIT_MID:
193 {
194 AMD_MID_PARAMS *param = (void *)StdHeader;
195 platform_BeforeInitMid(cb, param);
196 board_BeforeInitMid(cb, param);
197 status = module_dispatch(func, StdHeader);
198 break;
199 }
200
201 case AMD_S3_SAVE:
202 {
203 AMD_S3SAVE_PARAMS *param = (void *)StdHeader;
204 status = module_dispatch(func, StdHeader);
205 platform_AfterS3Save(cb, param);
206 break;
207 }
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300208
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200209 case AMD_INIT_LATE:
210 {
211 AMD_LATE_PARAMS *param = (void *)StdHeader;
Michał Żygowski506b9c12019-12-20 16:57:13 +0100212 platform_BeforeInitLate(cb, param);
213 board_BeforeInitLate(cb, param);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200214 status = module_dispatch(func, StdHeader);
215 platform_AfterInitLate(cb, param);
216 completion_InitLate(cb, param);
217 break;
218 }
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300219
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200220 default:
221 {
222 break;
223 }
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200224 }
225 return status;
226}
227
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200228int agesa_execute_state(struct sysinfo *cb, AGESA_STRUCT_NAME func)
229{
230 AMD_INTERFACE_PARAMS aip;
231 union {
232 AMD_RESET_PARAMS reset;
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200233 AMD_S3LATE_PARAMS s3late;
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200234 } agesa_params;
235 void *buf = NULL;
236 size_t len = 0;
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200237
238 AGESA_STATUS status, final;
239
240 struct agesa_state task;
241 memset(&task, 0, sizeof(task));
Kyösti Mälkkid1d4f932017-09-24 08:21:00 +0300242 agesa_state_on_entry(&task, func);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200243
244 aip.StdHeader = cb->StdHeader;
245
246 /* For these calls, heap is not available. */
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200247 if (func == AMD_INIT_RESET || func == AMD_S3LATE_RESTORE) {
Elyes Haouas76c63232022-07-16 09:47:00 +0200248 buf = (void *)&agesa_params;
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200249 len = sizeof(agesa_params);
250 memcpy(buf, &cb->StdHeader, sizeof(cb->StdHeader));
251 }
252
253 status = amd_create_struct(&aip, func, buf, len);
254 ASSERT(status == AGESA_SUCCESS);
255
256 /* Must call the function buffer was allocated for.*/
257 AMD_CONFIG_PARAMS *StdHeader = aip.NewStructPtr;
Jacob Garber176670e2019-06-04 15:13:46 -0600258 ASSERT(StdHeader != NULL && StdHeader->Func == func);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200259
Kyösti Mälkki43f6d9d2019-03-14 14:59:31 +0200260 if (CONFIG(AGESA_EXTRA_TIMESTAMPS) && task.ts_entry_id)
261 timestamp_add_now(task.ts_entry_id);
262
Kyösti Mälkki11cac782022-04-07 07:16:48 +0300263 if (ENV_RAMINIT)
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300264 final = romstage_dispatch(cb, func, StdHeader);
265
266 if (ENV_RAMSTAGE)
267 final = ramstage_dispatch(cb, func, StdHeader);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200268
Kyösti Mälkki43f6d9d2019-03-14 14:59:31 +0200269 if (CONFIG(AGESA_EXTRA_TIMESTAMPS) && task.ts_exit_id)
270 timestamp_add_now(task.ts_exit_id);
271
Kyösti Mälkkid1d4f932017-09-24 08:21:00 +0300272 agesawrapper_trace(final, StdHeader, task.function_name);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200273 ASSERT(final < AGESA_FATAL);
274
275 status = amd_release_struct(&aip);
276 ASSERT(status == AGESA_SUCCESS);
277
Kyösti Mälkkid1d4f932017-09-24 08:21:00 +0300278 agesa_state_on_exit(&task, &aip.StdHeader);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200279
280 return (final < AGESA_FATAL) ? 0 : -1;
281}
282
283#if ENV_RAMSTAGE
284
285static void amd_bs_ramstage_init(void *arg)
286{
287 struct sysinfo *cb = arg;
288
289 agesa_set_interface(cb);
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200290
291 if (!acpi_is_wakeup_s3())
292 agesa_execute_state(cb, AMD_INIT_ENV);
293 else {
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200294 agesa_execute_state(cb, AMD_S3LATE_RESTORE);
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300295 fchs3earlyrestore(&cb->StdHeader);
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200296 }
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200297}
298
299void sb_After_Pci_Restore_Init(void);
300
301static void amd_bs_dev_enable(void *arg)
302{
303 struct sysinfo *cb = arg;
304
305 if (!acpi_is_wakeup_s3())
306 agesa_execute_state(cb, AMD_INIT_MID);
307
308 /* FIXME */
Julius Wernercd49cce2019-03-05 16:53:33 -0800309 if (CONFIG(AMD_SB_CIMX) && acpi_is_wakeup_s3())
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200310 sb_After_Pci_Restore_Init();
311}
312
313static void amd_bs_post_device(void *arg)
314{
315 struct sysinfo *cb = arg;
316
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300317 if (acpi_is_wakeup_s3()) {
318 fchs3laterestore(&cb->StdHeader);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200319 return;
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300320 }
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200321
322 agesa_execute_state(cb, AMD_INIT_LATE);
323
324 if (!acpi_s3_resume_allowed())
325 return;
326
327 agesa_execute_state(cb, AMD_S3_SAVE);
328}
329
330static struct sysinfo state_machine;
331
332BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, amd_bs_ramstage_init,
333 &state_machine);
334
335BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_ENTRY, amd_bs_dev_enable,
336 &state_machine);
337
338BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, amd_bs_post_device,
339 &state_machine);
340
341#endif /* ENV_RAMSTAGE */
342
343/* Empty stubs for cases board does not need to override anything. */
Aaron Durbin64031672018-04-21 14:45:32 -0600344void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200345board_BeforeInitReset(struct sysinfo *cb, AMD_RESET_PARAMS *Reset) { }
Aaron Durbin64031672018-04-21 14:45:32 -0600346void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200347board_BeforeInitEarly(struct sysinfo *cb, AMD_EARLY_PARAMS *Early) { }
Aaron Durbin64031672018-04-21 14:45:32 -0600348void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200349board_BeforeInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post) { }
Aaron Durbin64031672018-04-21 14:45:32 -0600350void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200351board_BeforeInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env) { }
Aaron Durbin64031672018-04-21 14:45:32 -0600352void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200353board_BeforeInitMid(struct sysinfo *cb, AMD_MID_PARAMS *Mid) { }
Michał Żygowski506b9c12019-12-20 16:57:13 +0100354void __weak
355board_BeforeInitLate(struct sysinfo *cb, AMD_LATE_PARAMS *Late) { }
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300356
Aaron Durbin64031672018-04-21 14:45:32 -0600357AGESA_STATUS __weak
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300358fchs3earlyrestore(AMD_CONFIG_PARAMS *StdHeader)
359{
360 return AGESA_SUCCESS;
361}
362
Aaron Durbin64031672018-04-21 14:45:32 -0600363AGESA_STATUS __weak
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300364fchs3laterestore(AMD_CONFIG_PARAMS *StdHeader)
365{
366 return AGESA_SUCCESS;
367}