From 72f06ca554e6f7b155a6b4e2b8ce57942288ac2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20=C5=BBygowski?= Date: Mon, 13 Apr 2020 21:42:24 +0200 Subject: [PATCH] mb/dell/optiplex_9010: Add Dell OptiPlex 9010 SFF support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on the autoport. The OptiPlex 9010 comes in four different sizes: MT, DT, SFF and USFF. Tested on SFF only. The other PCBs are slightly different, but they are designed with intercompatibility in mind. With small devicetree overrides it should work on OptiPlex 7010 and other OptiPlex 9010 variants as well. Signed-off-by: Michał Żygowski Change-Id: I88d65cae30d08ca727d86d930707c2be25a527cf Reviewed-on: https://review.coreboot.org/c/coreboot/+/40351 Reviewed-by: Felix Held Tested-by: build bot (Jenkins) --- .../mainboard/dell/optiplex_9010.jpg | Bin 0 -> 80412 bytes Documentation/mainboard/dell/optiplex_9010.md | 147 ++++ Documentation/mainboard/index.md | 4 + configs/config.dell_optiplex_9010_sff | 9 + src/mainboard/dell/Kconfig | 16 + src/mainboard/dell/Kconfig.name | 2 + src/mainboard/dell/optiplex_9010/Kconfig | 69 ++ src/mainboard/dell/optiplex_9010/Kconfig.name | 2 + src/mainboard/dell/optiplex_9010/Makefile.inc | 22 + src/mainboard/dell/optiplex_9010/acpi/ec.asl | 0 .../dell/optiplex_9010/acpi/platform.asl | 54 ++ .../dell/optiplex_9010/acpi/superio.asl | 13 + .../dell/optiplex_9010/acpi_tables.c | 9 + .../dell/optiplex_9010/board_info.txt | 6 + src/mainboard/dell/optiplex_9010/cmos.default | 7 + src/mainboard/dell/optiplex_9010/cmos.layout | 95 +++ src/mainboard/dell/optiplex_9010/data.vbt | Bin 0 -> 4281 bytes .../dell/optiplex_9010/devicetree.cb | 99 +++ src/mainboard/dell/optiplex_9010/dsdt.asl | 32 + src/mainboard/dell/optiplex_9010/early_init.c | 47 ++ .../dell/optiplex_9010/gma-mainboard.ads | 19 + src/mainboard/dell/optiplex_9010/gpio.c | 208 +++++ src/mainboard/dell/optiplex_9010/hda_verb.c | 36 + src/mainboard/dell/optiplex_9010/mainboard.c | 191 +++++ src/mainboard/dell/optiplex_9010/romstage.c | 53 ++ src/mainboard/dell/optiplex_9010/sch5545_ec.c | 726 ++++++++++++++++++ src/mainboard/dell/optiplex_9010/sch5545_ec.h | 28 + .../dell/optiplex_9010/sch5545_ec_early.c | 116 +++ src/mainboard/dell/optiplex_9010/smihandler.c | 47 ++ 29 files changed, 2057 insertions(+) create mode 100644 Documentation/mainboard/dell/optiplex_9010.jpg create mode 100644 Documentation/mainboard/dell/optiplex_9010.md create mode 100644 configs/config.dell_optiplex_9010_sff create mode 100644 src/mainboard/dell/Kconfig create mode 100644 src/mainboard/dell/Kconfig.name create mode 100644 src/mainboard/dell/optiplex_9010/Kconfig create mode 100644 src/mainboard/dell/optiplex_9010/Kconfig.name create mode 100644 src/mainboard/dell/optiplex_9010/Makefile.inc create mode 100644 src/mainboard/dell/optiplex_9010/acpi/ec.asl create mode 100644 src/mainboard/dell/optiplex_9010/acpi/platform.asl create mode 100644 src/mainboard/dell/optiplex_9010/acpi/superio.asl create mode 100644 src/mainboard/dell/optiplex_9010/acpi_tables.c create mode 100644 src/mainboard/dell/optiplex_9010/board_info.txt create mode 100644 src/mainboard/dell/optiplex_9010/cmos.default create mode 100644 src/mainboard/dell/optiplex_9010/cmos.layout create mode 100644 src/mainboard/dell/optiplex_9010/data.vbt create mode 100644 src/mainboard/dell/optiplex_9010/devicetree.cb create mode 100644 src/mainboard/dell/optiplex_9010/dsdt.asl create mode 100644 src/mainboard/dell/optiplex_9010/early_init.c create mode 100644 src/mainboard/dell/optiplex_9010/gma-mainboard.ads create mode 100644 src/mainboard/dell/optiplex_9010/gpio.c create mode 100644 src/mainboard/dell/optiplex_9010/hda_verb.c create mode 100644 src/mainboard/dell/optiplex_9010/mainboard.c create mode 100644 src/mainboard/dell/optiplex_9010/romstage.c create mode 100644 src/mainboard/dell/optiplex_9010/sch5545_ec.c create mode 100644 src/mainboard/dell/optiplex_9010/sch5545_ec.h create mode 100644 src/mainboard/dell/optiplex_9010/sch5545_ec_early.c create mode 100644 src/mainboard/dell/optiplex_9010/smihandler.c diff --git a/Documentation/mainboard/dell/optiplex_9010.jpg b/Documentation/mainboard/dell/optiplex_9010.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a5978acace499b10ced0559f05eb9489f0041d70 GIT binary patch literal 80412 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

1|f#1AtO}Ob%=y^+B^-B7a*HAz>q6 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 I0RHd)*<{#ALI3~& literal 0 HcmV?d00001 diff --git a/Documentation/mainboard/dell/optiplex_9010.md b/Documentation/mainboard/dell/optiplex_9010.md new file mode 100644 index 0000000000..f22623d9d7 --- /dev/null +++ b/Documentation/mainboard/dell/optiplex_9010.md @@ -0,0 +1,147 @@ +# Dell OptiPlex 9010 + +This page describes how to run coreboot on Dell OptiPlex 9010 SFF. + +![](optiplex_9010.jpg) + +## Technology + +```eval_rst ++------------+---------------------------------------------------------------+ +| CPU | Intel Core 2nd Gen (Sandybridge) or 3rd Gen (Ivybridge) | ++------------+---------------------------------------------------------------+ +| DRAM | Up to 4 DIMM slots, up to 32GB 1600MHz non-ECC DDR3 SDRAM | ++------------+---------------------------------------------------------------+ +| Chipset | Intel Q77 Express | ++------------+---------------------------------------------------------------+ +| Super I/O | SMSC SCH5545 (or SCH5544) with Environmental Controller | ++------------+---------------------------------------------------------------+ +| TPM | ST Microelectronics ST33ZP24 | ++------------+---------------------------------------------------------------+ +| Boot | From USB, SATA, NVMe (using PCIe x4 expansion card) | ++------------+---------------------------------------------------------------+ +| Power | 200W-275W PSU | ++------------+---------------------------------------------------------------+ +``` + +More specifications on [Dell OptiPlex 9010 specifications]. + +## Required proprietary blobs + +```eval_rst ++------------------+---------------------------------+---------------------+ +| Binary file | Apply | Required / Optional | ++==================+=================================+=====================+ +| smsc_sch5545.bin | SMSC SCH5545 EC | Optional | ++------------------+---------------------------------+---------------------+ +| microcode | CPU microcode | Required | ++------------------+---------------------------------+---------------------+ +``` + +Microcode updates are automatically included into the coreboot image by build +system from the `3rdparty/intel-microcode` submodule. + +SMSC SC5545 EC firmware is optional, however lack of the binary will result in +EC malfunction after power failure and fans running at full speed. The blob can +be extracted from original firmware. It should be located under a file with +GUID D386BEB8-4B54-4E69-94F5-06091F67E0D3, raw section. The file begins with a +signature `SMSCUBIM`. The easiest way to do this is to use [UEFITool] and +`Extract body` option on the raw section of the file. + +## Flashing coreboot + +```eval_rst ++---------------------+--------------------------+ +| Type | Value | ++=====================+==========================+ +| Socketed flash | no | ++---------------------+--------------------------+ +| Model | MX25L6406E/MX25L3206E | ++---------------------+--------------------------+ +| Size | 8 + 4 MiB | ++---------------------+--------------------------+ +| Package | SOIC-16 + SOIC-8 | ++---------------------+--------------------------+ +| Write protection | chipset PRR | ++---------------------+--------------------------+ +| Dual BIOS feature | no | ++---------------------+--------------------------+ +| Internal flashing | yes | ++---------------------+--------------------------+ +``` + +### Internal programming + +The SPI flash can be accessed using [flashrom]. + + flashrom -p internal -w coreboot.rom --ifd -i bios + +Internal programming will not work when migrating from original UEFI firmware. +One will have to short the SERVICE_MODE jumper to enable HMRFPO and then boot +the machine to flash it. + +### External programming + +The external access to flash chip is available through standard SOP-8 clip +and/or SOP-16 clip on the right side of the CPU fan (marked on the board +image). The voltage of SPI flash is 3.3V. + +There are no restrictions as to the programmer device. It is only recommended +to flash firmware without supplying power. There are no diodes connected to the +flash chips. External programming can be performed, for example using OrangePi +and Armbian. You can use linux_spi driver which provides communication with SPI +devices. Example command to program SPI flash with OrangePi using linux_spi: + + flashrom -w coreboot.rom -p linux_spi:dev=/dev/spidev1.0,spispeed=16000 + +## Schematics + +There are no schematics for SFF, but if one looks for MT/DT schematics, they +can be found publicly. Most of the schematics should match the SFF (although +MT/DT has additional PCIe and PCI slot). + +## Known issues + +- There seems to be a problem with DRAM clearing on reboot. The SSKPD register + still contains 0xCAFE which leads to reset loop. + +## Untested + +Not all mainboard's peripherals and functions were tested because of lack of +the cables or not being populated on the board case. + +- Internal USB 2.0 header +- Wake from S3 using serial port +- Wake-on-Lan from ACPI S4/S5 + +## Working + +- USB 3.0 and 2.0 rear and front ports (SeaBIOS and Linux 4.19) +- Gigabit Ethernet +- VGA and 2x DP port using libgfxinit +- flashrom +- PCIe x1 WiFi in PCIe x4 slot +- NVMe PCIe x4 using PCIe x4 expansion card +- PCIe x16 PEG port using Dell Radeon HD 7570 +- SATA ports (SATA disks and DVD) +- Super I/O serial port 0 (RS232 DB9 connector on the rear side) +- SMBus (reading SPD from DIMMs) +- CPU initialization using Intel i7-3770 +- Sandy Bridge/Ivy Bridge native RAM initialization +- SeaBIOS payload (version rel-1.13.0) +- PS/2 keyboard and mouse (including wake support) +- LPC debug header (requires soldering of the pin header and shorting RF24 for + LPC clock) +- USB debug dongle (the most bottom USB 2.0 port under RJ45 on the read side) +- SMSC SCH5545 Super I/O initialization +- SMSC SCH5545 EC initialization and firmware update +- SMSC SCH5545 EC automatic fan control +- TPM 1.2 +- Booting Debian 10, Ubuntu 18.04, QubesOS R4.01 +- Boot with cleaned ME +- Intruder detection +- Wake-on-Lan from ACPI S3 + +[flashrom]: https://flashrom.org/Flashrom +[Dell OptiPlex 9010 specifications]: https://www.dell.com/downloads/global/products/optix/en/dell_optiplex_9010_spec_sheet.pdf +[UEFITool]: https://github.com/LongSoft/UEFITool diff --git a/Documentation/mainboard/index.md b/Documentation/mainboard/index.md index 33c60a4c97..b9fc68d052 100644 --- a/Documentation/mainboard/index.md +++ b/Documentation/mainboard/index.md @@ -26,6 +26,10 @@ This section contains documentation about coreboot on specific mainboards. - [CN81XX EVB SFF](cavium/cn8100_sff_evb.md) +## Dell + +- [OptiPlex 9010 SFF](dell/optiplex_9010.md) + ## Emulation The boards in this section are not real mainboards, but emulators. diff --git a/configs/config.dell_optiplex_9010_sff b/configs/config.dell_optiplex_9010_sff new file mode 100644 index 0000000000..e25653e148 --- /dev/null +++ b/configs/config.dell_optiplex_9010_sff @@ -0,0 +1,9 @@ +CONFIG_USE_OPTION_TABLE=y +CONFIG_USE_BLOBS=y +CONFIG_VENDOR_DELL=y +CONFIG_ONBOARD_VGA_IS_PRIMARY=y +# CONFIG_DRIVERS_UART_8250IO is not set +CONFIG_PCIEXP_CLK_PM=y +CONFIG_SEABIOS_PS2_TIMEOUT=3000 +CONFIG_POST_DEVICE_LPC=y +CONFIG_HAVE_EM100_SUPPORT=y diff --git a/src/mainboard/dell/Kconfig b/src/mainboard/dell/Kconfig new file mode 100644 index 0000000000..298c62b52b --- /dev/null +++ b/src/mainboard/dell/Kconfig @@ -0,0 +1,16 @@ +if VENDOR_DELL + +choice + prompt "Mainboard model" + +source "src/mainboard/dell/*/Kconfig.name" + +endchoice + +source "src/mainboard/dell/*/Kconfig" + +config MAINBOARD_VENDOR + string + default "Dell Inc." + +endif # VENDOR_DELL diff --git a/src/mainboard/dell/Kconfig.name b/src/mainboard/dell/Kconfig.name new file mode 100644 index 0000000000..3d2fefd11d --- /dev/null +++ b/src/mainboard/dell/Kconfig.name @@ -0,0 +1,2 @@ +config VENDOR_DELL + bool "Dell Inc." diff --git a/src/mainboard/dell/optiplex_9010/Kconfig b/src/mainboard/dell/optiplex_9010/Kconfig new file mode 100644 index 0000000000..6a3feb3751 --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/Kconfig @@ -0,0 +1,69 @@ +if BOARD_DELL_OPTIPLEX_9010 + +config BOARD_SPECIFIC_OPTIONS + def_bool y + 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 SOUTHBRIDGE_INTEL_C216 + 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 + +config MAINBOARD_DIR + string + default dell/optiplex_9010 + +config MAINBOARD_PART_NUMBER + string + default "OptiPlex 9010" + +config VGA_BIOS_FILE + string + default "pci8086,0162.rom" + +config VGA_BIOS_ID + string + default "8086,0162" + +config DRAM_RESET_GATE_GPIO + int + default 60 + +config MAX_CPUS + int + default 8 + +config USBDEBUG_HCD_INDEX + int + default 2 + +config CBFS_SIZE + hex + 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/optiplex_9010/Kconfig.name b/src/mainboard/dell/optiplex_9010/Kconfig.name new file mode 100644 index 0000000000..96707c2890 --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/Kconfig.name @@ -0,0 +1,2 @@ +config BOARD_DELL_OPTIPLEX_9010 + bool "OptiPlex 9010 SFF" diff --git a/src/mainboard/dell/optiplex_9010/Makefile.inc b/src/mainboard/dell/optiplex_9010/Makefile.inc new file mode 100644 index 0000000000..7a8a68423a --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/Makefile.inc @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: GPL-2.0-only + +smm-y += smihandler.c + +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 + +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 diff --git a/src/mainboard/dell/optiplex_9010/acpi/ec.asl b/src/mainboard/dell/optiplex_9010/acpi/ec.asl new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/mainboard/dell/optiplex_9010/acpi/platform.asl b/src/mainboard/dell/optiplex_9010/acpi/platform.asl new file mode 100644 index 0000000000..f890b5af54 --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/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/optiplex_9010/acpi/superio.asl b/src/mainboard/dell/optiplex_9010/acpi/superio.asl new file mode 100644 index 0000000000..fa1dfcf726 --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/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 diff --git a/src/mainboard/dell/optiplex_9010/acpi_tables.c b/src/mainboard/dell/optiplex_9010/acpi_tables.c new file mode 100644 index 0000000000..33feed2a98 --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/acpi_tables.c @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include + +void acpi_create_gnvs(global_nvs_t *gnvs) +{ + gnvs->tcrt = 100; + gnvs->tpsv = 90; +} diff --git a/src/mainboard/dell/optiplex_9010/board_info.txt b/src/mainboard/dell/optiplex_9010/board_info.txt new file mode 100644 index 0000000000..f49f3ba416 --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/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/optiplex_9010/cmos.default b/src/mainboard/dell/optiplex_9010/cmos.default new file mode 100644 index 0000000000..ccc7e64625 --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/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/optiplex_9010/cmos.layout b/src/mainboard/dell/optiplex_9010/cmos.layout new file mode 100644 index 0000000000..dcf9639d3f --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/cmos.layout @@ -0,0 +1,95 @@ +## SPDX-License-Identifier: GPL-2.0-only + +# ----------------------------------------------------------------- +entries + +# ----------------------------------------------------------------- +# Status Register A +# ----------------------------------------------------------------- +# Status Register B +# ----------------------------------------------------------------- +# Status Register C +#96 4 r 0 status_c_rsvd +#100 1 r 0 uf_flag +#101 1 r 0 af_flag +#102 1 r 0 pf_flag +#103 1 r 0 irqf_flag +# ----------------------------------------------------------------- +# Status Register D +#104 7 r 0 status_d_rsvd +#111 1 r 0 valid_cmos_ram +# ----------------------------------------------------------------- +# Diagnostic Status Register +#112 8 r 0 diag_rsvd1 + +# ----------------------------------------------------------------- +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/optiplex_9010/data.vbt b/src/mainboard/dell/optiplex_9010/data.vbt new file mode 100644 index 0000000000000000000000000000000000000000..d1a95e86329ad61642591a87cdd8ee551061713c GIT binary patch literal 4281 zcmdT{Z){uD75`noXZz*(J==N7ij%g{p?^ZsHqEo^dR>-j&woe0JPo|G&ieuS(=p}5yh3FSofLS3rO`EB3dZ9AcH{MSZGpA=CKT$n3`%q=D@TjLz zDO;fQgAZ2bD%F{V$}CMx-JK>0YwDSEr{-p9^xVTID%By9SnN&lOdEm`G1dj2z7r@1xTASiX=cOpfGC-Caud z%>3ikQxBb7puTKBCHMmaE}%PQ%ATpt@2B+K9F0q#vou~gTd6);ncZ*d65uj4RRF?| z$deG_p9!=9hKjs{K7wB$4crOj023JDhyVqkA1DI5fPFv|K2!KqcGK|YV_tMgN=8zo z^w}UOq2j%1M5AgzZy17rU)qCFK|(4H-fX7b|RTNG&JmFa)Ggc)@OzY5s+I1odfxjPtxrAM(_*I+Y$oq4;aVMeoXmidRw z&oTd8)A1VfW#&IHzt8+<=D#xkjXBt+qn&vx^KRxr=C3hlnU6Ami+P6myUgd97nz@8 z{webd%z<Oh`zfrGqvkyWYX)uWs(JHnOSQh|sjJ$^YKL=s=ba7lnq;tEdHE zRfmOA|Bl8I;IPg^9EckDs8=I; zzYOB`zu9sRuUT_V!67PI%@ z;xX8cJ>Su=^t?Ry*y^$FUZ;GqX~}=nu}{33aGc9cORNv6MWqpMBem$4`_H#^YEdk^ z^~PENoDFR2>O&VkzyF0M*CnaFAvS62^=&D<*H&Am)$LJjdPl>xrxnZgBv+9TZJN)o8f%~6LTZ|B zuJ*JevX&~|u)Y{82i7pISNflYVuUCWvT`APG(-y_>wHLG4$*5NYbB(=6QX~FEZxvM z4H`16qM=V2^gY9R#?UVs^jpJv+t5EW2&QG3`Zkj?rZs8m-!^HslmrQ!ov_3HP zk4)0SR(Dw66{aI$>w&QToiIHewq6YDFNf)^u(cZ2uY@TYv35lCeGzldRkh|@6}5Iw zbxtU)YVfv~eTFMP6;YP{$X$GmZHy%6pqH1Vlzq2GxD+A8%iE~0*4YS5PioNznTaqs zg_T<)Y%D5S8;v^PpOvaa7~XUh8;elZRHJ^T{Eazmj$mz_I$45c6CK3vm-zVYwm<&F zT?9H?MmSu;PP=zY3I~575dyy)?vh~;9jzhsZk=L;UYlY`lz-Pi_++O-|oe|Hr(#38k)F7wsFyV=?*IFh%F!{#};As;xS6ol5z;Xgre zPXVK~NZx!7{Le{dwVztpi!0r@RH8d`^Embo4op%y&kX7%Q)@D0^sj~p6s z$^+hI%l3j#?Li^MdEl;-$CFEq>tCX)4}L`5Ys}liW$) zJLdM{2e0pZwduAOD9tQX&v>Ka@g$WGk9(u?xwxE3gYr4~+ufslZZEC9TQ`F*@9cd9 sfzcKIPw>jd_Q(qK@+)5Z7v-AXwDYKSKCXQuPW=Yj_Z9r4Ip=lqUoXj?9{>OV literal 0 HcmV?d00001 diff --git a/src/mainboard/dell/optiplex_9010/devicetree.cb b/src/mainboard/dell/optiplex_9010/devicetree.cb new file mode 100644 index 0000000000..6a21d20b74 --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/devicetree.cb @@ -0,0 +1,99 @@ +chip northbridge/intel/sandybridge + device cpu_cluster 0 on + chip cpu/intel/model_206ax + register "c1_acpower" = "1" + register "c1_battery" = "1" + register "c2_acpower" = "3" + register "c2_battery" = "3" + register "c3_acpower" = "5" + register "c3_battery" = "5" + register "tcc_offset" = "5" # TCC of 95C + device lapic 0 on end + device lapic 0xacac off end + end + end + device domain 0x0 on + subsystemid 0x1028 0x052c inherit + + device pci 00.0 on end # Host bridge Host bridge + device pci 01.0 on # PEG1 (blue slot1) + smbios_slot_desc "0xB6" "4" "SLOT1" "0x0D" + 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" = "0x00000146" + register "alt_gp_smi_en" = "0x0004" + register "gpi2_routing" = "1" + register "gpi12_routing" = "2" + register "c2_latency" = "0x0065" + register "gen1_dec" = "0x007c0a01" + register "gen2_dec" = "0x007c0901" + register "gen3_dec" = "0x003c07e1" + register "gen4_dec" = "0x001c0901" + register "pcie_port_coalesce" = "1" + register "sata_interface_speed_support" = "0x3" + register "sata_port_map" = "0x7" + 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 on # PCIe Port #5 + smbios_slot_desc "0xB6" "4" "SLOT2" "0x0A" + 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 + 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/optiplex_9010/dsdt.asl b/src/mainboard/dell/optiplex_9010/dsdt.asl new file mode 100644 index 0000000000..6a6dcb4c36 --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/dsdt.asl @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +DefinitionBlock( + "dsdt.aml", + "DSDT", + 0x02, /* DSDT revision: ACPI 2.0 and up */ + OEM_ID, + ACPI_TABLE_CREATOR, + 0x20141018 /* OEM revision */ +) +{ + #include "acpi/platform.asl" + #include + #include + #include + #include + + Scope (\_SB) + { + Device (PCI0) + { + #include + #include + Device (GLAN) + { + Name (_ADR, 0x00190000) + Name (_PRW, Package() { 13, 4 }) + } + } + } +} diff --git a/src/mainboard/dell/optiplex_9010/early_init.c b/src/mainboard/dell/optiplex_9010/early_init.c new file mode 100644 index 0000000000..5469c94f15 --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/early_init.c @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include + +#include "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, (uintptr_t)DEFAULT_MCHBAR | 1); + pci_write_config32(HOST_BRIDGE, MCHBAR + 4, (0LL + (uintptr_t)DEFAULT_MCHBAR) >> 32); + MCHBAR16(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/optiplex_9010/gma-mainboard.ads b/src/mainboard/dell/optiplex_9010/gma-mainboard.ads new file mode 100644 index 0000000000..74b50645e6 --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/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/optiplex_9010/gpio.c b/src/mainboard/dell/optiplex_9010/gpio.c new file mode 100644 index 0000000000..d01e6221a6 --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/gpio.c @@ -0,0 +1,208 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include + +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/optiplex_9010/hda_verb.c b/src/mainboard/dell/optiplex_9010/hda_verb.c new file mode 100644 index 0000000000..eab4ba9053 --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/hda_verb.c @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include + +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/optiplex_9010/mainboard.c b/src/mainboard/dell/optiplex_9010/mainboard.c new file mode 100644 index 0000000000..4490c14a0d --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/mainboard.c @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "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/optiplex_9010/romstage.c b/src/mainboard/dell/optiplex_9010/romstage.c new file mode 100644 index 0000000000..36af6e49c0 --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/romstage.c @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sch5545_ec.h" + +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/optiplex_9010/sch5545_ec.c b/src/mainboard/dell/optiplex_9010/sch5545_ec.c new file mode 100644 index 0000000000..401345254d --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/sch5545_ec.c @@ -0,0 +1,726 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sch5545_ec.h" + +#define GPIO_CHASSIS_ID0 1 +#define GPIO_CHASSIS_ID1 17 +#define GPIO_CHASSIS_ID2 37 +#define GPIO_FRONT_PANEL_CHASSIS_DET_L 70 + +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; + +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 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 }, +}; + + + +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; + 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_boot_map_with_leak("sch5545_ecfw.bin", CBFS_TYPE_RAW, + &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; + 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: + return 5; + case 0x8: + return 4; + case 0x3: + case 0xb: + return 3; + case 0x1: + case 0x9: + case 0x5: + case 0xd: + return 6; + 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, val_2fc, chassis_type, fan_speed_full = 0; + + 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_chassis6, 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); + + if (get_option(&fan_speed_full, "fan_full_speed") != CB_SUCCESS) + printk(BIOS_INFO, "fan_full_speed CMOS option not found. " + "Fans will be set up for automatic control\n"); + + if (fan_speed_full) { + 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); + } + + 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, 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/optiplex_9010/sch5545_ec.h b/src/mainboard/dell/optiplex_9010/sch5545_ec.h new file mode 100644 index 0000000000..0ca589f9eb --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/sch5545_ec.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include + +#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; +}; + +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); diff --git a/src/mainboard/dell/optiplex_9010/sch5545_ec_early.c b/src/mainboard/dell/optiplex_9010/sch5545_ec_early.c new file mode 100644 index 0000000000..70b7de6064 --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/sch5545_ec_early.c @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include + +#include "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/optiplex_9010/smihandler.c b/src/mainboard/dell/optiplex_9010/smihandler.c new file mode 100644 index 0000000000..d3c83ef5e7 --- /dev/null +++ b/src/mainboard/dell/optiplex_9010/smihandler.c @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include + +void mainboard_smi_gpi(u32 gpi_sts) +{ + printk(BIOS_SPEW, "%s: gpi_sts: %08x\n", __func__, gpi_sts); +} + +int mainboard_smi_apmc(u8 data) +{ + u8 val; + switch (data) { + case APM_CNT_ACPI_ENABLE: + printk(BIOS_SPEW, "%s: APM CNT EN: %02x\n", __func__, data); + /* 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: + printk(BIOS_SPEW, "%s: APM CNT DIS: %02x\n", __func__, data); + /* 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; +} + +void mainboard_smi_sleep(u8 slp_typ) +{ + printk(BIOS_SPEW, "%s: SMI sleep: %02x\n", __func__, slp_typ); +}