Hi Simon, On Wed, Nov 12, 2014 at 8:18 AM, Simon Glass <s...@chromium.org> wrote: > Add code to set up the Local Advanced Peripheral Interrupt Controller. > > Signed-off-by: Simon Glass <s...@chromium.org> > --- > > arch/x86/cpu/Makefile | 1 + > arch/x86/cpu/lapic.c | 68 ++++++++++++++++++++++++ > arch/x86/include/asm/lapic.h | 123 > +++++++++++++++++++++++++++++++++++++++++++ > arch/x86/include/asm/post.h | 1 + > 4 files changed, 193 insertions(+) > create mode 100644 arch/x86/cpu/lapic.c > > diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile > index 1327f08..adfd258 100644 > --- a/arch/x86/cpu/Makefile > +++ b/arch/x86/cpu/Makefile > @@ -11,5 +11,6 @@ > extra-y = start.o > obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o > obj-y += interrupts.o cpu.o call64.o > +obj-y += lapic.o > obj-$(CONFIG_PCI) += pci.o > obj-y += turbo.o > diff --git a/arch/x86/cpu/lapic.c b/arch/x86/cpu/lapic.c > new file mode 100644 > index 0000000..8191d84 > --- /dev/null > +++ b/arch/x86/cpu/lapic.c > @@ -0,0 +1,68 @@ > +/* > + * From coreboot file of same name > + * > + * Copyright (C) 2008-2009 coresystems GmbH > + * Copyright (C) 2014 Google, Inc > + * > + * SPDX-License-Identifier: GPL-2.0 > + */ > + > +#include <common.h> > +#include <asm/msr.h> > +#include <asm/io.h> > +#include <asm/lapic.h> > +#include <asm/post.h> > + > +void lapic_setup(void) > +{ > +#if NEED_LAPIC == 1 > + /* Only Pentium Pro and later have those MSR stuff */ > + msr_t msr; > + > + debug("Setting up local apic: "); > + > + /* Enable the local apic */ > + msr = msr_read(LAPIC_BASE_MSR); > + msr.lo |= LAPIC_BASE_MSR_ENABLE; > + msr.lo &= ~LAPIC_BASE_MSR_ADDR_MASK; > + msr.lo |= LAPIC_DEFAULT_BASE; > + msr_write(LAPIC_BASE_MSR, msr); > +
Please replace above wih enable_lapic() which is already defined in lapic.h in your last patch series. > + /* > + * Set Task Priority to 'accept all'. > + */ > + lapic_write_around(LAPIC_TASKPRI, > + lapic_read_around(LAPIC_TASKPRI) & > ~LAPIC_TPRI_MASK); > + > + /* Put the local apic in virtual wire mode */ > + lapic_write_around(LAPIC_SPIV, (lapic_read_around(LAPIC_SPIV) & > + ~(LAPIC_VECTOR_MASK)) | LAPIC_SPIV_ENABLE); > + lapic_write_around(LAPIC_LVT0, (lapic_read_around(LAPIC_LVT0) & > + ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | > + LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY | > + LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 | > + LAPIC_DELIVERY_MODE_MASK)) | > + (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING | > + LAPIC_DELIVERY_MODE_EXTINT)); > + lapic_write_around(LAPIC_LVT1, (lapic_read_around(LAPIC_LVT1) & > + ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | > + LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY | > + LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 | > + LAPIC_DELIVERY_MODE_MASK)) | > + (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING | > + LAPIC_DELIVERY_MODE_NMI)); > + > + debug("apic_id: 0x%02lx, ", lapicid()); > +#else /* !NEED_LLAPIC */ > + /* Only Pentium Pro and later have those MSR stuff */ > + msr_t msr; > + > + debug("Disabling local apic:"); > + > + msr = msr_read(LAPIC_BASE_MSR); > + msr.lo &= ~LAPIC_BASE_MSR_ENABLE; > + msr_write(LAPIC_BASE_MSR, msr); Please replace above wih disable_lapic() which is already defined in lapic.h in your last patch series. > +#endif /* !NEED_LAPIC */ > + debug("done.\n"); > + post_code(POST_LAPIC); > +} > diff --git a/arch/x86/include/asm/lapic.h b/arch/x86/include/asm/lapic.h > index 948e643..ab00a18 100644 > --- a/arch/x86/include/asm/lapic.h > +++ b/arch/x86/include/asm/lapic.h > @@ -14,6 +14,13 @@ > #include <asm/msr.h> > #include <asm/processor.h> > > +/* See if I need to initialize the local apic */ > +#if CONFIG_SMP || CONFIG_IOAPIC > +# define NEED_LAPIC 1 > +#else > +# define NEED_LAPIC 0 > +#endif > + > static inline __attribute__((always_inline)) > unsigned long lapic_read(unsigned long reg) > { > @@ -56,4 +63,120 @@ static inline __attribute__((always_inline)) unsigned > long lapicid(void) > return lapic_read(LAPIC_ID) >> 24; > } > > +#if !CONFIG_AP_IN_SIPI_WAIT > +/* If we need to go back to sipi wait, we use the long non-inlined version of > + * this function in lapic_cpu_init.c > + */ > +static inline __attribute__((always_inline)) void stop_this_cpu(void) > +{ > + /* Called by an AP when it is ready to halt and wait for a new task */ > + for (;;) > + cpu_hlt(); > +} > +#else > +void stop_this_cpu(void); > +#endif > + > +#if !defined(__PRE_RAM__) __PRE_RAM__ is a coreboot stuff. Please clean it up. > + > +#define xchg(ptr, v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \ > + sizeof(*(ptr)))) > + > +struct __xchg_dummy { unsigned long a[100]; }; > +#define __xg(x) ((struct __xchg_dummy *)(x)) > + > +/* > + * Note: no "lock" prefix even on SMP: xchg always implies lock anyway > + * Note 2: xchg has side effect, so that attribute volatile is necessary, > + * but generally the primitive is invalid, *ptr is output argument. > --ANK > + */ > +static inline unsigned long __xchg(unsigned long x, volatile void *ptr, > + int size) > +{ > + switch (size) { > + case 1: > + __asm__ __volatile__("xchgb %b0,%1" > + : "=q" (x) > + : "m" (*__xg(ptr)), "0" (x) > + : "memory"); > + break; > + case 2: > + __asm__ __volatile__("xchgw %w0,%1" > + : "=r" (x) > + : "m" (*__xg(ptr)), "0" (x) > + : "memory"); > + break; > + case 4: > + __asm__ __volatile__("xchgl %0,%1" > + : "=r" (x) > + : "m" (*__xg(ptr)), "0" (x) > + : "memory"); > + break; > + } > + > + return x; > +} > + > +static inline void lapic_write_atomic(unsigned long reg, unsigned long v) > +{ > + (void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v); > +} > + > + > +#ifdef X86_GOOD_APIC > +# define FORCE_READ_AROUND_WRITE 0 > +# define lapic_read_around(x) lapic_read(x) > +# define lapic_write_around(x, y) lapic_write((x), (y)) > +#else > +# define FORCE_READ_AROUND_WRITE 1 > +# define lapic_read_around(x) lapic_read(x) > +# define lapic_write_around(x, y) lapic_write_atomic((x), (y)) > +#endif > + > +static inline int lapic_remote_read(int apicid, int reg, unsigned long > *pvalue) > +{ > + int timeout; > + unsigned long status; > + int result; > + lapic_wait_icr_idle(); > + lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid)); > + lapic_write_around(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4)); > + timeout = 0; > + do { > + status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK; > + } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000); > + > + result = -1; > + if (status == LAPIC_ICR_RR_VALID) { > + *pvalue = lapic_read(LAPIC_RRR); > + result = 0; > + } > + return result; > +} > + > + > +void lapic_setup(void); > + > +#if CONFIG_SMP > +struct device; > +int start_cpu(struct device *cpu); > +#endif /* CONFIG_SMP */ > + > +#endif /* !__PRE_RAM__ */ > + > +int boot_cpu(void); > + > +/** > + * struct x86_cpu_priv - Information about a single CPU > + * > + * @apic_id: Advanced Programmable Interrupt Controller Identifier, which is > + * just a number representing the CPU core > + * > + * TODO: Move this to driver model once lifecycle is understood > + */ > +struct x86_cpu_priv { > + int apic_id; > + int start_err; > +}; > + > #endif > diff --git a/arch/x86/include/asm/post.h b/arch/x86/include/asm/post.h > index ce68839..6d2ae5d 100644 > --- a/arch/x86/include/asm/post.h > +++ b/arch/x86/include/asm/post.h > @@ -30,6 +30,7 @@ > #define POST_PRE_MRC 0x2e > #define POST_MRC 0x2f > #define POST_DRAM 0x2f > +#define POST_LAPIC 0x30 > > #define POST_RAM_FAILURE 0xea > > -- Regards, Bin _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot