52 changes: 51 additions & 1 deletion MAINTAINERS
Expand Up @@ -245,6 +245,11 @@ F: src/mainboard/getac/p470/



GIGABYTE GA-D510UD MAINBOARD
M: Angel Pons <th3fanbus@gmail.com>
S: Maintained
F: src/mainboard/gigabyte/ga-d510ud/

GIGABYTE GA-G41M-ES2L MAINBOARD
M: Damien Zammit <damien@zamaudio.com>
S: Odd Fixes
Expand All @@ -256,12 +261,26 @@ S: Maintained
F: src/mainboard/gigabyte/ga-h61m-series/


GOOGLE BRYA MAINBOARDS
M: Tim Wawrzynczak <twawrzynczak@chromium.org>
S: Maintained
F: src/mainboard/google/brya/

GOOGLE HATCH MAINBOARDS
M: Tim Wawrzynczak <twawrzynczak@chromium.org>
S: Maintained
F: src/mainboard/google/hatch/

GOOGLE PANTHER MAINBOARD
M: Stefan Reinauer <stefan.reinauer@coreboot.org>
S: Supported
F: src/mainboard/google/panther/

GOOGLE VOLTEER MAINBOARDS
M: Tim Wawrzynczak <twawrzynczak@chromium.org>
S: Maintained
F: src/mainboard/google/volteer/

GOOGLE MAINBOARDS (Intel-based, legacy/inactive)
M: Matt DeVillier <MrChromebox@gmail.com>
S: Maintained
Expand All @@ -278,6 +297,13 @@ F: src/mainboard/google/stout/



HP 280 G2 MAINBOARD
M: Angel Pons <th3fanbus@gmail.com>
S: Maintained
F: src/mainboard/hp/280_g2/



INTEL D510MO MAINBOARD
M: Damien Zammit <damien@zamaudio.com>
S: Odd Fixes
Expand Down Expand Up @@ -325,6 +351,14 @@ S: Maintained
F: src/mainboard/libretrend/lt1000/



MSI H81M-P33 MAINBOARD
M: Angel Pons <th3fanbus@gmail.com>
S: Maintained
F: src/mainboard/msi/h81m-p33/



OCP DELTALAKE MAINBOARD
M: Jonathan Zhang <jonzhang@fb.com>
M: Reddy Chagam <anjaneya.chagam@intel.com>
Expand Down Expand Up @@ -476,6 +510,11 @@ F: src/include/cpu/x86/
# Embedded Controllers
################################################################################

CHROME EC
M: Tim Wawrzynczak <twawrzynczak@chromium.org>
S: Maintained
F: src/ec/google/chromeec/

LENOVO EC
M: Alexander Couzens <lynxis@fe80.eu>
S: Maintained
Expand Down Expand Up @@ -584,6 +623,11 @@ S: Maintained
F: src/soc/amd/picasso/
F: src/vendorcode/amd/fsp/picasso/

INTEL ALDERLAKE SOC
M: Tim Wawrzynczak <twawrzynczak@chromium.org>
S: Maintained
F: src/soc/intel/alderlake/

INTEL APOLLOLAKE_SOC
M: Andrey Petrov <andrey.petrov@gmail.com>
S: Maintained
Expand All @@ -597,6 +641,11 @@ S: Maintained
F: /src/soc/intel/braswell/
F: /src/vendorcode/intel/fsp/fsp1_1/braswell/

INTEL TIGERLAKE SOC
M: Tim Wawrzynczak <twawrzynczak@chromium.org>
S: Maintained
F: src/soc/intel/tigerlake/

INTEL Xeon Sacalable Processor Family
M: Jonathan Zhang <jonzhang@fb.com>
M: Reddy Chagam <anjaneya.chagam@intel.com>
Expand All @@ -605,7 +654,7 @@ M: Morgan Jang <Morgan_Jang@wiwynn.com>
M: Ryback Hung <<Ryback.Hung@quantatw.com>
M: Bryant Ou <Bryant.Ou@quantatw.com>
S: Supported
F: src/soc/intel/xeon_sp
F: src/soc/intel/xeon_sp/
F: src/vendorcode/intel/fsp/fsp2_0/skylake_sp/
F: src/vendorcode/intel/fsp/fsp2_0/copperlake_sp/

Expand Down Expand Up @@ -727,6 +776,7 @@ F: src/drivers/aspeed/ast2050/

ACPI
M: Lance Zhao <lance.zhao@gmail.com>
M: Tim Wawrzynczak <twawrzynczak@chromium.org>
S: Supported
F: src/acpi/
F: src/arch/x86/acpi/
Expand Down
14 changes: 12 additions & 2 deletions Makefile
Expand Up @@ -24,7 +24,10 @@ COREBOOT_EXPORTS += top src srck obj objutil objk
LANG:=C
LC_ALL:=C
TZ:=UTC0
COREBOOT_EXPORTS += LANG LC_ALL TZ
SOURCE_DATE_EPOCH := $(shell $(top)/util/genbuild_h/genbuild_h.sh . | sed -n 's/^.define COREBOOT_BUILD_EPOCH\>.*"\(.*\)".*/\1/p')
# don't use COREBOOT_EXPORTS to ensure build steps outside the coreboot build system
# are reproducible
export LANG LC_ALL TZ SOURCE_DATE_EPOCH

DOTCONFIG ?= $(top)/.config
KCONFIG_CONFIG = $(DOTCONFIG)
Expand Down Expand Up @@ -111,16 +114,22 @@ NOCOMPILE:=1
endif
ifneq ($(filter %clean lint% help% what-jenkins-does,$(MAKECMDGOALS)),)
NOMKDIR:=1
UNIT_TEST:=1
endif
endif

ifneq ($(filter %-test %-tests,$(MAKECMDGOALS)),)
ifneq ($(filter help%, $(MAKECMDGOALS)), )
NOCOMPILE:=1
UNIT_TEST:=1
else
ifneq ($(filter %-test %-tests, $(MAKECMDGOALS)),)
ifneq ($(filter-out %-test %-tests, $(MAKECMDGOALS)),)
$(error Cannot mix unit-tests targets with other targets)
endif
UNIT_TEST:=1
NOCOMPILE:=
endif
endif

$(xcompile): util/xcompile/xcompile
rm -f $@
Expand All @@ -138,6 +147,7 @@ include $(TOPLEVEL)/Makefile.inc
include $(TOPLEVEL)/payloads/Makefile.inc
include $(TOPLEVEL)/util/testing/Makefile.inc
-include $(TOPLEVEL)/site-local/Makefile.inc
include $(TOPLEVEL)/tests/Makefile.inc
real-all:
@echo "Error: Expected config file ($(DOTCONFIG)) not present." >&2
@echo "Please specify a config file or run 'make menuconfig' to" >&2
Expand Down
Expand Up @@ -10,7 +10,6 @@
# + Silicon Image SIL3114 driver
# + Genesys Logic GL9763E driver
# + EM100 support
# + SMM module loader V2
CONFIG_COVERAGE=y
CONFIG_ASAN=y
CONFIG_UBSAN=y
Expand Down Expand Up @@ -47,5 +46,4 @@ CONFIG_DEBUG_COVERAGE=y
CONFIG_DEBUG_BOOT_STATE=y
CONFIG_DEBUG_ADA_CODE=y
CONFIG_HAVE_EM100_SUPPORT=y
CONFIG_X86_SMM_LOADER_VERSION2=y
CONFIG_EM100=y
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu1
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.13.0.5"
CONFIG_LOCALVERSION="v4.13.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_NO_GFX_INIT=y
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu2
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.13.0.5"
CONFIG_LOCALVERSION="v4.13.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU2=y
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu3
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.13.0.5"
CONFIG_LOCALVERSION="v4.13.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU3=y
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu4
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.13.0.5"
CONFIG_LOCALVERSION="v4.13.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU4=y
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu5
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.13.0.5"
CONFIG_LOCALVERSION="v4.13.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU5=y
Expand Down
2 changes: 1 addition & 1 deletion configs/config.pcengines_apu6
@@ -1,4 +1,4 @@
CONFIG_LOCALVERSION="v4.13.0.5"
CONFIG_LOCALVERSION="v4.13.0.6"
CONFIG_VENDOR_PCENGINES=y
CONFIG_PAYLOAD_CONFIGFILE="$(top)/src/mainboard/$(MAINBOARDDIR)/seabios_config"
CONFIG_BOARD_PCENGINES_APU6=y
Expand Down
6 changes: 5 additions & 1 deletion payloads/external/LinuxBoot/targets/linux.mk
Expand Up @@ -18,7 +18,11 @@ decompress_flag=.done

OBJCOPY:=$(LINUXBOOT_CROSS_COMPILE)objcopy
KERNEL_MAKE_FLAGS = \
ARCH=$(ARCH-y)
ARCH=$(ARCH-y) \
KBUILD_BUILD_USER="coreboot" \
KBUILD_BUILD_HOST="reproducible" \
KBUILD_BUILD_TIMESTAMP="$(shell perl -e 'print scalar gmtime($(SOURCE_DATE_EPOCH))')" \
KBUILD_BUILD_VERSION="0"

ifeq ($(CONFIG_LINUXBOOT_KERNEL_CUSTOM),y)
kernel_version:=$(CONFIG_LINUXBOOT_KERNEL_CUSTOM_VERSION)
Expand Down
10 changes: 6 additions & 4 deletions payloads/external/depthcharge/Makefile
Expand Up @@ -8,11 +8,12 @@ project_config_file=$(project_dir)/.config
output_dir=$(project_dir)/build
libpayload_dir=$(abspath $(CURDIR)/../../libpayload)
libpayload_install_dir=$(output_dir)/lp_$(BOARD)
coreboot_build_dir=$(abspath $(CURDIR)/../../../build)

VBOOT_SOURCE ?= $(abspath $(CURDIR)/../../../3rdparty/vboot)
EC_HEADERS ?= $(abspath $(CURDIR)/../../../3rdparty/chromeec/include)

TAG-$(DEPTHCHARGE_MASTER)=origin/master
TAG-$(DEPTHCHARGE_MASTER)=origin/main
TAG-$(DEPTHCHARGE_STABLE)=$(STABLE_COMMIT_ID)
TAG-$(DEPTHCHARGE_REVISION)=$(DEPTHCHARGE_REVISION_ID)

Expand Down Expand Up @@ -44,17 +45,17 @@ fetch: $(project_dir)
@cd $(project_dir); \
git show $(TAG-y) >/dev/null 2>&1; \
if [ $$? -ne 0 ] || \
[ "$(TAG-y)" = "origin/master" ]; then \
[ "$(TAG-y)" = "origin/main" ]; then \
echo " Fetching new commits from the $(project_name) git repo"; \
git fetch; fi

# Check out the requested version of the tree
# Don't write a file for master branch so the latest remote version is always used
# Don't write a file for main branch so the latest remote version is always used
$(project_dir)/.version_$(TAG-y): fetch
echo " Checking out $(project_name) revision $(TAG-y)"
rm -f $(project_dir)/.version_*
cd $(project_dir); \
git checkout master; \
git checkout main; \
git branch -D coreboot 2>/dev/null; \
git checkout -b coreboot $(TAG-y)
ifneq ($(DEPTHCHARGE_MASTER),y)
Expand Down Expand Up @@ -84,6 +85,7 @@ config: $(project_dir)/.version_$(TAG-y) $(libpayload_install_dir)

build: config
echo " MAKE $(project_name) $(TAG-y)"
cp $(coreboot_build_dir)/static_fw_config.h depthcharge/src/base/
$(MAKE) -C $(project_dir) depthcharge BOARD=$(BOARD) \
LIBPAYLOAD_DIR=$(libpayload_install_dir)/libpayload \
VB_SOURCE=$(VBOOT_SOURCE) \
Expand Down
8 changes: 6 additions & 2 deletions payloads/external/tianocore/Makefile
Expand Up @@ -36,10 +36,14 @@ endif

TIMEOUT=-D PLATFORM_BOOT_TIMEOUT=$(CONFIG_TIANOCORE_BOOT_TIMEOUT)

ifeq ($(CONFIG_TIANOCORE_COREBOOTPAYLOAD),y)
ifeq ($(CONFIG_TIANOCORE_TARGET_IA32), y)
ARCH=-a IA32 -p $(bootloader)/$(bootloader)Ia32.dsc
ARCH=-a IA32 -p CorebootPayloadPkg/CorebootPayloadPkgIa32.dsc
else
ARCH=-a IA32 -a X64 -p $(bootloader)/$(bootloader)Ia32X64.dsc
ARCH=-a IA32 -a X64 -p CorebootPayloadPkg/CorebootPayloadPkgIa32X64.dsc
endif
else
ARCH=-a IA32 -a X64 -p UefiPayloadPkg/UefiPayloadPkg.dsc
endif

BUILD_STR=-q $(ARCH) -t COREBOOT -b $(BUILD_TYPE) $(TIMER) $(TIMEOUT) $(build_flavor)
Expand Down
73 changes: 52 additions & 21 deletions payloads/external/tint/Makefile
@@ -1,5 +1,25 @@
project_url=https://mirror.fsf.org/trisquel/pool/main/t/tint/tint_0.05.tar.xz
archive_name=tint_0.05.tar.xz
#
# TINT build system - helps to securely download TINT with a checksum verification and build it.
#

#
# Properties of the current TINT version
#

TINT_VERSION=0.05
TINT_EXT_VERSION=0.05
TINT_ARCHIVE_LINK="https://mirror.fsf.org/trisquel/pool/main/t/tint/tint_${TINT_EXT_VERSION}.tar.xz"
TINT_ARCHIVE="tint_${TINT_VERSION}.tar.xz"
TINT_DIR="tint-${TINT_VERSION}"
TINT_SHA1SUM="859008216930a4584e622d0df41fd75c44d2b47f"

#
# Locations of the input/output scripts
#

buildgcc="./../../../util/crossgcc/buildgcc"
corescript="./core.sh"
tintified="./tint.sh"

unexport KCONFIG_AUTOHEADER
unexport KCONFIG_AUTOCONFIG
Expand All @@ -10,28 +30,39 @@ unexport KCONFIG_NEGATIVES

all: tint

tint: patch
echo " MAKE TINT "
$(MAKE) -C tint

patch: download
cd tint; \
if [ -e debian ]; then \
rm -rf debian typedefs.h Makefile; \
touch Makefile; \
patch -l -p1 < ../libpayload_tint.patch; \
fi
################################################################################
#
# Three stages of TINT build system:
#
# 1) generate_core.sh extracts the core part from buildgcc script,
# most importantly the checksum calculation/verification functions.
#
# 2) tintify_core.sh adds the TINT-specific footer/header to the core,
# such as the properties of current version including its checksum.
#
# 3) tint.sh - generated and "tintified" core script - builds a TINT.
#
################################################################################

download:
test -d tint || { wget $(project_url); \
tar -xvf $(archive_name); \
rm $(archive_name); \
mv tint-0.05 tint; }
tint:
if [ ! -f ${tintified} ]; then \
chmod +x "./generate_core.sh" ; \
"./generate_core.sh" ${buildgcc} ${corescript} "prepare_before_patch" ; \
chmod +x "./tintify_core.sh" ; \
"./tintify_core.sh" ${corescript} ${tintified} \
${TINT_ARCHIVE_LINK} ${TINT_ARCHIVE} ${TINT_DIR} ${TINT_SHA1SUM} ; \
fi ; \
chmod +x ${tintified}
${tintified}

clean:
test -d tint && $(MAKE) -C tint clean || exit 0
test -d "./tint/" && $(MAKE) -C "./tint/" clean || exit 0

distclean:
rm -rf tint
rm -rf "./tint/"
rm -f ${corescript}
rm -f ${tintified}

.PHONY: tint clean distclean

.PHONY: download patch tint clean distclean
#
102 changes: 102 additions & 0 deletions payloads/external/tint/generate_core.sh
@@ -0,0 +1,102 @@
#!/bin/sh
#
# generate_core.sh extracts the core part from buildgcc script,
# most importantly the checksum calculation/verification functions.
#
# Copyright (C) 2019 Mike Banon <mikebdp2@gmail.com>
#
##############################################################################
#
# USAGE:
# ./generate_core.sh <buildgcc> <corescript> prepare_before_patch
# where
# buildgcc - path to input buildgcc script
# corescript - path to output core part script
# prepare_before_patch - optional argument to insert prepare_${package}
# call into the unpack_and_patch function, e.g.
# for removing some files with rm command
# in order to reduce the size of patch file
#
##############################################################################

buildgcc="$1"
corescript="$2"
prepare_before_patch="$3"

#
# Imports the source file fragment between start and end into the
# destination file, optionally excluding the last line if not needed
#

import_from_file() {
source="$1"
destination="$2"
start="$3"
end="$4"
last_line_disabled="$5"
if [ -z "${last_line_disabled}" ] ; then
sed -n "/^${start}/,/^${end}/{/^${start}/{p;n};{p}}" "$source" >> "$destination"
else
sed -n "/^${start}/,/^${end}/{/^${start}/{p;n};/^${end}/{q};{p}}" "$source" >> "$destination"
fi
}

#
# Import the color defines together with UNAME/HALT_FOR_TOOLS variables
#

import_from_file "$buildgcc" "$corescript" "red=" "HALT_FOR_TOOLS=0" || exit "$?"

#
# Import the core functions
#

FUNCTIONS="please_install searchtool download compute_hash error_hash_mismatch verify_hash unpack_and_patch"

for F in $FUNCTIONS ; do
import_from_file "$buildgcc" "$corescript" "$F()" "}" || exit "$?"
done

#
# Import a fragment where we find tar/patch/make and other essential tools
#

import_from_file "$buildgcc" "$corescript" "# Find all the required tools" "# Allow" "last_line_disabled" || exit "$?"

#
# Import a fragment with conditional exit if some required tools were not found
#

import_from_file "$buildgcc" "$corescript" "if \[ \"\$HALT_FOR_TOOLS" "fi" || exit "$?"

#
# Avoid the unnecessary subdirectories holding a single file each
#

sed -i -e "s/patches\///g" "$corescript"
sed -i -e "s/sum\///g" "$corescript"
sed -i -e "s/tarballs\///g" "$corescript"
sed -i -e "s/cd tarballs || exit 1//g" "$corescript"
sed -i -e "s/cd \.\.//g" "$corescript"

#
# Get the known checksum without using a dedicated single-line file
#

sed -i -e "s/\tknown_hash=\"\$(get_known_hash.*/\tknown_hash=\"\$2\"/g" "$corescript"

#
# Update the paths printed at the error messages
#

sed -i -e "s/util\/crossgcc\///g" "$corescript"

#
# Insert prepare_${package} function call between the unpack and patch operations
#

if [ ! -z "${prepare_before_patch}" ] ; then
sed -i -e "/\$TAR \$FLAGS \"\$(basename \"\$archive\")\"/a prepare_\${package} || exit \"\$?\"" "$corescript"
fi

#
File renamed without changes.
98 changes: 98 additions & 0 deletions payloads/external/tint/tintify_core.sh
@@ -0,0 +1,98 @@
#!/bin/sh
#
# tintify_core.sh adds the TINT-specific footer/header to the core,
# such as the properties of current TINT version including its checksum.
#
# Copyright (C) 2019 Mike Banon <mikebdp2@gmail.com>
#
################################################################################
#
# USAGE:
# ./tintify_core.sh <corescript> <tintified> \
# <TINT_ARCHIVE_LINK> <TINT_ARCHIVE> <TINT_DIR> <TINT_SHA1SUM>
# where
# corescript - path to input core script
# tintified - path to output tint script
#
################################################################################

corescript="$1"
tintified="$2"

#
# TINT-specific header
#

#
# Insert the properties of the current TINT version
#

echo "#!/bin/sh" > "$tintified"
echo "TINT_ARCHIVE_LINK=${3}" >> "$tintified"
echo "TINT_ARCHIVE=${4}" >> "$tintified"
echo "TINT_DIR=${5}" >> "$tintified"
echo "TINT_SHA1SUM=${6}" >> "$tintified"

#
# Add the replace_plus_with_minus() function - needed to fix the version number
#

echo "replace_plus_with_minus() {" >> "$tintified"
echo "for x in *\"+\"*; do" >> "$tintified"
echo "y=\$(printf %sa \"\$x\" | tr \"+\" \"-\")" >> "$tintified"
echo "mv -- \"\$x\" \"\${y%a}\"" >> "$tintified"
echo "done" >> "$tintified"
echo "}" >> "$tintified"

#
# Add the prepare_TINT() function, it will remove the unneeded debian directory
# as well as typedefs.h and old Makefile to significantly reduce the patch size
#

echo "prepare_TINT() {" >> "$tintified"
# echo "replace_plus_with_minus" >> "$tintified"
echo "if [ ! -z ./\${TINT_DIR} ] && [ -e ./\${TINT_DIR}/debian ] ; then" >> "$tintified"
echo "rm -rf ./\${TINT_DIR}/debian ./\${TINT_DIR}/typedefs.h ./\${TINT_DIR}/Makefile;" >> "$tintified"
echo "touch ./\${TINT_DIR}/Makefile;" >> "$tintified"
echo "fi" >> "$tintified"
echo "}" >> "$tintified"

#
# Importing the core script
#

cat "$corescript" >> "$tintified"

#
# download() function adjustments - became necessary after a version number fix
#

sed -i -e "/download() {/a package=\$1\narchive_link=\"\$(eval echo \\\\\$\$package\"_ARCHIVE_LINK\")\"" "$tintified"
sed -i -e "s/downloading from \$archive/&_link/g" "$tintified"
sed -i -e "s/\(download_showing_percentage \"\$archive\)./\1_link\"/g" "$tintified"

#
# TINT-specific footer
#

echo "if [ ! -d tint ] ; then" >> "$tintified"

echo "printf \"Downloading and verifying TINT tarball ... \\n\"" >> "$tintified"
echo "download TINT || exit \"\$?\"" >> "$tintified"
echo "verify_hash TINT \${TINT_SHA1SUM} || exit \"\$?\"" >> "$tintified"
echo "printf \"Downloaded TINT tarball ... \${green}ok\${NC}\\n\"" >> "$tintified"

echo "printf \"Unpacking and patching TINT... \\n\"" >> "$tintified"
echo "unpack_and_patch TINT || exit 1" >> "$tintified"
echo "printf \"Unpacked and patched TINT... \${green}ok\${NC}\\n\"" >> "$tintified"

echo "mv ./\${TINT_DIR} ./tint" >> "$tintified"
echo "fi" >> "$tintified"

echo "printf \"Building TINT ... \\n\"" >> "$tintified"
echo "make -C ./tint" >> "$tintified"
echo "printf \"TINT built ... \${green}ok\${NC}\\n\"" >> "$tintified"

chmod +x "$tintified"

#
4 changes: 4 additions & 0 deletions payloads/libpayload/configs/config.herobrine
@@ -0,0 +1,4 @@
CONFIG_LP_CHROMEOS=y
CONFIG_LP_ARCH_ARM64=y
CONFIG_LP_TIMER_ARM64_ARCH=y
CONFIG_LP_SERIAL_CONSOLE=y
1 change: 1 addition & 0 deletions payloads/libpayload/drivers/Makefile.inc
Expand Up @@ -77,6 +77,7 @@ libc-y += video/graphics.c
libc-$(CONFIG_LP_STORAGE) += storage/storage.c
libc-$(CONFIG_LP_STORAGE_AHCI) += storage/ahci.c
libc-$(CONFIG_LP_STORAGE_AHCI) += storage/ahci_common.c
libc-$(CONFIG_LP_STORAGE_NVME) += storage/nvme.c
ifeq ($(CONFIG_LP_STORAGE_ATA),y)
libc-$(CONFIG_LP_STORAGE_ATA) += storage/ata.c
libc-$(CONFIG_LP_STORAGE_ATA) += storage/ahci_ata.c
Expand Down
1 change: 1 addition & 0 deletions payloads/libpayload/drivers/i8042/i8042.h
Expand Up @@ -55,6 +55,7 @@
#define I8042_MODE_NUM_LOCK_OFF (0 << 1)
#define I8042_MODE_SCROLL_LOCK_ON (1 << 0)
#define I8042_MODE_SCROLL_LOCK_OFF (0 << 0)
#define I8042_KBCMD_ECHO 0xee
#define I8042_KBCMD_SET_SCANCODE 0xf0
#define I8042_KBCMD_SET_TYPEMATIC 0xf3
#define I8042_KBCMD_EN 0xf4
Expand Down
85 changes: 77 additions & 8 deletions payloads/libpayload/drivers/i8042/keyboard.c
Expand Up @@ -237,9 +237,17 @@ static bool set_scancode_set(const unsigned char set)
return ret;
}

static bool keyboard_peek_echo_result(void)
{
const uint8_t ch = i8042_peek_data_ps2();
return ch == 0xee || ch == 0xfe;
}

static enum keyboard_state {
STATE_INIT = 0,
STATE_SIMPLIFIED_INIT,
STATE_HOTPLUG,
STATE_HOTPLUG_ECHO,
STATE_DISABLE_SCAN,
STATE_DRAIN_INPUT,
STATE_DISABLE_TRANSLATION,
Expand All @@ -250,13 +258,16 @@ static enum keyboard_state {
STATE_ENABLE_TRANSLATION,
STATE_ENABLE_SCAN,
STATE_RUNNING,
STATE_IGNORE,
STATE_RUNNING_ECHO,
STATE_DETENTION,
} keyboard_state;

#define STATE_NAMES_ENTRY(name) [STATE_##name] = #name
static const char *const state_names[] = {
STATE_NAMES_ENTRY(INIT),
STATE_NAMES_ENTRY(SIMPLIFIED_INIT),
STATE_NAMES_ENTRY(HOTPLUG),
STATE_NAMES_ENTRY(HOTPLUG_ECHO),
STATE_NAMES_ENTRY(DISABLE_SCAN),
STATE_NAMES_ENTRY(DRAIN_INPUT),
STATE_NAMES_ENTRY(DISABLE_TRANSLATION),
Expand All @@ -267,7 +278,8 @@ static const char *const state_names[] = {
STATE_NAMES_ENTRY(ENABLE_TRANSLATION),
STATE_NAMES_ENTRY(ENABLE_SCAN),
STATE_NAMES_ENTRY(RUNNING),
STATE_NAMES_ENTRY(IGNORE),
STATE_NAMES_ENTRY(RUNNING_ECHO),
STATE_NAMES_ENTRY(DETENTION),
};

__attribute__((unused))
Expand Down Expand Up @@ -301,6 +313,28 @@ static void keyboard_poll(void)
next_state = STATE_CONFIGURE;
break;

case STATE_HOTPLUG:
if (timer_us(state_time) > 1*1000*1000) {
i8042_write_data(I8042_KBCMD_ECHO);
next_state = STATE_HOTPLUG_ECHO;
}
break;

case STATE_HOTPLUG_ECHO:
if (!i8042_data_ready_ps2()) {
if (timer_us(state_time) > 200*1000)
next_state = STATE_HOTPLUG;
break;
}

if (keyboard_peek_echo_result()) {
next_state = STATE_DISABLE_SCAN;
keyboard_time = timer_us(0);
}
(void)i8042_read_data_ps2();

break;

case STATE_DISABLE_SCAN:
(void)keyboard_cmd(I8042_KBCMD_DEFAULT_DIS);
next_state = STATE_DRAIN_INPUT;
Expand Down Expand Up @@ -394,23 +428,51 @@ static void keyboard_poll(void)
break;

case STATE_RUNNING:
/* TODO: Use echo command to detect detach. */
if (!i8042_data_ready_ps2()) {
if (timer_us(state_time) > 500*1000) {
i8042_write_data(I8042_KBCMD_ECHO);
next_state = STATE_RUNNING_ECHO;
}
} else {
state_time = timer_us(0);
}
break;

case STATE_RUNNING_ECHO:
if (!i8042_data_ready_ps2()) {
if (timer_us(state_time) > 200*1000) {
debug("INFO: Keyboard echo timed out.\n");
next_state = STATE_HOTPLUG;
}
break;
}

if (keyboard_peek_echo_result()) {
(void)i8042_read_data_ps2();
next_state = STATE_RUNNING;
}

state_time = timer_us(0);
break;

case STATE_IGNORE:
/* TODO: Try again after timeout if it ever seems useful. */
case STATE_DETENTION:
if (timer_us(state_time) > 5*1000*1000)
next_state = STATE_HOTPLUG;
break;

}

switch (next_state) {
case STATE_INIT:
case STATE_HOTPLUG:
case STATE_HOTPLUG_ECHO:
case STATE_RUNNING:
case STATE_IGNORE:
case STATE_RUNNING_ECHO:
case STATE_DETENTION:
break;
default:
if (timer_us(keyboard_time) > 30*1000*1000)
next_state = STATE_IGNORE;
next_state = STATE_DETENTION;
break;
}

Expand All @@ -424,7 +486,9 @@ static void keyboard_poll(void)
bool keyboard_havechar(void)
{
keyboard_poll();
return keyboard_state == STATE_RUNNING && i8042_data_ready_ps2();
return i8042_data_ready_ps2() &&
(keyboard_state == STATE_RUNNING ||
(keyboard_state == STATE_RUNNING_ECHO && !keyboard_peek_echo_result()));
}

unsigned char keyboard_get_scancode(void)
Expand Down Expand Up @@ -591,6 +655,11 @@ void keyboard_disconnect(void)
keyboard_cmd(I8042_KBCMD_DEFAULT_DIS);
keyboard_drain_input();

/* Nobody but us seems to still use scancode set #1.
So try to hand over with more modern settings. */
set_scancode_set(2);
i8042_set_kbd_translation(false);

/* Send keyboard disconnect command */
i8042_cmd(I8042_CMD_DIS_KB);

Expand Down
7 changes: 7 additions & 0 deletions payloads/libpayload/drivers/storage/Kconfig
Expand Up @@ -49,3 +49,10 @@ config STORAGE_AHCI_ONLY_TESTED
help
If this option is selected, only AHCI controllers which are known
to work will be used.

config STORAGE_NVME
bool "Support for NVMe devices"
depends on STORAGE && PCI
default y
help
Select this option if you want support for NVMe devices.
403 changes: 403 additions & 0 deletions payloads/libpayload/drivers/storage/nvme.c

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions payloads/libpayload/drivers/storage/storage.c
Expand Up @@ -29,6 +29,7 @@
#include <libpayload.h>
#include <pci/pci.h>
#include <storage/ahci.h>
#include <storage/nvme.h>
#include <storage/storage.h>

static storage_dev_t **devices = NULL;
Expand Down Expand Up @@ -115,6 +116,11 @@ void storage_initialize(void)
case PCI_CLASS_STORAGE_AHCI:
ahci_initialize(dev);
break;
#endif
#if CONFIG(LP_STORAGE_NVME)
case PCI_CLASS_STORAGE_NVME:
nvme_initialize(dev);
break;
#endif
default:
break;
Expand Down
1 change: 1 addition & 0 deletions payloads/libpayload/include/pci/pci.h
Expand Up @@ -67,6 +67,7 @@
#define PCI_ROM_ADDRESS_MASK ~0x7ff

#define PCI_CLASS_STORAGE_AHCI 0x0106
#define PCI_CLASS_STORAGE_NVME 0x0108
#define PCI_CLASS_MEMORY_OTHER 0x0580

#define PCI_VENDOR_ID_INTEL 0x8086
Expand Down
14 changes: 14 additions & 0 deletions payloads/libpayload/include/storage/nvme.h
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Libpayload NVMe device driver
* Copyright (C) 2019 secunet Security Networks AG
*/

#ifndef _STORAGE_NVME_H
#define _STORAGE_NVME_H

#include "storage.h"

void nvme_initialize(struct pci_dev *dev);

#endif /* _STORAGE_NVME_H */
1 change: 1 addition & 0 deletions payloads/libpayload/include/storage/storage.h
Expand Up @@ -42,6 +42,7 @@ typedef enum {
PORT_TYPE_IDE = (1 << 0),
PORT_TYPE_SATA = (1 << 1),
PORT_TYPE_USB = (1 << 2),
PORT_TYPE_NVME = (1 << 3),
} storage_port_t;

typedef enum {
Expand Down
7 changes: 7 additions & 0 deletions src/Kconfig
Expand Up @@ -1105,6 +1105,13 @@ config DEBUG_SPI_FLASH
help
This option enables additional SPI flash related debug messages.

config DEBUG_IPMI
bool "Output verbose IPMI debug messages"
default n
depends on IPMI_KCS
help
This option enables additional IPMI related debug messages.

if SOUTHBRIDGE_INTEL_BD82X6X && DEFAULT_CONSOLE_LOGLEVEL_8
# Only visible with the right southbridge and loglevel.
config DEBUG_INTEL_ME
Expand Down
2 changes: 1 addition & 1 deletion src/acpi/Makefile.inc
Expand Up @@ -10,7 +10,7 @@ ramstage-$(CONFIG_PCI) += acpigen_pci.c
ramstage-y += acpigen_ps2_keybd.c
ramstage-y += acpigen_usb.c
ramstage-y += device.c
ramstage-$(CONFIG_CHROMEOS) += chromeos-gnvs.c
ramstage-$(CONFIG_CHROMEOS_NVS) += chromeos-gnvs.c
ramstage-$(CONFIG_ACPI_SOC_NVS) += gnvs.c
ramstage-y += pld.c
ramstage-y += sata.c
Expand Down
6 changes: 2 additions & 4 deletions src/acpi/acpi.c
Expand Up @@ -638,17 +638,15 @@ unsigned long acpi_create_dmar_andd(unsigned long current, u8 device_number,
return andd->length;
}

unsigned long acpi_create_dmar_satc(unsigned long current, u8 flags,
u16 segment, const char *device_scope)
unsigned long acpi_create_dmar_satc(unsigned long current, u8 flags, u16 segment)
{
dmar_satc_entry_t *satc = (dmar_satc_entry_t *)current;
int satc_len = sizeof(dmar_satc_entry_t) + strlen(device_scope) + 1;
int satc_len = sizeof(dmar_satc_entry_t);
memset(satc, 0, satc_len);
satc->type = DMAR_SATC;
satc->length = satc_len;
satc->flags = flags;
satc->segment_number = segment;
memcpy(&satc->device_scope, device_scope, strlen(device_scope));

return satc->length;
}
Expand Down
72 changes: 72 additions & 0 deletions src/acpi/acpigen.c
Expand Up @@ -803,6 +803,78 @@ void acpigen_write_STA_ext(const char *namestring)
acpigen_pop_len();
}

void acpigen_write_LPI_package(u64 level, const struct acpi_lpi_state *states, u16 nentries)
{
/*
* Name (_LPI, Package (0x06) // _LPI: Low Power Idle States
* {
* 0x0000,
* 0x0000000000000000,
* 0x0003,
* Package (0x0A)
* {
* 0x00000002,
* 0x00000001,
* 0x00000001,
* 0x00000000,
* 0x00000000,
* 0x00000000,
* ResourceTemplate ()
* {
* Register (FFixedHW,
* 0x02, // Bit Width
* 0x02, // Bit Offset
* 0x0000000000000000, // Address
* ,)
* },
*
* ResourceTemplate ()
* {
* Register (SystemMemory,
* 0x00, // Bit Width
* 0x00, // Bit Offset
* 0x0000000000000000, // Address
* ,)
* },
*
* ResourceTemplate ()
* {
* Register (SystemMemory,
* 0x00, // Bit Width
* 0x00, // Bit Offset
* 0x0000000000000000, // Address
* ,)
* },
*
* "C1"
* },
* ...
* }
*/

acpigen_write_name("_LPI");
acpigen_write_package(3 + nentries);
acpigen_write_word(0); /* Revision */
acpigen_write_qword(level);
acpigen_write_word(nentries);

for (size_t i = 0; i < nentries; i++, states++) {
acpigen_write_package(0xA);
acpigen_write_dword(states->min_residency_us);
acpigen_write_dword(states->worst_case_wakeup_latency_us);
acpigen_write_dword(states->flags);
acpigen_write_dword(states->arch_context_lost_flags);
acpigen_write_dword(states->residency_counter_frequency_hz);
acpigen_write_dword(states->enabled_parent_state);
acpigen_write_register_resource(&states->entry_method);
acpigen_write_register_resource(&states->residency_counter_register);
acpigen_write_register_resource(&states->usage_counter_register);
acpigen_write_string(states->state_name);
acpigen_pop_len();
}
acpigen_pop_len();
}

/*
* Generates a func with max supported P-states.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/acpi/acpigen_extern.asl
Expand Up @@ -19,7 +19,7 @@ External (NVS1, IntObj)
OperationRegion (DNVS, SystemMemory, NVB1, NVS1)
#endif

#if CONFIG(CHROMEOS)
#if CONFIG(CHROMEOS_NVS)
External (NVB2, IntObj)
External (NVS2, IntObj)
OperationRegion (CNVS, SystemMemory, NVB2, NVS2)
Expand Down
2 changes: 1 addition & 1 deletion src/acpi/dsdt_top.asl
Expand Up @@ -2,7 +2,7 @@

#include <acpi/acpigen_extern.asl>

#if CONFIG(CHROMEOS)
#if CONFIG(CHROMEOS_NVS)
/* Chrome OS specific */
#include <vendorcode/google/chromeos/acpi/gnvs.asl>
#include <vendorcode/google/chromeos/acpi/chromeos.asl>
Expand Down
6 changes: 3 additions & 3 deletions src/acpi/gnvs.c
Expand Up @@ -26,7 +26,7 @@ void acpi_create_gnvs(void)
gnvs_size = 0x100;
if (CONFIG(ACPI_HAS_DEVICE_NVS))
gnvs_size = 0x2000;
else if (CONFIG(CHROMEOS))
else if (CONFIG(CHROMEOS_NVS))
gnvs_size = 0x1000;

gnvs = cbmem_add(CBMEM_ID_ACPI_GNVS, gnvs_size);
Expand All @@ -38,7 +38,7 @@ void acpi_create_gnvs(void)
if (CONFIG(CONSOLE_CBMEM))
gnvs->cbmc = (uintptr_t)cbmem_find(CBMEM_ID_CONSOLE);

if (CONFIG(CHROMEOS))
if (CONFIG(CHROMEOS_NVS))
gnvs_assign_chromeos((u8 *)gnvs + GNVS_CHROMEOS_ACPI_OFFSET);
}

Expand Down Expand Up @@ -78,7 +78,7 @@ void acpi_fill_gnvs(void)
acpigen_write_name_dword("NVS0", 0x100);
acpigen_pop_len();

if (CONFIG(CHROMEOS)) {
if (CONFIG(CHROMEOS_NVS)) {
acpigen_write_scope("\\");
acpigen_write_name_dword("NVB2", (uintptr_t)gnvs + GNVS_CHROMEOS_ACPI_OFFSET);
acpigen_write_name_dword("NVS2", 0xf00);
Expand Down
11 changes: 0 additions & 11 deletions src/arch/x86/cpu.c
Expand Up @@ -213,17 +213,6 @@ static void set_cpu_ops(struct device *cpu)
/* Keep track of default APIC ids for SMM. */
static int cpus_default_apic_id[CONFIG_MAX_CPUS];

/*
* When CPUID executes with EAX set to 1, additional processor identification
* information is returned to EBX register:
* Default APIC ID: EBX[31-24] - this number is the 8 bit ID that is assigned
* to the local APIC on the processor during power on.
*/
static int initial_lapicid(void)
{
return cpuid_ebx(1) >> 24;
}

/* Function to keep track of cpu default apic_id */
void cpu_add_map_entry(unsigned int index)
{
Expand Down
40 changes: 40 additions & 0 deletions src/arch/x86/include/arch/mmio.h
Expand Up @@ -45,4 +45,44 @@ static __always_inline void write64(volatile void *addr, uint64_t value)
*((volatile uint64_t *)(addr)) = value;
}

static __always_inline uint8_t read8p(const uintptr_t addr)
{
return read8((void *)addr);
}

static __always_inline uint16_t read16p(const uintptr_t addr)
{
return read16((void *)addr);
}

static __always_inline uint32_t read32p(const uintptr_t addr)
{
return read32((void *)addr);
}

static __always_inline uint64_t read64p(const uintptr_t addr)
{
return read64((void *)addr);
}

static __always_inline void write8p(const uintptr_t addr, const uint8_t value)
{
write8((void *)addr, value);
}

static __always_inline void write16p(const uintptr_t addr, const uint16_t value)
{
write16((void *)addr, value);
}

static __always_inline void write32p(const uintptr_t addr, const uint32_t value)
{
write32((void *)addr, value);
}

static __always_inline void write64p(const uintptr_t addr, const uint64_t value)
{
write64((void *)addr, value);
}

#endif /* __ARCH_MMIO_H__ */
6 changes: 4 additions & 2 deletions src/arch/x86/smbios.c
Expand Up @@ -390,7 +390,7 @@ static int smbios_write_type0(unsigned long *current, int handle)
t->vendor = smbios_add_string(t->eos, "coreboot");
t->bios_release_date = smbios_add_string(t->eos, coreboot_dmi_date);

if (CONFIG(CHROMEOS) && CONFIG(HAVE_ACPI_TABLES)) {
if (CONFIG(CHROMEOS_NVS)) {
uintptr_t version_address = (uintptr_t)t->eos;
/* SMBIOS offsets start at 1 rather than 0 */
version_address += (u32)smbios_string_table_len(t->eos) - 1;
Expand Down Expand Up @@ -930,7 +930,7 @@ int smbios_write_type9(unsigned long *current, int *handle,
const enum slot_data_bus_bandwidth bandwidth,
const enum misc_slot_usage usage,
const enum misc_slot_length length,
u8 slot_char1, u8 slot_char2, u8 bus, u8 dev_func)
const u16 id, u8 slot_char1, u8 slot_char2, u8 bus, u8 dev_func)
{
struct smbios_type9 *t = (struct smbios_type9 *)*current;
int len = sizeof(struct smbios_type9);
Expand All @@ -942,6 +942,7 @@ int smbios_write_type9(unsigned long *current, int *handle,
t->slot_designation = smbios_add_string(t->eos, name ? name : "SLOT");
t->slot_type = type;
/* TODO add slot_id supoort, will be "_SUN" for ACPI devices */
t->slot_id = id;
t->slot_data_bus_width = bandwidth;
t->current_usage = usage;
t->slot_length = length;
Expand Down Expand Up @@ -1272,6 +1273,7 @@ static int smbios_walk_device_tree_type9(struct device *dev, int *handle,
bandwidth,
usage,
length,
0,
1,
0,
dev->bus->secondary,
Expand Down
4 changes: 2 additions & 2 deletions src/commonlib/bsd/cbfs_mcache.c
Expand Up @@ -118,7 +118,7 @@ cb_err_t cbfs_mcache_lookup(const void *mcache, size_t mcache_size, const char *
current += ALIGN_UP(data_offset, CBFS_MCACHE_ALIGNMENT);
}

ERROR("CBFS mcache overflow!\n");
ERROR("CBFS mcache is not terminated!\n"); /* should never happen */
return CB_ERR;
}

Expand All @@ -127,7 +127,7 @@ size_t cbfs_mcache_real_size(const void *mcache, size_t mcache_size)
const void *end = mcache + mcache_size;
const void *current = mcache;

while (current + sizeof(uint32_t) < end) {
while (current + sizeof(uint32_t) <= end) {
const union mcache_entry *entry = current;

if (entry->magic == MCACHE_MAGIC_FULL || entry->magic == MCACHE_MAGIC_END) {
Expand Down
23 changes: 23 additions & 0 deletions src/commonlib/bsd/cbfs_private.c
Expand Up @@ -190,3 +190,26 @@ const void *cbfs_find_attr(const union cbfs_mdata *mdata, uint32_t attr_tag, siz

return NULL;
}

const struct vb2_hash *cbfs_file_hash(const union cbfs_mdata *mdata)
{
/* Hashes are variable-length attributes, so need to manually check the length. */
const struct cbfs_file_attr_hash *attr =
cbfs_find_attr(mdata, CBFS_FILE_ATTR_TAG_HASH, 0);
if (!attr)
return NULL; /* no hash */
const size_t asize = be32toh(attr->len);

const struct vb2_hash *hash = &attr->hash;
const size_t hsize = vb2_digest_size(hash->algo);
if (!hsize) {
ERROR("Hash algo %u for '%s' unsupported.\n", hash->algo, mdata->h.filename);
return NULL;
}
if (hsize != asize - offsetof(struct cbfs_file_attr_hash, hash.raw)) {
ERROR("Hash attribute size for '%s' (%zu) incorrect for algo %u.\n",
mdata->h.filename, asize, hash->algo);
return NULL;
}
return hash;
}
3 changes: 3 additions & 0 deletions src/commonlib/bsd/include/commonlib/bsd/cbfs_mdata.h
Expand Up @@ -24,4 +24,7 @@ union cbfs_mdata {
else caller is responsible for checking the |len| field to avoid reading out-of-bounds. */
const void *cbfs_find_attr(const union cbfs_mdata *mdata, uint32_t attr_tag, size_t size_check);

/* Returns pointer to CBFS file hash structure in metadata attributes, or NULL if invalid. */
const struct vb2_hash *cbfs_file_hash(const union cbfs_mdata *mdata);

#endif /* _COMMONLIB_BSD_CBFS_MDATA_H_ */
28 changes: 17 additions & 11 deletions src/commonlib/include/commonlib/mem_pool.h
Expand Up @@ -7,11 +7,14 @@
#include <stdint.h>

/*
* The memory pool allows one to allocate memory from a fixed size buffer
* that also allows freeing semantics for reuse. However, the current
* limitation is that the most recent allocation is the only one that
* can be freed. If one tries to free any allocation that isn't the
* most recently allocated it will result in a leak within the memory pool.
* The memory pool allows one to allocate memory from a fixed size buffer that
* also allows freeing semantics for reuse. However, the current limitation is
* that only the two most recent allocations can be freed (in exact reverse
* order). If one tries to free any allocation that isn't at the top of the
* allocation stack, or one allocates more than two buffers in a row without
* freeing, it will result in a leak within the memory pool. (Two allocations
* were chosen to optimize for the CBFS cache case which may need two buffers
* to map a single compressed file, and will free them in reverse order.)
*
* The memory returned by allocations are at least 8 byte aligned. Note
* that this requires the backing buffer to start on at least an 8 byte
Expand All @@ -22,20 +25,23 @@ struct mem_pool {
uint8_t *buf;
size_t size;
uint8_t *last_alloc;
uint8_t *second_to_last_alloc;
size_t free_offset;
};

#define MEM_POOL_INIT(buf_, size_) \
{ \
.buf = (buf_), \
.size = (size_), \
.last_alloc = NULL, \
.free_offset = 0, \
#define MEM_POOL_INIT(buf_, size_) \
{ \
.buf = (buf_), \
.size = (size_), \
.last_alloc = NULL, \
.second_to_last_alloc = NULL, \
.free_offset = 0, \
}

static inline void mem_pool_reset(struct mem_pool *mp)
{
mp->last_alloc = NULL;
mp->second_to_last_alloc = NULL;
mp->free_offset = 0;
}

Expand Down
13 changes: 9 additions & 4 deletions src/commonlib/include/commonlib/region.h
Expand Up @@ -164,14 +164,18 @@ static inline int rdev_chain_full(struct region_device *child,
ssize_t rdev_relative_offset(const struct region_device *p,
const struct region_device *c);

/* Helper functions to create an rdev that represents memory. */
int rdev_chain_mem(struct region_device *child, const void *base, size_t size);
int rdev_chain_mem_rw(struct region_device *child, void *base, size_t size);

struct mem_region_device {
char *base;
struct region_device rdev;
};

/* Initialize at runtime a mem_region_device. This would be used when
* the base and size are dynamic or can't be known during linking.
* There are two variants: read-only and read-write. */
/* Initialize at runtime a mem_region_device. Should only be used for mappings
that need to fit right up to the edge of the physical address space. Most use
cases will want to use rdev_chain_mem() instead. */
void mem_region_device_ro_init(struct mem_region_device *mdev, void *base,
size_t size);

Expand All @@ -182,7 +186,8 @@ extern const struct region_device_ops mem_rdev_ro_ops;

extern const struct region_device_ops mem_rdev_rw_ops;

/* Statically initialize mem_region_device. */
/* Statically initialize mem_region_device. Should normally only be used for
const globals. Most use cases will want to use rdev_chain_mem() instead. */
#define MEM_REGION_DEV_INIT(base_, size_, ops_) \
{ \
.base = (void *)(base_), \
Expand Down
8 changes: 8 additions & 0 deletions src/commonlib/include/commonlib/sd_mmc_ctrlr.h
Expand Up @@ -13,6 +13,14 @@
#define CARD_TIMEOUT -19
#define CARD_IN_PROGRESS -20 /* operation is in progress */

/* MMC status in CBMEM_ID_MMC_STATUS */
enum {
MMC_STATUS_NEED_RESET = 0,
MMC_STATUS_CMD1_READY_OR_IN_PROGRESS,
MMC_STATUS_CMD1_READY,
MMC_STATUS_CMD1_IN_PROGRESS,
};

struct mmc_command {
uint16_t cmdidx;

Expand Down
4 changes: 3 additions & 1 deletion src/commonlib/mem_pool.c
Expand Up @@ -17,6 +17,7 @@ void *mem_pool_alloc(struct mem_pool *mp, size_t sz)
p = &mp->buf[mp->free_offset];

mp->free_offset += sz;
mp->second_to_last_alloc = mp->last_alloc;
mp->last_alloc = p;

return p;
Expand All @@ -29,6 +30,7 @@ void mem_pool_free(struct mem_pool *mp, void *p)
return;

mp->free_offset = mp->last_alloc - mp->buf;
mp->last_alloc = mp->second_to_last_alloc;
/* No way to track allocation before this one. */
mp->last_alloc = NULL;
mp->second_to_last_alloc = NULL;
}
13 changes: 13 additions & 0 deletions src/commonlib/region.c
Expand Up @@ -287,6 +287,19 @@ const struct region_device_ops mem_rdev_rw_ops = {
.eraseat = mdev_eraseat,
};

static const struct mem_region_device mem_rdev = MEM_REGION_DEV_RO_INIT(0, ~(size_t)0);
static const struct mem_region_device mem_rdev_rw = MEM_REGION_DEV_RW_INIT(0, ~(size_t)0);

int rdev_chain_mem(struct region_device *child, const void *base, size_t size)
{
return rdev_chain(child, &mem_rdev.rdev, (uintptr_t)base, size);
}

int rdev_chain_mem_rw(struct region_device *child, void *base, size_t size)
{
return rdev_chain(child, &mem_rdev_rw.rdev, (uintptr_t)base, size);
}

void *mmap_helper_rdev_mmap(const struct region_device *rd, size_t offset,
size_t size)
{
Expand Down
2 changes: 1 addition & 1 deletion src/console/init.c
Expand Up @@ -26,7 +26,7 @@ static void init_log_level(void)
console_loglevel = get_console_loglevel();

if (!FIRST_CONSOLE)
get_option(&console_loglevel, "debug_level");
console_loglevel = get_int_option("debug_level", console_loglevel);
}

int console_log_level(int msg_level)
Expand Down
6 changes: 3 additions & 3 deletions src/console/printk.c
Expand Up @@ -69,7 +69,7 @@ static void wrap_putchar_cbmemc(unsigned char byte, void *data)
__cbmemc_tx_byte(byte);
}

int do_vprintk(int msg_level, const char *fmt, va_list args)
int vprintk(int msg_level, const char *fmt, va_list args)
{
int i, log_this;

Expand Down Expand Up @@ -98,13 +98,13 @@ int do_vprintk(int msg_level, const char *fmt, va_list args)
return i;
}

int do_printk(int msg_level, const char *fmt, ...)
int printk(int msg_level, const char *fmt, ...)
{
va_list args;
int i;

va_start(args, fmt);
i = do_vprintk(msg_level, fmt, args);
i = vprintk(msg_level, fmt, args);
va_end(args);

return i;
Expand Down
8 changes: 8 additions & 0 deletions src/cpu/intel/common/hyperthreading.c
Expand Up @@ -23,6 +23,14 @@ bool intel_ht_sibling(void)
if (!intel_ht_supported())
return false;

if (is_x2apic_mode()) {
if (cpuid_eax(0) >= 0xb) {
result = cpuid_ext(0xb, 0);
const uint32_t div = 1 << (result.eax & 0x1f);
return result.edx % div > 0;
}
}

apic_ids = 1;
if (cpuid_eax(0) >= 1)
apic_ids = (cpuid_ebx(1) >> 16) & 0xff;
Expand Down
32 changes: 16 additions & 16 deletions src/cpu/intel/haswell/haswell_init.c
Expand Up @@ -88,7 +88,7 @@ static int pcode_ready(void)

wait_count = 0;
do {
if (!(MCHBAR32(BIOS_MAILBOX_INTERFACE) & MAILBOX_RUN_BUSY))
if (!(mchbar_read32(BIOS_MAILBOX_INTERFACE) & MAILBOX_RUN_BUSY))
return 0;
wait_count += delay_step;
udelay(delay_step);
Expand All @@ -107,31 +107,31 @@ static void calibrate_24mhz_bclk(void)
}

/* A non-zero value initiates the PCODE calibration. */
MCHBAR32(BIOS_MAILBOX_DATA) = ~0;
MCHBAR32(BIOS_MAILBOX_INTERFACE) =
MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_FSM_MEASURE_INTVL;
mchbar_write32(BIOS_MAILBOX_DATA, ~0);
mchbar_write32(BIOS_MAILBOX_INTERFACE,
MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_FSM_MEASURE_INTVL);

if (pcode_ready() < 0) {
printk(BIOS_ERR, "PCODE: mailbox timeout on completion.\n");
return;
}

err_code = MCHBAR32(BIOS_MAILBOX_INTERFACE) & 0xff;
err_code = mchbar_read32(BIOS_MAILBOX_INTERFACE) & 0xff;

printk(BIOS_DEBUG, "PCODE: 24MHz BCLK calibration response: %d\n",
err_code);

/* Read the calibrated value. */
MCHBAR32(BIOS_MAILBOX_INTERFACE) =
MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_READ_CALIBRATION;
mchbar_write32(BIOS_MAILBOX_INTERFACE,
MAILBOX_RUN_BUSY | MAILBOX_BIOS_CMD_READ_CALIBRATION);

if (pcode_ready() < 0) {
printk(BIOS_ERR, "PCODE: mailbox timeout on read.\n");
return;
}

printk(BIOS_DEBUG, "PCODE: 24MHz BCLK calibration value: 0x%08x\n",
MCHBAR32(BIOS_MAILBOX_DATA));
mchbar_read32(BIOS_MAILBOX_DATA));
}

static u32 pcode_mailbox_read(u32 command)
Expand All @@ -142,15 +142,15 @@ static u32 pcode_mailbox_read(u32 command)
}

/* Send command and start transaction */
MCHBAR32(BIOS_MAILBOX_INTERFACE) = command | MAILBOX_RUN_BUSY;
mchbar_write32(BIOS_MAILBOX_INTERFACE, command | MAILBOX_RUN_BUSY);

if (pcode_ready() < 0) {
printk(BIOS_ERR, "PCODE: mailbox timeout on completion.\n");
return 0;
}

/* Read mailbox */
return MCHBAR32(BIOS_MAILBOX_DATA);
return mchbar_read32(BIOS_MAILBOX_DATA);
}

static int pcode_mailbox_write(u32 command, u32 data)
Expand All @@ -160,10 +160,10 @@ static int pcode_mailbox_write(u32 command, u32 data)
return -1;
}

MCHBAR32(BIOS_MAILBOX_DATA) = data;
mchbar_write32(BIOS_MAILBOX_DATA, data);

/* Send command and start transaction */
MCHBAR32(BIOS_MAILBOX_INTERFACE) = command | MAILBOX_RUN_BUSY;
mchbar_write32(BIOS_MAILBOX_INTERFACE, command | MAILBOX_RUN_BUSY);

if (pcode_ready() < 0) {
printk(BIOS_ERR, "PCODE: mailbox timeout on completion.\n");
Expand Down Expand Up @@ -365,12 +365,12 @@ void set_power_limits(u8 power_limit_1_time)
wrmsr(MSR_PKG_POWER_LIMIT, limit);

/* Set power limit values in MCHBAR as well */
MCHBAR32(MCH_PKG_POWER_LIMIT_LO) = limit.lo;
MCHBAR32(MCH_PKG_POWER_LIMIT_HI) = limit.hi;
mchbar_write32(MCH_PKG_POWER_LIMIT_LO, limit.lo);
mchbar_write32(MCH_PKG_POWER_LIMIT_HI, limit.hi);

/* Set DDR RAPL power limit by copying from MMIO to MSR */
msr.lo = MCHBAR32(MCH_DDR_POWER_LIMIT_LO);
msr.hi = MCHBAR32(MCH_DDR_POWER_LIMIT_HI);
msr.lo = mchbar_read32(MCH_DDR_POWER_LIMIT_LO);
msr.hi = mchbar_read32(MCH_DDR_POWER_LIMIT_HI);
wrmsr(MSR_DDR_RAPL_LIMIT, msr);

/* Use nominal TDP values for CPUs with configurable TDP */
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/intel/hyperthreading/intel_sibling.c
Expand Up @@ -21,7 +21,7 @@ void intel_sibling_init(struct device *cpu)
/* On the bootstrap processor see if I want sibling cpus enabled */
if (first_time) {
first_time = 0;
get_option(&disable_siblings, "hyper_threading");
disable_siblings = get_int_option("hyper_threading", disable_siblings);
}
result = cpuid(1);
/* Is hyperthreading supported */
Expand Down
14 changes: 0 additions & 14 deletions src/cpu/qemu-x86/Kconfig
Expand Up @@ -43,20 +43,6 @@ config CPU_QEMU_X86_TSEG_SMM

endchoice

choice
prompt "SMM loader"
default CPU_QEMU_X86_SMMLOADERV1
depends on SMM_TSEG

config CPU_QEMU_X86_SMMLOADERV1
bool "smmloader v1"

config CPU_QEMU_X86_SMMLOADERV2
bool "smmloader v2"
select X86_SMM_LOADER_VERSION2

endchoice

config MAX_CPUS
int
default 32 if SMM_TSEG
Expand Down
8 changes: 0 additions & 8 deletions src/cpu/x86/Kconfig
Expand Up @@ -121,14 +121,6 @@ config SMM_STUB_STACK_SIZE

endif

config X86_SMM_LOADER_VERSION2
bool
default n
depends on HAVE_SMI_HANDLER
help
This option enables SMM module loader that works with server
platforms which may contain more than 32 CPU threads.

config SMM_LAPIC_REMAP_MITIGATION
bool
default y if NORTHBRIDGE_INTEL_I945
Expand Down
2 changes: 1 addition & 1 deletion src/cpu/x86/lapic/lapic.c
Expand Up @@ -44,6 +44,6 @@ void lapic_virtual_wire_mode_init(void)
LAPIC_DELIVERY_MODE_NMI)
);

printk(BIOS_DEBUG, " apic_id: 0x%02x ", lapicid());
printk(BIOS_DEBUG, " apic_id: 0x%x ", lapicid());
printk(BIOS_INFO, "done.\n");
}
59 changes: 36 additions & 23 deletions src/cpu/x86/mp_init.c
Expand Up @@ -435,6 +435,28 @@ static int start_aps(struct bus *cpu_bus, int ap_count, atomic_t *num_aps)

printk(BIOS_DEBUG, "Attempting to start %d APs\n", ap_count);

if (is_x2apic_mode()) {
x2apic_send_ipi(LAPIC_DM_INIT | LAPIC_INT_LEVELTRIG |
LAPIC_INT_ASSERT | LAPIC_DEST_ALLBUT, 0);
mdelay(10);
x2apic_send_ipi(LAPIC_DM_STARTUP | LAPIC_INT_LEVELTRIG |
LAPIC_DEST_ALLBUT | sipi_vector, 0);

/* Wait for CPUs to check in up to 200 us. */
wait_for_aps(num_aps, ap_count, 200 /* us */, 15 /* us */);

x2apic_send_ipi(LAPIC_DM_STARTUP | LAPIC_INT_LEVELTRIG |
LAPIC_DEST_ALLBUT | sipi_vector, 0);

/* Wait for CPUs to check in. */
if (wait_for_aps(num_aps, ap_count, 100000 /* 100 ms */, 50 /* us */)) {
printk(BIOS_ERR, "Not all APs checked in: %d/%d.\n",
atomic_read(num_aps), ap_count);
return -1;
}
return 0;
}

if ((lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY)) {
printk(BIOS_DEBUG, "Waiting for ICR not to be busy...");
if (apic_wait_timeout(1000 /* 1 ms */, 50)) {
Expand Down Expand Up @@ -653,6 +675,11 @@ static void mp_initialize_cpu(void)

void smm_initiate_relocation_parallel(void)
{
if (is_x2apic_mode()) {
x2apic_send_ipi(LAPIC_DM_SMI | LAPIC_INT_LEVELTRIG, lapicid());
return;
}

if ((lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY)) {
printk(BIOS_DEBUG, "Waiting for ICR not to be busy...");
if (apic_wait_timeout(1000 /* 1 ms */, 50)) {
Expand Down Expand Up @@ -730,15 +757,10 @@ static void asmlinkage smm_do_relocation(void *arg)
* the location of the new SMBASE. If using SMM modules then this
* calculation needs to match that of the module loader.
*/
if (CONFIG(X86_SMM_LOADER_VERSION2)) {
perm_smbase = smm_get_cpu_smbase(cpu);
if (!perm_smbase) {
printk(BIOS_ERR, "%s: bad SMBASE for CPU %d\n", __func__, cpu);
return;
}
} else {
perm_smbase = mp_state.perm_smbase;
perm_smbase -= cpu * mp_state.smm_save_state_size;
perm_smbase = smm_get_cpu_smbase(cpu);
if (!perm_smbase) {
printk(BIOS_ERR, "%s: bad SMBASE for CPU %d\n", __func__, cpu);
return;
}

/* Setup code checks this callback for validity. */
Expand Down Expand Up @@ -769,19 +791,11 @@ static void adjust_smm_apic_id_map(struct smm_loader_params *smm_params)
}

static int install_relocation_handler(int num_cpus, size_t real_save_state_size,
size_t save_state_size)
size_t save_state_size, uintptr_t perm_smbase)
{
int cpus = num_cpus;
#if CONFIG(X86_SMM_LOADER_VERSION2)
/* Default SMRAM size is not big enough to concurrently
* handle relocation for more than ~32 CPU threads
* therefore, relocate 1 by 1. */
cpus = 1;
#endif

struct smm_loader_params smm_params = {
.per_cpu_stack_size = CONFIG_SMM_STUB_STACK_SIZE,
.num_concurrent_stacks = cpus,
.num_concurrent_stacks = num_cpus,
.real_cpu_save_state_size = real_save_state_size,
.per_cpu_save_state_size = save_state_size,
.num_concurrent_save_states = 1,
Expand All @@ -792,7 +806,7 @@ static int install_relocation_handler(int num_cpus, size_t real_save_state_size,
if (mp_state.ops.adjust_smm_params != NULL)
mp_state.ops.adjust_smm_params(&smm_params, 0);

if (smm_setup_relocation_handler(&smm_params)) {
if (smm_setup_relocation_handler((void *)perm_smbase, &smm_params)) {
printk(BIOS_ERR, "%s: smm setup failed\n", __func__);
return -1;
}
Expand Down Expand Up @@ -847,9 +861,8 @@ static void load_smm_handlers(void)
return;

/* Install handlers. */
if (install_relocation_handler(mp_state.cpu_count,
real_save_state_size,
smm_save_state_size) < 0) {
if (install_relocation_handler(mp_state.cpu_count, real_save_state_size,
smm_save_state_size, mp_state.perm_smbase) < 0) {
printk(BIOS_ERR, "Unable to install SMM relocation handler.\n");
smm_disable();
}
Expand Down
4 changes: 0 additions & 4 deletions src/cpu/x86/smm/Makefile.inc
@@ -1,10 +1,6 @@
## SPDX-License-Identifier: GPL-2.0-only

ifeq ($(CONFIG_X86_SMM_LOADER_VERSION2),y)
ramstage-y += smm_module_loaderv2.c
else
ramstage-y += smm_module_loader.c
endif
ramstage-y += smi_trigger.c

ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32),y)
Expand Down
547 changes: 389 additions & 158 deletions src/cpu/x86/smm/smm_module_loader.c

Large diffs are not rendered by default.

625 changes: 0 additions & 625 deletions src/cpu/x86/smm/smm_module_loaderv2.c

This file was deleted.

32 changes: 24 additions & 8 deletions src/cpu/x86/smm/smm_stub.S
Expand Up @@ -11,6 +11,7 @@

#include <cpu/x86/cr.h>
#include <cpu/x86/msr.h>
#include <cpu/x86/lapic_def.h>

.code32
.section ".module_parameters", "aw", @progbits
Expand All @@ -29,7 +30,7 @@ fxsave_area_size:
* APIC id is found at the given index, the contiguous CPU number is index
* into the table. */
apic_to_cpu_num:
.fill CONFIG_MAX_CPUS,1,0xff
.fill CONFIG_MAX_CPUS,2,0xffff
/* allows the STM to bring up SMM in 32-bit mode */
start32_offset:
.long smm_trampoline32 - _start
Expand Down Expand Up @@ -97,16 +98,31 @@ smm_trampoline32:

/* The CPU number is calculated by reading the initial APIC id. Since
* the OS can maniuplate the APIC id use the non-changing cpuid result
* for APIC id (ebx[31:24]). A table is used to handle a discontiguous
* for APIC id (ax). A table is used to handle a discontiguous
* APIC id space. */
mov $1, %eax
cpuid
bswap %ebx /* Default APIC id in bl. */
mov $(apic_to_cpu_num), %eax
xor %ecx, %ecx
apic_id:
mov $LAPIC_BASE_MSR, %ecx
rdmsr
andl $LAPIC_BASE_MSR_X2APIC_MODE, %eax
jz xapic

x2apic:
mov $X2APIC_LAPIC_ID, %ecx
rdmsr
jmp apicid_end

xapic:
movl $(LOCAL_APIC_ADDR | LAPIC_ID), %esi
movl (%esi), %eax
shr $24, %eax

apicid_end:

mov $(apic_to_cpu_num), %ebx
xor %ecx, %ecx

1:
cmp (%eax, %ecx, 1), %bl
cmp (%ebx, %ecx, 2), %ax
je 1f
inc %ecx
cmp $CONFIG_MAX_CPUS, %ecx
Expand Down
11 changes: 11 additions & 0 deletions src/device/Kconfig
Expand Up @@ -527,6 +527,15 @@ config AZALIA_MAX_CODECS
help
The maximum number of codecs supported on a single HD Audio controller.

config AZALIA_LOCK_DOWN_R_WO_GCAP
def_bool n
depends on AZALIA_PLUGIN_SUPPORT
help
The GCAP register is implemented as R/WO (Read / Write Once) on some
HD Audio controllers, such as Intel 6-series PCHs. Select this option
to lock down the GCAP register after deasserting the controller reset
bit. Locking is done by reading GCAP and writing back the read value.

config PCIEXP_PLUGIN_SUPPORT
bool
default y
Expand Down Expand Up @@ -626,6 +635,8 @@ if PCIEXP_HOTPLUG

config PCIEXP_HOTPLUG_BUSES
int "PCI Express Hotplug Buses"
default 8 if MMCONF_SUPPORT && MMCONF_BUS_NUMBER <= 64
default 16 if MMCONF_SUPPORT && MMCONF_BUS_NUMBER <= 128
default 32
help
This is the number of buses allocated for hotplug PCI express
Expand Down
5 changes: 5 additions & 0 deletions src/device/azalia_device.c
Expand Up @@ -56,6 +56,11 @@ static u16 codec_detect(u8 *base)
if (azalia_exit_reset(base) < 0)
goto no_codec;

if (CONFIG(AZALIA_LOCK_DOWN_R_WO_GCAP)) {
/* If GCAP is R/WO, lock it down after deasserting controller reset */
write16(base + HDA_GCAP_REG, read16(base + HDA_GCAP_REG));
}

/* clear STATESTS bits (BAR + 0xe)[2:0] */
reg16 = read16(base + HDA_STATESTS_REG);
reg16 |= codec_mask;
Expand Down
30 changes: 15 additions & 15 deletions src/device/device_util.c
Expand Up @@ -710,14 +710,14 @@ static void resource_tree(const struct device *root, int debug_level, int depth)
indent[i] = ' ';
indent[i] = '\0';

do_printk(BIOS_DEBUG, "%s%s", indent, dev_path(root));
printk(BIOS_DEBUG, "%s%s", indent, dev_path(root));
if (root->link_list && root->link_list->children)
do_printk(BIOS_DEBUG, " child on link 0 %s",
printk(BIOS_DEBUG, " child on link 0 %s",
dev_path(root->link_list->children));
do_printk(BIOS_DEBUG, "\n");
printk(BIOS_DEBUG, "\n");

for (res = root->resource_list; res; res = res->next) {
do_printk(debug_level, "%s%s resource base %llx size %llx "
printk(debug_level, "%s%s resource base %llx size %llx "
"align %d gran %d limit %llx flags %lx index %lx\n",
indent, dev_path(root), res->base, res->size,
res->align, res->gran, res->limit, res->flags,
Expand All @@ -735,12 +735,12 @@ void print_resource_tree(const struct device *root, int debug_level,
{
/* Bail if root is null. */
if (!root) {
do_printk(debug_level, "%s passed NULL for root!\n", __func__);
printk(debug_level, "%s passed NULL for root!\n", __func__);
return;
}

/* Bail if not printing to screen. */
if (!do_printk(debug_level, "Show resources in subtree (%s)...%s\n",
if (!printk(debug_level, "Show resources in subtree (%s)...%s\n",
dev_path(root), msg))
return;

Expand All @@ -758,7 +758,7 @@ void show_devs_tree(const struct device *dev, int debug_level, int depth)
depth_str[i] = ' ';
depth_str[i] = '\0';

do_printk(debug_level, "%s%s: enabled %d\n",
printk(debug_level, "%s%s: enabled %d\n",
depth_str, dev_path(dev), dev->enabled);

for (link = dev->link_list; link; link = link->next) {
Expand All @@ -771,18 +771,18 @@ void show_devs_tree(const struct device *dev, int debug_level, int depth)
void show_all_devs_tree(int debug_level, const char *msg)
{
/* Bail if not printing to screen. */
if (!do_printk(debug_level, "Show all devs in tree form... %s\n", msg))
if (!printk(debug_level, "Show all devs in tree form... %s\n", msg))
return;
show_devs_tree(all_devices, debug_level, 0);
}

void show_devs_subtree(struct device *root, int debug_level, const char *msg)
{
/* Bail if not printing to screen. */
if (!do_printk(debug_level, "Show all devs in subtree %s... %s\n",
if (!printk(debug_level, "Show all devs in subtree %s... %s\n",
dev_path(root), msg))
return;
do_printk(debug_level, "%s\n", msg);
printk(debug_level, "%s\n", msg);
show_devs_tree(root, debug_level, 0);
}

Expand All @@ -791,10 +791,10 @@ void show_all_devs(int debug_level, const char *msg)
struct device *dev;

/* Bail if not printing to screen. */
if (!do_printk(debug_level, "Show all devs... %s\n", msg))
if (!printk(debug_level, "Show all devs... %s\n", msg))
return;
for (dev = all_devices; dev; dev = dev->next) {
do_printk(debug_level, "%s: enabled %d\n",
printk(debug_level, "%s: enabled %d\n",
dev_path(dev), dev->enabled);
}
}
Expand All @@ -808,7 +808,7 @@ void show_one_resource(int debug_level, struct device *dev,
end = resource_end(resource);
buf[0] = '\0';

do_printk(debug_level, "%s %02lx <- [0x%010llx - 0x%010llx] "
printk(debug_level, "%s %02lx <- [0x%010llx - 0x%010llx] "
"size 0x%08llx gran 0x%02x %s%s%s\n", dev_path(dev),
resource->index, base, end, resource->size, resource->gran,
buf, resource_type(resource), comment);
Expand All @@ -818,12 +818,12 @@ void show_all_devs_resources(int debug_level, const char *msg)
{
struct device *dev;

if (!do_printk(debug_level, "Show all devs with resources... %s\n", msg))
if (!printk(debug_level, "Show all devs with resources... %s\n", msg))
return;

for (dev = all_devices; dev; dev = dev->next) {
struct resource *res;
do_printk(debug_level, "%s: enabled %d\n",
printk(debug_level, "%s: enabled %d\n",
dev_path(dev), dev->enabled);
for (res = dev->resource_list; res; res = res->next)
show_one_resource(debug_level, dev, res, "");
Expand Down
251 changes: 14 additions & 237 deletions src/device/dram/ddr3.c
Expand Up @@ -27,11 +27,11 @@
*
* @param type DIMM type. This is byte[3] of the SPD.
*/
int spd_dimm_is_registered_ddr3(enum spd_dimm_type type)
int spd_dimm_is_registered_ddr3(enum spd_dimm_type_ddr3 type)
{
if ((type == SPD_DIMM_TYPE_RDIMM)
| (type == SPD_DIMM_TYPE_MINI_RDIMM)
| (type == SPD_DIMM_TYPE_72B_SO_RDIMM))
if ((type == SPD_DDR3_DIMM_TYPE_RDIMM)
| (type == SPD_DDR3_DIMM_TYPE_MINI_RDIMM)
| (type == SPD_DDR3_DIMM_TYPE_72B_SO_RDIMM))
return 1;

return 0;
Expand Down Expand Up @@ -98,7 +98,7 @@ u16 spd_ddr3_calc_unique_crc(u8 *spd, int len)
* SPD_STATUS_INVALID_FIELD -- A field with an invalid value was
* detected.
*/
int spd_decode_ddr3(dimm_attr * dimm, spd_raw_data spd)
int spd_decode_ddr3(struct dimm_attr_ddr3_st *dimm, spd_raw_data spd)
{
int ret;
u16 crc, spd_crc;
Expand Down Expand Up @@ -394,7 +394,7 @@ int spd_decode_ddr3(dimm_attr * dimm, spd_raw_data spd)
* SPD_STATUS_INVALID_FIELD -- A field with an invalid value was
* detected.
*/
int spd_xmp_decode_ddr3(dimm_attr *dimm,
int spd_xmp_decode_ddr3(struct dimm_attr_ddr3_st *dimm,
spd_raw_data spd,
enum ddr3_xmp_profile profile)
{
Expand Down Expand Up @@ -505,7 +505,7 @@ int spd_xmp_decode_ddr3(dimm_attr *dimm,
*/
enum cb_err spd_add_smbios17(const u8 channel, const u8 slot,
const u16 selected_freq,
const dimm_attr *info)
const struct dimm_attr_ddr3_st *info)
{
struct memory_info *mem_info;
struct dimm_info *dimm;
Expand Down Expand Up @@ -544,22 +544,22 @@ enum cb_err spd_add_smbios17(const u8 channel, const u8 slot,
dimm->mod_id = info->manufacturer_id;

switch (info->dimm_type) {
case SPD_DIMM_TYPE_SO_DIMM:
case SPD_DDR3_DIMM_TYPE_SO_DIMM:
dimm->mod_type = SPD_SODIMM;
break;
case SPD_DIMM_TYPE_72B_SO_CDIMM:
case SPD_DDR3_DIMM_TYPE_72B_SO_CDIMM:
dimm->mod_type = SPD_72B_SO_CDIMM;
break;
case SPD_DIMM_TYPE_72B_SO_RDIMM:
case SPD_DDR3_DIMM_TYPE_72B_SO_RDIMM:
dimm->mod_type = SPD_72B_SO_RDIMM;
break;
case SPD_DIMM_TYPE_UDIMM:
case SPD_DDR3_DIMM_TYPE_UDIMM:
dimm->mod_type = SPD_UDIMM;
break;
case SPD_DIMM_TYPE_RDIMM:
case SPD_DDR3_DIMM_TYPE_RDIMM:
dimm->mod_type = SPD_RDIMM;
break;
case SPD_DIMM_TYPE_UNDEFINED:
case SPD_DDR3_DIMM_TYPE_UNDEFINED:
default:
dimm->mod_type = SPD_UNDEFINED;
break;
Expand Down Expand Up @@ -597,7 +597,7 @@ static void print_ns(const char *msg, u32 val)
*
* @param dimm pointer to already decoded @ref dimm_attr structure
*/
void dram_print_spd_ddr3(const dimm_attr * dimm)
void dram_print_spd_ddr3(const struct dimm_attr_ddr3_st *dimm)
{
u16 val16;
int i;
Expand Down Expand Up @@ -638,226 +638,3 @@ void dram_print_spd_ddr3(const dimm_attr * dimm)
printk(BIOS_INFO, " tCMDmin : %3u\n",
DIV_ROUND_UP(dimm->tCMD, 256));
}

/*==============================================================================
*= DDR3 MRS helpers
*----------------------------------------------------------------------------*/

/*
* MRS command structure:
* cmd[15:0] = Address pins MA[15:0]
* cmd[18:16] = Bank address BA[2:0]
*/

/* Map tWR value to a bitmask of the MR0 cycle */
static u16 ddr3_twr_to_mr0_map(u8 twr)
{
if ((twr >= 5) && (twr <= 8))
return (twr - 4) << 9;

/*
* From 8T onwards, we can only use even values. Round up if we are
* given an odd value.
*/
if ((twr >= 9) && (twr <= 14))
return ((twr + 1) >> 1) << 9;

/* tWR == 16T is [000] */
return 0;
}

/* Map the CAS latency to a bitmask for the MR0 cycle */
static u16 ddr3_cas_to_mr0_map(u8 cas)
{
u16 mask = 0;
/* A[6:4] are bits [2:0] of (CAS - 4) */
mask = ((cas - 4) & 0x07) << 4;

/* A2 is the MSB of (CAS - 4) */
if ((cas - 4) & (1 << 3))
mask |= (1 << 2);

return mask;
}

/**
* \brief Get command address for a DDR3 MR0 command
*
* The DDR3 specification only covers odd write_recovery up to 7T. If an odd
* write_recovery greater than 7 is specified, it will be rounded up. If a tWR
* greater than 8 is specified, it is recommended to explicitly round it up or
* down before calling this function.
*
* write_recovery and cas are given in clock cycles. For example, a CAS of 7T
* should be given as 7.
*
* @param precharge_pd
* @param write_recovery Write recovery latency, tWR in clock cycles.
* @param dll_reset
* @param mode
* @param cas CAS latency in clock cycles.
* @param burst_type
* @param burst_length
*/
mrs_cmd_t ddr3_get_mr0(enum ddr3_mr0_precharge precharge_pd,
u8 write_recovery,
enum ddr3_mr0_dll_reset dll_reset,
enum ddr3_mr0_mode mode,
u8 cas,
enum ddr3_mr0_burst_type burst_type,
enum ddr3_mr0_burst_length burst_length)
{
mrs_cmd_t cmd = 0 << 16;

if (precharge_pd == DDR3_MR0_PRECHARGE_FAST)
cmd |= (1 << 12);

cmd |= ddr3_twr_to_mr0_map(write_recovery);

if (dll_reset == DDR3_MR0_DLL_RESET_YES)
cmd |= (1 << 8);

if (mode == DDR3_MR0_MODE_TEST)
cmd |= (1 << 7);

cmd |= ddr3_cas_to_mr0_map(cas);

if (burst_type == DDR3_MR0_BURST_TYPE_INTERLEAVED)
cmd |= (1 << 3);

cmd |= (burst_length & 0x03) << 0;

return cmd;
}

static u16 ddr3_rtt_nom_to_mr1_map(enum ddr3_mr1_rtt_nom rtt_nom)
{
u16 mask = 0;
/* A9 <-> rtt_nom[2] */
if (rtt_nom & (1 << 2))
mask |= (1 << 9);
/* A6 <-> rtt_nom[1] */
if (rtt_nom & (1 << 1))
mask |= (1 << 6);
/* A2 <-> rtt_nom[0] */
if (rtt_nom & (1 << 0))
mask |= (1 << 2);

return mask;
}

static u16 ddr3_ods_to_mr1_map(enum ddr3_mr1_ods ods)
{
u16 mask = 0;
/* A5 <-> ods[1] */
if (ods & (1 << 1))
mask |= (1 << 5);
/* A1 <-> ods[0] */
if (ods & (1 << 0))
mask |= (1 << 1);

return mask;
}

/**
* \brief Get command address for a DDR3 MR1 command
*/
mrs_cmd_t ddr3_get_mr1(enum ddr3_mr1_qoff qoff,
enum ddr3_mr1_tqds tqds,
enum ddr3_mr1_rtt_nom rtt_nom,
enum ddr3_mr1_write_leveling write_leveling,
enum ddr3_mr1_ods ods,
enum ddr3_mr1_additive_latency additive_latency,
enum ddr3_mr1_dll dll_disable)
{
mrs_cmd_t cmd = 1 << 16;

if (qoff == DDR3_MR1_QOFF_DISABLE)
cmd |= (1 << 12);

if (tqds == DDR3_MR1_TQDS_ENABLE)
cmd |= (1 << 11);

cmd |= ddr3_rtt_nom_to_mr1_map(rtt_nom);

if (write_leveling == DDR3_MR1_WRLVL_ENABLE)
cmd |= (1 << 7);

cmd |= ddr3_ods_to_mr1_map(ods);

cmd |= (additive_latency & 0x03) << 3;

if (dll_disable == DDR3_MR1_DLL_DISABLE)
cmd |= (1 << 0);

return cmd;
}

/**
* \brief Get command address for a DDR3 MR2 command
*
* cas_cwl is given in clock cycles. For example, a cas_cwl of 7T should be
* given as 7.
*
* @param rtt_wr
* @param extended_temp
* @param self_refresh
* @param cas_cwl CAS write latency in clock cycles.
*/

mrs_cmd_t ddr3_get_mr2(enum ddr3_mr2_rttwr rtt_wr,
enum ddr3_mr2_srt_range extended_temp,
enum ddr3_mr2_asr self_refresh, u8 cas_cwl)
{
mrs_cmd_t cmd = 2 << 16;

cmd |= (rtt_wr & 0x03) << 9;

if (extended_temp == DDR3_MR2_SRT_EXTENDED)
cmd |= (1 << 7);

if (self_refresh == DDR3_MR2_ASR_AUTO)
cmd |= (1 << 6);

cmd |= ((cas_cwl - 5) & 0x07) << 3;

return cmd;
}

/**
* \brief Get command address for a DDR3 MR3 command
*
* @param dataflow_from_mpr Specify a non-zero value to put DRAM in read
* leveling mode. Zero for normal operation.
*/
mrs_cmd_t ddr3_get_mr3(char dataflow_from_mpr)
{
mrs_cmd_t cmd = 3 << 16;

if (dataflow_from_mpr)
cmd |= (1 << 2);

return cmd;
}

/**
* \brief Mirror the address bits for this MRS command
*
* Swap the following bits in the MRS command:
* - MA3 <-> MA4
* - MA5 <-> MA6
* - MA7 <-> MA8
* - BA0 <-> BA1
*/
mrs_cmd_t ddr3_mrs_mirror_pins(mrs_cmd_t cmd)
{
u32 downshift, upshift;
/* High bits= A4 | A6 | A8 | BA1 */
/* Low bits = A3 | A5 | A7 | BA0 */
u32 lowbits = (1 << 3) | (1 << 5) | (1 << 7) | (1 << 16);
downshift = (cmd & (lowbits << 1));
upshift = (cmd & lowbits);
cmd &= ~(lowbits | (lowbits << 1));
cmd |= (downshift >> 1) | (upshift << 1);
return cmd;
}
12 changes: 6 additions & 6 deletions src/device/dram/ddr4.c
Expand Up @@ -163,7 +163,7 @@ uint16_t ddr4_speed_mhz_to_reported_mts(uint16_t speed_mhz)
* SPD_STATUS_INVALID -- invalid SPD or not a DDR4 SPD
* SPD_STATUS_CRC_ERROR -- checksum mismatch
*/
int spd_decode_ddr4(dimm_attr *dimm, spd_raw_data spd)
int spd_decode_ddr4(struct dimm_attr_ddr4_st *dimm, spd_raw_data spd)
{
u8 reg8;
u8 bus_width, sdram_width;
Expand Down Expand Up @@ -261,7 +261,7 @@ int spd_decode_ddr4(dimm_attr *dimm, spd_raw_data spd)
}

enum cb_err spd_add_smbios17_ddr4(const u8 channel, const u8 slot, const u16 selected_freq,
const dimm_attr *info)
const struct dimm_attr_ddr4_st *info)
{
struct memory_info *mem_info;
struct dimm_info *dimm;
Expand Down Expand Up @@ -298,16 +298,16 @@ enum cb_err spd_add_smbios17_ddr4(const u8 channel, const u8 slot, const u16 sel
dimm->mod_id = info->manufacturer_id;

switch (info->dimm_type) {
case SPD_DIMM_TYPE_SO_DIMM:
case SPD_DDR4_DIMM_TYPE_SO_DIMM:
dimm->mod_type = SPD_SODIMM;
break;
case SPD_DIMM_TYPE_72B_SO_RDIMM:
case SPD_DDR4_DIMM_TYPE_72B_SO_RDIMM:
dimm->mod_type = SPD_72B_SO_RDIMM;
break;
case SPD_DIMM_TYPE_UDIMM:
case SPD_DDR4_DIMM_TYPE_UDIMM:
dimm->mod_type = SPD_UDIMM;
break;
case SPD_DIMM_TYPE_RDIMM:
case SPD_DDR4_DIMM_TYPE_RDIMM:
dimm->mod_type = SPD_RDIMM;
break;
default:
Expand Down
12 changes: 4 additions & 8 deletions src/device/i2c_bus.c
Expand Up @@ -25,10 +25,8 @@ struct bus *i2c_link(struct device *const dev)
link = NULL;
}

if (!link) {
printk(BIOS_ALERT, "%s Cannot find I2C or SMBus bus operations",
dev_path(dev));
}
if (!link)
printk(BIOS_ALERT, "%s Cannot find I2C or SMBus bus operations", dev_path(dev));

return link;
}
Expand Down Expand Up @@ -79,8 +77,7 @@ int i2c_dev_writeb(struct device *const dev, uint8_t val)
return busdev->ops->ops_smbus_bus->send_byte(dev, val);
}

printk(BIOS_ERR, "%s Missing ops_smbus_bus->send_byte",
dev_path(busdev));
printk(BIOS_ERR, "%s Missing ops_smbus_bus->send_byte", dev_path(busdev));
return -1;
}

Expand Down Expand Up @@ -140,8 +137,7 @@ int i2c_dev_writeb_at(struct device *const dev, const uint8_t off, const uint8_t
return busdev->ops->ops_smbus_bus->write_byte(dev, off, val);
}

printk(BIOS_ERR, "%s Missing ops_smbus_bus->write_byte",
dev_path(busdev));
printk(BIOS_ERR, "%s Missing ops_smbus_bus->write_byte", dev_path(busdev));
return -1;
}

Expand Down
5 changes: 4 additions & 1 deletion src/drivers/amd/i2s_machine_dev/chip.h
Expand Up @@ -12,7 +12,10 @@ struct drivers_amd_i2s_machine_dev_config {
/* ACPI _UID */
unsigned int uid;

/* DMIC select GPIO (required) */
/*
* DMIC select GPIO (optional). Needs to be configured if the audio framework cannot use
* all the mics and select the right channel based on the use-case.
*/
struct acpi_gpio dmic_select_gpio;
};

Expand Down
57 changes: 30 additions & 27 deletions src/drivers/amd/i2s_machine_dev/i2s_machine_dev.c
Expand Up @@ -9,10 +9,37 @@

#define AMD_I2S_ACPI_DESC "I2S machine driver"

static void i2s_machine_dev_fill_crs_dsd(const char *path,
const struct acpi_gpio *dmic_select_gpio)
{
struct acpi_dp *dsd;

/* Resources */
acpigen_write_name("_CRS");
acpigen_write_resourcetemplate_header();
acpi_device_write_gpio(dmic_select_gpio);
acpigen_write_resourcetemplate_footer();

dsd = acpi_dp_new_table("_DSD");
/*
* This GPIO is used to select DMIC0 or DMIC1 by the kernel driver. It does not
* really have a polarity since low and high control the selection of DMIC and
* hence does not have an active polarity.
* Kernel driver does not use the polarity field and instead treats the GPIO
* selection as follows:
* Set low (0) = Select DMIC0
* Set high (1) = Select DMIC1
*/
acpi_dp_add_gpio(dsd, "dmic-gpios", path,
0, /* Index = 0 (There is a single GPIO entry in _CRS). */
0, /* Pin = 0 (There is a single pin in the GPIO resource). */
0); /* Active low = 0 (Kernel driver does not use active polarity). */
acpi_dp_write(dsd);
}

static void i2s_machine_dev_fill_ssdt(const struct device *dev)
{
const char *scope = acpi_device_scope(dev);
struct acpi_dp *dsd;
const struct acpi_gpio *dmic_select_gpio;
const struct drivers_amd_i2s_machine_dev_config *cfg;
const char *path = acpi_device_path(dev);
Expand All @@ -31,11 +58,6 @@ static void i2s_machine_dev_fill_ssdt(const struct device *dev)
return;
}

if (dmic_select_gpio->pin_count == 0) {
printk(BIOS_ERR, "%s: ERROR: DMIC select GPIO required\n", dev_path(dev));
return;
}

acpigen_write_scope(scope); /* Scope */
acpigen_write_device(acpi_device_name(dev)); /* Device */
acpigen_write_name_string("_HID", cfg->hid);
Expand All @@ -44,27 +66,8 @@ static void i2s_machine_dev_fill_ssdt(const struct device *dev)

acpigen_write_STA(acpi_device_status(dev));

/* Resources */
acpigen_write_name("_CRS");
acpigen_write_resourcetemplate_header();
acpi_device_write_gpio(dmic_select_gpio);
acpigen_write_resourcetemplate_footer();

dsd = acpi_dp_new_table("_DSD");
/*
* This GPIO is used to select DMIC0 or DMIC1 by the kernel driver. It does not
* really have a polarity since low and high control the selection of DMIC and
* hence does not have an active polarity.
* Kernel driver does not use the polarity field and instead treats the GPIO
* selection as follows:
* Set low (0) = Select DMIC0
* Set high (1) = Select DMIC1
*/
acpi_dp_add_gpio(dsd, "dmic-gpios", path,
0, /* Index = 0 (There is a single GPIO entry in _CRS). */
0, /* Pin = 0 (There is a single pin in the GPIO resource). */
0); /* Active low = 0 (Kernel driver does not use active polarity). */
acpi_dp_write(dsd);
if (dmic_select_gpio->pin_count)
i2s_machine_dev_fill_crs_dsd(path, dmic_select_gpio);

acpigen_pop_len(); /* Device */
acpigen_pop_len(); /* Scope */
Expand Down
7 changes: 3 additions & 4 deletions src/drivers/elog/elog.c
Expand Up @@ -44,7 +44,7 @@ struct elog_state {

struct region_device nv_dev;
/* Device that mirrors the eventlog in memory. */
struct mem_region_device mirror_dev;
struct region_device mirror_dev;

enum elog_init_state elog_initialized;
};
Expand All @@ -56,7 +56,7 @@ static uint8_t elog_mirror_buf[ELOG_SIZE];

static inline struct region_device *mirror_dev_get(void)
{
return &elog_state.mirror_dev.rdev;
return &elog_state.mirror_dev;
}

static size_t elog_events_start(void)
Expand Down Expand Up @@ -798,8 +798,7 @@ int elog_init(void)
printk(BIOS_ERR, "ELOG: Unable to allocate backing store\n");
return -1;
}
mem_region_device_rw_init(&elog_state.mirror_dev, mirror_buffer,
elog_size);
rdev_chain_mem_rw(&elog_state.mirror_dev, mirror_buffer, elog_size);

/*
* Mark as initialized to allow elog_init() to be called and deemed
Expand Down
3 changes: 3 additions & 0 deletions src/drivers/generic/nau8315/Kconfig
@@ -0,0 +1,3 @@
config DRIVERS_GENERIC_NAU8315
bool
depends on HAVE_ACPI_TABLES
1 change: 1 addition & 0 deletions src/drivers/generic/nau8315/Makefile.inc
@@ -0,0 +1 @@
ramstage-$(CONFIG_DRIVERS_GENERIC_NAU8315) += nau8315.c
8 changes: 8 additions & 0 deletions src/drivers/generic/nau8315/chip.h
@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <acpi/acpi_device.h>

struct drivers_generic_nau8315_config {
/* ENABLE GPIO */
struct acpi_gpio enable_gpio;
};
74 changes: 74 additions & 0 deletions src/drivers/generic/nau8315/nau8315.c
@@ -0,0 +1,74 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <acpi/acpi_device.h>
#include <acpi/acpigen.h>
#include <console/console.h>
#include <device/device.h>
#include <device/path.h>
#include <gpio.h>
#include "chip.h"

static void nau8315_fill_ssdt(const struct device *dev)
{
struct drivers_generic_nau8315_config *config = dev->chip_info;
const char *path;
struct acpi_dp *dp;

if (!dev->enabled || !config)
return;

const char *scope = acpi_device_scope(dev);
const char *name = acpi_device_name(dev);
if (!scope || !name)
return;

/* Device */
acpigen_write_scope(scope);
acpigen_write_device(name);

acpigen_write_name_string("_HID", "NVTN2010");
acpigen_write_name_integer("_UID", 0);
acpigen_write_name_string("_DDN", dev->chip_ops->name);
acpigen_write_STA(acpi_device_status(dev));

/* Resources */
acpigen_write_name("_CRS");
acpigen_write_resourcetemplate_header();
acpi_device_write_gpio(&config->enable_gpio);
acpigen_write_resourcetemplate_footer();

/* _DSD for devicetree properties */
/* This points to the first pin in the first gpio entry in _CRS */
path = acpi_device_path(dev);
dp = acpi_dp_new_table("_DSD");
acpi_dp_add_gpio(dp, "enable-gpios", path, 0, 0,
config->enable_gpio.active_low);
acpi_dp_write(dp);

acpigen_pop_len(); /* Device */
acpigen_pop_len(); /* Scope */

printk(BIOS_INFO, "%s: %s\n", path, dev->chip_ops->name);
}

static const char *nau8315_acpi_name(const struct device *dev)
{
return "NVTN";
}

static struct device_operations nau8315_ops = {
.read_resources = noop_read_resources,
.set_resources = noop_set_resources,
.acpi_name = nau8315_acpi_name,
.acpi_fill_ssdt = nau8315_fill_ssdt,
};

static void nau8315_enable(struct device *dev)
{
dev->ops = &nau8315_ops;
}

struct chip_operations drivers_generic_nau8315_ops = {
CHIP_NAME("Nuvoton NAU8315 Amplifier")
.enable_dev = nau8315_enable
};
3 changes: 3 additions & 0 deletions src/drivers/i2c/cs42l42/Kconfig
@@ -0,0 +1,3 @@
config DRIVERS_I2C_CS42L42
bool
depends on HAVE_ACPI_TABLES
1 change: 1 addition & 0 deletions src/drivers/i2c/cs42l42/Makefile.inc
@@ -0,0 +1 @@
ramstage-$(CONFIG_DRIVERS_I2C_CS42L42) += cs42l42.c
109 changes: 109 additions & 0 deletions src/drivers/i2c/cs42l42/chip.h
@@ -0,0 +1,109 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <acpi/acpi_device.h>

enum cs42l42_ts_dbnc_rise {
RISE_DEB_0_MS = 0,
RISE_DEB_125_MS = 1,
RISE_DEB_250_MS = 2,
RISE_DEB_500_MS = 3,
RISE_DEB_750_MS = 4,
RISE_DEB_1000_MS = 5,
RISE_DEB_1250_MS = 6,
RISE_DEB_1500_MS = 7,
};

enum cs42l42_ts_dbnc_fall {
FALL_DEB_0_MS = 0,
FALL_DEB_125_MS = 1,
FALL_DEB_250_MS = 2,
FALL_DEB_500_MS = 3,
FALL_DEB_750_MS = 4,
FALL_DEB_1000_MS = 5,
FALL_DEB_1250_MS = 6,
FALL_DEB_1500_MS = 7,
};

enum cs42l42_hs_bias_ramp_rate {
HSBIAS_RAMP_FAST_RISE_SLOW_FALL = 0,
HSBIAS_RAMP_FAST = 1,
HSBIAS_RAMP_SLOW = 2,
HSBIAS_RAMP_SLOWEST = 3,
};

/*
* Cirrus Logic CS42L42 Audio Codec devicetree bindings
* linux/Documentation/devicetree/bindings/sound/cs42l42.txt
*/
struct drivers_i2c_cs42l42_config {
/* Interrupt configuration */
struct acpi_irq irq;

/* Use GPIO based interrupt instead of PIRQ */
struct acpi_gpio irq_gpio;

/* Use GPIO based reset gpio */
struct acpi_gpio reset_gpio;

/* I2C Bus Frequency in Hertz (default 400kHz) */
unsigned int bus_speed;

/* Define cs42L42 parameters */
/*
* cirrus,ts-inv : Boolean property. For jacks that invert the tip sense
* polarity. Normal jacks will short tip sense pin to HS1 when headphones are
* plugged in and leave tip sense floating when not plugged in. Inverting jacks
* short tip sense when unplugged and float when plugged in.
* false = Non-inverted
* true = Inverted
* Default = Non-inverted
*/
bool ts_inv;
/*
* cirrus,ts-dbnc-rise : Debounce the rising edge of TIP_SENSE_PLUG. With no
* debounce, the tip sense pin might be noisy on a plug event.
* Default = RISE_DEB_1000_MS
*/
enum cs42l42_ts_dbnc_rise ts_dbnc_rise;
/*
* cirrus,ts-dbnc-fall : Debounce the falling edge of TIP_SENSE_UNPLUG.
* With no debounce, the tip sense pin might be noisy on an unplug event.
* Default = FALL_DEB_1000_MS
*/
enum cs42l42_ts_dbnc_fall ts_dbnc_fall;
/*
* cirrus,btn-det-init-dbnce : This sets how long the driver sleeps after
* enabling button detection interrupts. After auto-detection and before
* servicing button interrupts, the HS bias needs time to settle. If you
* don't wait, there is possibility for erroneous button interrupt.
* Value in ms, 0 - 200.
* Default = 100ms
*/
unsigned int btn_det_init_dbnce;
/*
* cirrus,btn-det-event-dbnce : This sets how long the driver delays after
* receiving a button press interrupt. With level detect interrupts, you want
* to wait a small amount of time to make sure the button press is making a
* clean connection with the bias resistors.
* Value in ms, 0 - 20.
* Default = 10ms
*/
unsigned int btn_det_event_dbnce;
/*
* cirrus,bias-lvls : For a level-detect headset button scheme, each button
* will bias the mic pin to a certain voltage. To determine which button was
* pressed, the driver will compare this biased voltage to sequential,
* decreasing voltages and will stop when a comparator is tripped,
* indicating a comparator voltage < bias voltage. This value represents a
* percentage of the internally generated HS bias voltage. For different
* hardware setups, a designer might want to tweak this. This is an array of
* descending values for the comparator voltage.
* Array of 4 values
* Each 0-63
* < x1 x2 x3 x4 >
* Default = < 15 8 4 1>
*/
uint64_t bias_lvls[4];
/* headset bias ramp rate */
enum cs42l42_hs_bias_ramp_rate hs_bias_ramp_rate;
};
122 changes: 122 additions & 0 deletions src/drivers/i2c/cs42l42/cs42l42.c
@@ -0,0 +1,122 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <acpi/acpi.h>
#include <acpi/acpi_device.h>
#include <acpi/acpigen.h>
#include <console/console.h>
#include <device/i2c_simple.h>
#include <device/device.h>
#include <device/path.h>

#include "chip.h"

#define CS42L42_ACPI_NAME "CRUS"
#define CS42L42_ACPI_HID "10134242"

static void cs42l42_fill_ssdt(const struct device *dev)
{
struct drivers_i2c_cs42l42_config *config = dev->chip_info;
const char *scope = acpi_device_scope(dev);
const char *path = acpi_device_path(dev);
struct acpi_i2c i2c = {
.address = dev->path.i2c.device,
.mode_10bit = dev->path.i2c.mode_10bit,
.speed = config->bus_speed ? : I2C_SPEED_FAST,
.resource = scope,
};
struct acpi_dp *dsd;
int gpio_index = 0;

if (!scope)
return;

/* Device */
acpigen_write_scope(scope);
acpigen_write_device(acpi_device_name(dev));
acpigen_write_name_string("_HID", CS42L42_ACPI_HID);
acpigen_write_name_integer("_UID", 0);
acpigen_write_name_string("_DDN", dev->chip_ops->name);
acpigen_write_STA(acpi_device_status(dev));

/* Resources */
acpigen_write_name("_CRS");
acpigen_write_resourcetemplate_header();
acpi_device_write_i2c(&i2c);
/* Use either Interrupt() or GpioInt() */
if (config->irq_gpio.pin_count)
acpi_device_write_gpio(&config->irq_gpio);
else
acpi_device_write_interrupt(&config->irq);

/* for cs42l42reset gpio */
if (config->reset_gpio.pin_count)
acpi_device_write_gpio(&config->reset_gpio);

acpigen_write_resourcetemplate_footer();

/* AAD Child Device Properties */
dsd = acpi_dp_new_table("_DSD");
if (config->irq_gpio.pin_count)
acpi_dp_add_gpio(dsd, "irq-gpios", path,
gpio_index++, /* Index = 0 */
0, /* Pin = 0 (There is a single pin in the GPIO resource). */
config->irq_gpio.active_low);
if (config->reset_gpio.pin_count)
acpi_dp_add_gpio(dsd, "reset-gpios", path,
gpio_index++, /* Index = 0 or 1 (if irq gpio is written). */
0, /* Pin = 0 (There is a single pin in the GPIO resource). */
config->reset_gpio.active_low);
acpi_dp_add_integer(dsd, "cirrus,ts-inv", config->ts_inv ? 1 : 0);
acpi_dp_add_integer(dsd, "cirrus,ts-dbnc-rise", config->ts_dbnc_rise);
acpi_dp_add_integer(dsd, "cirrus,ts-dbnc-fall", config->ts_dbnc_fall);
acpi_dp_add_integer(dsd, "cirrus,btn-det-init-dbnce", config->btn_det_init_dbnce);

if (config->btn_det_init_dbnce > 200) {
printk(BIOS_ERR, "%s: Incorrect btn_det_init_dbnce(%d). Using default of 100ms\n",
__func__, config->btn_det_init_dbnce);
config->btn_det_init_dbnce = 100;
}

acpi_dp_add_integer(dsd, "cirrus,btn-det-event-dbnce", config->btn_det_event_dbnce);

if (config->btn_det_event_dbnce > 100) {
printk(BIOS_ERR, "%s: Incorrect btn_det_event_dbnce(%d). Using default of 10ms\n",
__func__, config->btn_det_event_dbnce);
config->btn_det_event_dbnce = 10;
}

acpi_dp_add_integer_array(dsd, "cirrus,bias-lvls", config->bias_lvls, 4);
acpi_dp_add_integer(dsd, "cirrus,hs-bias-ramp-rate", config->hs_bias_ramp_rate);

/* Write Device Property Hierarchy */
acpi_dp_write(dsd);

acpigen_pop_len(); /* Device */
acpigen_pop_len(); /* Scope */

printk(BIOS_INFO, "%s: %s address 0%xh irq %d\n",
acpi_device_path(dev), dev->chip_ops->name,
dev->path.i2c.device, config->irq.pin);
}

static const char *cs42l42_acpi_name(const struct device *dev)
{
return CS42L42_ACPI_NAME;
}

static struct device_operations cs42l42_ops = {
.read_resources = noop_read_resources,
.set_resources = noop_set_resources,
.acpi_name = cs42l42_acpi_name,
.acpi_fill_ssdt = cs42l42_fill_ssdt,
};

static void cs42l42_enable(struct device *dev)
{
dev->ops = &cs42l42_ops;
}

struct chip_operations drivers_i2c_cs42l42_ops = {
CHIP_NAME("Cirrus Logic CS42l42 Audio Codec")
.enable_dev = cs42l42_enable
};
1 change: 1 addition & 0 deletions src/drivers/i2c/nau8825/chip.h
Expand Up @@ -11,6 +11,7 @@
struct drivers_i2c_nau8825_config {
/* Interrupt configuration */
struct acpi_irq irq;
struct acpi_gpio irq_gpio;

/* I2C Bus Frequency in Hertz (default 400kHz) */
unsigned int bus_speed;
Expand Down
6 changes: 5 additions & 1 deletion src/drivers/i2c/nau8825/nau8825.c
Expand Up @@ -47,7 +47,11 @@ static void nau8825_fill_ssdt(const struct device *dev)
acpigen_write_name("_CRS");
acpigen_write_resourcetemplate_header();
acpi_device_write_i2c(&i2c);
acpi_device_write_interrupt(&config->irq);
/* Allow either GpioInt() or Interrupt() */
if (config->irq_gpio.pin_count)
acpi_device_write_gpio(&config->irq_gpio);
else
acpi_device_write_interrupt(&config->irq);
acpigen_write_resourcetemplate_footer();

/* Device Properties */
Expand Down
5 changes: 5 additions & 0 deletions src/drivers/i2c/tas5825m/Kconfig
@@ -0,0 +1,5 @@
config DRIVERS_I2C_TAS5825M
bool
default n
help
Enable support for TI TAS5825M Amplifier.
1 change: 1 addition & 0 deletions src/drivers/i2c/tas5825m/Makefile.inc
@@ -0,0 +1 @@
ramstage-$(CONFIG_DRIVERS_I2C_TAS5825M) += tas5825m.c
6 changes: 6 additions & 0 deletions src/drivers/i2c/tas5825m/chip.h
@@ -0,0 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */

struct drivers_i2c_tas5825m_config {
// Used to uniquely identify the AMP
int id;
};
80 changes: 80 additions & 0 deletions src/drivers/i2c/tas5825m/tas5825m.c
@@ -0,0 +1,80 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <console/console.h>
#include <device/smbus.h>
#include <device/pci.h>
#include "chip.h"
#include "tas5825m.h"

int tas5825m_write_at(struct device *dev, uint8_t addr, uint8_t value)
{
return smbus_write_byte(dev, addr, value);
}

//TODO: use I2C block write for better performance
int tas5825m_write_block_at(struct device *dev, uint8_t addr,
const uint8_t *values, uint8_t length)
{
int res = 0;
for (uint8_t i = 0; i < length; i++) {
res = smbus_write_byte(dev, addr + i, values[i]);
if (res < 0)
return res;
}
return (int)length;
}

int tas5825m_set_page(struct device *dev, uint8_t page)
{
return tas5825m_write_at(dev, 0x00, page);
}

int tas5825m_set_book(struct device *dev, uint8_t book)
{
int res = tas5825m_set_page(dev, 0x00);
if (res < 0)
return res;
return tas5825m_write_at(dev, 0x7F, book);
}

__weak int tas5825m_setup(struct device *dev, int id)
{
printk(BIOS_ERR, "tas5825m: setup not implemented\n");
return -1;
}

static void tas5825m_init(struct device *dev)
{
if (dev->enabled && dev->path.type == DEVICE_PATH_I2C &&
ops_smbus_bus(get_pbus_smbus(dev))) {
printk(BIOS_DEBUG, "tas5825m at %s\n", dev_path(dev));

struct drivers_i2c_tas5825m_config *config = dev->chip_info;
if (config) {
printk(BIOS_DEBUG, "tas5825m id %d\n", config->id);
int res = tas5825m_setup(dev, config->id);
if (res)
printk(BIOS_ERR, "tas5825m init failed: %d\n", res);
else
printk(BIOS_DEBUG, "tas5825m init successful\n");
} else {
printk(BIOS_ERR, "tas5825m: failed to find config\n");
}
}
}

static struct device_operations tas5825m_operations = {
.read_resources = noop_read_resources,
.set_resources = noop_set_resources,
.init = tas5825m_init,
};

static void tas5825m_enable_dev(struct device *dev)
{
dev->ops = &tas5825m_operations;
}

struct chip_operations drivers_i2c_tas5825m_ops = {
CHIP_NAME("TI TAS5825M Amplifier")
.enable_dev = tas5825m_enable_dev,
};
15 changes: 15 additions & 0 deletions src/drivers/i2c/tas5825m/tas5825m.h
@@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef TAS5825M_H
#define TAS5825M_H

#include <device/device.h>

int tas5825m_write_at(struct device *dev, uint8_t addr, uint8_t value);
int tas5825m_write_block_at(struct device *dev, uint8_t addr,
const uint8_t *values, uint8_t length);
int tas5825m_set_page(struct device *dev, uint8_t page);
int tas5825m_set_book(struct device *dev, uint8_t book);
int tas5825m_setup(struct device *dev, int id);

#endif // TAS5825M_H
10 changes: 0 additions & 10 deletions src/drivers/intel/dptf/Kconfig
Expand Up @@ -5,13 +5,3 @@ config DRIVERS_INTEL_DPTF
help
When enabled, entries in the devicetree are used to generate
Intel DPTF Tables at runtime in the SSDT.

config DPTF_USE_EISA_HID
bool
depends on DRIVERS_INTEL_DPTF
default n
help
Prior to Tiger Lake, all DPTF devices used 7-character EISA
IDs. If selected, the 7-character _HIDs will be emitted,
otherwise, it will use the "new" style, which are regular
8-character _HIDs.
61 changes: 29 additions & 32 deletions src/drivers/intel/dptf/dptf.c
Expand Up @@ -5,6 +5,7 @@
#include <console/console.h>
#include <device/device.h>
#include "chip.h"
#include "dptf.h"

/* Generic DPTF participants have a PTYP field to distinguish them */
enum dptf_generic_participant_type {
Expand All @@ -14,14 +15,6 @@ enum dptf_generic_participant_type {

#define DEFAULT_CHARGER_STR "Battery Charger"

#define DPTF_DEVICE_HID_EISAID "INT3400"
#define GENERIC_HID_EISAID "INT3403"
#define FAN_HID_EISAID "INT3404"

#define DPTF_DEVICE_HID "INTC1040"
#define GENERIC_HID "INTC1043"
#define FAN_HID "INTC1044"

/*
* Helper method to determine if a device is "used" (called out anywhere as a source or a target
* of any policies, and therefore should be included in the ACPI tables.
Expand Down Expand Up @@ -67,20 +60,26 @@ static int get_STA_value(const struct drivers_intel_dptf_config *config,
ACPI_STATUS_DEVICE_ALL_OFF;
}

static void dptf_write_hid(bool is_eisa, const char *hid)
{
if (is_eisa)
acpigen_emit_eisaid(hid);
else
acpigen_write_string(hid);
}

/* Devices with GENERIC _HID (distinguished by PTYP) */
static void dptf_write_generic_participant(const char *name,
enum dptf_generic_participant_type ptype,
const char *str, int sta_val)
const char *str, int sta_val,
const struct dptf_platform_info *platform_info)
{
/* Auto-incrementing UID for generic participants */
static int generic_uid = 0;

acpigen_write_device(name);
acpigen_write_name("_HID");
if (CONFIG(DPTF_USE_EISA_HID))
acpigen_emit_eisaid(GENERIC_HID_EISAID);
else
acpigen_write_string(GENERIC_HID);
dptf_write_hid(platform_info->use_eisa_hids, platform_info->generic_hid);

acpigen_write_name_integer("_UID", generic_uid++);
acpigen_write_STA(sta_val);
Expand All @@ -107,56 +106,54 @@ static void write_tcpu(const struct device *pci_dev,
}

/* \_SB.DPTF.TFN1 */
static void write_fan(const struct drivers_intel_dptf_config *config)
static void write_fan(const struct drivers_intel_dptf_config *config,
const struct dptf_platform_info *platform_info)
{
acpigen_write_device("TFN1");
acpigen_write_name("_HID");
if (CONFIG(DPTF_USE_EISA_HID))
acpigen_emit_eisaid(FAN_HID_EISAID);
else
acpigen_write_string(FAN_HID);

dptf_write_hid(platform_info->use_eisa_hids, platform_info->fan_hid);
acpigen_write_name_integer("_UID", 0);
acpigen_write_STA(get_STA_value(config, DPTF_FAN));
acpigen_pop_len(); /* Device */
}

/* \_SB.DPTF.xxxx */
static void write_generic_devices(const struct drivers_intel_dptf_config *config)
static void write_generic_devices(const struct drivers_intel_dptf_config *config,
const struct dptf_platform_info *platform_info)
{
enum dptf_participant participant;
char name[ACPI_NAME_BUFFER_SIZE];
int i;

dptf_write_generic_participant("TCHG", DPTF_GENERIC_PARTICIPANT_TYPE_CHARGER,
DEFAULT_CHARGER_STR, get_STA_value(config,
DPTF_CHARGER));
DEFAULT_CHARGER_STR,
get_STA_value(config, DPTF_CHARGER),
platform_info);

for (i = 0, participant = DPTF_TEMP_SENSOR_0; i < 4; ++i, ++participant) {
snprintf(name, sizeof(name), "TSR%1d", i);
dptf_write_generic_participant(name, DPTF_GENERIC_PARTICIPANT_TYPE_TSR,
NULL, get_STA_value(config, participant));
NULL, get_STA_value(config, participant),
platform_info);
}
}

/* \_SB.DPTF - note: leaves the Scope open for child devices*/
static void write_open_dptf_device(const struct device *dev)
static void write_open_dptf_device(const struct device *dev,
const struct dptf_platform_info *platform_info)
{
acpigen_write_scope("\\_SB");
acpigen_write_device(acpi_device_name(dev));
acpigen_write_name("_HID");
if (CONFIG(DPTF_USE_EISA_HID))
acpigen_emit_eisaid(DPTF_DEVICE_HID_EISAID);
else
acpigen_write_string(DPTF_DEVICE_HID);

dptf_write_hid(platform_info->use_eisa_hids, platform_info->dptf_device_hid);
acpigen_write_name_integer("_UID", 0);
acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
}

/* Add minimal definitions of DPTF devices into the SSDT */
static void write_device_definitions(const struct device *dev)
{
const struct dptf_platform_info *platform_info = get_dptf_platform_info();
const struct drivers_intel_dptf_config *config;
struct device *parent;

Expand All @@ -170,9 +167,9 @@ static void write_device_definitions(const struct device *dev)

config = config_of(dev);
write_tcpu(parent, config);
write_open_dptf_device(dev);
write_fan(config);
write_generic_devices(config);
write_open_dptf_device(dev, platform_info);
write_fan(config, platform_info);
write_generic_devices(config, platform_info);

acpigen_pop_len(); /* DPTF Device (write_open_dptf_device) */
acpigen_pop_len(); /* Scope */
Expand Down
21 changes: 21 additions & 0 deletions src/drivers/intel/dptf/dptf.h
@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef _DRIVERS_INTEL_DPTF_H_
#define _DRIVERS_INTEL_DPTF_H_

#include <types.h>

struct dptf_platform_info {
/*
* True indicates the platform-specific HIDs are to be emitted in EISA
* format instead of a string.
*/
bool use_eisa_hids;
const char *dptf_device_hid;
const char *generic_hid;
const char *fan_hid;
};

const struct dptf_platform_info *get_dptf_platform_info(void);

#endif /* _DRIVERS_INTEL_DPTF_H_ */
2 changes: 0 additions & 2 deletions src/drivers/intel/fsp1_1/Makefile.inc
Expand Up @@ -16,14 +16,12 @@ romstage-y += fsp_util.c
romstage-y += hob.c
romstage-y += raminit.c
romstage-y += romstage.c
romstage-$(CONFIG_MMA) += mma_core.c

ramstage-y += fsp_relocate.c
ramstage-y += fsp_util.c
ramstage-y += hob.c
ramstage-y += ramstage.c
ramstage-$(CONFIG_INTEL_GMA_ADD_VBT) += vbt.c
ramstage-$(CONFIG_MMA) += mma_core.c

CPPFLAGS_common += -Isrc/drivers/intel/fsp1_1/include

Expand Down
38 changes: 0 additions & 38 deletions src/drivers/intel/fsp1_1/mma_core.c

This file was deleted.

17 changes: 17 additions & 0 deletions src/drivers/intel/fsp2_0/Kconfig.debug_blob
Expand Up @@ -45,4 +45,21 @@ config DISPLAY_FSP_VERSION_INFO_2
Select this option to display Firmware version information
using new header 'FirmwareVersionInfo.h'.

config HAVE_GPIO_SNAPSHOT_VERIFY_SUPPORT
bool
default n
help
Select this option if platform provides support for GPIO
config snapshot and verify callbacks: `gpio_snapshot()`
and `gpio_verify_snapshot()`

config CHECK_GPIO_CONFIG_CHANGES
bool "Check GPIO config changes across calls to FSP-S"
depends on HAVE_GPIO_SNAPSHOT_VERIFY_SUPPORT
help
Select this option to identify if any GPIOs are re-configured
by FSP-S differently than the mainboard configuration. This
requires platform support to snapshot and verify that config
matches snapshot.

endif # PLATFORM_USES_FSP2_0