[coreboot-gerrit] Change in coreboot[master]: soc/intel/common: [WIP]Add SMI common code for Intel Platforms

Brandon Breitenstein (Code Review) gerrit at coreboot.org
Wed May 31 23:43:50 CEST 2017


Brandon Breitenstein has uploaded a new change for review. ( https://review.coreboot.org/19392 )

Change subject: soc/intel/common: [WIP]Add SMI common code for Intel Platforms
......................................................................

soc/intel/common: [WIP]Add SMI common code for Intel Platforms

SMI code is very similar across Intel platforms. Move this code to
common/block/smi to allow it to be shared between platforms instead
of duplicating the code for each platform. This patch relies on the
PMC implemenation for common code.

Change-Id: I599358f23d5de7564ef1ca414bccd54cebab5a4c
Signed-off-by: Brandon Breitenstein <brandon.breitenstein at intel.com>
---
M src/soc/intel/common/Makefile.inc
A src/soc/intel/common/block/include/intelblocks/smi.h
R src/soc/intel/common/block/include/intelblocks/smihandler.h
A src/soc/intel/common/block/smi/Kconfig
A src/soc/intel/common/block/smi/Makefile.inc
A src/soc/intel/common/block/smi/smi.c
R src/soc/intel/common/block/smi/smihandler.c
7 files changed, 165 insertions(+), 39 deletions(-)


  git pull ssh://review.coreboot.org:29418/coreboot refs/changes/92/19392/6

diff --git a/src/soc/intel/common/Makefile.inc b/src/soc/intel/common/Makefile.inc
index b01fc8a..1a1cef1 100644
--- a/src/soc/intel/common/Makefile.inc
+++ b/src/soc/intel/common/Makefile.inc
@@ -35,8 +35,6 @@
 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/block/include/intelblocks/smi.h b/src/soc/intel/common/block/include/intelblocks/smi.h
new file mode 100644
index 0000000..75a6e49
--- /dev/null
+++ b/src/soc/intel/common/block/include/intelblocks/smi.h
@@ -0,0 +1,33 @@
+/*
+ * 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_SMI_H
+#define SOC_INTEL_COMMON_BLOCK_SMI_H
+
+#include <soc/gpio.h>
+
+/*
+ * 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 smi_southbridge_clear_state(void);
+void smi_southbridge_enable(void);
+
+/* Mainboard handler for GPI SMIs*/
+void smi_mainboard_gpi_handler(const struct gpi_status *sts);
+
+#endif
diff --git a/src/soc/intel/common/smi.h b/src/soc/intel/common/block/include/intelblocks/smihandler.h
similarity index 76%
rename from src/soc/intel/common/smi.h
rename to src/soc/intel/common/block/include/intelblocks/smihandler.h
index 22c5104..a119e18 100644
--- a/src/soc/intel/common/smi.h
+++ b/src/soc/intel/common/block/include/intelblocks/smihandler.h
@@ -13,8 +13,8 @@
  * 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
 
 /*
  * The register value is used with get_reg and set_reg
@@ -59,48 +59,55 @@
  * the SMI event on SLP_EN. The default functionality is provided in
  * soc/intel/common/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
  */
-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
  */
-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
  */
-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
  */
-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
  */
-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);
+
+/*
+ * This function returns the ACPI base address for the platform. This is
+ * dependent on the specific platform defining this value. 0 is returned
+ * if the value is not defined by the platform.
+ */
+uint16_t smihandler_get_acpi_base(void);
 
 /*
  * Returns gnvs pointer within SMM context
diff --git a/src/soc/intel/common/block/smi/Kconfig b/src/soc/intel/common/block/smi/Kconfig
new file mode 100644
index 0000000..485986e
--- /dev/null
+++ b/src/soc/intel/common/block/smi/Kconfig
@@ -0,0 +1,5 @@
+config SOC_INTEL_COMMON_BLOCK_SMI
+	bool
+	default n
+	help
+	  Intel Processor common SMI support
diff --git a/src/soc/intel/common/block/smi/Makefile.inc b/src/soc/intel/common/block/smi/Makefile.inc
new file mode 100644
index 0000000..1737df8
--- /dev/null
+++ b/src/soc/intel/common/block/smi/Makefile.inc
@@ -0,0 +1,2 @@
+ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMI) += smi.c
+smm-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMI) += smihandler.c
diff --git a/src/soc/intel/common/block/smi/smi.c b/src/soc/intel/common/block/smi/smi.c
new file mode 100644
index 0000000..8cf083a
--- /dev/null
+++ b/src/soc/intel/common/block/smi/smi.c
@@ -0,0 +1,69 @@
+/*
+ * 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/smi.h>
+#include <soc/pm.h>
+
+void smi_southbridge_clear_state(void)
+{
+	printk(BIOS_DEBUG, "Initializing Southbridge SMI...");
+
+	if (pmc_get_smi_en() & APMC_EN) {
+		printk(BIOS_INFO, "SMI# handler already enabled?\n");
+		return;
+	}
+
+	printk(BIOS_DEBUG, "Done\n");
+
+	/* Dump and clear status registers */
+	pmc_clear_smi_status();
+	pmc_clear_pm1_status();
+	pmc_clear_tco_status();
+	pmc_clear_gpe_status();
+}
+
+void smi_southbridge_enable(void)
+{
+	printk(BIOS_DEBUG, "Enabling SMIs.\n");
+	/* Configure events */
+	pmc_enable_pm1(PWRBTN_EN | GBL_EN);
+	pmc_disable_gpe(PME_B0_EN);
+
+	/* Enable SMI generation: */
+	pmc_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)
+	);
+}
diff --git a/src/soc/intel/common/smihandler.c b/src/soc/intel/common/block/smi/smihandler.c
similarity index 87%
rename from src/soc/intel/common/smihandler.c
rename to src/soc/intel/common/block/smi/smihandler.c
index 549a914..d7f0cb0 100644
--- a/src/soc/intel/common/smihandler.c
+++ b/src/soc/intel/common/block/smi/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,14 +29,18 @@
 #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;
+}
+
+__attribute__((weak)) uint16_t smihandler_get_acpi_base(void)
+{
+	return 0;
 }
 
 static void *find_save_state(const struct smm_save_state_ops *save_state_ops,
@@ -70,9 +75,10 @@
 	return state;
 }
 
+/* Inherited from cpu/x86/smm.h resulting in a different signature */
 void southbridge_smi_set_eos(void)
 {
-	enable_smi(EOS);
+	pmc_enable_smi(EOS);
 }
 
 struct global_nvs_t *smm_get_gnvs(void)
@@ -91,7 +97,7 @@
 			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,15 +133,16 @@
 }
 
 
-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;
 
 	/* First, disable further SMIs */
-	disable_smi(SLP_SMI_EN);
+	pmc_disable_smi(SLP_SMI_EN);
 	/* Figure out SLP_TYP */
-	reg32 = inl(ACPI_PMIO_BASE + PM1_CNT);
+	reg32 = inl(smihandler_get_acpi_base() + PM1_CNT);
 	printk(BIOS_SPEW, "SMI#: SLP = 0x%08x\n", reg32);
 	slp_typ = acpi_sleep_from_pm1(reg32);
 
@@ -147,7 +154,7 @@
 		elog_add_event_byte(ELOG_TYPE_ACPI_ENTER, slp_typ);
 
 	/* Clear pending GPE events */
-	clear_gpe_status();
+	pmc_clear_gpe_status();
 
 	/* Next, do the deed. */
 
@@ -168,7 +175,7 @@
 		printk(BIOS_DEBUG, "SMI#: Entering S5 (Soft Power off)\n");
 
 		/* Disable all GPE */
-		disable_all_gpe();
+		pmc_disable_all_gpe();
 		/* also iterates over all bridges on bus 0 */
 		busmaster_disable_on_bus(0);
 		break;
@@ -178,7 +185,7 @@
 	}
 
 	/* Clear the gpio gpe0 status bits in ACPI registers */
-	clear_gpi_gpe_sts();
+	pmc_clear_gpi_gpe_sts();
 
 	/* Tri-state specific GPIOS to avoid leakage during S3/S5 */
 
@@ -187,7 +194,7 @@
 	 * event again. We need to set BIT13 (SLP_EN) though to make the
 	 * sleep happen.
 	 */
-	enable_pm1_control(SLP_EN);
+	pmc_enable_pm1_control(SLP_EN);
 
 	/* Make sure to stop executing code here for S3/S4/S5 */
 	if (slp_typ >= ACPI_S3)
@@ -198,15 +205,15 @@
 	 * the line above. However, if we entered sleep state S1 and wake
 	 * up again, we will continue to execute code in this function.
 	 */
-	reg32 = inl(ACPI_PMIO_BASE + PM1_CNT);
+	reg32 = inl(smihandler_get_acpi_base() + PM1_CNT);
 	if (reg32 & SCI_EN) {
 		/* The OS is not an ACPI OS, so we set the state to S0 */
-		disable_pm1_control(SLP_EN | SLP_TYP);
+		pmc_disable_pm1_control(SLP_EN | SLP_TYP);
 	}
 }
 
 static void southbridge_smi_gsmi(const struct
-			smm_save_state_ops *save_state_ops)
+			smm_save_state_ops * save_state_ops)
 {
 	u8 sub_command, ret;
 	void *io_smi = NULL;
@@ -239,7 +246,8 @@
 
 }
 
-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;
@@ -266,11 +274,11 @@
 		printk(BIOS_DEBUG, "P-state control\n");
 		break;
 	case APM_CNT_ACPI_DISABLE:
-		disable_pm1_control(SCI_EN);
+		pmc_disable_pm1_control(SCI_EN);
 		printk(BIOS_DEBUG, "SMI#: ACPI disabled.\n");
 		break;
 	case APM_CNT_ACPI_ENABLE:
-		enable_pm1_control(SCI_EN);
+		pmc_enable_pm1_control(SCI_EN);
 		printk(BIOS_DEBUG, "SMI#: ACPI enabled.\n");
 		break;
 	case APM_CNT_GNVS_UPDATE:
@@ -300,9 +308,10 @@
 	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();
+	uint16_t pm1_sts = pmc_clear_pm1_status();
 
 	/*
 	 * While OSPM is not active, poweroff immediately
@@ -312,19 +321,21 @@
 		/* power button pressed */
 		if (IS_ENABLED(CONFIG_ELOG_GSMI))
 			elog_add_event(ELOG_TYPE_POWER_BUTTON);
-		disable_pm1_control(-1UL);
-		enable_pm1_control(SLP_EN | (SLP_TYP_S5 << SLP_TYP_SHIFT));
+		pmc_disable_pm1_control(-1UL);
+		pmc_enable_pm1_control(SLP_EN | (SLP_TYP_S5 << SLP_TYP_SHIFT));
 	}
 }
 
-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();
+	pmc_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();
+	uint32_t tco_sts = pmc_clear_tco_status();
 
 	/* Any TCO event? */
 	if (!tco_sts)
@@ -336,11 +347,12 @@
 	}
 }
 
-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;
 
-	reg32 = get_smi_en();
+	reg32 = pmc_get_smi_en();
 
 	/* Are periodic SMIs enabled? */
 	if ((reg32 & PERIODIC_EN) == 0)
@@ -358,7 +370,7 @@
 	 * We need to clear the SMI status registers, or we won't see what's
 	 * happening in the following calls.
 	 */
-	smi_sts = clear_smi_status();
+	smi_sts = pmc_clear_smi_status();
 
 	save_state_ops = get_smm_save_state_ops();
 

-- 
To view, visit https://review.coreboot.org/19392
To unsubscribe, visit https://review.coreboot.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I599358f23d5de7564ef1ca414bccd54cebab5a4c
Gerrit-PatchSet: 6
Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Owner: Brandon Breitenstein <brandon.breitenstein at intel.com>
Gerrit-Reviewer: Aaron Durbin <adurbin at chromium.org>
Gerrit-Reviewer: Brandon Breitenstein <brandon.breitenstein at intel.com>
Gerrit-Reviewer: Brenton Dong <brenton.m.dong at intel.com>
Gerrit-Reviewer: Hannah Williams <hannah.williams at intel.com>
Gerrit-Reviewer: Lijian Zhao <lijian.zhao at intel.com>
Gerrit-Reviewer: Subrata Banik <subrata.banik at intel.com>



More information about the coreboot-gerrit mailing list