blob: 2225964268f85aa4e4b2ddc4fa26ee7d31cf07bd [file] [log] [blame]
Martin Roth433659a2014-05-12 21:55:00 -06001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2013 Google Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <stdint.h>
21#include <stdlib.h>
22#include <arch/hlt.h>
23#include <arch/io.h>
24#include <console/console.h>
25#include <cpu/x86/cache.h>
26#include <cpu/x86/smm.h>
27#include <device/pci_def.h>
28#include <elog.h>
29
30#include <baytrail/pci_devs.h>
31#include <baytrail/pmc.h>
32#include <baytrail/nvs.h>
33
34/* GNVS needs to be set by coreboot initiating a software SMI. */
35static global_nvs_t *gnvs;
36static int smm_initialized;
37
38int southbridge_io_trap_handler(int smif)
39{
40 switch (smif) {
41 case 0x32:
42 printk(BIOS_DEBUG, "OS Init\n");
43 /* gnvs->smif:
44 * On success, the IO Trap Handler returns 0
45 * On failure, the IO Trap Handler returns a value != 0
46 */
47 gnvs->smif = 0;
48 return 1; /* IO trap handled */
49 }
50
51 /* Not handled */
52 return 0;
53}
54
55void southbridge_smi_set_eos(void)
56{
57 enable_smi(EOS);
58}
59
60global_nvs_t *smm_get_gnvs(void)
61{
62 return gnvs;
63}
64
65static void busmaster_disable_on_bus(int bus)
66{
67 int slot, func;
68 unsigned int val;
69 unsigned char hdr;
70
71 for (slot = 0; slot < 0x20; slot++) {
72 for (func = 0; func < 8; func++) {
73 u32 reg32;
74 device_t dev = PCI_DEV(bus, slot, func);
75
76 val = pci_read_config32(dev, PCI_VENDOR_ID);
77
78 if (val == 0xffffffff || val == 0x00000000 ||
79 val == 0x0000ffff || val == 0xffff0000)
80 continue;
81
82 /* Disable Bus Mastering for this one device */
83 reg32 = pci_read_config32(dev, PCI_COMMAND);
84 reg32 &= ~PCI_COMMAND_MASTER;
85 pci_write_config32(dev, PCI_COMMAND, reg32);
86
87 /* If this is a bridge, then follow it. */
88 hdr = pci_read_config8(dev, PCI_HEADER_TYPE);
89 hdr &= 0x7f;
90 if (hdr == PCI_HEADER_TYPE_BRIDGE ||
91 hdr == PCI_HEADER_TYPE_CARDBUS) {
92 unsigned int buses;
93 buses = pci_read_config32(dev, PCI_PRIMARY_BUS);
94 busmaster_disable_on_bus((buses >> 8) & 0xff);
95 }
96 }
97 }
98}
99
100static void southbridge_smi_sleep(void)
101{
102 uint32_t reg32;
103 uint8_t slp_typ;
104 uint16_t pmbase = get_pmbase();
105
106 /* First, disable further SMIs */
107 disable_smi(SLP_SMI_EN);
108
109 /* Figure out SLP_TYP */
110 reg32 = inl(pmbase + PM1_CNT);
111 printk(BIOS_SPEW, "SMI#: SLP = 0x%08x\n", reg32);
112 slp_typ = (reg32 >> 10) & 7;
113
114 /* Do any mainboard sleep handling */
115 mainboard_smi_sleep(slp_typ-2);
116
117#if IS_ENABLED(CONFIG_ELOG_GSMI)
118 /* Log S3, S4, and S5 entry */
119 if (slp_typ >= 5)
120 elog_add_event_byte(ELOG_TYPE_ACPI_ENTER, slp_typ-2);
121#endif
122
123 /* Next, do the deed.
124 */
125
126 switch (slp_typ) {
127 case SLP_TYP_S0:
128 printk(BIOS_DEBUG, "SMI#: Entering S0 (On)\n");
129 break;
130 case SLP_TYP_S1:
131 printk(BIOS_DEBUG, "SMI#: Entering S1 (Assert STPCLK#)\n");
132 break;
133 case SLP_TYP_S3:
134 printk(BIOS_DEBUG, "SMI#: Entering S3 (Suspend-To-RAM)\n");
135
136 /* Invalidate the cache before going to S3 */
137 wbinvd();
138 break;
139 case SLP_TYP_S4:
140 printk(BIOS_DEBUG, "SMI#: Entering S4 (Suspend-To-Disk)\n");
141 break;
142 case SLP_TYP_S5:
143 printk(BIOS_DEBUG, "SMI#: Entering S5 (Soft Power off)\n");
144
145 /* Disable all GPE */
146 disable_all_gpe();
147
148 /* also iterates over all bridges on bus 0 */
149 busmaster_disable_on_bus(0);
150 break;
151 default:
152 printk(BIOS_DEBUG, "SMI#: ERROR: SLP_TYP reserved\n");
153 break;
154 }
155
156 /* Write back to the SLP register to cause the originally intended
157 * event again. We need to set BIT13 (SLP_EN) though to make the
158 * sleep happen.
159 */
160 enable_pm1_control(SLP_EN);
161
162 /* Make sure to stop executing code here for S3/S4/S5 */
163 if (slp_typ > 1)
164 hlt();
165
166 /* In most sleep states, the code flow of this function ends at
167 * the line above. However, if we entered sleep state S1 and wake
168 * up again, we will continue to execute code in this function.
169 */
170 reg32 = inl(pmbase + PM1_CNT);
171 if (reg32 & SCI_EN) {
172 /* The OS is not an ACPI OS, so we set the state to S0 */
173 disable_pm1_control(SLP_EN | SLP_TYP);
174 }
175}
176
177/*
178 * Look for Synchronous IO SMI and use save state from that
179 * core in case we are not running on the same core that
180 * initiated the IO transaction.
181 */
182static em64t100_smm_state_save_area_t *smi_apmc_find_state_save(uint8_t cmd)
183{
184#ifndef CONFIG_MAX_CPUS
185#error CONFIG_MAX_CPUS must be set.
186#endif
187 em64t100_smm_state_save_area_t *state;
188 int node;
189
190 /* Check all nodes looking for the one that issued the IO */
191 for (node = 0; node < CONFIG_MAX_CPUS; node++) {
192 state = smm_get_save_state(node);
193
194 /* Check for Synchronous IO (bit0==1) */
195 if (!(state->io_misc_info & (1 << 0)))
196 continue;
197
198 /* Make sure it was a write (bit4==0) */
199 if (state->io_misc_info & (1 << 4))
200 continue;
201
202 /* Check for APMC IO port */
203 if (((state->io_misc_info >> 16) & 0xff) != APM_CNT)
204 continue;
205
206 /* Check AX against the requested command */
207 if ((state->rax & 0xff) != cmd)
208 continue;
209
210 return state;
211 }
212
213 return NULL;
214}
215
216#if IS_ENABLED(CONFIG_ELOG_GSMI)
217static void southbridge_smi_gsmi(void)
218{
219 u32 *ret, *param;
220 uint8_t sub_command;
221 em64t100_smm_state_save_area_t *io_smi =
222 smi_apmc_find_state_save(ELOG_GSMI_APM_CNT);
223
224 if (!io_smi)
225 return;
226
227 /* Command and return value in EAX */
228 ret = (u32*)&io_smi->rax;
229 sub_command = (uint8_t)(*ret >> 8);
230
231 /* Parameter buffer in EBX */
232 param = (u32*)&io_smi->rbx;
233
234 /* drivers/elog/gsmi.c */
235 *ret = gsmi_exec(sub_command, param);
236}
237#endif
238static void southbridge_smi_apmc(void)
239{
240 uint8_t reg8;
241 em64t100_smm_state_save_area_t *state;
242
243 /* Emulate B2 register as the FADT / Linux expects it */
244
245 reg8 = inb(APM_CNT);
246 switch (reg8) {
247 case APM_CNT_CST_CONTROL:
248 /* Calling this function seems to cause
249 * some kind of race condition in Linux
250 * and causes a kernel oops
251 */
252 printk(BIOS_DEBUG, "C-state control\n");
253 break;
254 case APM_CNT_PST_CONTROL:
255 /* Calling this function seems to cause
256 * some kind of race condition in Linux
257 * and causes a kernel oops
258 */
259 printk(BIOS_DEBUG, "P-state control\n");
260 break;
261 case APM_CNT_ACPI_DISABLE:
262 disable_pm1_control(SCI_EN);
263 printk(BIOS_DEBUG, "SMI#: ACPI disabled.\n");
264 break;
265 case APM_CNT_ACPI_ENABLE:
266 enable_pm1_control(SCI_EN);
267 printk(BIOS_DEBUG, "SMI#: ACPI enabled.\n");
268 break;
269 case APM_CNT_GNVS_UPDATE:
270 if (smm_initialized) {
271 printk(BIOS_DEBUG,
272 "SMI#: SMM structures already initialized!\n");
273 return;
274 }
275 state = smi_apmc_find_state_save(reg8);
276 if (state) {
277 /* EBX in the state save contains the GNVS pointer */
278 gnvs = (global_nvs_t *)((uint32_t)state->rbx);
279 smm_initialized = 1;
280 printk(BIOS_DEBUG, "SMI#: Setting GNVS to %p\n", gnvs);
281 }
282 break;
283#if IS_ENABLED(CONFIG_ELOG_GSMI)
284 case ELOG_GSMI_APM_CNT:
285 southbridge_smi_gsmi();
286 break;
287#endif
288 }
289
290 mainboard_smi_apmc(reg8);
291}
292
293static void southbridge_smi_pm1(void)
294{
295 uint16_t pm1_sts = clear_pm1_status();
296
297 /* While OSPM is not active, poweroff immediately
298 * on a power button event.
299 */
300 if (pm1_sts & PWRBTN_STS) {
301 // power button pressed
302#if IS_ENABLED(CONFIG_ELOG_GSMI)
303 elog_add_event(ELOG_TYPE_POWER_BUTTON);
304#endif
305 disable_pm1_control(-1UL);
306 enable_pm1_control(SLP_EN | (SLP_TYP_S5 << SLP_TYP_SHIFT));
307 }
308}
309
310static void southbridge_smi_gpe0(void)
311{
312 clear_gpe_status();
313}
314
315static void southbridge_smi_tco(void)
316{
317 uint32_t tco_sts = clear_tco_status();
318
319 /* Any TCO event? */
320 if (!tco_sts)
321 return;
322
323 if (tco_sts & TCO_TIMEOUT) { /* TIMEOUT */
324 /* Handle TCO timeout */
325 printk(BIOS_DEBUG, "TCO Timeout.\n");
326 }
327}
328
329static void southbridge_smi_periodic(void)
330{
331 uint32_t reg32;
332
333 reg32 = inl(get_pmbase() + SMI_EN);
334
335 /* Are periodic SMIs enabled? */
336 if ((reg32 & PERIODIC_EN) == 0)
337 return;
338
339 printk(BIOS_DEBUG, "Periodic SMI.\n");
340}
341
342typedef void (*smi_handler_t)(void);
343
344static const smi_handler_t southbridge_smi[32] = {
345 NULL, // [0] reserved
346 NULL, // [1] reserved
347 NULL, // [2] BIOS_STS
348 NULL, // [3] LEGACY_USB_STS
349 southbridge_smi_sleep, // [4] SLP_SMI_STS
350 southbridge_smi_apmc, // [5] APM_STS
351 NULL, // [6] SWSMI_TMR_STS
352 NULL, // [7] reserved
353 southbridge_smi_pm1, // [8] PM1_STS
354 southbridge_smi_gpe0, // [9] GPE0_STS
355 NULL, // [10] reserved
356 NULL, // [11] reserved
357 NULL, // [12] reserved
358 southbridge_smi_tco, // [13] TCO_STS
359 southbridge_smi_periodic, // [14] PERIODIC_STS
360 NULL, // [15] SERIRQ_SMI_STS
361 NULL, // [16] SMBUS_SMI_STS
362 NULL, // [17] LEGACY_USB2_STS
363 NULL, // [18] INTEL_USB2_STS
364 NULL, // [19] reserved
365 NULL, // [20] PCI_EXP_SMI_STS
366 NULL, // [21] reserved
367 NULL, // [22] reserved
368 NULL, // [23] reserved
369 NULL, // [24] reserved
370 NULL, // [25] reserved
371 NULL, // [26] SPI_STS
372 NULL, // [27] reserved
373 NULL, // [28] PUNIT
374 NULL, // [29] GUNIT
375 NULL, // [30] reserved
376 NULL // [31] reserved
377};
378
379void southbridge_smi_handler(void)
380{
381 int i;
382 uint32_t smi_sts;
383
384 /* We need to clear the SMI status registers, or we won't see what's
385 * happening in the following calls.
386 */
387 smi_sts = clear_smi_status();
388
389 /* Call SMI sub handler for each of the status bits */
390 for (i = 0; i < ARRAY_SIZE(southbridge_smi); i++) {
391 if (!(smi_sts & (1 << i)))
392 continue;
393
394 if (southbridge_smi[i] != NULL) {
395 southbridge_smi[i]();
396 } else {
397 printk(BIOS_DEBUG,
398 "SMI_STS[%d] occured, but no "
399 "handler available.\n", i);
400 }
401 }
402
403 /* The GPIO SMI events do not have a status bit in SMI_STS. Therefore,
404 * these events need to be cleared and checked unconditionally. */
405 mainboard_smi_gpi(clear_alt_status());
406}