95ec1129a3f4d1d038ca78782854319946b04006
[coreboot.git] / src / southbridge / intel / i82801gx / smi.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2008-2009 coresystems GmbH
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; version 2 of
9  * the License.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
19  * MA 02110-1301 USA
20  */
21
22
23 #include <device/device.h>
24 #include <device/pci.h>
25 #include <console/console.h>
26 #include <arch/io.h>
27 #include <cpu/cpu.h>
28 #include <cpu/x86/cache.h>
29 #include <cpu/x86/smm.h>
30 #include <string.h>
31 #include "i82801gx.h"
32
33 extern unsigned char _binary_smm_start;
34 extern unsigned char _binary_smm_size;
35
36 /* I945 */
37 #define SMRAM           0x9d
38 #define   D_OPEN        (1 << 6)
39 #define   D_CLS         (1 << 5)
40 #define   D_LCK         (1 << 4)
41 #define   G_SMRAME      (1 << 3)
42 #define   C_BASE_SEG    ((0 << 2) | (1 << 1) | (0 << 0))
43
44 /* While we read PMBASE dynamically in case it changed, let's
45  * initialize it with a sane value
46  */
47 static u16 pmbase = DEFAULT_PMBASE;
48
49 /**
50  * @brief read and clear PM1_STS
51  * @return PM1_STS register
52  */
53 static u16 reset_pm1_status(void)
54 {
55         u16 reg16;
56
57         reg16 = inw(pmbase + PM1_STS);
58         /* set status bits are cleared by writing 1 to them */
59         outw(reg16, pmbase + PM1_STS);
60
61         return reg16;
62 }
63
64 static void dump_pm1_status(u16 pm1_sts)
65 {
66         printk(BIOS_DEBUG, "PM1_STS: ");
67         if (pm1_sts & (1 << 15)) printk(BIOS_DEBUG, "WAK ");
68         if (pm1_sts & (1 << 14)) printk(BIOS_DEBUG, "PCIEXPWAK ");
69         if (pm1_sts & (1 << 11)) printk(BIOS_DEBUG, "PRBTNOR ");
70         if (pm1_sts & (1 << 10)) printk(BIOS_DEBUG, "RTC ");
71         if (pm1_sts & (1 <<  8)) printk(BIOS_DEBUG, "PWRBTN ");
72         if (pm1_sts & (1 <<  5)) printk(BIOS_DEBUG, "GBL ");
73         if (pm1_sts & (1 <<  4)) printk(BIOS_DEBUG, "BM ");
74         if (pm1_sts & (1 <<  0)) printk(BIOS_DEBUG, "TMROF ");
75         printk(BIOS_DEBUG, "\n");
76 }
77
78 /**
79  * @brief read and clear SMI_STS
80  * @return SMI_STS register
81  */
82 static u32 reset_smi_status(void)
83 {
84         u32 reg32;
85
86         reg32 = inl(pmbase + SMI_STS);
87         /* set status bits are cleared by writing 1 to them */
88         outl(reg32, pmbase + SMI_STS);
89
90         return reg32;
91 }
92
93 static void dump_smi_status(u32 smi_sts)
94 {
95         printk(BIOS_DEBUG, "SMI_STS: ");
96         if (smi_sts & (1 << 26)) printk(BIOS_DEBUG, "SPI ");
97         if (smi_sts & (1 << 25)) printk(BIOS_DEBUG, "EL_SMI ");
98         if (smi_sts & (1 << 21)) printk(BIOS_DEBUG, "MONITOR ");
99         if (smi_sts & (1 << 20)) printk(BIOS_DEBUG, "PCI_EXP_SMI ");
100         if (smi_sts & (1 << 18)) printk(BIOS_DEBUG, "INTEL_USB2 ");
101         if (smi_sts & (1 << 17)) printk(BIOS_DEBUG, "LEGACY_USB2 ");
102         if (smi_sts & (1 << 16)) printk(BIOS_DEBUG, "SMBUS_SMI ");
103         if (smi_sts & (1 << 15)) printk(BIOS_DEBUG, "SERIRQ_SMI ");
104         if (smi_sts & (1 << 14)) printk(BIOS_DEBUG, "PERIODIC ");
105         if (smi_sts & (1 << 13)) printk(BIOS_DEBUG, "TCO ");
106         if (smi_sts & (1 << 12)) printk(BIOS_DEBUG, "DEVMON ");
107         if (smi_sts & (1 << 11)) printk(BIOS_DEBUG, "MCSMI ");
108         if (smi_sts & (1 << 10)) printk(BIOS_DEBUG, "GPI ");
109         if (smi_sts & (1 <<  9)) printk(BIOS_DEBUG, "GPE0 ");
110         if (smi_sts & (1 <<  8)) printk(BIOS_DEBUG, "PM1 ");
111         if (smi_sts & (1 <<  6)) printk(BIOS_DEBUG, "SWSMI_TMR ");
112         if (smi_sts & (1 <<  5)) printk(BIOS_DEBUG, "APM ");
113         if (smi_sts & (1 <<  4)) printk(BIOS_DEBUG, "SLP_SMI ");
114         if (smi_sts & (1 <<  3)) printk(BIOS_DEBUG, "LEGACY_USB ");
115         if (smi_sts & (1 <<  2)) printk(BIOS_DEBUG, "BIOS ");
116         printk(BIOS_DEBUG, "\n");
117 }
118
119
120 /**
121  * @brief read and clear GPE0_STS
122  * @return GPE0_STS register
123  */
124 static u32 reset_gpe0_status(void)
125 {
126         u32 reg32;
127
128         reg32 = inl(pmbase + GPE0_STS);
129         /* set status bits are cleared by writing 1 to them */
130         outl(reg32, pmbase + GPE0_STS);
131
132         return reg32;
133 }
134
135 static void dump_gpe0_status(u32 gpe0_sts)
136 {
137         int i;
138         printk(BIOS_DEBUG, "GPE0_STS: ");
139         for (i=31; i<= 16; i--) {
140                 if (gpe0_sts & (1 << i)) printk(BIOS_DEBUG, "GPIO%d ", (i-16));
141         }
142         if (gpe0_sts & (1 << 14)) printk(BIOS_DEBUG, "USB4 ");
143         if (gpe0_sts & (1 << 13)) printk(BIOS_DEBUG, "PME_B0 ");
144         if (gpe0_sts & (1 << 12)) printk(BIOS_DEBUG, "USB3 ");
145         if (gpe0_sts & (1 << 11)) printk(BIOS_DEBUG, "PME ");
146         if (gpe0_sts & (1 << 10)) printk(BIOS_DEBUG, "EL_SCI/BATLOW ");
147         if (gpe0_sts & (1 <<  9)) printk(BIOS_DEBUG, "PCI_EXP ");
148         if (gpe0_sts & (1 <<  8)) printk(BIOS_DEBUG, "RI ");
149         if (gpe0_sts & (1 <<  7)) printk(BIOS_DEBUG, "SMB_WAK ");
150         if (gpe0_sts & (1 <<  6)) printk(BIOS_DEBUG, "TCO_SCI ");
151         if (gpe0_sts & (1 <<  5)) printk(BIOS_DEBUG, "AC97 ");
152         if (gpe0_sts & (1 <<  4)) printk(BIOS_DEBUG, "USB2 ");
153         if (gpe0_sts & (1 <<  3)) printk(BIOS_DEBUG, "USB1 ");
154         if (gpe0_sts & (1 <<  2)) printk(BIOS_DEBUG, "HOT_PLUG ");
155         if (gpe0_sts & (1 <<  0)) printk(BIOS_DEBUG, "THRM ");
156         printk(BIOS_DEBUG, "\n");
157 }
158
159
160 /**
161  * @brief read and clear ALT_GP_SMI_STS
162  * @return ALT_GP_SMI_STS register
163  */
164 static u16 reset_alt_gp_smi_status(void)
165 {
166         u16 reg16;
167
168         reg16 = inl(pmbase + ALT_GP_SMI_STS);
169         /* set status bits are cleared by writing 1 to them */
170         outl(reg16, pmbase + ALT_GP_SMI_STS);
171
172         return reg16;
173 }
174
175 static void dump_alt_gp_smi_status(u16 alt_gp_smi_sts)
176 {
177         int i;
178         printk(BIOS_DEBUG, "ALT_GP_SMI_STS: ");
179         for (i=15; i<= 0; i--) {
180                 if (alt_gp_smi_sts & (1 << i)) printk(BIOS_DEBUG, "GPI%d ", (i-16));
181         }
182         printk(BIOS_DEBUG, "\n");
183 }
184
185
186
187 /**
188  * @brief read and clear TCOx_STS
189  * @return TCOx_STS registers
190  */
191 static u32 reset_tco_status(void)
192 {
193         u32 tcobase = pmbase + 0x60;
194         u32 reg32;
195
196         reg32 = inl(tcobase + 0x04);
197         /* set status bits are cleared by writing 1 to them */
198         outl(reg32 & ~(1<<18), tcobase + 0x04); //  Don't clear BOOT_STS before SECOND_TO_STS
199         if (reg32 & (1 << 18))
200                 outl(reg32 & (1<<18), tcobase + 0x04); // clear BOOT_STS
201
202         return reg32;
203 }
204
205
206 static void dump_tco_status(u32 tco_sts)
207 {
208         printk(BIOS_DEBUG, "TCO_STS: ");
209         if (tco_sts & (1 << 20)) printk(BIOS_DEBUG, "SMLINK_SLV ");
210         if (tco_sts & (1 << 18)) printk(BIOS_DEBUG, "BOOT ");
211         if (tco_sts & (1 << 17)) printk(BIOS_DEBUG, "SECOND_TO ");
212         if (tco_sts & (1 << 16)) printk(BIOS_DEBUG, "INTRD_DET ");
213         if (tco_sts & (1 << 12)) printk(BIOS_DEBUG, "DMISERR ");
214         if (tco_sts & (1 << 10)) printk(BIOS_DEBUG, "DMISMI ");
215         if (tco_sts & (1 <<  9)) printk(BIOS_DEBUG, "DMISCI ");
216         if (tco_sts & (1 <<  8)) printk(BIOS_DEBUG, "BIOSWR ");
217         if (tco_sts & (1 <<  7)) printk(BIOS_DEBUG, "NEWCENTURY ");
218         if (tco_sts & (1 <<  3)) printk(BIOS_DEBUG, "TIMEOUT ");
219         if (tco_sts & (1 <<  2)) printk(BIOS_DEBUG, "TCO_INT ");
220         if (tco_sts & (1 <<  1)) printk(BIOS_DEBUG, "SW_TCO ");
221         if (tco_sts & (1 <<  0)) printk(BIOS_DEBUG, "NMI2SMI ");
222         printk(BIOS_DEBUG, "\n");
223 }
224
225
226
227 /**
228  * @brief Set the EOS bit
229  */
230 static void smi_set_eos(void)
231 {
232         u8 reg8;
233
234         reg8 = inb(pmbase + SMI_EN);
235         reg8 |= EOS;
236         outb(reg8, pmbase + SMI_EN);
237 }
238
239 extern uint8_t smm_relocation_start, smm_relocation_end;
240
241 static void smm_relocate(void)
242 {
243         u32 smi_en;
244         u16 pm1_en;
245
246         printk(BIOS_DEBUG, "Initializing SMM handler...");
247
248         pmbase = pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x1f, 0)), 0x40) & 0xfffc;
249         printk(BIOS_SPEW, " ... pmbase = 0x%04x\n", pmbase);
250
251         smi_en = inl(pmbase + SMI_EN);
252         if (smi_en & APMC_EN) {
253                 printk(BIOS_INFO, "SMI# handler already enabled?\n");
254                 return;
255         }
256
257         /* copy the SMM relocation code */
258         memcpy((void *)0x38000, &smm_relocation_start,
259                         &smm_relocation_end - &smm_relocation_start);
260
261         printk(BIOS_DEBUG, "\n");
262         dump_smi_status(reset_smi_status());
263         dump_pm1_status(reset_pm1_status());
264         dump_gpe0_status(reset_gpe0_status());
265         dump_alt_gp_smi_status(reset_alt_gp_smi_status());
266         dump_tco_status(reset_tco_status());
267
268         /* Enable SMI generation:
269          *  - on TCO events
270          *  - on APMC writes (io 0xb2)
271          *  - on writes to SLP_EN (sleep states)
272          *  - on writes to GBL_RLS (bios commands)
273          * No SMIs:
274          *  - on microcontroller writes (io 0x62/0x66)
275          */
276
277         smi_en = 0; /* reset SMI enables */
278
279 #if 0
280         smi_en |= LEGACY_USB2_EN | LEGACY_USB_EN;
281 #endif
282         smi_en |= TCO_EN;
283         smi_en |= APMC_EN;
284 #if DEBUG_PERIODIC_SMIS
285         /* Set DEBUG_PERIODIC_SMIS in i82801gx.h to debug using
286          * periodic SMIs.
287          */
288         smi_en |= PERIODIC_EN;
289 #endif
290         smi_en |= SLP_SMI_EN;
291         smi_en |= BIOS_EN;
292
293         /* The following need to be on for SMIs to happen */
294         smi_en |= EOS | GBL_SMI_EN;
295
296         outl(smi_en, pmbase + SMI_EN);
297
298         pm1_en = 0;
299         pm1_en |= PWRBTN_EN;
300         pm1_en |= GBL_EN;
301         outw(pm1_en, pmbase + PM1_EN);
302
303         /**
304          * There are several methods of raising a controlled SMI# via
305          * software, among them:
306          *  - Writes to io 0xb2 (APMC)
307          *  - Writes to the Local Apic ICR with Delivery mode SMI.
308          *
309          * Using the local apic is a bit more tricky. According to
310          * AMD Family 11 Processor BKDG no destination shorthand must be
311          * used.
312          * The whole SMM initialization is quite a bit hardware specific, so
313          * I'm not too worried about the better of the methods at the moment
314          */
315
316         /* raise an SMI interrupt */
317         printk(BIOS_SPEW, "  ... raise SMI#\n");
318         outb(0x00, 0xb2);
319 }
320
321 static int smm_handler_copied = 0;
322
323 static void smm_install(void)
324 {
325         /* The first CPU running this gets to copy the SMM handler. But not all
326          * of them.
327          */
328         if (smm_handler_copied)
329                 return;
330         smm_handler_copied = 1;
331
332         /* enable the SMM memory window */
333         pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM,
334                                 D_OPEN | G_SMRAME | C_BASE_SEG);
335
336         /* copy the real SMM handler */
337         memcpy((void *)0xa0000, &_binary_smm_start, (size_t)&_binary_smm_size);
338         wbinvd();
339
340         /* close the SMM memory window and enable normal SMM */
341         pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM,
342                         G_SMRAME | C_BASE_SEG);
343 }
344
345 void smm_init(void)
346 {
347         /* Put SMM code to 0xa0000 */
348         smm_install();
349
350         /* Put relocation code to 0x38000 and relocate SMBASE */
351         smm_relocate();
352
353         /* We're done. Make sure SMIs can happen! */
354         smi_set_eos();
355 }
356
357 void smm_lock(void)
358 {
359         /* LOCK the SMM memory window and enable normal SMM.
360          * After running this function, only a full reset can
361          * make the SMM registers writable again.
362          */
363         printk(BIOS_DEBUG, "Locking SMM.\n");
364         pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM,
365                         D_LCK | G_SMRAME | C_BASE_SEG);
366 }
367
368 void smm_setup_structures(void *gnvs, void *tcg, void *smi1)
369 {
370         /* The GDT or coreboot table is going to live here. But a long time
371          * after we relocated the GNVS, so this is not troublesome.
372          */
373         *(u32 *)0x500 = (u32)gnvs;
374         *(u32 *)0x504 = (u32)tcg;
375         *(u32 *)0x508 = (u32)smi1;
376         outb(0xea, 0xb2);
377 }