blob: 7743603f0ba8deb5bc506f17563c73879baad902 [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>
21#include <bootstate.h>
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030022#include <cbfs.h>
Kyösti Mälkki21e609c2017-03-09 20:08:15 +020023#include <cbmem.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>
28#include "amdlib.h"
29#include <cpu/amd/agesa/s3_resume.h>
30
31#include "AMD.h"
32#include "heapManager.h"
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020033
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030034#if IS_ENABLED(CONFIG_CPU_AMD_AGESA_OPENSOURCE)
35#include "Dispatcher.h"
36#endif
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020037
38#if ENV_ROMSTAGE
39#include <PlatformMemoryConfiguration.h>
40CONST PSO_ENTRY ROMDATA DefaultPlatformMemoryConfiguration[] = {PSO_END};
41#endif
42
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030043static void agesa_locate_image(AMD_CONFIG_PARAMS *StdHeader)
44{
45#if IS_ENABLED(CONFIG_CPU_AMD_AGESA_BINARY_PI)
46 const char ModuleIdentifier[] = AGESA_ID;
47 const void *agesa, *image;
48 size_t file_size;
49
50 agesa = cbfs_boot_map_with_leak((const char *)CONFIG_AGESA_CBFS_NAME,
51 CBFS_TYPE_RAW, &file_size);
52 if (agesa == NULL)
53 return;
54
55 image = LibAmdLocateImage(agesa, agesa + file_size, 4096,
56 ModuleIdentifier);
57 StdHeader->ImageBasePtr = (void*) image;
58#endif
59}
60
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020061void agesa_set_interface(struct sysinfo *cb)
62{
63 memset(&cb->StdHeader, 0, sizeof(AMD_CONFIG_PARAMS));
64
65 cb->StdHeader.CalloutPtr = GetBiosCallout;
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030066
67 if (IS_ENABLED(CONFIG_CPU_AMD_AGESA_BINARY_PI)) {
68 agesa_locate_image(&cb->StdHeader);
69 AMD_IMAGE_HEADER *image =
70 (void*)(uintptr_t)cb->StdHeader.ImageBasePtr;
71 ASSERT(image);
72 AMD_MODULE_HEADER *module =
73 (void*)(uintptr_t)image->ModuleInfoOffset;
74 ASSERT(module && module->ModuleDispatcher);
75 }
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020076}
77
78AGESA_STATUS module_dispatch(AGESA_STRUCT_NAME func,
79 AMD_CONFIG_PARAMS *StdHeader)
80{
Kyösti Mälkkidbd64952017-07-16 16:08:58 +030081 MODULE_ENTRY dispatcher;
82
83#if IS_ENABLED(CONFIG_CPU_AMD_AGESA_OPENSOURCE)
84 dispatcher = AmdAgesaDispatcher;
85#endif
86#if IS_ENABLED(CONFIG_CPU_AMD_AGESA_BINARY_PI)
87 AMD_IMAGE_HEADER *image = (void*)(uintptr_t)StdHeader->ImageBasePtr;
88 AMD_MODULE_HEADER *module = (void*)(uintptr_t)image->ModuleInfoOffset;
89 dispatcher = module->ModuleDispatcher;
90#endif
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +020091
92 StdHeader->Func = func;
93 return dispatcher(StdHeader);
94}
95
96static AGESA_STATUS amd_create_struct(AMD_INTERFACE_PARAMS *aip,
97 AGESA_STRUCT_NAME func, void *buf, size_t len)
98{
99 aip->AgesaFunctionName = func;
100 aip->AllocationMethod = 0;
101 aip->NewStructPtr = buf;
102 aip->NewStructSize = len;
103 if (buf != NULL && len != 0)
104 aip->AllocationMethod = ByHost;
105
106 return module_dispatch(AMD_CREATE_STRUCT, &aip->StdHeader);
107}
108
109static AGESA_STATUS amd_release_struct(AMD_INTERFACE_PARAMS *aip)
110{
111 /* Cannot release AMD_LATE_PARAMS until ACPI tables are done. */
112 if (aip->AgesaFunctionName == AMD_INIT_LATE)
113 return AGESA_SUCCESS;
114
115 return module_dispatch(AMD_RELEASE_STRUCT, &aip->StdHeader);
116}
117
118/* By design, for each valid AGESA_STRUCT_NAME, AMD_CONFIG_PARAMS
119 * can be evaluated to apply correct typecast based on Func field.
120 */
121
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300122static AGESA_STATUS romstage_dispatch(struct sysinfo *cb,
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200123 AGESA_STRUCT_NAME func, AMD_CONFIG_PARAMS *StdHeader)
124{
125 AGESA_STATUS status = AGESA_UNSUPPORTED;
126
127 switch (func)
128 {
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200129 case AMD_INIT_RESET:
130 {
131 AMD_RESET_PARAMS *param = (void *)StdHeader;
132 platform_BeforeInitReset(cb, param);
133 board_BeforeInitReset(cb, param);
134 status = module_dispatch(func, StdHeader);
135 break;
136 }
137
138 case AMD_INIT_EARLY:
139 {
140 AMD_EARLY_PARAMS *param = (void *)StdHeader;
141 platform_BeforeInitEarly(cb, param);
142 board_BeforeInitEarly(cb, param);
143 status = module_dispatch(func, StdHeader);
144 break;
145 }
146
147 case AMD_INIT_POST:
148 {
149 AMD_POST_PARAMS *param = (void *)StdHeader;
150 platform_BeforeInitPost(cb, param);
151 board_BeforeInitPost(cb, param);
152 status = module_dispatch(func, StdHeader);
153 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);
162 platform_AfterInitResume(cb, param);
163 break;
164 }
165
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300166 default:
167 {
168 break;
169 }
170
171 }
172 return status;
173}
174
175static AGESA_STATUS ramstage_dispatch(struct sysinfo *cb,
176 AGESA_STRUCT_NAME func, AMD_CONFIG_PARAMS *StdHeader)
177{
178 AGESA_STATUS status = AGESA_UNSUPPORTED;
179
180 switch (func)
181 {
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200182 case AMD_INIT_ENV:
183 {
184 AMD_ENV_PARAMS *param = (void *)StdHeader;
185 platform_BeforeInitEnv(cb, param);
186 board_BeforeInitEnv(cb, param);
187 status = module_dispatch(func, StdHeader);
188 platform_AfterInitEnv(cb, param);
189 break;
190 }
191
192 case AMD_S3LATE_RESTORE:
193 {
194 AMD_S3LATE_PARAMS *param = (void *)StdHeader;
195 platform_BeforeS3LateRestore(cb, param);
196 status = module_dispatch(func, StdHeader);
197 platform_AfterS3LateRestore(cb, param);
198 break;
199 }
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200200
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200201 case AMD_INIT_MID:
202 {
203 AMD_MID_PARAMS *param = (void *)StdHeader;
204 platform_BeforeInitMid(cb, param);
205 board_BeforeInitMid(cb, param);
206 status = module_dispatch(func, StdHeader);
207 break;
208 }
209
210 case AMD_S3_SAVE:
211 {
212 AMD_S3SAVE_PARAMS *param = (void *)StdHeader;
213 status = module_dispatch(func, StdHeader);
214 platform_AfterS3Save(cb, param);
215 break;
216 }
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300217
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200218 case AMD_INIT_LATE:
219 {
220 AMD_LATE_PARAMS *param = (void *)StdHeader;
221 status = module_dispatch(func, StdHeader);
222 platform_AfterInitLate(cb, param);
223 completion_InitLate(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 default:
228 {
229 break;
230 }
231
232 }
233 return status;
234}
235
236/* DEBUG trace helper */
237
238struct agesa_state
239{
240 u8 apic_id;
241
242 AGESA_STRUCT_NAME func;
243 const char *function_name;
244};
245
246static void state_on_entry(struct agesa_state *task, AGESA_STRUCT_NAME func,
247 const char *struct_name)
248{
249 task->apic_id = (u8) (cpuid_ebx(1) >> 24);
250 task->func = func;
251 task->function_name = struct_name;
252
253 printk(BIOS_DEBUG, "\nAPIC %02d: ** Enter %s [%08x]\n",
254 task->apic_id, task->function_name, task->func);
255}
256
257static void state_on_exit(struct agesa_state *task,
258 AMD_CONFIG_PARAMS *StdHeader)
259{
260 printk(BIOS_DEBUG, "APIC %02d: Heap in %s (%d) at 0x%08x\n",
261 task->apic_id, heap_status_name(StdHeader->HeapStatus),
262 StdHeader->HeapStatus, (u32)StdHeader->HeapBasePtr);
263
264 printk(BIOS_DEBUG, "APIC %02d: ** Exit %s [%08x]\n",
265 task->apic_id, task->function_name, task->func);
266}
267
268int agesa_execute_state(struct sysinfo *cb, AGESA_STRUCT_NAME func)
269{
270 AMD_INTERFACE_PARAMS aip;
271 union {
272 AMD_RESET_PARAMS reset;
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200273 AMD_S3LATE_PARAMS s3late;
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200274 } agesa_params;
275 void *buf = NULL;
276 size_t len = 0;
277 const char *state_name = agesa_struct_name(func);
278
279 AGESA_STATUS status, final;
280
281 struct agesa_state task;
282 memset(&task, 0, sizeof(task));
283 state_on_entry(&task, func, state_name);
284
285 aip.StdHeader = cb->StdHeader;
286
287 /* For these calls, heap is not available. */
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200288 if (func == AMD_INIT_RESET || func == AMD_S3LATE_RESTORE) {
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200289 buf = (void *) &agesa_params;
290 len = sizeof(agesa_params);
291 memcpy(buf, &cb->StdHeader, sizeof(cb->StdHeader));
292 }
293
294 status = amd_create_struct(&aip, func, buf, len);
295 ASSERT(status == AGESA_SUCCESS);
296
297 /* Must call the function buffer was allocated for.*/
298 AMD_CONFIG_PARAMS *StdHeader = aip.NewStructPtr;
299 ASSERT(StdHeader->Func == func);
300
Kyösti Mälkkia18f58b2017-07-25 11:34:43 +0300301 if (ENV_ROMSTAGE)
302 final = romstage_dispatch(cb, func, StdHeader);
303
304 if (ENV_RAMSTAGE)
305 final = ramstage_dispatch(cb, func, StdHeader);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200306
307 agesawrapper_trace(final, StdHeader, state_name);
308 ASSERT(final < AGESA_FATAL);
309
310 status = amd_release_struct(&aip);
311 ASSERT(status == AGESA_SUCCESS);
312
313 state_on_exit(&task, &aip.StdHeader);
314
315 return (final < AGESA_FATAL) ? 0 : -1;
316}
317
318#if ENV_RAMSTAGE
319
320static void amd_bs_ramstage_init(void *arg)
321{
322 struct sysinfo *cb = arg;
323
324 agesa_set_interface(cb);
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200325
326 if (!acpi_is_wakeup_s3())
327 agesa_execute_state(cb, AMD_INIT_ENV);
328 else {
329 /* We need HEAP from CBMEM early. */
330 if (IS_ENABLED(CONFIG_LATE_CBMEM_INIT))
331 cbmem_initialize();
332 agesa_execute_state(cb, AMD_S3LATE_RESTORE);
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300333 fchs3earlyrestore(&cb->StdHeader);
Kyösti Mälkki21e609c2017-03-09 20:08:15 +0200334 }
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200335}
336
337void sb_After_Pci_Restore_Init(void);
338
339static void amd_bs_dev_enable(void *arg)
340{
341 struct sysinfo *cb = arg;
342
343 if (!acpi_is_wakeup_s3())
344 agesa_execute_state(cb, AMD_INIT_MID);
345
346 /* FIXME */
347 if (IS_ENABLED(CONFIG_AMD_SB_CIMX) && acpi_is_wakeup_s3())
348 sb_After_Pci_Restore_Init();
349}
350
351static void amd_bs_post_device(void *arg)
352{
353 struct sysinfo *cb = arg;
354
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300355 if (acpi_is_wakeup_s3()) {
356 fchs3laterestore(&cb->StdHeader);
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200357 return;
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300358 }
Kyösti Mälkki28c4d2f2016-11-25 11:21:02 +0200359
360 agesa_execute_state(cb, AMD_INIT_LATE);
361
362 if (!acpi_s3_resume_allowed())
363 return;
364
365 agesa_execute_state(cb, AMD_S3_SAVE);
366}
367
368static struct sysinfo state_machine;
369
370BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, amd_bs_ramstage_init,
371 &state_machine);
372
373BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_ENTRY, amd_bs_dev_enable,
374 &state_machine);
375
376BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, amd_bs_post_device,
377 &state_machine);
378
379#endif /* ENV_RAMSTAGE */
380
381/* Empty stubs for cases board does not need to override anything. */
382void __attribute__((weak))
383board_BeforeInitReset(struct sysinfo *cb, AMD_RESET_PARAMS *Reset) { }
384void __attribute__((weak))
385board_BeforeInitEarly(struct sysinfo *cb, AMD_EARLY_PARAMS *Early) { }
386void __attribute__((weak))
387board_BeforeInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post) { }
388void __attribute__((weak))
389board_BeforeInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env) { }
390void __attribute__((weak))
391board_BeforeInitMid(struct sysinfo *cb, AMD_MID_PARAMS *Mid) { }
Kyösti Mälkki38aff1a2017-07-26 00:57:30 +0300392
393AGESA_STATUS __attribute__((weak))
394fchs3earlyrestore(AMD_CONFIG_PARAMS *StdHeader)
395{
396 return AGESA_SUCCESS;
397}
398
399AGESA_STATUS __attribute__((weak))
400fchs3laterestore(AMD_CONFIG_PARAMS *StdHeader)
401{
402 return AGESA_SUCCESS;
403}