2 * This file is part of the coreboot project.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <arch/acpi.h>
17 #include <console/console.h>
18 #include <timestamp.h>
19 #include <amdblocks/biosram.h>
20 #include <amdblocks/s3_resume.h>
21 #include <amdblocks/agesawrapper.h>
22 #include <amdblocks/BiosCallOuts.h>
23 #include <soc/pci_devs.h>
24 #include <soc/northbridge.h>
27 void __weak
SetMemParams(AMD_POST_PARAMS
*PostParams
) {}
28 void __weak
OemPostParams(AMD_POST_PARAMS
*PostParams
) {}
30 /* ACPI table pointers returned by AmdInitLate */
31 static void *DmiTable
;
32 static void *AcpiPstate
;
33 static void *AcpiSrat
;
34 static void *AcpiSlit
;
36 static void *AcpiWheaMce
;
37 static void *AcpiWheaCmc
;
38 static void *AcpiAlib
;
39 static void *AcpiIvrs
;
40 static void *AcpiCrat
;
42 static AGESA_STATUS
module_dispatch(AGESA_STRUCT_NAME func
,
43 AMD_CONFIG_PARAMS
*StdHeader
)
45 MODULE_ENTRY dispatcher
= agesa_get_dispatcher();
48 return AGESA_UNSUPPORTED
;
50 StdHeader
->Func
= func
;
51 return dispatcher(StdHeader
);
54 static AGESA_STATUS
amd_dispatch(void *Params
)
56 AMD_CONFIG_PARAMS
*StdHeader
= Params
;
57 return module_dispatch(StdHeader
->Func
, StdHeader
);
60 AGESA_STATUS
amd_late_run_ap_task(AP_EXE_PARAMS
*ApExeParams
)
62 AMD_CONFIG_PARAMS
*StdHeader
= (void *)ApExeParams
;
63 return module_dispatch(AMD_LATE_RUN_AP_TASK
, StdHeader
);
66 static AGESA_STATUS
amd_create_struct(AMD_INTERFACE_PARAMS
*aip
,
67 AGESA_STRUCT_NAME func
, void *buf
, size_t len
)
71 /* Should clone entire StdHeader here. */
72 memset(aip
, 0, sizeof(*aip
));
73 aip
->StdHeader
.CalloutPtr
= &GetBiosCallout
;
75 /* If we provide the buffer, API expects it to have
76 StdHeader already filled. */
77 if (buf
!= NULL
&& len
>= sizeof(aip
->StdHeader
)) {
78 memcpy(buf
, &aip
->StdHeader
, sizeof(aip
->StdHeader
));
79 aip
->AllocationMethod
= ByHost
;
80 aip
->NewStructPtr
= buf
;
81 aip
->NewStructSize
= len
;
84 aip
->AllocationMethod
= PreMemHeap
;
86 aip
->AllocationMethod
= PostMemDram
;
89 aip
->AgesaFunctionName
= func
;
90 status
= module_dispatch(AMD_CREATE_STRUCT
, &aip
->StdHeader
);
92 if (status
!= AGESA_SUCCESS
) {
93 printk(BIOS_ERR
, "Error: AmdCreateStruct() for 0x%x returned 0x%x. "
94 "Proper system initialization may not be possible.\n",
95 aip
->AgesaFunctionName
, status
);
98 if (!aip
->NewStructPtr
)
99 die("No AGESA structure created");
104 static AGESA_STATUS
amd_release_struct(AMD_INTERFACE_PARAMS
*aip
)
106 return module_dispatch(AMD_RELEASE_STRUCT
, &aip
->StdHeader
);
109 static AGESA_STATUS
amd_init_reset(AMD_RESET_PARAMS
*ResetParams
)
113 SetFchResetParams(&ResetParams
->FchInterface
);
115 timestamp_add_now(TS_AGESA_INIT_RESET_START
);
116 status
= amd_dispatch(ResetParams
);
117 timestamp_add_now(TS_AGESA_INIT_RESET_DONE
);
122 static AGESA_STATUS
amd_init_early(AMD_EARLY_PARAMS
*EarlyParams
)
126 soc_customize_init_early(EarlyParams
);
127 OemCustomizeInitEarly(EarlyParams
);
129 timestamp_add_now(TS_AGESA_INIT_EARLY_START
);
130 status
= amd_dispatch(EarlyParams
);
131 timestamp_add_now(TS_AGESA_INIT_EARLY_DONE
);
136 static void print_init_post_settings(AMD_POST_PARAMS
*parms
)
138 u64 syslimit
, bottomio
, uma_size
, uma_start
;
141 switch (parms
->MemConfig
.UmaMode
) {
146 mode
= "UMA_SPECIFIED";
156 syslimit
= (u64
)(parms
->MemConfig
.SysLimit
+ 1) * 64 * KiB
- 1;
157 bottomio
= (u64
)parms
->MemConfig
.BottomIo
* 64 * KiB
;
159 uma_size
= (u64
)parms
->MemConfig
.UmaSize
* 64 * KiB
;
160 uma_start
= (u64
)parms
->MemConfig
.UmaBase
* 64 * KiB
;
162 printk(BIOS_SPEW
, "AGESA set: umamode %s\n", mode
);
163 printk(BIOS_SPEW
, " : syslimit 0x%llx, bottomio 0x%08llx\n",
165 printk(BIOS_SPEW
, " : uma size %lluMB, uma start 0x%08llx\n",
166 uma_size
/ MiB
, uma_start
);
169 static AGESA_STATUS
amd_init_post(AMD_POST_PARAMS
*PostParams
)
173 PostParams
->MemConfig
.UmaMode
= CONFIG(GFXUMA
) ? UMA_AUTO
: UMA_NONE
;
174 PostParams
->MemConfig
.UmaSize
= 0;
175 PostParams
->MemConfig
.BottomIo
= (uint16_t)
176 (CONFIG_BOTTOMIO_POSITION
>> 24);
178 SetMemParams(PostParams
);
179 OemPostParams(PostParams
);
180 printk(BIOS_SPEW
, "DRAM clear on reset: %s\n",
181 (PostParams
->MemConfig
.EnableMemClr
== FALSE
) ? "Keep" :
182 (PostParams
->MemConfig
.EnableMemClr
== TRUE
) ? "Clear" :
186 timestamp_add_now(TS_AGESA_INIT_POST_START
);
187 status
= amd_dispatch(PostParams
);
188 timestamp_add_now(TS_AGESA_INIT_POST_DONE
);
191 * AGESA passes back the base and size of UMA. This is the only
192 * opportunity to get and save these settings to be used in resource
193 * allocation. We also need to allocate the top of low memory.
194 * If UMA is below 4GiB, UMA base is the top of low memory, otherwise
195 * Sub4GCachetop is the top of low memory.
196 * With UMA_NONE we see UmaBase==0.
199 if (PostParams
->MemConfig
.UmaBase
&&
200 (PostParams
->MemConfig
.UmaBase
< ((4ull * GiB
) >> 16)))
201 top
= PostParams
->MemConfig
.UmaBase
<< 16;
203 top
= PostParams
->MemConfig
.Sub4GCacheTop
;
204 backup_top_of_low_cacheable(top
);
206 save_uma_size(PostParams
->MemConfig
.UmaSize
* 64 * KiB
);
207 save_uma_base((u64
)PostParams
->MemConfig
.UmaBase
* 64 * KiB
);
209 print_init_post_settings(PostParams
);
214 static AGESA_STATUS
amd_init_env(AMD_ENV_PARAMS
*EnvParams
)
218 SetFchEnvParams(&EnvParams
->FchInterface
);
219 SetNbEnvParams(&EnvParams
->GnbEnvConfiguration
);
221 timestamp_add_now(TS_AGESA_INIT_ENV_START
);
222 status
= amd_dispatch(EnvParams
);
223 timestamp_add_now(TS_AGESA_INIT_ENV_DONE
);
228 void *agesawrapper_getlateinitptr(int pick
)
254 static AGESA_STATUS
amd_init_mid(AMD_MID_PARAMS
*MidParams
)
258 /* Enable MMIO on AMD CPU Address Map Controller */
261 SetFchMidParams(&MidParams
->FchInterface
);
262 SetNbMidParams(&MidParams
->GnbMidConfiguration
);
264 timestamp_add_now(TS_AGESA_INIT_MID_START
);
265 status
= amd_dispatch(MidParams
);
266 timestamp_add_now(TS_AGESA_INIT_MID_DONE
);
271 static AGESA_STATUS
amd_init_late(AMD_LATE_PARAMS
*LateParams
)
275 const struct device
*dev
= pcidev_path_on_root(IOMMU_DEVFN
);
276 if (dev
&& dev
->enabled
) {
277 LateParams
->GnbLateConfiguration
.GnbIoapicId
= CONFIG_MAX_CPUS
279 LateParams
->GnbLateConfiguration
.FchIoapicId
= CONFIG_MAX_CPUS
;
282 timestamp_add_now(TS_AGESA_INIT_LATE_START
);
283 Status
= amd_dispatch(LateParams
);
284 timestamp_add_now(TS_AGESA_INIT_LATE_DONE
);
286 DmiTable
= LateParams
->DmiTable
;
287 AcpiPstate
= LateParams
->AcpiPState
;
289 AcpiWheaMce
= LateParams
->AcpiWheaMce
;
290 AcpiWheaCmc
= LateParams
->AcpiWheaCmc
;
291 AcpiAlib
= LateParams
->AcpiAlib
;
292 AcpiIvrs
= LateParams
->AcpiIvrs
;
293 AcpiCrat
= LateParams
->AcpiCrat
;
295 printk(BIOS_DEBUG
, "DmiTable:%p, AcpiPstatein: %p, AcpiSrat:%p,"
296 "AcpiSlit:%p, Mce:%p, Cmc:%p,"
297 "Alib:%p, AcpiIvrs:%p in %s\n",
298 DmiTable
, AcpiPstate
, AcpiSrat
,
299 AcpiSlit
, AcpiWheaMce
, AcpiWheaCmc
,
300 AcpiAlib
, AcpiIvrs
, __func__
);
305 static AGESA_STATUS
amd_init_rtb(AMD_RTB_PARAMS
*RtbParams
)
309 timestamp_add_now(TS_AGESA_INIT_RTB_START
);
310 Status
= amd_dispatch(RtbParams
);
311 timestamp_add_now(TS_AGESA_INIT_RTB_DONE
);
313 if (Status
!= AGESA_SUCCESS
)
316 if (OemS3Save(&RtbParams
->S3DataBlock
) != AGESA_SUCCESS
)
317 printk(BIOS_ERR
, "S3 data not saved, resuming impossible\n");
322 static AGESA_STATUS
amd_init_resume(AMD_RESUME_PARAMS
*InitResumeParams
)
326 OemInitResume(&InitResumeParams
->S3DataBlock
);
328 timestamp_add_now(TS_AGESA_INIT_RESUME_START
);
329 status
= amd_dispatch(InitResumeParams
);
330 timestamp_add_now(TS_AGESA_INIT_RESUME_DONE
);
335 static AGESA_STATUS
amd_s3late_restore(AMD_S3LATE_PARAMS
*S3LateParams
)
341 OemS3LateRestore(&S3LateParams
->S3DataBlock
);
343 timestamp_add_now(TS_AGESA_S3_LATE_START
);
344 Status
= amd_dispatch(S3LateParams
);
345 timestamp_add_now(TS_AGESA_S3_LATE_DONE
);
350 static AGESA_STATUS
amd_s3final_restore(AMD_S3FINAL_PARAMS
*S3FinalParams
)
354 OemS3LateRestore(&S3FinalParams
->S3DataBlock
);
356 timestamp_add_now(TS_AGESA_S3_FINAL_START
);
357 Status
= amd_dispatch(S3FinalParams
);
358 timestamp_add_now(TS_AGESA_S3_FINAL_DONE
);
363 static AGESA_STATUS
romstage_dispatch(AMD_CONFIG_PARAMS
*StdHeader
)
365 void *Params
= StdHeader
;
367 switch (StdHeader
->Func
) {
369 return amd_init_reset(Params
);
371 return amd_init_early(Params
);
373 return amd_init_post(Params
);
374 case AMD_INIT_RESUME
:
375 return amd_init_resume(Params
);
377 return AGESA_UNSUPPORTED
;
381 static AGESA_STATUS
ramstage_dispatch(AMD_CONFIG_PARAMS
*StdHeader
)
383 void *Params
= StdHeader
;
385 switch (StdHeader
->Func
) {
387 return amd_init_env(Params
);
389 return amd_init_mid(Params
);
391 return amd_init_late(Params
);
393 return amd_init_rtb(Params
);
394 case AMD_S3LATE_RESTORE
:
395 return amd_s3late_restore(Params
);
396 case AMD_S3FINAL_RESTORE
:
397 return amd_s3final_restore(Params
);
399 return AGESA_UNSUPPORTED
;
404 AGESA_STATUS
agesa_execute_state(AGESA_STRUCT_NAME func
)
406 AGESA_STATUS status
= AGESA_UNSUPPORTED
;
407 AMD_CONFIG_PARAMS
template = {};
408 AMD_CONFIG_PARAMS
*StdHeader
= &template;
409 AMD_INTERFACE_PARAMS AmdParamStruct
;
410 AMD_INTERFACE_PARAMS
*aip
= &AmdParamStruct
;
412 AMD_RESET_PARAMS ResetParams
;
413 AMD_S3LATE_PARAMS S3LateParams
;
414 AMD_S3FINAL_PARAMS S3FinalParams
;
417 if ((func
== AMD_INIT_RESET
) || (func
== AMD_S3LATE_RESTORE
) ||
418 (func
== AMD_S3FINAL_RESTORE
)) {
419 memset(&sp
, 0, sizeof(sp
));
420 amd_create_struct(aip
, func
, &sp
, sizeof(sp
));
422 amd_create_struct(aip
, func
, NULL
, 0);
425 StdHeader
= aip
->NewStructPtr
;
426 StdHeader
->Func
= func
;
429 status
= romstage_dispatch(StdHeader
);
431 status
= ramstage_dispatch(StdHeader
);
433 amd_release_struct(aip
);