blob: 19ec5859ac5741166232740706c7d90c20856555 [file] [log] [blame]
Angel Pons1c9a8d82022-05-07 00:26:10 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
2
3#include <assert.h>
4#include <console/console.h>
5#include <cpu/intel/haswell/haswell.h>
Angel Pons1c9a8d82022-05-07 00:26:10 +02006#include <device/pci_ops.h>
7#include <northbridge/intel/haswell/chip.h>
8#include <northbridge/intel/haswell/haswell.h>
9#include <northbridge/intel/haswell/raminit.h>
10#include <string.h>
11#include <types.h>
12
13#include "raminit_native.h"
14
15struct task_entry {
16 enum raminit_status (*task)(struct sysinfo *);
17 bool is_enabled;
18 const char *name;
19};
20
21static const struct task_entry cold_boot[] = {
Angel Pons1b254222022-05-07 13:48:53 +020022 { collect_spd_info, true, "PROCSPD", },
Angel Pons1c9a8d82022-05-07 00:26:10 +020023};
24
25/* Return a generic stepping value to make stepping checks simpler */
26static enum generic_stepping get_stepping(const uint32_t cpuid)
27{
28 switch (cpuid) {
29 case CPUID_HASWELL_A0:
30 die("Haswell stepping A0 is not supported\n");
31 case CPUID_HASWELL_B0:
32 case CPUID_HASWELL_ULT_B0:
33 case CPUID_CRYSTALWELL_B0:
34 return STEPPING_B0;
35 case CPUID_HASWELL_C0:
36 case CPUID_HASWELL_ULT_C0:
37 case CPUID_CRYSTALWELL_C0:
38 return STEPPING_C0;
39 default:
40 /** TODO: Add Broadwell support someday **/
41 die("Unknown CPUID 0x%x\n", cpuid);
42 }
43}
44
45static void initialize_ctrl(struct sysinfo *ctrl)
46{
47 const struct northbridge_intel_haswell_config *cfg = config_of_soc();
48 const enum raminit_boot_mode bootmode = ctrl->bootmode;
49
50 memset(ctrl, 0, sizeof(*ctrl));
51
52 ctrl->cpu = cpu_get_cpuid();
53 ctrl->stepping = get_stepping(ctrl->cpu);
54 ctrl->dq_pins_interleaved = cfg->dq_pins_interleaved;
55 ctrl->bootmode = bootmode;
56}
57
58static enum raminit_status try_raminit(struct sysinfo *ctrl)
59{
60 const struct task_entry *const schedule = cold_boot;
61 const size_t length = ARRAY_SIZE(cold_boot);
62
63 enum raminit_status status = RAMINIT_STATUS_UNSPECIFIED_ERROR;
64
65 for (size_t i = 0; i < length; i++) {
66 const struct task_entry *const entry = &schedule[i];
67 assert(entry);
68 assert(entry->name);
69 if (!entry->is_enabled)
70 continue;
71
72 assert(entry->task);
73 printk(RAM_DEBUG, "\nExecuting raminit task %s\n", entry->name);
74 status = entry->task(ctrl);
75 printk(RAM_DEBUG, "\n");
76 if (status) {
77 printk(BIOS_ERR, "raminit failed on step %s\n", entry->name);
78 break;
79 }
80 }
81
82 return status;
83}
84
85void raminit_main(const enum raminit_boot_mode bootmode)
86{
87 /*
88 * The mighty_ctrl struct. Will happily nuke the pre-RAM stack
89 * if left unattended. Make it static and pass pointers to it.
90 */
91 static struct sysinfo mighty_ctrl;
92
93 mighty_ctrl.bootmode = bootmode;
94 initialize_ctrl(&mighty_ctrl);
95
96 /** TODO: Try more than once **/
97 enum raminit_status status = try_raminit(&mighty_ctrl);
98
99 if (status != RAMINIT_STATUS_SUCCESS)
100 die("Memory initialization was met with utmost failure and misery\n");
101
102 /** TODO: Implement the required magic **/
103 die("NATIVE RAMINIT: More Magic (tm) required.\n");
104}