blob: c6e36b22595ab359252e0f45ba3c84145bacf304 [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>
19
20#include <arch/acpi.h>
Elyes HAOUASd2b9ec12018-10-27 09:41:02 +020021#include <arch/cpu.h>
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020022#include <bootstate.h>
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030023#include <cbfs.h>
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020024
25#include <northbridge/amd/agesa/state_machine.h>
26#include <northbridge/amd/agesa/agesa_helper.h>
27#include <northbridge/amd/agesa/BiosCallOuts.h>
Elyes HAOUAS19f5ba82018-10-14 14:52:06 +020028#include <amdlib.h>
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020029
Elyes HAOUAS19f5ba82018-10-14 14:52:06 +020030#include <AMD.h>
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020031
Julius Wernercd49cce2019-03-05 16:53:33 -080032#if CONFIG(CPU_AMD_AGESA_OPENSOURCE)
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030033#include "Dispatcher.h"
34#endif
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020035
36#if ENV_ROMSTAGE
37#include <PlatformMemoryConfiguration.h>
38CONST PSO_ENTRY ROMDATA DefaultPlatformMemoryConfiguration[] = {PSO_END};
39#endif
40
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030041static void agesa_locate_image(AMD_CONFIG_PARAMS *StdHeader)
42{
Julius Wernercd49cce2019-03-05 16:53:33 -080043#if CONFIG(CPU_AMD_AGESA_BINARY_PI)
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030044 const char ModuleIdentifier[] = AGESA_ID;
45 const void *agesa, *image;
46 size_t file_size;
47
48 agesa = cbfs_boot_map_with_leak((const char *)CONFIG_AGESA_CBFS_NAME,
49 CBFS_TYPE_RAW, &file_size);
50 if (agesa == NULL)
51 return;
52
53 image = LibAmdLocateImage(agesa, agesa + file_size, 4096,
54 ModuleIdentifier);
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +020055 StdHeader->ImageBasePtr = (void *) image;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030056#endif
57}
58
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020059void agesa_set_interface(struct sysinfo *cb)
60{
61 memset(&cb->StdHeader, 0, sizeof(AMD_CONFIG_PARAMS));
62
63 cb->StdHeader.CalloutPtr = GetBiosCallout;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030064
Julius Wernercd49cce2019-03-05 16:53:33 -080065 if (CONFIG(CPU_AMD_AGESA_BINARY_PI)) {
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030066 agesa_locate_image(&cb->StdHeader);
67 AMD_IMAGE_HEADER *image =
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +020068 (void *)(uintptr_t)cb->StdHeader.ImageBasePtr;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030069 ASSERT(image);
70 AMD_MODULE_HEADER *module =
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +020071 (void *)(uintptr_t)image->ModuleInfoOffset;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030072 ASSERT(module && module->ModuleDispatcher);
73 }
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020074}
75
76AGESA_STATUS module_dispatch(AGESA_STRUCT_NAME func,
77 AMD_CONFIG_PARAMS *StdHeader)
78{
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030079 MODULE_ENTRY dispatcher;
80
Julius Wernercd49cce2019-03-05 16:53:33 -080081#if CONFIG(CPU_AMD_AGESA_OPENSOURCE)
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030082 dispatcher = AmdAgesaDispatcher;
83#endif
Julius Wernercd49cce2019-03-05 16:53:33 -080084#if CONFIG(CPU_AMD_AGESA_BINARY_PI)
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +020085 AMD_IMAGE_HEADER *image = (void *)(uintptr_t)StdHeader->ImageBasePtr;
86 AMD_MODULE_HEADER *module = (void *)(uintptr_t)image->ModuleInfoOffset;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030087 dispatcher = module->ModuleDispatcher;
88#endif
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020089
90 StdHeader->Func = func;
91 return dispatcher(StdHeader);
92}
93
94static AGESA_STATUS amd_create_struct(AMD_INTERFACE_PARAMS *aip,
95 AGESA_STRUCT_NAME func, void *buf, size_t len)
96{
97 aip->AgesaFunctionName = func;
98 aip->AllocationMethod = 0;
99 aip->NewStructPtr = buf;
100 aip->NewStructSize = len;
101 if (buf != NULL && len != 0)
102 aip->AllocationMethod = ByHost;
103
104 return module_dispatch(AMD_CREATE_STRUCT, &aip->StdHeader);
105}
106
107static AGESA_STATUS amd_release_struct(AMD_INTERFACE_PARAMS *aip)
108{
109 /* Cannot release AMD_LATE_PARAMS until ACPI tables are done. */
110 if (aip->AgesaFunctionName == AMD_INIT_LATE)
111 return AGESA_SUCCESS;
112
113 return module_dispatch(AMD_RELEASE_STRUCT, &aip->StdHeader);
114}
115
116/* By design, for each valid AGESA_STRUCT_NAME, AMD_CONFIG_PARAMS
117 * can be evaluated to apply correct typecast based on Func field.
118 */
119
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300120static AGESA_STATUS romstage_dispatch(struct sysinfo *cb,
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200121 AGESA_STRUCT_NAME func, AMD_CONFIG_PARAMS *StdHeader)
122{
123 AGESA_STATUS status = AGESA_UNSUPPORTED;
124
125 switch (func)
126 {
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200127 case AMD_INIT_RESET:
128 {
129 AMD_RESET_PARAMS *param = (void *)StdHeader;
130 platform_BeforeInitReset(cb, param);
131 board_BeforeInitReset(cb, param);
132 status = module_dispatch(func, StdHeader);
133 break;
134 }
135
136 case AMD_INIT_EARLY:
137 {
138 AMD_EARLY_PARAMS *param = (void *)StdHeader;
139 platform_BeforeInitEarly(cb, param);
140 board_BeforeInitEarly(cb, param);
141 status = module_dispatch(func, StdHeader);
142 break;
143 }
144
145 case AMD_INIT_POST:
146 {
147 AMD_POST_PARAMS *param = (void *)StdHeader;
148 platform_BeforeInitPost(cb, param);
149 board_BeforeInitPost(cb, param);
150 status = module_dispatch(func, StdHeader);
151 platform_AfterInitPost(cb, param);
152 break;
153 }
154
155 case AMD_INIT_RESUME:
156 {
157 AMD_RESUME_PARAMS *param = (void *)StdHeader;
158 platform_BeforeInitResume(cb, param);
159 status = module_dispatch(func, StdHeader);
160 platform_AfterInitResume(cb, param);
161 break;
162 }
163
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300164 default:
165 {
166 break;
167 }
168
169 }
170 return status;
171}
172
173static AGESA_STATUS ramstage_dispatch(struct sysinfo *cb,
174 AGESA_STRUCT_NAME func, AMD_CONFIG_PARAMS *StdHeader)
175{
176 AGESA_STATUS status = AGESA_UNSUPPORTED;
177
178 switch (func)
179 {
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200180 case AMD_INIT_ENV:
181 {
182 AMD_ENV_PARAMS *param = (void *)StdHeader;
183 platform_BeforeInitEnv(cb, param);
184 board_BeforeInitEnv(cb, param);
185 status = module_dispatch(func, StdHeader);
186 platform_AfterInitEnv(cb, param);
187 break;
188 }
189
190 case AMD_S3LATE_RESTORE:
191 {
192 AMD_S3LATE_PARAMS *param = (void *)StdHeader;
193 platform_BeforeS3LateRestore(cb, param);
194 status = module_dispatch(func, StdHeader);
195 platform_AfterS3LateRestore(cb, param);
196 break;
197 }
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200198
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200199 case AMD_INIT_MID:
200 {
201 AMD_MID_PARAMS *param = (void *)StdHeader;
202 platform_BeforeInitMid(cb, param);
203 board_BeforeInitMid(cb, param);
204 status = module_dispatch(func, StdHeader);
205 break;
206 }
207
208 case AMD_S3_SAVE:
209 {
210 AMD_S3SAVE_PARAMS *param = (void *)StdHeader;
211 status = module_dispatch(func, StdHeader);
212 platform_AfterS3Save(cb, param);
213 break;
214 }
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300215
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200216 case AMD_INIT_LATE:
217 {
218 AMD_LATE_PARAMS *param = (void *)StdHeader;
219 status = module_dispatch(func, StdHeader);
220 platform_AfterInitLate(cb, param);
221 completion_InitLate(cb, param);
222 break;
223 }
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300224
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200225 default:
226 {
227 break;
228 }
229
230 }
231 return status;
232}
233
234/* DEBUG trace helper */
235
236struct agesa_state
237{
238 u8 apic_id;
239
240 AGESA_STRUCT_NAME func;
241 const char *function_name;
242};
243
244static void state_on_entry(struct agesa_state *task, AGESA_STRUCT_NAME func,
245 const char *struct_name)
246{
247 task->apic_id = (u8) (cpuid_ebx(1) >> 24);
248 task->func = func;
249 task->function_name = struct_name;
250
251 printk(BIOS_DEBUG, "\nAPIC %02d: ** Enter %s [%08x]\n",
252 task->apic_id, task->function_name, task->func);
253}
254
255static void state_on_exit(struct agesa_state *task,
256 AMD_CONFIG_PARAMS *StdHeader)
257{
258 printk(BIOS_DEBUG, "APIC %02d: Heap in %s (%d) at 0x%08x\n",
259 task->apic_id, heap_status_name(StdHeader->HeapStatus),
260 StdHeader->HeapStatus, (u32)StdHeader->HeapBasePtr);
261
262 printk(BIOS_DEBUG, "APIC %02d: ** Exit %s [%08x]\n",
263 task->apic_id, task->function_name, task->func);
264}
265
266int agesa_execute_state(struct sysinfo *cb, AGESA_STRUCT_NAME func)
267{
268 AMD_INTERFACE_PARAMS aip;
269 union {
270 AMD_RESET_PARAMS reset;
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200271 AMD_S3LATE_PARAMS s3late;
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200272 } agesa_params;
273 void *buf = NULL;
274 size_t len = 0;
275 const char *state_name = agesa_struct_name(func);
276
277 AGESA_STATUS status, final;
278
279 struct agesa_state task;
280 memset(&task, 0, sizeof(task));
281 state_on_entry(&task, func, state_name);
282
283 aip.StdHeader = cb->StdHeader;
284
285 /* For these calls, heap is not available. */
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200286 if (func == AMD_INIT_RESET || func == AMD_S3LATE_RESTORE) {
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200287 buf = (void *) &agesa_params;
288 len = sizeof(agesa_params);
289 memcpy(buf, &cb->StdHeader, sizeof(cb->StdHeader));
290 }
291
292 status = amd_create_struct(&aip, func, buf, len);
293 ASSERT(status == AGESA_SUCCESS);
294
295 /* Must call the function buffer was allocated for.*/
296 AMD_CONFIG_PARAMS *StdHeader = aip.NewStructPtr;
297 ASSERT(StdHeader->Func == func);
298
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300299 if (ENV_ROMSTAGE)
300 final = romstage_dispatch(cb, func, StdHeader);
301
302 if (ENV_RAMSTAGE)
303 final = ramstage_dispatch(cb, func, StdHeader);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200304
305 agesawrapper_trace(final, StdHeader, state_name);
306 ASSERT(final < AGESA_FATAL);
307
308 status = amd_release_struct(&aip);
309 ASSERT(status == AGESA_SUCCESS);
310
311 state_on_exit(&task, &aip.StdHeader);
312
313 return (final < AGESA_FATAL) ? 0 : -1;
314}
315
316#if ENV_RAMSTAGE
317
318static void amd_bs_ramstage_init(void *arg)
319{
320 struct sysinfo *cb = arg;
321
322 agesa_set_interface(cb);
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200323
324 if (!acpi_is_wakeup_s3())
325 agesa_execute_state(cb, AMD_INIT_ENV);
326 else {
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200327 agesa_execute_state(cb, AMD_S3LATE_RESTORE);
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300328 fchs3earlyrestore(&cb->StdHeader);
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200329 }
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200330}
331
332void sb_After_Pci_Restore_Init(void);
333
334static void amd_bs_dev_enable(void *arg)
335{
336 struct sysinfo *cb = arg;
337
338 if (!acpi_is_wakeup_s3())
339 agesa_execute_state(cb, AMD_INIT_MID);
340
341 /* FIXME */
Julius Wernercd49cce2019-03-05 16:53:33 -0800342 if (CONFIG(AMD_SB_CIMX) && acpi_is_wakeup_s3())
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200343 sb_After_Pci_Restore_Init();
344}
345
346static void amd_bs_post_device(void *arg)
347{
348 struct sysinfo *cb = arg;
349
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300350 if (acpi_is_wakeup_s3()) {
351 fchs3laterestore(&cb->StdHeader);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200352 return;
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300353 }
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200354
355 agesa_execute_state(cb, AMD_INIT_LATE);
356
357 if (!acpi_s3_resume_allowed())
358 return;
359
360 agesa_execute_state(cb, AMD_S3_SAVE);
361}
362
363static struct sysinfo state_machine;
364
365BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, amd_bs_ramstage_init,
366 &state_machine);
367
368BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_ENTRY, amd_bs_dev_enable,
369 &state_machine);
370
371BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, amd_bs_post_device,
372 &state_machine);
373
374#endif /* ENV_RAMSTAGE */
375
376/* Empty stubs for cases board does not need to override anything. */
Aaron Durbin64031672018-04-21 14:45:32 -0600377void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200378board_BeforeInitReset(struct sysinfo *cb, AMD_RESET_PARAMS *Reset) { }
Aaron Durbin64031672018-04-21 14:45:32 -0600379void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200380board_BeforeInitEarly(struct sysinfo *cb, AMD_EARLY_PARAMS *Early) { }
Aaron Durbin64031672018-04-21 14:45:32 -0600381void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200382board_BeforeInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post) { }
Aaron Durbin64031672018-04-21 14:45:32 -0600383void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200384board_BeforeInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env) { }
Aaron Durbin64031672018-04-21 14:45:32 -0600385void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200386board_BeforeInitMid(struct sysinfo *cb, AMD_MID_PARAMS *Mid) { }
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300387
Aaron Durbin64031672018-04-21 14:45:32 -0600388AGESA_STATUS __weak
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300389fchs3earlyrestore(AMD_CONFIG_PARAMS *StdHeader)
390{
391 return AGESA_SUCCESS;
392}
393
Aaron Durbin64031672018-04-21 14:45:32 -0600394AGESA_STATUS __weak
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300395fchs3laterestore(AMD_CONFIG_PARAMS *StdHeader)
396{
397 return AGESA_SUCCESS;
398}