tree: drop last paragraph of GPL copyright header
[coreboot.git] / src / soc / intel / fsp_baytrail / smm.c
blob236106ca260e449487f5e143a0b9d49e11eb5a1f
1 /*
2 * This file is part of the coreboot project.
4 * Copyright (C) 2013 Google Inc.
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.
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.
17 #include <device/device.h>
18 #include <device/pci.h>
19 #include <console/console.h>
20 #include <arch/io.h>
21 #include <cpu/cpu.h>
22 #include <cpu/x86/smm.h>
23 #include <string.h>
25 #include <baytrail/iomap.h>
26 #include <baytrail/pmc.h>
27 #include <baytrail/smm.h>
29 /* Save the gpio route register. The settings are committed from
30 * southcluster_smm_enable_smi(). */
31 static uint32_t gpio_route;
33 void southcluster_smm_save_gpio_route(uint32_t route)
35 gpio_route = route;
38 void southcluster_smm_clear_state(void)
40 uint32_t smi_en;
42 /* Log events from chipset before clearing */
43 southcluster_log_state();
45 printk(BIOS_DEBUG, "Initializing Southbridge SMI...");
46 printk(BIOS_SPEW, " pmbase = 0x%04x\n", get_pmbase());
48 smi_en = inl(get_pmbase() + SMI_EN);
49 if (smi_en & APMC_EN) {
50 printk(BIOS_INFO, "SMI# handler already enabled?\n");
51 return;
54 /* Dump and clear status registers */
55 clear_smi_status();
56 clear_pm1_status();
57 clear_tco_status();
58 clear_gpe_status();
59 clear_alt_status();
60 clear_pmc_status();
63 static void southcluster_smm_route_gpios(void)
65 u32 *gpio_rout = (u32 *)(PMC_BASE_ADDRESS + GPIO_ROUT);
66 const unsigned short alt_gpio_smi = ACPI_BASE_ADDRESS + ALT_GPIO_SMI;
67 uint32_t alt_gpio_reg = 0;
68 uint32_t route_reg = gpio_route;
69 int i;
71 printk(BIOS_DEBUG, "GPIO_ROUT = %08x\n", route_reg);
73 /* Start the routing for the specific gpios. */
74 write32(gpio_rout, route_reg);
76 /* Enable SMIs for the gpios that are set to trigger the SMI. */
77 for (i = 0; i < 16; i++) {
78 if ((route_reg & ROUTE_MASK) == ROUTE_SMI) {
79 alt_gpio_reg |= (1 << i);
81 route_reg >>= 2;
83 printk(BIOS_DEBUG, "ALT_GPIO_SMI = %08x\n", alt_gpio_reg);
85 outl(alt_gpio_reg, alt_gpio_smi);
88 void southcluster_smm_enable_smi(void)
91 printk(BIOS_DEBUG, "Enabling SMIs.\n");
92 /* Configure events Disable pcie wake. */
93 enable_pm1(PWRBTN_EN | GBL_EN | PCIEXPWAK_DIS);
94 disable_gpe(PME_B0_EN);
96 /* Set up the GPIO route. */
97 southcluster_smm_route_gpios();
99 /* Enable SMI generation:
100 * - on APMC writes (io 0xb2)
101 * - on writes to SLP_EN (sleep states)
102 * - on writes to GBL_RLS (bios commands)
103 * No SMIs:
104 * - on TCO events
105 * - on microcontroller writes (io 0x62/0x66)
107 enable_smi(APMC_EN | SLP_SMI_EN | GBL_SMI_EN | EOS);
110 void smm_setup_structures(void *gnvs, void *tcg, void *smi1)
113 * Issue SMI to set the gnvs pointer in SMM.
114 * tcg and smi1 are unused.
116 * EAX = APM_CNT_GNVS_UPDATE
117 * EBX = gnvs pointer
118 * EDX = APM_CNT
120 asm volatile (
121 "outb %%al, %%dx\n\t"
122 : /* ignore result */
123 : "a" (APM_CNT_GNVS_UPDATE),
124 "b" ((uint32_t)gnvs),
125 "d" (APM_CNT)