summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2014-11-12 22:42:27 -0700
committerSimon Glass <sjg@chromium.org>2014-11-21 07:34:15 +0100
commit3eafce05278f867678a66efd867f398cc055359a (patch)
tree9138917abe452743e2eac74b1cfab76d11efca4e
parenta49e3c7f09abf4961f2945275338c3a0c18b9b61 (diff)
x86: ivybridge: Add LAPIC support
The local advanced programmable interrupt controller is not used much in U-Boot but we do need to set it up. Add basic support for this, which will be extended as needed. Signed-off-by: Simon Glass <sjg@chromium.org>
-rw-r--r--arch/x86/cpu/ivybridge/cpu.c3
-rw-r--r--arch/x86/include/asm/lapic.h59
-rw-r--r--arch/x86/include/asm/lapic_def.h101
3 files changed, 163 insertions, 0 deletions
diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c
index d5be2f587f..60976db44d 100644
--- a/arch/x86/cpu/ivybridge/cpu.c
+++ b/arch/x86/cpu/ivybridge/cpu.c
@@ -16,6 +16,7 @@
#include <fdtdec.h>
#include <asm/cpu.h>
#include <asm/io.h>
+#include <asm/lapic.h>
#include <asm/msr.h>
#include <asm/mtrr.h>
#include <asm/pci.h>
@@ -283,6 +284,8 @@ int print_cpuinfo(void)
if (ret)
return ret;
+ enable_lapic();
+
ret = microcode_update_intel();
if (ret && ret != -ENOENT && ret != -EEXIST)
return ret;
diff --git a/arch/x86/include/asm/lapic.h b/arch/x86/include/asm/lapic.h
new file mode 100644
index 0000000000..948e643a7e
--- /dev/null
+++ b/arch/x86/include/asm/lapic.h
@@ -0,0 +1,59 @@
+/*
+ * From Coreboot file of same name
+ *
+ * Copyright (C) 2014 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _ARCH_ASM_LAPIC_H
+#define _ARCH_ASM_LAPIC_H
+
+#include <asm/io.h>
+#include <asm/lapic_def.h>
+#include <asm/msr.h>
+#include <asm/processor.h>
+
+static inline __attribute__((always_inline))
+ unsigned long lapic_read(unsigned long reg)
+{
+ return readl(LAPIC_DEFAULT_BASE + reg);
+}
+
+static inline __attribute__((always_inline))
+ void lapic_write(unsigned long reg, unsigned long val)
+{
+ writel(val, LAPIC_DEFAULT_BASE + reg);
+}
+
+static inline __attribute__((always_inline)) void lapic_wait_icr_idle(void)
+{
+ do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY);
+}
+
+static inline void enable_lapic(void)
+{
+ msr_t msr;
+
+ msr = msr_read(LAPIC_BASE_MSR);
+ msr.hi &= 0xffffff00;
+ msr.lo &= 0x000007ff;
+ msr.lo |= LAPIC_DEFAULT_BASE | (1 << 11);
+ msr_write(LAPIC_BASE_MSR, msr);
+}
+
+static inline void disable_lapic(void)
+{
+ msr_t msr;
+
+ msr = msr_read(LAPIC_BASE_MSR);
+ msr.lo &= ~(1 << 11);
+ msr_write(LAPIC_BASE_MSR, msr);
+}
+
+static inline __attribute__((always_inline)) unsigned long lapicid(void)
+{
+ return lapic_read(LAPIC_ID) >> 24;
+}
+
+#endif
diff --git a/arch/x86/include/asm/lapic_def.h b/arch/x86/include/asm/lapic_def.h
new file mode 100644
index 0000000000..722ceadaa4
--- /dev/null
+++ b/arch/x86/include/asm/lapic_def.h
@@ -0,0 +1,101 @@
+/*
+ * Taken from the Coreboot file of the same name
+ *
+ * (C) Copyright 2014 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef _ASM_LAPIC_DEF_H
+#define _ASM_LAPIC_DEF_H
+
+#define LAPIC_BASE_MSR 0x1B
+#define LAPIC_BASE_MSR_BOOTSTRAP_PROCESSOR (1 << 8)
+#define LAPIC_BASE_MSR_ENABLE (1 << 11)
+#define LAPIC_BASE_MSR_ADDR_MASK 0xFFFFF000
+
+#define LOCAL_APIC_ADDR 0xfee00000
+#define LAPIC_DEFAULT_BASE LOCAL_APIC_ADDR
+
+#define LAPIC_ID 0x020
+#define LAPIC_LVR 0x030
+#define LAPIC_TASKPRI 0x80
+#define LAPIC_TPRI_MASK 0xFF
+#define LAPIC_ARBID 0x090
+#define LAPIC_RRR 0x0C0
+#define LAPIC_SVR 0x0f0
+#define LAPIC_SPIV 0x0f0
+#define LAPIC_SPIV_ENABLE 0x100
+#define LAPIC_ESR 0x280
+#define LAPIC_ESR_SEND_CS 0x00001
+#define LAPIC_ESR_RECV_CS 0x00002
+#define LAPIC_ESR_SEND_ACC 0x00004
+#define LAPIC_ESR_RECV_ACC 0x00008
+#define LAPIC_ESR_SENDILL 0x00020
+#define LAPIC_ESR_RECVILL 0x00040
+#define LAPIC_ESR_ILLREGA 0x00080
+#define LAPIC_ICR 0x300
+#define LAPIC_DEST_SELF 0x40000
+#define LAPIC_DEST_ALLINC 0x80000
+#define LAPIC_DEST_ALLBUT 0xC0000
+#define LAPIC_ICR_RR_MASK 0x30000
+#define LAPIC_ICR_RR_INVALID 0x00000
+#define LAPIC_ICR_RR_INPROG 0x10000
+#define LAPIC_ICR_RR_VALID 0x20000
+#define LAPIC_INT_LEVELTRIG 0x08000
+#define LAPIC_INT_ASSERT 0x04000
+#define LAPIC_ICR_BUSY 0x01000
+#define LAPIC_DEST_LOGICAL 0x00800
+#define LAPIC_DM_FIXED 0x00000
+#define LAPIC_DM_LOWEST 0x00100
+#define LAPIC_DM_SMI 0x00200
+#define LAPIC_DM_REMRD 0x00300
+#define LAPIC_DM_NMI 0x00400
+#define LAPIC_DM_INIT 0x00500
+#define LAPIC_DM_STARTUP 0x00600
+#define LAPIC_DM_EXTINT 0x00700
+#define LAPIC_VECTOR_MASK 0x000FF
+#define LAPIC_ICR2 0x310
+#define GET_LAPIC_DEST_FIELD(x) (((x) >> 24) & 0xFF)
+#define SET_LAPIC_DEST_FIELD(x) ((x) << 24)
+#define LAPIC_LVTT 0x320
+#define LAPIC_LVTPC 0x340
+#define LAPIC_LVT0 0x350
+#define LAPIC_LVT_TIMER_BASE_MASK (0x3 << 18)
+#define GET_LAPIC_TIMER_BASE(x) (((x) >> 18) & 0x3)
+#define SET_LAPIC_TIMER_BASE(x) (((x) << 18))
+#define LAPIC_TIMER_BASE_CLKIN 0x0
+#define LAPIC_TIMER_BASE_TMBASE 0x1
+#define LAPIC_TIMER_BASE_DIV 0x2
+#define LAPIC_LVT_TIMER_PERIODIC (1 << 17)
+#define LAPIC_LVT_MASKED (1 << 16)
+#define LAPIC_LVT_LEVEL_TRIGGER (1 << 15)
+#define LAPIC_LVT_REMOTE_IRR (1 << 14)
+#define LAPIC_INPUT_POLARITY (1 << 13)
+#define LAPIC_SEND_PENDING (1 << 12)
+#define LAPIC_LVT_RESERVED_1 (1 << 11)
+#define LAPIC_DELIVERY_MODE_MASK (7 << 8)
+#define LAPIC_DELIVERY_MODE_FIXED (0 << 8)
+#define LAPIC_DELIVERY_MODE_NMI (4 << 8)
+#define LAPIC_DELIVERY_MODE_EXTINT (7 << 8)
+#define GET_LAPIC_DELIVERY_MODE(x) (((x) >> 8) & 0x7)
+#define SET_LAPIC_DELIVERY_MODE(x, y) (((x) & ~0x700)|((y) << 8))
+#define LAPIC_MODE_FIXED 0x0
+#define LAPIC_MODE_NMI 0x4
+#define LAPIC_MODE_EXINT 0x7
+#define LAPIC_LVT1 0x360
+#define LAPIC_LVTERR 0x370
+#define LAPIC_TMICT 0x380
+#define LAPIC_TMCCT 0x390
+#define LAPIC_TDCR 0x3E0
+#define LAPIC_TDR_DIV_TMBASE (1 << 2)
+#define LAPIC_TDR_DIV_1 0xB
+#define LAPIC_TDR_DIV_2 0x0
+#define LAPIC_TDR_DIV_4 0x1
+#define LAPIC_TDR_DIV_8 0x2
+#define LAPIC_TDR_DIV_16 0x3
+#define LAPIC_TDR_DIV_32 0x8
+#define LAPIC_TDR_DIV_64 0x9
+#define LAPIC_TDR_DIV_128 0xA
+
+#endif