]> git.sur5r.net Git - u-boot/blob - arch/x86/include/asm/lapic.h
x86: crownbay: Add MP initialization
[u-boot] / arch / x86 / include / asm / lapic.h
1 /*
2  * From coreboot file of same name
3  *
4  * Copyright (C) 2014 Google, Inc
5  *
6  * SPDX-License-Identifier:     GPL-2.0
7  */
8
9 #ifndef _ARCH_ASM_LAPIC_H
10 #define _ARCH_ASM_LAPIC_H
11
12 #include <asm/io.h>
13 #include <asm/msr.h>
14 #include <asm/msr-index.h>
15 #include <asm/processor.h>
16
17 #define LAPIC_DEFAULT_BASE              0xfee00000
18
19 #define LAPIC_ID                        0x020
20 #define LAPIC_LVR                       0x030
21
22 #define LAPIC_TASKPRI                   0x080
23 #define LAPIC_TPRI_MASK                 0xff
24
25 #define LAPIC_RRR                       0x0c0
26
27 #define LAPIC_SPIV                      0x0f0
28 #define LAPIC_SPIV_ENABLE               0x100
29
30 #define LAPIC_ICR                       0x300
31 #define LAPIC_DEST_SELF                 0x40000
32 #define LAPIC_DEST_ALLINC               0x80000
33 #define LAPIC_DEST_ALLBUT               0xc0000
34 #define LAPIC_ICR_RR_MASK               0x30000
35 #define LAPIC_ICR_RR_INVALID            0x00000
36 #define LAPIC_ICR_RR_INPROG             0x10000
37 #define LAPIC_ICR_RR_VALID              0x20000
38 #define LAPIC_INT_LEVELTRIG             0x08000
39 #define LAPIC_INT_ASSERT                0x04000
40 #define LAPIC_ICR_BUSY                  0x01000
41 #define LAPIC_DEST_LOGICAL              0x00800
42 #define LAPIC_DM_FIXED                  0x00000
43 #define LAPIC_DM_LOWEST                 0x00100
44 #define LAPIC_DM_SMI                    0x00200
45 #define LAPIC_DM_REMRD                  0x00300
46 #define LAPIC_DM_NMI                    0x00400
47 #define LAPIC_DM_INIT                   0x00500
48 #define LAPIC_DM_STARTUP                0x00600
49 #define LAPIC_DM_EXTINT                 0x00700
50 #define LAPIC_VECTOR_MASK               0x000ff
51
52 #define LAPIC_ICR2                      0x310
53 #define GET_LAPIC_DEST_FIELD(x)         (((x) >> 24) & 0xff)
54 #define SET_LAPIC_DEST_FIELD(x)         ((x) << 24)
55
56 #define LAPIC_LVT0                      0x350
57 #define LAPIC_LVT1                      0x360
58 #define LAPIC_LVT_MASKED                (1 << 16)
59 #define LAPIC_LVT_LEVEL_TRIGGER         (1 << 15)
60 #define LAPIC_LVT_REMOTE_IRR            (1 << 14)
61 #define LAPIC_INPUT_POLARITY            (1 << 13)
62 #define LAPIC_SEND_PENDING              (1 << 12)
63 #define LAPIC_LVT_RESERVED_1            (1 << 11)
64 #define LAPIC_DELIVERY_MODE_MASK        (7 << 8)
65 #define LAPIC_DELIVERY_MODE_FIXED       (0 << 8)
66 #define LAPIC_DELIVERY_MODE_NMI         (4 << 8)
67 #define LAPIC_DELIVERY_MODE_EXTINT      (7 << 8)
68
69 static inline __attribute__((always_inline))
70                 unsigned long lapic_read(unsigned long reg)
71 {
72         return readl(LAPIC_DEFAULT_BASE + reg);
73 }
74
75 static inline __attribute__((always_inline))
76                 void lapic_write(unsigned long reg, unsigned long val)
77 {
78         writel(val, LAPIC_DEFAULT_BASE + reg);
79 }
80
81 static inline __attribute__((always_inline)) void lapic_wait_icr_idle(void)
82 {
83         do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY);
84 }
85
86 static inline void enable_lapic(void)
87 {
88         msr_t msr;
89
90         msr = msr_read(MSR_IA32_APICBASE);
91         msr.hi &= 0xffffff00;
92         msr.lo |= MSR_IA32_APICBASE_ENABLE;
93         msr.lo &= ~MSR_IA32_APICBASE_BASE;
94         msr.lo |= LAPIC_DEFAULT_BASE;
95         msr_write(MSR_IA32_APICBASE, msr);
96 }
97
98 static inline void disable_lapic(void)
99 {
100         msr_t msr;
101
102         msr = msr_read(MSR_IA32_APICBASE);
103         msr.lo &= ~MSR_IA32_APICBASE_ENABLE;
104         msr_write(MSR_IA32_APICBASE, msr);
105 }
106
107 static inline __attribute__((always_inline)) unsigned long lapicid(void)
108 {
109         return lapic_read(LAPIC_ID) >> 24;
110 }
111
112 static inline __attribute__((always_inline)) void stop_this_cpu(void)
113 {
114         /* Called by an AP when it is ready to halt and wait for a new task */
115         for (;;)
116                 cpu_hlt();
117 }
118
119 #define xchg(ptr, v)    ((__typeof__(*(ptr)))__xchg((unsigned long)(v), (ptr), \
120                                                     sizeof(*(ptr))))
121
122 struct __xchg_dummy     { unsigned long a[100]; };
123 #define __xg(x)         ((struct __xchg_dummy *)(x))
124
125 /*
126  * Note: no "lock" prefix even on SMP. xchg always implies lock anyway.
127  *
128  * Note 2: xchg has side effect, so that attribute volatile is necessary,
129  *         but generally the primitive is invalid, *ptr is output argument.
130  */
131 static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
132                                    int size)
133 {
134         switch (size) {
135         case 1:
136                 __asm__ __volatile__("xchgb %b0,%1"
137                         : "=q" (x)
138                         : "m" (*__xg(ptr)), "0" (x)
139                         : "memory");
140                 break;
141         case 2:
142                 __asm__ __volatile__("xchgw %w0,%1"
143                         : "=r" (x)
144                         : "m" (*__xg(ptr)), "0" (x)
145                         : "memory");
146                 break;
147         case 4:
148                 __asm__ __volatile__("xchgl %0,%1"
149                         : "=r" (x)
150                         : "m" (*__xg(ptr)), "0" (x)
151                         : "memory");
152                 break;
153         }
154
155         return x;
156 }
157
158 static inline void lapic_write_atomic(unsigned long reg, unsigned long v)
159 {
160         (void)xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE + reg), v);
161 }
162
163 #define lapic_read_around(x)            lapic_read(x)
164 #define lapic_write_around(x, y)        lapic_write_atomic((x), (y))
165
166 static inline int lapic_remote_read(int apicid, int reg, unsigned long *pvalue)
167 {
168         int timeout;
169         unsigned long status;
170         int result;
171
172         lapic_wait_icr_idle();
173         lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
174         lapic_write_around(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
175
176         timeout = 0;
177         do {
178                 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
179         } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
180
181         result = -1;
182         if (status == LAPIC_ICR_RR_VALID) {
183                 *pvalue = lapic_read(LAPIC_RRR);
184                 result = 0;
185         }
186
187         return result;
188 }
189
190 void lapic_setup(void);
191
192 #endif