spd/lp5: Add Hynix memory part
[coreboot2.git] / src / cpu / x86 / lapic / lapic.c
blob6afd6c56ea798f7d4557fd3a9e151bdef21547ea
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <assert.h>
4 #include <console/console.h>
5 #include <cpu/cpu.h>
6 #include <cpu/x86/lapic.h>
7 #include <cpu/x86/lapic_def.h>
8 #include <cpu/x86/msr.h>
9 #include <smp/node.h>
10 #include <types.h>
12 static bool quirk_x2apic_allowed;
14 void enable_lapic_mode(bool try_set_x2apic)
16 uintptr_t apic_base;
17 bool use_x2apic = false;
18 msr_t msr;
20 msr = rdmsr(LAPIC_BASE_MSR);
21 if (!(msr.lo & LAPIC_BASE_MSR_ENABLE)) {
22 msr.hi &= 0xffffff00;
23 msr.lo &= ~LAPIC_BASE_MSR_ADDR_MASK;
24 msr.lo |= LAPIC_DEFAULT_BASE;
25 msr.lo |= LAPIC_BASE_MSR_ENABLE;
26 wrmsr(LAPIC_BASE_MSR, msr);
27 msr = rdmsr(LAPIC_BASE_MSR);
30 ASSERT(msr.lo & LAPIC_BASE_MSR_ENABLE);
32 apic_base = msr.lo & LAPIC_BASE_MSR_ADDR_MASK;
33 ASSERT(apic_base == LAPIC_DEFAULT_BASE);
35 if (try_set_x2apic)
36 use_x2apic = !!(cpu_get_feature_flags_ecx() & CPUID_X2APIC);
38 if (use_x2apic == !!(msr.lo & LAPIC_BASE_MSR_X2APIC_MODE)) {
39 printk(BIOS_INFO, "LAPIC 0x%x in %s mode.\n", lapicid(),
40 use_x2apic ? "X2APIC" : "XAPIC");
41 } else if (use_x2apic) {
42 msr.lo |= LAPIC_BASE_MSR_X2APIC_MODE;
43 wrmsr(LAPIC_BASE_MSR, msr);
44 msr = rdmsr(LAPIC_BASE_MSR);
45 ASSERT(!!(msr.lo & LAPIC_BASE_MSR_X2APIC_MODE));
46 printk(BIOS_INFO, "LAPIC 0x%x switched to X2APIC mode.\n", lapicid());
47 } else {
48 die("Switching from X2APIC to XAPIC mode is not implemented.");
51 if (CONFIG(X2APIC_LATE_WORKAROUND) && use_x2apic)
52 quirk_x2apic_allowed = true;
55 void enable_lapic(void)
57 bool try_set_x2apic = true;
59 if (CONFIG(XAPIC_ONLY))
60 try_set_x2apic = false;
61 else if (CONFIG(X2APIC_LATE_WORKAROUND))
62 try_set_x2apic = quirk_x2apic_allowed;
64 enable_lapic_mode(try_set_x2apic);
67 uintptr_t cpu_get_lapic_addr(void)
69 return LAPIC_DEFAULT_BASE;
72 void setup_lapic_interrupts(void)
75 * Set Task Priority to 'accept all'.
77 lapic_update32(LAPIC_TASKPRI, ~LAPIC_TPRI_MASK, 0);
79 /* Set spurious interrupt vector to 0 and keep LAPIC enabled to
80 be able to clear LVT register mask bits. */
81 lapic_update32(LAPIC_SPIV, ~LAPIC_VECTOR_MASK, LAPIC_SPIV_ENABLE);
83 /* Put the local APIC in virtual wire mode */
84 uint32_t mask = LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | LAPIC_INPUT_POLARITY |
85 LAPIC_DELIVERY_MODE_MASK;
87 if (boot_cpu())
88 lapic_update32(LAPIC_LVT0, ~mask, LAPIC_DELIVERY_MODE_EXTINT);
89 else
90 lapic_update32(LAPIC_LVT0, ~mask, LAPIC_LVT_MASKED |
91 LAPIC_DELIVERY_MODE_EXTINT);
93 lapic_update32(LAPIC_LVT1, ~mask, LAPIC_DELIVERY_MODE_NMI);