blob: 1678f841d02d9df1af79639df8e48d0b7ce0ac76 [file] [log] [blame]
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +02001/*
2 * This file is part of the coreboot project.
3 *
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +02004 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <stdint.h>
15#include <string.h>
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020016#include <arch/acpi.h>
17#include <bootstate.h>
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030018#include <cbfs.h>
Kyösti Mälkki43f6d9d2019-03-14 14:59:31 +020019#include <cbmem.h>
20#include <timestamp.h>
21
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020022#include <northbridge/amd/agesa/state_machine.h>
23#include <northbridge/amd/agesa/agesa_helper.h>
24#include <northbridge/amd/agesa/BiosCallOuts.h>
Elyes HAOUAS19f5ba82018-10-14 14:52:06 +020025#include <amdlib.h>
Kyösti Mälkkic6918f92018-06-11 08:52:22 +030026
Elyes HAOUAS19f5ba82018-10-14 14:52:06 +020027#include <AMD.h>
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020028
Julius Wernercd49cce2019-03-05 16:53:33 -080029#if CONFIG(CPU_AMD_AGESA_OPENSOURCE)
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030030#include "Dispatcher.h"
31#endif
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020032
33#if ENV_ROMSTAGE
34#include <PlatformMemoryConfiguration.h>
35CONST PSO_ENTRY ROMDATA DefaultPlatformMemoryConfiguration[] = {PSO_END};
36#endif
37
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030038static void agesa_locate_image(AMD_CONFIG_PARAMS *StdHeader)
39{
Julius Wernercd49cce2019-03-05 16:53:33 -080040#if CONFIG(CPU_AMD_AGESA_BINARY_PI)
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030041 const char ModuleIdentifier[] = AGESA_ID;
42 const void *agesa, *image;
43 size_t file_size;
44
45 agesa = cbfs_boot_map_with_leak((const char *)CONFIG_AGESA_CBFS_NAME,
46 CBFS_TYPE_RAW, &file_size);
47 if (agesa == NULL)
48 return;
49
50 image = LibAmdLocateImage(agesa, agesa + file_size, 4096,
51 ModuleIdentifier);
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +020052 StdHeader->ImageBasePtr = (void *) image;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030053#endif
54}
55
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020056void agesa_set_interface(struct sysinfo *cb)
57{
58 memset(&cb->StdHeader, 0, sizeof(AMD_CONFIG_PARAMS));
59
60 cb->StdHeader.CalloutPtr = GetBiosCallout;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030061
Julius Wernercd49cce2019-03-05 16:53:33 -080062 if (CONFIG(CPU_AMD_AGESA_BINARY_PI)) {
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030063 agesa_locate_image(&cb->StdHeader);
64 AMD_IMAGE_HEADER *image =
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +020065 (void *)(uintptr_t)cb->StdHeader.ImageBasePtr;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030066 ASSERT(image);
67 AMD_MODULE_HEADER *module =
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +020068 (void *)(uintptr_t)image->ModuleInfoOffset;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030069 ASSERT(module && module->ModuleDispatcher);
70 }
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020071}
72
73AGESA_STATUS module_dispatch(AGESA_STRUCT_NAME func,
74 AMD_CONFIG_PARAMS *StdHeader)
75{
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030076 MODULE_ENTRY dispatcher;
77
Julius Wernercd49cce2019-03-05 16:53:33 -080078#if CONFIG(CPU_AMD_AGESA_OPENSOURCE)
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030079 dispatcher = AmdAgesaDispatcher;
80#endif
Julius Wernercd49cce2019-03-05 16:53:33 -080081#if CONFIG(CPU_AMD_AGESA_BINARY_PI)
Elyes HAOUASb0b0c8c2018-07-08 12:33:47 +020082 AMD_IMAGE_HEADER *image = (void *)(uintptr_t)StdHeader->ImageBasePtr;
83 AMD_MODULE_HEADER *module = (void *)(uintptr_t)image->ModuleInfoOffset;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030084 dispatcher = module->ModuleDispatcher;
85#endif
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020086
87 StdHeader->Func = func;
88 return dispatcher(StdHeader);
89}
90
91static AGESA_STATUS amd_create_struct(AMD_INTERFACE_PARAMS *aip,
92 AGESA_STRUCT_NAME func, void *buf, size_t len)
93{
94 aip->AgesaFunctionName = func;
95 aip->AllocationMethod = 0;
96 aip->NewStructPtr = buf;
97 aip->NewStructSize = len;
98 if (buf != NULL && len != 0)
99 aip->AllocationMethod = ByHost;
100
101 return module_dispatch(AMD_CREATE_STRUCT, &aip->StdHeader);
102}
103
104static AGESA_STATUS amd_release_struct(AMD_INTERFACE_PARAMS *aip)
105{
106 /* Cannot release AMD_LATE_PARAMS until ACPI tables are done. */
107 if (aip->AgesaFunctionName == AMD_INIT_LATE)
108 return AGESA_SUCCESS;
109
110 return module_dispatch(AMD_RELEASE_STRUCT, &aip->StdHeader);
111}
112
113/* By design, for each valid AGESA_STRUCT_NAME, AMD_CONFIG_PARAMS
114 * can be evaluated to apply correct typecast based on Func field.
115 */
116
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300117static AGESA_STATUS romstage_dispatch(struct sysinfo *cb,
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200118 AGESA_STRUCT_NAME func, AMD_CONFIG_PARAMS *StdHeader)
119{
120 AGESA_STATUS status = AGESA_UNSUPPORTED;
121
122 switch (func)
123 {
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200124 case AMD_INIT_RESET:
125 {
126 AMD_RESET_PARAMS *param = (void *)StdHeader;
127 platform_BeforeInitReset(cb, param);
128 board_BeforeInitReset(cb, param);
129 status = module_dispatch(func, StdHeader);
130 break;
131 }
132
133 case AMD_INIT_EARLY:
134 {
135 AMD_EARLY_PARAMS *param = (void *)StdHeader;
136 platform_BeforeInitEarly(cb, param);
137 board_BeforeInitEarly(cb, param);
138 status = module_dispatch(func, StdHeader);
139 break;
140 }
141
142 case AMD_INIT_POST:
143 {
144 AMD_POST_PARAMS *param = (void *)StdHeader;
145 platform_BeforeInitPost(cb, param);
146 board_BeforeInitPost(cb, param);
147 status = module_dispatch(func, StdHeader);
Kyösti Mälkki43f6d9d2019-03-14 14:59:31 +0200148
149 /* FIXME: Detect if TSC frequency really
150 * changed during raminit? */
151 timestamp_rescale_table(1, 4);
152
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200153 platform_AfterInitPost(cb, param);
154 break;
155 }
156
157 case AMD_INIT_RESUME:
158 {
159 AMD_RESUME_PARAMS *param = (void *)StdHeader;
160 platform_BeforeInitResume(cb, param);
161 status = module_dispatch(func, StdHeader);
Kyösti Mälkki43f6d9d2019-03-14 14:59:31 +0200162
163 /* FIXME: Detect if TSC frequency really
164 * changed during raminit? */
165 timestamp_rescale_table(1, 4);
166
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200167 platform_AfterInitResume(cb, param);
168 break;
169 }
170
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300171 default:
172 {
173 break;
174 }
175
176 }
177 return status;
178}
179
180static AGESA_STATUS ramstage_dispatch(struct sysinfo *cb,
181 AGESA_STRUCT_NAME func, AMD_CONFIG_PARAMS *StdHeader)
182{
183 AGESA_STATUS status = AGESA_UNSUPPORTED;
184
185 switch (func)
186 {
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200187 case AMD_INIT_ENV:
188 {
189 AMD_ENV_PARAMS *param = (void *)StdHeader;
190 platform_BeforeInitEnv(cb, param);
191 board_BeforeInitEnv(cb, param);
192 status = module_dispatch(func, StdHeader);
193 platform_AfterInitEnv(cb, param);
194 break;
195 }
196
197 case AMD_S3LATE_RESTORE:
198 {
199 AMD_S3LATE_PARAMS *param = (void *)StdHeader;
200 platform_BeforeS3LateRestore(cb, param);
201 status = module_dispatch(func, StdHeader);
202 platform_AfterS3LateRestore(cb, param);
203 break;
204 }
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200205
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200206 case AMD_INIT_MID:
207 {
208 AMD_MID_PARAMS *param = (void *)StdHeader;
209 platform_BeforeInitMid(cb, param);
210 board_BeforeInitMid(cb, param);
211 status = module_dispatch(func, StdHeader);
212 break;
213 }
214
215 case AMD_S3_SAVE:
216 {
217 AMD_S3SAVE_PARAMS *param = (void *)StdHeader;
218 status = module_dispatch(func, StdHeader);
219 platform_AfterS3Save(cb, param);
220 break;
221 }
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300222
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200223 case AMD_INIT_LATE:
224 {
225 AMD_LATE_PARAMS *param = (void *)StdHeader;
Michał Żygowski506b9c12019-12-20 16:57:13 +0100226 platform_BeforeInitLate(cb, param);
227 board_BeforeInitLate(cb, param);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200228 status = module_dispatch(func, StdHeader);
229 platform_AfterInitLate(cb, param);
230 completion_InitLate(cb, param);
231 break;
232 }
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300233
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200234 default:
235 {
236 break;
237 }
238
239 }
240 return status;
241}
242
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200243int agesa_execute_state(struct sysinfo *cb, AGESA_STRUCT_NAME func)
244{
245 AMD_INTERFACE_PARAMS aip;
246 union {
247 AMD_RESET_PARAMS reset;
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200248 AMD_S3LATE_PARAMS s3late;
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200249 } agesa_params;
250 void *buf = NULL;
251 size_t len = 0;
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200252
253 AGESA_STATUS status, final;
254
255 struct agesa_state task;
256 memset(&task, 0, sizeof(task));
Kyösti Mälkkid1d4f932017-09-24 08:21:00 +0300257 agesa_state_on_entry(&task, func);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200258
259 aip.StdHeader = cb->StdHeader;
260
261 /* For these calls, heap is not available. */
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200262 if (func == AMD_INIT_RESET || func == AMD_S3LATE_RESTORE) {
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200263 buf = (void *) &agesa_params;
264 len = sizeof(agesa_params);
265 memcpy(buf, &cb->StdHeader, sizeof(cb->StdHeader));
266 }
267
268 status = amd_create_struct(&aip, func, buf, len);
269 ASSERT(status == AGESA_SUCCESS);
270
271 /* Must call the function buffer was allocated for.*/
272 AMD_CONFIG_PARAMS *StdHeader = aip.NewStructPtr;
Jacob Garber176670e2019-06-04 15:13:46 -0600273 ASSERT(StdHeader != NULL && StdHeader->Func == func);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200274
Kyösti Mälkki43f6d9d2019-03-14 14:59:31 +0200275 if (CONFIG(AGESA_EXTRA_TIMESTAMPS) && task.ts_entry_id)
276 timestamp_add_now(task.ts_entry_id);
277
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300278 if (ENV_ROMSTAGE)
279 final = romstage_dispatch(cb, func, StdHeader);
280
281 if (ENV_RAMSTAGE)
282 final = ramstage_dispatch(cb, func, StdHeader);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200283
Kyösti Mälkki43f6d9d2019-03-14 14:59:31 +0200284 if (CONFIG(AGESA_EXTRA_TIMESTAMPS) && task.ts_exit_id)
285 timestamp_add_now(task.ts_exit_id);
286
Kyösti Mälkkid1d4f932017-09-24 08:21:00 +0300287 agesawrapper_trace(final, StdHeader, task.function_name);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200288 ASSERT(final < AGESA_FATAL);
289
290 status = amd_release_struct(&aip);
291 ASSERT(status == AGESA_SUCCESS);
292
Kyösti Mälkkid1d4f932017-09-24 08:21:00 +0300293 agesa_state_on_exit(&task, &aip.StdHeader);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200294
295 return (final < AGESA_FATAL) ? 0 : -1;
296}
297
298#if ENV_RAMSTAGE
299
300static void amd_bs_ramstage_init(void *arg)
301{
302 struct sysinfo *cb = arg;
303
304 agesa_set_interface(cb);
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200305
306 if (!acpi_is_wakeup_s3())
307 agesa_execute_state(cb, AMD_INIT_ENV);
308 else {
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200309 agesa_execute_state(cb, AMD_S3LATE_RESTORE);
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300310 fchs3earlyrestore(&cb->StdHeader);
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200311 }
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200312}
313
314void sb_After_Pci_Restore_Init(void);
315
316static void amd_bs_dev_enable(void *arg)
317{
318 struct sysinfo *cb = arg;
319
320 if (!acpi_is_wakeup_s3())
321 agesa_execute_state(cb, AMD_INIT_MID);
322
323 /* FIXME */
Julius Wernercd49cce2019-03-05 16:53:33 -0800324 if (CONFIG(AMD_SB_CIMX) && acpi_is_wakeup_s3())
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200325 sb_After_Pci_Restore_Init();
326}
327
328static void amd_bs_post_device(void *arg)
329{
330 struct sysinfo *cb = arg;
331
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300332 if (acpi_is_wakeup_s3()) {
333 fchs3laterestore(&cb->StdHeader);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200334 return;
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300335 }
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200336
337 agesa_execute_state(cb, AMD_INIT_LATE);
338
339 if (!acpi_s3_resume_allowed())
340 return;
341
342 agesa_execute_state(cb, AMD_S3_SAVE);
343}
344
345static struct sysinfo state_machine;
346
347BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, amd_bs_ramstage_init,
348 &state_machine);
349
350BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_ENTRY, amd_bs_dev_enable,
351 &state_machine);
352
353BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, amd_bs_post_device,
354 &state_machine);
355
356#endif /* ENV_RAMSTAGE */
357
358/* Empty stubs for cases board does not need to override anything. */
Aaron Durbin64031672018-04-21 14:45:32 -0600359void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200360board_BeforeInitReset(struct sysinfo *cb, AMD_RESET_PARAMS *Reset) { }
Aaron Durbin64031672018-04-21 14:45:32 -0600361void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200362board_BeforeInitEarly(struct sysinfo *cb, AMD_EARLY_PARAMS *Early) { }
Aaron Durbin64031672018-04-21 14:45:32 -0600363void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200364board_BeforeInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post) { }
Aaron Durbin64031672018-04-21 14:45:32 -0600365void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200366board_BeforeInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env) { }
Aaron Durbin64031672018-04-21 14:45:32 -0600367void __weak
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200368board_BeforeInitMid(struct sysinfo *cb, AMD_MID_PARAMS *Mid) { }
Michał Żygowski506b9c12019-12-20 16:57:13 +0100369void __weak
370board_BeforeInitLate(struct sysinfo *cb, AMD_LATE_PARAMS *Late) { }
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}