summaryrefslogtreecommitdiffstats
path: root/src/mainboard/dell/snb_ivb_workstations
diff options
context:
space:
mode:
authorMichał Żygowski <michal.zygowski@3mdeb.com>2022-02-20 23:27:18 +0100
committerMichał Żygowski <michal.zygowski@3mdeb.com>2022-03-25 09:26:40 +0000
commit7e8b597093b1e312532be2e64a5744c53a89e0c0 (patch)
tree8067f4494db18d7b38aa920406c09fb57b56a24a /src/mainboard/dell/snb_ivb_workstations
parentb017a43a6d31d2babd6170b6adf7712506f776c2 (diff)
downloadcoreboot-7e8b597093b1e312532be2e64a5744c53a89e0c0.tar.gz
coreboot-7e8b597093b1e312532be2e64a5744c53a89e0c0.tar.bz2
coreboot-7e8b597093b1e312532be2e64a5744c53a89e0c0.zip
mb/dell: Convert OptiPlex 9010 into directory with variants
New boards like Dell Precision T1650 will be added as variants, in subsequent commit. They share most of the code, except some EC initialization tables, PCIe port configuration and subsystem ID. Signed-off-by: Michał Żygowski <michal.zygowski@3mdeb.com> Change-Id: I4075f0ae3b24892fcc2be07061a01f8070659239 Reviewed-on: https://review.coreboot.org/c/coreboot/+/62211 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Krystian Hebel <krystian.hebel@3mdeb.com>
Diffstat (limited to 'src/mainboard/dell/snb_ivb_workstations')
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/Kconfig66
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/Kconfig.name4
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/Makefile.inc28
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/acpi/ec.asl0
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/acpi/platform.asl54
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/acpi/superio.asl13
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/board_info.txt6
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/cmos.default7
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/cmos.layout75
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/dsdt.asl33
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/early_init.c47
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/gma-mainboard.ads19
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/gpio.c208
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/hda_verb.c0
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/mainboard.c191
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/romstage.c66
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/sch5545_ec.c489
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/sch5545_ec_early.c116
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/smihandler.c34
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/variants/baseboard/devicetree.cb91
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/variants/baseboard/include/baseboard/sch5545_ec.h45
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/variants/optiplex_9010_sff/data.vbtbin0 -> 4281 bytes
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/variants/optiplex_9010_sff/hda_verb.c36
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/variants/optiplex_9010_sff/include/variant/sch5545_ec_tables.h237
-rw-r--r--src/mainboard/dell/snb_ivb_workstations/variants/optiplex_9010_sff/overridetree.cb14
25 files changed, 1879 insertions, 0 deletions
diff --git a/src/mainboard/dell/snb_ivb_workstations/Kconfig b/src/mainboard/dell/snb_ivb_workstations/Kconfig
new file mode 100644
index 000000000000..5d64fd7c10a6
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/Kconfig
@@ -0,0 +1,66 @@
+config BOARD_DELL_SNB_IVB_WORKSTATIONS
+ def_bool n
+ select BOARD_ROMSIZE_KB_12288
+ select HAVE_ACPI_RESUME
+ select HAVE_ACPI_TABLES
+ select INTEL_INT15
+ select NORTHBRIDGE_INTEL_SANDYBRIDGE
+ select SERIRQ_CONTINUOUS_MODE
+ select USE_NATIVE_RAMINIT
+ select MAINBOARD_HAS_LPC_TPM
+ select MAINBOARD_HAS_TPM1
+ select MAINBOARD_USES_IFD_GBE_REGION
+ select SUPERIO_SMSC_SCH5545
+ select MAINBOARD_HAS_LIBGFXINIT
+ select INTEL_GMA_HAVE_VBT
+ select HAVE_OPTION_TABLE
+ select HAVE_CMOS_DEFAULT
+ select PCIEXP_L1_SUB_STATE
+ select DRIVERS_UART_8250IO
+
+if BOARD_DELL_SNB_IVB_WORKSTATIONS
+
+config IGNORE_IASL_MISSING_DEPENDENCY
+ def_bool y
+
+config MAINBOARD_DIR
+ default "dell/snb_ivb_workstations"
+
+config MAINBOARD_PART_NUMBER
+ default "OptiPlex 9010" if BOARD_DELL_OPTIPLEX_9010
+
+config VARIANT_DIR
+ default "optiplex_9010_sff" if BOARD_DELL_OPTIPLEX_9010
+
+config DEVICETREE
+ default "variants/baseboard/devicetree.cb"
+
+config OVERRIDE_DEVICETREE
+ default "variants/\$(CONFIG_VARIANT_DIR)/overridetree.cb"
+
+config DRAM_RESET_GATE_GPIO
+ int
+ default 60
+
+config USBDEBUG_HCD_INDEX
+ int
+ default 2
+
+config CBFS_SIZE
+ default 0x600000
+
+config INCLUDE_SMSC_SCH5545_EC_FW
+ bool "Include SMSC SCH5545 EC firmware binary"
+ default n
+ help
+ This option allows to add the SMSC SCH5545 Environmental Controller
+ firmware binary. The firmware must be loaded after each power failure
+ in order to properly initialize the fan control, because EC loses its
+ configuration when power is cut off. Otherwise the fans will keep
+ running at full speed after power failure.
+
+config SMSC_SCH5545_EC_FW_FILE
+ string "File path to the SMSC SCH5545 EC firmware binary"
+ depends on INCLUDE_SMSC_SCH5545_EC_FW
+
+endif
diff --git a/src/mainboard/dell/snb_ivb_workstations/Kconfig.name b/src/mainboard/dell/snb_ivb_workstations/Kconfig.name
new file mode 100644
index 000000000000..51b7030a04b8
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/Kconfig.name
@@ -0,0 +1,4 @@
+config BOARD_DELL_OPTIPLEX_9010
+ bool "OptiPlex 9010 SFF"
+ select BOARD_DELL_SNB_IVB_WORKSTATIONS
+ select SOUTHBRIDGE_INTEL_BD82X6X
diff --git a/src/mainboard/dell/snb_ivb_workstations/Makefile.inc b/src/mainboard/dell/snb_ivb_workstations/Makefile.inc
new file mode 100644
index 000000000000..a53d8c19d323
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/Makefile.inc
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+bootblock-y += gpio.c
+romstage-y += gpio.c
+
+bootblock-y += early_init.c
+romstage-y += early_init.c
+
+bootblock-y += sch5545_ec_early.c
+
+romstage-y += sch5545_ec.c
+ramstage-y += sch5545_ec.c
+
+ramstage-$(CONFIG_MAINBOARD_USE_LIBGFXINIT) += gma-mainboard.ads
+
+ramstage-y += variants/$(VARIANT_DIR)/hda_verb.c
+
+ifeq ($(CONFIG_INCLUDE_SMSC_SCH5545_EC_FW),y)
+cbfs-files-y += sch5545_ecfw.bin
+sch5545_ecfw.bin-file := $(call strip_quotes,$(CONFIG_SMSC_SCH5545_EC_FW_FILE))
+sch5545_ecfw.bin-type := raw
+endif
+
+subdirs-y += variants/baseboard
+CPPFLAGS_common += -I$(src)/mainboard/$(MAINBOARDDIR)/variants/baseboard/include
+
+subdirs-y += variants/$(VARIANT_DIR)
+CPPFLAGS_common += -I$(src)/mainboard/$(MAINBOARDDIR)/variants/$(VARIANT_DIR)/include
diff --git a/src/mainboard/dell/snb_ivb_workstations/acpi/ec.asl b/src/mainboard/dell/snb_ivb_workstations/acpi/ec.asl
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/acpi/ec.asl
diff --git a/src/mainboard/dell/snb_ivb_workstations/acpi/platform.asl b/src/mainboard/dell/snb_ivb_workstations/acpi/platform.asl
new file mode 100644
index 000000000000..f890b5af5418
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/acpi/platform.asl
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+Method(_WAK,1)
+{
+ \_SB.PCI0.LPCB.SIO1.SIOW (Arg0)
+
+ Return(Package(){0,0})
+}
+
+Method(_PTS,1)
+{
+ \_SB.PCI0.LPCB.SIO1.SIOS (Arg0)
+}
+
+Scope (\_SB)
+{
+ Device (PWRB)
+ {
+ Name (_HID, EisaId ("PNP0C0C"))
+ Name (_UID, 0xAA)
+ Name (_STA, 0x0B)
+
+ Name (_PRW, Package() { 8, 3})
+ }
+}
+
+Scope (\_GPE)
+{
+ Method (_L08, 0, NotSerialized)
+ {
+ \_SB.PCI0.LPCB.SIO1.SIOH ()
+ Notify (\_SB.PWRB, 0x02)
+ }
+
+ Method (_L0D, 0, NotSerialized)
+ {
+ Notify (\_SB.PCI0.EHC1, 0x02)
+ Notify (\_SB.PCI0.EHC2, 0x02)
+ Notify (\_SB.PCI0.GLAN, 0x02)
+ }
+
+ Method (_L09, 0, NotSerialized)
+ {
+ Notify (\_SB.PCI0.RP01, 0x02)
+ Notify (\_SB.PCI0.RP02, 0x02)
+ Notify (\_SB.PCI0.RP03, 0x02)
+ Notify (\_SB.PCI0.RP04, 0x02)
+ Notify (\_SB.PCI0.RP05, 0x02)
+ Notify (\_SB.PCI0.RP06, 0x02)
+ Notify (\_SB.PCI0.RP07, 0x02)
+ Notify (\_SB.PCI0.RP08, 0x02)
+ Notify (\_SB.PCI0.PEGP, 0x02)
+ }
+}
diff --git a/src/mainboard/dell/snb_ivb_workstations/acpi/superio.asl b/src/mainboard/dell/snb_ivb_workstations/acpi/superio.asl
new file mode 100644
index 000000000000..fa1dfcf726f5
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/acpi/superio.asl
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#undef SUPERIO_DEV
+#undef SUPERIO_PNP_BASE
+#define SUPERIO_DEV SIO1
+#define SUPERIO_PNP_BASE 0x2e
+
+#define SCH5545_RUNTIME_BASE 0xa00
+#define SCH5545_EMI_BASE 0xa40
+#define SCH5545_SHOW_UARTA
+#define SCH5545_SHOW_KBC
+
+#include <superio/smsc/sch5545/acpi/superio.asl>
diff --git a/src/mainboard/dell/snb_ivb_workstations/board_info.txt b/src/mainboard/dell/snb_ivb_workstations/board_info.txt
new file mode 100644
index 000000000000..f49f3ba416e1
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/board_info.txt
@@ -0,0 +1,6 @@
+Category: desktop
+ROM protocol: SPI
+ROM package: SOIC-8, SOIC-16
+ROM socketed: n
+Flashrom support: y
+Release year: 2012
diff --git a/src/mainboard/dell/snb_ivb_workstations/cmos.default b/src/mainboard/dell/snb_ivb_workstations/cmos.default
new file mode 100644
index 000000000000..ccc7e64625a6
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/cmos.default
@@ -0,0 +1,7 @@
+boot_option=Fallback
+debug_level=Debug
+power_on_after_fail=Disable
+nmi=Enable
+sata_mode=AHCI
+gfx_uma_size=128M
+fan_full_speed=Disable
diff --git a/src/mainboard/dell/snb_ivb_workstations/cmos.layout b/src/mainboard/dell/snb_ivb_workstations/cmos.layout
new file mode 100644
index 000000000000..cff6004fec07
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/cmos.layout
@@ -0,0 +1,75 @@
+## SPDX-License-Identifier: GPL-2.0-only
+
+# -----------------------------------------------------------------
+entries
+
+# -----------------------------------------------------------------
+0 120 r 0 reserved_memory
+
+# -----------------------------------------------------------------
+# RTC_BOOT_BYTE (coreboot hardcoded)
+384 1 e 4 boot_option
+388 4 h 0 reboot_counter
+
+# -----------------------------------------------------------------
+# coreboot config options: console
+395 4 e 6 debug_level
+
+#400 8 r 0 reserved for century byte
+
+# coreboot config options: southbridge
+408 1 e 1 nmi
+409 2 e 7 power_on_after_fail
+411 1 e 8 sata_mode
+
+# coreboot config options: EC
+412 1 e 1 fan_full_speed
+
+# coreboot config options: northbridge
+432 3 e 9 gfx_uma_size
+
+# SandyBridge MRC Scrambler Seed values
+896 32 r 0 mrc_scrambler_seed
+928 32 r 0 mrc_scrambler_seed_s3
+960 16 r 0 mrc_scrambler_seed_chk
+
+# coreboot config options: check sums
+984 16 h 0 check_sum
+
+# -----------------------------------------------------------------
+
+enumerations
+
+#ID value text
+1 0 Disable
+1 1 Enable
+2 0 Enable
+2 1 Disable
+4 0 Fallback
+4 1 Normal
+6 0 Emergency
+6 1 Alert
+6 2 Critical
+6 3 Error
+6 4 Warning
+6 5 Notice
+6 6 Info
+6 7 Debug
+6 8 Spew
+7 0 Disable
+7 1 Enable
+7 2 Keep
+8 0 AHCI
+8 1 Compatible
+9 0 32M
+9 1 64M
+9 2 96M
+9 3 128M
+9 4 160M
+9 5 192M
+9 6 224M
+
+# -----------------------------------------------------------------
+checksums
+
+checksum 392 447 984
diff --git a/src/mainboard/dell/snb_ivb_workstations/dsdt.asl b/src/mainboard/dell/snb_ivb_workstations/dsdt.asl
new file mode 100644
index 000000000000..fa9cb86402f4
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/dsdt.asl
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <acpi/acpi.h>
+DefinitionBlock(
+ "dsdt.aml",
+ "DSDT",
+ ACPI_DSDT_REV_2,
+ OEM_ID,
+ ACPI_TABLE_CREATOR,
+ 0x20141018 /* OEM revision */
+)
+{
+ #include <acpi/dsdt_top.asl>
+ #include "acpi/platform.asl"
+ #include <cpu/intel/common/acpi/cpu.asl>
+ #include <southbridge/intel/common/acpi/platform.asl>
+ #include <southbridge/intel/bd82x6x/acpi/globalnvs.asl>
+ #include <southbridge/intel/common/acpi/sleepstates.asl>
+
+ Scope (\_SB)
+ {
+ Device (PCI0)
+ {
+ #include <northbridge/intel/sandybridge/acpi/sandybridge.asl>
+ #include <southbridge/intel/bd82x6x/acpi/pch.asl>
+ Device (GLAN)
+ {
+ Name (_ADR, 0x00190000)
+ Name (_PRW, Package() { 13, 4 })
+ }
+ }
+ }
+}
diff --git a/src/mainboard/dell/snb_ivb_workstations/early_init.c b/src/mainboard/dell/snb_ivb_workstations/early_init.c
new file mode 100644
index 000000000000..4a381df93792
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/early_init.c
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <bootblock_common.h>
+#include <device/pci_ops.h>
+#include <northbridge/intel/sandybridge/sandybridge.h>
+#include <southbridge/intel/bd82x6x/pch.h>
+#include <superio/smsc/sch5545/sch5545.h>
+#include <superio/smsc/sch5545/sch5545_emi.h>
+
+#include <baseboard/sch5545_ec.h>
+
+const struct southbridge_usb_port mainboard_usb_ports[] = {
+ { 1, 6, 0 },
+ { 1, 6, 0 },
+ { 1, 1, 1 },
+ { 1, 1, 1 },
+ { 1, 1, 2 },
+ { 1, 1, 2 },
+ { 1, 6, 3 },
+ { 1, 6, 3 },
+ { 1, 6, 4 },
+ { 1, 6, 4 },
+ { 1, 6, 5 },
+ { 1, 1, 5 },
+ { 1, 1, 6 },
+ { 1, 6, 6 },
+};
+
+void bootblock_mainboard_early_init(void)
+{
+ /*
+ * FIXME: the board gets stuck in reset loop in
+ * mainboard_romstage_entry. Avoid that by clearing SSKPD
+ */
+ pci_write_config32(HOST_BRIDGE, MCHBAR, CONFIG_FIXED_MCHBAR_MMIO_BASE | 1);
+ pci_write_config32(HOST_BRIDGE, MCHBAR + 4, 0);
+ mchbar_write16(SSKPD_HI, 0);
+
+ sch5545_early_init(0x2e);
+ /* Bare EC and SIO GPIO initialization which allows to enable serial port */
+ sch5545_emi_init(0x2e);
+ sch5545_emi_disable_interrupts();
+ sch5545_ec_early_init();
+
+ if (CONFIG(CONSOLE_SERIAL))
+ sch5545_enable_uart(0x2e, 0);
+}
diff --git a/src/mainboard/dell/snb_ivb_workstations/gma-mainboard.ads b/src/mainboard/dell/snb_ivb_workstations/gma-mainboard.ads
new file mode 100644
index 000000000000..74b50645e6d8
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/gma-mainboard.ads
@@ -0,0 +1,19 @@
+-- SPDX-License-Identifier: GPL-2.0-or-later
+
+with HW.GFX.GMA;
+with HW.GFX.GMA.Display_Probing;
+
+use HW.GFX.GMA;
+use HW.GFX.GMA.Display_Probing;
+
+private package GMA.Mainboard is
+
+ ports : constant Port_List :=
+ (DP1,
+ DP2,
+ HDMI1,
+ HDMI2,
+ Analog,
+ others => Disabled);
+
+end GMA.Mainboard;
diff --git a/src/mainboard/dell/snb_ivb_workstations/gpio.c b/src/mainboard/dell/snb_ivb_workstations/gpio.c
new file mode 100644
index 000000000000..d01e6221a641
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/gpio.c
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <southbridge/intel/common/gpio.h>
+
+static const struct pch_gpio_set1 pch_gpio_set1_mode = {
+ .gpio0 = GPIO_MODE_NATIVE,
+ .gpio1 = GPIO_MODE_GPIO, /* CHASSIS_ID0 */
+ .gpio2 = GPIO_MODE_GPIO,
+ .gpio3 = GPIO_MODE_GPIO,
+ .gpio4 = GPIO_MODE_GPIO, /* VGA_CBL_DET# */
+ .gpio5 = GPIO_MODE_GPIO,
+ .gpio6 = GPIO_MODE_GPIO, /* PCH_HS_DET# (unused?) */
+ .gpio7 = GPIO_MODE_GPIO, /* SKU2 */
+ .gpio8 = GPIO_MODE_GPIO,
+ .gpio9 = GPIO_MODE_NATIVE,
+ .gpio10 = GPIO_MODE_NATIVE,
+ .gpio11 = GPIO_MODE_GPIO, /* PCIE_X4_WAKE*/
+ .gpio12 = GPIO_MODE_NATIVE,
+ .gpio13 = GPIO_MODE_GPIO, /* PCIE_X1_WAKE (MT/DT only)*/
+ .gpio14 = GPIO_MODE_GPIO,
+ .gpio15 = GPIO_MODE_GPIO,
+ .gpio16 = GPIO_MODE_GPIO,
+ .gpio17 = GPIO_MODE_GPIO, /* CHASSIS_ID1 */
+ .gpio18 = GPIO_MODE_NATIVE,
+ .gpio19 = GPIO_MODE_NATIVE,
+ .gpio20 = GPIO_MODE_GPIO, /* FLEXBAY_HDR_CBL_DET# */
+ .gpio21 = GPIO_MODE_GPIO, /* BOARD_REV0 */
+ .gpio22 = GPIO_MODE_GPIO,
+ .gpio23 = GPIO_MODE_GPIO,
+ .gpio24 = GPIO_MODE_GPIO,
+ .gpio25 = GPIO_MODE_NATIVE,
+ .gpio26 = GPIO_MODE_NATIVE,
+ .gpio27 = GPIO_MODE_GPIO,
+ .gpio28 = GPIO_MODE_GPIO,
+ .gpio29 = GPIO_MODE_GPIO,
+ .gpio30 = GPIO_MODE_NATIVE,
+ .gpio31 = GPIO_MODE_GPIO, /* Password Clear Jumper */
+};
+
+static const struct pch_gpio_set1 pch_gpio_set1_direction = {
+ .gpio1 = GPIO_DIR_INPUT,
+ .gpio2 = GPIO_DIR_INPUT,
+ .gpio3 = GPIO_DIR_INPUT,
+ .gpio4 = GPIO_DIR_INPUT,
+ .gpio5 = GPIO_DIR_INPUT,
+ .gpio6 = GPIO_DIR_INPUT,
+ .gpio7 = GPIO_DIR_INPUT,
+ .gpio8 = GPIO_DIR_OUTPUT,
+ .gpio11 = GPIO_DIR_INPUT,
+ .gpio13 = GPIO_DIR_INPUT,
+ .gpio14 = GPIO_DIR_OUTPUT,
+ .gpio15 = GPIO_DIR_OUTPUT,
+ .gpio16 = GPIO_DIR_INPUT,
+ .gpio17 = GPIO_DIR_INPUT,
+ .gpio20 = GPIO_DIR_INPUT,
+ .gpio21 = GPIO_DIR_INPUT,
+ .gpio22 = GPIO_DIR_INPUT,
+ .gpio23 = GPIO_DIR_INPUT,
+ .gpio24 = GPIO_DIR_INPUT,
+ .gpio27 = GPIO_DIR_OUTPUT,
+ .gpio28 = GPIO_DIR_OUTPUT,
+ .gpio29 = GPIO_DIR_OUTPUT,
+ .gpio31 = GPIO_DIR_INPUT,
+};
+
+static const struct pch_gpio_set1 pch_gpio_set1_level = {
+ .gpio8 = GPIO_LEVEL_HIGH,
+ .gpio14 = GPIO_LEVEL_HIGH,
+ .gpio15 = GPIO_LEVEL_LOW,
+ .gpio27 = GPIO_LEVEL_LOW,
+ .gpio28 = GPIO_LEVEL_LOW,
+ .gpio29 = GPIO_LEVEL_HIGH,
+};
+
+static const struct pch_gpio_set1 pch_gpio_set1_reset = {
+};
+
+static const struct pch_gpio_set1 pch_gpio_set1_invert = {
+ .gpio2 = GPIO_INVERT,
+ .gpio5 = GPIO_INVERT,
+ .gpio6 = GPIO_INVERT,
+ .gpio11 = GPIO_INVERT,
+ .gpio13 = GPIO_INVERT,
+};
+
+static const struct pch_gpio_set1 pch_gpio_set1_blink = {
+};
+
+static const struct pch_gpio_set2 pch_gpio_set2_mode = {
+ .gpio32 = GPIO_MODE_GPIO, /* SKU0 */
+ .gpio33 = GPIO_MODE_GPIO,
+ .gpio34 = GPIO_MODE_GPIO,
+ .gpio35 = GPIO_MODE_GPIO, /* SKU1 */
+ .gpio36 = GPIO_MODE_NATIVE,
+ .gpio37 = GPIO_MODE_NATIVE,
+ .gpio38 = GPIO_MODE_GPIO, /* CHASSIS_ID2 */
+ .gpio39 = GPIO_MODE_GPIO, /* FP_PRESENCE# */
+ .gpio40 = GPIO_MODE_NATIVE,
+ .gpio41 = GPIO_MODE_NATIVE,
+ .gpio42 = GPIO_MODE_NATIVE,
+ .gpio43 = GPIO_MODE_NATIVE,
+ .gpio44 = GPIO_MODE_GPIO, /* INTRUD_CBL_DET# */
+ .gpio45 = GPIO_MODE_GPIO, /* COM_SER2_DET# (unused?) */
+ .gpio46 = GPIO_MODE_GPIO, /* BOARD_REV1 */
+ .gpio47 = GPIO_MODE_NATIVE,
+ .gpio48 = GPIO_MODE_GPIO,
+ .gpio49 = GPIO_MODE_GPIO,
+ .gpio50 = GPIO_MODE_NATIVE,
+ .gpio51 = GPIO_MODE_NATIVE,
+ .gpio52 = GPIO_MODE_NATIVE,
+ .gpio53 = GPIO_MODE_NATIVE,
+ .gpio54 = GPIO_MODE_NATIVE,
+ .gpio55 = GPIO_MODE_NATIVE,
+ .gpio56 = GPIO_MODE_NATIVE,
+ .gpio57 = GPIO_MODE_GPIO,
+ .gpio58 = GPIO_MODE_NATIVE,
+ .gpio59 = GPIO_MODE_NATIVE,
+ .gpio60 = GPIO_MODE_GPIO,
+ .gpio61 = GPIO_MODE_NATIVE,
+ .gpio62 = GPIO_MODE_NATIVE,
+ .gpio63 = GPIO_MODE_NATIVE,
+};
+
+static const struct pch_gpio_set2 pch_gpio_set2_direction = {
+ .gpio32 = GPIO_DIR_INPUT,
+ .gpio33 = GPIO_DIR_OUTPUT,
+ .gpio34 = GPIO_DIR_OUTPUT,
+ .gpio35 = GPIO_DIR_INPUT,
+ .gpio38 = GPIO_DIR_INPUT,
+ .gpio39 = GPIO_DIR_INPUT,
+ .gpio44 = GPIO_DIR_INPUT,
+ .gpio45 = GPIO_DIR_INPUT,
+ .gpio46 = GPIO_DIR_INPUT,
+ .gpio48 = GPIO_DIR_INPUT,
+ .gpio49 = GPIO_DIR_OUTPUT,
+ .gpio57 = GPIO_DIR_OUTPUT,
+ .gpio60 = GPIO_DIR_OUTPUT,
+ .gpio63 = GPIO_DIR_OUTPUT,
+};
+
+static const struct pch_gpio_set2 pch_gpio_set2_level = {
+ .gpio33 = GPIO_LEVEL_HIGH,
+ .gpio34 = GPIO_LEVEL_HIGH,
+ .gpio49 = GPIO_LEVEL_HIGH,
+ .gpio57 = GPIO_LEVEL_LOW,
+ .gpio60 = GPIO_LEVEL_HIGH,
+};
+
+static const struct pch_gpio_set2 pch_gpio_set2_reset = {
+};
+
+static const struct pch_gpio_set3 pch_gpio_set3_mode = {
+ .gpio64 = GPIO_MODE_NATIVE,
+ .gpio65 = GPIO_MODE_NATIVE,
+ .gpio66 = GPIO_MODE_NATIVE,
+ .gpio67 = GPIO_MODE_NATIVE,
+ .gpio68 = GPIO_MODE_GPIO, /* BOARD_REV2 */
+ .gpio69 = GPIO_MODE_GPIO, /* USB_HDR_DET# */
+ .gpio70 = GPIO_MODE_GPIO, /* FP_CHAS_DET# */
+ .gpio71 = GPIO_MODE_GPIO,
+ .gpio72 = GPIO_MODE_GPIO,
+ .gpio73 = GPIO_MODE_GPIO,
+ .gpio74 = GPIO_MODE_GPIO, /* ME_MFG_MODE */
+ .gpio75 = GPIO_MODE_NATIVE,
+};
+
+static const struct pch_gpio_set3 pch_gpio_set3_direction = {
+ .gpio68 = GPIO_DIR_INPUT,
+ .gpio69 = GPIO_DIR_INPUT,
+ .gpio70 = GPIO_DIR_INPUT,
+ .gpio71 = GPIO_DIR_OUTPUT,
+ .gpio72 = GPIO_DIR_OUTPUT,
+ .gpio73 = GPIO_DIR_INPUT,
+ .gpio74 = GPIO_DIR_OUTPUT,
+};
+
+static const struct pch_gpio_set3 pch_gpio_set3_level = {
+ .gpio71 = GPIO_LEVEL_HIGH,
+ .gpio72 = GPIO_LEVEL_HIGH,
+ .gpio74 = GPIO_LEVEL_HIGH,
+};
+
+static const struct pch_gpio_set3 pch_gpio_set3_reset = {
+ .gpio74 = GPIO_RESET_RSMRST,
+};
+
+const struct pch_gpio_map mainboard_gpio_map = {
+ .set1 = {
+ .mode = &pch_gpio_set1_mode,
+ .direction = &pch_gpio_set1_direction,
+ .level = &pch_gpio_set1_level,
+ .blink = &pch_gpio_set1_blink,
+ .invert = &pch_gpio_set1_invert,
+ .reset = &pch_gpio_set1_reset,
+ },
+ .set2 = {
+ .mode = &pch_gpio_set2_mode,
+ .direction = &pch_gpio_set2_direction,
+ .level = &pch_gpio_set2_level,
+ .reset = &pch_gpio_set2_reset,
+ },
+ .set3 = {
+ .mode = &pch_gpio_set3_mode,
+ .direction = &pch_gpio_set3_direction,
+ .level = &pch_gpio_set3_level,
+ .reset = &pch_gpio_set3_reset,
+ },
+};
diff --git a/src/mainboard/dell/snb_ivb_workstations/hda_verb.c b/src/mainboard/dell/snb_ivb_workstations/hda_verb.c
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/hda_verb.c
diff --git a/src/mainboard/dell/snb_ivb_workstations/mainboard.c b/src/mainboard/dell/snb_ivb_workstations/mainboard.c
new file mode 100644
index 000000000000..c32121112a95
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/mainboard.c
@@ -0,0 +1,191 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <bootstate.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci_ops.h>
+#include <drivers/intel/gma/int15.h>
+#include <southbridge/intel/bd82x6x/pch.h>
+#include <southbridge/intel/common/gpio.h>
+#include <superio/smsc/sch5545/sch5545.h>
+
+#include <baseboard/sch5545_ec.h>
+
+#define SIO_PORT 0x2e
+
+#define GPIO_CHASSIS_ID0 1
+#define GPIO_VGA_CABLE_DET_L 4
+#define GPIO_SKU2 7
+#define GPIO_CHASSIS_ID1 17
+/* Internal USB header on mainboard */
+#define FLEXBAY_HEADER_CABLE_DET_L 20
+#define GPIO_BOARD_REV0 21
+/* Password clear jumper */
+#define GPIO_PSWD_CLR 31
+#define GPIO_SKU0 32
+#define GPIO_SKU1 35
+#define GPIO_CHASSIS_ID2 37
+/* Front panel presence */
+#define GPIO_FRONT_PANEL_PRESENT_L 39
+#define GPIO_INTRUDER_CABLE_DET_L 44
+#define GPIO_BOARD_REV1 46
+#define GPIO_BOARD_REV2 68
+/* Front USB 3.0 ports */
+#define GPIO_USB_HEADER_DET_L 69
+/* Differentiate between MT/DT on the Medium Tower and Desktop variants */
+#define GPIO_FRONT_PANEL_CHASSIS_DET_L 70
+/*
+ * This GPIO is connected to the transistor gate. If high, it will pull the
+ * HDA_SDO high. When strapped at PCH_PWROK it will enable the Flash Descriptor
+ * Security Override and disable ME after chipset bringup. Alternative method
+ * is to use the service jumper on the mainboard.
+ */
+#define GPIO_ME_MFG_MODE 74
+
+/* These GPIOs are on SCH5545 */
+
+/* Detect if the power switch cable is connected */
+#define SIO_GPIO_FP_CBL_DET_L 25
+/* Detect internal speaker connected to front cover */
+#define SIO_GPIO_PCSPKR_DET_L 31
+
+static void mainboard_enable(struct device *dev)
+{
+ int pin_sts;
+ install_intel_vga_int15_handler(GMA_INT15_ACTIVE_LFP_NONE,
+ GMA_INT15_PANEL_FIT_DEFAULT,
+ GMA_INT15_BOOT_DISPLAY_DEFAULT, 0);
+
+ pin_sts = get_gpio(GPIO_CHASSIS_ID0);
+ pin_sts |= get_gpio(GPIO_CHASSIS_ID1) << 1;
+ pin_sts |= get_gpio(GPIO_CHASSIS_ID2) << 2;
+ pin_sts |= get_gpio(GPIO_FRONT_PANEL_CHASSIS_DET_L) << 3;
+
+ printk(BIOS_DEBUG, "Chassis type: ");
+ switch (pin_sts) {
+ case 0:
+ printk(BIOS_DEBUG, "MT\n");
+ break;
+ case 3:
+ case 11:
+ printk(BIOS_DEBUG, "USFF\n");
+ break;
+ case 4:
+ /* As per table in schematics, but don't know what this is */
+ printk(BIOS_DEBUG, "Comoros\n");
+ break;
+ case 1:
+ case 9:
+ case 5:
+ case 13:
+ printk(BIOS_DEBUG, "SFF\n");
+ break;
+ case 8:
+ printk(BIOS_DEBUG, "DT\n");
+ break;
+ default:
+ printk(BIOS_DEBUG, "Unknown chassis type %u\n", pin_sts);
+ break;
+ }
+
+ pin_sts = get_gpio(GPIO_BOARD_REV0);
+ pin_sts |= get_gpio(GPIO_BOARD_REV1) << 1;
+ pin_sts |= get_gpio(GPIO_BOARD_REV2) << 2;
+
+ printk(BIOS_DEBUG, "Board revision: %d\n", pin_sts);
+
+ pin_sts = get_gpio(GPIO_SKU0);
+ pin_sts |= get_gpio(GPIO_SKU1) << 1;
+ pin_sts |= get_gpio(GPIO_SKU2) << 2;
+
+ printk(BIOS_DEBUG, "SKU ID is %d:", pin_sts);
+ switch (pin_sts) {
+ case 0:
+ printk(BIOS_DEBUG, "TPM\n");
+ break;
+ case 1:
+ printk(BIOS_DEBUG, "TCM\n");
+ break;
+ case 2:
+ printk(BIOS_DEBUG, "Non TPM/TCM\n");
+ break;
+ default:
+ printk(BIOS_DEBUG, "Unknown/reserved\n");
+ break;
+ }
+
+ printk(BIOS_DEBUG, "VGA cable %sconnected\n",
+ get_gpio(GPIO_VGA_CABLE_DET_L) ? "dis" : "");
+
+ printk(BIOS_DEBUG, "Flexbay %sattached to internal USB 2.0 header\n",
+ get_gpio(FLEXBAY_HEADER_CABLE_DET_L) ? "not " : "");
+
+ printk(BIOS_DEBUG, "Password clear jumper %sactive\n",
+ get_gpio(GPIO_PSWD_CLR) ? "in" : "");
+
+ if (!get_gpio(GPIO_FRONT_PANEL_PRESENT_L)) {
+ printk(BIOS_DEBUG, "Front panel cable connected\n");
+ } else {
+ printk(BIOS_WARNING, "Front panel cable not connected!\n");
+ printk(BIOS_WARNING, "Front USB 2.0 ports, SATA LED, microphone"
+ " and speaker jacks will not work!\n");
+ printk(BIOS_WARNING, "Check the front panel cable!\n");
+ }
+
+ if (!get_gpio(GPIO_INTRUDER_CABLE_DET_L)) {
+ printk(BIOS_DEBUG, "Intruder cable connected\n");
+ } else {
+ printk(BIOS_WARNING, "Intruder cable not connected!\n");
+ printk(BIOS_WARNING, "Intrusion detection will not work!\n");
+ printk(BIOS_WARNING, "Check the intruder cable!\n");
+ }
+
+ if (!get_gpio(GPIO_USB_HEADER_DET_L)) {
+ printk(BIOS_DEBUG, "Front USB 3.0 cable connected\n");
+ } else {
+ printk(BIOS_WARNING, "Front USB 3.0 cable not connected!\n");
+ printk(BIOS_WARNING, "Front USB 3.0 ports will not work!\n");
+ printk(BIOS_WARNING, "Check the front USB 3.0 cable!\n");
+ }
+}
+
+static void mainboard_final(void *chip_info)
+{
+ int pin_sts;
+ struct device *dev = pcidev_on_root(0x1f, 0);
+ const u8 pirq_routing = 11;
+
+ pci_write_config8(dev, PIRQA_ROUT, pirq_routing);
+ pci_write_config8(dev, PIRQB_ROUT, pirq_routing);
+ pci_write_config8(dev, PIRQC_ROUT, pirq_routing);
+ pci_write_config8(dev, PIRQD_ROUT, pirq_routing);
+
+ pci_write_config8(dev, PIRQE_ROUT, pirq_routing);
+ pci_write_config8(dev, PIRQF_ROUT, pirq_routing);
+ pci_write_config8(dev, PIRQG_ROUT, pirq_routing);
+ pci_write_config8(dev, PIRQH_ROUT, pirq_routing);
+
+ pin_sts = sch5545_get_gpio(SIO_PORT, SIO_GPIO_FP_CBL_DET_L);
+
+ if (pin_sts != -1) {
+ if (pin_sts) {
+ printk(BIOS_WARNING, "Power switch cable not connected!\n");
+ printk(BIOS_WARNING, "Check power switch cable!\n");
+ } else {
+ printk(BIOS_DEBUG, "Power switch cable connected\n");
+ }
+ }
+
+ pin_sts = sch5545_get_gpio(SIO_PORT, SIO_GPIO_PCSPKR_DET_L);
+
+ if (pin_sts != -1)
+ printk(BIOS_DEBUG, "Internal chassis PC speaker %sconnected\n",
+ pin_sts ? "not " : "");
+}
+
+struct chip_operations mainboard_ops = {
+ .enable_dev = mainboard_enable,
+ .final = mainboard_final,
+};
+
+BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, sch5545_ec_hwm_init, NULL);
diff --git a/src/mainboard/dell/snb_ivb_workstations/romstage.c b/src/mainboard/dell/snb_ivb_workstations/romstage.c
new file mode 100644
index 000000000000..83c00c7260f9
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/romstage.c
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <stdint.h>
+#include <arch/io.h>
+#include <console/console.h>
+#include <northbridge/intel/sandybridge/sandybridge.h>
+#include <northbridge/intel/sandybridge/raminit_native.h>
+#include <southbridge/intel/common/rcba.h>
+#include <southbridge/intel/bd82x6x/pch.h>
+#include <superio/smsc/sch5545/sch5545.h>
+#include <superio/smsc/sch5545/sch5545_emi.h>
+
+#include <baseboard/sch5545_ec.h>
+
+void mainboard_late_rcba_config(void)
+{
+ DIR_ROUTE(D31IR, PIRQA, PIRQD, PIRQC, PIRQA);
+ DIR_ROUTE(D29IR, PIRQH, PIRQD, PIRQA, PIRQC);
+ DIR_ROUTE(D28IR, PIRQA, PIRQB, PIRQC, PIRQD);
+ DIR_ROUTE(D27IR, PIRQG, PIRQB, PIRQC, PIRQD);
+ DIR_ROUTE(D26IR, PIRQA, PIRQF, PIRQC, PIRQD);
+ DIR_ROUTE(D25IR, PIRQE, PIRQF, PIRQG, PIRQH);
+ DIR_ROUTE(D22IR, PIRQA, PIRQD, PIRQC, PIRQB);
+ DIR_ROUTE(D20IR, PIRQA, PIRQB, PIRQC, PIRQD);
+}
+
+void mainboard_early_init(int s3resume)
+{
+ uint16_t ec_fw_version;
+
+ /*
+ * We do EC initialization in romstage, because it makes no sense to
+ * bloat the bootblock any more. Secondly, the EC expects to receive
+ * correct initialization sequence from the host in the time window of
+ * about 3-5 seconds since system reset. If it doesn't receive the
+ * initialization sequence, it enters an error path which results in
+ * fans spinned up to high speed. In this state EC doesn't respond to
+ * further messages sent over EMI. The issue appears after power
+ * failure, where EC loses its configuration. For this particular
+ * reasons we do the initialization in romstage instead of ramstage.
+ */
+ sch5545_emi_init(0x2e);
+ if (sch5545_emi_get_int_mask_high())
+ printk(BIOS_SPEW, "EC interrupt mask MSB is not 0\n");
+
+ sch5545_ec_hwm_early_init();
+
+ if (!s3resume) {
+ ec_fw_version = sch5545_get_ec_fw_version();
+ printk(BIOS_DEBUG, "SCH5545 EC firmware version %04x\n", ec_fw_version);
+ sch5545_update_ec_firmware(ec_fw_version);
+ }
+ printk(BIOS_DEBUG, "EC early init complete.\n");
+
+ /* Disable SMIs and clear SMI status */
+ outb(0, SCH5545_RUNTIME_REG_BASE + SCH5545_RR_SMI_EN);
+ outb(SCH5545_SMI_GLOBAL_STS, SCH5545_RUNTIME_REG_BASE + SCH5545_RR_SMI_STS);
+}
+
+void mainboard_get_spd(spd_raw_data *spd, bool id_only)
+{
+ read_spd(&spd[0], 0x50, id_only);
+ read_spd(&spd[1], 0x51, id_only);
+ read_spd(&spd[2], 0x52, id_only);
+ read_spd(&spd[3], 0x53, id_only);
+}
diff --git a/src/mainboard/dell/snb_ivb_workstations/sch5545_ec.c b/src/mainboard/dell/snb_ivb_workstations/sch5545_ec.c
new file mode 100644
index 000000000000..a68f285a9862
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/sch5545_ec.c
@@ -0,0 +1,489 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <cbfs.h>
+#include <cf9_reset.h>
+#include <option.h>
+#include <cpu/x86/msr.h>
+#include <console/console.h>
+#include <cpu/intel/model_206ax/model_206ax.h>
+#include <southbridge/intel/common/gpio.h>
+#include <superio/smsc/sch5545/sch5545.h>
+#include <superio/smsc/sch5545/sch5545_emi.h>
+
+#include <baseboard/sch5545_ec.h>
+#include <variant/sch5545_ec_tables.h>
+
+#define GPIO_CHASSIS_ID0 1
+#define GPIO_CHASSIS_ID1 17
+#define GPIO_CHASSIS_ID2 37
+#define GPIO_FRONT_PANEL_CHASSIS_DET_L 70
+
+static const struct ec_val_reg ec_hwm_init_seq[] = {
+ { 0xa0, 0x02fc },
+ { 0x32, 0x02fd },
+ { 0x77, 0x0005 },
+ { 0x0f, 0x0018 },
+ { 0x2f, 0x0019 },
+ { 0x2f, 0x001a },
+ { 0x33, 0x008a },
+ { 0x33, 0x008b },
+ { 0x33, 0x008c },
+ { 0x10, 0x00ba },
+ { 0xff, 0x00d1 },
+ { 0xff, 0x00d6 },
+ { 0xff, 0x00db },
+ { 0x00, 0x0048 },
+ { 0x00, 0x0049 },
+ { 0x00, 0x007a },
+ { 0x00, 0x007b },
+ { 0x00, 0x007c },
+ { 0x00, 0x0080 },
+ { 0x00, 0x0081 },
+ { 0x00, 0x0082 },
+ { 0xbb, 0x0083 },
+ { 0xb0, 0x0084 },
+ { 0x88, 0x01a1 },
+ { 0x80, 0x01a4 },
+ { 0x00, 0x0088 },
+ { 0x00, 0x0089 },
+ { 0x02, 0x00a0 },
+ { 0x02, 0x00a1 },
+ { 0x02, 0x00a2 },
+ { 0x04, 0x00a4 },
+ { 0x04, 0x00a5 },
+ { 0x04, 0x00a6 },
+ { 0x00, 0x00ab },
+ { 0x3f, 0x00ad },
+ { 0x07, 0x00b7 },
+ { 0x50, 0x0062 },
+ { 0x46, 0x0063 },
+ { 0x50, 0x0064 },
+ { 0x46, 0x0065 },
+ { 0x50, 0x0066 },
+ { 0x46, 0x0067 },
+ { 0x98, 0x0057 },
+ { 0x98, 0x0059 },
+ { 0x7c, 0x0061 },
+ { 0x00, 0x01bc },
+ { 0x00, 0x01bd },
+ { 0x00, 0x01bb },
+ { 0xdd, 0x0085 },
+ { 0xdd, 0x0086 },
+ { 0x07, 0x0087 },
+ { 0x5e, 0x0090 },
+ { 0x5e, 0x0091 },
+ { 0x5d, 0x0095 },
+ { 0x00, 0x0096 },
+ { 0x00, 0x0097 },
+ { 0x00, 0x009b },
+ { 0x86, 0x00ae },
+ { 0x86, 0x00af },
+ { 0x67, 0x00b3 },
+ { 0xff, 0x00c4 },
+ { 0xff, 0x00c5 },
+ { 0xff, 0x00c9 },
+ { 0x01, 0x0040 },
+ { 0x00, 0x02fc },
+ { 0x9a, 0x02b3 },
+ { 0x05, 0x02b4 },
+ { 0x01, 0x02cc },
+ { 0x4c, 0x02d0 },
+ { 0x01, 0x02d2 },
+ { 0x01, 0x006f },
+ { 0x02, 0x0070 },
+ { 0x03, 0x0071 },
+};
+
+
+static uint8_t send_mbox_msg_with_int(uint8_t mbox_message)
+{
+ uint8_t int_sts, int_cond;
+
+ sch5545_emi_h2ec_mbox_write(mbox_message);
+
+ do {
+ int_sts = sch5545_emi_get_int_src_low();
+ int_cond = int_sts & 0x71;
+ } while (int_cond == 0);
+
+ sch5545_emi_set_int_src_low(int_cond);
+
+ if ((int_sts & 1) == 0)
+ return 0;
+
+ if (sch5545_emi_ec2h_mbox_read() == mbox_message)
+ return 1;
+
+ return 0;
+}
+
+static uint8_t send_mbox_msg_simple(uint8_t mbox_message)
+{
+ uint8_t int_sts;
+
+ sch5545_emi_h2ec_mbox_write(mbox_message);
+
+ do {
+ int_sts = sch5545_emi_get_int_src_low();
+ if ((int_sts & 70) != 0)
+ return 0;
+ } while ((int_sts & 1) == 0);
+
+ if (sch5545_emi_ec2h_mbox_read() == mbox_message)
+ return 1;
+
+ return 0;
+}
+
+static void ec_check_mbox_and_int_status(uint8_t int_src, uint8_t mbox_msg)
+{
+ uint8_t val;
+
+ val = sch5545_emi_ec2h_mbox_read();
+ if (val != mbox_msg)
+ printk(BIOS_SPEW, "EC2H mailbox should be %02x, is %02x\n", mbox_msg, val);
+
+ val = sch5545_emi_get_int_src_low();
+ if (val != int_src)
+ printk(BIOS_SPEW, "EC INT SRC should be %02x, is %02x\n", int_src, val);
+
+ sch5545_emi_set_int_src_low(val);
+}
+
+static uint8_t ec_read_write_reg(uint8_t ldn, uint16_t reg, uint8_t *value, uint8_t rw_bit)
+{
+ uint8_t int_mask_bckup, ret = 0;
+ rw_bit &= 1;
+
+ int_mask_bckup = sch5545_emi_get_int_mask_low();
+ sch5545_emi_set_int_mask_low(0);
+
+ sch5545_emi_ec_write16(0x8000, (ldn << 1) | 0x100 | rw_bit);
+ if (rw_bit)
+ sch5545_emi_ec_write32(0x8004, (reg << 16) | *value);
+ else
+ sch5545_emi_ec_write32(0x8004, reg << 16);
+
+ ret = send_mbox_msg_with_int(1);
+ if (ret && !rw_bit)
+ *value = sch5545_emi_ec_read8(0x8004);
+ else if (ret != 1 && rw_bit)
+ printk(BIOS_WARNING, "EC mailbox returned unexpected value "
+ "when writing %02x to %04x\n", *value, reg);
+ else if (ret != 1 && !rw_bit)
+ printk(BIOS_WARNING, "EC mailbox returned unexpected value "
+ "when reading %04x\n", reg);
+
+ sch5545_emi_set_int_mask_low(int_mask_bckup);
+
+ return ret;
+}
+
+uint16_t sch5545_get_ec_fw_version(void)
+{
+ uint8_t val = 0;
+ uint16_t ec_fw_version;
+
+ /* Read the FW version currently loaded used by EC */
+ ec_read_write_reg(EC_HWM_LDN, 0x2ad, &val, READ_OP);
+ ec_fw_version = (val << 8);
+ ec_read_write_reg(EC_HWM_LDN, 0x2ae, &val, READ_OP);
+ ec_fw_version |= val;
+ ec_read_write_reg(EC_HWM_LDN, 0x2ac, &val, READ_OP);
+ ec_read_write_reg(EC_HWM_LDN, 0x2fd, &val, READ_OP);
+ ec_read_write_reg(EC_HWM_LDN, 0x2b0, &val, READ_OP);
+
+ return ec_fw_version;
+}
+
+void sch5545_update_ec_firmware(uint16_t ec_version)
+{
+ uint8_t status;
+ uint16_t ec_fw_version;
+ uint32_t *ec_fw_file;
+ size_t ec_fw_file_size;
+
+ ec_fw_file = cbfs_map("sch5545_ecfw.bin", &ec_fw_file_size);
+
+ if (!ec_fw_file || ec_fw_file_size != 0x1750) {
+ printk(BIOS_ERR, "EC firmware file not found in CBFS!\n");
+ printk(BIOS_ERR, "The fans will keep running at maximum speed.\n");
+ return;
+ }
+
+ ec_fw_version = ec_fw_file[3] & 0xffff;
+
+ /*
+ * After power failure EC loses its configuration. The currently used firmware version
+ * by EC will be reported as 0x0000. In such case EC firmware needs to be uploaded.
+ */
+ if (ec_version != ec_fw_version) {
+ printk(BIOS_INFO, "SCH5545 EC is not functional, probably due to power "
+ "failure\n");
+ printk(BIOS_INFO, "Uploading EC firmware (version %04x) to SCH5545\n",
+ ec_fw_version);
+
+ if (!send_mbox_msg_simple(0x03)) {
+ printk(BIOS_WARNING, "EC didn't accept FW upload start signal\n");
+ printk(BIOS_WARNING, "EC firmware update failed!\n");
+ return;
+ }
+
+ sch5545_emi_ec_write32_bulk(0x8100, ec_fw_file, ec_fw_file_size);
+
+ status = send_mbox_msg_simple(0x04);
+ status += send_mbox_msg_simple(0x06);
+
+ if (status != 2)
+ printk(BIOS_WARNING, "EC firmware update failed!\n");
+
+ if (ec_fw_version != sch5545_get_ec_fw_version()) {
+ printk(BIOS_ERR, "EC firmware update failed!\n");
+ printk(BIOS_ERR, "The fans will keep running at maximum speed\n");
+ } else {
+ printk(BIOS_INFO, "EC firmware update success\n");
+ /*
+ * The vendor BIOS does a full reset after EC firmware update. Most
+ * likely because the fans are adapting very slowly after automatic fan
+ * control is enabled. This makes huge noise. To avoid it, also do the
+ * full reset. On next boot, it will not be necessary.
+ */
+ full_reset();
+ }
+ } else {
+ printk(BIOS_INFO, "SCH5545 EC firmware up to date (version %04x)\n",
+ ec_version);
+ }
+}
+
+void sch5545_ec_hwm_early_init(void)
+{
+ uint8_t val = 0;
+ int i;
+
+ printk(BIOS_DEBUG, "%s\n", __func__);
+
+ ec_check_mbox_and_int_status(0x20, 0x01);
+
+ ec_read_write_reg(2, 0xcb, &val, READ_OP);
+ ec_read_write_reg(2, 0xb8, &val, READ_OP);
+
+ for (i = 0; i < ARRAY_SIZE(ec_hwm_init_seq); i++) {
+ val = ec_hwm_init_seq[i].val;
+ ec_read_write_reg(EC_HWM_LDN, ec_hwm_init_seq[i].reg, &val,
+ WRITE_OP);
+ }
+
+ ec_check_mbox_and_int_status(0x01, 0x01);
+}
+
+static uint8_t get_sku_tdp_config(void)
+{
+ msr_t msr;
+ uint32_t power_unit, tdp;
+ /* Get units */
+ msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
+ power_unit = msr.lo & 0xf;
+
+ /* Get power defaults for this SKU */
+ msr = rdmsr(MSR_PKG_POWER_SKU);
+ tdp = msr.lo & 0x7fff;
+
+ /* These numbers will determine which settings to use to init EC */
+ if ((tdp >> power_unit) < 66)
+ return 16;
+ else
+ return 32;
+}
+
+static uint8_t get_chassis_type(void)
+{
+ uint8_t chassis_id;
+
+ chassis_id = get_gpio(GPIO_CHASSIS_ID0);
+ chassis_id |= get_gpio(GPIO_CHASSIS_ID1) << 1;
+ chassis_id |= get_gpio(GPIO_CHASSIS_ID2) << 2;
+ chassis_id |= get_gpio(GPIO_FRONT_PANEL_CHASSIS_DET_L) << 3;
+
+ /* This mapping will determine which EC init sequence to use */
+ switch (chassis_id) {
+ case 0x0:
+ case 0x4:
+ return 5; /* MT */
+ case 0x8:
+ return 4; /* DT */
+ case 0x3:
+ case 0xb:
+ return 3; /* USFF */
+ case 0x1:
+ case 0x9:
+ case 0x5:
+ case 0xd:
+ return 6; /* SFF */
+ default:
+ printk(BIOS_DEBUG, "Unknown chassis ID %x\n", chassis_id);
+ break;
+ }
+
+ return 0xff;
+}
+
+static void ec_hwm_init_late(const ec_chassis_tdp_t *ec_hwm_sequence, size_t size)
+{
+ unsigned int i;
+ uint8_t val;
+ uint8_t tdp_config = get_sku_tdp_config();
+
+ for (i = 0; i < size; i++) {
+ if (ec_hwm_sequence[i].tdp == tdp_config ||
+ ec_hwm_sequence[i].tdp == TDP_COMMON) {
+ val = ec_hwm_sequence[i].val;
+ ec_read_write_reg(EC_HWM_LDN, ec_hwm_sequence[i].reg, &val, WRITE_OP);
+ }
+ }
+}
+
+static void prepare_for_hwm_ec_sequence(uint8_t write_only, uint8_t *value)
+{
+ uint16_t reg;
+ uint8_t val;
+
+ if (write_only == 1) {
+ val = *value;
+ reg = 0x02fc;
+ } else {
+ if (value != NULL)
+ ec_read_write_reg(EC_HWM_LDN, 0x02fc, value, READ_OP);
+ val = 0xa0;
+ ec_read_write_reg(EC_HWM_LDN, 0x2fc, &val, WRITE_OP);
+ val = 0x32;
+ reg = 0x02fd;
+ }
+
+ ec_read_write_reg(1, reg, &val, WRITE_OP);
+}
+
+void sch5545_ec_hwm_init(void *unused)
+{
+ uint8_t val = 0, val_2fc, chassis_type;
+
+ printk(BIOS_DEBUG, "%s\n", __func__);
+ sch5545_emi_init(0x2e);
+
+ chassis_type = get_chassis_type();
+
+ ec_read_write_reg(EC_HWM_LDN, 0x0048, &val, READ_OP);
+ ec_read_write_reg(EC_HWM_LDN, 0x0048, &val, WRITE_OP);
+ ec_read_write_reg(EC_HWM_LDN, 0x0042, &val, READ_OP);
+ ec_read_write_reg(EC_HWM_LDN, 0x0048, &val, READ_OP);
+ val |= 0x02;
+ ec_read_write_reg(EC_HWM_LDN, 0x0048, &val, WRITE_OP);
+
+ ec_read_write_reg(EC_HWM_LDN, 0x0048, &val, READ_OP);
+ ec_read_write_reg(EC_HWM_LDN, 0x0048, &val, WRITE_OP);
+ ec_read_write_reg(EC_HWM_LDN, 0x0042, &val, READ_OP);
+ ec_read_write_reg(EC_HWM_LDN, 0x0048, &val, READ_OP);
+ val |= 0x04;
+ ec_read_write_reg(EC_HWM_LDN, 0x0048, &val, WRITE_OP);
+
+ ec_read_write_reg(EC_HWM_LDN, 0x0081, &val, READ_OP);
+ ec_read_write_reg(EC_HWM_LDN, 0x0027, &val, READ_OP);
+
+ ec_check_mbox_and_int_status(0x00, 0x01);
+
+ prepare_for_hwm_ec_sequence(0, &val_2fc);
+
+ if (chassis_type != 0xff) {
+ printk(BIOS_DEBUG, "Performing HWM init for chassis %d\n", chassis_type);
+ switch (chassis_type) {
+ case 3:
+ ec_hwm_init_late(ec_hwm_chassis3, ARRAY_SIZE(ec_hwm_chassis3));
+ break;
+ case 4:
+ ec_hwm_init_late(ec_hwm_chassis4, ARRAY_SIZE(ec_hwm_chassis4));
+ break;
+ case 5:
+ ec_hwm_init_late(ec_hwm_chassis5, ARRAY_SIZE(ec_hwm_chassis5));
+ break;
+ case 6:
+ ec_hwm_init_late(ec_hwm_chassis6, ARRAY_SIZE(ec_hwm_chassis6));
+ break;
+ }
+ }
+
+ if (CONFIG_MAX_CPUS > 2) {
+ val = 0x30;
+ ec_read_write_reg(EC_HWM_LDN, 0x009e, &val, WRITE_OP);
+ ec_read_write_reg(EC_HWM_LDN, 0x00ea, &val, READ_OP);
+ ec_read_write_reg(EC_HWM_LDN, 0x00eb, &val, WRITE_OP);
+ }
+
+ ec_read_write_reg(EC_HWM_LDN, 0x02fc, &val_2fc, WRITE_OP);
+
+ unsigned int fan_speed_full = get_uint_option("fan_full_speed", 0);
+ if (fan_speed_full) {
+ printk(BIOS_INFO, "Will set up fans to run at full speed\n");
+ ec_read_write_reg(EC_HWM_LDN, 0x0080, &val, READ_OP);
+ val |= 0x60;
+ ec_read_write_reg(EC_HWM_LDN, 0x0080, &val, WRITE_OP);
+ ec_read_write_reg(EC_HWM_LDN, 0x0081, &val, READ_OP);
+ val |= 0x60;
+ ec_read_write_reg(EC_HWM_LDN, 0x0081, &val, WRITE_OP);
+ } else {
+ printk(BIOS_INFO, "Will set up fans for automatic control\n");
+ }
+
+ ec_read_write_reg(EC_HWM_LDN, 0x00b8, &val, READ_OP);
+
+
+ if (chassis_type == 4 || chassis_type == 5) {
+ ec_read_write_reg(EC_HWM_LDN, 0x0027, &val, READ_OP);
+ if (val == 0) {
+ printk(BIOS_INFO, "Applying HWM fix-up for MT/DT chassis\n");
+ ec_read_write_reg(EC_HWM_LDN, 0x00a0, &val, READ_OP);
+ val &= 0xfb;
+ ec_read_write_reg(EC_HWM_LDN, 0x00a0, &val, WRITE_OP);
+ ec_read_write_reg(EC_HWM_LDN, 0x00a1, &val, READ_OP);
+ val &= 0xfb;
+ ec_read_write_reg(EC_HWM_LDN, 0x00a1, &val, WRITE_OP);
+ ec_read_write_reg(EC_HWM_LDN, 0x00a2, &val, READ_OP);
+ val &= 0xfb;
+ ec_read_write_reg(EC_HWM_LDN, 0x00a2, &val, WRITE_OP);
+ val = 0x99;
+ ec_read_write_reg(EC_HWM_LDN, 0x008a, &val, WRITE_OP);
+ val = 0x47;
+ ec_read_write_reg(EC_HWM_LDN, 0x008b, &val, WRITE_OP);
+ val = 0x91;
+ ec_read_write_reg(EC_HWM_LDN, 0x008c, &val, WRITE_OP);
+ }
+ }
+
+ ec_read_write_reg(EC_HWM_LDN, 0x0049, &val, READ_OP);
+ val &= 0xf7;
+ ec_read_write_reg(EC_HWM_LDN, 0x0049, &val, WRITE_OP);
+
+ val = 0x6a;
+ if (chassis_type != 3)
+ ec_read_write_reg(EC_HWM_LDN, 0x0059, &val, WRITE_OP);
+ else
+ ec_read_write_reg(EC_HWM_LDN, 0x0057, &val, WRITE_OP);
+
+ ec_read_write_reg(EC_HWM_LDN, 0x0041, &val, READ_OP);
+ val |= 0x40;
+ ec_read_write_reg(EC_HWM_LDN, 0x0041, &val, WRITE_OP);
+
+ if (chassis_type == 3) {
+ ec_read_write_reg(EC_HWM_LDN, 0x0049, &val, READ_OP);
+ val |= 0x04;
+ } else {
+ ec_read_write_reg(EC_HWM_LDN, 0x0049, &val, READ_OP);
+ val |= 0x08;
+ }
+ ec_read_write_reg(EC_HWM_LDN, 0x0049, &val, WRITE_OP);
+
+ val = 0x0e;
+ ec_read_write_reg(EC_HWM_LDN, 0x007b, &val, WRITE_OP);
+ ec_read_write_reg(EC_HWM_LDN, 0x007c, &val, WRITE_OP);
+ val = 0x01;
+ ec_read_write_reg(EC_HWM_LDN, 0x007a, &val, WRITE_OP);
+}
diff --git a/src/mainboard/dell/snb_ivb_workstations/sch5545_ec_early.c b/src/mainboard/dell/snb_ivb_workstations/sch5545_ec_early.c
new file mode 100644
index 000000000000..fd5fbca17cc8
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/sch5545_ec_early.c
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <arch/io.h>
+#include <superio/smsc/sch5545/sch5545.h>
+#include <superio/smsc/sch5545/sch5545_emi.h>
+
+#include <baseboard/sch5545_ec.h>
+
+static uint16_t emi_bar;
+
+static const struct ec_val_reg ec_gpio_init_table[] = {
+ /*
+ * Probably some early GPIO initialization, setting GPIO functions.
+ * The LSBs in third column match the GPIO config registers offsets for
+ * non-default GPIOs.
+ */
+ { EC_GPIO_PP | EC_GPIO_FUNC1, 0x08cc }, /* GP063 (def) / KBDRST# */
+ { EC_GPIO_PP | EC_GPIO_FUNC1, 0x08d0 }, /* GP064 (def) / A20M */
+ { EC_GPIO_PP | EC_GPIO_FUNC1, 0x089c }, /* GP047 / TXD1 (def) */
+ { EC_GPIO_PP | EC_GPIO_FUNC1, 0x0878 }, /* GP036 (def) / SMBCLK1 */
+ { EC_GPIO_PP | EC_GPIO_FUNC1, 0x0880 }, /* GP040 (def) / SMBDAT1 */
+ { EC_GPIO_OD | EC_GPIO_FUNC1, 0x0884 }, /* GP041 (def) / IO_PME# */
+ { EC_GPIO_PP | EC_GPIO_FUNC1, 0x08e4 }, /* GP071 (def) / IO_SMI# */
+ { EC_GPIO_PP | EC_GPIO_FUNC1, 0x08e0 }, /* GP070 (def) / SPEAKER */
+ { EC_GPIO_PP | EC_GPIO_FUNC1, 0x0848 }, /* GP022 (def) / PWM1 */
+ { EC_GPIO_PP | EC_GPIO_FUNC1, 0x084c }, /* GP023 (def) / PWM2 */
+ { EC_GPIO_PP | EC_GPIO_FUNC1, 0x0850 }, /* GP024 (def) / PWM3 */
+ { EC_GPIO_PP | EC_GPIO_FUNC1, 0x083c }, /* GP017 / TACH1 (def) */
+ { EC_GPIO_PP | EC_GPIO_FUNC1, 0x0840 }, /* GP020 / TACH2 (def) */
+ { EC_GPIO_PP | EC_GPIO_FUNC1, 0x0844 }, /* GP021 / TACH3 (def) */
+ { EC_GPIO_PP | EC_GPIO_FUNC1, 0x0814 }, /* GP005 (def) / PECI_REQ# */
+};
+
+static const struct ec_val_reg ec_hwm_early_init_table[] = {
+ /* Probably some early hardware monitor initialization */
+ { 0xff, 0x0005 },
+ { 0x30, 0x00f0 },
+ { 0x10, 0x00f8 },
+ { 0x00, 0x00f9 },
+ { 0x00, 0x00fa },
+ { 0x00, 0x00fb },
+ { 0x00, 0x00ea },
+ { 0x00, 0x00eb },
+ { 0x7c, 0x00ef },
+ { 0x03, 0x006e },
+ { 0x51, 0x02d0 },
+ { 0x01, 0x02d2 },
+ { 0x12, 0x059a },
+ { 0x11, 0x059e },
+ { 0x14, 0x05a2 },
+ { 0x55, 0x05a3 },
+ { 0x01, 0x02db },
+ { 0x01, 0x0040 },
+};
+
+static void ec_read_write_reg_timeout(uint16_t ldn, uint8_t *val, uint16_t reg,
+ uint8_t rw_bit)
+{
+ uint16_t timeout = 0;
+ rw_bit &= 1;
+ sch5545_emi_ec2h_mailbox_clear();
+ sch5545_emi_ec_write16(0x8000, (ldn << 1) | 0x100 | rw_bit);
+
+ sch5545_emi_set_ec_addr(0x8004);
+
+ if (rw_bit)
+ outb(*val, emi_bar + SCH5545_EMI_EC_DATA);
+
+ outb(reg & 0xff, emi_bar + SCH5545_EMI_EC_DATA + 2);
+ outb((reg >> 8) & 0xff, emi_bar + SCH5545_EMI_EC_DATA + 3);
+ sch5545_emi_h2ec_mbox_write(1);
+
+ do {
+ timeout++;
+ if ((sch5545_emi_ec2h_mbox_read() & 1) != 0)
+ break;
+ } while (timeout < 0xfff);
+
+ sch5545_emi_set_int_src(0x11);
+ sch5545_emi_h2ec_mbox_write(0xc0);
+
+ if (!rw_bit)
+ *val = inb(emi_bar + SCH5545_EMI_EC_DATA);
+}
+
+static void ec_init_gpios(void)
+{
+ unsigned int i;
+ uint8_t val;
+
+ for (i = 0; i < ARRAY_SIZE(ec_gpio_init_table); i++) {
+ val = ec_gpio_init_table[i].val;
+ ec_read_write_reg_timeout(EC_GPIO_LDN, &val, ec_gpio_init_table[i].reg,
+ WRITE_OP);
+ }
+}
+
+static void ec_early_hwm_init(void)
+{
+ unsigned int i;
+ uint8_t val;
+
+ for (i = 0; i < ARRAY_SIZE(ec_hwm_early_init_table); i++) {
+ val = ec_hwm_early_init_table[i].val;
+ ec_read_write_reg_timeout(EC_HWM_LDN, &val, ec_hwm_early_init_table[i].reg,
+ WRITE_OP);
+ }
+}
+
+void sch5545_ec_early_init(void)
+{
+ emi_bar = sch5545_read_emi_bar(0x2e);
+
+ ec_init_gpios();
+ ec_early_hwm_init();
+}
diff --git a/src/mainboard/dell/snb_ivb_workstations/smihandler.c b/src/mainboard/dell/snb_ivb_workstations/smihandler.c
new file mode 100644
index 000000000000..3ed0d1148349
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/smihandler.c
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <stdint.h>
+#include <arch/io.h>
+#include <cpu/x86/smm.h>
+#include <superio/smsc/sch5545/sch5545.h>
+
+int mainboard_smi_apmc(u8 data)
+{
+ u8 val;
+ switch (data) {
+ case APM_CNT_ACPI_ENABLE:
+ /* Enable wake on PS2 */
+ val = inb(SCH5545_RUNTIME_REG_BASE + SCH5545_RR_PME_EN1);
+ val |= (SCH5545_KBD_PME_EN | SCH5545_MOUSE_PME_EN);
+ outb(val, SCH5545_RUNTIME_REG_BASE + SCH5545_RR_PME_EN1);
+ /* Clear pending and enable PMEs */
+ outb(SCH5545_GLOBAL_PME_STS, SCH5545_RUNTIME_REG_BASE + SCH5545_RR_PME_STS);
+ outb(SCH5545_GLOBAL_PME_EN, SCH5545_RUNTIME_REG_BASE + SCH5545_RR_PME_EN);
+ break;
+ case APM_CNT_ACPI_DISABLE:
+ /* Disable wake on PS2 */
+ val = inb(SCH5545_RUNTIME_REG_BASE + SCH5545_RR_PME_EN1);
+ val &= ~(SCH5545_KBD_PME_EN | SCH5545_MOUSE_PME_EN);
+ outb(val, SCH5545_RUNTIME_REG_BASE + SCH5545_RR_PME_EN1);
+ /* Clear pending and disable PMEs */
+ outb(SCH5545_GLOBAL_PME_STS, SCH5545_RUNTIME_REG_BASE + SCH5545_RR_PME_STS);
+ outb(0, SCH5545_RUNTIME_REG_BASE + SCH5545_RR_PME_EN);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
diff --git a/src/mainboard/dell/snb_ivb_workstations/variants/baseboard/devicetree.cb b/src/mainboard/dell/snb_ivb_workstations/variants/baseboard/devicetree.cb
new file mode 100644
index 000000000000..e614f1e52319
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/variants/baseboard/devicetree.cb
@@ -0,0 +1,91 @@
+chip northbridge/intel/sandybridge
+ device cpu_cluster 0 on
+ chip cpu/intel/model_206ax
+ register "acpi_c1" = "1"
+ register "acpi_c2" = "3"
+ register "acpi_c3" = "5"
+ register "tcc_offset" = "5" # TCC of 95C
+ device lapic 0 on end
+ device lapic 0xacac off end
+ end
+ end
+ device domain 0 on
+
+ device pci 00.0 on end # Host bridge Host bridge
+ device pci 01.0 on # PEG1 (blue slot1)
+ smbios_slot_desc "SlotTypePciExpressGen3X16" "SlotLengthLong" "SLOT1" "SlotDataBusWidth16X"
+ end
+ device pci 02.0 on end # Internal graphics VGA controller
+ device pci 06.0 off end # PEG2
+
+ chip southbridge/intel/bd82x6x # Intel Series 7 Panther Point PCH
+ register "gpe0_en" = "0x00002a46"
+ register "alt_gp_smi_en" = "0x0004"
+ register "gpi2_routing" = "1"
+ register "gpi12_routing" = "2"
+ register "gen1_dec" = "0x007c0a01"
+ register "gen2_dec" = "0x007c0901"
+ register "gen3_dec" = "0x003c07e1"
+ register "gen4_dec" = "0x001c0901"
+ register "pcie_port_coalesce" = "true"
+ register "sata_interface_speed_support" = "0x3"
+ register "spi_lvscc" = "0x2005"
+ register "spi_uvscc" = "0x2005"
+ register "superspeed_capable_ports" = "0x0000000f"
+ register "xhci_overcurrent_mapping" = "0x08040201"
+ register "xhci_switchable_ports" = "0x0000000f"
+ device pci 14.0 on end # USB 3.0 Controller
+ device pci 16.0 off end # Management Engine Interface 1
+ device pci 16.1 off end # Management Engine Interface 2
+ device pci 16.2 off end # Management Engine IDE-R
+ device pci 16.3 off end # Management Engine KT
+ device pci 19.0 on end # Intel Gigabit Ethernet
+ device pci 1a.0 on end # USB2 EHCI #2
+ device pci 1b.0 on end # High Definition Audio controller
+ device pci 1c.0 off end # PCIe Port #1
+ device pci 1c.1 off end # PCIe Port #2
+ device pci 1c.2 off end # PCIe Port #3
+ device pci 1c.3 off end # PCIe Port #4
+ device pci 1c.4 off end # PCIe Port #5
+ device pci 1c.5 off end # PCIe Port #6
+ device pci 1c.6 off end # PCIe Port #7
+ device pci 1c.7 off end # PCIe Port #8
+ device pci 1d.0 on end # USB2 EHCI #1
+ device pci 1e.0 off end # PCI bridge
+ device pci 1f.0 on # LPC bridge
+ chip drivers/pc80/tpm
+ device pnp 0c31.0 on end
+ end
+ chip superio/smsc/sch5545
+ device pnp 2e.c on # LPC
+ io 0x60 = 0x2e
+ end
+ device pnp 2e.0 on # EMI
+ io 0x60 = 0xa40
+ end
+ device pnp 2e.1 on # KBC/PS2M
+ io 0x60 = 0x60
+ irq 0x70 = 1
+ irq 0x72 = 12
+ end
+ device pnp 2e.7 on # UART1
+ io 0x60 = 0x3f8
+ irq 0x70 = 4
+ irq 0xf0 = 0x02
+ end
+ device pnp 2e.8 off end # UART2
+ device pnp 2e.a on # Runtime registers
+ io 0x60 = 0xa00
+ irq 0x70 = 9 # PME
+ end
+ device pnp 2e.b off end # Floppy
+ device pnp 2e.11 off end # PP
+ end
+ end
+ device pci 1f.2 on end # SATA Controller 1
+ device pci 1f.3 on end # SMBus
+ device pci 1f.5 off end # SATA Controller 2
+ device pci 1f.6 on end # Thermal
+ end
+ end
+end
diff --git a/src/mainboard/dell/snb_ivb_workstations/variants/baseboard/include/baseboard/sch5545_ec.h b/src/mainboard/dell/snb_ivb_workstations/variants/baseboard/include/baseboard/sch5545_ec.h
new file mode 100644
index 000000000000..80d978e9db7f
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/variants/baseboard/include/baseboard/sch5545_ec.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef SCH5545_BOARD_EC_H
+#define SCH5545_BOARD_EC_H
+
+#include <stdint.h>
+
+#define READ_OP 0
+#define WRITE_OP 1
+
+#define EC_HWM_LDN 1
+#define EC_GPIO_LDN 2
+
+/* EC GPIO configuration */
+#define EC_GPIO_PP (0 << 0)
+#define EC_GPIO_OD (1 << 0)
+#define EC_GPIO_FUNC0 (0 << 4)
+#define EC_GPIO_FUNC1 (1 << 4)
+#define EC_GPIO_FUNC2 (2 << 4)
+#define EC_GPIO_FUNC3 (3 << 4)
+
+struct ec_val_reg {
+ uint8_t val;
+ uint16_t reg;
+};
+
+enum {
+ TDP_16 = 0x10,
+ TDP_32 = 0x20,
+ TDP_COMMON = 0xff,
+};
+
+typedef struct ec_val_reg_tdp {
+ uint8_t val;
+ uint16_t reg;
+ uint8_t tdp;
+} ec_chassis_tdp_t;
+
+uint16_t sch5545_get_ec_fw_version(void);
+void sch5545_update_ec_firmware(uint16_t ec_version);
+void sch5545_ec_early_init(void);
+void sch5545_ec_hwm_early_init(void);
+void sch5545_ec_hwm_init(void *unused);
+
+#endif // SCH5545_BOARD_EC_H
diff --git a/src/mainboard/dell/snb_ivb_workstations/variants/optiplex_9010_sff/data.vbt b/src/mainboard/dell/snb_ivb_workstations/variants/optiplex_9010_sff/data.vbt
new file mode 100644
index 000000000000..d1a95e86329a
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/variants/optiplex_9010_sff/data.vbt
Binary files differ
diff --git a/src/mainboard/dell/snb_ivb_workstations/variants/optiplex_9010_sff/hda_verb.c b/src/mainboard/dell/snb_ivb_workstations/variants/optiplex_9010_sff/hda_verb.c
new file mode 100644
index 000000000000..eab4ba9053f2
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/variants/optiplex_9010_sff/hda_verb.c
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <device/azalia_device.h>
+
+const u32 cim_verb_data[] = {
+ 0x10ec0269, /* Codec Vendor / Device ID: Realtek */
+ 0x1028052c, /* Subsystem ID */
+
+ 11, /* Number of 4 dword sets */
+
+ AZALIA_SUBVENDOR(0, 0x1028052c),
+ AZALIA_PIN_CFG(0, 0x12, 0x411111f0),
+ AZALIA_PIN_CFG(0, 0x14, 0x99130110),
+ AZALIA_PIN_CFG(0, 0x17, 0x411111f0),
+ AZALIA_PIN_CFG(0, 0x18, 0x02a19830),
+ AZALIA_PIN_CFG(0, 0x19, 0x01a19840),
+ AZALIA_PIN_CFG(0, 0x1a, 0x411111f0),
+ AZALIA_PIN_CFG(0, 0x1b, 0x01014020),
+ AZALIA_PIN_CFG(0, 0x1d, 0x411111f0),
+ AZALIA_PIN_CFG(0, 0x1e, 0x411111f0),
+ AZALIA_PIN_CFG(0, 0x21, 0x0221402f),
+
+ 0x80862806, /* Codec Vendor / Device ID: Intel */
+ 0x80860101, /* Subsystem ID */
+
+ 4, /* Number of 4 dword sets */
+
+ AZALIA_SUBVENDOR(3, 0x80860101),
+ AZALIA_PIN_CFG(3, 0x05, 0x18560010),
+ AZALIA_PIN_CFG(3, 0x06, 0x18560020),
+ AZALIA_PIN_CFG(3, 0x07, 0x58560030),
+};
+
+const u32 pc_beep_verbs[0] = {};
+
+AZALIA_ARRAY_SIZES;
diff --git a/src/mainboard/dell/snb_ivb_workstations/variants/optiplex_9010_sff/include/variant/sch5545_ec_tables.h b/src/mainboard/dell/snb_ivb_workstations/variants/optiplex_9010_sff/include/variant/sch5545_ec_tables.h
new file mode 100644
index 000000000000..02096b7edbde
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/variants/optiplex_9010_sff/include/variant/sch5545_ec_tables.h
@@ -0,0 +1,237 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef SCH5545_BOARD_EC_TABLE_H
+#define SCH5545_BOARD_EC_TABLE_H
+
+#include <baseboard/sch5545_ec.h>
+
+static const ec_chassis_tdp_t ec_hwm_chassis3[] = {
+ { 0x33, 0x0005, TDP_COMMON },
+ { 0x2f, 0x0018, TDP_COMMON },
+ { 0x2f, 0x0019, TDP_COMMON },
+ { 0x2f, 0x001a, TDP_COMMON },
+ { 0x00, 0x0080, TDP_COMMON },
+ { 0x00, 0x0081, TDP_COMMON },
+ { 0xbb, 0x0083, TDP_COMMON },
+ { 0x8a, 0x0085, TDP_16 },
+ { 0x2c, 0x0086, TDP_16 },
+ { 0x66, 0x008a, TDP_16 },
+ { 0x5b, 0x008b, TDP_16 },
+ { 0x65, 0x0090, TDP_COMMON },
+ { 0x70, 0x0091, TDP_COMMON },
+ { 0x86, 0x0092, TDP_COMMON },
+ { 0xa4, 0x0096, TDP_COMMON },
+ { 0xa4, 0x0097, TDP_COMMON },
+ { 0xa4, 0x0098, TDP_COMMON },
+ { 0xa4, 0x009b, TDP_COMMON },
+ { 0x0e, 0x00a0, TDP_COMMON },
+ { 0x0e, 0x00a1, TDP_COMMON },
+ { 0x7c, 0x00ae, TDP_COMMON },
+ { 0x86, 0x00af, TDP_COMMON },
+ { 0x95, 0x00b0, TDP_COMMON },
+ { 0x9a, 0x00b3, TDP_COMMON },
+ { 0x08, 0x00b6, TDP_COMMON },
+ { 0x08, 0x00b7, TDP_COMMON },
+ { 0x64, 0x00ea, TDP_COMMON },
+ { 0xff, 0x00ef, TDP_COMMON },
+ { 0x15, 0x00f8, TDP_COMMON },
+ { 0x00, 0x00f9, TDP_COMMON },
+ { 0x30, 0x00f0, TDP_COMMON },
+ { 0x01, 0x00fd, TDP_COMMON },
+ { 0x88, 0x01a1, TDP_COMMON },
+ { 0x08, 0x01a2, TDP_COMMON },
+ { 0x08, 0x01b1, TDP_COMMON },
+ { 0x94, 0x01be, TDP_COMMON },
+ { 0x94, 0x0280, TDP_16 },
+ { 0x11, 0x0281, TDP_16 },
+ { 0x03, 0x0282, TDP_COMMON },
+ { 0x0a, 0x0283, TDP_COMMON },
+ { 0x80, 0x0284, TDP_COMMON },
+ { 0x03, 0x0285, TDP_COMMON },
+ { 0x68, 0x0288, TDP_16 },
+ { 0x10, 0x0289, TDP_16 },
+ { 0x03, 0x028a, TDP_COMMON },
+ { 0x0a, 0x028b, TDP_COMMON },
+ { 0x80, 0x028c, TDP_COMMON },
+ { 0x03, 0x028d, TDP_COMMON },
+};
+
+static const ec_chassis_tdp_t ec_hwm_chassis4[] = {
+ { 0x33, 0x0005, TDP_COMMON },
+ { 0x2f, 0x0018, TDP_COMMON },
+ { 0x2f, 0x0019, TDP_COMMON },
+ { 0x2f, 0x001a, TDP_COMMON },
+ { 0x00, 0x0080, TDP_COMMON },
+ { 0x00, 0x0081, TDP_COMMON },
+ { 0xbb, 0x0083, TDP_COMMON },
+ { 0x99, 0x0085, TDP_32 },
+ { 0x98, 0x0085, TDP_16 },
+ { 0xbc, 0x0086, TDP_32 },
+ { 0x1c, 0x0086, TDP_16 },
+ { 0x39, 0x008a, TDP_32 },
+ { 0x3d, 0x008a, TDP_16 },
+ { 0x40, 0x008b, TDP_32 },
+ { 0x43, 0x008b, TDP_16 },
+ { 0x68, 0x0090, TDP_COMMON },
+ { 0x5e, 0x0091, TDP_COMMON },
+ { 0x86, 0x0092, TDP_COMMON },
+ { 0xa4, 0x0096, TDP_COMMON },
+ { 0xa4, 0x0097, TDP_COMMON },
+ { 0xa4, 0x0098, TDP_COMMON },
+ { 0xa4, 0x009b, TDP_COMMON },
+ { 0x0c, 0x00a0, TDP_COMMON },
+ { 0x0c, 0x00a1, TDP_COMMON },
+ { 0x72, 0x00ae, TDP_COMMON },
+ { 0x7c, 0x00af, TDP_COMMON },
+ { 0x9a, 0x00b0, TDP_COMMON },
+ { 0x7c, 0x00b3, TDP_COMMON },
+ { 0x08, 0x00b6, TDP_COMMON },
+ { 0x08, 0x00b7, TDP_COMMON },
+ { 0x64, 0x00ea, TDP_COMMON },
+ { 0xff, 0x00ef, TDP_COMMON },
+ { 0x15, 0x00f8, TDP_COMMON },
+ { 0x00, 0x00f9, TDP_COMMON },
+ { 0x30, 0x00f0, TDP_COMMON },
+ { 0x01, 0x00fd, TDP_COMMON },
+ { 0x88, 0x01a1, TDP_COMMON },
+ { 0x08, 0x01a2, TDP_COMMON },
+ { 0x08, 0x01b1, TDP_COMMON },
+ { 0x90, 0x01be, TDP_COMMON },
+ { 0x94, 0x0280, TDP_32 },
+ { 0x11, 0x0281, TDP_32 },
+ { 0x68, 0x0280, TDP_16 },
+ { 0x10, 0x0281, TDP_16 },
+ { 0x03, 0x0282, TDP_COMMON },
+ { 0x0a, 0x0283, TDP_COMMON },
+ { 0x80, 0x0284, TDP_COMMON },
+ { 0x03, 0x0285, TDP_COMMON },
+ { 0xa0, 0x0288, TDP_32 },
+ { 0x0f, 0x0289, TDP_32 },
+ { 0xd8, 0x0288, TDP_16 },
+ { 0x0e, 0x0289, TDP_16 },
+ { 0x03, 0x028a, TDP_COMMON },
+ { 0x0a, 0x028b, TDP_COMMON },
+ { 0x80, 0x028c, TDP_COMMON },
+ { 0x03, 0x028d, TDP_COMMON },
+};
+
+static const ec_chassis_tdp_t ec_hwm_chassis5[] = {
+ { 0x33, 0x0005, TDP_COMMON },
+ { 0x2f, 0x0018, TDP_COMMON },
+ { 0x2f, 0x0019, TDP_COMMON },
+ { 0x2f, 0x001a, TDP_COMMON },
+ { 0x00, 0x0080, TDP_COMMON },
+ { 0x00, 0x0081, TDP_COMMON },
+ { 0xbb, 0x0083, TDP_COMMON },
+ { 0x89, 0x0085, TDP_32 },
+ { 0x99, 0x0085, TDP_16 },
+ { 0x9c, 0x0086, TDP_COMMON },
+ { 0x39, 0x008a, TDP_32 },
+ { 0x42, 0x008a, TDP_16 },
+ { 0x6b, 0x008b, TDP_32 },
+ { 0x74, 0x008b, TDP_16 },
+ { 0x5e, 0x0091, TDP_COMMON },
+ { 0x86, 0x0092, TDP_COMMON },
+ { 0xa4, 0x0096, TDP_COMMON },
+ { 0xa4, 0x0097, TDP_COMMON },
+ { 0xa4, 0x0098, TDP_COMMON },
+ { 0xa4, 0x009b, TDP_COMMON },
+ { 0x0c, 0x00a0, TDP_COMMON },
+ { 0x0c, 0x00a1, TDP_COMMON },
+ { 0x7c, 0x00ae, TDP_COMMON },
+ { 0x7c, 0x00af, TDP_COMMON },
+ { 0x9a, 0x00b0, TDP_COMMON },
+ { 0x7c, 0x00b3, TDP_COMMON },
+ { 0x08, 0x00b6, TDP_COMMON },
+ { 0x08, 0x00b7, TDP_COMMON },
+ { 0x64, 0x00ea, TDP_COMMON },
+ { 0xff, 0x00ef, TDP_COMMON },
+ { 0x15, 0x00f8, TDP_COMMON },
+ { 0x00, 0x00f9, TDP_COMMON },
+ { 0x30, 0x00f0, TDP_COMMON },
+ { 0x01, 0x00fd, TDP_COMMON },
+ { 0x88, 0x01a1, TDP_COMMON },
+ { 0x08, 0x01a2, TDP_COMMON },
+ { 0x08, 0x01b1, TDP_COMMON },
+ { 0x90, 0x01be, TDP_COMMON },
+ { 0x94, 0x0280, TDP_32 },
+ { 0x11, 0x0281, TDP_32 },
+ { 0x3c, 0x0280, TDP_16 },
+ { 0x0f, 0x0281, TDP_16 },
+ { 0x03, 0x0282, TDP_COMMON },
+ { 0x0a, 0x0283, TDP_COMMON },
+ { 0x80, 0x0284, TDP_COMMON },
+ { 0x03, 0x0285, TDP_COMMON },
+ { 0x60, 0x0288, TDP_32 },
+ { 0x09, 0x0289, TDP_32 },
+ { 0x98, 0x0288, TDP_16 },
+ { 0x08, 0x0289, TDP_16 },
+ { 0x03, 0x028a, TDP_COMMON },
+ { 0x0a, 0x028b, TDP_COMMON },
+ { 0x80, 0x028c, TDP_COMMON },
+ { 0x03, 0x028d, TDP_COMMON },
+};
+
+static const ec_chassis_tdp_t ec_hwm_chassis6[] = {
+ { 0x33, 0x0005, TDP_COMMON },
+ { 0x2f, 0x0018, TDP_COMMON },
+ { 0x2f, 0x0019, TDP_COMMON },
+ { 0x2f, 0x001a, TDP_COMMON },
+ { 0x00, 0x0080, TDP_COMMON },
+ { 0x00, 0x0081, TDP_COMMON },
+ { 0xbb, 0x0083, TDP_COMMON },
+ { 0x99, 0x0085, TDP_32 },
+ { 0x98, 0x0085, TDP_16 },
+ { 0xdc, 0x0086, TDP_32 },
+ { 0x9c, 0x0086, TDP_16 },
+ { 0x3d, 0x008a, TDP_32 },
+ { 0x43, 0x008a, TDP_16 },
+ { 0x4e, 0x008b, TDP_32 },
+ { 0x47, 0x008b, TDP_16 },
+ { 0x6d, 0x0090, TDP_COMMON },
+ { 0x5f, 0x0091, TDP_32 },
+ { 0x61, 0x0091, TDP_16 },
+ { 0x86, 0x0092, TDP_COMMON },
+ { 0xa4, 0x0096, TDP_COMMON },
+ { 0xa4, 0x0097, TDP_COMMON },
+ { 0xa4, 0x0098, TDP_COMMON },
+ { 0xa4, 0x009b, TDP_COMMON },
+ { 0x0e, 0x00a0, TDP_COMMON },
+ { 0x0e, 0x00a1, TDP_COMMON },
+ { 0x7c, 0x00ae, TDP_COMMON },
+ { 0x7c, 0x00af, TDP_COMMON },
+ { 0x98, 0x00b0, TDP_32 },
+ { 0x9a, 0x00b0, TDP_16 },
+ { 0x9a, 0x00b3, TDP_COMMON },
+ { 0x08, 0x00b6, TDP_COMMON },
+ { 0x08, 0x00b7, TDP_COMMON },
+ { 0x64, 0x00ea, TDP_COMMON },
+ { 0xff, 0x00ef, TDP_COMMON },
+ { 0x15, 0x00f8, TDP_COMMON },
+ { 0x00, 0x00f9, TDP_COMMON },
+ { 0x30, 0x00f0, TDP_COMMON },
+ { 0x01, 0x00fd, TDP_COMMON },
+ { 0x88, 0x01a1, TDP_COMMON },
+ { 0x08, 0x01a2, TDP_COMMON },
+ { 0x08, 0x01b1, TDP_COMMON },
+ { 0x97, 0x01be, TDP_32 },
+ { 0x95, 0x01be, TDP_16 },
+ { 0x68, 0x0280, TDP_32 },
+ { 0x10, 0x0281, TDP_32 },
+ { 0xd8, 0x0280, TDP_16 },
+ { 0x0e, 0x0281, TDP_16 },
+ { 0x03, 0x0282, TDP_COMMON },
+ { 0x0a, 0x0283, TDP_COMMON },
+ { 0x80, 0x0284, TDP_COMMON },
+ { 0x03, 0x0285, TDP_COMMON },
+ { 0xe4, 0x0288, TDP_32 },
+ { 0x0c, 0x0289, TDP_32 },
+ { 0x10, 0x0288, TDP_16 },
+ { 0x0e, 0x0289, TDP_16 },
+ { 0x03, 0x028a, TDP_COMMON },
+ { 0x0a, 0x028b, TDP_COMMON },
+ { 0x80, 0x028c, TDP_COMMON },
+ { 0x03, 0x028d, TDP_COMMON },
+};
+
+#endif // SCH5545_BOARD_EC_TABLE_H
diff --git a/src/mainboard/dell/snb_ivb_workstations/variants/optiplex_9010_sff/overridetree.cb b/src/mainboard/dell/snb_ivb_workstations/variants/optiplex_9010_sff/overridetree.cb
new file mode 100644
index 000000000000..30167f9e9a0e
--- /dev/null
+++ b/src/mainboard/dell/snb_ivb_workstations/variants/optiplex_9010_sff/overridetree.cb
@@ -0,0 +1,14 @@
+chip northbridge/intel/sandybridge
+ device domain 0 on
+ subsystemid 0x1028 0x052c inherit
+ chip southbridge/intel/bd82x6x # Intel Series 7 Panther Point PCH
+ register "sata_port_map" = "0x7"
+ device pci 1c.4 on # PCIe Port #5
+ smbios_slot_desc "SlotTypePciExpressGen3X16" "SlotLengthLong" "SLOT2" "SlotDataBusWidth4X"
+ end
+ device pci 1c.5 on end # PCIe Port #6
+ device pci 1c.6 on end # PCIe Port #7
+ device pci 1c.7 on end # PCIe Port #8
+ end
+ end
+end