summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/apollolake/Kconfig2
-rw-r--r--src/soc/intel/apollolake/Makefile.inc1
-rw-r--r--src/soc/intel/apollolake/cpu.c7
-rw-r--r--src/soc/intel/apollolake/include/soc/pm.h14
-rw-r--r--src/soc/intel/apollolake/memmap.c2
-rw-r--r--src/soc/intel/apollolake/smihandler.c29
-rw-r--r--src/soc/intel/common/Makefile.inc2
-rw-r--r--src/soc/intel/common/block/include/intelblocks/smihandler.h (renamed from src/soc/intel/common/smi.h)49
-rw-r--r--src/soc/intel/common/block/include/intelblocks/smm.h34
-rw-r--r--src/soc/intel/common/block/smm/Kconfig4
-rw-r--r--src/soc/intel/common/block/smm/Makefile.inc2
-rw-r--r--src/soc/intel/common/block/smm/smihandler.c (renamed from src/soc/intel/common/smihandler.c)31
-rw-r--r--src/soc/intel/common/block/smm/smm.c78
13 files changed, 198 insertions, 57 deletions
diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig
index 8d9f56293a..23e514901b 100644
--- a/src/soc/intel/apollolake/Kconfig
+++ b/src/soc/intel/apollolake/Kconfig
@@ -68,7 +68,7 @@ config CPU_SPECIFIC_OPTIONS
select SOC_INTEL_COMMON_BLOCK_UART
select SOC_INTEL_COMMON_BLOCK_XDCI
select SOC_INTEL_COMMON_BLOCK_XHCI
- select SOC_INTEL_COMMON_SMI
+ select SOC_INTEL_COMMON_BLOCK_SMM
select SOC_INTEL_COMMON_SPI_FLASH_PROTECT
select UDELAY_TSC
select TSC_CONSTANT_RATE
diff --git a/src/soc/intel/apollolake/Makefile.inc b/src/soc/intel/apollolake/Makefile.inc
index 619713876e..fe55ae9b5e 100644
--- a/src/soc/intel/apollolake/Makefile.inc
+++ b/src/soc/intel/apollolake/Makefile.inc
@@ -65,7 +65,6 @@ ramstage-y += spi.c
ramstage-y += pmutil.c
ramstage-y += pmc.c
ramstage-y += reset.c
-ramstage-y += smi.c
ramstage-y += sram.c
ramstage-y += spi.c
ramstage-y += xdci.c
diff --git a/src/soc/intel/apollolake/cpu.c b/src/soc/intel/apollolake/cpu.c
index 43f9b8381f..caf749f25f 100644
--- a/src/soc/intel/apollolake/cpu.c
+++ b/src/soc/intel/apollolake/cpu.c
@@ -25,14 +25,15 @@
#include <cpu/x86/mtrr.h>
#include <device/device.h>
#include <device/pci.h>
+#include <fsp/memmap.h>
#include <intelblocks/cpulib.h>
#include <intelblocks/fast_spi.h>
#include <intelblocks/msr.h>
+#include <intelblocks/smm.h>
#include <reg_script.h>
#include <soc/cpu.h>
#include <soc/iomap.h>
#include <soc/pm.h>
-#include <soc/smm.h>
#include <cpu/intel/turbo.h>
static const struct reg_script core_msr_script[] = {
@@ -189,9 +190,9 @@ static const struct mp_ops mp_ops = {
.get_cpu_count = get_cpu_count,
.get_smm_info = get_smm_info,
.get_microcode_info = get_microcode_info,
- .pre_mp_smm_init = southbridge_smm_clear_state,
+ .pre_mp_smm_init = smm_southbridge_clear_state,
.relocation_handler = relocation_handler,
- .post_mp_init = southbridge_smm_enable_smi,
+ .post_mp_init = smm_southbridge_enable,
};
void apollolake_init_cpus(struct device *dev)
diff --git a/src/soc/intel/apollolake/include/soc/pm.h b/src/soc/intel/apollolake/include/soc/pm.h
index 7db63f6bdc..6c189198ab 100644
--- a/src/soc/intel/apollolake/include/soc/pm.h
+++ b/src/soc/intel/apollolake/include/soc/pm.h
@@ -82,6 +82,20 @@
#define EOS (1 << SMI_EOS) /* End of SMI (deassert SMI#) */
#define GBL_SMI_EN (1 << SMI_GBL) /* Global SMI Enable */
+/* SMI_EN Params for this platform to pass to enable_smi
+ *
+ * Enable SMI generation:
+ * - on APMC writes (io 0xb2)
+ * - on writes to SLP_EN (sleep states)
+ * - on writes to GBL_RLS (bios commands)
+ * - on eSPI events (does nothing on LPC systems)
+ * No SMIs:
+ * - on microcontroller writes (io 0x62/0x66)
+ * - on TCO events
+ */
+#define ENABLE_SMI_PARAMS \
+ (APMC_EN | SLP_SMI_EN | GBL_SMI_EN | EOS | GPIO_EN)
+
#define SMI_STS 0x44
/* Bits for SMI status */
#define PMC_OCP_SMI_STS 27
diff --git a/src/soc/intel/apollolake/memmap.c b/src/soc/intel/apollolake/memmap.c
index 0f85b10aab..c54423c944 100644
--- a/src/soc/intel/apollolake/memmap.c
+++ b/src/soc/intel/apollolake/memmap.c
@@ -27,9 +27,9 @@
#include <assert.h>
#include <cbmem.h>
#include <device/pci.h>
+#include <fsp/memmap.h>
#include <soc/systemagent.h>
#include <soc/pci_devs.h>
-#include <soc/smm.h>
static uintptr_t smm_region_start(void)
{
diff --git a/src/soc/intel/apollolake/smihandler.c b/src/soc/intel/apollolake/smihandler.c
index 0272a5c3c2..f834b1da70 100644
--- a/src/soc/intel/apollolake/smihandler.c
+++ b/src/soc/intel/apollolake/smihandler.c
@@ -14,25 +14,15 @@
* GNU General Public License for more details.
*/
-#include <arch/hlt.h>
#include <arch/io.h>
-#include <console/console.h>
-#include <cpu/x86/cache.h>
#include <cpu/x86/smm.h>
-#include <device/pci_def.h>
-#include <elog.h>
-#include <soc/nvs.h>
-#include <soc/pm.h>
+#include <intelblocks/smihandler.h>
#include <soc/gpio.h>
#include <soc/iomap.h>
#include <soc/pci_devs.h>
-#include <soc/intel/common/smi.h>
-#include <spi-generic.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <soc/smm.h>
+#include <soc/pm.h>
-int smm_disable_busmaster(device_t dev)
+int smihandler_disable_busmaster(device_t dev)
{
if (dev == PCH_DEV_PMC)
return 0;
@@ -47,7 +37,8 @@ const struct smm_save_state_ops *get_smm_save_state_ops(void)
void __attribute__((weak))
mainboard_smi_gpi_handler(const struct gpi_status *sts) { }
-static void southbridge_smi_gpi(const struct smm_save_state_ops *save_state_ops)
+static void southbridge_smi_gpi(
+ const struct smm_save_state_ops *save_state_ops)
{
struct gpi_status smi_sts;
@@ -59,10 +50,10 @@ static void southbridge_smi_gpi(const struct smm_save_state_ops *save_state_ops)
}
const smi_handler_t southbridge_smi[32] = {
- [SLP_SMI_STS] = southbridge_smi_sleep,
- [APM_SMI_STS] = southbridge_smi_apmc,
- [FAKE_PM1_SMI_STS] = southbridge_smi_pm1,
+ [SLP_SMI_STS] = smihandler_southbridge_sleep,
+ [APM_SMI_STS] = smihandler_southbridge_apmc,
+ [FAKE_PM1_SMI_STS] = smihandler_southbridge_pm1,
[GPIO_SMI_STS] = southbridge_smi_gpi,
- [TCO_SMI_STS] = southbridge_smi_tco,
- [PERIODIC_SMI_STS] = southbridge_smi_periodic,
+ [TCO_SMI_STS] = smihandler_southbridge_tco,
+ [PERIODIC_SMI_STS] = smihandler_southbridge_periodic,
};
diff --git a/src/soc/intel/common/Makefile.inc b/src/soc/intel/common/Makefile.inc
index 340e001d2d..110977585d 100644
--- a/src/soc/intel/common/Makefile.inc
+++ b/src/soc/intel/common/Makefile.inc
@@ -31,8 +31,6 @@ ramstage-$(CONFIG_SOC_INTEL_COMMON_GFX_OPREGION) += opregion.c
ramstage-$(CONFIG_SOC_INTEL_COMMON_ACPI) += ./acpi/acpi.c
ramstage-$(CONFIG_SOC_INTEL_COMMON_NHLT) += nhlt.c
-smm-$(CONFIG_SOC_INTEL_COMMON_SMI) += smihandler.c
-
bootblock-$(CONFIG_MAINBOARD_HAS_TPM_CR50) += tpm_tis.c
verstage-$(CONFIG_MAINBOARD_HAS_TPM_CR50) += tpm_tis.c
romstage-$(CONFIG_MAINBOARD_HAS_TPM_CR50) += tpm_tis.c
diff --git a/src/soc/intel/common/smi.h b/src/soc/intel/common/block/include/intelblocks/smihandler.h
index 22c510435b..b587bb136d 100644
--- a/src/soc/intel/common/smi.h
+++ b/src/soc/intel/common/block/include/intelblocks/smihandler.h
@@ -13,8 +13,13 @@
* GNU General Public License for more details.
*/
-#ifndef _INTEL_COMMON_SMI_H_
-#define _INTEL_COMMON_SMI_H_
+#ifndef SOC_INTEL_COMMON_BLOCK_SMI_HANDLER_H
+#define SOC_INTEL_COMMON_BLOCK_SMI_HANDLER_H
+
+#include <stdint.h>
+
+struct gpi_status;
+struct global_nvs_t;
/*
* The register value is used with get_reg and set_reg
@@ -26,8 +31,7 @@ enum smm_reg {
RDX,
};
-
-struct smm_save_state_ops {
+struct smm_save_state_ops {
/* return io_misc_info from SMM Save State Area */
uint32_t (*get_io_misc_info)(void *state);
@@ -50,63 +54,72 @@ const struct smm_save_state_ops *get_smm_save_state_ops(void);
/*
* southbridge_smi should be defined inside SOC specific code and should have
* handlers for any SMI events that need to be handled. Default handlers
- * for some SMI events are provided in soc/intel/common/smihandler.c
+ * for some SMI events are provided in soc/intel/common/block/smm/smihandler.c
*/
extern const smi_handler_t southbridge_smi[32];
/*
* This function should be implemented in SOC specific code to handle
* the SMI event on SLP_EN. The default functionality is provided in
- * soc/intel/common/smihandler.c
+ * soc/intel/common/block/smm/smihandler.c
*/
-void southbridge_smi_sleep(const struct smm_save_state_ops *save_state_ops);
+void smihandler_southbridge_sleep(
+ const struct smm_save_state_ops *save_state_ops);
/*
* This function should be implemented in SOC specific code to handle
* SMI_APM event. The default functionality is provided in
- * soc/intel/common/smihandler.c
+ * soc/intel/common/block/smm/smihandler.c
*/
-void southbridge_smi_apmc(const struct smm_save_state_ops *save_state_ops);
+void smihandler_southbridge_apmc(
+ const struct smm_save_state_ops *save_state_ops);
/*
* This function should be implemented in SOC specific code to handle
* SMI_PM1 event. The default functionality is provided in
- * soc/intel/common/smihandler.c
+ * soc/intel/common/block/smm/smihandler.c
*/
-void southbridge_smi_pm1(const struct smm_save_state_ops *save_state_ops);
+void smihandler_southbridge_pm1(
+ const struct smm_save_state_ops *save_state_ops);
/*
* This function should be implemented in SOC specific code to handle
* SMI_GPE0 event. The default functionality is provided in
- * soc/intel/common/smihandler.c
+ * soc/intel/common/block/smm/smihandler.c
*/
-void southbridge_smi_gpe0(const struct smm_save_state_ops *save_state_ops);
+void smihandler_southbridge_gpe0(
+ const struct smm_save_state_ops *save_state_ops);
/*
* This function should be implemented in SOC specific code to handle
* SMI_TCO event. The default functionality is provided in
- * soc/intel/common/smihandler.c
+ * soc/intel/common/block/smm/smihandler.c
*/
-void southbridge_smi_tco(const struct smm_save_state_ops *save_state_ops);
+void smihandler_southbridge_tco(
+ const struct smm_save_state_ops *save_state_ops);
/*
* This function should be implemented in SOC specific code to handle
* SMI PERIODIC_STS event. The default functionality is provided in
- * soc/intel/common/smihandler.c
+ * soc/intel/common/block/smm/smihandler.c
*/
-void southbridge_smi_periodic(const struct smm_save_state_ops *save_state_ops);
+void smihandler_southbridge_periodic(
+ const struct smm_save_state_ops *save_state_ops);
/*
* This function returns a 1 or 0 depending on whether disable_busmaster
* needs to be done for the specified device on S5 entry
*/
-int smm_disable_busmaster(device_t dev);
+int smihandler_disable_busmaster(device_t dev);
/*
* Returns gnvs pointer within SMM context
*/
struct global_nvs_t *smm_get_gnvs(void);
+/* Mainboard handler for GPI SMIs */
+void mainboard_smi_gpi_handler(const struct gpi_status *sts);
+
extern const struct smm_save_state_ops em64t100_smm_ops;
extern const struct smm_save_state_ops em64t101_smm_ops;
diff --git a/src/soc/intel/common/block/include/intelblocks/smm.h b/src/soc/intel/common/block/include/intelblocks/smm.h
new file mode 100644
index 0000000000..09378b9463
--- /dev/null
+++ b/src/soc/intel/common/block/include/intelblocks/smm.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 201 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+
+#ifndef SOC_INTEL_COMMON_BLOCK_SMM_H
+#define SOC_INTEL_COMMON_BLOCK_SMM_H
+
+/*
+ * This common code block relies on each specific SOC defining the macro
+ * ENABLE_SMI_PARAMS for the values needed for SMI enabling on the
+ * specific SOC
+ */
+
+/*
+ * The initialization of the southbridge is split into 2 compoments. One is
+ * for clearing the state in the SMM registers. The other is for enabling
+ * SMIs.
+ */
+void smm_southbridge_clear_state(void);
+void smm_southbridge_enable(void);
+
+#endif
diff --git a/src/soc/intel/common/block/smm/Kconfig b/src/soc/intel/common/block/smm/Kconfig
new file mode 100644
index 0000000000..003fc24cd8
--- /dev/null
+++ b/src/soc/intel/common/block/smm/Kconfig
@@ -0,0 +1,4 @@
+config SOC_INTEL_COMMON_BLOCK_SMM
+ bool
+ help
+ Intel Processor common SMM support
diff --git a/src/soc/intel/common/block/smm/Makefile.inc b/src/soc/intel/common/block/smm/Makefile.inc
new file mode 100644
index 0000000000..13793ee891
--- /dev/null
+++ b/src/soc/intel/common/block/smm/Makefile.inc
@@ -0,0 +1,2 @@
+ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMM) += smm.c
+smm-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMM) += smihandler.c
diff --git a/src/soc/intel/common/smihandler.c b/src/soc/intel/common/block/smm/smihandler.c
index 88ea819012..b620ff9f1e 100644
--- a/src/soc/intel/common/smihandler.c
+++ b/src/soc/intel/common/block/smm/smihandler.c
@@ -21,6 +21,7 @@
#include <cpu/x86/smm.h>
#include <device/pci_def.h>
#include <elog.h>
+#include <intelblocks/smihandler.h>
#include <soc/nvs.h>
#include <soc/pm.h>
#include <soc/gpio.h>
@@ -28,18 +29,17 @@
#include <spi-generic.h>
#include <stdint.h>
#include <stdlib.h>
-#include "smi.h"
/* GNVS needs to be set by coreboot initiating a software SMI. */
static struct global_nvs_t *gnvs;
-__attribute__((weak)) int smm_disable_busmaster(device_t dev)
+__attribute__((weak)) int smihandler_disable_busmaster(device_t dev)
{
return 1;
}
static void *find_save_state(const struct smm_save_state_ops *save_state_ops,
- int cmd)
+ int cmd)
{
int node;
void *state = NULL;
@@ -70,6 +70,7 @@ static void *find_save_state(const struct smm_save_state_ops *save_state_ops,
return state;
}
+/* Inherited from cpu/x86/smm.h resulting in a different signature */
void southbridge_smi_set_eos(void)
{
enable_smi(EOS);
@@ -91,7 +92,7 @@ static void busmaster_disable_on_bus(int bus)
u32 reg32;
device_t dev = PCI_DEV(bus, slot, func);
- if (!smm_disable_busmaster(dev))
+ if (!smihandler_disable_busmaster(dev))
continue;
val = pci_read_config32(dev, PCI_VENDOR_ID);
@@ -127,7 +128,8 @@ static void busmaster_disable_on_bus(int bus)
}
-void southbridge_smi_sleep(const struct smm_save_state_ops *save_state_ops)
+void smihandler_southbridge_sleep(
+ const struct smm_save_state_ops *save_state_ops)
{
uint32_t reg32;
uint8_t slp_typ;
@@ -205,8 +207,8 @@ void southbridge_smi_sleep(const struct smm_save_state_ops *save_state_ops)
}
}
-static void southbridge_smi_gsmi(const struct
- smm_save_state_ops *save_state_ops)
+static void southbridge_smi_gsmi(
+ const struct smm_save_state_ops *save_state_ops)
{
u8 sub_command, ret;
void *io_smi = NULL;
@@ -239,7 +241,8 @@ static void finalize(void)
}
-void southbridge_smi_apmc(const struct smm_save_state_ops *save_state_ops)
+void smihandler_southbridge_apmc(
+ const struct smm_save_state_ops *save_state_ops)
{
uint8_t reg8;
void *state = NULL;
@@ -300,7 +303,8 @@ void southbridge_smi_apmc(const struct smm_save_state_ops *save_state_ops)
mainboard_smi_apmc(reg8);
}
-void southbridge_smi_pm1(const struct smm_save_state_ops *save_state_ops)
+void smihandler_southbridge_pm1(
+ const struct smm_save_state_ops *save_state_ops)
{
uint16_t pm1_sts = clear_pm1_status();
@@ -317,12 +321,14 @@ void southbridge_smi_pm1(const struct smm_save_state_ops *save_state_ops)
}
}
-void southbridge_smi_gpe0(const struct smm_save_state_ops *save_state_ops)
+void smihandler_southbridge_gpe0(
+ const struct smm_save_state_ops *save_state_ops)
{
clear_gpe_status();
}
-void southbridge_smi_tco(const struct smm_save_state_ops *save_state_ops)
+void smihandler_southbridge_tco(
+ const struct smm_save_state_ops *save_state_ops)
{
uint32_t tco_sts = clear_tco_status();
@@ -336,7 +342,8 @@ void southbridge_smi_tco(const struct smm_save_state_ops *save_state_ops)
}
}
-void southbridge_smi_periodic(const struct smm_save_state_ops *save_state_ops)
+void smihandler_southbridge_periodic(
+ const struct smm_save_state_ops *save_state_ops)
{
uint32_t reg32;
diff --git a/src/soc/intel/common/block/smm/smm.c b/src/soc/intel/common/block/smm/smm.c
new file mode 100644
index 0000000000..ab60af615d
--- /dev/null
+++ b/src/soc/intel/common/block/smm/smm.c
@@ -0,0 +1,78 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ * Copyright (C) 2014 Google Inc.
+ * Copyright (C) 2015 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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.
+ */
+
+#include <console/console.h>
+#include <cpu/x86/smm.h>
+#include <intelblocks/smm.h>
+#include <soc/pm.h>
+
+void smm_southbridge_clear_state(void)
+{
+ printk(BIOS_DEBUG, "Clearing SMI status registers\n");
+
+ if (get_smi_en() & APMC_EN) {
+ printk(BIOS_INFO, "SMI# handler already enabled?\n");
+ return;
+ }
+
+ /* Dump and clear status registers */
+ clear_smi_status();
+ clear_pm1_status();
+ clear_tco_status();
+ clear_gpe_status();
+}
+
+void smm_southbridge_enable(void)
+{
+ printk(BIOS_DEBUG, "Enabling SMIs.\n");
+ /* Configure events */
+ enable_pm1(PWRBTN_EN | GBL_EN);
+ disable_gpe(PME_B0_EN);
+
+ /*
+ * Enable SMI generation:
+ * - on APMC writes (io 0xb2)
+ * - on writes to SLP_EN (sleep states)
+ * - on writes to GBL_RLS (bios commands)
+ * - on eSPI events (does nothing on LPC systems)
+ * No SMIs:
+ * - on microcontroller writes (io 0x62/0x66)
+ * - on TCO events
+ */
+
+ /* Enable SMI generation: */
+ enable_smi(ENABLE_SMI_PARAMS);
+}
+
+void smm_setup_structures(void *gnvs, void *tcg, void *smi1)
+{
+ /*
+ * Issue SMI to set the gnvs pointer in SMM.
+ * tcg and smi1 are unused.
+ *
+ * EAX = APM_CNT_GNVS_UPDATE
+ * EBX = gnvs pointer
+ * EDX = APM_CNT
+ */
+ asm volatile (
+ "outb %%al, %%dx\n\t"
+ : /* ignore result */
+ : "a" (APM_CNT_GNVS_UPDATE),
+ "b" ((u32)gnvs),
+ "d" (APM_CNT)
+ );
+}