soc/intel/ptl: Do initial Panther Lake SoC commit till ramstage

List of changes:
1. Add required SoC programming till ramstage.
2. Include only required headers into include/soc.
3. Skeleton code used to call FSP-S API.

BUG=b:348678529
TEST=Verified on Intel® Simics® Pre Silicon Simulation platform
     for PTL using google/fatcat mainboard.

Change-Id: I61930726ad0c765bfa1d72c5df893262be884834
Signed-off-by: Saurabh Mishra <mishra.saurabh@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/84332
Reviewed-by: Jérémy Compostella <jeremy.compostella@intel.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Subrata Banik <subratabanik@google.com>
This commit is contained in:
Saurabh Mishra 2024-09-12 10:52:56 +05:30 committed by Subrata Banik
commit 95cf9c0052
41 changed files with 3675 additions and 93 deletions

View file

@ -7,37 +7,100 @@ config SOC_INTEL_PANTHERLAKE_BASE
select BOOT_DEVICE_SUPPORTS_WRITES
select CACHE_MRC_SETTINGS
select CPU_INTEL_COMMON
select CPU_INTEL_COMMON_VOLTAGE
select CPU_INTEL_FIRMWARE_INTERFACE_TABLE
select FSP_M_XIP
select FSP_USES_CB_DEBUG_EVENT_HANDLER
select CPU_SUPPORTS_INTEL_TME
select CPU_SUPPORTS_PM_TIMER_EMULATION
select DEFAULT_SOFTWARE_CONNECTION_MANAGER if MAINBOARD_HAS_CHROMEOS
select DEFAULT_X2APIC_LATE_WORKAROUND
select DISPLAY_FSP_VERSION_INFO_2
select FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW
select FSP_COMPRESS_FSP_S_LZ4
select FSP_M_XIP
select FSP_STATUS_GLOBAL_RESET_REQUIRED_3
select FSP_UGOP_EARLY_SIGN_OF_LIFE
select FSP_USES_CB_DEBUG_EVENT_HANDLER
select FSPS_HAS_ARCH_UPD
select GENERIC_GPIO_LIB
select HAVE_DEBUG_RAM_SETUP
select HAVE_FSP_GOP
select HAVE_FSP_LOGO_SUPPORT if RUN_FSP_GOP
select HAVE_HYPERTHREADING
select HAVE_INTEL_COMPLIANCE_TEST_MODE
select HAVE_SMI_HANDLER
select HAVE_X86_64_SUPPORT
select IDT_IN_EVERY_STAGE
select INTEL_GMA_ADD_VBT if RUN_FSP_GOP
select INTEL_DESCRIPTOR_MODE_CAPABLE
select INTEL_GMA_ACPI
select INTEL_GMA_ADD_VBT if RUN_FSP_GOP
select INTEL_GMA_OPREGION_2_1
select INTEL_GMA_VERSION_2
select INTEL_KEYLOCKER
select IOAPIC
select MICROCODE_BLOB_UNDISCLOSED
select MP_SERVICES_PPI_V2
select MRC_CACHE_USING_MRC_VERSION
select MRC_SETTINGS_PROTECT
select PARALLEL_MP_AP_WORK
select PCIE_CLOCK_CONTROL_THROUGH_P2SB
select PLATFORM_USES_FSP2_4
select PMC_GLOBAL_RESET_ENABLE_LOCK
select SOC_INTEL_COMMON
select SOC_INTEL_COMMON_ACPI_WAKE_SOURCE
select SOC_INTEL_COMMON_BASECODE
select SOC_INTEL_COMMON_BASECODE_RAMTOP
select SOC_INTEL_COMMON_BLOCK
select SOC_INTEL_COMMON_BLOCK_CAR
select SOC_INTEL_COMMON_BLOCK_CHIP_CONFIG
select SOC_INTEL_COMMON_BLOCK_CNVI
select SOC_INTEL_COMMON_BLOCK_CPU
select SOC_INTEL_COMMON_BLOCK_CPU_MPINIT
select SOC_INTEL_COMMON_BLOCK_CPU_SMMRELOCATE
select SOC_INTEL_COMMON_BLOCK_DTT
select SOC_INTEL_COMMON_BLOCK_GPIO_DUAL_ROUTE_SUPPORT
select SOC_INTEL_COMMON_BLOCK_GPIO_IOSTANDBY
select SOC_INTEL_COMMON_BLOCK_GPIO_LOCK_USING_PCR
select SOC_INTEL_COMMON_BLOCK_GPIO_PMODE_4BITS
select SOC_INTEL_COMMON_BLOCK_GSPI_VERSION_2
select SOC_INTEL_COMMON_BLOCK_HDA
select SOC_INTEL_COMMON_BLOCK_HECI1_DISABLE_USING_PMC_IPC
select SOC_INTEL_COMMON_BLOCK_IOC
select SOC_INTEL_COMMON_BLOCK_IOE_P2SB
select SOC_INTEL_COMMON_BLOCK_IPU
select SOC_INTEL_COMMON_BLOCK_IRQ
select SOC_INTEL_COMMON_BLOCK_ME_SPEC_18 # TODO: Update with ME21 Spec
select SOC_INTEL_COMMON_BLOCK_MEMINIT
select SOC_INTEL_COMMON_BLOCK_PCIE_RTD3
select SOC_INTEL_COMMON_BLOCK_PMC_EPOC
select SOC_INTEL_COMMON_BLOCK_POWER_LIMIT
select SOC_INTEL_COMMON_BLOCK_SA
select SOC_INTEL_COMMON_BLOCK_SMM
select SOC_INTEL_COMMON_BLOCK_SMM_IO_TRAP
select SOC_INTEL_COMMON_BLOCK_SMM_TCO_ENABLE
select SOC_INTEL_COMMON_BLOCK_THERMAL_BEHIND_PMC
select SOC_INTEL_COMMON_BLOCK_TRACEHUB
select SOC_INTEL_COMMON_BLOCK_XHCI
select SOC_INTEL_COMMON_BLOCK_XHCI_ELOG
select SOC_INTEL_COMMON_FSP_RESET
select SOC_INTEL_COMMON_PCH_CLIENT
select SOC_INTEL_COMMON_RESET
select SOC_INTEL_CRASHLOG
select SOC_INTEL_CSE_LITE_PSR if MAINBOARD_HAS_CHROMEOS && SOC_INTEL_CSE_LITE_SKU
select SOC_INTEL_CSE_SEND_EOP_LATE if !MAINBOARD_HAS_CHROMEOS
select SOC_INTEL_CSE_SET_EOP
select SOC_INTEL_GFX_NON_PREFETCHABLE_MMIO
select SOC_INTEL_IOE_DIE_SUPPORT
select SOC_INTEL_MEM_MAPPED_PM_CONFIGURATION
select SOC_QDF_DYNAMIC_READ_PMC
select SSE2
select SUPPORT_CPU_UCODE_IN_CBFS
select TME_KEY_REGENERATION_ON_WARM_BOOT
select TSC_MONOTONIC_TIMER
select UDELAY_TSC
select UDK_202302_BINDING
select USE_X86_64_SUPPORT
select X86_CLFLUSH_CAR
select X86_INIT_NEED_1_SIPI
help
Intel Pantherlake support. Mainboards should specify the SoC
type using the `SOC_INTEL_PANTHERLAKE_*` options instead
@ -49,8 +112,6 @@ config SOC_INTEL_PANTHERLAKE_U_H
help
Choose this option if the mainboard is built using either a PTL-U (15W) or
PTL-H 12Xe (25W) system-on-a-chip SoC.
Note, PTL U/H processor line is offered in a single package platform that includes the
Compute tile, the PCD tile, and the GFX tile on the same package.
config SOC_INTEL_PANTHERLAKE_H
bool
@ -58,11 +119,17 @@ config SOC_INTEL_PANTHERLAKE_H
select SOC_INTEL_PANTHERLAKE_BASE
help
Choose this option if the mainboard is built using PTL-H 4Xe system-on-a-chip (SoC).
Note, PTL-H processor line is offered in a single package platform that includes the
Compute tile, the PCD tile, and the GFX tile on the same package.
if SOC_INTEL_PANTHERLAKE_BASE
config SOC_INTEL_PANTHERLAKE_TCSS_USB4_SUPPORT
bool
default y
select SOC_INTEL_COMMON_BLOCK_TCSS
select SOC_INTEL_COMMON_BLOCK_USB4
select SOC_INTEL_COMMON_BLOCK_USB4_PCIE
select SOC_INTEL_COMMON_BLOCK_USB4_XHCI
config CAR_ENHANCED_NEM
bool
default y if !INTEL_CAR_NEM
@ -101,6 +168,16 @@ config FSP_TEMP_RAM_SIZE
Refer to Platform FSP integration guide document to know
the exact FSP requirement for Heap setup.
config CHIPSET_DEVICETREE
string
default "soc/intel/pantherlake/chipset.cb"
config EXT_BIOS_WIN_BASE
default 0xf8000000
config EXT_BIOS_WIN_SIZE
default 0x2000000
config IFD_CHIPSET
string
default "ptl"
@ -109,6 +186,26 @@ config IED_REGION_SIZE
hex
default 0x400000
# Intel recommends reserving the PCIe TBT root port resources as below:
# - 42 buses
# - 194 MiB Non-prefetchable memory
# - 448 MiB Prefetchable memory
if SOC_INTEL_ENABLE_USB4_PCIE_RESOURCES
config PCIEXP_HOTPLUG_BUSES
int
default 42
config PCIEXP_HOTPLUG_MEM
hex
default 0xc200000
config PCIEXP_HOTPLUG_PREFETCH_MEM
hex
default 0x1c000000
endif # SOC_INTEL_ENABLE_USB4_PCIE_RESOURCES
config MAX_TBT_ROOT_PORTS
int
default 4
@ -122,6 +219,14 @@ config MAX_PCIE_CLOCK_SRC
int
default 9
config SMM_TSEG_SIZE
hex
default 0x2000000
config SMM_RESERVED_SIZE
hex
default 0x200000
config PCR_BASE_ADDRESS
hex
default 0x4000000000
@ -137,6 +242,14 @@ config P2SB_2_PCR_BASE_ADDRESS
config ECAM_MMCONF_BASE_ADDRESS
default 0xe0000000
config SOC_INTEL_PERFORMANCE_CORE_SCALE_FACTOR
int
default 125 # TODO: Update with PTL data
config SOC_INTEL_EFFICIENT_CORE_SCALE_FACTOR
int
default 100 # TODO: Update with PTL data
config CPU_BCLK_MHZ
int
default 100
@ -178,7 +291,7 @@ config CONSOLE_UART_BASE_ADDRESS
depends on INTEL_LPSS_UART_FOR_CONSOLE
# Clock divider parameters for 115200 baud rate
# Baudrate = (UART source clcok * M) /(N *16)
# Baudrate = (UART source clock * M) /(N *16)
# PTL UART source clock: 100MHz
config SOC_INTEL_COMMON_LPSS_UART_CLK_M_VAL
hex
@ -189,12 +302,13 @@ config SOC_INTEL_COMMON_LPSS_UART_CLK_N_VAL
default 0x7fff
config VBOOT
select VBOOT_SEPARATE_VERSTAGE
select VBOOT_MUST_REQUEST_DISPLAY
select VBOOT_SEPARATE_VERSTAGE
select VBOOT_STARTS_IN_BOOTBLOCK
select VBOOT_VBNV_CMOS
select VBOOT_VBNV_CMOS_BACKUP_TO_FLASH
select VBOOT_X86_SHA256_ACCELERATION
select VBOOT_X86_RSA_ACCELERATION
# Default hash block size is 1KiB. Increasing it to 4KiB to improve
# hashing time as well as read time.
@ -242,4 +356,62 @@ config MRC_CHANNEL_WIDTH
int
default 16
config SOC_INTEL_GFX_FRAMEBUFFER_OFFSET
hex
default 0x800000
config DROP_CPU_FEATURE_PROGRAM_IN_FSP
bool
default n
help
This is to avoid FSP running basic CPU feature programming on BSP
and on APs using the "CpuFeaturesPei.efi" module. The feature programming
includes enabling x2APIC, MCA, MCE and Turbo etc.
Most of these feature programming are getting performed today in scope
of coreboot doing MP Init. Running these redundant programming in scope
of FSP (when `USE_FSP_FEATURE_PROGRAM_ON_APS` config is enabled) would
results in CPU exception.
SoC users to select this config after dropping "CpuFeaturesPei.ffs" module
from FSP-S Firmware Volume (FV). Upon selection, coreboot runs those additional
feature programming on BSP and APs.
This feature is default enabled, in case of "coreboot running MP init"
aka MP_SERVICES_PPI_V2_NOOP config is selected.
config PCIE_LTR_MAX_SNOOP_LATENCY
hex
default 0x100f
help
Latency tolerance reporting, max snoop latency value defaults to 15.73 ms.
config PCIE_LTR_MAX_NO_SNOOP_LATENCY
hex
default 0x100f
help
Latency tolerance reporting, max non-snoop latency value defaults to 15.73 ms.
config HAVE_BMP_LOGO_COMPRESS_LZMA
default n
# The default offset to store CSE RW FW version information is at 68.
# However, in Intel Panther Lake based systems that use PSR, the additional
# size required to keep CSE RW FW version information and PSR back-up status
# in adjacent CMOS memory at offset 68 is not available. Therefore, we
# override the default offset to 161, which has enough space to keep both
# the CSE related information together.
config SOC_INTEL_CSE_FW_PARTITION_CMOS_OFFSET
int
default 161
config SOC_INTEL_COMMON_BLOCK_ACPI_SLP_S0_FREQ_HZ
default 0x2005
help
slp_s0_residency granularity in 122us ticks (i.e. ~8.2KHz) in Panther Lake.
config SOC_PHYSICAL_ADDRESS_WIDTH
int
default 42
endif

View file

@ -6,20 +6,55 @@ subdirs-y += romstage
subdirs-y += ../../../cpu/intel/microcode
subdirs-y += ../../../cpu/intel/turbo
# all (bootblock, verstage, romstage, postcar, ramstage)
all-y += gspi.c
all-y += i2c.c
all-y += pmutil.c
all-y += spi.c
all-y += uart.c
all-y += gpio.c
bootblock-y += bootblock/bootblock.c
bootblock-y += bootblock/pcd.c
bootblock-y += bootblock/report_platform.c
bootblock-y += espi.c
bootblock-y += gpio.c
bootblock-y += soc_info.c
romstage-$(CONFIG_SOC_INTEL_CSE_PRE_CPU_RESET_TELEMETRY) += cse_telemetry.c
romstage-y += espi.c
romstage-y += gpio.c
romstage-y += meminit.c
romstage-y += pcie_rp.c
romstage-y += reset.c
romstage-y += soc_info.c
ramstage-y += acpi.c
ramstage-y += chip.c
ramstage-y += cpu.c
ramstage-$(CONFIG_SOC_INTEL_CRASHLOG) += crashlog.c
ramstage-y += elog.c
ramstage-y += espi.c
ramstage-y += finalize.c
ramstage-y += fsp_params.c
ramstage-y += lockdown.c
ramstage-y += p2sb.c
ramstage-y += pcie_rp.c
ramstage-y += pmc.c
ramstage-y += reset.c
ramstage-y += retimer.c
ramstage-y += soc_info.c
ramstage-y += soundwire.c
ramstage-y += systemagent.c
ramstage-y += tcss.c
ramstage-y += xhci.c
smm-y += elog.c
smm-y += gpio.c
smm-y += p2sb.c
smm-y += pmutil.c
smm-y += smihandler.c
smm-y += soc_info.c
smm-y += uart.c
smm-y += xhci.c
CPPFLAGS_common += -I$(src)/soc/intel/pantherlake
CPPFLAGS_common += -I$(src)/soc/intel/pantherlake/include

View file

@ -0,0 +1,358 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <acpi/acpi.h>
#include <acpi/acpi_gnvs.h>
#include <acpi/acpigen.h>
#include <arch/ioapic.h>
#include <arch/smp/mpspec.h>
#include <console/console.h>
#include <device/device.h>
#include <device/mmio.h>
#include <device/pci_ops.h>
#include <fw_config.h>
#include <intelblocks/cpulib.h>
#include <intelblocks/pmclib.h>
#include <intelblocks/acpi.h>
#include <soc/cpu.h>
#include <soc/iomap.h>
#include <soc/nvs.h>
#include <soc/pci_devs.h>
#include <soc/pm.h>
#include <soc/soc_chip.h>
#include <soc/systemagent.h>
#include <types.h>
/*
* TODO: Update as per PTL spec.
* List of supported C-states in this processor.
*/
enum {
C_STATE_C0, /* 0 */
C_STATE_C1, /* 1 */
C_STATE_C1E, /* 2 */
C_STATE_C6_SHORT_LAT, /* 3 */
C_STATE_C6_LONG_LAT, /* 4 */
C_STATE_C7_SHORT_LAT, /* 5 */
C_STATE_C7_LONG_LAT, /* 6 */
C_STATE_C7S_SHORT_LAT, /* 7 */
C_STATE_C7S_LONG_LAT, /* 8 */
C_STATE_C8, /* 9 */
C_STATE_C9, /* 10 */
C_STATE_C10, /* 11 */
NUM_C_STATES
};
/* TODO: Update as per PTL spec. */
static const acpi_cstate_t cstate_map[NUM_C_STATES] = {
[C_STATE_C0] = {},
[C_STATE_C1] = {
.latency = C1_LATENCY,
.power = C1_POWER,
.resource = MWAIT_RES(0, 0),
},
[C_STATE_C1E] = {
.latency = C1_LATENCY,
.power = C1_POWER,
.resource = MWAIT_RES(0, 1),
},
[C_STATE_C6_SHORT_LAT] = {
.latency = C6_LATENCY,
.power = C6_POWER,
.resource = MWAIT_RES(2, 0),
},
[C_STATE_C6_LONG_LAT] = {
.latency = C6_LATENCY,
.power = C6_POWER,
.resource = MWAIT_RES(2, 1),
},
[C_STATE_C7_SHORT_LAT] = {
.latency = C7_LATENCY,
.power = C7_POWER,
.resource = MWAIT_RES(3, 0),
},
[C_STATE_C7_LONG_LAT] = {
.latency = C7_LATENCY,
.power = C7_POWER,
.resource = MWAIT_RES(3, 1),
},
[C_STATE_C7S_SHORT_LAT] = {
.latency = C7_LATENCY,
.power = C7_POWER,
.resource = MWAIT_RES(3, 2),
},
[C_STATE_C7S_LONG_LAT] = {
.latency = C7_LATENCY,
.power = C7_POWER,
.resource = MWAIT_RES(3, 3),
},
[C_STATE_C8] = {
.latency = C8_LATENCY,
.power = C8_POWER,
.resource = MWAIT_RES(4, 0),
},
[C_STATE_C9] = {
.latency = C9_LATENCY,
.power = C9_POWER,
.resource = MWAIT_RES(5, 0),
},
[C_STATE_C10] = {
.latency = C10_LATENCY,
.power = C10_POWER,
.resource = MWAIT_RES(6, 0),
},
};
/* TODO: Update as per PTL spec */
static int cstate_set_non_s0ix[] = {
C_STATE_C1,
C_STATE_C6_LONG_LAT,
C_STATE_C7S_LONG_LAT
};
/* TODO: Update as per PTL spec */
static int cstate_set_s0ix[] = {
C_STATE_C1,
C_STATE_C6_LONG_LAT,
C_STATE_C10
};
const acpi_cstate_t *soc_get_cstate_map(size_t *entries)
{
static acpi_cstate_t map[MAX(ARRAY_SIZE(cstate_set_s0ix),
ARRAY_SIZE(cstate_set_non_s0ix))];
static bool c_state_initialized = false;
size_t i;
if (c_state_initialized)
return map;
config_t *config = config_of_soc();
if (config == NULL) {
printk(BIOS_ERR, "Error: Configuration could not be retrieved.\n");
return NULL;
}
int *set;
if (config->s0ix_enable) {
*entries = ARRAY_SIZE(cstate_set_s0ix);
set = cstate_set_s0ix;
} else {
*entries = ARRAY_SIZE(cstate_set_non_s0ix);
set = cstate_set_non_s0ix;
}
for (i = 0; i < *entries; i++) {
map[i] = cstate_map[set[i]];
map[i].ctype = i + 1;
}
c_state_initialized = true;
return map;
}
void soc_power_states_generation(int core_id, int cores_per_package)
{
config_t *config = config_of_soc();
if (config == NULL) {
printk(BIOS_ERR, "Error: Configuration could not be retrieved.\n");
return;
}
if (config->eist_enable)
/* Generate P-state tables */
generate_p_state_entries(core_id, cores_per_package);
}
void soc_fill_fadt(acpi_fadt_t *fadt)
{
const uint16_t pmbase = ACPI_BASE_ADDRESS;
config_t *config = config_of_soc();
if (config == NULL) {
printk(BIOS_ERR, "Error: Configuration could not be retrieved.\n");
return;
}
fadt->pm_tmr_blk = pmbase + PM1_TMR;
fadt->pm_tmr_len = sizeof(uint32_t);
fill_fadt_extended_pm_io(fadt);
if (config->s0ix_enable)
fadt->flags |= ACPI_FADT_LOW_PWR_IDLE_S0;
}
static struct min_sleep_state min_pci_sleep_states[] = {
{ SA_DEVFN_ROOT, ACPI_DEVICE_SLEEP_D3 },
{ SA_DEVFN_IGD, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_IPU, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_TBT0, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_TBT1, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_TBT2, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_TBT3, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_TCSS_XHCI, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_TCSS_XDCI, ACPI_DEVICE_SLEEP_D3 },
{ SA_DEVFN_TCSS_DMA0, ACPI_DEVICE_SLEEP_D3 },
{ SA_DEVFN_TCSS_DMA1, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_THC0, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_THC1, ACPI_DEVICE_SLEEP_D3 },
{ PCH_DEVFN_XHCI, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_USBOTG, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_SRAM, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_CNVI_WIFI, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_I2C0, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_I2C1, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_I2C2, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_I2C3, ACPI_DEVICE_SLEEP_D3 },
{ PCH_DEVFN_CSE, ACPI_DEVICE_SLEEP_D0 },
{ PCI_DEVFN_I2C4, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_I2C5, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_UART2, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_PCIE1, ACPI_DEVICE_SLEEP_D0 },
{ PCI_DEVFN_PCIE2, ACPI_DEVICE_SLEEP_D0 },
{ PCI_DEVFN_PCIE3, ACPI_DEVICE_SLEEP_D0 },
{ PCI_DEVFN_PCIE4, ACPI_DEVICE_SLEEP_D0 },
{ PCI_DEVFN_PCIE5, ACPI_DEVICE_SLEEP_D0 },
{ PCI_DEVFN_PCIE6, ACPI_DEVICE_SLEEP_D0 },
{ PCI_DEVFN_PCIE7, ACPI_DEVICE_SLEEP_D0 },
{ PCI_DEVFN_PCIE8, ACPI_DEVICE_SLEEP_D0 },
{ PCI_DEVFN_PCIE9, ACPI_DEVICE_SLEEP_D0 },
{ PCI_DEVFN_PCIE10, ACPI_DEVICE_SLEEP_D0 },
{ PCI_DEVFN_PCIE11, ACPI_DEVICE_SLEEP_D0 },
{ PCI_DEVFN_PCIE12, ACPI_DEVICE_SLEEP_D0 },
{ PCI_DEVFN_UART0, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_UART1, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_GSPI0, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_GSPI1, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_ESPI, ACPI_DEVICE_SLEEP_D0 },
{ PCH_DEVFN_PMC, ACPI_DEVICE_SLEEP_D0 },
{ PCI_DEVFN_HDA, ACPI_DEVICE_SLEEP_D0 },
{ PCI_DEVFN_SPI, ACPI_DEVICE_SLEEP_D3 },
{ PCI_DEVFN_GBE, ACPI_DEVICE_SLEEP_D3 },
};
struct min_sleep_state *soc_get_min_sleep_state_array(size_t *size)
{
*size = ARRAY_SIZE(min_pci_sleep_states);
return min_pci_sleep_states;
}
uint32_t soc_read_sci_irq_select(void)
{
return read32p(soc_read_pmc_base() + IRQ_REG);
}
static unsigned long soc_fill_dmar(unsigned long current)
{
uint32_t vtd_engine_enabled = MCHBAR32(GFXVTBAR);
const uint64_t gfxvtbar = MCHBAR64(GFXVTBAR) & VTBAR_MASK;
bool is_ipu_enabled = is_devfn_enabled(PCI_DEVFN_IPU);
bool is_dptf_enabled = is_devfn_enabled(PCI_DEVFN_DPTF);
bool is_npu_enabled = is_devfn_enabled(PCI_DEVFN_NPU);
bool is_iaa_enabled = is_devfn_enabled(PCI_DEVFN_IAA);
printk(BIOS_DEBUG, "%s - gfxvtbar:0x%llx 0x%x\n", __func__, gfxvtbar, MCHBAR32(GFXVTBAR));
if (vtd_engine_enabled & GFXVT_ENABLED) {
const unsigned long tmp = current;
current += acpi_create_dmar_drhd(current, 0, 0, gfxvtbar, GFXVT_BASE_SIZE);
current += acpi_create_dmar_ds_pci(current, 0, PCI_DEV_SLOT_IGD, 0);
acpi_dmar_drhd_fixup(tmp, current);
}
if ((is_ipu_enabled || is_dptf_enabled || is_npu_enabled || is_iaa_enabled) &&
(vtd_engine_enabled & NONGFXVT_ENABLED)) {
const unsigned long tmp = current;
current += acpi_create_dmar_drhd(current,
0, 0, (uint64_t)VTVC0_BASE_ADDRESS, VTVC0_BASE_SIZE);
if (is_ipu_enabled)
current += acpi_create_dmar_ds_pci(current, 0, PCI_DEV_SLOT_IPU, 0);
if (is_dptf_enabled)
current += acpi_create_dmar_ds_pci(current, 0, PCI_DEV_SLOT_DPTF, 0);
if (is_npu_enabled)
current += acpi_create_dmar_ds_pci(current, 0, PCI_DEV_SLOT_NPU, 0);
if (is_iaa_enabled)
current += acpi_create_dmar_ds_pci(current, 0, PCI_DEV_SLOT_IAA, 0);
acpi_dmar_drhd_fixup(tmp, current);
}
if (vtd_engine_enabled & IOCVT_ENABLED) {
const unsigned long tmp = current;
current += acpi_create_dmar_drhd(current,
DRHD_INCLUDE_PCI_ALL, 0, (uint64_t)IOCVTD_BASE_ADDRESS, IOCVTD_BASE_SIZE);
current += acpi_create_dmar_ds_ioapic_from_hw(current,
IO_APIC_ADDR, V_P2SB_CFG_IBDF_BUS, V_P2SB_CFG_IBDF_DEV, V_P2SB_CFG_IBDF_FUNC);
current += acpi_create_dmar_ds_msi_hpet(current, 0, V_P2SB_CFG_HBDF_BUS,
V_P2SB_CFG_HBDF_DEV, V_P2SB_CFG_HBDF_FUNC);
acpi_dmar_drhd_fixup(tmp, current);
}
/* Add RMRR entry */
if (vtd_engine_enabled & GFXVT_ENABLED) {
const unsigned long tmp = current;
current += acpi_create_dmar_rmrr(current, 0,
sa_get_gsm_base(), sa_get_tolud_base() - 1);
current += acpi_create_dmar_ds_pci(current, 0, PCI_DEV_SLOT_IGD, 0);
acpi_dmar_rmrr_fixup(tmp, current);
}
if (is_ipu_enabled || is_dptf_enabled || is_npu_enabled || is_iaa_enabled) {
const unsigned long tmp = current;
current += acpi_create_dmar_satc(current, ATC_REQUIRED, 0);
current += acpi_create_dmar_ds_pci(current, 0, PCI_DEV_SLOT_IGD, 0);
if (is_dptf_enabled)
current += acpi_create_dmar_ds_pci(current, 0, PCI_DEV_SLOT_DPTF, 0);
if (is_ipu_enabled)
current += acpi_create_dmar_ds_pci(current, 0, PCI_DEV_SLOT_IPU, 0);
if (is_npu_enabled)
current += acpi_create_dmar_ds_pci(current, 0, PCI_DEV_SLOT_NPU, 0);
if (is_iaa_enabled)
current += acpi_create_dmar_ds_pci(current, 0, PCI_DEV_SLOT_IAA, 0);
acpi_dmar_satc_fixup(tmp, current);
}
return current;
}
unsigned long sa_write_acpi_tables(const struct device *dev, unsigned long current,
struct acpi_rsdp *rsdp)
{
acpi_dmar_t *const dmar = (acpi_dmar_t *)current;
/*
* Create DMAR table only if we have VT-d capability and FSP does not override its
* feature.
*/
if ((pci_read_config32(dev, CAPID0_A) & VTD_DISABLE) ||
!(MCHBAR32(GFXVTBAR) & (GFXVT_ENABLED | NONGFXVT_ENABLED | IOCVT_ENABLED)))
return current;
printk(BIOS_DEBUG, "ACPI: * DMAR\n");
acpi_create_dmar(dmar, DMAR_INTR_REMAP | DMA_CTRL_PLATFORM_OPT_IN_FLAG, soc_fill_dmar);
current += dmar->header.length;
current = acpi_align_current(current);
acpi_add_table(rsdp, dmar);
return current;
}
void soc_fill_gnvs(struct global_nvs *gnvs)
{
config_t *config = config_of_soc();
if (config == NULL) {
printk(BIOS_ERR, "Configuration could not be retrieved.\n");
return;
}
/* Enable DPTF based on mainboard configuration */
gnvs->dpte = config->dptf_enable;
/* Set USB2/USB3 wake enable bitmaps. */
gnvs->u2we = config->usb2_wake_enable_bitmap;
gnvs->u3we = config->usb3_wake_enable_bitmap;
}
int soc_madt_sci_irq_polarity(int sci)
{
return MP_IRQ_POLARITY_HIGH;
}

View file

@ -0,0 +1,283 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <device/device.h>
#include <device/pci.h>
#include <fsp/api.h>
#include <fsp/util.h>
#include <gpio.h>
#include <intelblocks/acpi.h>
#include <intelblocks/cfg.h>
#include <intelblocks/cse.h>
#include <intelblocks/irq.h>
#include <intelblocks/itss.h>
#include <intelblocks/p2sb.h>
#include <intelblocks/pcie_rp.h>
#include <intelblocks/systemagent.h>
#include <intelblocks/tcss.h>
#include <intelblocks/xdci.h>
#include <soc/intel/common/reset.h>
#include <soc/intel/common/vbt.h>
#include <soc/iomap.h>
#include <soc/p2sb.h>
#include <soc/pci_devs.h>
#include <soc/pcie.h>
#include <soc/ramstage.h>
#include <soc/soc_chip.h>
#include <soc/tcss.h>
#if CONFIG(HAVE_ACPI_TABLES)
const char *soc_acpi_name(const struct device *dev)
{
if (dev->path.type == DEVICE_PATH_DOMAIN)
return "PCI0";
if (dev->path.type == DEVICE_PATH_USB) {
switch (dev->path.usb.port_type) {
case 0:
/* Root Hub */
return "RHUB";
case 2:
/* USB2 ports */
switch (dev->path.usb.port_id) {
case 0: return "HS01";
case 1: return "HS02";
case 2: return "HS03";
case 3: return "HS04";
case 4: return "HS05";
case 5: return "HS06";
case 6: return "HS07";
case 7: return "HS08";
}
break;
case 3:
/* USB3 ports */
switch (dev->path.usb.port_id) {
case 0: return "SS01";
case 1: return "SS02";
case 2: return "SS03";
case 3: return "SS04";
}
break;
}
printk(BIOS_ERR, "Missing ACPI Name for USB port_type=0x%x\n",
dev->path.usb.port_type);
return NULL;
}
if (dev->path.type != DEVICE_PATH_PCI) {
printk(BIOS_ERR, "Missing ACPI Name for USB path_type=0x%x\n",
dev->path.type);
return NULL;
}
switch (dev->path.pci.devfn) {
case PCI_DEVFN_ROOT: return "MCHC";
case PCI_DEVFN_IGD: return "GFX0";
case PCI_DEVFN_TCSS_XHCI: return "TXHC";
case PCI_DEVFN_TCSS_XDCI: return "TXDC";
case PCI_DEVFN_TCSS_DMA0: return "TDM0";
case PCI_DEVFN_TCSS_DMA1: return "TDM1";
case PCI_DEVFN_TBT0: return "TRP0";
case PCI_DEVFN_TBT1: return "TRP1";
case PCI_DEVFN_TBT2: return "TRP2";
case PCI_DEVFN_TBT3: return "TRP3";
case PCI_DEVFN_NPU: return "NPU";
case PCI_DEVFN_IPU: return "IPU";
case PCI_DEVFN_ISH: return "ISHB";
case PCI_DEVFN_XHCI: return "XHCI";
case PCI_DEVFN_I2C0: return "I2C0";
case PCI_DEVFN_I2C1: return "I2C1";
case PCI_DEVFN_I2C2: return "I2C2";
case PCI_DEVFN_I2C3: return "I2C3";
case PCI_DEVFN_I2C4: return "I2C4";
case PCI_DEVFN_I2C5: return "I2C5";
case PCI_DEVFN_CSE: return "HECI";
case PCI_DEVFN_PCIE1: return "RP01";
case PCI_DEVFN_PCIE2: return "RP02";
case PCI_DEVFN_PCIE3: return "RP03";
case PCI_DEVFN_PCIE4: return "RP04";
case PCI_DEVFN_PCIE5: return "RP05";
case PCI_DEVFN_PCIE6: return "RP06";
case PCI_DEVFN_PCIE7: return "RP07";
case PCI_DEVFN_PCIE8: return "RP08";
case PCI_DEVFN_PCIE9: return "RP09";
case PCI_DEVFN_PCIE10: return "RP10";
case PCI_DEVFN_PCIE11: return "RP11";
case PCI_DEVFN_PCIE12: return "RP12";
case PCI_DEVFN_PMC: return "PMC";
case PCI_DEVFN_UART0: return "UAR0";
case PCI_DEVFN_UART1: return "UAR1";
case PCI_DEVFN_UART2: return "UAR2";
case PCI_DEVFN_GSPI0: return "SPI0";
case PCI_DEVFN_GSPI1: return "SPI1";
/* Keeping ACPI device name coherent with ec.asl */
case PCI_DEVFN_ESPI: return "LPCB";
case PCI_DEVFN_HDA: return "HDAS";
case PCI_DEVFN_SMBUS: return "SBUS";
case PCI_DEVFN_GBE: return "GLAN";
}
printk(BIOS_ERR, "Missing ACPI Name for PCI: 00:%02x.%01x\n",
PCI_SLOT(dev->path.pci.devfn), PCI_FUNC(dev->path.pci.devfn));
return NULL;
}
#endif
#if CONFIG(SOC_INTEL_STORE_ISH_FW_VERSION)
/* SoC override API to identify if ISH Firmware existed inside CSE FPT */
bool soc_is_ish_partition_enabled(void)
{
struct device *ish = pcidev_path_on_root(PCI_DEVFN_ISH);
uint16_t ish_pci_id = ish ? pci_read_config16(ish, PCI_DEVICE_ID) : 0xFFFF;
if (ish_pci_id == 0xFFFF)
return false;
return true;
}
#endif
/* SoC routine to fill GPIO PM mask and value for GPIO_MISCCFG register */
static void soc_fill_gpio_pm_configuration(void)
{
uint8_t value[TOTAL_GPIO_COMM];
const config_t *config = config_of_soc();
if (config->gpio_override_pm)
memcpy(value, config->gpio_pm, sizeof(value));
else
memset(value, MISCCFG_GPIO_PM_CONFIG_BITS, sizeof(value));
gpio_pm_configure(value, TOTAL_GPIO_COMM);
}
/* Enable tracehub in device tree */
static void soc_enable_tracehub(void)
{
struct device *dev;
dev = pcidev_path_on_root(PCI_DEVFN_NPK);
if (dev) {
dev->enabled = 1;
printk(BIOS_DEBUG, "Tracehub is enabled.\n");
}
}
void soc_init_pre_device(void *chip_info)
{
config_t *config = config_of_soc();
if (config == NULL) {
printk(BIOS_ERR, "Error: Configuration could not be retrieved.\n");
return;
}
/* Validate TBT image authentication */
config->tbt_authentication = ioe_p2sb_sbi_read(PID_IOM,
IOM_CSME_IMR_TBT_STATUS) & TBT_VALID_AUTHENTICATION;
if (CONFIG(SOC_INTEL_COMMON_BLOCK_TRACEHUB))
soc_enable_tracehub();
/* Perform silicon specific init. */
fsp_silicon_init();
/* Display FIRMWARE_VERSION_INFO_HOB */
fsp_display_fvi_version_hob();
soc_fill_gpio_pm_configuration();
/* Swap enabled PCI ports in device tree if needed. */
pcie_rp_update_devicetree(get_pcie_rp_table());
/* Swap enabled TBT root ports in device tree if needed. */
pcie_rp_update_devicetree(get_tbt_pcie_rp_table());
/*
* Earlier when coreboot used to send EOP at late as possible caused
* issue of delayed response from CSE since CSE was busy loading payload.
* To resolve the issue, EOP should be sent earlier than current sequence
* in the boot sequence at BS_DEV_INIT.
*
* Intel CSE team recommends to send EOP close to FW init (between FSP-S
* exit and current boot sequence) to reduce message response time from
* CSE hence moving sending EOP to earlier stage.
*/
if (CONFIG(SOC_INTEL_CSE_SEND_EOP_EARLY) || CONFIG(SOC_INTEL_CSE_SEND_EOP_ASYNC)) {
printk(BIOS_INFO, "Sending EOP early from SoC\n");
cse_send_end_of_post();
}
}
static void cpu_fill_ssdt(const struct device *dev)
{
if (!generate_pin_irq_map())
printk(BIOS_ERR, "Failed to generate ACPI _PRT table!\n");
generate_cpu_entries(dev);
}
static void cpu_set_north_irqs(struct device *dev)
{
irq_program_non_pch();
}
static struct device_operations pci_domain_ops = {
.read_resources = &pci_domain_read_resources,
.set_resources = &pci_domain_set_resources,
.scan_bus = &pci_host_bridge_scan_bus,
#if CONFIG(HAVE_ACPI_TABLES)
.acpi_name = &soc_acpi_name,
.acpi_fill_ssdt = ssdt_set_above_4g_pci,
#endif
};
static struct device_operations cpu_bus_ops = {
.read_resources = noop_read_resources,
.set_resources = noop_set_resources,
.enable_resources = cpu_set_north_irqs,
#if CONFIG(HAVE_ACPI_TABLES)
.acpi_fill_ssdt = cpu_fill_ssdt,
#endif
};
static void soc_enable(struct device *dev)
{
/*
* Set the operations if it is a special bus type or a hidden PCI
* device.
*/
if (dev->path.type == DEVICE_PATH_DOMAIN)
dev->ops = &pci_domain_ops;
else if (dev->path.type == DEVICE_PATH_CPU_CLUSTER)
dev->ops = &cpu_bus_ops;
else if (dev->path.type == DEVICE_PATH_PCI &&
dev->path.pci.devfn == PCI_DEVFN_PMC)
dev->ops = &pmc_ops;
else if (dev->path.type == DEVICE_PATH_PCI &&
dev->path.pci.devfn == PCI_DEVFN_P2SB)
dev->ops = &pcd_p2sb_ops;
else if (dev->path.type == DEVICE_PATH_PCI &&
dev->path.pci.devfn == PCI_DEVFN_P2SB2)
dev->ops = &pcd_p2sb_2_ops;
else if (dev->path.type == DEVICE_PATH_GPIO)
block_gpio_enable(dev);
}
static void soc_init_final_device(void *chip_info)
{
uint32_t reset_status = fsp_get_pch_reset_status();
if (reset_status == FSP_SUCCESS)
return;
/* Handle any pending reset request from previously executed FSP APIs */
fsp_handle_reset(reset_status);
/* Control shouldn't return here */
die_with_post_code(POSTCODE_HW_INIT_FAILURE,
"Failed to handle the FSP reset request with error 0x%08x\n", reset_status);
}
struct chip_operations soc_intel_pantherlake_ops = {
.name = "Intel Pantherlake",
.enable_dev = &soc_enable,
.init = &soc_init_pre_device,
.final = &soc_init_final_device,
};

View file

@ -3,7 +3,9 @@
#ifndef _SOC_PANTHERLAKE_CHIP_H_
#define _SOC_PANTHERLAKE_CHIP_H_
#include <device/pci_ids.h>
#include <drivers/i2c/designware/dw_i2c.h>
#include <gpio.h>
#include <intelblocks/cfg.h>
#include <intelblocks/gpio.h>
#include <intelblocks/gspi.h>
@ -20,11 +22,14 @@
/* Define config parameters for In-Band ECC (IBECC). */
#define MAX_IBECC_REGIONS 8
#define MAX_SAGV_POINTS 4
#define MAX_HD_AUDIO_SDI_LINKS 2
/* In-Band ECC Operation Mode */
enum ibecc_mode {
IBECC_MODE_PER_REGION,
IBECC_MODE_NONE,
IBECC_MODE_ALL
IBECC_MODE_ALL,
};
struct ibecc_config {
@ -36,14 +41,32 @@ struct ibecc_config {
uint16_t region_mask[MAX_IBECC_REGIONS];
};
/* Types of different SKUs */
enum soc_intel_pantherlake_power_limits {
PTL_U_15W_POWER_LIMITS,
PTL_H_25W_POWER_LIMITS,
PTL_H_45W_POWER_LIMITS,
PTL_U_1_CORE,
PTL_H_1_CORE,
PTL_H_2_CORE,
PTL_H_3_CORE,
PTL_POWER_LIMITS_COUNT,
};
/* TDP values for different SKUs */
enum soc_intel_pantherlake_cpu_tdps {
TDP_15W = 15,
TDP_25W = 25,
TDP_45W = 45,
};
/* Mapping of different SKUs based on CPU ID and TDP values */
static const struct {
unsigned int cpu_id;
enum soc_intel_pantherlake_power_limits limits;
enum soc_intel_pantherlake_cpu_tdps cpu_tdp;
} cpuid_to_ptl[] = {
{ PCI_DID_INTEL_PTL_U_ID_1, PTL_U_1_CORE, TDP_15W },
{ PCI_DID_INTEL_PTL_H_ID_1, PTL_H_1_CORE, TDP_25W },
{ PCI_DID_INTEL_PTL_H_ID_2, PTL_H_3_CORE, TDP_45W },
};
/* Types of display ports */
enum ddi_ports {
DDI_PORT_A,
@ -61,6 +84,70 @@ enum ddi_port_flags {
DDI_ENABLE_HPD = BIT(1), /* Hot Plug Detect */
};
/*
* TODO: Update as per PTL spec
* The Max Pkg Cstate
* Values 0 - C0/C1, 1 - C2, 2 - C3, 3 - C6, 4 - C7, 5 - C7S, 6 - C8, 7 - C9, 8 - C10,
* 254 - CPU Default , 255 - Auto.
*/
enum pkgcstate_limit {
LIMIT_C0_C1 = 0,
LIMIT_C2 = 1,
LIMIT_C3 = 2,
LIMIT_C6 = 3,
LIMIT_C7 = 4,
LIMIT_C7S = 5,
LIMIT_C8 = 6,
LIMIT_C9 = 7,
LIMIT_C10 = 8,
LIMIT_CPUDEFAULT = 254,
LIMIT_AUTO = 255,
};
/* Bit values for use in LpmStateEnableMask. */
enum lpm_state_mask {
LPM_S0i2_0 = BIT(0),
LPM_S0i2_1 = BIT(1),
LPM_S0i2_2 = BIT(2),
LPM_S0i3_0 = BIT(3),
LPM_S0i3_1 = BIT(4),
LPM_S0i3_2 = BIT(5),
LPM_S0i3_3 = BIT(6),
LPM_S0i3_4 = BIT(7),
LPM_S0iX_ALL = LPM_S0i2_0 | LPM_S0i2_1 | LPM_S0i2_2
| LPM_S0i3_0 | LPM_S0i3_1 | LPM_S0i3_2 | LPM_S0i3_3 | LPM_S0i3_4,
};
/*
* As per definition from FSP header:
* - [0] for IA
* - [1] for GT
* - [2] for SA
* - [3] through [5] are reserved
*/
enum vr_domain {
VR_DOMAIN_IA,
VR_DOMAIN_GT,
VR_DOMAIN_SA,
NUM_VR_DOMAINS,
};
/*
* Slew Rate configuration for Deep Package C States for VR domain.
* They are fast time divided by 2.
* 0 - Fast/2
* 1 - Fast/4
* 2 - Fast/8
* 3 - Fast/16
*/
enum slew_rate {
SLEW_FAST_2,
SLEW_FAST_4,
SLEW_FAST_8,
SLEW_FAST_16,
SLEW_IGNORE = 0xff,
};
struct soc_intel_pantherlake_config {
/* Common struct containing soc config data required by common code */
@ -70,7 +157,8 @@ struct soc_intel_pantherlake_config {
struct soc_power_limits_config power_limits_config[PTL_POWER_LIMITS_COUNT];
/* Gpio group routed to each dword of the GPE0 block. Values are
* of the form PMC_GPP_[A:U] or GPD. */
* of the form PMC_GPP_[A:U] or GPD.
*/
uint8_t pmc_gpe0_dw0; /* GPE0_31_0 STS/EN */
uint8_t pmc_gpe0_dw1; /* GPE0_63_32 STS/EN */
uint8_t pmc_gpe0_dw2; /* GPE0_95_64 STS/EN */
@ -82,44 +170,54 @@ struct soc_intel_pantherlake_config {
uint32_t gen4_dec;
/* Enable S0iX support */
int s0ix_enable;
bool s0ix_enable;
/* Support for TCSS xhci, xdci, TBT PCIe root ports and DMA controllers */
uint8_t tcss_d3_hot_disable;
bool tcss_d3_hot_disable;
/* Support for TBT PCIe root ports and DMA controllers with D3Hot->D3Cold */
uint8_t TcssD3ColdDisable;
bool tcss_d3_cold_disable;
/* Enable DPTF support */
int dptf_enable;
bool dptf_enable;
/* Deep SX enable for both AC and DC */
int deep_s3_enable_ac;
int deep_s3_enable_dc;
int deep_s5_enable_ac;
int deep_s5_enable_dc;
bool deep_s3_enable_ac;
bool deep_s3_enable_dc;
bool deep_s5_enable_ac;
bool deep_s5_enable_dc;
/* Deep Sx Configuration
* DSX_EN_WAKE_PIN - Enable WAKE# pin
* DSX_EN_LAN_WAKE_PIN - Enable LAN_WAKE# pin
* DSX_DIS_AC_PRESENT_PD - Disable pull-down on AC_PRESENT pin */
* DSX_DIS_AC_PRESENT_PD - Disable pull-down on AC_PRESENT pin
*/
uint32_t deep_sx_config;
/* TCC activation offset */
uint32_t tcc_offset;
/* In-Band ECC (IBECC) configuration */
struct ibecc_config ibecc;
/* System Agent dynamic frequency support. Only effects ULX/ULT CPUs.
* When enabled memory will be training at two different frequencies.
* 0:Disabled, 1:FixedPoint0, 2:FixedPoint1, 3:FixedPoint2,
* 4:FixedPoint3, 5:Enabled */
* 0:Disabled, 1:Enabled
*/
enum {
SaGv_Disabled,
SaGv_FixedPoint0,
SaGv_FixedPoint1,
SaGv_FixedPoint2,
SaGv_FixedPoint3,
SaGv_Enabled,
SAGV_DISABLED,
SAGV_ENABLED,
} sagv;
/* Rank Margin Tool. 1:Enable, 0:Disable */
uint8_t rmt;
/* System Agent dynamic frequency work points that memory will be training
* at the enabled frequencies. Possible work points are:
* 0x3:Points0_1, 0x7:Points0_1_2, 0xF:AllPoints0_1_2_3
*/
enum {
SAGV_POINTS_0_1 = 0x03,
SAGV_POINTS_0_1_2 = 0x07,
SAGV_POINTS_0_1_2_3 = 0x0f,
} sagv_wp_bitmap;
/* Rank Margin Tool. true:Enable, false:Disable */
bool rmt;
/* USB related */
struct usb2_port_config usb2_ports[CONFIG_SOC_INTEL_USB2_DEV_MAX];
@ -137,7 +235,9 @@ struct soc_intel_pantherlake_config {
bool tbt_authentication;
/* Audio related */
uint8_t pch_hda_dsp_enable;
bool pch_hda_audio_link_hda_enable;
bool pch_hda_dsp_enable;
bool pch_hda_sdi_enable[MAX_HD_AUDIO_SDI_LINKS];
/* iDisp-Link T-Mode 0: 2T, 2: 4T, 3: 8T, 4: 16T */
enum {
@ -178,9 +278,84 @@ struct soc_intel_pantherlake_config {
IGD_SM_52MB = 0xFC,
IGD_SM_56MB = 0xFD,
IGD_SM_60MB = 0xFE,
} IgdDvmt50PreAlloc;
} igd_dvmt50_pre_alloc;
bool skip_ext_gfx_scan;
/* Enable/Disable EIST. true:Enabled, false:Disabled */
bool eist_enable;
/*
* When enabled, this feature makes the SoC throttle when the power
* consumption exceeds the I_TRIP threshold.
*
* FSPs sets a by default I_TRIP threshold adapted to the current SoC
* and assuming a Voltage Regulator error accuracy of 6.5%.
*/
bool enable_fast_vmode[NUM_VR_DOMAINS];
/*
* Current Excursion Protection needs to be set for each VR domain
* in order to be able to enable fast Vmode.
*/
bool cep_enable[NUM_VR_DOMAINS];
/*
* VR Fast Vmode I_TRIP threshold.
* 0-255A in 1/4 A units. Example: 400 = 100A
* This setting overrides the default value set by FSPs when Fast VMode
* is enabled.
*/
uint16_t fast_vmode_i_trip[NUM_VR_DOMAINS];
/*
* Power state current threshold 1.
* Defined in 1/4 A increments. A value of 400 = 100A. Range 0-512,
* which translates to 0-128A. 0 = AUTO. [0] for IA, [1] for GT, [2] for
* SA, [3] through [5] are Reserved.
*/
uint16_t ps_cur_1_threshold[NUM_VR_DOMAINS];
/*
* Power state current threshold 2.
* Defined in 1/4 A increments. A value of 400 = 100A. Range 0-512,
* which translates to 0-128A. 0 = AUTO. [0] for IA, [1] for GT, [2] for
* SA, [3] through [5] are Reserved.
*/
uint16_t ps_cur_2_threshold[NUM_VR_DOMAINS];
/*
* Power state current threshold 3.
* Defined in 1/4 A increments. A value of 400 = 100A. Range 0-512,
* which translates to 0-128A. 0 = AUTO. [0] for IA, [1] for GT, [2] for
* SA, [3] through [5] are Reserved.
*/
uint16_t ps_cur_3_threshold[NUM_VR_DOMAINS];
/*
* SerialIO device mode selection:
* PchSerialIoDisabled,
* PchSerialIoPci,
* PchSerialIoHidden,
* PchSerialIoLegacyUart,
* PchSerialIoSkipInit
*/
uint8_t serial_io_i2c_mode[CONFIG_SOC_INTEL_I2C_DEV_MAX];
uint8_t serial_io_gspi_mode[CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX];
uint8_t serial_io_uart_mode[CONFIG_SOC_INTEL_UART_DEV_MAX];
/*
* GSPIn Default Chip Select Mode:
* 0:Hardware Mode,
* 1:Software Mode
*/
uint8_t serial_io_gspi_cs_mode[CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX];
/*
* GSPIn Default Chip Select State:
* 0: Low,
* 1: High
*/
uint8_t serial_io_gspi_cs_state[CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX];
/* CNVi WiFi Core Enable/Disable */
bool cnvi_wifi_core;
@ -190,43 +365,6 @@ struct soc_intel_pantherlake_config {
/* CNVi BT Audio Offload: Enable/Disable BT Audio Offload. */
bool cnvi_bt_audio_offload;
/* In-Band ECC (IBECC) configuration */
struct ibecc_config ibecc;
/* HeciEnabled decides the state of Heci1 at end of boot
* Setting to 0 (default) disables Heci1 and hides the device from OS */
uint8_t HeciEnabled;
/* Enable/Disable EIST. 1b:Enabled, 0b:Disabled */
uint8_t eist_enable;
/* Enable C6 DRAM */
uint8_t enable_c6dram;
uint8_t PmTimerDisabled;
/*
* SerialIO device mode selection:
* PchSerialIoDisabled,
* PchSerialIoPci,
* PchSerialIoHidden,
* PchSerialIoLegacyUart,
* PchSerialIoSkipInit
*/
uint8_t SerialIoI2cMode[CONFIG_SOC_INTEL_I2C_DEV_MAX];
uint8_t SerialIoGSpiMode[CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX];
uint8_t SerialIoUartMode[CONFIG_SOC_INTEL_UART_DEV_MAX];
/*
* GSPIn Default Chip Select Mode:
* 0:Hardware Mode,
* 1:Software Mode
*/
uint8_t SerialIoGSpiCsMode[CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX];
/*
* GSPIn Default Chip Select State:
* 0: Low,
* 1: High
*/
uint8_t SerialIoGSpiCsState[CONFIG_SOC_INTEL_COMMON_BLOCK_GSPI_MAX];
/* Debug interface selection */
enum {
DEBUG_INTERFACE_RAM = BIT(0),
@ -288,11 +426,6 @@ struct soc_intel_pantherlake_config {
/* Enable(1)/Disable(0) HPD/DDC */
uint8_t ddi_ports_config[DDI_PORT_COUNT];
/* Hybrid storage mode enable (1) / disable (0)
* This mode makes FSP detect Optane and NVME and set PCIe lane mode
* accordingly */
uint8_t HybridStorageMode;
/*
* Override CPU flex ratio value:
* CPU ratio value controls the maximum processor non-turbo ratio.
@ -307,25 +440,78 @@ struct soc_intel_pantherlake_config {
uint8_t cpu_ratio_override;
/*
* Enable(0)/Disable(1) DMI Power Optimizer on PCH side.
* Default 0. Setting this to 1 disables the DMI Power Optimizer.
* Enable(true)/Disable(false) CPU Replacement check.
* Default false. Setting this to true to check CPU replacement.
*/
uint8_t DmiPwrOptimizeDisable;
/*
* Enable(1)/Disable(0) CPU Replacement check.
* Default 0. Setting this to 1 to check CPU replacement.
*/
uint8_t cpu_replacement_check;
bool cpu_replacement_check;
/* ISA Serial Base selection. */
enum {
ISA_SERIAL_BASE_ADDR_3F8,
ISA_SERIAL_BASE_ADDR_2F8,
} IsaSerialUartBase;
} isa_serial_uart_base;
/*
* Enable or Disable C1 C-state Auto Demotion & un-demotion
* The algorithm looks at the behavior of the wake up tracker, how
* often it is waking up, and based on that it demote the c-state.
* Default false. Set this to true in order to disable C1-state auto
* demotion.
* NOTE: Un-Demotion from Demoted C1 needs to be disabled when
* C1 C-state Auto Demotion is disabled.
*/
bool disable_c1_state_auto_demotion;
/*
* Enable or Disable Package C-state Demotion.
* Default is set to false.
* Set this to true in order to disable Package C-state demotion.
* NOTE: Un-Demotion from demoted Package C-state needs to be disabled
* when auto demotion is disabled.
*/
bool disable_package_c_state_demotion;
/* Enable PCH to CPU energy report feature. */
bool pch_pm_energy_report_enable;
/* Energy-Performance Preference (HWP feature) */
bool enable_energy_perf_pref;
uint8_t energy_perf_pref_value;
bool disable_vmx;
/*
* SAGV Frequency per point in Mhz. 0 is Auto, otherwise holds the
* frequency value expressed as an integer. For example: 1867
*/
uint16_t sagv_freq_mhz[MAX_SAGV_POINTS];
/* Gear Selection for SAGV points. 0: Auto, 1: Gear 1, 2: Gear 2, 4: Gear 4 */
uint8_t sagv_gear[MAX_SAGV_POINTS];
/*
* Enable or Disable Reduced BasicMemoryTest size.
* Default is set to false.
* Set this to true in order to reduce BasicMemoryTest size
*/
bool lower_basic_mem_test_size;
/* Platform Power Pmax in Watts. Zero means automatic. */
uint16_t psys_pmax_watts;
/* Platform Power Limit 2 in Watts. */
uint16_t psys_pl2_watts;
/* Enable or Disable Acoustic Noise Mitigation feature */
bool enable_acoustic_noise_mitigation;
/* Disable Fast Slew Rate for Deep Package C States for VR domains */
bool disable_fast_pkgc_ramp[NUM_VR_DOMAINS];
/*
* Slew Rate configuration for Deep Package C States for VR domains
* as per `enum slew_rate` data type.
*/
uint8_t slow_slew_rate_config[NUM_VR_DOMAINS];
/* USB overcurrent pin mapping */
uint8_t pch_usb_oc_enable;
};
typedef struct soc_intel_pantherlake_config config_t;

View file

@ -2,12 +2,24 @@ chip soc/intel/pantherlake
device cpu_cluster 0 on end
register "power_limits_config[PTL_U_15W_POWER_LIMITS]" = "{
register "power_limits_config[PTL_U_1_CORE]" = "{
.tdp_pl1_override = 15,
.tdp_pl2_override = 54,
.tdp_pl4 = 142,
}"
register "power_limits_config[PTL_H_1_CORE]" = "{
.tdp_pl1_override = 25,
.tdp_pl2_override = 64,
.tdp_pl4 = 154,
}"
register "power_limits_config[PTL_H_2_CORE]" = "{
.tdp_pl1_override = 25,
.tdp_pl2_override = 80,
.tdp_pl4 = 240,
}"
# NOTE: if any variant wants to override this value, use the same format
# as register "common_soc_config.pch_thermal_trip" = "value", instead of
# putting it under register "common_soc_config" in overridetree.cb file.
@ -116,7 +128,7 @@ chip soc/intel/pantherlake
end
end
end
device pci 14.2 alias shared_sram off end
device pci 14.2 alias pmc_shared_sram off end
device pci 14.3 alias cnvi_wifi off end
device pci 14.7 alias cnvi_bluetooth off end
device pci 14.5 alias ieh off end

View file

@ -0,0 +1,226 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <assert.h>
#include <console/console.h>
#include <cpu/cpu.h>
#include <cpu/intel/common/common.h>
#include <cpu/intel/microcode.h>
#include <cpu/intel/smm_reloc.h>
#include <cpu/intel/turbo.h>
#include <cpu/x86/lapic.h>
#include <cpu/x86/mp.h>
#include <cpu/x86/msr.h>
#include <device/pci.h>
#include <fsp/api.h>
#include <intelblocks/acpi.h>
#include <intelblocks/cpulib.h>
#include <intelblocks/mp_init.h>
#include <intelblocks/msr.h>
#include <soc/cpu.h>
#include <soc/msr.h>
#include <soc/pci_devs.h>
#include <soc/soc_chip.h>
#include <soc/soc_info.h>
bool cpu_soc_is_in_untrusted_mode(void)
{
msr_t msr;
msr = rdmsr(MSR_BIOS_DONE);
return !!(msr.lo & ENABLE_IA_UNTRUSTED);
}
void cpu_soc_bios_done(void)
{
msr_t msr;
msr = rdmsr(MSR_BIOS_DONE);
msr.lo |= ENABLE_IA_UNTRUSTED;
wrmsr(MSR_BIOS_DONE, msr);
}
uint8_t get_supported_lpm_mask(void)
{
return LPM_S0i2_0 | LPM_S0i2_1 | LPM_S0i2_2;
}
static void soc_fsp_load(void)
{
fsps_load();
}
static void configure_misc(void)
{
msr_t msr;
config_t *conf = (config_t *)config_of_soc();
msr = rdmsr(IA32_MISC_ENABLE);
msr.lo |= FAST_STRINGS_ENABLE_BIT;
msr.lo |= TM1_TM2_EMTTM_ENABLE_BIT;
wrmsr(IA32_MISC_ENABLE, msr);
/* Set EIST status */
cpu_set_eist(conf->eist_enable);
/* Disable Thermal interrupts */
msr.lo = 0;
msr.hi = 0;
wrmsr(IA32_THERM_INTERRUPT, msr);
/* Enable package critical interrupt only */
msr.lo = CRITICAL_TEMP_INTERRUPT_ENABLE;
msr.hi = 0;
wrmsr(IA32_PACKAGE_THERM_INTERRUPT, msr);
/* Enable PROCHOT and Power Performance Platform Override */
msr = rdmsr(MSR_POWER_CTL);
msr.lo |= ENABLE_BIDIR_PROCHOT;
msr.lo |= VR_THERM_ALERT_DISABLE_LOCK;
msr.lo |= PWR_PERF_PLATFORM_OVR;
wrmsr(MSR_POWER_CTL, msr);
}
enum core_type get_soc_cpu_type(void)
{
if (cpu_is_hybrid_supported())
return cpu_get_cpu_type();
return CPUID_CORE_TYPE_INTEL_CORE;
}
bool soc_is_nominal_freq_supported(void)
{
return true;
}
static void enable_x2apic(void)
{
if (!CONFIG(X2APIC_LATE_WORKAROUND))
return;
enable_lapic_mode(true);
}
/* All CPUs including BSP will run the following function. */
void soc_core_init(struct device *cpu)
{
/* Clear out pending MCEs */
mca_configure();
enable_x2apic();
enable_lapic_tpr();
/* Configure Enhanced SpeedStep and Thermal Sensors */
configure_misc();
enable_pm_timer_emulation();
/* Enable Direct Cache Access */
configure_dca_cap();
/* Set energy policy */
set_energy_perf_bias(ENERGY_POLICY_NORMAL);
const config_t *conf = config_of_soc();
/* Set energy-performance preference */
if (conf != NULL && conf->enable_energy_perf_pref) {
if (check_energy_perf_cap())
set_energy_perf_pref(conf->energy_perf_pref_value);
}
/* Enable Turbo */
enable_turbo();
/* Set core type in struct cpu_info */
set_dev_core_type();
if (CONFIG(INTEL_TME) && is_tme_supported())
set_tme_core_activate();
/* TODO: Add support for DROP_CPU_FEATURE_PROGRAM_IN_FSP */
}
static void per_cpu_smm_trigger(void)
{
/* Relocate the SMM handler. */
smm_relocate();
}
static void pre_mp_init(void)
{
soc_fsp_load();
const config_t *conf = config_of_soc();
if (conf == NULL) {
printk(BIOS_ERR, "Configuration could not be retrieved.\n");
return;
}
if (conf->enable_energy_perf_pref) {
if (check_energy_perf_cap())
enable_energy_perf_pref();
else
printk(BIOS_WARNING, "Energy Performance Preference not supported!\n");
}
}
static void post_mp_init(void)
{
/* Set Max Ratio */
cpu_set_max_ratio();
/*
* 1. Now that all APs have been relocated as well as the BSP let SMIs
* start flowing.
* 2. Skip enabling power button SMI and enable it after BS_CHIPS_INIT
* to avoid shutdown hang due to lack of init on certain IP in FSP-S.
*/
global_smi_enable_no_pwrbtn();
}
static const struct mp_ops mp_ops = {
/*
* Skip Pre MP init MTRR programming as MTRRs are mirrored from BSP,
* that are set prior to ramstage.
* Real MTRRs programming are being done after resource allocation.
*/
.pre_mp_init = pre_mp_init,
.get_cpu_count = get_cpu_count,
.get_smm_info = smm_info,
.get_microcode_info = get_microcode_info,
.pre_mp_smm_init = smm_initialize,
.per_cpu_smm_trigger = per_cpu_smm_trigger,
.relocation_handler = smm_relocation_handler,
.post_mp_init = post_mp_init,
};
void mp_init_cpus(struct bus *cpu_bus)
{
if (mp_init_with_smm(cpu_bus, &mp_ops))
printk(BIOS_ERR, "MP initialization failure.\n");
/* Thermal throttle activation offset */
configure_tcc_thermal_target();
}
int soc_skip_ucode_update(u32 current_patch_id, u32 new_patch_id)
{
if (!CONFIG(CHROMEOS))
return 0;
/*
* Locked RO Descriptor Implications:
*
* - A locked descriptor signals the RO binary is fixed; the FIT will load the
* RO's microcode during system reset.
* - Attempts to load newer microcode from the RW CBFS will cause a boot-time
* delay (~60ms, core-dependent), as the microcode must be reloaded on BSP+APs.
* - The kernel can load microcode updates without impacting AP FW boot time.
* - Skipping RW CBFS microcode loading is low-risk when the RO is locked,
* prioritizing fast boot times.
*/
if (CONFIG(LOCK_MANAGEMENT_ENGINE) && current_patch_id)
return 1;
return 0;
}

View file

@ -0,0 +1,516 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <arch/bert_storage.h>
#include <console/console.h>
#include <cpu/cpu.h>
#include <cpu/intel/cpu_ids.h>
#include <delay.h>
#include <device/pci_ops.h>
#include <intelblocks/crashlog.h>
#include <intelblocks/pmc_ipc.h>
#include <soc/crashlog.h>
#include <soc/iomap.h>
#include <soc/pci_devs.h>
#include <string.h>
#define CONTROL_INTERFACE_OFFSET 0x5
#define CRASHLOG_NODES_COUNT 0x2
#define CRASHLOG_PUNIT_STORAGE_OFF_MASK BIT(24)
#define CRASHLOG_RE_ARM_STATUS_MASK BIT(25)
#define CRASHLOG_CONSUMED_MASK BIT(31)
/* Global crashLog info */
static bool m_pmc_crash_log_support;
static bool m_pmc_crash_log_present;
static bool m_cpu_crash_log_support;
static bool m_cpu_crash_log_present;
static u32 m_pmc_crash_log_size;
static u32 m_cpu_crash_log_size;
static u32 cpu_crash_version;
static pmc_ipc_discovery_buf_t discovery_buf;
static pmc_crashlog_desc_table_t descriptor_table;
static tel_crashlog_devsc_cap_t cpu_cl_devsc_cap;
static cpu_crashlog_discovery_table_t cpu_cl_disc_tab;
static uintptr_t disc_tab_addr;
static u64 get_disc_tab_header(void)
{
return read64p(disc_tab_addr);
}
/* Get the SRAM BAR. */
static uintptr_t get_sram_bar(pci_devfn_t sram_devfn)
{
const struct device *dev;
struct resource *res;
dev = pcidev_path_on_root(sram_devfn);
if (!dev) {
printk(BIOS_ERR, "device: 0x%x not found!\n", sram_devfn);
return 0;
}
res = probe_resource(dev, PCI_BASE_ADDRESS_0);
if (!res) {
printk(BIOS_ERR, "SOC SRAM device not found!\n");
return 0;
}
/* Return the base address of the resource */
return res->base;
}
static void configure_sram(const struct device *sram_dev, uintptr_t base_addr)
{
pci_update_config16(sram_dev, PCI_COMMAND, ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY), 0);
/* Program BAR 0 and enable command register memory space decoding */
pci_write_config32(sram_dev, PCI_BASE_ADDRESS_0, base_addr);
pci_or_config16(sram_dev, PCI_COMMAND, PCI_COMMAND_MEMORY);
}
void cl_get_pmc_sram_data(cl_node_t *head)
{
uintptr_t pmc_sram_base = cl_get_cpu_tmp_bar();
u32 pmc_crashLog_size = cl_get_pmc_record_size();
cl_node_t *cl_cur = head;
if (!pmc_crashLog_size) {
printk(BIOS_ERR, "No PMC crashlog records\n");
return;
}
if (!pmc_sram_base) {
printk(BIOS_ERR, "PMC SRAM base not valid\n");
return;
}
if (!cl_pmc_sram_has_mmio_access())
return;
printk(BIOS_DEBUG, "PMC crashLog size : 0x%x\n", pmc_crashLog_size);
/* Goto tail node */
while (cl_cur && cl_cur->next) {
cl_cur = cl_cur->next;
}
/* Process crashlog records */
for (int i = 0; i < descriptor_table.numb_regions + 1; i++) {
uintptr_t sram_base = 0;
bool pmc_sram = true;
printk(BIOS_DEBUG, "Region[0x%x].Tag=0x%x offset=0x%x, size=0x%x\n",
i,
descriptor_table.regions[i].bits.assign_tag,
descriptor_table.regions[i].bits.offset,
descriptor_table.regions[i].bits.size);
if (!descriptor_table.regions[i].bits.size)
continue;
/*
* Region with metadata TAG contains information about BDF entry for SOC PMC SRAM
* and IOE SRAM. We don't need to parse this as we already define BDFs in
* soc/pci_devs.h for these SRAMs. Also we need to skip this region as it does not
* contain any crashlog data.
*/
if (descriptor_table.regions[i].bits.assign_tag ==
CRASHLOG_DESCRIPTOR_TABLE_TAG_META) {
pmc_crashLog_size -= descriptor_table.regions[i].bits.size *
sizeof(u32);
printk(BIOS_DEBUG, "Found metadata tag. PMC crashlog size adjusted to: 0x%x\n",
pmc_crashLog_size);
continue;
} else {
if (descriptor_table.regions[i].bits.assign_tag ==
CRASHLOG_DESCRIPTOR_TABLE_TAG_SOC)
sram_base = pmc_sram_base;
else
continue;
cl_node_t *cl_node = malloc_cl_node(descriptor_table.regions[i].bits.size);
if (!cl_node) {
printk(BIOS_DEBUG, "failed to allocate cl_node [region = %d]\n", i);
goto pmc_send_re_arm_after_reset;
}
if (cl_copy_data_from_sram(sram_base,
descriptor_table.regions[i].bits.offset,
descriptor_table.regions[i].bits.size,
cl_node->data,
i,
pmc_sram)) {
cl_cur->next = cl_node;
cl_cur = cl_cur->next;
} else {
/* Coping data from sram failed */
pmc_crashLog_size -= descriptor_table.regions[i].bits.size *
sizeof(u32);
printk(BIOS_DEBUG, "PMC crashlog size adjusted to: 0x%x\n",
pmc_crashLog_size);
/* Free cl_node */
free_cl_node(cl_node);
}
}
}
update_new_pmc_crashlog_size(&pmc_crashLog_size);
pmc_send_re_arm_after_reset:
/* When bit 7 of discov cmd resp is set -> bit 2 of size field */
cl_pmc_re_arm_after_reset();
/* Clear the SSRAM region after copying the error log */
cl_pmc_clear();
}
bool pmc_cl_discovery(void)
{
uintptr_t bar_addr = 0, desc_table_addr = 0;
const struct pmc_ipc_buffer req = { 0 };
struct pmc_ipc_buffer res;
uint32_t cmd_reg;
int r;
cmd_reg = pmc_make_ipc_cmd(PMC_IPC_CMD_CRASHLOG,
PMC_IPC_CMD_ID_CRASHLOG_DISCOVERY,
PMC_IPC_CMD_SIZE_SHIFT);
printk(BIOS_DEBUG, "cmd_reg from pmc_make_ipc_cmd %d in %s\n", cmd_reg, __func__);
r = pmc_send_ipc_cmd(cmd_reg, &req, &res);
if (r < 0) {
printk(BIOS_ERR, "pmc_send_ipc_cmd failed in %s\n", __func__);
return false;
}
discovery_buf.conv_val_64_bits = ((u64)res.buf[1] << 32) | res.buf[0];
if ((discovery_buf.conv_bits64.supported != 1) ||
(discovery_buf.conv_bits64.discov_mechanism == 0) ||
(discovery_buf.conv_bits64.crash_dis_sts == 1)) {
printk(BIOS_INFO, "PCH crashlog feature not supported.\n");
m_pmc_crash_log_support = false;
m_pmc_crash_log_size = 0;
printk(BIOS_DEBUG, "discovery_buf supported: %d, mechanism: %d, CrashDisSts: %d\n",
discovery_buf.conv_bits64.supported,
discovery_buf.conv_bits64.discov_mechanism,
discovery_buf.conv_bits64.crash_dis_sts);
return false;
}
printk(BIOS_INFO, "PMC crashlog feature is supported.\n");
m_pmc_crash_log_support = true;
/* Program BAR 0 and enable command register memory space decoding */
bar_addr = get_sram_bar(PCI_DEVFN_SRAM);
if (bar_addr == 0) {
printk(BIOS_ERR, "PCH SRAM not available, crashlog feature can't be enabled.\n");
return false;
}
configure_sram(PCI_DEV_SRAM, bar_addr);
desc_table_addr = bar_addr + discovery_buf.conv_bits64.desc_tabl_offset;
m_pmc_crash_log_size = pmc_cl_gen_descriptor_table(desc_table_addr,
&descriptor_table);
printk(BIOS_DEBUG, "PMC CrashLog size in discovery mode: 0x%X\n",
m_pmc_crash_log_size);
m_pmc_crash_log_present = m_pmc_crash_log_size > 0;
return true;
}
uintptr_t cl_get_cpu_bar_addr(void)
{
uintptr_t base_addr = 0;
if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR0) {
base_addr = pci_read_config32(PCI_DEV_TELEMETRY, PCI_BASE_ADDRESS_0) &
~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
} else if (cpu_cl_devsc_cap.discovery_data.fields.t_bir_q == TEL_DVSEC_TBIR_BAR1) {
base_addr = pci_read_config32(PCI_DEV_TELEMETRY, PCI_BASE_ADDRESS_1) &
~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
} else {
printk(BIOS_ERR, "Invalid TEL_CFG_BAR value %d, discovery failure expected.\n",
cpu_cl_devsc_cap.discovery_data.fields.t_bir_q);
}
return base_addr;
}
uintptr_t cl_get_cpu_tmp_bar(void)
{
return get_sram_bar(PCI_DEVFN_SRAM);
}
bool cl_pmc_sram_has_mmio_access(void)
{
if (pci_read_config16(PCI_DEV_SRAM, PCI_VENDOR_ID) == 0xFFFF) {
printk(BIOS_ERR, "PMC SSRAM PCI device disabled. Can be enabled in device tree.\n");
return false;
}
return true;
}
static bool cpu_cl_get_capability(tel_crashlog_devsc_cap_t *cl_devsc_cap)
{
cl_devsc_cap->cap_data.data = pci_read_config32(PCI_DEV_TELEMETRY,
TEL_DVSEC_OFFSET + TEL_DVSEC_PCIE_CAP_ID);
if (cl_devsc_cap->cap_data.fields.pcie_cap_id != TELEMETRY_EXTENDED_CAP_ID) {
printk(BIOS_DEBUG, "Read ID for Telemetry: 0x%x differs from expected: 0x%x\n",
cl_devsc_cap->cap_data.fields.pcie_cap_id, TELEMETRY_EXTENDED_CAP_ID);
return false;
}
/* Walk through the entries until crashLog entry */
cl_devsc_cap->devsc_data.data_32[1] = pci_read_config32(PCI_DEV_TELEMETRY, TEL_DVSEV_ID);
int new_offset = 0;
while (cl_devsc_cap->devsc_data.fields.devsc_id != CRASHLOG_DVSEC_ID) {
if (cl_devsc_cap->cap_data.fields.next_cap_offset == 0
|| cl_devsc_cap->cap_data.fields.next_cap_offset == 0xFFFF) {
printk(BIOS_DEBUG, "Read invalid pcie_cap_id value: 0x%x\n",
cl_devsc_cap->cap_data.fields.pcie_cap_id);
return false;
}
new_offset = cl_devsc_cap->cap_data.fields.next_cap_offset;
cl_devsc_cap->cap_data.data = pci_read_config32(PCI_DEV_TELEMETRY,
new_offset + TEL_DVSEC_PCIE_CAP_ID);
cl_devsc_cap->devsc_data.data_32[1] = pci_read_config32(PCI_DEV_TELEMETRY,
new_offset + TEL_DVSEV_ID);
}
cpu_crash_version = cl_devsc_cap->devsc_data.fields.devsc_ver;
cl_devsc_cap->discovery_data.data = pci_read_config32(PCI_DEV_TELEMETRY, new_offset
+ TEL_DVSEV_DISCOVERY_TABLE_OFFSET);
return true;
}
static u32 get_disc_table_offset(void)
{
u32 offset = cpu_cl_devsc_cap.discovery_data.fields.discovery_table_offset;
return offset;
}
static bool is_crashlog_data_valid(u32 dw0)
{
return (dw0 != 0x0 && dw0 != INVALID_CRASHLOG_RECORD);
}
static bool cpu_cl_gen_discovery_table(void)
{
uintptr_t bar_addr = cl_get_cpu_bar_addr();
if (!bar_addr)
return false;
disc_tab_addr = bar_addr + get_disc_table_offset();
memset(&cpu_cl_disc_tab, 0, sizeof(cpu_crashlog_discovery_table_t));
cpu_cl_disc_tab.header.data = get_disc_tab_header();
/* Check both 32 bit header data and status register for non-zero values */
if ((!is_crashlog_data_valid(cpu_cl_disc_tab.header.data & 0xFFFFFFFF)) &&
(!is_crashlog_data_valid((cpu_cl_disc_tab.header.data) >> 32)))
return false;
u32 cur_offset = 0;
cpu_cl_disc_tab.header.fields.count = CRASHLOG_NODES_COUNT;
printk(BIOS_DEBUG, "cpu_crashlog_discovery_table buffer count: 0x%x\n",
cpu_cl_disc_tab.header.fields.count);
for (int i = 0; i < cpu_cl_disc_tab.header.fields.count; i++) {
cur_offset = 8 + 24 * i;
u32 cl_buffer_size = read32p(disc_tab_addr + cur_offset + 4);
/* Check for buffer size */
if (!(is_crashlog_data_valid(cl_buffer_size)))
continue;
u32 dw0 = read32p(disc_tab_addr + cur_offset);
if (dw0 & CRASHLOG_CONSUMED_MASK) {
printk(BIOS_DEBUG, "cpu crashlog records already consumed."
"id: 0x%x dw0: 0x%x\n", i, dw0);
break;
}
cpu_cl_disc_tab.buffers[i].data = read64p(disc_tab_addr + cur_offset);
printk(BIOS_DEBUG, "cpu_crashlog_discovery_table buffer: 0x%x size: "
"0x%x offset: 0x%x\n", i, cpu_cl_disc_tab.buffers[i].fields.size,
cpu_cl_disc_tab.buffers[i].fields.offset);
m_cpu_crash_log_size += cpu_cl_disc_tab.buffers[i].fields.size * sizeof(u32);
}
if (m_cpu_crash_log_size > 0)
m_cpu_crash_log_present = true;
else
m_cpu_crash_log_present = false;
return true;
}
bool cpu_cl_discovery(void)
{
memset(&cpu_cl_devsc_cap, 0, sizeof(tel_crashlog_devsc_cap_t));
if (!cpu_cl_get_capability(&cpu_cl_devsc_cap)) {
printk(BIOS_ERR, "CPU crashlog capability not found.\n");
m_cpu_crash_log_support = false;
return false;
}
m_cpu_crash_log_support = true;
if (!cpu_cl_gen_discovery_table()) {
printk(BIOS_ERR, "CPU crashlog discovery table not valid.\n");
m_cpu_crash_log_present = false;
return false;
}
return true;
}
void reset_discovery_buffers(void)
{
memset(&discovery_buf, 0, sizeof(pmc_ipc_discovery_buf_t));
memset(&descriptor_table, 0, sizeof(pmc_crashlog_desc_table_t));
memset(&cpu_cl_devsc_cap, 0, sizeof(tel_crashlog_devsc_cap_t));
}
int cl_get_total_data_size(void)
{
printk(BIOS_DEBUG, "crashlog size:pmc-0x%x, cpu-0x%x\n",
m_pmc_crash_log_size, m_cpu_crash_log_size);
return m_pmc_crash_log_size + m_cpu_crash_log_size;
}
static uintptr_t get_control_status_interface(void)
{
if (disc_tab_addr)
return (disc_tab_addr + CONTROL_INTERFACE_OFFSET * sizeof(u32));
return 0;
}
int cpu_cl_clear_data(void)
{
return 0;
}
static bool wait_and_check(u32 bit_mask)
{
u32 stall_cnt = 0;
do {
cpu_cl_disc_tab.header.data = get_disc_tab_header();
udelay(CPU_CRASHLOG_WAIT_STALL);
stall_cnt++;
} while (((cpu_cl_disc_tab.header.data & bit_mask) == 0) &&
((stall_cnt * CPU_CRASHLOG_WAIT_STALL) < CPU_CRASHLOG_WAIT_TIMEOUT));
return (cpu_cl_disc_tab.header.data & bit_mask);
}
void cpu_cl_rearm(void)
{
uintptr_t ctrl_sts_intfc_addr = get_control_status_interface();
if (!ctrl_sts_intfc_addr) {
printk(BIOS_ERR, "CPU crashlog control and status interface address not valid\n");
return;
}
/* Rearm the CPU crashlog. Crashlog does not get collected if rearming fails */
cl_punit_control_interface_t punit_ctrl_intfc;
memset(&punit_ctrl_intfc, 0, sizeof(cl_punit_control_interface_t));
punit_ctrl_intfc.fields.set_re_arm = 1;
write32p(ctrl_sts_intfc_addr, punit_ctrl_intfc.data);
if (!wait_and_check(CRASHLOG_RE_ARM_STATUS_MASK))
printk(BIOS_ERR, "CPU crashlog re_arm not asserted\n");
else
printk(BIOS_DEBUG, "CPU crashlog re_arm asserted\n");
}
void cpu_cl_cleanup(void)
{
/* Perform any SOC specific cleanup after reading the crashlog data from SRAM */
uintptr_t ctrl_sts_intfc_addr = get_control_status_interface();
if (!ctrl_sts_intfc_addr) {
printk(BIOS_ERR, "CPU crashlog control and status interface address not valid\n");
return;
}
/* If storage-off is supported, turn off the PUNIT SRAM
* stroage to save power. This clears crashlog records also.
*/
if (!cpu_cl_disc_tab.header.fields.storage_off_support) {
printk(BIOS_INFO, "CPU crashlog storage_off not supported\n");
return;
}
cl_punit_control_interface_t punit_ctrl_intfc;
memset(&punit_ctrl_intfc, 0, sizeof(cl_punit_control_interface_t));
punit_ctrl_intfc.fields.set_storage_off = 1;
write32p(ctrl_sts_intfc_addr, punit_ctrl_intfc.data);
if (!wait_and_check(CRASHLOG_PUNIT_STORAGE_OFF_MASK))
printk(BIOS_ERR, "CPU crashlog storage_off not asserted\n");
else
printk(BIOS_DEBUG, "CPU crashlog storage_off asserted\n");
}
pmc_ipc_discovery_buf_t cl_get_pmc_discovery_buf(void)
{
return discovery_buf;
}
pmc_crashlog_desc_table_t cl_get_pmc_descriptor_table(void)
{
return descriptor_table;
}
int cl_get_pmc_record_size(void)
{
return m_pmc_crash_log_size;
}
int cl_get_cpu_record_size(void)
{
return m_cpu_crash_log_size;
}
bool cl_cpu_data_present(void)
{
return m_cpu_crash_log_present;
}
bool cl_pmc_data_present(void)
{
return m_pmc_crash_log_present;
}
bool cpu_crashlog_support(void)
{
return m_cpu_crash_log_support;
}
bool pmc_crashlog_support(void)
{
return m_pmc_crash_log_support;
}
void update_new_pmc_crashlog_size(u32 *pmc_crash_size)
{
m_pmc_crash_log_size = *pmc_crash_size;
}
cpu_crashlog_discovery_table_t cl_get_cpu_discovery_table(void)
{
return cpu_cl_disc_tab;
}
void update_new_cpu_crashlog_size(u32 *cpu_crash_size)
{
m_cpu_crash_log_size = *cpu_crash_size;
}

View file

@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <console/console.h>
#include <intelblocks/cse.h>
#include <timestamp.h>
void soc_cbmem_inject_telemetry_data(s64 *ts, s64 current_time)
{
s64 start_stamp;
if (!ts) {
printk(BIOS_ERR, "%s: Failed to insert CSME timestamps\n", __func__);
return;
}
start_stamp = current_time - ts[PERF_DATA_CSME_GET_PERF_RESPONSE];
timestamp_add(TS_ME_ROM_START, start_stamp);
timestamp_add(TS_ME_BOOT_STALL_END,
start_stamp + ts[PERF_DATA_CSME_RBE_BOOT_STALL_DONE_TO_PMC]);
timestamp_add(TS_ME_ICC_CONFIG_START,
start_stamp + ts[PERF_DATA_CSME_GOT_ICC_CFG_START_MSG_FROM_PMC]);
timestamp_add(TS_ME_HOST_BOOT_PREP_END,
start_stamp + ts[PERF_DATA_CSME_HOST_BOOT_PREP_DONE]);
timestamp_add(TS_ME_RECEIVED_CRDA_FROM_PMC,
start_stamp + ts[PERF_DATA_PMC_SENT_CRDA]);
timestamp_add(TS_ISSE_DMU_LOAD_END,
start_stamp + ts[PERF_DATA_ISSE_DMU_LOAD_COMPLETED]);
}

View file

@ -0,0 +1,220 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <bootstate.h>
#include <console/console.h>
#include <device/pci_ops.h>
#include <elog.h>
#include <intelblocks/pmclib.h>
#include <intelblocks/xhci.h>
#include <soc/pci_devs.h>
#include <soc/pm.h>
#include <soc/soc_info.h>
#include <types.h>
struct pme_map {
unsigned int devfn;
unsigned int wake_source;
};
static void pch_log_gpio_gpe(u32 gpe0_sts, u32 gpe0_en, int start)
{
int i;
gpe0_sts &= gpe0_en;
for (i = 0; i <= 31; i++) {
if (gpe0_sts & (1 << i))
elog_add_event_wake(ELOG_WAKE_SOURCE_GPE, i + start);
}
}
static void pch_log_rp_wake_source(void)
{
size_t i;
uint8_t max_port = get_max_pcie_port();
const struct pme_map pme_map[] = {
{ PCI_DEVFN_PCIE1, ELOG_WAKE_SOURCE_PME_PCIE1 },
{ PCI_DEVFN_PCIE2, ELOG_WAKE_SOURCE_PME_PCIE2 },
{ PCI_DEVFN_PCIE3, ELOG_WAKE_SOURCE_PME_PCIE3 },
{ PCI_DEVFN_PCIE4, ELOG_WAKE_SOURCE_PME_PCIE4 },
{ PCI_DEVFN_PCIE5, ELOG_WAKE_SOURCE_PME_PCIE5 },
{ PCI_DEVFN_PCIE6, ELOG_WAKE_SOURCE_PME_PCIE6 },
{ PCI_DEVFN_PCIE7, ELOG_WAKE_SOURCE_PME_PCIE7 },
{ PCI_DEVFN_PCIE8, ELOG_WAKE_SOURCE_PME_PCIE8 },
{ PCI_DEVFN_PCIE9, ELOG_WAKE_SOURCE_PME_PCIE9 },
{ PCI_DEVFN_PCIE10, ELOG_WAKE_SOURCE_PME_PCIE10 },
#if CONFIG(SOC_INTEL_PANTHERLAKE_U_H)
{ PCI_DEVFN_PCIE11, ELOG_WAKE_SOURCE_PME_PCIE11 },
{ PCI_DEVFN_PCIE12, ELOG_WAKE_SOURCE_PME_PCIE12 },
#endif
};
for (i = 0; i < MIN(max_port, ARRAY_SIZE(pme_map)); ++i) {
if (pci_dev_is_wake_source(PCI_DEV(0, PCI_SLOT(pme_map[i].devfn),
PCI_FUNC(pme_map[i].devfn))))
elog_add_event_wake(pme_map[i].wake_source, 0);
}
}
static void pch_log_pme_internal_wake_source(void)
{
const struct pme_map ipme_map[] = {
{ PCI_DEVFN_HDA, ELOG_WAKE_SOURCE_PME_HDA },
{ PCI_DEVFN_GBE, ELOG_WAKE_SOURCE_PME_GBE },
{ PCI_DEVFN_CSE, ELOG_WAKE_SOURCE_PME_CSE },
{ PCI_DEVFN_XHCI, ELOG_WAKE_SOURCE_PME_XHCI },
{ PCI_DEVFN_USBOTG, ELOG_WAKE_SOURCE_PME_XDCI },
{ PCI_DEVFN_CNVI_WIFI, ELOG_WAKE_SOURCE_PME_WIFI },
{ PCI_DEVFN_TCSS_XDCI, ELOG_WAKE_SOURCE_PME_TCSS_XDCI },
};
const struct xhci_wake_info xhci_wake_info[] = {
{ PCI_DEVFN_XHCI, ELOG_WAKE_SOURCE_PME_XHCI },
{ PCI_DEVFN_TCSS_XHCI, ELOG_WAKE_SOURCE_PME_TCSS_XHCI },
};
bool dev_found = false;
size_t i;
for (i = 0; i < ARRAY_SIZE(ipme_map); i++) {
unsigned int devfn = ipme_map[i].devfn;
if (pci_dev_is_wake_source(PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn)))) {
elog_add_event_wake(ipme_map[i].wake_source, 0);
dev_found = true;
}
}
/* Check Thunderbolt ports */
for (i = 0; i < NUM_TBT_FUNCTIONS; i++) {
unsigned int devfn = PCI_DEVFN_TBT(i);
if (pci_dev_is_wake_source(PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn)))) {
elog_add_event_wake(ELOG_WAKE_SOURCE_PME_TBT, i);
dev_found = true;
}
}
/* Check DMA devices */
for (i = 0; i < NUM_TCSS_DMA_FUNCTIONS; i++) {
unsigned int devfn = PCI_DEVFN_TCSS_DMA(i);
if (pci_dev_is_wake_source(PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn)))) {
elog_add_event_wake(ELOG_WAKE_SOURCE_PME_TCSS_DMA, i);
dev_found = true;
}
}
/*
* Probe the XHCI controllers and their USB2 and USB3 ports to determine
* if any of them were wake sources.
*/
dev_found |= xhci_update_wake_event(xhci_wake_info, ARRAY_SIZE(xhci_wake_info));
if (!dev_found)
elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0);
}
static void pch_log_wake_source(struct chipset_power_state *ps)
{
/* Power Button */
if (ps->pm1_sts & PWRBTN_STS)
elog_add_event_wake(ELOG_WAKE_SOURCE_PWRBTN, 0);
/* RTC */
if (ps->pm1_sts & RTC_STS)
elog_add_event_wake(ELOG_WAKE_SOURCE_RTC, 0);
/* PCI Express */
if (ps->pm1_sts & PCIEXPWAK_STS)
pch_log_rp_wake_source();
/* PME (TODO: determine wake device) */
if (ps->gpe0_sts[GPE_STD] & PME_STS)
elog_add_event_wake(ELOG_WAKE_SOURCE_PME, 0);
/* Internal PME */
if (ps->gpe0_sts[GPE_STD] & PME_B0_STS)
pch_log_pme_internal_wake_source();
/* SMBUS Wake */
if (ps->gpe0_sts[GPE_STD] & SMB_WAK_STS)
elog_add_event_wake(ELOG_WAKE_SOURCE_SMBUS, 0);
/* Log GPIO events in set 1-3 */
pch_log_gpio_gpe(ps->gpe0_sts[GPE_31_0], ps->gpe0_en[GPE_31_0], 0);
pch_log_gpio_gpe(ps->gpe0_sts[GPE_63_32], ps->gpe0_en[GPE_63_32], 32);
pch_log_gpio_gpe(ps->gpe0_sts[GPE_95_64], ps->gpe0_en[GPE_95_64], 64);
/* Treat the STD as an extension of GPIO to obtain visibility. */
pch_log_gpio_gpe(ps->gpe0_sts[GPE_STD], ps->gpe0_en[GPE_STD], 96);
}
static void pch_log_power_and_resets(const struct chipset_power_state *ps)
{
/* Thermal Trip */
if (ps->gblrst_cause[0] & GBLRST_CAUSE0_THERMTRIP)
elog_add_event(ELOG_TYPE_THERM_TRIP);
/* CSME-Initiated Host Reset with power down */
if (ps->hpr_cause0 & HPR_CAUSE0_MI_HRPD)
elog_add_event(ELOG_TYPE_MI_HRPD);
/* CSME-Initiated Host Reset with power cycle */
if (ps->hpr_cause0 & HPR_CAUSE0_MI_HRPC)
elog_add_event(ELOG_TYPE_MI_HRPC);
/* CSME-Initiated Host Reset without power cycle */
if (ps->hpr_cause0 & HPR_CAUSE0_MI_HR)
elog_add_event(ELOG_TYPE_MI_HR);
/* PWR_FLR Power Failure */
if (ps->gen_pmcon_a & PWR_FLR)
elog_add_event(ELOG_TYPE_POWER_FAIL);
/* SUS Well Power Failure */
if (ps->gen_pmcon_a & SUS_PWR_FLR)
elog_add_event(ELOG_TYPE_SUS_POWER_FAIL);
/* TCO Timeout */
if (ps->prev_sleep_state != ACPI_S3 &&
ps->tco2_sts & TCO2_STS_SECOND_TO)
elog_add_event(ELOG_TYPE_TCO_RESET);
/* Power Button Override */
if (ps->pm1_sts & PRBTNOR_STS)
elog_add_event(ELOG_TYPE_POWER_BUTTON_OVERRIDE);
/* RTC reset */
if (ps->gen_pmcon_b & RTC_BATTERY_DEAD)
elog_add_event(ELOG_TYPE_RTC_RESET);
/* Host Reset Status */
if (ps->gen_pmcon_a & HOST_RST_STS)
elog_add_event(ELOG_TYPE_SYSTEM_RESET);
/* ACPI Wake Event */
if (ps->prev_sleep_state != ACPI_S0)
elog_add_event_byte(ELOG_TYPE_ACPI_WAKE, ps->prev_sleep_state);
}
static void pch_log_state(void *unused)
{
struct chipset_power_state *ps = pmc_get_power_state();
if (!ps) {
printk(BIOS_ERR, "chipset_power_state not found!\n");
return;
}
/* Power and Reset */
pch_log_power_and_resets(ps);
/* Wake Sources */
if (ps->prev_sleep_state > ACPI_S0)
pch_log_wake_source(ps);
}
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT, pch_log_state, NULL);
void elog_gsmi_cb_platform_log_wake_source(void)
{
struct chipset_power_state ps;
pmc_fill_pm_reg_info(&ps);
pch_log_wake_source(&ps);
}

View file

@ -0,0 +1,82 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <arch/io.h>
#include <bootstate.h>
#include <console/console.h>
#include <cpu/x86/smm.h>
#include <device/mmio.h>
#include <device/pci.h>
#include <intelblocks/cse.h>
#include <intelblocks/lpc_lib.h>
#include <intelblocks/pcr.h>
#include <intelblocks/pmclib.h>
#include <intelblocks/systemagent.h>
#include <intelblocks/tco.h>
#include <intelblocks/thermal.h>
#include <intelpch/lockdown.h>
#include <soc/p2sb.h>
#include <soc/pci_devs.h>
#include <soc/pcr_ids.h>
#include <soc/pm.h>
#include <soc/smbus.h>
#include <soc/soc_chip.h>
#include <soc/systemagent.h>
#include <spi-generic.h>
#include <timer.h>
static void pch_finalize(void)
{
/* TCO Lock down */
tco_lockdown();
pmc_clear_pmcon_sts();
}
static void tbt_finalize(void)
{
int i;
const struct device *dev;
/* Disable Thunderbolt PCIe root ports bus master */
for (i = 0; i < NUM_TBT_FUNCTIONS; i++) {
dev = pcidev_path_on_root(PCI_DEVFN_TBT(i));
if (dev)
pci_dev_disable_bus_master(dev);
}
}
static void sa_finalize(void)
{
if (get_lockdown_config() == CHIPSET_LOCKDOWN_COREBOOT)
sa_lock_pam();
}
static void heci_finalize(void)
{
heci_set_to_d0i3();
if (CONFIG(DISABLE_HECI1_AT_PRE_BOOT))
heci1_disable();
}
static void soc_finalize(void *unused)
{
printk(BIOS_DEBUG, "Finalizing chipset.\n");
pch_finalize();
apm_control(APM_CNT_FINALIZE);
tbt_finalize();
sa_finalize();
if (CONFIG(USE_FSP_NOTIFY_PHASE_READY_TO_BOOT) &&
CONFIG(USE_FSP_NOTIFY_PHASE_END_OF_FIRMWARE))
heci_finalize();
/* Indicate finalize step with post code */
post_code(POSTCODE_OS_BOOT);
}
BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, soc_finalize, NULL);
/*
* The purpose of this change is to accommodate more time to push out sending
* CSE EOP messages at post.
*/
BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, soc_finalize, NULL);

View file

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <soc/ramstage.h>
__weak void mainboard_update_soc_chip_config(struct soc_intel_pantherlake_config *config)
{
/* Override settings per board. */
}
/* UPD parameters to be initialized before SiliconInit */
void platform_fsp_silicon_init_params_cb(FSPS_UPD *supd)
{
/* Override settings per board. */
}
/* Mainboard GPIO Configuration */
__weak void mainboard_silicon_init_params(FSP_S_CONFIG *s_cfg)
{
printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
}

View file

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <intelblocks/gspi.h>
#include <soc/pci_devs.h>
int gspi_soc_bus_to_devfn(unsigned int gspi_bus)
{
switch (gspi_bus) {
case 0:
return PCI_DEVFN_GSPI0;
case 1:
return PCI_DEVFN_GSPI1;
case 2:
return PCI_DEVFN_GSPI2;
}
return -1;
}

View file

@ -0,0 +1,43 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <device/device.h>
#include <drivers/i2c/designware/dw_i2c.h>
#include <soc/pci_devs.h>
int dw_i2c_soc_devfn_to_bus(unsigned int devfn)
{
switch (devfn) {
case PCI_DEVFN_I2C0:
return 0;
case PCI_DEVFN_I2C1:
return 1;
case PCI_DEVFN_I2C2:
return 2;
case PCI_DEVFN_I2C3:
return 3;
case PCI_DEVFN_I2C4:
return 4;
case PCI_DEVFN_I2C5:
return 5;
}
return -1;
}
int dw_i2c_soc_bus_to_devfn(unsigned int bus)
{
switch (bus) {
case 0:
return PCI_DEVFN_I2C0;
case 1:
return PCI_DEVFN_I2C1;
case 2:
return PCI_DEVFN_I2C2;
case 3:
return PCI_DEVFN_I2C3;
case 4:
return PCI_DEVFN_I2C4;
case 5:
return PCI_DEVFN_I2C5;
}
return -1;
}

View file

@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _SOC_PANTHERLAKE_CPU_H_
#define _SOC_PANTHERLAKE_CPU_H_
/* Latency times in us */
#define C1_LATENCY 1
#define C6_LATENCY 127
#define C7_LATENCY 253
#define C8_LATENCY 260
#define C9_LATENCY 487
#define C10_LATENCY 1048
/* Power in units of mW */
#define C1_POWER 0x3e8
#define C6_POWER 0x15e
#define C7_POWER 0xc8
#define C8_POWER 0xc8
#define C9_POWER 0xc8
#define C10_POWER 0xc8
/* Get a bitmask of supported LPM states */
uint8_t get_supported_lpm_mask(void);
#endif

View file

@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _SOC_PANTHERLAKE_CRASHLOG_H_
#define _SOC_PANTHERLAKE_CRASHLOG_H_
#include <types.h>
/* DVSEC capability Registers */
#define TEL_DVSEC_OFFSET 0x100
#define TEL_DVSEC_PCIE_CAP_ID 0x0
#define TEL_DVSEV_ID 0x8
#define TEL_DVSEV_DISCOVERY_TABLE_OFFSET 0xC
#define TELEMETRY_EXTENDED_CAP_ID 0x23
#define CRASHLOG_DVSEC_ID 0x04
#define TEL_DVSEC_TBIR_BAR0 0
#define TEL_DVSEC_TBIR_BAR1 1
/* CPU CrashLog MMIO Registers */
#define CRASHLOG_MAILBOX_INTF_ADDRESS 0x6038
typedef union {
struct {
u32 reserved1 :27;
u32 set_storage_off :1;
u32 set_re_arm :1;
u32 reserved2 :1;
u32 set_clr :1;
u32 reserved3 :1;
} fields;
u32 data;
} __packed cl_punit_control_interface_t;
#endif /* _SOC_PANTHERLAKE_CRASHLOG_H_ */

View file

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _SOC_PANTHERLAKE_DPTF_H_
#define _SOC_PANTHERLAKE_DPTF_H_
/*
* Below is a list of unique ACPI Device IDs for thermal and DPTF
* (Dynamic Platform and Thermal Framework)
*/
/* DPTF ACPI Device ID */
#define DPTF_DPTF_DEVICE "INTC10D4"
/* Generic ACPI Device ID for TSR0/1/2/3 and charger */
#define DPTF_GEN_DEVICE "INTC10D5"
/* Fan ACPI Device ID */
#define DPTF_FAN_DEVICE "INTC10D6"
/* TPCH ACPI Device ID */
#define DPTF_TPCH_DEVICE "INTC10D7"
/* TPWR ACPI Device ID */
#define DPTF_TPWR_DEVICE "INTC10D8"
/* BAT1 ACPI Device ID */
#define DPTF_BAT1_DEVICE "INTC10D9"
#endif

View file

@ -20,6 +20,9 @@
#define SAF_BASE_ADDRESS 0x3ffe000000
#define SAF_BASE_SIZE 0x2000000
/* Add dummy entry to cater common/block/acpi/acpi/northbridge.asl */
#define DMI_BASE_SIZE 0
#define EP_BASE_ADDRESS 0xfeda1000
#define EP_BASE_SIZE 0x1000

View file

@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _SOC_PANTHERLAKE_IRQ_H_
#define _SOC_PANTHERLAKE_IRQ_H_
#define GPIO_IRQ14 14
#define GPIO_IRQ15 15
#define PCH_IRQ10 10
#define PCH_IRQ11 11
#endif

View file

@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _SOC_PANTHERLAKE_NVS_H_
#define _SOC_PANTHERLAKE_NVS_H_
#include <intelblocks/nvs.h>
#endif

View file

@ -8,7 +8,7 @@
#define PCH_P2SB_EPMASK0 0x220
extern struct device_operations soc_p2sb_ops;
extern struct device_operations soc_p2sb_2_ops;
extern struct device_operations pcd_p2sb_ops;
extern struct device_operations pcd_p2sb_2_ops;
#endif /* _SOC_PANTHERLAKE_P2SB_H_ */
#endif

View file

@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __SOC_PANTHERLAKE_PCIE_H__
#define __SOC_PANTHERLAKE_PCIE_H__
#include <intelblocks/pcie_rp.h>
const struct pcie_rp_group *get_pcie_rp_table(void);
const struct pcie_rp_group *get_tbt_pcie_rp_table(void);
#endif

View file

@ -23,7 +23,7 @@ extern struct device_operations pmc_ops;
#define MEM_SR BIT(21)
#define ALLOW_SPXB_CG_INC0 BIT(20)
#define ALLOW_L1LOW_C0 BIT(19)
#define MS4V BIT(18)
#define MS4V BIT_FLAG_32(18)
#define ALLOW_L1LOW_OPI_ON BIT(17)
#define SUS_PWR_FLR BIT(16)
#define PME_B0_S5_DIS BIT(15)

View file

@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _SOC_PANTHERLAKE_RAMSTAGE_H_
#define _SOC_PANTHERLAKE_RAMSTAGE_H_
#include <fsp/api.h>
#include <fsp/util.h>
#include <soc/soc_chip.h>
void mainboard_silicon_init_params(FSP_S_CONFIG *params);
void mainboard_update_soc_chip_config(struct soc_intel_pantherlake_config *config);
void soc_init_pre_device(void *chip_info);
#endif

View file

@ -0,0 +1,35 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _SOC_PANTHERLAKE_SERIALIO_H_
#define _SOC_PANTHERLAKE_SERIALIO_H_
enum {
PchSerialIoDisabled,
PchSerialIoPci,
PchSerialIoHidden,
PchSerialIoLegacyUart,
PchSerialIoSkipInit
};
enum {
PchSerialIoIndexI2C0,
PchSerialIoIndexI2C1,
PchSerialIoIndexI2C2,
PchSerialIoIndexI2C3,
PchSerialIoIndexI2C4,
PchSerialIoIndexI2C5
};
enum {
PchSerialIoIndexGSPI0,
PchSerialIoIndexGSPI1,
PchSerialIoIndexGSPI2,
};
enum {
PchSerialIoIndexUART0,
PchSerialIoIndexUART1,
PchSerialIoIndexUART2
};
#endif /* _SOC_PANTHERLAKE_SERIALIO_H_ */

View file

@ -15,6 +15,9 @@
/* MCHBAR offsets */
#define VTDBAR 0x5410
#define GFXVTBAR VTDBAR
#define GFXVT_ENABLED BIT(0)
#define NONGFXVT_ENABLED BIT(1)
#define IOCVT_ENABLED BIT(2)
#define REGBAR 0x5420
#define MCH_DDR_POWER_LIMIT_LO 0x58e0
#define MCH_DDR_POWER_LIMIT_HI 0x58e4
@ -50,18 +53,6 @@ static const struct sa_mmio_descriptor soc_vtd_resources[] = {
#define LT_SECURITY_SIZE (384 * KiB)
#define APIC_SIZE (1 * MiB)
#define MASK_PCIEXBAR_LENGTH 0x0000000E // bits [3:1]
#define PCIEXBAR_LENGTH_LSB 1 // used to shift right
#define DSM_BASE_ADDR_REG 0xB0
#define MASK_DSM_LENGTH 0xFF00 // [15:8]
#define MASK_DSM_LENGTH_LSB 8 // used to shift right
#define MASK_GSM_LENGTH 0xC0 // [7:6]
#define MASK_GSM_LENGTH_LSB 6 // used to shift right
#define DPR_REG 0x5C
#define MASK_DPR_LENGTH 0xFF0 // [11:4]
#define MASK_DPR_LENGTH_LSB 4 // used to shift right
uint64_t get_mmcfg_size(const struct device *dev);
uint64_t get_dsm_size(const struct device *dev);
uint64_t get_gsm_size(const struct device *dev);

View file

@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#ifndef _SOC_PANTHERLAKE_TCSS_H_
#define _SOC_PANTHERLAKE_TCSS_H_
/* Thunderbolt firmware IMR status */
#define IOM_CSME_IMR_TBT_STATUS 0x14
#define TBT_VALID_AUTHENTICATION BIT(30)
/* IOM aux bias control registers in REGBAR MMIO space */
#define IOM_AUX_BIAS_CTRL_PULLUP_OFFSET_0 0x1070
#define IOM_AUX_BIAS_CTRL_PULLUP_OFFSET(x) (IOM_AUX_BIAS_CTRL_PULLUP_OFFSET_0 + (x) * 4)
#define IOM_AUX_BIAS_CTRL_PULLDOWN_OFFSET_0 0x1088
#define IOM_AUX_BIAS_CTRL_PULLDOWN_OFFSET(x) (IOM_AUX_BIAS_CTRL_PULLDOWN_OFFSET_0 + (x) * 4)
#define BIAS_CTRL_VW_INDEX_SHIFT 24
#define BIAS_CTRL_BIT_POS_SHIFT 16
#endif

View file

@ -0,0 +1,155 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _SOC_PANTHERLAKE_USB_H_
#define _SOC_PANTHERLAKE_USB_H_
#include <stdint.h>
/* Per Port HS Transmitter Emphasis */
#define USB2_EMP_OFF 0
#define USB2_DE_EMP_ON 1
#define USB2_PRE_EMP_ON 2
#define USB2_DE_EMP_ON_PRE_EMP_ON 3
/* Per Port Half Bit Pre-emphasis */
#define USB2_FULL_BIT_PRE_EMP 0
#define USB2_HALF_BIT_PRE_EMP 1
/* Per Port HS Preemphasis Bias */
#define USB2_BIAS_0MV 0
#define USB2_BIAS_11P25MV 1
#define USB2_BIAS_16P9MV 2
#define USB2_BIAS_28P15MV 3
#define USB2_BIAS_39P35MV 5
#define USB2_BIAS_45MV 6
#define USB2_BIAS_56P3MV 7
struct usb2_port_config {
uint8_t enable;
uint8_t ocpin;
uint8_t tx_bias;
uint8_t tx_emp_enable;
uint8_t pre_emp_bias;
uint8_t pre_emp_bit;
uint8_t type_c;
};
/* USB Overcurrent pins definition */
enum {
OC0 = 0,
OC1,
OC2,
OC3,
OC4,
OC5,
OC6,
OC7,
OCMAX,
OC_SKIP = 0xff, /* Skip OC programming */
};
/* Standard USB Port based on length:
* - External
* - Back Panel
* - OTG
* - M.2
* - Internal device down */
#define USB2_PORT_EMPTY { \
.enable = 0, \
.ocpin = OC_SKIP, \
.tx_bias = USB2_BIAS_0MV, \
.tx_emp_enable = USB2_EMP_OFF, \
.pre_emp_bias = USB2_BIAS_0MV, \
.pre_emp_bit = USB2_HALF_BIT_PRE_EMP, \
}
/* Length = 11.5"-12" */
#define USB2_PORT_LONG(pin) { \
.enable = 1, \
.ocpin = (pin), \
.tx_bias = USB2_BIAS_39P35MV, \
.tx_emp_enable = USB2_PRE_EMP_ON, \
.pre_emp_bias = USB2_BIAS_56P3MV, \
.pre_emp_bit = USB2_HALF_BIT_PRE_EMP, \
}
/* Length = 6"-11.49" */
#define USB2_PORT_MID(pin) { \
.enable = 1, \
.ocpin = (pin), \
.tx_bias = USB2_BIAS_0MV, \
.tx_emp_enable = USB2_DE_EMP_ON_PRE_EMP_ON, \
.pre_emp_bias = USB2_BIAS_45MV, \
.pre_emp_bit = USB2_FULL_BIT_PRE_EMP, \
}
/* Length = 3"-5.99" */
#define USB2_PORT_SHORT(pin) { \
.enable = 1, \
.ocpin = (pin), \
.tx_bias = USB2_BIAS_39P35MV, \
.tx_emp_enable = USB2_PRE_EMP_ON | USB2_DE_EMP_ON, \
.pre_emp_bias = USB2_BIAS_39P35MV, \
.pre_emp_bit = USB2_FULL_BIT_PRE_EMP, \
}
/* Max TX and Pre-emp settings */
#define USB2_PORT_MAX(pin) { \
.enable = 1, \
.ocpin = (pin), \
.tx_bias = USB2_BIAS_56P3MV, \
.tx_emp_enable = USB2_PRE_EMP_ON, \
.pre_emp_bias = USB2_BIAS_56P3MV, \
.pre_emp_bit = USB2_HALF_BIT_PRE_EMP, \
}
/* Type-C Port, no BC1.2 charge detect module / MUX
* Length = 3.0" - 9.00" */
#define USB2_PORT_TYPE_C(pin) { \
.enable = 1, \
.ocpin = (pin), \
.tx_bias = USB2_BIAS_0MV, \
.tx_emp_enable = USB2_PRE_EMP_ON, \
.pre_emp_bias = USB2_BIAS_56P3MV, \
.pre_emp_bit = USB2_HALF_BIT_PRE_EMP, \
.type_c = 1, \
}
struct usb3_port_config {
uint8_t enable;
uint8_t ocpin;
uint8_t tx_de_emp;
uint8_t tx_downscale_amp;
};
#define USB3_PORT_EMPTY { \
.enable = 0, \
.ocpin = OC_SKIP, \
.tx_de_emp = 0x00, \
.tx_downscale_amp = 0x00, \
}
#define USB3_PORT_DEFAULT(pin) { \
.enable = 1, \
.ocpin = (pin), \
.tx_de_emp = 0x0, \
.tx_downscale_amp = 0x00, \
}
struct tcss_port_config {
uint8_t enable;
uint8_t ocpin;
};
#define TCSS_PORT_EMPTY { \
.enable = 0, \
.ocpin = OC_SKIP, \
}
#define TCSS_PORT_DEFAULT(pin) { \
.enable = 1, \
.ocpin = (pin), \
}
#endif /* _SOC_PANTHERLAKE_USB_H_ */

View file

@ -0,0 +1,54 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <device/mmio.h>
#include <intelblocks/cfg.h>
#include <intelblocks/pcr.h>
#include <intelblocks/pmclib.h>
#include <intelpch/lockdown.h>
#include <soc/pcr_ids.h>
#include <soc/pm.h>
#include <stdint.h>
/* PCR PSTH Control Register */
#define PCR_PSTH_CTRLREG 0x1d00
#define PSTH_CTRLREG_IOSFPTCGE BIT(2)
static void pmc_lockdown_cfg(int chipset_lockdown)
{
uint8_t *pmcbase = pmc_mmio_regs();
/* PMSYNC */
setbits32(pmcbase + PMSYNC_TPR_CFG, PCH2CPU_TPR_CFG_LOCK);
/* Lock down ABASE and sleep stretching policy */
setbits32(pmcbase + GEN_PMCON_B, SLP_STR_POL_LOCK | ACPI_BASE_LOCK);
if (chipset_lockdown == CHIPSET_LOCKDOWN_COREBOOT)
setbits32(pmcbase + GEN_PMCON_B, SMI_LOCK);
if (!CONFIG(USE_FSP_NOTIFY_PHASE_POST_PCI_ENUM)) {
setbits32(pmcbase + GEN_PMCON_B, ST_FDIS_LOCK);
setbits32(pmcbase + SSML, SSML_SSL_EN);
setbits32(pmcbase + PM_CFG, PM_CFG_DBG_MODE_LOCK |
PM_CFG_XRAM_READ_DISABLE);
}
/* Send PMC IPC to inform about both BIOS Reset and PCI enumeration done */
pmc_send_bios_reset_pci_enum_done();
}
static void soc_die_lockdown_cfg(void)
{
if (CONFIG(USE_FSP_NOTIFY_PHASE_POST_PCI_ENUM))
return;
/* Enable IOSF Primary Trunk Clock Gating */
pcr_rmw32(PID_PSTH, PCR_PSTH_CTRLREG, ~0, PSTH_CTRLREG_IOSFPTCGE);
}
void soc_lockdown_config(int chipset_lockdown)
{
/* PMC lock down configuration */
pmc_lockdown_cfg(chipset_lockdown);
/* SOC Die lock down configuration */
soc_die_lockdown_cfg();
}

View file

@ -0,0 +1,57 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <console/console.h>
#include <device/device.h>
#include <device/pci_def.h>
#include <intelblocks/p2sb.h>
#include <soc/iomap.h>
void p2sb_soc_get_sb_mask(uint32_t *ep_mask, size_t count)
{
uint32_t mask;
if (count != P2SB_EP_MASK_MAX_REG) {
printk(BIOS_ERR, "Unable to program EPMASK registers\n");
return;
}
/* Remove the host accessing right to PSF register range.
* Set p2sb PCI offset EPMASK5 [29, 28, 27, 26] to disable Sideband
* access for PCI Root Bridge.
*/
mask = BIT(29) | BIT(28) | BIT(27) | BIT(26);
ep_mask[P2SB_EP_MASK_5_REG] = mask;
/*
* Set p2sb PCI offset EPMASK7 [31, 30] to disable Sideband
* access for Broadcast and Multicast.
*/
mask = BIT(31) | BIT(30);
ep_mask[P2SB_EP_MASK_7_REG] = mask;
}
static void p2sb2_read_resources(struct device *dev)
{
/* Add the fixed MMIO resource for P2SB#2 */
mmio_range(dev, PCI_BASE_ADDRESS_0, IOE_P2SB_BAR, IOE_P2SB_SIZE);
}
static void p2sb_read_resources(struct device *dev)
{
/* Add the fixed MMIO resource for P2SB#1 */
mmio_range(dev, PCI_BASE_ADDRESS_0, P2SB_BAR, P2SB_SIZE);
}
struct device_operations pcd_p2sb_2_ops = {
.read_resources = p2sb2_read_resources,
.set_resources = noop_set_resources,
.scan_bus = scan_static_bus,
};
struct device_operations pcd_p2sb_ops = {
.read_resources = p2sb_read_resources,
.set_resources = noop_set_resources,
.scan_bus = scan_static_bus,
};

View file

@ -0,0 +1,47 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <intelblocks/pcie_rp.h>
#include <soc/pci_devs.h>
#include <soc/pcie.h>
#include <soc/soc_info.h>
/*
* TBT's LCAP registers are returning port index which starts from 0x10 (Usually for other PCIe
* root ports index starts from 1). Thus keeping lcap_port_base 0x10 for TBT, so that coreboot's
* PCIe remapping logic can return correct index (0-based)
*/
static const struct pcie_rp_group tbt_rp_groups[] = {
{ .slot = PCI_DEV_SLOT_TBT, .count = CONFIG_MAX_TBT_ROOT_PORTS, .lcap_port_base = 0x10 },
{ 0 }
};
static const struct pcie_rp_group ptl_rp_groups[] = {
{ .slot = PCI_DEV_SLOT_PCIE_1, .count = 8, .lcap_port_base = 1 },
#if CONFIG(SOC_INTEL_PANTHERLAKE_U_H)
{ .slot = PCI_DEV_SLOT_PCIE_2, .count = 4, .lcap_port_base = 1 },
#else
{ .slot = PCI_DEV_SLOT_PCIE_2, .count = 2, .lcap_port_base = 1 },
#endif
{ 0 }
};
const struct pcie_rp_group *get_pcie_rp_table(void)
{
return ptl_rp_groups;
}
const struct pcie_rp_group *get_tbt_pcie_rp_table(void)
{
return tbt_rp_groups;
}
enum pcie_rp_type soc_get_pcie_rp_type(const struct device *dev)
{
return PCIE_RP_PCH;
}
int soc_get_cpu_rp_vw_idx(const struct device *dev)
{
return -1;
}

View file

@ -0,0 +1,200 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <acpi/acpigen.h>
#include <bootstate.h>
#include <console/console.h>
#include <device/device.h>
#include <device/mmio.h>
#include <drivers/intel/pmc_mux/chip.h>
#include <intelblocks/acpi.h>
#include <intelblocks/pmc.h>
#include <intelblocks/pmc_ipc.h>
#include <intelblocks/pmclib.h>
#include <intelblocks/rtc.h>
#include <soc/cpu.h>
#include <soc/pci_devs.h>
#include <soc/pm.h>
#include <soc/soc_chip.h>
#include <stdint.h>
#define PMC_HID "INTC1026"
static void config_deep_sX(uint32_t offset, uint32_t mask, int sx, int enable)
{
uint32_t reg;
uint8_t *pmcbase = pmc_mmio_regs();
if (pmcbase == NULL) {
printk(BIOS_ERR, "PMC MMIO regs could not be retrieved.\n");
return;
}
printk(BIOS_DEBUG, "%sabling Deep S%c\n",
enable ? "En" : "Dis", sx + '0');
reg = read32(pmcbase + offset);
if (enable)
reg |= mask;
else
reg &= ~mask;
write32(pmcbase + offset, reg);
}
static void config_deep_s5(int on_ac, int on_dc)
{
/* Treat S4 the same as S5. */
config_deep_sX(S4_PWRGATE_POL, S4AC_GATE_SUS, 4, on_ac);
config_deep_sX(S4_PWRGATE_POL, S4DC_GATE_SUS, 4, on_dc);
config_deep_sX(S5_PWRGATE_POL, S5AC_GATE_SUS, 5, on_ac);
config_deep_sX(S5_PWRGATE_POL, S5DC_GATE_SUS, 5, on_dc);
}
static void config_deep_s3(int on_ac, int on_dc)
{
config_deep_sX(S3_PWRGATE_POL, S3AC_GATE_SUS, 3, on_ac);
config_deep_sX(S3_PWRGATE_POL, S3DC_GATE_SUS, 3, on_dc);
}
static void config_deep_sx(uint32_t deepsx_config)
{
uint32_t reg;
uint8_t *pmcbase = pmc_mmio_regs();
reg = read32(pmcbase + DSX_CFG);
reg &= ~DSX_CFG_MASK;
reg |= deepsx_config;
write32(pmcbase + DSX_CFG, reg);
}
static void soc_pmc_enable(struct device *dev)
{
const config_t *config = config_of_soc();
rtc_init();
pmc_set_power_failure_state(true);
pmc_gpe_init();
config_deep_s3(config->deep_s3_enable_ac, config->deep_s3_enable_dc);
config_deep_s5(config->deep_s5_enable_ac, config->deep_s5_enable_dc);
config_deep_sx(config->deep_sx_config);
}
static void soc_pmc_read_resources(struct device *dev)
{
struct resource *res;
/* Add the fixed MMIO resource */
mmio_range(dev, PWRMBASE, PCH_PWRM_BASE_ADDRESS, PCH_PWRM_BASE_SIZE);
/* Add the fixed I/O resource */
res = new_resource(dev, 1);
res->base = (resource_t)ACPI_BASE_ADDRESS;
res->size = (resource_t)ACPI_BASE_SIZE;
res->limit = res->base + res->size - 1;
res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
}
static void soc_pmc_fill_ssdt(const struct device *dev)
{
const char *scope = acpi_device_scope(dev);
const char *name = acpi_device_name(dev);
if (!scope || !name)
return;
acpigen_write_scope(scope);
acpigen_write_device(name);
acpigen_write_name_string("_HID", PMC_HID);
acpigen_write_name_string("_DDN", "Intel(R) Panther Lake IPC Controller");
/* Hide the device so that Windows does not complain on missing driver */
acpigen_write_STA(ACPI_STATUS_DEVICE_HIDDEN_ON);
/*
* Part of the PCH's reserved 32 MB MMIO range (0xFC800000 - 0xFE7FFFFF).
* The PMC gets 0xFE000000 - 0xFE00FFFF.
*/
acpigen_write_name("_CRS");
acpigen_write_resourcetemplate_header();
acpigen_write_mem32fixed(1, PCH_PWRM_BASE_ADDRESS, PCH_PWRM_BASE_SIZE);
acpigen_write_resourcetemplate_footer();
/* Define IPC Write Method */
if (CONFIG(PMC_IPC_ACPI_INTERFACE))
pmc_ipc_acpi_fill_ssdt();
acpigen_pop_len(); /* PMC Device */
acpigen_pop_len(); /* Scope */
if (CONFIG(SOC_INTEL_COMMON_BLOCK_ACPI_PEP)) {
const struct soc_pmc_lpm ptl_pmc_lpm = {
.num_substates = 8,
.num_req_regs = 6,
.lpm_ipc_offset = 0x1000,
.req_reg_stride = 0x30,
.lpm_enable_mask = get_supported_lpm_mask(),
};
generate_acpi_power_engine_with_lpm(&ptl_pmc_lpm);
}
printk(BIOS_INFO, "%s: %s at %s\n", acpi_device_path(dev), dev->chip_ops->name,
dev_path(dev));
}
static void soc_pmc_init(struct device *dev)
{
/*
* pmc_set_acpi_mode() should be delayed until BS_DEV_INIT in order
* to ensure the ordering does not break the assumptions that other
* drivers make about ACPI mode (e.g. Chrome EC). Since it disables
* ACPI mode, other drivers may take different actions based on this
* (e.g. Chrome EC will flush any pending hostevent bits). Because
* PTL has its PMC device available for device_operations, it can be
* done from the "ops->init" callback.
*/
pmc_set_acpi_mode();
/*
* Disable ACPI PM timer based on Kconfig
*
* Disabling ACPI PM timer is necessary for XTAL OSC shutdown.
* Disabling ACPI PM timer also switches off TCO
*/
if (!CONFIG(USE_PM_ACPI_TIMER))
setbits8(pmc_mmio_regs() + PCH_PWRM_ACPI_TMR_CTL, ACPI_TIM_DIS);
}
static void pm1_enable_pwrbtn_smi(void *unused)
{
/* Enable power button SMI after BS_DEV_INIT_CHIPS (FSP-S) is done. */
pmc_update_pm1_enable(PWRBTN_EN);
}
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_EXIT, pm1_enable_pwrbtn_smi, NULL);
/*
* `pmc_final` function is native implementation of equivalent events performed by
* each FSP NotifyPhase() API invocations.
*
*
* Clear PMCON status bits (Global Reset/Power Failure/Host Reset Status bits)
*
* Perform the PMCON status bit clear operation from `.final`
* to cover any such chances where later boot stage requested a global
* reset and PMCON status bit remains set.
*/
static void pmc_final(struct device *dev)
{
pmc_clear_pmcon_sts();
}
struct device_operations pmc_ops = {
.read_resources = soc_pmc_read_resources,
.set_resources = noop_set_resources,
.init = soc_pmc_init,
.enable = soc_pmc_enable,
#if CONFIG(HAVE_ACPI_TABLES)
.acpi_fill_ssdt = soc_pmc_fill_ssdt,
#endif
.scan_bus = scan_static_bus,
.final = pmc_final,
};

View file

@ -0,0 +1,267 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Helper functions for dealing with power management registers
* and the differences between PCH variants.
*/
#define __SIMPLE_DEVICE__
#include <acpi/acpi_pm.h>
#include <console/console.h>
#include <device/mmio.h>
#include <device/device.h>
#include <device/pci.h>
#include <intelblocks/pmclib.h>
#include <intelblocks/rtc.h>
#include <intelblocks/tco.h>
#include <intelpch/espi.h>
#include <security/vboot/vbnv.h>
#include <soc/gpe.h>
#include <soc/gpio.h>
#include <soc/iomap.h>
#include <soc/pci_devs.h>
#include <soc/pm.h>
#include <soc/smbus.h>
#include <soc/soc_chip.h>
#include <types.h>
/*
* SMI
*/
const char *const *soc_smi_sts_array(size_t *a)
{
static const char *const smi_sts_bits[] = {
[BIOS_STS_BIT] = "BIOS",
[LEGACY_USB_STS_BIT] = "LEGACY_USB",
[SMI_ON_SLP_EN_STS_BIT] = "SLP_SMI",
[APM_STS_BIT] = "APM",
[SWSMI_TMR_STS_BIT] = "SWSMI_TMR",
[PM1_STS_BIT] = "PM1",
[GPE0_STS_BIT] = "GPE0",
[GPIO_STS_BIT] = "GPI",
[MCSMI_STS_BIT] = "MCSMI",
[DEVMON_STS_BIT] = "DEVMON",
[TCO_STS_BIT] = "TCO",
[PERIODIC_STS_BIT] = "PERIODIC",
[SERIRQ_SMI_STS_BIT] = "SERIRQ_SMI",
[SMBUS_SMI_STS_BIT] = "SMBUS_SMI",
[PCI_EXP_SMI_STS_BIT] = "PCI_EXP_SMI",
[MONITOR_STS_BIT] = "MONITOR",
[SPI_SMI_STS_BIT] = "SPI",
[GPIO_UNLOCK_SMI_STS_BIT] = "GPIO_UNLOCK",
[ESPI_SMI_STS_BIT] = "ESPI_SMI",
};
*a = ARRAY_SIZE(smi_sts_bits);
return smi_sts_bits;
}
/*
* TCO
*/
const char *const *soc_tco_sts_array(size_t *a)
{
static const char *const tco_sts_bits[] = {
[0] = "NMI2SMI",
[1] = "SW_TCO",
[2] = "TCO_INT",
[3] = "TIMEOUT",
[7] = "NEWCENTURY",
[8] = "BIOSWR",
[9] = "DMISCI",
[10] = "DMISMI",
[12] = "DMISERR",
[13] = "SLVSEL",
[16] = "INTRD_DET",
[17] = "SECOND_TO",
[18] = "BOOT",
[20] = "SMLINK_SLV"
};
*a = ARRAY_SIZE(tco_sts_bits);
return tco_sts_bits;
}
/*
* GPE0
*/
const char *const *soc_std_gpe_sts_array(size_t *a)
{
static const char *const gpe_sts_bits[] = {
[1] = "HOTPLUG",
[2] = "SWGPE",
[6] = "TCO_SCI",
[7] = "SMB_WAK",
[9] = "PCI_EXP",
[10] = "BATLOW",
[11] = "PME",
[12] = "ME",
[13] = "PME_B0",
[14] = "eSPI",
[15] = "GPIO Tier-2",
[16] = "LAN_WAKE",
[18] = "WADT"
};
*a = ARRAY_SIZE(gpe_sts_bits);
return gpe_sts_bits;
}
void pmc_set_disb(void)
{
/* Set the DISB after DRAM init */
uint8_t disb_val;
/* Only care about bits [23:16] of register GEN_PMCON_A */
uint8_t *addr = (uint8_t *)(pmc_mmio_regs() + GEN_PMCON_A + 2);
disb_val = read8(addr);
disb_val |= (DISB >> 16);
/* Don't clear bits that are write-1-to-clear */
disb_val &= ~((MS4V | SUS_PWR_FLR) >> 16);
write8(addr, disb_val);
}
/*
* PMC controller gets hidden from PCI bus
* during FSP-Silicon init call. Hence PWRMBASE
* can't be accessible using PCI configuration space
* read/write.
*/
uint8_t *pmc_mmio_regs(void)
{
return (void *)(uintptr_t)PCH_PWRM_BASE_ADDRESS;
}
uintptr_t soc_read_pmc_base(void)
{
return (uintptr_t)pmc_mmio_regs();
}
uint32_t *soc_pmc_etr_addr(void)
{
return (uint32_t *)(soc_read_pmc_base() + ETR);
}
void soc_get_gpi_gpe_configs(uint8_t *dw0, uint8_t *dw1, uint8_t *dw2)
{
DEVTREE_CONST struct soc_intel_pantherlake_config *config;
config = config_of_soc();
if (config == NULL) {
printk(BIOS_ERR, "Configuration could not be retrieved.\n");
return;
}
/* Assign to out variable */
*dw0 = config->pmc_gpe0_dw0;
*dw1 = config->pmc_gpe0_dw1;
*dw2 = config->pmc_gpe0_dw2;
}
static int rtc_failed(uint32_t gen_pmcon_b)
{
return !!(gen_pmcon_b & RTC_BATTERY_DEAD);
}
int soc_get_rtc_failed(void)
{
const struct chipset_power_state *ps;
if (acpi_fetch_pm_state(&ps, PS_CLAIMER_RTC) < 0)
return 1;
return rtc_failed(ps->gen_pmcon_b);
}
int vbnv_cmos_failed(void)
{
return rtc_failed(read32(pmc_mmio_regs() + GEN_PMCON_B));
}
static inline int deep_s3_enabled(void)
{
uint32_t deep_s3_pol;
deep_s3_pol = read32(pmc_mmio_regs() + S3_PWRGATE_POL);
return !!(deep_s3_pol & (S3DC_GATE_SUS | S3AC_GATE_SUS));
}
/* Return 0, 3, or 5 to indicate the previous sleep state. */
int soc_prev_sleep_state(const struct chipset_power_state *ps, int prev_sleep_state)
{
/*
* Check for any power failure to determine if this a wake from
* S5 because the PCH does not set the WAK_STS bit when waking
* from a true G3 state.
*/
if (!(ps->pm1_sts & WAK_STS) && (ps->gen_pmcon_a & (PWR_FLR | SUS_PWR_FLR)))
prev_sleep_state = ACPI_S5;
/*
* If waking from S3 determine if deep S3 is enabled. If not,
* need to check both deep sleep well and normal suspend well.
* Otherwise just check deep sleep well.
*/
if (prev_sleep_state == ACPI_S3) {
/* PWR_FLR represents deep sleep power well loss. */
uint32_t mask = PWR_FLR;
/* If deep s3 isn't enabled check the suspend well too. */
if (!deep_s3_enabled())
mask |= SUS_PWR_FLR;
if (ps->gen_pmcon_a & mask)
prev_sleep_state = ACPI_S5;
}
return prev_sleep_state;
}
void soc_fill_power_state(struct chipset_power_state *ps)
{
uint8_t *pmc;
ps->tco1_sts = tco_read_reg(TCO1_STS);
ps->tco2_sts = tco_read_reg(TCO2_STS);
printk(BIOS_DEBUG, "TCO_STS: %04x %04x\n", ps->tco1_sts, ps->tco2_sts);
pmc = pmc_mmio_regs();
ps->gen_pmcon_a = read32(pmc + GEN_PMCON_A);
ps->gen_pmcon_b = read32(pmc + GEN_PMCON_B);
ps->gblrst_cause[0] = read32(pmc + GBLRST_CAUSE0);
ps->gblrst_cause[1] = read32(pmc + GBLRST_CAUSE1);
ps->hpr_cause0 = read32(pmc + HPR_CAUSE0);
printk(BIOS_DEBUG, "GEN_PMCON: %08x %08x\n",
ps->gen_pmcon_a, ps->gen_pmcon_b);
printk(BIOS_DEBUG, "GBLRST_CAUSE: %08x %08x\n",
ps->gblrst_cause[0], ps->gblrst_cause[1]);
printk(BIOS_DEBUG, "HPR_CAUSE0: %08x\n", ps->hpr_cause0);
}
/* STM Support */
uint16_t get_pmbase(void)
{
return (uint16_t)ACPI_BASE_ADDRESS;
}
/*
* Set which power state system will be after reapplying
* the power (from G3 State)
*/
void pmc_soc_set_afterg3_en(const bool on)
{
uint8_t reg8;
uint8_t *const pmcbase = pmc_mmio_regs();
reg8 = read8(pmcbase + GEN_PMCON_A);
if (on)
reg8 &= ~SLEEP_AFTER_POWER_FAIL;
else
reg8 |= SLEEP_AFTER_POWER_FAIL;
write8(pmcbase + GEN_PMCON_A, reg8);
}

View file

@ -0,0 +1,30 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <console/console.h>
#include <device/device.h>
#include <drivers/intel/usb4/retimer/retimer.h>
#include <intelblocks/tcss.h>
int retimer_get_index_for_typec(uint8_t typec_port)
{
const struct device *tcss_port_arr[] = {
DEV_PTR(tcss_usb3_port0),
DEV_PTR(tcss_usb3_port1),
DEV_PTR(tcss_usb3_port2),
DEV_PTR(tcss_usb3_port3),
};
for (int i = 0, ec_port = 0; i < MAX_TYPE_C_PORTS; i++) {
if (i == typec_port) {
printk(BIOS_INFO, "USB Type-C %d mapped to EC port %d\n", typec_port,
ec_port);
return ec_port;
}
if (is_dev_enabled(tcss_port_arr[i]))
ec_port++;
}
/* Code should not come here if typec_port input is correct */
return -1;
}

View file

@ -0,0 +1,30 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <device/pci_def.h>
#include <intelblocks/smihandler.h>
#include <soc/soc_chip.h>
#include <soc/pci_devs.h>
#include <soc/pm.h>
int smihandler_soc_disable_busmaster(pci_devfn_t dev)
{
/* Skip disabling PMC bus master to keep IO decode enabled */
if (dev == PCI_DEV_PMC)
return 0;
return 1;
}
const smi_handler_t southbridge_smi[SMI_STS_BITS] = {
[SMI_ON_SLP_EN_STS_BIT] = smihandler_southbridge_sleep,
[APM_STS_BIT] = smihandler_southbridge_apmc,
[PM1_STS_BIT] = smihandler_southbridge_pm1,
[GPE0_STS_BIT] = smihandler_southbridge_gpe0,
[GPIO_STS_BIT] = smihandler_southbridge_gpi,
[ESPI_SMI_STS_BIT] = smihandler_southbridge_espi,
[MCSMI_STS_BIT] = smihandler_southbridge_mc,
#if CONFIG(SOC_INTEL_COMMON_BLOCK_SMM_TCO_ENABLE)
[TCO_STS_BIT] = smihandler_southbridge_tco,
#endif
[PERIODIC_STS_BIT] = smihandler_southbridge_periodic,
[MONITOR_STS_BIT] = smihandler_southbridge_monitor,
};

View file

@ -0,0 +1,72 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <acpi/acpi_soundwire.h>
#include <console/console.h>
#include <device/mmio.h>
#include <device/soundwire.h>
#include <drivers/intel/soundwire/soundwire.h>
#include <intelblocks/pmclib.h>
#include <soc/pmc.h>
#include <stddef.h>
#include <string.h>
static const struct soundwire_link link_xtal_38_4 = {
.clock_stop_mode0_supported = 1,
.clock_stop_mode1_supported = 1,
.clock_frequencies_supported_count = 1,
.clock_frequencies_supported = { 4800 * KHz },
.default_frame_rate = 48 * KHz,
.default_frame_row_size = 50,
.default_frame_col_size = 4,
.dynamic_frame_shape = 1,
.command_error_threshold = 16,
};
static const struct soundwire_link link_xtal_24 = {
.clock_stop_mode0_supported = 1,
.clock_stop_mode1_supported = 1,
.clock_frequencies_supported_count = 1,
.clock_frequencies_supported = { 6 * MHz },
.default_frame_rate = 48 * KHz,
.default_frame_row_size = 125,
.default_frame_col_size = 2,
.dynamic_frame_shape = 1,
.command_error_threshold = 16,
};
static struct intel_soundwire_controller intel_controller = {
.acpi_address = 0x40000000, /* Custom address for SNDW driver */
.sdw = {
.master_list_count = 4
}
};
int soc_fill_soundwire_controller(struct intel_soundwire_controller **controller)
{
const struct soundwire_link *link;
enum pch_pmc_xtal xtal = pmc_get_xtal_freq();
size_t i;
/* Select link config based on XTAL frequency and set IP clock. */
switch (xtal) {
case XTAL_24_MHZ:
link = &link_xtal_24;
intel_controller.ip_clock = 24 * MHz;
break;
case XTAL_38_4_MHZ:
link = &link_xtal_38_4;
intel_controller.ip_clock = 38400 * KHz;
break;
case XTAL_19_2_MHZ:
default:
printk(BIOS_ERR, "%s: XTAL not supported: 0x%x\n", __func__, xtal);
return -1;
}
/* Fill link config in controller map based on selected XTAL. */
for (i = 0; i < intel_controller.sdw.master_list_count; i++)
memcpy(&intel_controller.sdw.master_list[i], link, sizeof(*link));
*controller = &intel_controller;
return 0;
}

View file

@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include <intelblocks/fast_spi.h>
#include <intelblocks/spi.h>
#include <soc/pci_devs.h>
#define PSF_SPI_DESTINATION_ID 0x5140
int spi_soc_devfn_to_bus(unsigned int devfn)
{
switch (devfn) {
case PCI_DEVFN_GSPI0:
return 1;
case PCI_DEVFN_GSPI1:
return 2;
case PCI_DEVFN_GSPI2:
return 3;
}
return -1;
}
uint32_t soc_get_spi_psf_destination_id(void)
{
return PSF_SPI_DESTINATION_ID;
}

View file

@ -0,0 +1,211 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <arch/ioapic.h>
#include <console/console.h>
#include <cpu/x86/msr.h>
#include <device/device.h>
#include <device/pci.h>
#include <intelblocks/cpulib.h>
#include <intelblocks/msr.h>
#include <intelblocks/power_limit.h>
#include <intelblocks/systemagent.h>
#include <soc/iomap.h>
#include <soc/soc_chip.h>
#include <soc/systemagent.h>
/*
* SoC implementation
*
* Add all known fixed memory ranges for Host Controller/Memory
* controller.
*/
void soc_add_fixed_mmio_resources(struct device *dev, int *index)
{
static const struct sa_mmio_descriptor soc_fixed_resources[] = {
{ MCHBAR, MCH_BASE_ADDRESS, MCH_BASE_SIZE, "MCHBAR" },
{ SAFBAR, SAF_BASE_ADDRESS, SAF_BASE_SIZE, "SAFBAR" },
{ EPBAR, EP_BASE_ADDRESS, EP_BASE_SIZE, "EPBAR" },
{ REGBAR, REG_BASE_ADDRESS, REG_BASE_SIZE, "REGBAR" },
/* First field (sa_mmio_descriptor.index) is not used, setting to 0: */
{ 0, CRAB_ABORT_BASE_ADDR, CRAB_ABORT_SIZE, "CRAB_ABORT" },
{ 0, LT_SECURITY_BASE_ADDR, LT_SECURITY_SIZE, "LT_SECURITY" },
{ 0, IO_APIC_ADDR, APIC_SIZE, "APIC" },
{ 0, PCH_PRESERVED_BASE_ADDRESS, PCH_PRESERVED_BASE_SIZE, "PCH_RESERVED" },
};
sa_add_fixed_mmio_resources(dev, index, soc_fixed_resources,
ARRAY_SIZE(soc_fixed_resources));
/* Add Vt-d resources if VT-d is enabled */
if ((pci_read_config32(dev, CAPID0_A) & VTD_DISABLE))
return;
sa_add_fixed_mmio_resources(dev, index, soc_vtd_resources,
ARRAY_SIZE(soc_vtd_resources));
}
/*
* Set MMIO resource's fields
*/
static void set_mmio_resource(
struct sa_mmio_descriptor *resource,
uint64_t base,
uint64_t size,
const char *description)
{
if (resource == NULL) {
printk(BIOS_ERR, "%s: argument resource is NULL for %s\n",
__func__, description);
return;
}
resource->base = base;
resource->size = size;
resource->description = description;
}
int soc_get_uncore_prmmr_base_and_mask(uint64_t *prmrr_base,
uint64_t *prmrr_mask)
{
msr_t msr;
msr = rdmsr(MSR_PRMRR_BASE_0);
*prmrr_base = (uint64_t)msr.hi << 32 | msr.lo;
msr = rdmsr(MSR_PRMRR_PHYS_MASK);
*prmrr_mask = (uint64_t)msr.hi << 32 | msr.lo;
return 0;
}
/*
* SoC implementation
*
* Add all known configurable memory ranges for Host Controller/Memory
* controller.
*/
void soc_add_configurable_mmio_resources(struct device *dev, int *resource_cnt)
{
uint64_t size, base, tseg_base;
int count = 0;
struct sa_mmio_descriptor cfg_rsrc[6]; /* Increase size when adding more resources */
/* MMCONF */
size = sa_get_mmcfg_size();
if (size > 0)
set_mmio_resource(&(cfg_rsrc[count++]), CONFIG_ECAM_MMCONF_BASE_ADDRESS,
size, "MMCONF");
/* DSM */
size = sa_get_dsm_size();
if (size > 0) {
base = pci_read_config32(dev, BDSM) & 0xFFF00000;
set_mmio_resource(&(cfg_rsrc[count++]), base, size, "DSM");
}
/* TSEG */
size = sa_get_tseg_size();
tseg_base = sa_get_tseg_base();
if (size > 0)
set_mmio_resource(&(cfg_rsrc[count++]), tseg_base, size, "TSEG");
/* PMRR */
size = get_valid_prmrr_size();
if (size > 0) {
uint64_t mask;
if (soc_get_uncore_prmmr_base_and_mask(&base, &mask) == 0) {
base &= mask;
set_mmio_resource(&(cfg_rsrc[count++]), base, size, "PMRR");
} else {
printk(BIOS_ERR, "SA: Failed to get PRMRR base and mask\n");
}
}
/* GSM */
size = sa_get_gsm_size();
if (size > 0) {
base = sa_get_gsm_base();
set_mmio_resource(&(cfg_rsrc[count++]), base, size, "GSM");
}
/* DPR */
size = sa_get_dpr_size();
if (size > 0) {
/* DPR just below TSEG: */
base = tseg_base - size;
set_mmio_resource(&(cfg_rsrc[count++]), base, size, "DPR");
}
/* Add all the above */
sa_add_fixed_mmio_resources(dev, resource_cnt, cfg_rsrc, count);
}
static void configure_tdp(struct device *dev)
{
struct soc_power_limits_config *soc_config;
struct device *sa;
uint16_t sa_pci_id;
u8 tdp;
size_t i;
bool config_tdp = false;
config_t *config;
config = config_of_soc();
/* Get System Agent PCI ID */
sa = pcidev_path_on_root(PCI_DEVFN_ROOT);
sa_pci_id = sa ? pci_read_config16(sa, PCI_DEVICE_ID) : 0xFFFF;
if (sa_pci_id == 0xFFFF) {
printk(BIOS_WARNING, "Unknown SA PCI Device!\n");
return;
}
tdp = get_cpu_tdp();
/*
* Choose power limits configuration based on the CPU SA PCI ID and
* CPU TDP value.
*/
for (i = 0; i < ARRAY_SIZE(cpuid_to_ptl); i++) {
if (sa_pci_id == cpuid_to_ptl[i].cpu_id &&
tdp == cpuid_to_ptl[i].cpu_tdp) {
soc_config = &config->power_limits_config[cpuid_to_ptl[i].limits];
set_power_limits(MOBILE_SKU_PL1_TIME_SEC, soc_config);
config_tdp = true;
printk(BIOS_DEBUG, "Configured power limits for SA PCI ID: 0x%4x\n",
sa_pci_id);
break;
}
}
if (!config_tdp) {
printk(BIOS_WARNING, "Skipped power limits configuration for SA PCI ID: 0x%4x\n",
sa_pci_id);
return;
}
}
/*
* SoC implementation
*
* Perform System Agent Initialization during ramstage phase.
*/
void soc_systemagent_init(struct device *dev)
{
/* Enable Power Aware Interrupt Routing */
enable_power_aware_intr();
/* Configure TDP */
configure_tdp(dev);
}
uint32_t soc_systemagent_max_chan_capacity_mib(u8 capid0_a_ddrsz)
{
switch (capid0_a_ddrsz) {
case 1:
return 8192;
case 2:
return 4096;
case 3:
return 2048;
default:
return 65536;
}
}

View file

@ -0,0 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <intelblocks/tcss.h>
#include <soc/soc_chip.h>
const struct soc_tcss_ops tcss_ops = {
/* TODO: Implement AUX BIAS PAD Programming if required */
.configure_aux_bias_pads = NULL,
.valid_tbt_auth = NULL,
};

View file

@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <commonlib/helpers.h>
#include <soc/pci_devs.h>
const unsigned int uart_devices[] = {
PCI_DEVFN_UART0,
PCI_DEVFN_UART1,
PCI_DEVFN_UART2,
};
const int uart_devices_size = ARRAY_SIZE(uart_devices);

View file

@ -0,0 +1,39 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <device/pci_type.h>
#include <intelblocks/xhci.h>
#include <soc/pci_devs.h>
#define XHCI_USB2_PORT_STATUS_REG 0x480
#define XHCI_USB3_PORT_STATUS_REG 0x540
#define XHCI_USB2_PORT_NUM CONFIG_SOC_INTEL_USB2_DEV_MAX
#define XHCI_USB3_PORT_NUM CONFIG_SOC_INTEL_USB3_DEV_MAX
#define TCSS_XHCI_USB2_PORT_STATUS_REG 0x480
#define TCSS_XHCI_USB3_PORT_STATUS_REG 0x490
#define TCSS_XHCI_USB2_PORT_NUM 0
#define TCSS_XHCI_USB3_PORT_NUM 4
static const struct xhci_usb_info usb_info = {
.usb2_port_status_reg = XHCI_USB2_PORT_STATUS_REG,
.num_usb2_ports = XHCI_USB2_PORT_NUM,
.usb3_port_status_reg = XHCI_USB3_PORT_STATUS_REG,
.num_usb3_ports = XHCI_USB3_PORT_NUM,
};
static const struct xhci_usb_info tcss_usb_info = {
.usb2_port_status_reg = TCSS_XHCI_USB2_PORT_STATUS_REG,
.num_usb2_ports = TCSS_XHCI_USB2_PORT_NUM,
.usb3_port_status_reg = TCSS_XHCI_USB3_PORT_STATUS_REG,
.num_usb3_ports = TCSS_XHCI_USB3_PORT_NUM,
};
const struct xhci_usb_info *soc_get_xhci_usb_info(pci_devfn_t xhci_dev)
{
if (xhci_dev == PCI_DEVFN_XHCI)
return &usb_info;
else if (xhci_dev == PCI_DEVFN_TCSS_XHCI)
return &tcss_usb_info;
return NULL;
}