Author: rminnich Date: 2008-08-12 01:02:34 +0200 (Tue, 12 Aug 2008) New Revision: 745
Added: coreboot-v3/include/arch/x86/lapic.h coreboot-v3/include/arch/x86/lapic_def.h Log: Add lapic defines and support.
Signed-off-by: Ronald G. Minnich rminnich@gmail.com
Acked-by: Marc Jones marc.jones@amd.com
Added: coreboot-v3/include/arch/x86/lapic.h =================================================================== --- coreboot-v3/include/arch/x86/lapic.h (rev 0) +++ coreboot-v3/include/arch/x86/lapic.h 2008-08-11 23:02:34 UTC (rev 745) @@ -0,0 +1,168 @@ +/* + * This file is part of the coreboot project. + * Copyright (C) 2004 Linux Networx + * (Written by Eric Biederman ebiederman@lnxi.com for Linux Networx) + * Copyright (C) 2005 Stefan Reinauer stepan@coresystems.de + * Copyright (C) 2007 AMD Marc Jones + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef CPU_X86_LAPIC_H +#define CPU_X86_LAPIC_H + +#include <cpu.h> +#include <lapic_def.h> +#include <msr.h> + +/* See if I need to initialize the local apic */ +#if defined(CONFIG_SMP) || defined(CONFIG_IOAPIC) +# define NEED_LAPIC 1 +#endif + +static inline __attribute__((always_inline)) unsigned long lapic_read(unsigned long reg) +{ + return *((volatile unsigned long *)(LAPIC_DEFAULT_BASE+reg)); +} + +static inline __attribute__((always_inline)) void lapic_write(unsigned long reg, unsigned long v) +{ + *((volatile unsigned long *)(LAPIC_DEFAULT_BASE+reg)) = v; +} + +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) +{ + + struct msr msr; + msr = rdmsr(LAPIC_BASE_MSR); + msr.hi &= 0xffffff00; + msr.lo &= 0x000007ff; + msr.lo |= LAPIC_DEFAULT_BASE | (1 << 11); + wrmsr(LAPIC_BASE_MSR, msr); +} + +static inline void disable_lapic(void) +{ + struct msr msr; + msr = rdmsr(LAPIC_BASE_MSR); + msr.lo &= ~(1 << 11); + wrmsr(LAPIC_BASE_MSR, msr); +} + +static inline __attribute__((always_inline)) unsigned long lapicid(void) +{ + return lapic_read(LAPIC_ID) >> 24; +} + +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(;;) { + hlt(); + } +} + +#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; +} + + +extern inline void lapic_write_atomic(unsigned long reg, unsigned long v) +{ + xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE+reg), v); +} + + +#ifdef CONFIG_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 { +#if 0 + udelay(100); +#endif + 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 setup_lapic(void); + + +#ifdef CONFIG_SMP +struct device; +int start_cpu(struct device *cpu); + +#endif /* CONFIG_SMP */ + +#endif /* CPU_X86_LAPIC_H */
Added: coreboot-v3/include/arch/x86/lapic_def.h =================================================================== --- coreboot-v3/include/arch/x86/lapic_def.h (rev 0) +++ coreboot-v3/include/arch/x86/lapic_def.h 2008-08-11 23:02:34 UTC (rev 745) @@ -0,0 +1,111 @@ +/* + * This file is part of the coreboot project. + * Copyright (C) 2004 Linux Networx + * (Written by Eric Biederman ebiederman@lnxi.com for Linux Networx) + * Copyright (C) 2005 Stefan Reinauer stepan@coresystems.de + * Copyright (C) 2007 AMD Marc Jones + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef CPU_X86_LAPIC_DEF_H +#define CPU_X86_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 LAPIC_DEFAULT_BASE 0xfee00000 + +#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 /* CPU_X86_LAPIC_DEF_H */