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:
parent
4ba9eeab08
commit
95cf9c0052
41 changed files with 3675 additions and 93 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
358
src/soc/intel/pantherlake/acpi.c
Normal file
358
src/soc/intel/pantherlake/acpi.c
Normal 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;
|
||||
}
|
||||
283
src/soc/intel/pantherlake/chip.c
Normal file
283
src/soc/intel/pantherlake/chip.c
Normal 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,
|
||||
};
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
226
src/soc/intel/pantherlake/cpu.c
Normal file
226
src/soc/intel/pantherlake/cpu.c
Normal 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;
|
||||
}
|
||||
516
src/soc/intel/pantherlake/crashlog.c
Normal file
516
src/soc/intel/pantherlake/crashlog.c
Normal 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;
|
||||
}
|
||||
29
src/soc/intel/pantherlake/cse_telemetry.c
Normal file
29
src/soc/intel/pantherlake/cse_telemetry.c
Normal 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]);
|
||||
}
|
||||
220
src/soc/intel/pantherlake/elog.c
Normal file
220
src/soc/intel/pantherlake/elog.c
Normal 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);
|
||||
}
|
||||
82
src/soc/intel/pantherlake/finalize.c
Normal file
82
src/soc/intel/pantherlake/finalize.c
Normal 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);
|
||||
20
src/soc/intel/pantherlake/fsp_params.c
Normal file
20
src/soc/intel/pantherlake/fsp_params.c
Normal 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__);
|
||||
}
|
||||
17
src/soc/intel/pantherlake/gspi.c
Normal file
17
src/soc/intel/pantherlake/gspi.c
Normal 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;
|
||||
}
|
||||
43
src/soc/intel/pantherlake/i2c.c
Normal file
43
src/soc/intel/pantherlake/i2c.c
Normal 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;
|
||||
}
|
||||
25
src/soc/intel/pantherlake/include/soc/cpu.h
Normal file
25
src/soc/intel/pantherlake/include/soc/cpu.h
Normal 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
|
||||
33
src/soc/intel/pantherlake/include/soc/crashlog.h
Normal file
33
src/soc/intel/pantherlake/include/soc/crashlog.h
Normal 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_ */
|
||||
23
src/soc/intel/pantherlake/include/soc/dptf.h
Normal file
23
src/soc/intel/pantherlake/include/soc/dptf.h
Normal 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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
12
src/soc/intel/pantherlake/include/soc/irq.h
Normal file
12
src/soc/intel/pantherlake/include/soc/irq.h
Normal 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
|
||||
8
src/soc/intel/pantherlake/include/soc/nvs.h
Normal file
8
src/soc/intel/pantherlake/include/soc/nvs.h
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
11
src/soc/intel/pantherlake/include/soc/pcie.h
Normal file
11
src/soc/intel/pantherlake/include/soc/pcie.h
Normal 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
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
14
src/soc/intel/pantherlake/include/soc/ramstage.h
Normal file
14
src/soc/intel/pantherlake/include/soc/ramstage.h
Normal 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
|
||||
35
src/soc/intel/pantherlake/include/soc/serialio.h
Normal file
35
src/soc/intel/pantherlake/include/soc/serialio.h
Normal 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_ */
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
19
src/soc/intel/pantherlake/include/soc/tcss.h
Normal file
19
src/soc/intel/pantherlake/include/soc/tcss.h
Normal 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
|
||||
155
src/soc/intel/pantherlake/include/soc/usb.h
Normal file
155
src/soc/intel/pantherlake/include/soc/usb.h
Normal 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_ */
|
||||
54
src/soc/intel/pantherlake/lockdown.c
Normal file
54
src/soc/intel/pantherlake/lockdown.c
Normal 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();
|
||||
}
|
||||
57
src/soc/intel/pantherlake/p2sb.c
Normal file
57
src/soc/intel/pantherlake/p2sb.c
Normal 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,
|
||||
};
|
||||
47
src/soc/intel/pantherlake/pcie_rp.c
Normal file
47
src/soc/intel/pantherlake/pcie_rp.c
Normal 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;
|
||||
}
|
||||
200
src/soc/intel/pantherlake/pmc.c
Normal file
200
src/soc/intel/pantherlake/pmc.c
Normal 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,
|
||||
};
|
||||
267
src/soc/intel/pantherlake/pmutil.c
Normal file
267
src/soc/intel/pantherlake/pmutil.c
Normal 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);
|
||||
}
|
||||
30
src/soc/intel/pantherlake/retimer.c
Normal file
30
src/soc/intel/pantherlake/retimer.c
Normal 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;
|
||||
}
|
||||
30
src/soc/intel/pantherlake/smihandler.c
Normal file
30
src/soc/intel/pantherlake/smihandler.c
Normal 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,
|
||||
};
|
||||
72
src/soc/intel/pantherlake/soundwire.c
Normal file
72
src/soc/intel/pantherlake/soundwire.c
Normal 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;
|
||||
}
|
||||
25
src/soc/intel/pantherlake/spi.c
Normal file
25
src/soc/intel/pantherlake/spi.c
Normal 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;
|
||||
}
|
||||
211
src/soc/intel/pantherlake/systemagent.c
Normal file
211
src/soc/intel/pantherlake/systemagent.c
Normal 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;
|
||||
}
|
||||
}
|
||||
10
src/soc/intel/pantherlake/tcss.c
Normal file
10
src/soc/intel/pantherlake/tcss.c
Normal 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,
|
||||
};
|
||||
12
src/soc/intel/pantherlake/uart.c
Normal file
12
src/soc/intel/pantherlake/uart.c
Normal 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);
|
||||
39
src/soc/intel/pantherlake/xhci.c
Normal file
39
src/soc/intel/pantherlake/xhci.c
Normal 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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue