soc/intel/elkhartlake: Introduce Intel PSE

The Intel® Programmable Services Engine (Intel® PSE) is a
dedicated offload engine for IoT functions powered by an ARM
Cortex-M7 microcontroller. It provides independent, low-DMIPS
computing and low-speed I/Os for IoT applications, plus
dedicated services for real-time computing and time-sensitive
synchronization.

The PSE hosts new functions, including remote out-of-band
device management, network proxy, embedded controller lite
and sensor hub.

This CL enables the user to provide the base address of the
PSE FW blob which will then be loaded by the FSP-S onto the
ARM controller. PSE FW will do the initialization work of
PSE controller and its peripherals. The loading of PSE FW
should have negligible impact on boot time unless PSE
controller could not locate the PSE FW and FSP will attempt to
redo PSE FW loading and wait for PSE handshake until it times
out. Once PSE controller locate the PSE FW, it will do
initialization concurrently by itself with coreboot booting.

It also adds PSE related FSP-S UPD settings which enable the
setup of peripheral ownership (assigned to the PSE or x86
subsystem) and interrupts. These assignments need to take
place at a given point in the boot process and cannot be
changed later.

To verify if PSE FW is loaded properly, the user could enable
PchPseShellEnabled flag and the log will be printed at PSE UART
2.

For further info please refer to doc #611825 (for HW overview)
and #614110 (for PSE EDS).

Signed-off-by: Lean Sheng Tan <lean.sheng.tan@intel.com>
Change-Id: Ifea08fb82fea18ef66bab04b3ce378e79a0afbf7
Reviewed-on: https://review.coreboot.org/c/coreboot/+/55367
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Werner Zeh <werner.zeh@siemens.com>
This commit is contained in:
Lean Sheng Tan 2021-06-09 13:58:12 -07:00 committed by Felix Held
parent 36425312ee
commit 5cd7579ee5
5 changed files with 173 additions and 1 deletions

View File

@ -194,6 +194,44 @@ config FSP_FD_PATH
depends on FSP_USE_REPO
default "3rdparty/fsp/ElkhartLakeFspBinPkg/FspBin/FSPRel.bin"
config PSE_ENABLE
bool "Enable PSE ARM controller"
help
Enable PSE IP. The PSE describes the integrated programmable
service engine that is designed together with x86 Atom cores
as an Asymmetric Multi-Processing (AMP) system.
config ADD_PSE_IMAGE_TO_CBFS
bool "Add PSE Firmware to CBFS"
depends on PSE_ENABLE
default n
help
PSE FW binary is required to use PSE dedicated peripherals from
x86 subsystem. Once PSE is enabled, the FW will be loaded from
CBFS by FSP and executed.
config PSE_IMAGE_FILE
string "PSE binary path and filename"
depends on ADD_PSE_IMAGE_TO_CBFS
help
The path and filename of the PSE binary.
config PSE_FW_FILE_SIZE_KIB
hex "Memory buffer (KiB) for PSE FW image"
depends on ADD_PSE_IMAGE_TO_CBFS
default 0x200
help
It is recommended to allocate at least 512 KiB for PSE FW.
config PSE_CONFIG_BUFFER_SIZE_KIB
hex "Memory buffer (KiB) for PSE config data"
depends on ADD_PSE_IMAGE_TO_CBFS
default 0x100
help
It is recommended to allocate at least 256 KiB for PSE config
data (FSP will append PSE config data to memory region right
after PSE FW memory region).
config SOC_INTEL_ELKHARTLAKE_DEBUG_CONSENT
int "Debug Consent for EHL"
# USB DBC is more common for developers so make this default to 3 if

View File

@ -51,5 +51,18 @@ CPPFLAGS_common += -I$(src)/soc/intel/elkhartlake/include
# B0 stepping
cpu_microcode_bins += 3rdparty/intel-microcode/intel-ucode/06-96-01
cbfs-files-$(CONFIG_ADD_PSE_IMAGE_TO_CBFS) += pse.bin
pse.bin-file := $(CONFIG_PSE_IMAGE_FILE)
pse.bin-type := raw
pse.bin-compression := lzma
# Add a build time check if the PSE file size fits
ifeq ($(CONFIG_ADD_PSE_IMAGE_TO_CBFS),y)
ifeq ($(call int-gt,\
$(call file-size,$(CONFIG_PSE_IMAGE_FILE))\
$(shell printf "%d" $(call int-shift-left, $(CONFIG_PSE_FW_FILE_SIZE_KIB) 10))), 1)
$(error PSE binary larger than CONFIG_PSE_FW_FILE_SIZE_KIB.)
endif
endif # CONFIG_ADD_PSE_IMAGE_TO_CBFS
endif

View File

@ -48,6 +48,18 @@ enum tsn_gbe_link_speed {
Tsn_1_Gbps,
};
/*
* PSE native pins and ownership assignment:-
* 0: Disable/pins are not owned by PSE/host
* 1: Pins are muxed to PSE IP, the IO is owned by PSE
* 2: Pins are muxed to PSE IP, the IO is owned by host
*/
enum pse_device_ownership {
Device_Disabled,
PSE_Owned,
Host_Owned,
};
/*
* Enable external V1P05 Rail in: BIT0:S0i1/S0i2,
* BIT1:S0i3, BIT2:S3, BIT3:S4, BIT4:S5
@ -453,6 +465,46 @@ struct soc_intel_elkhartlake_config {
bool PchTsnGbeSgmiiEnable;
/* PCH TSN GBE Multiple Virtual Channel: Disable (0) / Enable (1) */
bool PchTsnGbeMultiVcEnable;
/* PSE related */
/*
* PSE (Intel Programmable Services Engine) native pins and ownership
* assignment. If the device is configured as 'PSE owned', PSE will have
* full control of specific device and it will be hidden from coreboot
* and OS. If the device is configured as 'Host owned', the device will
* be visible to coreboot and OS as a PCI device, while PSE will still
* do some IP initialization and pin assignment works.
*
* PSE is still required during runtime to ensure any of PSE devices
* works properly.
*/
enum pse_device_ownership PseDmaOwn[3];
enum pse_device_ownership PseUartOwn[6];
enum pse_device_ownership PseHsuartOwn[4];
enum pse_device_ownership PseQepOwn[4];
enum pse_device_ownership PseI2cOwn[8];
enum pse_device_ownership PseI2sOwn[2];
enum pse_device_ownership PseSpiOwn[4];
enum pse_device_ownership PseSpiCs0Own[4];
enum pse_device_ownership PseSpiCs1Own[4];
enum pse_device_ownership PseCanOwn[2];
enum pse_device_ownership PsePwmOwn;
enum pse_device_ownership PseAdcOwn;
/* PSE devices sideband interrupt: Disable (0) / Enable (1) */
bool PseDmaSbIntEn[3];
bool PseUartSbIntEn[6];
bool PseQepSbIntEn[4];
bool PseI2cSbIntEn[8];
bool PseI2sSbIntEn[2];
bool PseSpiSbIntEn[4];
bool PseCanSbIntEn[2];
bool PseLh2PseSbIntEn;
bool PsePwmSbIntEn;
bool PseAdcSbIntEn;
/* PSE PWM native function: Disable (0) / Enable (1) */
bool PsePwmPinEn[16];
/* PSE Console Shell */
bool PseShellEn;
};
typedef struct soc_intel_elkhartlake_config config_t;

View File

@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <assert.h>
#include <cbfs.h>
#include <console/console.h>
#include <device/device.h>
#include <fsp/api.h>
@ -78,6 +79,70 @@ static void fill_fsps_fivr_params(FSP_S_CONFIG *s_cfg,
s_cfg->FivrSpreadSpectrum = config->fivr.spread_spectrum;
}
static void fill_fsps_pse_params(FSP_S_CONFIG *params,
const struct soc_intel_elkhartlake_config *config)
{
static char psefwbuf[(CONFIG_PSE_FW_FILE_SIZE_KIB +
CONFIG_PSE_CONFIG_BUFFER_SIZE_KIB) * KiB];
uint32_t pse_fw_base;
size_t psefwsize = cbfs_load("pse.bin", psefwbuf, sizeof(psefwbuf));
if (psefwsize > 0) {
pse_fw_base = (uintptr_t)&psefwbuf;
params->SiipRegionBase = pse_fw_base;
params->SiipRegionSize = psefwsize;
printk(BIOS_DEBUG, "PSE base: %08x size: %08zx\n", pse_fw_base, psefwsize);
/* Configure PSE peripherals */
FSP_ARRAY_LOAD(params->PchPseDmaEnable, config->PseDmaOwn);
FSP_ARRAY_LOAD(params->PchPseDmaSbInterruptEnable, config->PseDmaSbIntEn);
FSP_ARRAY_LOAD(params->PchPseUartEnable, config->PseUartOwn);
FSP_ARRAY_LOAD(params->PchPseUartSbInterruptEnable, config->PseUartSbIntEn);
FSP_ARRAY_LOAD(params->PchPseHsuartEnable, config->PseHsuartOwn);
FSP_ARRAY_LOAD(params->PchPseQepEnable, config->PseQepOwn);
FSP_ARRAY_LOAD(params->PchPseQepSbInterruptEnable, config->PseQepSbIntEn);
FSP_ARRAY_LOAD(params->PchPseI2cEnable, config->PseI2cOwn);
FSP_ARRAY_LOAD(params->PchPseI2cSbInterruptEnable, config->PseI2cSbIntEn);
FSP_ARRAY_LOAD(params->PchPseI2sEnable, config->PseI2sOwn);
FSP_ARRAY_LOAD(params->PchPseI2sSbInterruptEnable, config->PseI2sSbIntEn);
FSP_ARRAY_LOAD(params->PchPseSpiEnable, config->PseSpiOwn);
FSP_ARRAY_LOAD(params->PchPseSpiSbInterruptEnable, config->PseSpiSbIntEn);
FSP_ARRAY_LOAD(params->PchPseSpiCs0Enable, config->PseSpiCs0Own);
FSP_ARRAY_LOAD(params->PchPseSpiCs1Enable, config->PseSpiCs1Own);
FSP_ARRAY_LOAD(params->PchPseCanEnable, config->PseCanOwn);
FSP_ARRAY_LOAD(params->PchPseCanSbInterruptEnable, config->PseCanSbIntEn);
params->PchPsePwmEnable = config->PsePwmOwn;
params->PchPsePwmSbInterruptEnable = config->PsePwmSbIntEn;
FSP_ARRAY_LOAD(params->PchPsePwmPinEnable, config->PsePwmPinEn);
params->PchPseAdcEnable = config->PseAdcOwn;
params->PchPseAdcSbInterruptEnable = config->PseAdcSbIntEn;
params->PchPseLh2PseSbInterruptEnable = config->PseLh2PseSbIntEn;
params->PchPseShellEnabled = config->PseShellEn;
/*
* As a minimum requirement for PSE initialization, the configuration
* of devices below are required as shown.
* TODO: Help needed to find a better way to handle this part of code
* as the settings from devicetree are overwritten here.
*
* Set the ownership of these devices to PSE. These are hardcoded for now,
* if the PSE should be opened one day (hopefully), this can be handled
* much better.
*/
params->PchPseDmaEnable[0] = PSE_Owned;
params->PchPseUartEnable[2] = PSE_Owned;
params->PchPseHsuartEnable[2] = PSE_Owned;
params->PchPseI2cEnable[2] = PSE_Owned;
params->PchPseTimedGpioEnable[0] = PSE_Owned;
params->PchPseTimedGpioEnable[1] = PSE_Owned;
/* Disable PSE DMA Sideband Interrupt for DMA 0 */
params->PchPseDmaSbInterruptEnable[0] = 0;
/* Set the log output to PSE UART 2 */
params->PchPseLogOutputChannel = 3;
} else {
die("PSE enabled but PSE FW not available!\n");
}
}
static void parse_devicetree(FSP_S_CONFIG *params)
{
const struct soc_intel_elkhartlake_config *config = config_of_soc();
@ -366,6 +431,10 @@ void platform_fsp_silicon_init_params_cb(FSPS_UPD *supd)
}
}
/* PSE (Intel Programmable Services Engine) config */
if (CONFIG(PSE_ENABLE) && cbfs_file_exists("pse.bin"))
fill_fsps_pse_params(params, config);
/* Override/Fill FSP Silicon Param for mainboard */
mainboard_silicon_init_params(params);
}

View File

@ -123,7 +123,7 @@ static void soc_memory_init_params(FSP_M_CONFIG *m_cfg,
}
}
/* PSE (Intel Programmable Services Engine) switch */
m_cfg->PchPseEnable = 0;
m_cfg->PchPseEnable = CONFIG(PSE_ENABLE) && cbfs_file_exists("pse.bin");
}
void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version)