blob: 0406eeea6659d5ee81ac9b0d11c2dc83c2ba5761 [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>
22
23#include <northbridge/amd/agesa/state_machine.h>
24#include <northbridge/amd/agesa/agesa_helper.h>
25#include <northbridge/amd/agesa/BiosCallOuts.h>
26#include "amdlib.h"
27#include <cpu/amd/agesa/s3_resume.h>
28
29#include "AMD.h"
30#include "heapManager.h"
31#include "Dispatcher.h"
32
33
34#if ENV_ROMSTAGE
35#include <PlatformMemoryConfiguration.h>
36CONST PSO_ENTRY ROMDATA DefaultPlatformMemoryConfiguration[] = {PSO_END};
37#endif
38
39void agesa_set_interface(struct sysinfo *cb)
40{
41 memset(&cb->StdHeader, 0, sizeof(AMD_CONFIG_PARAMS));
42
43 cb->StdHeader.CalloutPtr = GetBiosCallout;
44}
45
46AGESA_STATUS module_dispatch(AGESA_STRUCT_NAME func,
47 AMD_CONFIG_PARAMS *StdHeader)
48{
49 MODULE_ENTRY dispatcher = AmdAgesaDispatcher;
50
51 StdHeader->Func = func;
52 return dispatcher(StdHeader);
53}
54
55static AGESA_STATUS amd_create_struct(AMD_INTERFACE_PARAMS *aip,
56 AGESA_STRUCT_NAME func, void *buf, size_t len)
57{
58 aip->AgesaFunctionName = func;
59 aip->AllocationMethod = 0;
60 aip->NewStructPtr = buf;
61 aip->NewStructSize = len;
62 if (buf != NULL && len != 0)
63 aip->AllocationMethod = ByHost;
64
65 return module_dispatch(AMD_CREATE_STRUCT, &aip->StdHeader);
66}
67
68static AGESA_STATUS amd_release_struct(AMD_INTERFACE_PARAMS *aip)
69{
70 /* Cannot release AMD_LATE_PARAMS until ACPI tables are done. */
71 if (aip->AgesaFunctionName == AMD_INIT_LATE)
72 return AGESA_SUCCESS;
73
74 return module_dispatch(AMD_RELEASE_STRUCT, &aip->StdHeader);
75}
76
77/* By design, for each valid AGESA_STRUCT_NAME, AMD_CONFIG_PARAMS
78 * can be evaluated to apply correct typecast based on Func field.
79 */
80
81static AGESA_STATUS amd_dispatch(struct sysinfo *cb,
82 AGESA_STRUCT_NAME func, AMD_CONFIG_PARAMS *StdHeader)
83{
84 AGESA_STATUS status = AGESA_UNSUPPORTED;
85
86 switch (func)
87 {
88#if ENV_ROMSTAGE
89 case AMD_INIT_RESET:
90 {
91 AMD_RESET_PARAMS *param = (void *)StdHeader;
92 platform_BeforeInitReset(cb, param);
93 board_BeforeInitReset(cb, param);
94 status = module_dispatch(func, StdHeader);
95 break;
96 }
97
98 case AMD_INIT_EARLY:
99 {
100 AMD_EARLY_PARAMS *param = (void *)StdHeader;
101 platform_BeforeInitEarly(cb, param);
102 board_BeforeInitEarly(cb, param);
103 status = module_dispatch(func, StdHeader);
104 break;
105 }
106
107 case AMD_INIT_POST:
108 {
109 AMD_POST_PARAMS *param = (void *)StdHeader;
110 platform_BeforeInitPost(cb, param);
111 board_BeforeInitPost(cb, param);
112 status = module_dispatch(func, StdHeader);
113 platform_AfterInitPost(cb, param);
114 break;
115 }
116
117 case AMD_INIT_RESUME:
118 {
119 AMD_RESUME_PARAMS *param = (void *)StdHeader;
120 platform_BeforeInitResume(cb, param);
121 status = module_dispatch(func, StdHeader);
122 platform_AfterInitResume(cb, param);
123 break;
124 }
125
126 case AMD_INIT_ENV:
127 {
128 AMD_ENV_PARAMS *param = (void *)StdHeader;
129 platform_BeforeInitEnv(cb, param);
130 board_BeforeInitEnv(cb, param);
131 status = module_dispatch(func, StdHeader);
132 platform_AfterInitEnv(cb, param);
133 break;
134 }
135
136 case AMD_S3LATE_RESTORE:
137 {
138 AMD_S3LATE_PARAMS *param = (void *)StdHeader;
139 platform_BeforeS3LateRestore(cb, param);
140 status = module_dispatch(func, StdHeader);
141 platform_AfterS3LateRestore(cb, param);
142 break;
143 }
144#endif
145#if ENV_RAMSTAGE
146 case AMD_INIT_MID:
147 {
148 AMD_MID_PARAMS *param = (void *)StdHeader;
149 platform_BeforeInitMid(cb, param);
150 board_BeforeInitMid(cb, param);
151 status = module_dispatch(func, StdHeader);
152 break;
153 }
154
155 case AMD_S3_SAVE:
156 {
157 AMD_S3SAVE_PARAMS *param = (void *)StdHeader;
158 status = module_dispatch(func, StdHeader);
159 platform_AfterS3Save(cb, param);
160 break;
161 }
162 case AMD_INIT_LATE:
163 {
164 AMD_LATE_PARAMS *param = (void *)StdHeader;
165 status = module_dispatch(func, StdHeader);
166 platform_AfterInitLate(cb, param);
167 completion_InitLate(cb, param);
168 break;
169 }
170#endif
171 default:
172 {
173 break;
174 }
175
176 }
177 return status;
178}
179
180/* DEBUG trace helper */
181
182struct agesa_state
183{
184 u8 apic_id;
185
186 AGESA_STRUCT_NAME func;
187 const char *function_name;
188};
189
190static void state_on_entry(struct agesa_state *task, AGESA_STRUCT_NAME func,
191 const char *struct_name)
192{
193 task->apic_id = (u8) (cpuid_ebx(1) >> 24);
194 task->func = func;
195 task->function_name = struct_name;
196
197 printk(BIOS_DEBUG, "\nAPIC %02d: ** Enter %s [%08x]\n",
198 task->apic_id, task->function_name, task->func);
199}
200
201static void state_on_exit(struct agesa_state *task,
202 AMD_CONFIG_PARAMS *StdHeader)
203{
204 printk(BIOS_DEBUG, "APIC %02d: Heap in %s (%d) at 0x%08x\n",
205 task->apic_id, heap_status_name(StdHeader->HeapStatus),
206 StdHeader->HeapStatus, (u32)StdHeader->HeapBasePtr);
207
208 printk(BIOS_DEBUG, "APIC %02d: ** Exit %s [%08x]\n",
209 task->apic_id, task->function_name, task->func);
210}
211
212int agesa_execute_state(struct sysinfo *cb, AGESA_STRUCT_NAME func)
213{
214 AMD_INTERFACE_PARAMS aip;
215 union {
216 AMD_RESET_PARAMS reset;
217 } agesa_params;
218 void *buf = NULL;
219 size_t len = 0;
220 const char *state_name = agesa_struct_name(func);
221
222 AGESA_STATUS status, final;
223
224 struct agesa_state task;
225 memset(&task, 0, sizeof(task));
226 state_on_entry(&task, func, state_name);
227
228 aip.StdHeader = cb->StdHeader;
229
230 /* For these calls, heap is not available. */
231 if (func == AMD_INIT_RESET) {
232 buf = (void *) &agesa_params;
233 len = sizeof(agesa_params);
234 memcpy(buf, &cb->StdHeader, sizeof(cb->StdHeader));
235 }
236
237 status = amd_create_struct(&aip, func, buf, len);
238 ASSERT(status == AGESA_SUCCESS);
239
240 /* Must call the function buffer was allocated for.*/
241 AMD_CONFIG_PARAMS *StdHeader = aip.NewStructPtr;
242 ASSERT(StdHeader->Func == func);
243
244 final = amd_dispatch(cb, func, StdHeader);
245
246 agesawrapper_trace(final, StdHeader, state_name);
247 ASSERT(final < AGESA_FATAL);
248
249 status = amd_release_struct(&aip);
250 ASSERT(status == AGESA_SUCCESS);
251
252 state_on_exit(&task, &aip.StdHeader);
253
254 return (final < AGESA_FATAL) ? 0 : -1;
255}
256
257#if ENV_RAMSTAGE
258
259static void amd_bs_ramstage_init(void *arg)
260{
261 struct sysinfo *cb = arg;
262
263 agesa_set_interface(cb);
264}
265
266void sb_After_Pci_Restore_Init(void);
267
268static void amd_bs_dev_enable(void *arg)
269{
270 struct sysinfo *cb = arg;
271
272 if (!acpi_is_wakeup_s3())
273 agesa_execute_state(cb, AMD_INIT_MID);
274
275 /* FIXME */
276 if (IS_ENABLED(CONFIG_AMD_SB_CIMX) && acpi_is_wakeup_s3())
277 sb_After_Pci_Restore_Init();
278}
279
280static void amd_bs_post_device(void *arg)
281{
282 struct sysinfo *cb = arg;
283
284 if (acpi_is_wakeup_s3())
285 return;
286
287 agesa_execute_state(cb, AMD_INIT_LATE);
288
289 if (!acpi_s3_resume_allowed())
290 return;
291
292 agesa_execute_state(cb, AMD_S3_SAVE);
293}
294
295static struct sysinfo state_machine;
296
297BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, amd_bs_ramstage_init,
298 &state_machine);
299
300BOOT_STATE_INIT_ENTRY(BS_DEV_ENABLE, BS_ON_ENTRY, amd_bs_dev_enable,
301 &state_machine);
302
303BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, amd_bs_post_device,
304 &state_machine);
305
306#endif /* ENV_RAMSTAGE */
307
308/* Empty stubs for cases board does not need to override anything. */
309void __attribute__((weak))
310board_BeforeInitReset(struct sysinfo *cb, AMD_RESET_PARAMS *Reset) { }
311void __attribute__((weak))
312board_BeforeInitEarly(struct sysinfo *cb, AMD_EARLY_PARAMS *Early) { }
313void __attribute__((weak))
314board_BeforeInitPost(struct sysinfo *cb, AMD_POST_PARAMS *Post) { }
315void __attribute__((weak))
316board_BeforeInitEnv(struct sysinfo *cb, AMD_ENV_PARAMS *Env) { }
317void __attribute__((weak))
318board_BeforeInitMid(struct sysinfo *cb, AMD_MID_PARAMS *Mid) { }