Alexandru Gagniuc (mr.nuke.me(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/5493
-gerrit
commit b4defe9bb406ed2cfbb7a1c5022c7beba13a0918
Author: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
Date: Sat Apr 12 21:57:18 2014 -0500
cpu/amd/agesa/family15tn: Add initial support for SMM mode
This is the minimal setup needed to be able to execute SMI handlers.
Only support for ASEG handlers is added, which should be sufficient
for Trinity (up to 4 cores).
There are a few hacks which need to be introduced in generic code in
order to make this work properly, but these hacks are self-contained.
They are a not a result of any special needs of this CPU, but rather
from a poorly designed infrastructure. Comments are added to explain
how such code could be refactored in the future.
Change-Id: Iefd4ae17cf0206cae8848cadba3a12cbe3b2f8b6
Signed-off-by: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
---
src/cpu/amd/agesa/family15tn/Makefile.inc | 1 +
src/cpu/amd/agesa/family15tn/model_15_init.c | 16 ++++++++++++++++
src/cpu/x86/smm/smmhandler.S | 8 ++++++++
src/cpu/x86/smm/smmrelocate.S | 3 ++-
src/include/cpu/amd/amdfam15.h | 2 ++
5 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/src/cpu/amd/agesa/family15tn/Makefile.inc b/src/cpu/amd/agesa/family15tn/Makefile.inc
index 372113e..a447044 100644
--- a/src/cpu/amd/agesa/family15tn/Makefile.inc
+++ b/src/cpu/amd/agesa/family15tn/Makefile.inc
@@ -457,6 +457,7 @@ romstage-y += $(agesa_lib_src)
ramstage-y += $(agesa_lib_src)
subdirs-y += ../../mtrr
+subdirs-y += ../../smm
subdirs-y += ../../../x86/tsc
subdirs-y += ../../../x86/lapic
subdirs-y += ../../../x86/cache
diff --git a/src/cpu/amd/agesa/family15tn/model_15_init.c b/src/cpu/amd/agesa/family15tn/model_15_init.c
index f396201..467a301 100644
--- a/src/cpu/amd/agesa/family15tn/model_15_init.c
+++ b/src/cpu/amd/agesa/family15tn/model_15_init.c
@@ -19,6 +19,7 @@
#include <console/console.h>
#include <cpu/x86/msr.h>
+#include <cpu/x86/smm.h>
#include <cpu/amd/mtrr.h>
#include <device/device.h>
#include <string.h>
@@ -43,6 +44,7 @@ static void model_15_init(device_t dev)
u8 i;
msr_t msr;
int msrno;
+ unsigned int cpu_idx;
#if CONFIG_LOGICAL_CPUS
u32 siblings;
#endif
@@ -110,6 +112,20 @@ static void model_15_init(device_t dev)
msr.hi &= ~(1 << (46 - 32));
wrmsr(NB_CFG_MSR, msr);
+ if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)) {
+ cpu_idx = cpu_info()->index;
+ printk(BIOS_INFO, "Initializing SMM for CPU %u\n", cpu_idx);
+
+ /* Set SMM base address for this CPU */
+ msr = rdmsr(MSR_SMM_BASE);
+ msr.lo = SMM_BASE - (cpu_idx * 0x400);
+ wrmsr(MSR_SMM_BASE, msr);
+
+ /* Enable the SMM memory window */
+ msr = rdmsr(MSR_SMM_MASK);
+ msr.lo |= (1 << 0); /* Enable ASEG SMRAM Range */
+ wrmsr(MSR_SMM_MASK, msr);
+ }
/* Write protect SMM space with SMMLOCK. */
msr = rdmsr(HWCR_MSR);
diff --git a/src/cpu/x86/smm/smmhandler.S b/src/cpu/x86/smm/smmhandler.S
index 774088e..484b643 100644
--- a/src/cpu/x86/smm/smmhandler.S
+++ b/src/cpu/x86/smm/smmhandler.S
@@ -105,6 +105,14 @@ smm_handler_start:
movl (%esi), %ecx
shr $24, %ecx
+ /* This is an ugly hack, and we should find a way to read the CPU index
+ * without relying on the LAPIC ID.
+ */
+#if IS_ENABLED(CONFIG_CPU_AMD_AGESA_FAMILY15_TN)
+ /* LAPIC IDs start from 0x10; map that to the proper core index */
+ subl $0x10, %ecx
+#endif
+
/* calculate stack offset by multiplying the APIC ID
* by 1024 (0x400), and save that offset in ebp.
*/
diff --git a/src/cpu/x86/smm/smmrelocate.S b/src/cpu/x86/smm/smmrelocate.S
index 71f74e7..bdc9771 100644
--- a/src/cpu/x86/smm/smmrelocate.S
+++ b/src/cpu/x86/smm/smmrelocate.S
@@ -23,7 +23,8 @@
#define __PRE_RAM__
/* On AMD's platforms we can set SMBASE by writing an MSR */
-#if !CONFIG_NORTHBRIDGE_AMD_AMDK8 && !CONFIG_NORTHBRIDGE_AMD_AMDFAM10
+#if !CONFIG_NORTHBRIDGE_AMD_AMDK8 && !CONFIG_NORTHBRIDGE_AMD_AMDFAM10 \
+ && !CONFIG_CPU_AMD_AGESA_FAMILY15_TN
// FIXME: Is this piece of code southbridge specific, or
// can it be cleaned up so this include is not required?
diff --git a/src/include/cpu/amd/amdfam15.h b/src/include/cpu/amd/amdfam15.h
index 0c2cf7b..67e7cee 100644
--- a/src/include/cpu/amd/amdfam15.h
+++ b/src/include/cpu/amd/amdfam15.h
@@ -23,6 +23,8 @@
#include <cpu/x86/msr.h>
#define MCI_STATUS 0x00000401
+#define MSR_SMM_BASE 0xC0010111
+#define MSR_SMM_MASK 0xC0010113
#define HWCR_MSR 0xC0010015
#define NB_CFG_MSR 0xC001001f
Alexandru Gagniuc (mr.nuke.me(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/5501
-gerrit
commit d372d3e52fff30678b5a798c65ea580287813457
Author: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
Date: Mon Apr 14 10:54:00 2014 -0500
cpu/amd/agesa: Include lapic_timer.c in SMM objects if requested
This is needed on AMD CPUs for the implementation of udelay().
lapic_timer.c cannot always be included in SMM, as some chipsets have
a separate udelay implementation for SMM. Thus, restrict it to AGESA
based CPUs.
Change-Id: Ifa02ca73455b382f830c9b30b80b4f1bb18706b4
Signed-off-by: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
---
src/cpu/amd/agesa/Makefile.inc | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/cpu/amd/agesa/Makefile.inc b/src/cpu/amd/agesa/Makefile.inc
index dbdfba9..e74cd51 100644
--- a/src/cpu/amd/agesa/Makefile.inc
+++ b/src/cpu/amd/agesa/Makefile.inc
@@ -26,3 +26,7 @@ subdirs-$(CONFIG_CPU_AMD_AGESA_FAMILY16_KB) += family16kb
romstage-$(CONFIG_HAVE_ACPI_RESUME) += s3_resume.c
ramstage-$(CONFIG_HAVE_ACPI_RESUME) += s3_resume.c
cpu_incs += $(src)/cpu/amd/agesa/cache_as_ram.inc
+
+ifeq ($(CONFIG_UDELAY_LAPIC), y)
+smm-$(CONFIG_HAVE_SMI_HANDLER) += ../../x86/lapic/apic_timer.c
+endif
Edward O'Callaghan (eocallaghan(a)alterapraxis.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/5500
-gerrit
commit e743ba1c07e4cf0a7b3cc07554fc56fc5c5f289d
Author: Edward O'Callaghan <eocallaghan(a)alterapraxis.com>
Date: Sun Apr 13 22:31:08 2014 +1000
mainboard/jetway/nf81-t56n-lf: Init SIO HWM multi-func regs
The Fintek F71869AD found on this board needs special "Multifunction
registers" to be tweaked before it will control the CPU fan properly.
We provide two main functions init_hwm_multifunc() and init_hwm_registers(),
init_hwm_multifunc() configures the Super I/O into AMD TSI mode to
correctly read the right GPIO pins for CPU thermosters and the correct
protocol to use. The init_hwm_registers() configures the Super I/O's fan
settings to have reasonable upper and lower bounds to keep the CPU
around 38*C.
Change-Id: I0b93c878b532bfa39b9ceb10ce6bada079408b6b
Signed-off-by: Edward O'Callaghan <eocallaghan(a)alterapraxis.com>
---
src/mainboard/jetway/nf81-t56n-lf/Makefile.inc | 4 +-
src/mainboard/jetway/nf81-t56n-lf/romstage.c | 7 +
src/mainboard/jetway/nf81-t56n-lf/superio_hwm.c | 183 ++++++++++++++++++++++++
src/mainboard/jetway/nf81-t56n-lf/superio_hwm.h | 29 ++++
4 files changed, 221 insertions(+), 2 deletions(-)
diff --git a/src/mainboard/jetway/nf81-t56n-lf/Makefile.inc b/src/mainboard/jetway/nf81-t56n-lf/Makefile.inc
index e1f18a9..2e9bd0c 100644
--- a/src/mainboard/jetway/nf81-t56n-lf/Makefile.inc
+++ b/src/mainboard/jetway/nf81-t56n-lf/Makefile.inc
@@ -29,9 +29,9 @@ romstage-y += agesawrapper.c
romstage-y += BiosCallOuts.c
romstage-y += PlatformGnbPcie.c
+romstage-y += superio_hwm.c
+
ramstage-y += buildOpts.c
ramstage-y += agesawrapper.c
ramstage-y += BiosCallOuts.c
ramstage-y += PlatformGnbPcie.c
-
-
diff --git a/src/mainboard/jetway/nf81-t56n-lf/romstage.c b/src/mainboard/jetway/nf81-t56n-lf/romstage.c
index 846d5c7..6fff368 100644
--- a/src/mainboard/jetway/nf81-t56n-lf/romstage.c
+++ b/src/mainboard/jetway/nf81-t56n-lf/romstage.c
@@ -19,6 +19,7 @@
*/
#include "agesawrapper.h"
+#include "superio_hwm.h"
#include <arch/cpu.h>
#include <arch/io.h>
@@ -52,6 +53,9 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx);
/* Ensure Super I/O config address (i.e., 0x2e or 0x4e) matches that of devicetree.cb */
#define SERIAL_DEV PNP_DEV(0x2e, F71869AD_SP1)
+#define HWM_DEV PNP_DEV(0x2e, F71869AD_HWM)
+#define HWM_BASE_ADDR 0x225
+
void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
{
u32 val;
@@ -79,6 +83,9 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
console_init();
}
+ /* Fintek F71869AD Hardware Monitor needs special configuration */
+ superio_enable_hwm(HWM_DEV, HWM_BASE_ADDR);
+
/* Halt if there was a built in self test failure */
post_code(0x34);
report_bist_failure(bist);
diff --git a/src/mainboard/jetway/nf81-t56n-lf/superio_hwm.c b/src/mainboard/jetway/nf81-t56n-lf/superio_hwm.c
new file mode 100644
index 0000000..19393e2
--- /dev/null
+++ b/src/mainboard/jetway/nf81-t56n-lf/superio_hwm.c
@@ -0,0 +1,183 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Edward O'Callaghan <eocallaghan(a)alterapraxis.com>
+ *
+ * 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.
+ *
+ * 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
+ */
+
+/*
+ * Just enough of a driver to make coreboot control system fans.
+ * No configuration is necessary for the OS to pick up the device.
+ */
+
+#include <console/console.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <arch/io.h>
+#include <device/device.h>
+#include <device/pnp.h>
+
+#include "superio_hwm.h"
+
+#define DEBUG_SUPERIO_HWM 0
+
+/* Enable configuration: pass entry key '0x87' into index port dev. */
+static void pnp_enter_conf_state(device_t dev)
+{
+ u16 port = dev >> 8;
+ outb(0x87, port);
+ outb(0x87, port);
+}
+
+/* Disable configuration: pass exit key '0xAA' into index port dev. */
+static void pnp_exit_conf_state(device_t dev)
+{
+ u16 port = dev >> 8;
+ outb(0xaa, port);
+}
+
+static void toggle_clk_tune_en(device_t dev, int state)
+{
+ u8 reg8;
+
+ reg8 = pnp_read_config(dev, 0x26);
+
+ switch(state) {
+ case 1:
+ reg8 ^= 0x08; /* CLK_TUNE_EN=1 */
+ break;
+ case 0:
+ reg8 &= 0xF7; /* CLK_TUNE_EN=0 */
+ break;
+ }
+
+ pnp_write_config(dev, 0x26, reg8);
+}
+
+static void init_hwm_multifunc(device_t dev)
+{
+ pnp_write_config(dev, 0x25, 0x09); /* powerdown FDC & PP */
+ pnp_write_config(dev, 0x27, 0xa1); /* debug+timing_gpio */
+ pnp_write_config(dev, 0x28, 0x01); /* multi-func select reg1 */
+
+ /* CLK_TUNE_EN switch index 0x29 ~ 0x2C to WDT fine tune registers */
+ toggle_clk_tune_en(dev, 1); /* CLK_TUNE_EN=1 */
+ pnp_write_config(dev, 0x29, 0x6f); /* WDT clock divisor high byte (CLK_TUNE_EN=1) */
+ pnp_write_config(dev, 0x2a, 0x24); /* WDT clock divisor low byte (CLK_TUNE_EN=1) */
+ pnp_write_config(dev, 0x2b, 0x00); /* WDT clock fine tune count (CLK_TUNE_EN=1) */
+ pnp_write_config(dev, 0x2b, 0x60); /* WDT clock fine tune count (CLK_TUNE_EN=1) */
+ /* CLK_TUNE_EN switch index 0x29 ~ 0x2C from WDT fine tune registers */
+ toggle_clk_tune_en(dev, 0); /* CLK_TUNE_EN=0 */
+
+ pnp_write_config(dev, 0x29, 0x6f); /* multi-func select reg2 (CLK_TUNE_EN=0) */
+ pnp_write_config(dev, 0x2a, 0x24); /* multi-func select reg3 (CLK_TUNE_EN=0) */
+ pnp_write_config(dev, 0x2b, 0x00); /* multi-func select reg4 (CLK_TUNE_EN=0) */
+ /* multi-func sel reg5 - Configure pins 57/58 as SCL/SDA (AMD TSI bus). */
+ pnp_write_config(dev, 0x2c, 0x60); /* multi-func select reg5 (CLK_TUNE_EN=0) */
+ pnp_write_config(dev, 0x2f, 0x2f); /* wakeup control register */
+}
+
+
+/* TODO:
+ * replace with pnp_read/write_config() and make devicetree.cb configurable.
+ */
+static void write_index(u16 port, u8 reg, u8 value)
+{
+ outb(reg, port);
+ outb(value, port + 1);
+}
+
+static u8 read_index(u16 port, u8 reg)
+{
+ outb(reg, port);
+ return inb(port + 1);
+}
+/* .. */
+
+static void init_hwm_registers(u16 base, u8 * hwm_reg_values, int size)
+{
+ u8 reg, value;
+ int i;
+
+ for (i = 0; i < size; i += 3) {
+ reg = hwm_reg_values[i];
+ value = read_index(base, reg);
+ value &= 0xff & hwm_reg_values[i + 1];
+ value |= 0xff & hwm_reg_values[i + 2];
+ printk(BIOS_SPEW, "Super I/O HWM: base = 0x%04x, reg = 0x%02x, "
+ "value = 0x%02x\n", base, reg, value);
+ write_index(base, reg, value);
+
+#if DEBUG_SUPERIO_HWM == 1
+ value = read_index(base, reg);
+ printk(BIOS_DEBUG, "Super I/O HWM (read back): base = 0x%04x, reg = 0x%02x, "
+ "value = 0x%02x\n", base, reg, value);
+#endif /* DEBUG_SUPERIO_HWM */
+ }
+}
+
+/* Initialize F71869AD hardware monitor registers, usually at 0x225. */
+void superio_enable_hwm(device_t dev, u16 iobase)
+{
+ printk(BIOS_INFO, "Super I/O HWM: Initializing Hardware Monitor..\n");
+ printk(BIOS_DEBUG, "Super I/O HWM: Base Address at 0x%x\n", iobase);
+
+ pnp_enter_conf_state(dev);
+
+ printk(BIOS_DEBUG, "Super I/O HWM: Configure SMBus to TSI mode\n");
+ init_hwm_multifunc(dev);
+
+ /* note: multifunc registers need to be tweaked before here */
+ pnp_set_logical_device(dev);
+ pnp_set_iobase(dev, PNP_IDX_IO0, iobase);
+
+ /* Fintek F71869AD AMD mode HWM (ordered) programming sequence. */
+ u8 hwm_reg_values[] = {
+ /* reg mask data */
+ 0x08, 0x00, 0x98, /* SMBus Address p.53 */
+ 0x0a, 0x00, 0x02, /* Configure pins 57/58 as PECI_REQ#/PECI (AMD_TSI) p.54 */
+ /* Tfan1 = Tnow + (Ta - Tb)*Ct where, */
+ 0xaf, 0x00, 0x8c, /* FAN1_TEMP_SEL_DIG, FAN1_TEMP_SEL (Tnow) set to come from CR7Ah p.73 */
+ 0x9f, 0x00, 0x8a, /* set FAN_PROG_SEL = 1 */
+ 0x94, 0x00, 0x00, /* FAN1_BASE_TEMP (Tb) set when FAN_PROG_SEL=1, p.64-65 */
+ 0x96, 0x00, 0x07, /* set TFAN1_ADJ_SEL (Ta) p.67 to use CR7Ah p.61 */
+ 0x95, 0x00, 0x33, /* TFAN1_ADJ_{UP,DOWN}_RATE (Ct=1/4 up & down) in 0x95 when FAN_PROG_SEL = 1, p.88 */
+ 0x9f, 0x00, 0x0a, /* set FAN_PROG_SEL = 0 */
+ /* .. */
+ 0x02, 0x00, 0x30, /* OVT_MODE p.52 */
+ 0x60, 0x00, 0x22, /* Temperature PME# Enable Register p.79 */
+ 0x63, 0x00, 0x20, /* Temperature BEEP Enable Register p.58 */
+ 0x64, 0x00, 0x22, /* T1 OVT and High Limit Temperature Select Register p.82 */
+ 0x66, 0x00, 0x22, /* OVT and Alert Output Enable Register 1 p.59 */
+ 0x82, 0x00, 0x76, /* Temperature sensors 1 OVT limit p.61 */
+ 0x91, 0x00, 0x07, /* FAN Interrupt Status Register p.63 */
+ 0x90, 0x00, 0x02, /* FAN PME# Enable Register p.85 */
+ 0xa3, 0x00, 0x0e, /* FAN1 RPM mode p.70 */
+ 0xa9, 0x00, 0x14, /* VT1 Boundary 2 Temperature p.71 */
+ 0xaa, 0x00, 0xff, /* FAN1 Segment 1 Speed Count */
+ 0xab, 0x00, 0x0e, /* FAN1 Segment 2 Speed Count */
+ 0xae, 0x00, 0x07, /* FAN1 Segment 3 Speed Count */
+ /* .. */
+ 0xee, 0x00, 0x01, /* SMB_Status p.83 */
+ 0xed, 0x00, 0x01, /* SMB/TSI Command Byte p.83 */
+ 0xef, 0x00, 0x82, /* SMB_Protocal p.83 */
+ };
+
+ printk(BIOS_DEBUG, "Super I/O HWM: Configuring registers...\n");
+ init_hwm_registers(iobase, hwm_reg_values, ARRAY_SIZE(hwm_reg_values));
+
+ pnp_exit_conf_state(dev);
+}
diff --git a/src/mainboard/jetway/nf81-t56n-lf/superio_hwm.h b/src/mainboard/jetway/nf81-t56n-lf/superio_hwm.h
new file mode 100644
index 0000000..802c828
--- /dev/null
+++ b/src/mainboard/jetway/nf81-t56n-lf/superio_hwm.h
@@ -0,0 +1,29 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Edward O'Callaghan <eocallaghan(a)alterapraxis.com>
+ *
+ * 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.
+ *
+ * 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
+ */
+
+#ifndef SUPERIO_HWM_H
+#define SUPERIO_HWM_H
+
+#include <arch/io.h>
+
+/* Initialize F71869AD hardware monitor registers, usually at 0x225. */
+void superio_enable_hwm(device_t dev, u16 iobase);
+
+#endif /* SUPERIO_HWM_H */
Alexandru Gagniuc (mr.nuke.me(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/5501
-gerrit
commit 6c75446cd502b2c1ef46266ad70eb91988005391
Author: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
Date: Mon Apr 14 10:54:00 2014 -0500
cpu/x86/lapic: Include lapic_timer.c in SMM objects if requested
This is needed on AMD CPUs for the implementation of udelay().
Change-Id: Ifa02ca73455b382f830c9b30b80b4f1bb18706b4
Signed-off-by: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
---
src/cpu/x86/lapic/Makefile.inc | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/cpu/x86/lapic/Makefile.inc b/src/cpu/x86/lapic/Makefile.inc
index 3061024..7479dc5 100644
--- a/src/cpu/x86/lapic/Makefile.inc
+++ b/src/cpu/x86/lapic/Makefile.inc
@@ -5,3 +5,7 @@ romstage-$(CONFIG_UDELAY_LAPIC) += apic_timer.c
ramstage-$(CONFIG_UDELAY_LAPIC) += apic_timer.c
romstage-y += boot_cpu.c
ramstage-y += boot_cpu.c
+
+ifeq ($(CONFIG_UDELAY_LAPIC), y)
+smm-$(CONFIG_HAVE_SMI_HANDLER) += apic_timer.c
+endif
Alexandru Gagniuc (mr.nuke.me(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/5493
-gerrit
commit 38970b255e1760b04ddf4d1f0cc427094d8336e1
Author: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
Date: Sat Apr 12 21:57:18 2014 -0500
cpu/amd/agesa/family15tn: Add initial support for SMM mode
This is the minimal setup needed to be able to execute SMI handlers.
Only support for ASEG handlers is added, which should be sufficient
for Trinity (up to 4 cores).
There are a few hacks which need to be introduced in generic code in
order to make this work properly, but these hacks are self-contained.
They are a not a result of any special needs of this CPU, but rather
from a poorly designed infrastructure. Comments are added to explain
how such code could be refactored in the future.
Change-Id: Iefd4ae17cf0206cae8848cadba3a12cbe3b2f8b6
Signed-off-by: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
---
src/cpu/amd/agesa/family15tn/Makefile.inc | 1 +
src/cpu/amd/agesa/family15tn/model_15_init.c | 16 ++++++++++++++++
src/cpu/x86/smm/smmhandler.S | 8 ++++++++
src/cpu/x86/smm/smmrelocate.S | 3 ++-
src/include/cpu/amd/amdfam15.h | 2 ++
5 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/src/cpu/amd/agesa/family15tn/Makefile.inc b/src/cpu/amd/agesa/family15tn/Makefile.inc
index 372113e..a447044 100644
--- a/src/cpu/amd/agesa/family15tn/Makefile.inc
+++ b/src/cpu/amd/agesa/family15tn/Makefile.inc
@@ -457,6 +457,7 @@ romstage-y += $(agesa_lib_src)
ramstage-y += $(agesa_lib_src)
subdirs-y += ../../mtrr
+subdirs-y += ../../smm
subdirs-y += ../../../x86/tsc
subdirs-y += ../../../x86/lapic
subdirs-y += ../../../x86/cache
diff --git a/src/cpu/amd/agesa/family15tn/model_15_init.c b/src/cpu/amd/agesa/family15tn/model_15_init.c
index f396201..467a301 100644
--- a/src/cpu/amd/agesa/family15tn/model_15_init.c
+++ b/src/cpu/amd/agesa/family15tn/model_15_init.c
@@ -19,6 +19,7 @@
#include <console/console.h>
#include <cpu/x86/msr.h>
+#include <cpu/x86/smm.h>
#include <cpu/amd/mtrr.h>
#include <device/device.h>
#include <string.h>
@@ -43,6 +44,7 @@ static void model_15_init(device_t dev)
u8 i;
msr_t msr;
int msrno;
+ unsigned int cpu_idx;
#if CONFIG_LOGICAL_CPUS
u32 siblings;
#endif
@@ -110,6 +112,20 @@ static void model_15_init(device_t dev)
msr.hi &= ~(1 << (46 - 32));
wrmsr(NB_CFG_MSR, msr);
+ if (IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)) {
+ cpu_idx = cpu_info()->index;
+ printk(BIOS_INFO, "Initializing SMM for CPU %u\n", cpu_idx);
+
+ /* Set SMM base address for this CPU */
+ msr = rdmsr(MSR_SMM_BASE);
+ msr.lo = SMM_BASE - (cpu_idx * 0x400);
+ wrmsr(MSR_SMM_BASE, msr);
+
+ /* Enable the SMM memory window */
+ msr = rdmsr(MSR_SMM_MASK);
+ msr.lo |= (1 << 0); /* Enable ASEG SMRAM Range */
+ wrmsr(MSR_SMM_MASK, msr);
+ }
/* Write protect SMM space with SMMLOCK. */
msr = rdmsr(HWCR_MSR);
diff --git a/src/cpu/x86/smm/smmhandler.S b/src/cpu/x86/smm/smmhandler.S
index 774088e..484b643 100644
--- a/src/cpu/x86/smm/smmhandler.S
+++ b/src/cpu/x86/smm/smmhandler.S
@@ -105,6 +105,14 @@ smm_handler_start:
movl (%esi), %ecx
shr $24, %ecx
+ /* This is an ugly hack, and we should find a way to read the CPU index
+ * without relying on the LAPIC ID.
+ */
+#if IS_ENABLED(CONFIG_CPU_AMD_AGESA_FAMILY15_TN)
+ /* LAPIC IDs start from 0x10; map that to the proper core index */
+ subl $0x10, %ecx
+#endif
+
/* calculate stack offset by multiplying the APIC ID
* by 1024 (0x400), and save that offset in ebp.
*/
diff --git a/src/cpu/x86/smm/smmrelocate.S b/src/cpu/x86/smm/smmrelocate.S
index 71f74e7..bdc9771 100644
--- a/src/cpu/x86/smm/smmrelocate.S
+++ b/src/cpu/x86/smm/smmrelocate.S
@@ -23,7 +23,8 @@
#define __PRE_RAM__
/* On AMD's platforms we can set SMBASE by writing an MSR */
-#if !CONFIG_NORTHBRIDGE_AMD_AMDK8 && !CONFIG_NORTHBRIDGE_AMD_AMDFAM10
+#if !CONFIG_NORTHBRIDGE_AMD_AMDK8 && !CONFIG_NORTHBRIDGE_AMD_AMDFAM10 \
+ && !CONFIG_CPU_AMD_AGESA_FAMILY15_TN
// FIXME: Is this piece of code southbridge specific, or
// can it be cleaned up so this include is not required?
diff --git a/src/include/cpu/amd/amdfam15.h b/src/include/cpu/amd/amdfam15.h
index 0c2cf7b..67e7cee 100644
--- a/src/include/cpu/amd/amdfam15.h
+++ b/src/include/cpu/amd/amdfam15.h
@@ -23,6 +23,8 @@
#include <cpu/x86/msr.h>
#define MCI_STATUS 0x00000401
+#define MSR_SMM_BASE 0xC0010111
+#define MSR_SMM_MASK 0xC0010113
#define HWCR_MSR 0xC0010015
#define NB_CFG_MSR 0xC001001f
the following patch was just integrated into master:
commit 5405d3fe91ba9f218521c5f0a84561909d37ce5a
Author: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
Date: Wed Apr 9 16:14:25 2014 -0500
hp/pavilion_m6_1035dx: Fix GPIO map and add WLAN pin
Change-Id: I07725b71508c8b08451022307ae934c1b227f7f9
Signed-off-by: Alexandru Gagniuc <mr.nuke.me(a)gmail.com>
Reviewed-on: http://review.coreboot.org/5491
Tested-by: build bot (Jenkins)
Reviewed-by: Kyösti Mälkki <kyosti.malkki(a)gmail.com>
See http://review.coreboot.org/5491 for details.
-gerrit
Edward O'Callaghan (eocallaghan(a)alterapraxis.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/5500
-gerrit
commit e659869787b52b0806c7815456f0f6c0355acdaa
Author: Edward O'Callaghan <eocallaghan(a)alterapraxis.com>
Date: Sun Apr 13 22:31:08 2014 +1000
mainboard/jetway/nf81-t56n-lf: Init SIO HWM multi-func regs
The Fintek F71869AD found on this board needs special "Multifunction
registers" to be tweaked before it will control the CPU fan properly.
We provide two main functions init_hwm_multifunc() and init_hwm_registers(),
init_hwm_multifunc() configures the Super I/O into AMD TSI mode to
correctly read the right GPIO pins for CPU thermosters and the correct
protocol to use. The init_hwm_registers() configures the Super I/O's fan
settings to have reasonable upper and lower bounds to keep the CPU
around 38*C.
Change-Id: I0b93c878b532bfa39b9ceb10ce6bada079408b6b
Signed-off-by: Edward O'Callaghan <eocallaghan(a)alterapraxis.com>
---
src/mainboard/jetway/nf81-t56n-lf/Makefile.inc | 4 +-
src/mainboard/jetway/nf81-t56n-lf/romstage.c | 7 +
src/mainboard/jetway/nf81-t56n-lf/superio_hwm.c | 181 ++++++++++++++++++++++++
src/mainboard/jetway/nf81-t56n-lf/superio_hwm.h | 29 ++++
4 files changed, 219 insertions(+), 2 deletions(-)
diff --git a/src/mainboard/jetway/nf81-t56n-lf/Makefile.inc b/src/mainboard/jetway/nf81-t56n-lf/Makefile.inc
index e1f18a9..2e9bd0c 100644
--- a/src/mainboard/jetway/nf81-t56n-lf/Makefile.inc
+++ b/src/mainboard/jetway/nf81-t56n-lf/Makefile.inc
@@ -29,9 +29,9 @@ romstage-y += agesawrapper.c
romstage-y += BiosCallOuts.c
romstage-y += PlatformGnbPcie.c
+romstage-y += superio_hwm.c
+
ramstage-y += buildOpts.c
ramstage-y += agesawrapper.c
ramstage-y += BiosCallOuts.c
ramstage-y += PlatformGnbPcie.c
-
-
diff --git a/src/mainboard/jetway/nf81-t56n-lf/romstage.c b/src/mainboard/jetway/nf81-t56n-lf/romstage.c
index 846d5c7..6fff368 100644
--- a/src/mainboard/jetway/nf81-t56n-lf/romstage.c
+++ b/src/mainboard/jetway/nf81-t56n-lf/romstage.c
@@ -19,6 +19,7 @@
*/
#include "agesawrapper.h"
+#include "superio_hwm.h"
#include <arch/cpu.h>
#include <arch/io.h>
@@ -52,6 +53,9 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx);
/* Ensure Super I/O config address (i.e., 0x2e or 0x4e) matches that of devicetree.cb */
#define SERIAL_DEV PNP_DEV(0x2e, F71869AD_SP1)
+#define HWM_DEV PNP_DEV(0x2e, F71869AD_HWM)
+#define HWM_BASE_ADDR 0x225
+
void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
{
u32 val;
@@ -79,6 +83,9 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
console_init();
}
+ /* Fintek F71869AD Hardware Monitor needs special configuration */
+ superio_enable_hwm(HWM_DEV, HWM_BASE_ADDR);
+
/* Halt if there was a built in self test failure */
post_code(0x34);
report_bist_failure(bist);
diff --git a/src/mainboard/jetway/nf81-t56n-lf/superio_hwm.c b/src/mainboard/jetway/nf81-t56n-lf/superio_hwm.c
new file mode 100644
index 0000000..6805d93
--- /dev/null
+++ b/src/mainboard/jetway/nf81-t56n-lf/superio_hwm.c
@@ -0,0 +1,181 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Edward O'Callaghan <eocallaghan(a)alterapraxis.com>
+ *
+ * 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.
+ *
+ * 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
+ */
+
+/*
+ * Just enough of a driver to make coreboot control system fans.
+ * No configuration is necessary for the OS to pick up the device.
+ */
+
+#include <console/console.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <arch/io.h>
+#include <device/device.h>
+#include <device/pnp.h>
+
+#include "superio_hwm.h"
+
+#define DEBUG_SUPERIO_HWM 0
+
+/* Enable configuration: pass entry key '0x87' into index port dev. */
+static void pnp_enter_conf_state(device_t dev)
+{
+ u16 port = dev >> 8;
+ outb(0x87, port);
+ outb(0x87, port);
+}
+
+/* Disable configuration: pass exit key '0xAA' into index port dev. */
+static void pnp_exit_conf_state(device_t dev)
+{
+ u16 port = dev >> 8;
+ outb(0xaa, port);
+}
+
+static void toggle_clk_tune_en(device_t dev, int state)
+{
+ u8 reg8;
+
+ reg8 = pnp_read_config(dev, 0x26);
+
+ switch(state) {
+ case 1:
+ reg8 ^= 0x08; /* CLK_TUNE_EN=1 */
+ break;
+ case 0:
+ reg8 &= 0xF7; /* CLK_TUNE_EN=0 */
+ break;
+ }
+
+ pnp_write_config(dev, 0x26, reg8);
+}
+
+static void init_hwm_multifunc(device_t dev)
+{
+ pnp_write_config(dev, 0x25, 0x09); /* powerdown FDC & PP */
+ pnp_write_config(dev, 0x27, 0xa1); /* debug+timing_gpio */
+ pnp_write_config(dev, 0x28, 0x01); /* multi-func select reg1 */
+
+ /* CLK_TUNE_EN switch index 0x29 ~ 0x2C to WDT fine tune registers */
+ toggle_clk_tune_en(dev, 1); /* CLK_TUNE_EN=1 */
+ pnp_write_config(dev, 0x29, 0x6f); /* WDT clock divisor high byte (CLK_TUNE_EN=1) */
+ pnp_write_config(dev, 0x2a, 0x24); /* WDT clock divisor low byte (CLK_TUNE_EN=1) */
+ pnp_write_config(dev, 0x2b, 0x00); /* WDT clock fine tune count (CLK_TUNE_EN=1) */
+ pnp_write_config(dev, 0x2b, 0x60); /* WDT clock fine tune count (CLK_TUNE_EN=1) */
+ /* CLK_TUNE_EN switch index 0x29 ~ 0x2C from WDT fine tune registers */
+ toggle_clk_tune_en(dev, 0); /* CLK_TUNE_EN=0 */
+
+ pnp_write_config(dev, 0x29, 0x6f); /* multi-func select reg2 (CLK_TUNE_EN=0) */
+ pnp_write_config(dev, 0x2a, 0x24); /* multi-func select reg3 (CLK_TUNE_EN=0) */
+ pnp_write_config(dev, 0x2b, 0x00); /* multi-func select reg4 (CLK_TUNE_EN=0) */
+ /* multi-func sel reg5 - Configure pins 57/58 as SCL/SDA (AMD TSI bus). */
+ pnp_write_config(dev, 0x2c, 0x60); /* multi-func select reg5 (CLK_TUNE_EN=0) */
+ pnp_write_config(dev, 0x2f, 0x2f); /* wakeup control register */
+}
+
+
+/* TODO:
+ * replace with pnp_read/write_config() and make devicetree.cb configurable.
+ */
+static void write_index(u16 port, u8 reg, u8 value)
+{
+ outb(reg, port);
+ outb(value, port + 1);
+}
+
+static u8 read_index(u16 port, u8 reg)
+{
+ outb(reg, port);
+ return inb(port + 1);
+}
+/* .. */
+
+static void init_hwm_registers(u16 base, u8 * hwm_reg_values, int size)
+{
+ u8 reg, value;
+ int i;
+
+ for (i = 0; i < size; i += 3) {
+ reg = hwm_reg_values[i];
+ value = read_index(base, reg);
+ value &= 0xff & hwm_reg_values[i + 1];
+ value |= 0xff & hwm_reg_values[i + 2];
+ printk(BIOS_SPEW, "Super I/O HWM: base = 0x%04x, reg = 0x%02x, "
+ "value = 0x%02x\n", base, reg, value);
+ write_index(base, reg, value);
+
+#if DEBUG_SUPERIO_HWM == 1
+ value = read_index(base, reg);
+ printk(BIOS_DEBUG, "Super I/O HWM (read back): base = 0x%04x, reg = 0x%02x, "
+ "value = 0x%02x\n", base, reg, value);
+#endif /* DEBUG_SUPERIO_HWM */
+ }
+}
+
+/* Initialize F71869AD hardware monitor registers, usually at 0x225. */
+void superio_enable_hwm(device_t dev, u16 iobase)
+{
+ printk(BIOS_INFO, "Super I/O HWM: Initializing Hardware Monitor..\n");
+ printk(BIOS_DEBUG, "Super I/O HWM: Base Address at 0x%x\n", iobase);
+
+ pnp_enter_conf_state(dev);
+ pnp_set_logical_device(dev);
+ pnp_set_iobase(dev, PNP_IDX_IO0, iobase);
+
+ printk(BIOS_DEBUG, "Super I/O HWM: Configure SMBus to TSI mode\n");
+ init_hwm_multifunc(dev);
+
+ /* Fintek F71869AD AMD mode HWM (ordered) programming sequence. */
+ u8 hwm_reg_values[] = {
+ /* reg mask data */
+ 0x08, 0x00, 0x98, /* SMBus Address p.53 */
+ 0x0a, 0x00, 0x02, /* Configure pins 57/58 as PECI_REQ#/PECI (AMD_TSI) p.54 */
+ /* Tfan1 = Tnow + (Ta - Tb)*Ct where, */
+ 0xaf, 0x00, 0x8c, /* FAN1_TEMP_SEL_DIG, FAN1_TEMP_SEL (Tnow) set to come from CR7Ah p.73 */
+ 0x9f, 0x00, 0x8a, /* set FAN_PROG_SEL = 1 */
+ 0x94, 0x00, 0x00, /* FAN1_BASE_TEMP (Tb) set when FAN_PROG_SEL=1, p.64-65 */
+ 0x96, 0x00, 0x07, /* set TFAN1_ADJ_SEL (Ta) p.67 to use CR7Ah p.61 */
+ 0x95, 0x00, 0x33, /* TFAN1_ADJ_{UP,DOWN}_RATE (Ct=1/4 up & down) in 0x95 when FAN_PROG_SEL = 1, p.88 */
+ 0x9f, 0x00, 0x0a, /* set FAN_PROG_SEL = 0 */
+ /* .. */
+ 0x02, 0x00, 0x30, /* OVT_MODE p.52 */
+ 0x60, 0x00, 0x22, /* Temperature PME# Enable Register p.79 */
+ 0x63, 0x00, 0x20, /* Temperature BEEP Enable Register p.58 */
+ 0x64, 0x00, 0x22, /* T1 OVT and High Limit Temperature Select Register p.82 */
+ 0x66, 0x00, 0x22, /* OVT and Alert Output Enable Register 1 p.59 */
+ 0x82, 0x00, 0x76, /* Temperature sensors 1 OVT limit p.61 */
+ 0x91, 0x00, 0x07, /* FAN Interrupt Status Register p.63 */
+ 0x90, 0x00, 0x02, /* FAN PME# Enable Register p.85 */
+ 0xa3, 0x00, 0x0e, /* FAN1 RPM mode p.70 */
+ 0xa9, 0x00, 0x14, /* VT1 Boundary 2 Temperature p.71 */
+ 0xaa, 0x00, 0xff, /* FAN1 Segment 1 Speed Count */
+ 0xab, 0x00, 0x0e, /* FAN1 Segment 2 Speed Count */
+ 0xae, 0x00, 0x07, /* FAN1 Segment 3 Speed Count */
+ /* .. */
+ 0xee, 0x00, 0x01, /* SMB_Status p.83 */
+ 0xed, 0x00, 0x01, /* SMB/TSI Command Byte p.83 */
+ 0xef, 0x00, 0x82, /* SMB_Protocal p.83 */
+ };
+
+ printk(BIOS_DEBUG, "Super I/O HWM: Configuring registers...\n");
+ init_hwm_registers(iobase, hwm_reg_values, ARRAY_SIZE(hwm_reg_values));
+
+ pnp_exit_conf_state(dev);
+}
diff --git a/src/mainboard/jetway/nf81-t56n-lf/superio_hwm.h b/src/mainboard/jetway/nf81-t56n-lf/superio_hwm.h
new file mode 100644
index 0000000..1d862f0
--- /dev/null
+++ b/src/mainboard/jetway/nf81-t56n-lf/superio_hwm.h
@@ -0,0 +1,29 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Edward O'Callaghan <eocallaghan(a)alterapraxis.com>
+ *
+ * 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.
+ *
+ * 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
+ */
+
+#ifndef SUPERIO_HWM_H
+#define SUPERIO_HWM_H
+
+#include <arch/io.h>
+
+/* Initialize F71869AD hardware monitor registers, usually at 0x225. */
+void superio_enable_hwm(device_t, u16);
+
+#endif /* SUPERIO_HWM_H */