aboutsummaryrefslogtreecommitdiff
path: root/src/soc/intel/skylake/smihandler.c
diff options
context:
space:
mode:
authorLee Leahy <leroy.p.leahy@intel.com>2015-05-12 18:23:27 -0700
committerLeroy P Leahy <leroy.p.leahy@intel.com>2015-07-16 17:24:48 +0200
commit1d14b3e926c15027f9272f1e80b8913fef8cf25d (patch)
treeb3d89ad4bb1b0ea5ac05d1d7dc6cbf26ec93e6c3 /src/soc/intel/skylake/smihandler.c
parentb000513741d330947bb832a5835378e35bdfb394 (diff)
soc/intel: Add Skylake SOC support
Add the files to support the Skylake SOC. Matches chromium tree at 927026db BRANCH=none BUG=None TEST=Build and run on a Skylake platform Change-Id: I80248f7e47eaf13b52e3c7ff951eb1976edbaa15 Signed-off-by: Lee Leahy <leroy.p.leahy@intel.com> Reviewed-on: http://review.coreboot.org/10341 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src/soc/intel/skylake/smihandler.c')
-rw-r--r--src/soc/intel/skylake/smihandler.c313
1 files changed, 130 insertions, 183 deletions
diff --git a/src/soc/intel/skylake/smihandler.c b/src/soc/intel/skylake/smihandler.c
index 63c93739e7..dddba56ee8 100644
--- a/src/soc/intel/skylake/smihandler.c
+++ b/src/soc/intel/skylake/smihandler.c
@@ -3,6 +3,7 @@
*
* 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
@@ -15,11 +16,12 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * Foundation, Inc.
*/
#include <delay.h>
#include <types.h>
+#include <arch/hlt.h>
#include <arch/io.h>
#include <console/console.h>
#include <cpu/x86/cache.h>
@@ -27,16 +29,16 @@
#include <cpu/x86/smm.h>
#include <spi-generic.h>
#include <elog.h>
-#include <halt.h>
#include <pc80/mc146818rtc.h>
+#include <soc/iomap.h>
#include <soc/lpc.h>
#include <soc/nvs.h>
#include <soc/pci_devs.h>
+#include <soc/pch.h>
+#include <soc/pcr.h>
#include <soc/pm.h>
-#include <soc/rcba.h>
+#include <soc/pmc.h>
#include <soc/smm.h>
-#include <soc/xhci.h>
-#include <drivers/intel/gma/i915_reg.h>
static u8 smm_initialized = 0;
@@ -55,9 +57,10 @@ int southbridge_io_trap_handler(int smif)
switch (smif) {
case 0x32:
printk(BIOS_DEBUG, "OS Init\n");
- /* gnvs->smif:
- * On success, the IO Trap Handler returns 0
- * On failure, the IO Trap Handler returns a value != 0
+ /*
+ * gnvs->smif:
+ * - On success, the IO Trap Handler returns 0
+ * - On failure, the IO Trap Handler returns a value != 0
*/
gnvs->smif = 0;
return 1; /* IO trap handled */
@@ -67,9 +70,7 @@ int southbridge_io_trap_handler(int smif)
return 0;
}
-/**
- * @brief Set the EOS bit
- */
+/* Set the EOS bit */
void southbridge_smi_set_eos(void)
{
enable_smi(EOS);
@@ -77,78 +78,39 @@ void southbridge_smi_set_eos(void)
static void busmaster_disable_on_bus(int bus)
{
- int slot, func;
- unsigned int val;
- unsigned char hdr;
-
- for (slot = 0; slot < 0x20; slot++) {
- for (func = 0; func < 8; func++) {
- u32 reg32;
- device_t dev = PCI_DEV(bus, slot, func);
-
- val = pci_read_config32(dev, PCI_VENDOR_ID);
-
- if (val == 0xffffffff || val == 0x00000000 ||
- val == 0x0000ffff || val == 0xffff0000)
- continue;
-
- /* Disable Bus Mastering for this one device */
- reg32 = pci_read_config32(dev, PCI_COMMAND);
- reg32 &= ~PCI_COMMAND_MASTER;
- pci_write_config32(dev, PCI_COMMAND, reg32);
-
- /* If this is a bridge, then follow it. */
- hdr = pci_read_config8(dev, PCI_HEADER_TYPE);
- hdr &= 0x7f;
- if (hdr == PCI_HEADER_TYPE_BRIDGE ||
- hdr == PCI_HEADER_TYPE_CARDBUS) {
- unsigned int buses;
- buses = pci_read_config32(dev, PCI_PRIMARY_BUS);
- busmaster_disable_on_bus((buses >> 8) & 0xff);
- }
- }
- }
+ int slot, func;
+ unsigned int val;
+ unsigned char hdr;
+
+ for (slot = 0; slot < 0x20; slot++) {
+ for (func = 0; func < 8; func++) {
+ u32 reg32;
+ device_t dev = PCI_DEV(bus, slot, func);
+
+ val = pci_read_config32(dev, PCI_VENDOR_ID);
+
+ if (val == 0xffffffff || val == 0x00000000 ||
+ val == 0x0000ffff || val == 0xffff0000)
+ continue;
+
+ /* Disable Bus Mastering for this one device */
+ reg32 = pci_read_config32(dev, PCI_COMMAND);
+ reg32 &= ~PCI_COMMAND_MASTER;
+ pci_write_config32(dev, PCI_COMMAND, reg32);
+
+ /* If this is a bridge, then follow it. */
+ hdr = pci_read_config8(dev, PCI_HEADER_TYPE);
+ hdr &= 0x7f;
+ if (hdr == PCI_HEADER_TYPE_BRIDGE ||
+ hdr == PCI_HEADER_TYPE_CARDBUS) {
+ unsigned int buses;
+ buses = pci_read_config32(dev, PCI_PRIMARY_BUS);
+ busmaster_disable_on_bus((buses >> 8) & 0xff);
+ }
+ }
+ }
}
-/*
- * Turn off the backlight if it is on, and wait for the specified
- * backlight off delay. This will allow panel power timings to meet
- * spec and prevent brief garbage on the screen when turned off
- * during firmware with power button triggered SMI.
- */
-static void backlight_off(void)
-{
- void *reg_base;
- uint32_t pp_ctrl;
- uint32_t bl_off_delay;
-
- reg_base = (void *)((uintptr_t)pci_read_config32(SA_DEV_IGD, PCI_BASE_ADDRESS_0) & ~0xf);
-
- /* Check if backlight is enabled */
- pp_ctrl = read32(reg_base + PCH_PP_CONTROL);
- if (!(pp_ctrl & EDP_BLC_ENABLE))
- return;
-
- /* Enable writes to this register */
- pp_ctrl &= ~PANEL_UNLOCK_MASK;
- pp_ctrl |= PANEL_UNLOCK_REGS;
-
- /* Turn off backlight */
- pp_ctrl &= ~EDP_BLC_ENABLE;
-
- write32(reg_base + PCH_PP_CONTROL, pp_ctrl);
- read32(reg_base + PCH_PP_CONTROL);
-
- /* Read backlight off delay in 100us units */
- bl_off_delay = read32(reg_base + PCH_PP_OFF_DELAYS);
- bl_off_delay &= PANEL_LIGHT_OFF_DELAY_MASK;
- bl_off_delay *= 100;
-
- /* Wait for backlight to turn off */
- udelay(bl_off_delay);
-
- printk(BIOS_INFO, "Backlight turned off\n");
-}
static void southbridge_smi_sleep(void)
{
@@ -176,21 +138,15 @@ static void southbridge_smi_sleep(void)
/* Do any mainboard sleep handling */
mainboard_smi_sleep(slp_typ-2);
- /* USB sleep preparations */
- usb_xhci_sleep_prepare(PCH_DEV_XHCI, slp_typ);
-
-#if CONFIG_ELOG_GSMI
- /* Log S3, S4, and S5 entry */
- if (slp_typ >= 5)
- elog_add_event_byte(ELOG_TYPE_ACPI_ENTER, slp_typ-2);
-#endif
+ if (IS_ENABLED(CONFIG_ELOG_GSMI))
+ /* Log S3, S4, and S5 entry */
+ if (slp_typ >= 5)
+ elog_add_event_byte(ELOG_TYPE_ACPI_ENTER, slp_typ-2);
/* Clear pending GPE events */
clear_gpe_status();
- /* Next, do the deed.
- */
-
+ /* Next, do the deed. */
switch (slp_typ) {
case SLP_TYP_S0:
printk(BIOS_DEBUG, "SMI#: Entering S0 (On)\n");
@@ -204,27 +160,23 @@ static void southbridge_smi_sleep(void)
/* Invalidate the cache before going to S3 */
wbinvd();
break;
- case SLP_TYP_S4:
- printk(BIOS_DEBUG, "SMI#: Entering S4 (Suspend-To-Disk)\n");
- break;
case SLP_TYP_S5:
printk(BIOS_DEBUG, "SMI#: Entering S5 (Soft Power off)\n");
-
- /* Turn off backlight if needed */
- backlight_off();
-
+ /*TODO: cmos_layout.bin need to verify; cause wrong CMOS setup*/
+ s5pwr = MAINBOARD_POWER_ON;
/* Disable all GPE */
disable_all_gpe();
- /* Always set the flag in case CMOS was changed on runtime. For
+ /*
+ * Always set the flag in case CMOS was changed on runtime. For
* "KEEP", switch to "OFF" - KEEP is software emulated
*/
- reg8 = pci_read_config8(PCH_DEV_LPC, GEN_PMCON_3);
+ reg8 = pci_read_config8(PCH_DEV_PMC, GEN_PMCON_B);
if (s5pwr == MAINBOARD_POWER_ON)
reg8 &= ~1;
else
reg8 |= 1;
- pci_write_config8(PCH_DEV_LPC, GEN_PMCON_3, reg8);
+ pci_write_config8(PCH_DEV_PMC, GEN_PMCON_B, reg8);
/* also iterates over all bridges on bus 0 */
busmaster_disable_on_bus(0);
@@ -243,7 +195,7 @@ static void southbridge_smi_sleep(void)
/* Make sure to stop executing code here for S3/S4/S5 */
if (slp_typ > 1)
- halt();
+ hlt();
/*
* In most sleep states, the code flow of this function ends at
@@ -293,9 +245,9 @@ static em64t101_smm_state_save_area_t *smi_apmc_find_state_save(u8 cmd)
return NULL;
}
-#if CONFIG_ELOG_GSMI
static void southbridge_smi_gsmi(void)
{
+#if IS_ENABLED(CONFIG_ELOG_GSMI)
u32 *ret, *param;
u8 sub_command;
em64t101_smm_state_save_area_t *io_smi =
@@ -305,16 +257,16 @@ static void southbridge_smi_gsmi(void)
return;
/* Command and return value in EAX */
- ret = (u32*)&io_smi->rax;
+ ret = (u32 *)&io_smi->rax;
sub_command = (u8)(*ret >> 8);
/* Parameter buffer in EBX */
- param = (u32*)&io_smi->rbx;
+ param = (u32 *)&io_smi->rbx;
/* drivers/elog/gsmi.c */
*ret = gsmi_exec(sub_command, param);
-}
#endif
+}
static void finalize(void)
{
@@ -326,10 +278,9 @@ static void finalize(void)
}
finalize_done = 1;
-#if CONFIG_SPI_FLASH_SMM
- /* Re-init SPI driver to handle locked BAR */
- spi_init();
-#endif
+ if (IS_ENABLED(CONFIG_SPI_FLASH_SMM))
+ /* Re-init SPI driver to handle locked BAR */
+ spi_init();
}
static void southbridge_smi_apmc(void)
@@ -341,9 +292,6 @@ static void southbridge_smi_apmc(void)
reg8 = inb(APM_CNT);
switch (reg8) {
- case APM_CNT_CST_CONTROL:
- printk(BIOS_DEBUG, "C-state control\n");
- break;
case APM_CNT_PST_CONTROL:
printk(BIOS_DEBUG, "P-state control\n");
break;
@@ -372,11 +320,10 @@ static void southbridge_smi_apmc(void)
printk(BIOS_DEBUG, "SMI#: Setting GNVS to %p\n", gnvs);
}
break;
-#if CONFIG_ELOG_GSMI
case ELOG_GSMI_APM_CNT:
- southbridge_smi_gsmi();
+ if (IS_ENABLED(CONFIG_ELOG_GSMI))
+ southbridge_smi_gsmi();
break;
-#endif
}
mainboard_smi_apmc(reg8);
@@ -386,14 +333,14 @@ static void southbridge_smi_pm1(void)
{
u16 pm1_sts = clear_pm1_status();
- /* While OSPM is not active, poweroff immediately
- * on a power button event.
+ /*
+ * While OSPM is not active, poweroff immediately on a power button
+ * event.
*/
if (pm1_sts & PWRBTN_STS) {
/* power button pressed */
-#if CONFIG_ELOG_GSMI
- elog_add_event(ELOG_TYPE_POWER_BUTTON);
-#endif
+ 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 << 10));
}
@@ -431,8 +378,8 @@ static void southbridge_smi_tco(void)
if (!tco_sts)
return;
- if (tco_sts & (1 << 8)) { // BIOSWR
- u8 bios_cntl = pci_read_config16(PCH_DEV_LPC, BIOS_CNTL);
+ if (tco_sts & (1 << 8)) { /* BIOSWR */
+ u8 bios_cntl = pci_read_config16(PCH_DEV_SPI, BIOS_CNTL);
if (bios_cntl & 1) {
/*
@@ -446,7 +393,7 @@ static void southbridge_smi_tco(void)
* box.
*/
printk(BIOS_DEBUG, "Switching back to RO\n");
- pci_write_config32(PCH_DEV_LPC, BIOS_CNTL,
+ pci_write_config32(PCH_DEV_SPI, BIOS_CNTL,
(bios_cntl & ~1));
} /* No else for now? */
} else if (tco_sts & (1 << 3)) { /* TIMEOUT */
@@ -472,12 +419,14 @@ static void southbridge_smi_monitor(void)
u32 trap_sts, trap_cycle;
u32 data, mask = 0;
int i;
-
- trap_sts = RCBA32(0x1e00); // TRSR - Trap Status Register
- RCBA32(0x1e00) = trap_sts; // Clear trap(s) in TRSR
-
- trap_cycle = RCBA32(0x1e10);
- for (i=16; i<20; i++) {
+ /* TRSR - Trap Status Register */
+ pcr_read32(PID_PSTH, R_PCH_PCR_PSTH_TRPST, &trap_sts);
+ /* Clear trap(s) in TRSR */
+ pcr_write8(PID_PSTH, R_PCH_PCR_PSTH_TRPST, trap_sts);
+
+ /* TRPC - Trapped cycle */
+ pcr_read32(PID_PSTH, R_PCH_PCR_PSTH_TRPC, &trap_cycle);
+ for (i = 16; i < 20; i++) {
if (trap_cycle & (1 << i))
mask |= (0xff << ((i - 16) << 2));
}
@@ -486,30 +435,30 @@ static void southbridge_smi_monitor(void)
/* IOTRAP(3) SMI function call */
if (IOTRAP(3)) {
if (gnvs && gnvs->smif)
- io_trap_handler(gnvs->smif); // call function smif
+ io_trap_handler(gnvs->smif); /* call function smif */
return;
}
- /* IOTRAP(2) currently unused
- * IOTRAP(1) currently unused */
+ /*
+ * IOTRAP(2) currently unused
+ * IOTRAP(1) currently unused
+ */
/* IOTRAP(0) SMIC */
if (IOTRAP(0)) {
- if (!(trap_cycle & (1 << 24))) { // It's a write
+ if (!(trap_cycle & (1 << 24))) { /* It's a write */
printk(BIOS_DEBUG, "SMI1 command\n");
- data = RCBA32(0x1e18);
+ /* Trapped write data */
+ pcr_read32(PID_PSTH, R_PCH_PCR_PSTH_TRPD, &data);
data &= mask;
- // if (smi1)
- // southbridge_smi_command(data);
- // return;
}
- // Fall through to debug
}
printk(BIOS_DEBUG, " trapped io address = 0x%x\n",
trap_cycle & 0xfffc);
- for (i=0; i < 4; i++)
- if(IOTRAP(i)) printk(BIOS_DEBUG, " TRAP = %d\n", i);
+ for (i = 0; i < 4; i++)
+ if (IOTRAP(i))
+ printk(BIOS_DEBUG, " TRAP = %d\n", i);
printk(BIOS_DEBUG, " AHBE = %x\n", (trap_cycle >> 16) & 0xf);
printk(BIOS_DEBUG, " MASK = 0x%08x\n", mask);
printk(BIOS_DEBUG, " read/write: %s\n",
@@ -517,7 +466,7 @@ static void southbridge_smi_monitor(void)
if (!(trap_cycle & (1 << 24))) {
/* Write Cycle */
- data = RCBA32(0x1e18);
+ pcr_read32(PID_PSTH, R_PCH_PCR_PSTH_TRPD, &data);
printk(BIOS_DEBUG, " iotrap written data = 0x%08x\n", data);
}
#undef IOTRAP
@@ -526,52 +475,50 @@ static void southbridge_smi_monitor(void)
typedef void (*smi_handler_t)(void);
static smi_handler_t southbridge_smi[32] = {
- NULL, // [0] reserved
- NULL, // [1] reserved
- NULL, // [2] BIOS_STS
- NULL, // [3] LEGACY_USB_STS
- southbridge_smi_sleep, // [4] SLP_SMI_STS
- southbridge_smi_apmc, // [5] APM_STS
- NULL, // [6] SWSMI_TMR_STS
- NULL, // [7] reserved
- southbridge_smi_pm1, // [8] PM1_STS
- southbridge_smi_gpe0, // [9] GPE0_STS
- southbridge_smi_gpi, // [10] GPI_STS
- southbridge_smi_mc, // [11] MCSMI_STS
- NULL, // [12] DEVMON_STS
- southbridge_smi_tco, // [13] TCO_STS
- southbridge_smi_periodic, // [14] PERIODIC_STS
- NULL, // [15] SERIRQ_SMI_STS
- NULL, // [16] SMBUS_SMI_STS
- NULL, // [17] LEGACY_USB2_STS
- NULL, // [18] INTEL_USB2_STS
- NULL, // [19] reserved
- NULL, // [20] PCI_EXP_SMI_STS
- southbridge_smi_monitor, // [21] MONITOR_STS
- NULL, // [22] reserved
- NULL, // [23] reserved
- NULL, // [24] reserved
- NULL, // [25] EL_SMI_STS
- NULL, // [26] SPI_STS
- NULL, // [27] reserved
- NULL, // [28] reserved
- NULL, // [29] reserved
- NULL, // [30] reserved
- NULL // [31] reserved
+ NULL, /* [0] reserved */
+ NULL, /* [1] reserved */
+ NULL, /* [2] BIOS_STS */
+ NULL, /* [3] LEGACY_USB_STS */
+ southbridge_smi_sleep, /* [4] SLP_SMI_STS */
+ southbridge_smi_apmc, /* [5] APM_STS */
+ NULL, /* [6] SWSMI_TMR_STS */
+ NULL, /* [7] reserved */
+ southbridge_smi_pm1, /* [8] PM1_STS */
+ southbridge_smi_gpe0, /* [9] GPE0_STS */
+ southbridge_smi_gpi, /* [10] GPI_STS */
+ southbridge_smi_mc, /* [11] MCSMI_STS */
+ NULL, /* [12] DEVMON_STS */
+ southbridge_smi_tco, /* [13] TCO_STS */
+ southbridge_smi_periodic, /* [14] PERIODIC_STS */
+ NULL, /* [15] SERIRQ_SMI_STS */
+ NULL, /* [16] SMBUS_SMI_STS */
+ NULL, /* [17] LEGACY_USB2_STS */
+ NULL, /* [18] INTEL_USB2_STS */
+ NULL, /* [19] reserved */
+ NULL, /* [20] PCI_EXP_SMI_STS */
+ southbridge_smi_monitor, /* [21] MONITOR_STS */
+ NULL, /* [22] reserved */
+ NULL, /* [23] reserved */
+ NULL, /* [24] reserved */
+ NULL, /* [25] EL_SMI_STS */
+ NULL, /* [26] SPI_STS */
+ NULL, /* [27] reserved */
+ NULL, /* [28] reserved */
+ NULL, /* [29] reserved */
+ NULL, /* [30] reserved */
+ NULL /* [31] reserved */
};
-/**
- * @brief Interrupt handler for SMI#
- *
- * @param smm_revision revision of the smm state save map
+/*
+ * Interrupt handler for SMI#
*/
-
void southbridge_smi_handler(void)
{
int i;
u32 smi_sts;
- /* We need to clear the SMI status registers, or we won't see what's
+ /*
+ * 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();
@@ -583,8 +530,8 @@ void southbridge_smi_handler(void)
southbridge_smi[i]();
} else {
printk(BIOS_DEBUG,
- "SMI_STS[%d] occurred, but no "
- "handler available.\n", i);
+ "SMI_STS[%d] occured, but no handler available.\n",
+ i);
}
}
}