blob: c8529c5e048a0f53d81275f2c3310f63eba3d8fe [file] [log] [blame]
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +02001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2011-2012 Advanced Micro Devices, Inc.
5 * Copyright (C) 2016 Kyösti Mälkki
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <stdint.h>
18#include <string.h>
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020019#include <arch/acpi.h>
Elyes HAOUASd2b9ec12018-10-27 09:41:02 +020020#include <arch/cpu.h>
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020021#include <bootstate.h>
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030022#include <cbfs.h>
Kyösti Mälkki43f6d9d2019-03-14 14:59:31 +020023#include <cbmem.h>
24#include <timestamp.h>
25
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020026#include <northbridge/amd/agesa/state_machine.h>
27#include <northbridge/amd/agesa/agesa_helper.h>
28#include <northbridge/amd/agesa/BiosCallOuts.h>
Elyes HAOUAS19f5ba82018-10-14 14:52:06 +020029#include <amdlib.h>
Kyösti Mälkkic6918f92018-06-11 08:52:22 +030030
Elyes HAOUAS19f5ba82018-10-14 14:52:06 +020031#include <AMD.h>
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020032
Julius Wernercd49cce2019-03-05 16:53:33 -080033#if CONFIG(CPU_AMD_AGESA_OPENSOURCE)
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030034#include "Dispatcher.h"
35#endif
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020036
37#if ENV_ROMSTAGE
38#include <PlatformMemoryConfiguration.h>
39CONST PSO_ENTRY ROMDATA DefaultPlatformMemoryConfiguration[] = {PSO_END};
40#endif
41
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030042static void agesa_locate_image(AMD_CONFIG_PARAMS *StdHeader)
43{
Julius Wernercd49cce2019-03-05 16:53:33 -080044#if CONFIG(CPU_AMD_AGESA_BINARY_PI)
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030045 const char ModuleIdentifier[] = AGESA_ID;
46 const void *agesa, *image;
47 size_t file_size;
48
49 agesa = cbfs_boot_map_with_leak((const char *)CONFIG_AGESA_CBFS_NAME,
50 CBFS_TYPE_RAW, &file_size);
51 if (agesa == NULL)
52 return;
53
54 image = LibAmdLocateImage(agesa, agesa + file_size, 4096,
55 ModuleIdentifier);
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +020056 StdHeader->ImageBasePtr = (void *) image;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030057#endif
58}
59
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020060void agesa_set_interface(struct sysinfo *cb)
61{
62 memset(&cb->StdHeader, 0, sizeof(AMD_CONFIG_PARAMS));
63
64 cb->StdHeader.CalloutPtr = GetBiosCallout;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030065
Julius Wernercd49cce2019-03-05 16:53:33 -080066 if (CONFIG(CPU_AMD_AGESA_BINARY_PI)) {
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030067 agesa_locate_image(&cb->StdHeader);
68 AMD_IMAGE_HEADER *image =
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +020069 (void *)(uintptr_t)cb->StdHeader.ImageBasePtr;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030070 ASSERT(image);
71 AMD_MODULE_HEADER *module =
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +020072 (void *)(uintptr_t)image->ModuleInfoOffset;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030073 ASSERT(module && module->ModuleDispatcher);
74 }
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020075}
76
77AGESA_STATUS module_dispatch(AGESA_STRUCT_NAME func,
78 AMD_CONFIG_PARAMS *StdHeader)
79{
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030080 MODULE_ENTRY dispatcher;
81
Julius Wernercd49cce2019-03-05 16:53:33 -080082#if CONFIG(CPU_AMD_AGESA_OPENSOURCE)
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030083 dispatcher = AmdAgesaDispatcher;
84#endif
Julius Wernercd49cce2019-03-05 16:53:33 -080085#if CONFIG(CPU_AMD_AGESA_BINARY_PI)
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +020086 AMD_IMAGE_HEADER *image = (void *)(uintptr_t)StdHeader->ImageBasePtr;
87 AMD_MODULE_HEADER *module = (void *)(uintptr_t)image->ModuleInfoOffset;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030088 dispatcher = module->ModuleDispatcher;
89#endif
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020090
91 StdHeader->Func = func;
92 return dispatcher(StdHeader);
93}
94
95static AGESA_STATUS amd_create_struct(AMD_INTERFACE_PARAMS *aip,
96 AGESA_STRUCT_NAME func, void *buf, size_t len)
97{
98 aip->AgesaFunctionName = func;
99 aip->AllocationMethod = 0;
100 aip->NewStructPtr = buf;
101 aip->NewStructSize = len;
102 if (buf != NULL && len != 0)
103 aip->AllocationMethod = ByHost;
104
105 return module_dispatch(AMD_CREATE_STRUCT, &aip->StdHeader);
106}
107
108static AGESA_STATUS amd_release_struct(AMD_INTERFACE_PARAMS *aip)
109{
110 /* Cannot release AMD_LATE_PARAMS until ACPI tables are done. */
111 if (aip->AgesaFunctionName == AMD_INIT_LATE)
112 return AGESA_SUCCESS;
113
114 return module_dispatch(AMD_RELEASE_STRUCT, &aip->StdHeader);
115}
116
117/* By design, for each valid AGESA_STRUCT_NAME, AMD_CONFIG_PARAMS
118 * can be evaluated to apply correct typecast based on Func field.
119 */
120
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300121static AGESA_STATUS romstage_dispatch(struct sysinfo *cb,
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200122 AGESA_STRUCT_NAME func, AMD_CONFIG_PARAMS *StdHeader)
123{
124 AGESA_STATUS status = AGESA_UNSUPPORTED;
125
126 switch (func)
127 {
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200128 case AMD_INIT_RESET:
129 {
130 AMD_RESET_PARAMS *param = (void *)StdHeader;
131 platform_BeforeInitReset(cb, param);
132 board_BeforeInitReset(cb, param);
133 status = module_dispatch(func, StdHeader);
134 break;
135 }
136
137 case AMD_INIT_EARLY:
138 {
139 AMD_EARLY_PARAMS *param = (void *)StdHeader;
140 platform_BeforeInitEarly(cb, param);
141 board_BeforeInitEarly(cb, param);
142 status = module_dispatch(func, StdHeader);
143 break;
144 }
145
146 case AMD_INIT_POST:
147 {
148 AMD_POST_PARAMS *param = (void *)StdHeader;
149 platform_BeforeInitPost(cb, param);
150 board_BeforeInitPost(cb, param);
151 status = module_dispatch(func, StdHeader);
Kyösti Mälkki43f6d9d2019-03-14 14:59:31 +0200152
153 /* FIXME: Detect if TSC frequency really
154 * changed during raminit? */
155 timestamp_rescale_table(1, 4);
156
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200157 platform_AfterInitPost(cb, param);
158 break;
159 }
160
161 case AMD_INIT_RESUME:
162 {
163 AMD_RESUME_PARAMS *param = (void *)StdHeader;
164 platform_BeforeInitResume(cb, param);
165 status = module_dispatch(func, StdHeader);
Kyösti Mälkki43f6d9d2019-03-14 14:59:31 +0200166
167 /* FIXME: Detect if TSC frequency really
168 * changed during raminit? */
169 timestamp_rescale_table(1, 4);
170
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200171 platform_AfterInitResume(cb, param);
172 break;
173 }
174
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300175 default:
176 {
177 break;
178 }
179
180 }
181 return status;
182}
183
184static AGESA_STATUS ramstage_dispatch(struct sysinfo *cb,
185 AGESA_STRUCT_NAME func, AMD_CONFIG_PARAMS *StdHeader)
186{
187 AGESA_STATUS status = AGESA_UNSUPPORTED;
188
189 switch (func)
190 {
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200191 case AMD_INIT_ENV:
192 {
193 AMD_ENV_PARAMS *param = (void *)StdHeader;
194 platform_BeforeInitEnv(cb, param);
195 board_BeforeInitEnv(cb, param);
196 status = module_dispatch(func, StdHeader);
197 platform_AfterInitEnv(cb, param);
198 break;
199 }
200
201 case AMD_S3LATE_RESTORE:
202 {
203 AMD_S3LATE_PARAMS *param = (void *)StdHeader;
204 platform_BeforeS3LateRestore(cb, param);
205 status = module_dispatch(func, StdHeader);
206 platform_AfterS3LateRestore(cb, param);
207 break;
208 }
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200209
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200210 case AMD_INIT_MID:
211 {
212 AMD_MID_PARAMS *param = (void *)StdHeader;
213 platform_BeforeInitMid(cb, param);
214 board_BeforeInitMid(cb, param);
215 status = module_dispatch(func, StdHeader);
216 break;
217 }
218
219 case AMD_S3_SAVE:
220 {
221 AMD_S3SAVE_PARAMS *param = (void *)StdHeader;
222 status = module_dispatch(func, StdHeader);
223 platform_AfterS3Save(cb, param);
224 break;
225 }
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300226
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200227 case AMD_INIT_LATE:
228 {
229 AMD_LATE_PARAMS *param = (void *)StdHeader;
230 status = module_dispatch(func, StdHeader);
231 platform_AfterInitLate(cb, param);
232 completion_InitLate(cb, param);
233 break;
234 }
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300235
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200236 default:
237 {
238 break;
239 }
240
241 }
242 return status;
243}
244
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200245int agesa_execute_state(struct sysinfo *cb, AGESA_STRUCT_NAME func)
246{
247 AMD_INTERFACE_PARAMS aip;
248 union {
249 AMD_RESET_PARAMS reset;
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200250 AMD_S3LATE_PARAMS s3late;
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200251 } agesa_params;
252 void *buf = NULL;
253 size_t len = 0;
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200254
255 AGESA_STATUS status, final;
256
257 struct agesa_state task;
258 memset(&task, 0, sizeof(task));
Kyösti Mälkkid1d4f932017-09-24 08:21:00 +0300259 agesa_state_on_entry(&task, func);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200260
261 aip.StdHeader = cb->StdHeader;
262
263 /* For these calls, heap is not available. */
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200264 if (func == AMD_INIT_RESET || func == AMD_S3LATE_RESTORE) {
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200265 buf = (void *) &agesa_params;
266 len = sizeof(agesa_params);
267 memcpy(buf, &cb->StdHeader, sizeof(cb->StdHeader));
268 }
269
270 status = amd_create_struct(&aip, func, buf, len);
271 ASSERT(status == AGESA_SUCCESS);
272
273 /* Must call the function buffer was allocated for.*/
274 AMD_CONFIG_PARAMS *StdHeader = aip.NewStructPtr;
275 ASSERT(StdHeader->Func == func);
276
Kyösti Mälkki43f6d9d2019-03-14 14:59:31 +0200277 if (CONFIG(AGESA_EXTRA_TIMESTAMPS) && task.ts_entry_id)
278 timestamp_add_now(task.ts_entry_id);
279
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300280 if (ENV_ROMSTAGE)
281 final = romstage_dispatch(cb, func, StdHeader);
282
283 if (ENV_RAMSTAGE)
284 final = ramstage_dispatch(cb, func, StdHeader);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200285
Kyösti Mälkki43f6d9d2019-03-14 14:59:31 +0200286 if (CONFIG(AGESA_EXTRA_TIMESTAMPS) && task.ts_exit_id)
287 timestamp_add_now(task.ts_exit_id);
288
Kyösti Mälkkid1d4f932017-09-24 08:21:00 +0300289 agesawrapper_trace(final, StdHeader, task.function_name);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200290 ASSERT(final < AGESA_FATAL);
291
292 status = amd_release_struct(&aip);
293 ASSERT(status == AGESA_SUCCESS);
294
Kyösti Mälkkid1d4f932017-09-24 08:21:00 +0300295 agesa_state_on_exit(&task, &aip.StdHeader);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200296
297 return (final < AGESA_FATAL) ? 0 : -1;
298}
299
300#if ENV_RAMSTAGE
301
302static void amd_bs_ramstage_init(void *arg)
303{
304 struct sysinfo *cb = arg;
305
306 agesa_set_interface(cb);
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200307
308 if (!acpi_is_wakeup_s3())
309 agesa_execute_state(cb, AMD_INIT_ENV);
310 else {
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200311 agesa_execute_state(cb, AMD_S3LATE_RESTORE);
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300312 fchs3earlyrestore(&cb->StdHeader);
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200313 }
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200314}
315
316void sb_After_Pci_Restore_Init(void);
317
318static void amd_bs_dev_enable(void *arg)
319{
320 struct sysinfo *cb = arg;
321
322 if (!acpi_is_wakeup_s3())
323 agesa_execute_state(cb, AMD_INIT_MID);
324
325 /* FIXME */
Julius Wernercd49cce2019-03-05 16:53:33 -0800326 if (CONFIG(AMD_SB_CIMX) && acpi_is_wakeup_s3())
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200327 sb_After_Pci_Restore_Init();
328}
329
330static void amd_bs_post_device(void *arg)
331{
332 struct sysinfo *cb = arg;
333
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300334 if (acpi_is_wakeup_s3()) {
335 fchs3laterestore(&cb->StdHeader);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200336 return;
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300337 }
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200338
339 agesa_execute_state(cb, AMD_INIT_LATE);
340
341 if (!acpi_s3_resume_allowed())
342 return;
343
344 agesa_execute_state(cb, AMD_S3_SAVE);
345}
346
347static struct sysinfo state_machine;
348
349BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, amd_bs_ramstage_init,
350 &state_machine);
351
352BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_ENTRY, amd_bs_dev_enable,
353 &state_machine);
354
355BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, amd_bs_post_device,
356 &state_machine);
357
358#endif /* ENV_RAMSTAGE */
359
360/* Empty stubs for cases board does not need to override anything. */
Aaron Durbin64031672018-04-21 14:45:32 -0600361void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200362board_BeforeInitReset(struct sysinfo *cb, AMD_RESET_PARAMS *Reset) { }
Aaron Durbin64031672018-04-21 14:45:32 -0600363void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200364board_BeforeInitEarly(struct sysinfo *cb, AMD_EARLY_PARAMS *Early) { }
Aaron Durbin64031672018-04-21 14:45:32 -0600365void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200366board_BeforeInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post) { }
Aaron Durbin64031672018-04-21 14:45:32 -0600367void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200368board_BeforeInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env) { }
Aaron Durbin64031672018-04-21 14:45:32 -0600369void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200370board_BeforeInitMid(struct sysinfo *cb, AMD_MID_PARAMS *Mid) { }
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300371
Aaron Durbin64031672018-04-21 14:45:32 -0600372AGESA_STATUS __weak
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300373fchs3earlyrestore(AMD_CONFIG_PARAMS *StdHeader)
374{
375 return AGESA_SUCCESS;
376}
377
Aaron Durbin64031672018-04-21 14:45:32 -0600378AGESA_STATUS __weak
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300379fchs3laterestore(AMD_CONFIG_PARAMS *StdHeader)
380{
381 return AGESA_SUCCESS;
382}